LCOV - code coverage report
Current view: top level - bgp - bgp_session.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 51 62 82.3 %
Date: 2026-11-09 02:10:49 Functions: 12 14 85.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #include "bgp/bgp_session.h"
       7             : 
       8             : #include <algorithm>
       9             : #include <string>
      10             : 
      11             : #include "bgp/bgp_log.h"
      12             : #include "bgp/bgp_peer.h"
      13             : #include "bgp/bgp_server.h"
      14             : #include "bgp/bgp_session_manager.h"
      15             : #include "bgp/bgp_update_sender.h"
      16             : 
      17             : using std::string;
      18             : 
      19             : using boost::asio::mutable_buffer;
      20             : 
      21             : // Extract the total BGP message length. This is a 2 byte field after the
      22             : // 16 byte marker. If the buffer doesn't have 18 bytes available return -1.
      23      176403 : int BgpMessageReader::MsgLength(Buffer buffer, int offset) {
      24      176403 :     size_t size = TcpSession::BufferSize(buffer);
      25      176403 :     int remain = size - offset;
      26      176403 :     if (remain < BgpMessageReader::kHeaderLenSize) {
      27           4 :         return -1;
      28             :     }
      29      176399 :     const uint8_t *data = TcpSession::BufferData(buffer) + offset;
      30      176399 :     data += 16;
      31      176399 :     int length = get_value(data, 2);
      32      176395 :     if (bgp_log_test::unit_test())
      33      176396 :         assert(length <= 4096);
      34      176396 :     return length;
      35             : }
      36             : 
      37       14665 : BgpMessageReader::BgpMessageReader(TcpSession *session,
      38       14665 :     ReceiveCallback callback)
      39       14665 :     : TcpMessageReader(session, callback) {
      40       14654 : }
      41             : 
      42       29334 : BgpMessageReader::~BgpMessageReader() {
      43       29334 : }
      44             : 
      45       14656 : BgpSession::BgpSession(BgpSessionManager *session_mgr, Socket *socket)
      46             :     : TcpSession(session_mgr, socket),
      47       14667 :       session_mgr_(session_mgr),
      48       14667 :       peer_(NULL),
      49       14667 :       task_instance_(-1),
      50       29319 :       reader_(new BgpMessageReader(this,
      51       29319 :               boost::bind(&BgpSession::ReceiveMsg, this, _1, _2))) {
      52       14650 : }
      53             : 
      54       28239 : BgpSession::~BgpSession() {
      55       28239 : }
      56             : 
      57             : //
      58             : // Concurrency: called in the context of io::Reader task.
      59             : //
      60      176388 : bool BgpSession::ReceiveMsg(const u_int8_t *msg, size_t size) {
      61      176388 :     return (peer_ ? peer_->ReceiveMsg(this, msg, size) : false);
      62             : }
      63             : 
      64             : //
      65             : // Concurrency: called in the context of bgp::Config task.
      66             : //
      67             : // Process write ready callback.
      68             : //
      69             : // 1. Tell BgpUpdateSender that the IPeer is send ready.
      70             : // 2. Tell BgpPeer that it's send ready so that it can resume Keepalives.
      71             : //
      72           0 : void BgpSession::ProcessWriteReady() {
      73           0 :     if (!peer_)
      74           0 :         return;
      75           0 :     BgpServer *server = peer_->server();
      76           0 :     BgpUpdateSender *sender = server->update_sender();
      77           0 :     sender->PeerSendReady(peer_);
      78           0 :     peer_->SetSendReady();
      79             : }
      80             : 
      81             : //
      82             : // Concurrency: called in the context of io thread.
      83             : //
      84             : // Handle write ready callback.  Enqueue the session to a WorkQueue in the
      85             : // BgpSessionManager.  The WorkQueue gets processed in the context of the
      86             : // bgp::Config task.  This ensures that we don't access the BgpPeer while
      87             : // the BgpPeer is trying to clear our back pointer to it.
      88             : //
      89             : // We can ignore any errors since the StateMachine will get informed of the
      90             : // TcpSession close independently and react to it.
      91             : //
      92           0 : void BgpSession::WriteReady(const boost::system::error_code &error) {
      93           0 :     if (error)
      94           0 :         return;
      95           0 :     session_mgr_->EnqueueWriteReady(this);
      96             : }
      97             : 
      98       12546 : void BgpSession::LogNotification(int code, int subcode, const string &direction,
      99             :                                  const string &peer_key,
     100             :                                  const BgpProto::Notification &msg) const {
     101             :     // Use SYS_DEBUG for connection collision, SYS_NOTICE for the rest.
     102       12546 :     if (code == BgpProto::Notification::Cease &&
     103             :         subcode == BgpProto::Notification::ConnectionCollision) {
     104        1993 :         BGP_LOG(BgpPeerNotification, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     105             :                 peer_key, direction, code, subcode, msg.ToString());
     106             :     } else {
     107       10553 :         BGP_LOG(BgpPeerNotificationNotice, SandeshLevel::SYS_NOTICE,
     108             :                 BGP_LOG_FLAG_ALL, peer_key, direction, code, subcode,
     109             :                 msg.ToString());
     110             :     }
     111       12549 : }
     112             : 
     113        7607 : void BgpSession::SendNotification(int code, int subcode,
     114             :                                   const string &data) {
     115        7607 :     BgpProto::Notification msg;
     116        7604 :     msg.error = code;
     117        7604 :     msg.subcode = subcode;
     118        7604 :     msg.data = data;
     119             :     uint8_t buf[BgpProto::kMaxMessageSize];
     120        7604 :     int msglen = BgpProto::Encode(&msg, buf, sizeof(buf));
     121             : 
     122        7595 :     LogNotification(code, subcode, BGP_PEER_DIR_OUT,
     123       15194 :                     peer_ ? peer_->ToUVEKey() : ToString(), msg);
     124        7602 :     if (msglen > BgpProto::kMinMessageSize) {
     125        7602 :         Send(buf, msglen, NULL);
     126             :     }
     127        7608 : }
     128             : 
     129       11453 : void BgpSession::set_peer(BgpPeer *peer) {
     130       11453 :     peer_ = peer;
     131       11453 :     task_instance_ = peer_->GetTaskInstance();
     132       11453 : }
     133             : 
     134             : //
     135             : // Dissociate the peer from the this BgpSession.
     136             : // Do not invalidate the task_instance since it can be used to spawn an
     137             : // io::ReaderTask while this method is being executed.
     138             : //
     139        6210 : void BgpSession::clear_peer() {
     140        6210 :     peer_ = NULL;
     141        6210 : }

Generated by: LCOV version 1.14