11 #include <arpa/inet.h> 15 #include "ns3/ipv4-list-routing.h" 16 #include "ns3/ipv4-static-routing.h" 17 #include "ns3/tcp-socket-factory.h" 18 #include "ns3/simulator.h" 22 NS_LOG_COMPONENT_DEFINE(
"Bgp");
23 NS_OBJECT_ENSURE_REGISTERED(Bgp);
40 socket->SetRecvCallback(MakeNullCallback<
void, Ptr<Socket>>());
41 socket->SetCloseCallbacks(
42 MakeNullCallback<
void, Ptr<Socket>>(),
43 MakeNullCallback<
void, Ptr<Socket>>()
51 TypeId Bgp::GetTypeId (
void) {
52 static TypeId tid = TypeId(
"ns3::Bgp")
53 .SetParent<Application>()
54 .SetGroupName(
"Internet")
55 .AddConstructor<
Bgp>()
56 .AddAttribute(
"LibbgpLogLevel",
"Log level for libbgp to use",
57 EnumValue(libbgp::INFO),
58 MakeEnumAccessor(&Bgp::_log_level),
60 libbgp::FATAL,
"Fatal",
61 libbgp::ERROR,
"Error",
62 libbgp::WARN,
"Warning",
64 libbgp::DEBUG,
"Debug"))
65 .AddAttribute(
"RouterID",
"Local BGP ID",
67 MakeIpv4AddressAccessor(&Bgp::_bgp_id),
68 MakeIpv4AddressChecker())
69 .AddAttribute(
"HoldTimer",
"Hold Timer",
70 TimeValue(Seconds(120)),
71 MakeTimeAccessor(&Bgp::_hold_timer),
72 MakeTimeChecker(Seconds(3), Seconds(UINT16_MAX)))
73 .AddAttribute(
"ClockInterval",
"Time to wait between ticking FSMs",
74 TimeValue(Seconds(1)),
75 MakeTimeAccessor(&Bgp::_clock_interval),
77 .AddAttribute(
"ErrorHold",
"Time to wait before retry.",
78 TimeValue(Seconds(45)),
79 MakeTimeAccessor(&Bgp::_error_hold),
85 Bgp::Bgp() : _logger(
"(local)"), _rib(&_logger) {
86 _log_level = libbgp::INFO;
88 _logger.setLogLevel(_log_level);
89 _routing = CreateObject<BgpRouting>();
90 _routing->SetRib(&_rib);
93 _listen_socket =
nullptr;
96 void Bgp::StartApplication(
void) {
98 NS_LOG_WARN(
"BGP application already started.");
102 NS_LOG_LOGIC(
"creating configuration template...");
103 _template.clock = &_clock;
104 _template.forced_default_nexthop4 =
false;
105 _template.hold_timer = (uint16_t) _hold_timer.GetSeconds();
106 _template.no_collision_detection =
false;
107 _template.no_nexthop_check4 =
false;
108 _template.rev_bus = &_bus;
109 _template.rib4 = &_rib;
110 _template.router_id = htonl(_bgp_id.Get());
111 _template.use_4b_asn =
true;
113 Ptr<Ipv4> ipv4 = GetNode()->GetObject<Ipv4>();
115 NS_LOG_LOGIC(
"installing BgpRouting...");
117 Ptr<Ipv4ListRouting> list_routing = CreateObject<Ipv4ListRouting>();
118 list_routing->AddRoutingProtocol(CreateObject<Ipv4StaticRouting>(), 10);
119 list_routing->AddRoutingProtocol(_routing, 5);
120 ipv4->SetRoutingProtocol(list_routing);
122 NS_LOG_LOGIC(
"starting listening socket...");
124 _listen_socket = Socket::CreateSocket(GetNode(), TcpSocketFactory::GetTypeId());
126 if (_listen_socket->Bind(InetSocketAddress(Ipv4Address::GetAny(), 179)) == -1) {
127 NS_FATAL_ERROR(
"failed to bind socket.");
130 if (_listen_socket->Listen() == -1) {
131 NS_FATAL_ERROR(
"failed to listen socket");
134 NS_LOG_LOGIC(
"registering callbacks...");
136 _listen_socket->SetAcceptCallback(
137 MakeCallback(&Bgp::HandleConnectInRequest,
this),
138 MakeCallback(&Bgp::HandleConnectIn,
this)
141 NS_LOG_LOGIC(
"sending OPEN message to peers...");
143 for (Ptr<Peer> &peer : _peers) {
145 NS_LOG_LOGIC(
"skipping passive peer AS" << peer->peer_asn <<
" (" << peer->peer_address <<
").");
150 Simulator::ScheduleNow(&Bgp::ConnectPeer,
this, peer);
154 NS_LOG_LOGIC(
"init complete.");
157 Simulator::Schedule(_clock_interval, &Bgp::Tick,
this);
160 void Bgp::StopApplication(
void) {
161 if (!_running)
return;
165 NS_LOG_LOGIC(
"closing listening socket...");
167 _listen_socket->Close();
168 _listen_socket->SetAcceptCallback(
169 MakeNullCallback<
bool, Ptr<Socket>,
const Address &> (),
170 MakeNullCallback<
void, Ptr<Socket>,
const Address &> ()
173 NS_LOG_LOGIC(
"de-peering...");
175 for (std::vector<Ptr<Session>>::iterator s = _sessions.begin(); s != _sessions.end();) {
180 NS_LOG_LOGIC(
"stopped.");
184 for (Ptr<Session> session : _sessions) {
185 session->fsm->tick();
188 if (_running) Simulator::Schedule(_clock_interval, &Bgp::Tick,
this);
189 else NS_LOG_LOGIC(
"ticker stopped.");
192 bool Bgp::ConnectPeer(Ptr<Peer> peer) {
193 if (!_running)
return false;
195 for (
const Ptr<Session> session : _sessions) {
196 if (session->peer == peer) {
197 NS_LOG_LOGIC(
"session or fsm for peer AS" << peer->peer_asn <<
" (" << peer->peer_address <<
") already exist, skipping.");
202 NS_LOG_LOGIC(
"obtaning local address information for peer AS" << peer->peer_asn <<
" (" << peer->peer_address <<
").");
204 Ipv4InterfaceAddress local_address = _routing->GetAddressByNexthop(peer->peer_address);
206 if (local_address.GetLocal().Get() == 0) {
207 NS_LOG_WARN(
"peer AS" << peer->peer_asn <<
" (" << peer->peer_address <<
") unreachable on any device, skipping.");
211 NS_LOG_LOGIC(
"create and bind socket for peer AS" << peer->peer_asn <<
" (" << peer->peer_address <<
").");
213 Ptr<Socket> peer_socket = Socket::CreateSocket(GetNode(), TcpSocketFactory::GetTypeId());
215 NS_LOG_LOGIC(
"using local address: " << local_address);
216 NS_LOG_LOGIC(
"registering callbacks...");
218 peer_socket->SetConnectCallback(
219 MakeCallback(&Bgp::HandleConnectOut,
this),
220 MakeCallback(&Bgp::HandleConnectOutFailed,
this)
223 if (peer->local_asn != peer->peer_asn) peer_socket->SetIpTtl(peer->ebgp_multihop);
225 if (peer_socket->Connect(InetSocketAddress(peer->peer_address, 179)) == -1) {
226 NS_LOG_ERROR(
"failed to connect: " << strerror(errno));
233 bool Bgp::HandleConnectInRequest(Ptr<Socket> socket,
const Address &src) {
237 void Bgp::HandleConnectOutFailed(Ptr<Socket> socket) {
238 NS_LOG_WARN(
"socket connect failed: " << socket);
241 void Bgp::HandleClose(Ptr<Socket> socket) {
242 NS_LOG_LOGIC(
"handling connection shutdown: " << socket);
244 for (std::vector<Ptr<Session>>::iterator session = _sessions.begin();
245 session != _sessions.end(); session++) {
246 if ((*session)->socket == socket) {
248 if (_running && !(*session)->peer->passive) {
249 NS_LOG_LOGIC(
"scheduled retry in " << _error_hold.GetSeconds() <<
" seconds.");
250 Simulator::Schedule(_error_hold, &Bgp::ConnectPeer,
this, (*session)->peer);
253 NS_LOG_INFO(
"dropping session of AS" << (*session)->peer->peer_asn <<
"/" << ((*session)->local_init ?
'L' :
'R') <<
" (" << (*session)->peer->peer_address <<
").");
255 _sessions.erase(session);
262 void Bgp::HandleConnectIn(Ptr<Socket> socket,
const Address &peer_addr) {
263 NS_LOG_LOGIC(
"incoming connection.");
264 SessionInit(
false, socket);
267 void Bgp::HandleConnectOut(Ptr<Socket> socket) {
268 NS_LOG_LOGIC(
"connected. unregister connect callback...");
269 socket->SetConnectCallback(
270 MakeNullCallback<
void, Ptr<Socket>>(),
271 MakeNullCallback<
void, Ptr<Socket>>()
273 SessionInit(
true, socket);
276 bool Bgp::SessionInit(
bool local_init, Ptr<Socket> socket) {
279 if (socket->GetPeerName(peer_addr) == -1) {
280 NS_LOG_WARN(
"failed to get peer information.");
285 InetSocketAddress peer_sockaddr = InetSocketAddress::ConvertFrom(peer_addr);
286 Ptr<Peer> peer =
nullptr;
288 NS_LOG_LOGIC(
"prepareing session with " << peer_sockaddr.GetIpv4() <<
"...");
290 for (Ptr<Peer> _peer : _peers) {
291 if (_peer->peer_address == peer_sockaddr.GetIpv4()) {
297 if (peer ==
nullptr) {
298 NS_LOG_WARN(
"socket peer address " << peer_sockaddr.GetIpv4() <<
" does not belong to any peer.");
303 for (
const Ptr<Session> session : _sessions) {
304 if (session->peer == peer && session->fsm->getState() == libbgp::ESTABLISHED) {
305 NS_LOG_INFO(
"session or fsm for peer AS" << peer->peer_asn <<
" (" << peer->peer_address <<
") already exist and established, closing socket.");
311 Ipv4InterfaceAddress local_addr = _routing->GetAddressByNexthop(peer_sockaddr.GetIpv4());
313 if (local_addr.GetLocal().Get() == 0) {
314 NS_LOG_WARN(
"peer AS" << peer->peer_asn <<
" (" << peer->peer_address <<
") unreachable on any device.");
319 NS_LOG_LOGIC(
"matching peer found. (AS" << peer->peer_asn <<
", " << peer->peer_address <<
").");
323 peer_name, 128,
"AS%d/AS%d/%c",
324 peer->local_asn, peer->peer_asn,
325 local_init ?
'L' :
'R');
328 Ptr<BgpLog> peer_logger = Create<BgpLog>(peer_name);
329 Ptr<BgpNs3SocketOut> peer_out_handler = Create<BgpNs3SocketOut>(socket, MakeCallback(&Bgp::HandleStateChange,
this));
331 peer_logger->setLogLevel(_log_level);
333 peer_config.
asn = peer->local_asn;
336 peer_config.
log_handler = PeekPointer(peer_logger);
338 peer_config.
out_handler = PeekPointer(peer_out_handler);
339 peer_config.
peer_asn = peer->peer_asn;
341 htonl(local_addr.GetLocal().CombineMask(local_addr.GetMask()).Get()),
342 local_addr.GetMask().GetPrefixLength());
346 peer_config.
weight = peer->weight;
348 peer_config.ibgp_alter_nexthop = peer->ibgp_alter_nexthop;
350 Ptr<BgpNs3Fsm> peer_fsm = Create<BgpNs3Fsm>(peer_config);
351 Ptr<Session> peer_session = Create<Session>();
352 Ptr<BgpNs3SocketIn> in_handler = Create<BgpNs3SocketIn>(peer_fsm);
353 peer_session->peer = peer;
354 peer_session->socket = socket;
355 peer_session->fsm = peer_fsm;
356 peer_session->logger = peer_logger;
358 peer_session->in_handler = in_handler;
359 peer_session->local_init = local_init;
362 socket->SetCloseCallbacks(
363 MakeCallback(&Bgp::HandleClose,
this),
364 MakeCallback(&Bgp::HandleClose,
this)
367 if (local_init) peer_fsm->start();
369 _sessions.push_back(peer_session);
374 void Bgp::HandleStateChange(Ptr<Socket> socket,
int old_state,
int new_state) {
375 if (new_state == libbgp::IDLE || new_state == libbgp::BROKEN) {
386 NS_ASSERT(!_running);
387 _peers.push_back(Create<Peer>(peer));
397 NS_ASSERT(!_running);
398 _rib.insert(&_logger, route, nexthop);
409 NS_ASSERT(!_running);
420 void Bgp::AddRoute(
const Ipv4Address &prefix,
const Ipv4Mask &mask,
const Ipv4Address &nexthop) {
421 NS_ASSERT(!_running);
422 AddRoute(htonl(prefix.Get()), (uint8_t) mask.GetPrefixLength(), htonl(nexthop.Get()));
431 NS_ASSERT(!_running);
432 _log_level = log_level;
441 NS_ASSERT(!_running);
451 NS_ASSERT(!_running);
452 _hold_timer = hold_timer;
461 NS_ASSERT(!_running);
462 _clock_interval = interval;
bool forced_default_nexthop
always use peering IP as nexthop.
BgpLogHandler * log_handler
void SetHoldTimer(Time hold_timer)
Set local hold timer.
Peer configuration class.
void SetBgpId(Ipv4Address bgp_id)
Set local router ID.
BgpFilterRules in_filters4
uint32_t default_nexthop4
bool ibgp_alter_nexthop
alter IBGP nexthop attribute the same way as EBGP.
bool forced_default_nexthop4
int32_t weight
weight of this peer
int8_t allow_local_as
Allow N local ASN in AS_PATH.
void AddPeer(const Peer &peer)
Add a peer to the BGP application.
bool passive
passive peering (don't send OPEN)
bool no_nexthop_check
disable nexthop attribute validation
BgpFilterRules out_filters4
void AddRoute(libbgp::Prefix4 route, uint32_t nexthop)
Add a route to BGP routing table.
void HandleRead(Ptr< Socket > socket)
Handle reading from socket.
BgpOutHandler * out_handler
void Drop()
Drop this session.
void SetLibbgpLogLevel(libbgp::LogLevel log_level)
Set libbgp log level.
void SetClockInterval(Time interval)
Set Tick() interval.