/
bgp_session.cc
100 lines (84 loc) · 2.85 KB
/
bgp_session.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/*
* Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
*/
#include "bgp/bgp_session.h"
#include <algorithm>
#include <string>
#include "base/logging.h"
#include "base/parse_object.h"
#include "bgp/bgp_log.h"
#include "bgp/bgp_peer.h"
#include "bgp/bgp_session_manager.h"
#include "bgp/scheduling_group.h"
using std::string;
using boost::asio::mutable_buffer;
// Extract the total BGP message length. This is a 2 byte field after the
// 16 byte marker. If the buffer doesn't have 18 bytes available return -1.
int BgpMessageReader::MsgLength(Buffer buffer, int offset) {
size_t size = TcpSession::BufferSize(buffer);
int remain = size - offset;
if (remain < BgpMessageReader::kHeaderLenSize) {
return -1;
}
const uint8_t *data = TcpSession::BufferData(buffer) + offset;
data += 16;
int length = get_value(data, 2);
return length;
}
BgpMessageReader::BgpMessageReader(TcpSession *session,
ReceiveCallback callback)
: TcpMessageReader(session, callback) {
}
BgpMessageReader::~BgpMessageReader() {
}
BgpSession::BgpSession(BgpSessionManager *session, Socket *socket)
: TcpSession(session, socket),
peer_(NULL),
reader_(new BgpMessageReader(this,
boost::bind(&BgpSession::ReceiveMsg, this, _1, _2))) {
}
BgpSession::~BgpSession() {
}
//
// Handle write ready callback.
//
// 1. Tell SchedulingGroupManager that the IPeer is send ready.
// 2. Tell BgpPeer that it's send ready so that it can resume Keepalives.
//
// We can ignore any errors since the StateMachine will get informed of the
// TcpSession close independently and react to it.
//
void BgpSession::WriteReady(const boost::system::error_code &error) {
if (error || !peer_)
return;
BgpServer *server = peer_->server();
SchedulingGroupManager *sg_mgr = server->scheduling_group_manager();
sg_mgr->SendReady(peer_);
peer_->SetSendReady();
}
int BgpSession::GetSessionInstance() const {
return peer_->GetIndex();
}
void BgpSession::SendNotification(int code, int subcode,
const string &data) {
BgpProto::Notification msg;
msg.error = code;
msg.subcode = subcode;
msg.data = data;
uint8_t buf[BgpProto::kMaxMessageSize];
int msglen = BgpProto::Encode(&msg, buf, sizeof(buf));
// Use SYS_DEBUG for connection collision, SYS_NOTICE for the rest.
SandeshLevel::type log_level;
if (code == BgpProto::Notification::Cease &&
subcode == BgpProto::Notification::ConnectionCollision) {
log_level = SandeshLevel::SYS_DEBUG;
} else {
log_level = SandeshLevel::SYS_NOTICE;
}
BGP_LOG(BgpPeerNotification, log_level, BGP_LOG_FLAG_ALL,
peer_ ? peer_->ToUVEKey() : ToString(),
BGP_PEER_DIR_OUT, code, subcode, msg.ToString());
if (msglen > BgpProto::kMinMessageSize) {
Send(buf, msglen, NULL);
}
}