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_xmpp_channel.h"
7 :
8 : #include <boost/assign/list_of.hpp>
9 : #include <boost/foreach.hpp>
10 :
11 : #include <limits>
12 : #include <sstream>
13 : #include <vector>
14 : #include <atomic>
15 :
16 : #include "base/regex.h"
17 : #include "base/task_annotations.h"
18 : #include "bgp/bgp_config.h"
19 : #include "bgp/bgp_factory.h"
20 : #include "bgp/bgp_log.h"
21 : #include "bgp/bgp_membership.h"
22 : #include "bgp/bgp_server.h"
23 : #include "bgp/bgp_update_sender.h"
24 : #include "bgp/bgp_xmpp_peer_close.h"
25 : #include "bgp/inet/inet_table.h"
26 : #include "bgp/inet6/inet6_table.h"
27 : #include "bgp/extended-community/etree.h"
28 : #include "bgp/extended-community/load_balance.h"
29 : #include "bgp/extended-community/mac_mobility.h"
30 : #include "bgp/extended-community/local_sequence_number.h"
31 : #include "bgp/extended-community/router_mac.h"
32 : #include "bgp/extended-community/tag.h"
33 : #include "bgp/large-community/tag.h"
34 : #include "bgp/ermvpn/ermvpn_table.h"
35 : #include "bgp/evpn/evpn_route.h"
36 : #include "bgp/evpn/evpn_table.h"
37 : #include "bgp/mvpn/mvpn_table.h"
38 : #include "bgp/peer_close_manager.h"
39 : #include "bgp/peer_stats.h"
40 : #include "bgp/security_group/security_group.h"
41 : #include "bgp/tunnel_encap/tunnel_encap.h"
42 : #include "bgp/bgp_xmpp_rtarget_manager.h"
43 : #include "control-node/sandesh/control_node_types.h"
44 : #include "net/community_type.h"
45 : #include "schema/xmpp_multicast_types.h"
46 : #include "schema/xmpp_enet_types.h"
47 : #include "schema/xmpp_mvpn_types.h"
48 : #include "xml/xml_pugi.h"
49 : #include "xmpp/xmpp_connection.h"
50 : #include "xmpp/xmpp_init.h"
51 : #include "xmpp/xmpp_server.h"
52 : #include "xmpp/sandesh/xmpp_peer_info_types.h"
53 :
54 : using autogen::EnetItemType;
55 : using autogen::EnetNextHopListType;
56 : using autogen::EnetSecurityGroupListType;
57 : using autogen::EnetTunnelEncapsulationListType;
58 :
59 : using autogen::McastItemType;
60 : using autogen::McastNextHopsType;
61 : using autogen::McastTunnelEncapsulationListType;
62 :
63 : using autogen::MvpnItemType;
64 : using autogen::MvpnNextHopType;
65 : using autogen::MvpnTunnelEncapsulationListType;
66 :
67 : using autogen::ItemType;
68 : using autogen::NextHopListType;
69 : using autogen::SecurityGroupListType;
70 : using autogen::CommunityTagListType;
71 : using autogen::TunnelEncapsulationListType;
72 : using autogen::TagListType;
73 :
74 : using boost::assign::list_of;
75 : using boost::smatch;
76 : using boost::system::error_code;
77 : using contrail::regex;
78 : using contrail::regex_match;
79 : using contrail::regex_search;
80 : using pugi::xml_node;
81 : using std::unique_ptr;
82 : using std::make_pair;
83 : using std::numeric_limits;
84 : using std::ostringstream;
85 : using std::pair;
86 : using std::set;
87 : using std::string;
88 : using std::vector;
89 :
90 : //
91 : // Calculate med from local preference.
92 : // Should move agent definitions to a common location and use those here
93 : // instead of hard coded values.
94 : //
95 12366 : static uint32_t GetMedFromLocalPref(uint32_t local_pref) {
96 12366 : if (local_pref == 0)
97 2384 : return 0;
98 9982 : if (local_pref == 100)
99 6861 : return 200;
100 3121 : if (local_pref == 200)
101 34 : return 100;
102 3087 : return numeric_limits<uint32_t>::max() - local_pref;
103 : }
104 :
105 2 : void BgpXmppChannel::ErrorStats::incr_inet6_rx_bad_xml_token_count() {
106 2 : ++inet6_rx_bad_xml_token_count;
107 2 : }
108 :
109 2 : void BgpXmppChannel::ErrorStats::incr_inet6_rx_bad_prefix_count() {
110 2 : ++inet6_rx_bad_prefix_count;
111 2 : }
112 :
113 3 : void BgpXmppChannel::ErrorStats::incr_inet6_rx_bad_nexthop_count() {
114 3 : ++inet6_rx_bad_nexthop_count;
115 3 : }
116 :
117 3 : void BgpXmppChannel::ErrorStats::incr_inet6_rx_bad_afi_safi_count() {
118 3 : ++inet6_rx_bad_afi_safi_count;
119 3 : }
120 :
121 77 : uint64_t BgpXmppChannel::ErrorStats::get_inet6_rx_bad_xml_token_count() const {
122 77 : return inet6_rx_bad_xml_token_count;
123 : }
124 :
125 77 : uint64_t BgpXmppChannel::ErrorStats::get_inet6_rx_bad_prefix_count() const {
126 77 : return inet6_rx_bad_prefix_count;
127 : }
128 :
129 77 : uint64_t BgpXmppChannel::ErrorStats::get_inet6_rx_bad_nexthop_count() const {
130 77 : return inet6_rx_bad_nexthop_count;
131 : }
132 :
133 80 : uint64_t BgpXmppChannel::ErrorStats::get_inet6_rx_bad_afi_safi_count() const {
134 80 : return inet6_rx_bad_afi_safi_count;
135 : }
136 :
137 : class BgpXmppChannel::PeerStats : public IPeerDebugStats {
138 : public:
139 10042 : explicit PeerStats(BgpXmppChannel *peer)
140 10042 : : parent_(peer) {
141 10042 : }
142 :
143 : // Used when peer flaps.
144 : // Don't need to do anything since the BgpXmppChannel itself gets deleted.
145 0 : virtual void Clear() {
146 0 : }
147 :
148 : // Printable name
149 0 : virtual string ToString() const {
150 0 : return parent_->ToString();
151 : }
152 :
153 : // Previous State of the peer
154 487 : virtual string last_state() const {
155 487 : return (parent_->channel_->LastStateName());
156 : }
157 : // Last state change occurred at
158 487 : virtual string last_state_change_at() const {
159 487 : return (parent_->channel_->LastStateChangeAt());
160 : }
161 :
162 : // Last error on this peer
163 487 : virtual string last_error() const {
164 487 : return "";
165 : }
166 :
167 : // Last Event on this peer
168 487 : virtual string last_event() const {
169 487 : return (parent_->channel_->LastEvent());
170 : }
171 :
172 : // When was the Last
173 1461 : virtual string last_flap() const {
174 1461 : return (parent_->channel_->LastFlap());
175 : }
176 :
177 : // Total number of flaps
178 1461 : virtual uint64_t num_flaps() const {
179 1461 : return (parent_->channel_->FlapCount());
180 : }
181 :
182 561 : virtual void GetRxProtoStats(ProtoStats *stats) const {
183 561 : stats->open = parent_->channel_->rx_open();
184 561 : stats->close = parent_->channel_->rx_close();
185 561 : stats->keepalive = parent_->channel_->rx_keepalive();
186 561 : stats->update = parent_->channel_->rx_update();
187 561 : }
188 :
189 561 : virtual void GetTxProtoStats(ProtoStats *stats) const {
190 561 : stats->open = parent_->channel_->tx_open();
191 561 : stats->close = parent_->channel_->tx_close();
192 561 : stats->keepalive = parent_->channel_->tx_keepalive();
193 561 : stats->update = parent_->channel_->tx_update();
194 561 : }
195 :
196 635 : virtual void GetRxRouteUpdateStats(UpdateStats *stats) const {
197 635 : stats->reach = parent_->stats_[RX].reach.load();
198 635 : stats->unreach = parent_->stats_[RX].unreach.load();
199 635 : stats->end_of_rib = parent_->stats_[RX].end_of_rib.load();
200 635 : stats->total = stats->reach + stats->unreach + stats->end_of_rib;
201 635 : }
202 :
203 635 : virtual void GetTxRouteUpdateStats(UpdateStats *stats) const {
204 635 : stats->reach = parent_->stats_[TX].reach.load();
205 635 : stats->unreach = parent_->stats_[TX].unreach.load();
206 635 : stats->end_of_rib = parent_->stats_[TX].end_of_rib.load();
207 635 : stats->total = stats->reach + stats->unreach + stats->end_of_rib;
208 635 : }
209 :
210 487 : virtual void GetRxSocketStats(IPeerDebugStats::SocketStats *stats) const {
211 487 : const XmppSession *session = parent_->GetSession();
212 487 : if (session) {
213 475 : const io::SocketStats &socket_stats = session->GetSocketStats();
214 475 : stats->calls = socket_stats.read_calls;
215 475 : stats->bytes = socket_stats.read_bytes;
216 : }
217 487 : }
218 :
219 487 : virtual void GetTxSocketStats(IPeerDebugStats::SocketStats *stats) const {
220 487 : const XmppSession *session = parent_->GetSession();
221 487 : if (session) {
222 475 : const io::SocketStats &socket_stats = session->GetSocketStats();
223 475 : stats->calls = socket_stats.write_calls;
224 475 : stats->bytes = socket_stats.write_bytes;
225 475 : stats->blocked_count = socket_stats.write_blocked;
226 475 : stats->blocked_duration_usecs =
227 475 : socket_stats.write_blocked_duration_usecs;
228 : }
229 487 : }
230 :
231 74 : virtual void GetRxErrorStats(RxErrorStats *stats) const {
232 74 : const BgpXmppChannel::ErrorStats &err_stats = parent_->error_stats();
233 74 : stats->inet6_bad_xml_token_count =
234 74 : err_stats.get_inet6_rx_bad_xml_token_count();
235 74 : stats->inet6_bad_prefix_count =
236 74 : err_stats.get_inet6_rx_bad_prefix_count();
237 74 : stats->inet6_bad_nexthop_count =
238 74 : err_stats.get_inet6_rx_bad_nexthop_count();
239 74 : stats->inet6_bad_afi_safi_count =
240 74 : err_stats.get_inet6_rx_bad_afi_safi_count();
241 74 : }
242 :
243 74 : virtual void GetRxRouteStats(RxRouteStats *stats) const {
244 74 : stats->total_path_count = parent_->Peer()->GetTotalPathCount();
245 74 : stats->primary_path_count = parent_->Peer()->GetPrimaryPathCount();
246 74 : }
247 :
248 1570639 : virtual void UpdateTxUnreachRoute(uint64_t count) {
249 1570639 : parent_->stats_[TX].unreach += count;
250 1570687 : }
251 :
252 1570489 : virtual void UpdateTxReachRoute(uint64_t count) {
253 1570489 : parent_->stats_[TX].reach += count;
254 1570686 : }
255 :
256 : private:
257 : BgpXmppChannel *parent_;
258 : };
259 :
260 : class BgpXmppChannel::XmppPeer : public IPeer {
261 : public:
262 10042 : XmppPeer(BgpServer *server, BgpXmppChannel *channel)
263 20084 : : server_(server),
264 10042 : parent_(channel),
265 10042 : is_closed_(false),
266 10042 : send_ready_(true),
267 10042 : closed_at_(0) {
268 10042 : total_path_count_ = 0;
269 10042 : primary_path_count_ = 0;
270 10042 : }
271 :
272 20084 : virtual ~XmppPeer() {
273 10042 : assert(GetTotalPathCount() == 0);
274 :
275 20084 : XmppPeerInfoData peer_info;
276 10042 : peer_info.set_name(ToUVEKey());
277 10042 : peer_info.set_deleted(true);
278 10042 : parent_->XMPPPeerInfoSend(peer_info);
279 :
280 20084 : PeerStatsData peer_stats_data;
281 10042 : peer_stats_data.set_name(ToUVEKey());
282 10042 : peer_stats_data.set_deleted(true);
283 10042 : assert(!peer_stats_data.get_name().empty());
284 10042 : BGP_UVE_SEND2(PeerStatsUve, peer_stats_data, "ObjectXmppPeerInfo");
285 20084 : }
286 :
287 19537 : virtual bool MembershipPathCallback(DBTablePartBase *tpart, BgpRoute *rt,
288 : BgpPath *path) {
289 19537 : if (parent_->close_manager_->IsMembershipInUse())
290 19507 : return parent_->close_manager_->MembershipPathCallback(tpart, rt,
291 19520 : path);
292 :
293 30 : BgpTable *table = static_cast<BgpTable *>(tpart->parent());
294 30 : return table->DeletePath(tpart, rt, path);
295 : }
296 :
297 : virtual bool SendUpdate(const uint8_t *msg, size_t msgsize,
298 : const std::string *msg_str);
299 56932 : virtual bool SendUpdate(const uint8_t *msg, size_t msgsize) {
300 56932 : return SendUpdate(msg, msgsize, NULL);
301 : }
302 1663811 : virtual const string &ToString() const {
303 1663811 : return parent_->ToString();
304 : }
305 :
306 6312 : virtual bool CanUseMembershipManager() const {
307 6312 : return parent_->GetMembershipRequestQueueSize() == 0;
308 : }
309 :
310 59151 : virtual bool IsRegistrationRequired() const { return true; }
311 :
312 634165 : virtual const string &ToUVEKey() const {
313 634165 : return parent_->ToUVEKey();
314 : }
315 :
316 754516 : virtual BgpServer *server() { return server_; }
317 3881677 : virtual BgpServer *server() const { return server_; }
318 0 : virtual IPeerClose *peer_close() {
319 0 : return parent_->peer_close_.get();
320 : }
321 65703 : virtual IPeerClose *peer_close() const {
322 65703 : return parent_->peer_close_.get();
323 : }
324 :
325 65703 : void UpdateCloseRouteStats(Address::Family family, const BgpPath *old_path,
326 : uint32_t path_flags) const {
327 65703 : peer_close()->UpdateRouteStats(family, old_path, path_flags);
328 65702 : }
329 :
330 1570576 : virtual IPeerDebugStats *peer_stats() {
331 1570576 : return parent_->peer_stats_.get();
332 : }
333 2583 : virtual const IPeerDebugStats *peer_stats() const {
334 2583 : return parent_->peer_stats_.get();
335 : }
336 :
337 193272 : virtual bool IsReady() const {
338 193272 : return (parent_->channel_->GetPeerState() == xmps::READY);
339 : }
340 0 : virtual const string GetStateName() const {
341 0 : switch (parent_->channel_->GetPeerState()) {
342 0 : case xmps::UNKNOWN: return "UNKNOWN";
343 0 : case xmps::READY: return "READY";
344 0 : case xmps::NOT_READY: return "NOT_READY";
345 0 : case xmps::TIMEDOUT: return "TIMEDOUT";
346 : }
347 0 : return "UNKNOWN";
348 : }
349 1760394 : virtual bool IsXmppPeer() const {
350 1760394 : return true;
351 : }
352 : virtual void Close(bool graceful);
353 :
354 74470 : const bool IsDeleted() const { return is_closed_; }
355 16608 : void SetPeerClosed(bool closed) {
356 16608 : is_closed_ = closed;
357 16608 : if (is_closed_)
358 16384 : closed_at_ = UTCTimestampUsec();
359 16609 : }
360 974 : uint64_t closed_at() const { return closed_at_; }
361 :
362 493268 : virtual BgpProto::BgpPeerType PeerType() const {
363 493268 : return BgpProto::XMPP;
364 : }
365 :
366 228922 : virtual uint32_t bgp_identifier() const {
367 228922 : const TcpSession::Endpoint &remote = parent_->endpoint();
368 228922 : if (remote.address().is_v4()) {
369 228921 : return remote.address().to_v4().to_ulong();
370 : }
371 0 : return 0;
372 : }
373 :
374 251046 : virtual void UpdateTotalPathCount(int count) const {
375 251046 : total_path_count_ += count;
376 251064 : }
377 10116 : virtual int GetTotalPathCount() const {
378 10116 : return total_path_count_;
379 : }
380 0 : virtual bool IsAs4Supported() const { return true; }
381 128922 : virtual void UpdatePrimaryPathCount(int count,
382 : Address::Family family) const {
383 128922 : primary_path_count_ += count;
384 128924 : }
385 1048 : virtual int GetPrimaryPathCount() const {
386 1048 : return primary_path_count_;
387 : }
388 125127 : virtual void ProcessPathTunnelEncapsulation(const BgpPath *path,
389 : BgpAttr *attr, ExtCommunityDB *extcomm_db, const BgpTable *table)
390 : const {
391 125127 : }
392 0 : virtual const std::vector<std::string> GetDefaultTunnelEncap(
393 : Address::Family family) const {
394 0 : return std::vector<std::string>();
395 : }
396 0 : virtual bool IsInGRTimerWaitState() const {
397 0 : return parent_->close_manager_->IsInGRTimerWaitState();
398 : }
399 :
400 141165 : void MembershipRequestCallback(BgpTable *table) {
401 141165 : parent_->MembershipRequestCallback(table);
402 141165 : }
403 :
404 1800474 : virtual bool send_ready() const { return send_ready_; }
405 26108 : bool IsRouterTypeBGPaaS() const { return false; }
406 :
407 : private:
408 2 : void WriteReadyCb(const boost::system::error_code &ec) {
409 2 : if (!server_) return;
410 2 : BgpUpdateSender *sender = server_->update_sender();
411 3 : BGP_LOG_PEER(Event, this, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
412 : BGP_PEER_DIR_NA, "Send ready");
413 2 : sender->PeerSendReady(this);
414 2 : send_ready_ = true;
415 :
416 : // Restart EndOfRib Send timer if necessary.
417 2 : parent_->ResetEndOfRibSendState();
418 : }
419 :
420 : BgpServer *server_;
421 : BgpXmppChannel *parent_;
422 : mutable std::atomic<int> total_path_count_;
423 : mutable std::atomic<int> primary_path_count_;
424 : bool is_closed_;
425 : bool send_ready_;
426 : uint64_t closed_at_;
427 : };
428 :
429 : // Skip sending updates if the destinatin matches against the pattern.
430 : // XXX Used in test environments only
431 1623936 : bool BgpXmppChannel::SkipUpdateSend() {
432 1623936 : static char *skip_env_ = getenv("XMPP_SKIP_UPDATE_SEND");
433 1623942 : if (!skip_env_)
434 1623942 : return false;
435 :
436 : // Use XMPP_SKIP_UPDATE_SEND as a regex pattern to match against destination
437 : // Cache the result to avoid redundant regex evaluation
438 0 : if (!skip_update_send_cached_) {
439 0 : smatch matches;
440 0 : skip_update_send_ = regex_search(ToString(), matches, regex(skip_env_));
441 0 : skip_update_send_cached_ = true;
442 0 : }
443 0 : return skip_update_send_;
444 : }
445 :
446 1627270 : bool BgpXmppChannel::XmppPeer::SendUpdate(const uint8_t *msg, size_t msgsize,
447 : const string *msg_str) {
448 1627270 : XmppChannel *channel = parent_->channel_;
449 1627270 : if (channel->GetPeerState() == xmps::READY) {
450 1623679 : parent_->stats_[TX].rt_updates++;
451 1624000 : if (parent_->SkipUpdateSend())
452 0 : return true;
453 1623939 : send_ready_ = channel->Send(msg, msgsize, msg_str, xmps::BGP,
454 : boost::bind(&BgpXmppChannel::XmppPeer::WriteReadyCb, this, _1));
455 1623923 : if (!send_ready_) {
456 118 : BGP_LOG_PEER(Event, this, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
457 : BGP_PEER_DIR_NA, "Send blocked");
458 :
459 : // If EndOfRib Send timer is running, cancel it and reschedule it
460 : // after socket gets unblocked.
461 88 : if (parent_->eor_send_timer_ && parent_->eor_send_timer_->running())
462 63 : parent_->eor_send_timer_->Cancel();
463 : }
464 1623899 : return send_ready_;
465 : } else {
466 3594 : return false;
467 : }
468 : }
469 :
470 10167 : void BgpXmppChannel::XmppPeer::Close(bool graceful) {
471 10167 : send_ready_ = true;
472 10167 : parent_->set_peer_closed(true);
473 10168 : if (server_ == NULL)
474 3815 : return;
475 :
476 : XmppConnection *connection =
477 6353 : const_cast<XmppConnection *>(parent_->channel_->connection());
478 :
479 6354 : if (connection && !connection->IsActiveChannel()) {
480 :
481 : // Clear EOR state.
482 6344 : parent_->ClearEndOfRibState();
483 :
484 6344 : parent_->peer_close_->Close(graceful);
485 : }
486 : }
487 :
488 10042 : BgpXmppChannel::BgpXmppChannel(XmppChannel *channel,
489 : BgpServer *bgp_server,
490 10042 : BgpXmppChannelManager *manager)
491 10042 : : channel_(channel),
492 10042 : peer_id_(xmps::BGP),
493 10042 : rtarget_manager_(new BgpXmppRTargetManager(this)),
494 10042 : bgp_server_(bgp_server),
495 10042 : peer_(new XmppPeer(bgp_server, this)),
496 10042 : peer_close_(new BgpXmppPeerClose(this)),
497 10042 : peer_stats_(new PeerStats(this)),
498 10042 : bgp_policy_(BgpProto::XMPP, RibExportPolicy::XMPP, -1, 0),
499 10042 : manager_(manager),
500 10042 : delete_in_progress_(false),
501 10042 : deleted_(false),
502 10042 : defer_peer_close_(false),
503 10042 : skip_update_send_(false),
504 10042 : skip_update_send_cached_(false),
505 10042 : eor_sent_(false),
506 10042 : eor_receive_timer_(NULL),
507 10042 : eor_send_timer_(NULL),
508 10042 : eor_receive_timer_start_time_(0),
509 10042 : eor_send_timer_start_time_(0),
510 20084 : membership_response_worker_(
511 : TaskScheduler::GetInstance()->GetTaskId("xmpp::StateMachine"),
512 10042 : channel->GetTaskInstance(),
513 : boost::bind(&BgpXmppChannel::MembershipResponseHandler, this, _1)),
514 60252 : lb_mgr_(new LabelBlockManager()) {
515 10041 : close_manager_.reset(
516 10042 : BgpStaticObjectFactory::Create<PeerCloseManager>(static_cast<IPeerClose*>(peer_close_.get())));
517 10042 : if (bgp_server) {
518 6227 : eor_receive_timer_ =
519 6227 : TimerManager::CreateTimer(*bgp_server->ioservice(),
520 : "EndOfRib receive timer",
521 : TaskScheduler::GetInstance()->GetTaskId("xmpp::StateMachine"),
522 6227 : channel->GetTaskInstance());
523 6227 : eor_send_timer_ =
524 6227 : TimerManager::CreateTimer(*bgp_server->ioservice(),
525 : "EndOfRib send timer",
526 : TaskScheduler::GetInstance()->GetTaskId("xmpp::StateMachine"),
527 6227 : channel->GetTaskInstance());
528 : }
529 10042 : channel_->RegisterReferer(peer_id_);
530 10042 : channel_->RegisterReceive(peer_id_,
531 : boost::bind(&BgpXmppChannel::ReceiveUpdate, this, _1));
532 12449 : BGP_LOG_PEER(Event, peer_.get(), SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
533 : BGP_PEER_DIR_NA, "Created");
534 10042 : }
535 :
536 15587 : BgpXmppChannel::~BgpXmppChannel() {
537 10042 : if (channel_->connection() && !channel_->connection()->IsActiveChannel()) {
538 6178 : CHECK_CONCURRENCY("bgp::Config");
539 : }
540 :
541 10042 : if (manager_)
542 6188 : manager_->RemoveChannel(channel_);
543 10042 : if (manager_ && delete_in_progress_)
544 6178 : manager_->decrement_deleting_count();
545 10042 : STLDeleteElements(&defer_q_);
546 10042 : assert(peer_deleted());
547 10042 : assert(!close_manager_->IsMembershipInUse());
548 10042 : assert(table_membership_request_map_.empty());
549 10042 : TimerManager::DeleteTimer(eor_receive_timer_);
550 10042 : TimerManager::DeleteTimer(eor_send_timer_);
551 12449 : BGP_LOG_PEER(Event, peer_.get(), SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
552 : BGP_PEER_DIR_NA, "Deleted");
553 10042 : channel_->UnRegisterWriteReady(peer_id_);
554 10042 : channel_->UnRegisterReferer(peer_id_);
555 10042 : channel_->UnRegisterReceive(peer_id_);
556 15587 : }
557 :
558 10042 : void BgpXmppChannel::XMPPPeerInfoSend(const XmppPeerInfoData &peer_info) const {
559 10042 : assert(!peer_info.get_name().empty());
560 10042 : BGP_UVE_SEND(XMPPPeerInfo, peer_info);
561 10042 : }
562 :
563 5662 : const XmppSession *BgpXmppChannel::GetSession() const {
564 5662 : if (channel_ && channel_->connection()) {
565 5662 : return channel_->connection()->session();
566 : }
567 0 : return NULL;
568 : }
569 :
570 1666752 : const string &BgpXmppChannel::ToString() const {
571 1666752 : return channel_->ToString();
572 : }
573 :
574 634165 : const string &BgpXmppChannel::ToUVEKey() const {
575 634165 : if (channel_->connection()) {
576 633807 : return channel_->connection()->ToUVEKey();
577 : } else {
578 368 : return channel_->ToString();
579 : }
580 : }
581 :
582 974 : string BgpXmppChannel::StateName() const {
583 974 : return channel_->StateName();
584 : }
585 :
586 :
587 6312 : size_t BgpXmppChannel::GetMembershipRequestQueueSize() const {
588 6312 : return table_membership_request_map_.size();
589 : }
590 :
591 2797 : void BgpXmppChannel::RoutingInstanceCallback(string vrf_name, int op) {
592 2797 : if (delete_in_progress_)
593 76 : return;
594 2721 : if (vrf_name == BgpConfigManager::kMasterInstance)
595 131 : return;
596 2590 : if (op == RoutingInstanceMgr::INSTANCE_DELETE)
597 428 : return;
598 :
599 2162 : RoutingInstanceMgr *instance_mgr = bgp_server_->routing_instance_mgr();
600 2162 : assert(instance_mgr);
601 2162 : RoutingInstance *rt_instance = instance_mgr->GetRoutingInstance(vrf_name);
602 2162 : assert(rt_instance);
603 :
604 2162 : if (op == RoutingInstanceMgr::INSTANCE_ADD) {
605 : const InstanceMembershipRequestState *imr_state =
606 64 : GetInstanceMembershipState(vrf_name);
607 64 : if (!imr_state)
608 32 : return;
609 32 : ProcessDeferredSubscribeRequest(rt_instance, *imr_state);
610 32 : DeleteInstanceMembershipState(vrf_name);
611 : } else {
612 2098 : SubscriptionState *sub_state = GetSubscriptionState(rt_instance);
613 2098 : if (!sub_state)
614 773 : return;
615 1325 : rtarget_manager_->RoutingInstanceCallback(
616 : rt_instance, &sub_state->targets);
617 : }
618 : }
619 :
620 1495958 : IPeer *BgpXmppChannel::Peer() {
621 1495958 : return peer_.get();
622 : }
623 :
624 5167 : const IPeer *BgpXmppChannel::Peer() const {
625 5167 : return peer_.get();
626 : }
627 :
628 228913 : TcpSession::Endpoint BgpXmppChannel::endpoint() const {
629 228913 : return channel_->connection()->endpoint();
630 : }
631 :
632 30058 : bool BgpXmppChannel::XmppDecodeAddress(int af, const string &address,
633 : IpAddress *addrp, bool zero_ok) {
634 30058 : if (af != BgpAf::IPv4 && af != BgpAf::IPv6 && af != BgpAf::L2Vpn)
635 0 : return false;
636 :
637 30058 : error_code error;
638 30058 : *addrp = IpAddress::from_string(address, error);
639 30063 : if (error)
640 17 : return false;
641 :
642 30046 : return (zero_ok ? true : !addrp->is_unspecified());
643 : }
644 :
645 : //
646 : // Return true if there's a pending request, false otherwise.
647 : //
648 40075 : bool BgpXmppChannel::GetMembershipInfo(BgpTable *table,
649 : int *instance_id, uint64_t *subscription_gen_id, RequestType *req_type) {
650 40075 : *instance_id = -1;
651 40075 : *subscription_gen_id = 0;
652 : TableMembershipRequestState *tmr_state =
653 40075 : GetTableMembershipState(table->name());
654 40076 : if (tmr_state) {
655 1270 : *req_type = tmr_state->pending_req;
656 1270 : *instance_id = tmr_state->instance_id;
657 1270 : return true;
658 : } else {
659 38806 : *req_type = NONE;
660 38806 : BgpMembershipManager *mgr = bgp_server_->membership_mgr();
661 38807 : mgr->GetRegistrationInfo(peer_.get(), table,
662 : instance_id, subscription_gen_id);
663 38811 : return false;
664 : }
665 : }
666 :
667 : //
668 : // Add entry to the pending table request map.
669 : //
670 72819 : void BgpXmppChannel::AddTableMembershipState(const string &table_name,
671 : TableMembershipRequestState tmr_state) {
672 72819 : table_membership_request_map_.insert(make_pair(table_name, tmr_state));
673 72819 : }
674 :
675 : //
676 : // Delete entry from the pending table request map.
677 : // Return true if the entry was found and deleted.
678 : //
679 72819 : bool BgpXmppChannel::DeleteTableMembershipState(const string &table_name) {
680 72819 : return (table_membership_request_map_.erase(table_name) > 0);
681 : }
682 :
683 : //
684 : // Find entry in the pending table request map.
685 : //
686 : BgpXmppChannel::TableMembershipRequestState *
687 185949 : BgpXmppChannel::GetTableMembershipState(
688 : const string &table_name) {
689 : TableMembershipRequestMap::iterator loc =
690 185949 : table_membership_request_map_.find(table_name);
691 185943 : return (loc == table_membership_request_map_.end() ? NULL : &loc->second);
692 : }
693 :
694 : //
695 : // Find entry in the pending table request map.
696 : // Const version.
697 : //
698 : const BgpXmppChannel::TableMembershipRequestState *
699 9500 : BgpXmppChannel::GetTableMembershipState(
700 : const string &table_name) const {
701 : TableMembershipRequestMap::const_iterator loc =
702 9500 : table_membership_request_map_.find(table_name);
703 9500 : return (loc == table_membership_request_map_.end() ? NULL : &loc->second);
704 : }
705 :
706 : //
707 : // Add entry to the pending instance request map.
708 : //
709 143 : void BgpXmppChannel::AddInstanceMembershipState(const string &instance,
710 : InstanceMembershipRequestState imr_state) {
711 143 : instance_membership_request_map_.insert(make_pair(instance, imr_state));
712 143 : }
713 :
714 : //
715 : // Delete entry from the pending instance request map.
716 : // Return true if the entry was found and deleted.
717 : //
718 193 : bool BgpXmppChannel::DeleteInstanceMembershipState(const string &instance) {
719 193 : return (instance_membership_request_map_.erase(instance) > 0);
720 : }
721 :
722 : //
723 : // Find the entry in the pending instance request map.
724 : //
725 : const BgpXmppChannel::InstanceMembershipRequestState *
726 5620 : BgpXmppChannel::GetInstanceMembershipState(const string &instance) const {
727 : InstanceMembershipRequestMap::const_iterator loc =
728 5620 : instance_membership_request_map_.find(instance);
729 5620 : return loc != instance_membership_request_map_.end() ? &loc->second : NULL;
730 : }
731 :
732 : //
733 : // Verify that there's a subscribe or pending subscribe for the table
734 : // corresponding to the vrf and family.
735 : // If there's a subscribe, populate the table and instance_id.
736 : // If there's a pending subscribe, populate the instance_id.
737 : // The subscribe_pending parameter is set appropriately.
738 : //
739 : // Return true if there's a subscribe or pending subscribe, false otherwise.
740 : //
741 41639 : bool BgpXmppChannel::VerifyMembership(const string &vrf_name,
742 : Address::Family family, BgpTable **table,
743 : int *instance_id, uint64_t *subscription_gen_id, bool *subscribe_pending,
744 : bool add_change) {
745 41639 : *table = NULL;
746 41639 : *subscribe_pending = false;
747 :
748 41639 : RoutingInstanceMgr *instance_mgr = bgp_server_->routing_instance_mgr();
749 41639 : RoutingInstance *rt_instance = instance_mgr->GetRoutingInstance(vrf_name);
750 41637 : if (rt_instance)
751 41579 : *table = rt_instance->GetTable(family);
752 41634 : if (rt_instance != NULL && !rt_instance->deleted()) {
753 : RequestType req_type;
754 40076 : if (GetMembershipInfo(*table, instance_id,
755 : subscription_gen_id, &req_type)) {
756 : // Bail if there's a pending unsubscribe.
757 1270 : if (req_type != SUBSCRIBE) {
758 8 : BGP_LOG_PEER_INSTANCE_CRITICAL(Peer(), vrf_name,
759 : BGP_PEER_DIR_IN, BGP_LOG_FLAG_ALL,
760 : "Received route after unsubscribe");
761 21 : return false;
762 : }
763 1266 : *subscribe_pending = true;
764 : } else {
765 : // Bail if we are not subscribed to the table.
766 38811 : if (*instance_id < 0) {
767 29 : BGP_LOG_PEER_INSTANCE_CRITICAL(Peer(), vrf_name,
768 : BGP_PEER_DIR_IN, BGP_LOG_FLAG_ALL,
769 : "Received route without subscribe");
770 17 : return false;
771 : }
772 : }
773 : } else {
774 : // Bail if there's no pending subscribe for the instance.
775 : // Note that route retract can be received while the instance is
776 : // marked for deletion.
777 : const InstanceMembershipRequestState *imr_state =
778 1559 : GetInstanceMembershipState(vrf_name);
779 1559 : if (imr_state) {
780 56 : *instance_id = imr_state->instance_id;
781 56 : *subscribe_pending = true;
782 1503 : } else if (add_change || !rt_instance) {
783 18 : BGP_LOG_PEER_INSTANCE_CRITICAL(Peer(), vrf_name, BGP_PEER_DIR_IN,
784 : BGP_LOG_FLAG_ALL, "Received route without pending subscribe");
785 8 : return false;
786 : }
787 : }
788 :
789 41609 : return true;
790 : }
791 :
792 1174 : bool BgpXmppChannel::ProcessMcastItem(string vrf_name,
793 : const pugi::xml_node &node, bool add_change) {
794 1174 : McastItemType item;
795 1173 : item.Clear();
796 :
797 1173 : if (!item.XmlParse(node)) {
798 2 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
799 : BGP_LOG_FLAG_ALL, "Invalid multicast route message received");
800 1 : return false;
801 : }
802 :
803 1172 : if (item.entry.nlri.af != BgpAf::IPv4) {
804 2 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
805 : "Unsupported address family " << item.entry.nlri.af <<
806 : " for multicast route");
807 1 : return false;
808 : }
809 :
810 1171 : if (item.entry.nlri.safi != BgpAf::Mcast) {
811 2 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
812 : BGP_LOG_FLAG_ALL, "Unsupported subsequent address family " <<
813 : item.entry.nlri.safi << " for multicast route");
814 1 : return false;
815 : }
816 :
817 1170 : error_code error;
818 1170 : IpAddress grp_address = IpAddress::from_string("0.0.0.0", error);
819 1170 : if (!item.entry.nlri.group.empty()) {
820 1170 : if (!XmppDecodeAddress(item.entry.nlri.af,
821 : item.entry.nlri.group, &grp_address, false)) {
822 7 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
823 : "Bad group address " << item.entry.nlri.group);
824 4 : return false;
825 : }
826 : }
827 :
828 1167 : IpAddress src_address = IpAddress::from_string("0.0.0.0", error);
829 1167 : if (!item.entry.nlri.source.empty()) {
830 1167 : if (!XmppDecodeAddress(item.entry.nlri.af,
831 : item.entry.nlri.source, &src_address, true)) {
832 5 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
833 : "Bad source address " << item.entry.nlri.source);
834 3 : return false;
835 : }
836 : }
837 :
838 : bool subscribe_pending;
839 : int instance_id;
840 : uint64_t subscription_gen_id;
841 : BgpTable *table;
842 1164 : if (!VerifyMembership(vrf_name, Address::ERMVPN, &table, &instance_id,
843 : &subscription_gen_id, &subscribe_pending, add_change)) {
844 6 : channel_->Close();
845 6 : return false;
846 : }
847 :
848 : // Build the key to the Multicast DBTable
849 : uint16_t cluster_seed =
850 1158 : bgp_server_->global_config()->rd_cluster_seed();
851 1156 : RouteDistinguisher mc_rd;
852 1157 : if (cluster_seed) {
853 0 : mc_rd = RouteDistinguisher(cluster_seed, peer_->bgp_identifier(),
854 0 : instance_id);
855 : } else {
856 1157 : mc_rd = RouteDistinguisher(peer_->bgp_identifier(), instance_id);
857 : }
858 :
859 : ErmVpnPrefix mc_prefix(ErmVpnPrefix::NativeRoute, mc_rd,
860 1157 : grp_address.to_v4(), src_address.to_v4());
861 :
862 : // Build and enqueue a DB request for route-addition
863 1157 : DBRequest req;
864 1157 : req.key.reset(new ErmVpnTable::RequestKey(mc_prefix, peer_.get()));
865 :
866 1157 : uint32_t flags = 0;
867 1157 : ExtCommunitySpec ext;
868 1156 : string label_range("none");
869 :
870 1157 : if (add_change) {
871 728 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
872 728 : vector<uint32_t> labels;
873 729 : const McastNextHopsType &inh_list = item.entry.next_hops;
874 :
875 729 : if (inh_list.next_hop.empty()) {
876 2 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
877 : BGP_LOG_FLAG_ALL, "Missing next-hop for multicast route " <<
878 : mc_prefix.ToString());
879 1 : return false;
880 : }
881 :
882 : // Agents should send only one next-hop in the item
883 727 : if (inh_list.next_hop.size() != 1) {
884 2 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
885 : "More than one nexthop received for multicast route " <<
886 : mc_prefix.ToString());
887 1 : return false;
888 : }
889 :
890 726 : McastNextHopsType::const_iterator nit = inh_list.begin();
891 :
892 : // Label Allocation item.entry.label by parsing the range
893 726 : label_range = nit->label;
894 1452 : if (!stringToIntegerList(label_range, "-", labels) ||
895 726 : labels.size() != 2) {
896 4 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
897 : "Bad label range " << label_range <<
898 : " for multicast route " << mc_prefix.ToString());
899 3 : return false;
900 : }
901 :
902 723 : if (!labels[0] || !labels[1] || labels[1] < labels[0]) {
903 6 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
904 : BGP_LOG_FLAG_ALL, "Bad label range " << label_range <<
905 : " for multicast route " << mc_prefix.ToString());
906 3 : return false;
907 : }
908 :
909 721 : BgpAttrSpec attrs;
910 720 : LabelBlockPtr lbptr = lb_mgr_->LocateBlock(labels[0], labels[1]);
911 :
912 721 : BgpAttrLabelBlock attr_label(lbptr);
913 721 : attrs.push_back(&attr_label);
914 :
915 : // Next-hop ip address
916 720 : IpAddress nh_address;
917 720 : if (!XmppDecodeAddress(nit->af, nit->address, &nh_address)) {
918 5 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
919 : BGP_LOG_FLAG_ALL, "Bad nexthop address " << nit->address <<
920 : " for multicast route " << mc_prefix.ToString());
921 3 : return false;
922 : }
923 718 : BgpAttrNextHop nexthop(nh_address.to_v4().to_ulong());
924 718 : attrs.push_back(&nexthop);
925 :
926 : // Process tunnel encapsulation list.
927 718 : bool no_tunnel_encap = true;
928 718 : bool no_valid_tunnel_encap = true;
929 718 : for (McastTunnelEncapsulationListType::const_iterator eit =
930 718 : nit->tunnel_encapsulation_list.begin();
931 753 : eit != nit->tunnel_encapsulation_list.end(); ++eit) {
932 35 : no_tunnel_encap = false;
933 35 : TunnelEncap tun_encap(*eit);
934 35 : if (tun_encap.tunnel_encap() == TunnelEncapType::UNSPEC)
935 0 : continue;
936 35 : no_valid_tunnel_encap = false;
937 35 : ext.communities.push_back(tun_encap.GetExtCommunityValue());
938 : }
939 :
940 : // Mark the path as infeasible if all tunnel encaps published
941 : // by agent are invalid.
942 718 : if (!no_tunnel_encap && no_valid_tunnel_encap) {
943 0 : flags = BgpPath::NoTunnelEncap;
944 : }
945 :
946 718 : if (!ext.communities.empty())
947 23 : attrs.push_back(&ext);
948 :
949 718 : BgpAttrPtr attr = bgp_server_->attr_db()->Locate(attrs);
950 717 : req.data.reset(new ErmVpnTable::RequestData(
951 717 : attr, flags, 0, 0, subscription_gen_id));
952 717 : stats_[RX].reach++;
953 738 : } else {
954 429 : req.oper = DBRequest::DB_ENTRY_DELETE;
955 429 : stats_[RX].unreach++;
956 : }
957 :
958 : // Defer all requests till subscribe is processed.
959 1147 : if (subscribe_pending) {
960 46 : DBRequest *request_entry = new DBRequest();
961 46 : request_entry->Swap(&req);
962 : string table_name =
963 46 : RoutingInstance::GetTableName(vrf_name, Address::ERMVPN);
964 46 : defer_q_.insert(make_pair(
965 92 : make_pair(vrf_name, table_name), request_entry));
966 46 : return true;
967 46 : }
968 :
969 1101 : assert(table);
970 1320 : BGP_LOG_PEER_INSTANCE(Peer(), vrf_name,
971 : SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
972 : "Multicast group " << item.entry.nlri.group <<
973 : " source " << item.entry.nlri.source <<
974 : " and label range " << label_range <<
975 : " enqueued for " << (add_change ? "add/change" : "delete"));
976 1101 : table->Enqueue(&req);
977 1101 : return true;
978 1174 : }
979 :
980 88 : void BgpXmppChannel::CreateType5MvpnRouteRequest(IpAddress grp_address,
981 : IpAddress src_address, bool add_change, uint64_t subscription_gen_id,
982 : int instance_id, DBRequest& req, const MvpnNextHopType &nexthop) {
983 88 : RouteDistinguisher mc_rd = RouteDistinguisher::kZeroRd;
984 : MvpnPrefix mc_prefix(MvpnPrefix::SourceActiveADRoute, mc_rd,
985 88 : grp_address.to_v4(), src_address.to_v4());
986 88 : uint32_t flags = 0;
987 :
988 : // Build and enqueue a DB request for route-addition
989 88 : req.key.reset(new MvpnTable::RequestKey(mc_prefix, peer_.get()));
990 :
991 88 : if (add_change) {
992 76 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
993 :
994 76 : BgpAttrSpec attrs;
995 : // Next-hop ip address
996 76 : IpAddress nh_address;
997 76 : if (!XmppDecodeAddress(nexthop.af, nexthop.address, &nh_address)) {
998 0 : return;
999 : }
1000 :
1001 : BgpAttrSourceRd source_rd(
1002 76 : RouteDistinguisher(nh_address.to_v4().to_ulong(), instance_id));
1003 76 : attrs.push_back(&source_rd);
1004 76 : BgpAttrPtr attr = bgp_server_->attr_db()->Locate(attrs);
1005 76 : req.data.reset(new MvpnTable::RequestData(
1006 76 : attr, flags, 0, 0, subscription_gen_id));
1007 76 : stats_[RX].reach++;
1008 76 : } else {
1009 12 : req.oper = DBRequest::DB_ENTRY_DELETE;
1010 12 : stats_[RX].unreach++;
1011 : }
1012 88 : }
1013 :
1014 158 : void BgpXmppChannel::CreateType7MvpnRouteRequest(IpAddress grp_address,
1015 : IpAddress src_address, bool add_change, uint64_t subscription_gen_id,
1016 : DBRequest& req) {
1017 158 : RouteDistinguisher mc_rd = RouteDistinguisher::kZeroRd;
1018 : MvpnPrefix mc_prefix(MvpnPrefix::SourceTreeJoinRoute, mc_rd, 0,
1019 158 : grp_address.to_v4(), src_address.to_v4());
1020 158 : uint32_t flags = BgpPath::ResolveNexthop;
1021 :
1022 : // Build and enqueue a DB request for route-addition
1023 158 : req.key.reset(new MvpnTable::RequestKey(mc_prefix, peer_.get()));
1024 :
1025 158 : if (add_change) {
1026 126 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
1027 :
1028 126 : BgpAttrSpec attrs;
1029 :
1030 : // Next-hop ip address
1031 126 : BgpAttrNextHop nexthop(src_address);
1032 126 : attrs.push_back(&nexthop);
1033 :
1034 126 : BgpAttrPtr attr = bgp_server_->attr_db()->Locate(attrs);
1035 126 : req.data.reset(new MvpnTable::RequestData(
1036 126 : attr, flags, 0, 0, subscription_gen_id));
1037 126 : stats_[RX].reach++;
1038 126 : } else {
1039 32 : req.oper = DBRequest::DB_ENTRY_DELETE;
1040 32 : stats_[RX].unreach++;
1041 : }
1042 158 : }
1043 :
1044 248 : bool BgpXmppChannel::ProcessMvpnItem(string vrf_name,
1045 : const pugi::xml_node &node, bool add_change) {
1046 248 : MvpnItemType item;
1047 248 : item.Clear();
1048 :
1049 248 : if (!item.XmlParse(node)) {
1050 0 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1051 : BGP_LOG_FLAG_ALL, "Invalid multicast route message received");
1052 0 : return false;
1053 : }
1054 :
1055 248 : if (item.entry.nlri.af != BgpAf::IPv4) {
1056 0 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1057 : "Unsupported address family " << item.entry.nlri.af <<
1058 : " for multicast route");
1059 0 : return false;
1060 : }
1061 :
1062 248 : if (item.entry.nlri.safi != BgpAf::MVpn) {
1063 0 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1064 : BGP_LOG_FLAG_ALL, "Unsupported subsequent address family " <<
1065 : item.entry.nlri.safi << " for multicast route");
1066 0 : return false;
1067 : }
1068 :
1069 248 : if (item.entry.nlri.group.empty()) {
1070 0 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1071 : "Mandatory group address not specified");
1072 0 : return false;
1073 : }
1074 :
1075 248 : error_code error;
1076 248 : IpAddress grp_address = IpAddress::from_string("0.0.0.0", error);
1077 248 : if (!XmppDecodeAddress(item.entry.nlri.af,
1078 : item.entry.nlri.group, &grp_address, false)) {
1079 2 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1080 : "Bad group address " << item.entry.nlri.group);
1081 1 : return false;
1082 : }
1083 :
1084 247 : if (item.entry.nlri.source.empty()) {
1085 0 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1086 : "Mandatory source address not specified");
1087 0 : return false;
1088 : }
1089 :
1090 247 : IpAddress src_address = IpAddress::from_string("0.0.0.0", error);
1091 247 : if (!XmppDecodeAddress(item.entry.nlri.af,
1092 : item.entry.nlri.source, &src_address, true)) {
1093 2 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1094 : "Bad source address " << item.entry.nlri.source);
1095 1 : return false;
1096 : }
1097 :
1098 : bool subscribe_pending;
1099 : int instance_id;
1100 : uint64_t subscription_gen_id;
1101 : BgpTable *table;
1102 246 : if (!VerifyMembership(vrf_name, Address::MVPN, &table, &instance_id,
1103 : &subscription_gen_id, &subscribe_pending, add_change)) {
1104 0 : channel_->Close();
1105 0 : return false;
1106 : }
1107 :
1108 246 : int rt_type = item.entry.nlri.route_type;
1109 246 : DBRequest req;
1110 : // Build the key to the Multicast DBTable
1111 246 : if (rt_type == MvpnPrefix::SourceTreeJoinRoute) {
1112 158 : CreateType7MvpnRouteRequest(grp_address, src_address, add_change,
1113 : subscription_gen_id, req);
1114 88 : } else if (rt_type == MvpnPrefix::SourceActiveADRoute) {
1115 88 : CreateType5MvpnRouteRequest(grp_address, src_address, add_change,
1116 : subscription_gen_id, instance_id, req, item.entry.next_hop);
1117 : } else {
1118 0 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1119 : "Unsupported route type " << item.entry.nlri.route_type);
1120 0 : return false;
1121 : }
1122 :
1123 : // Need to locate path resolver if not done already
1124 246 : assert(table);
1125 246 : table->LocatePathResolver();
1126 :
1127 : // Defer all requests till subscribe is processed.
1128 246 : if (subscribe_pending) {
1129 6 : DBRequest *request_entry = new DBRequest();
1130 6 : request_entry->Swap(&req);
1131 : string table_name =
1132 6 : RoutingInstance::GetTableName(vrf_name, Address::MVPN);
1133 6 : defer_q_.insert(make_pair(
1134 12 : make_pair(vrf_name, table_name), request_entry));
1135 6 : return true;
1136 6 : }
1137 :
1138 480 : BGP_LOG_PEER_INSTANCE(Peer(), vrf_name,
1139 : SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
1140 : "Multicast group " << item.entry.nlri.group <<
1141 : " source " << item.entry.nlri.source <<
1142 : " enqueued for " << (add_change ? "add/change" : "delete"));
1143 240 : table->Enqueue(&req);
1144 240 : return true;
1145 248 : }
1146 :
1147 25612 : bool BgpXmppChannel::ProcessItem(string vrf_name,
1148 : const pugi::xml_node &node, bool add_change, int primary_instance_id) {
1149 25612 : ItemType item;
1150 25612 : item.Clear();
1151 :
1152 25612 : if (!item.XmlParse(node)) {
1153 2 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1154 : "Invalid inet route message received");
1155 1 : return false;
1156 : }
1157 :
1158 25611 : if (item.entry.nlri.af != BgpAf::IPv4) {
1159 2 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1160 : "Unsupported address family " << item.entry.nlri.af <<
1161 : " for inet route " << item.entry.nlri.address);
1162 1 : return false;
1163 : }
1164 :
1165 25610 : if ((item.entry.nlri.safi != BgpAf::Unicast) &&
1166 11 : (item.entry.nlri.safi != BgpAf::Mpls)) {
1167 0 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1168 : "Unsupported subsequent address family " << item.entry.nlri.safi <<
1169 : " for inet route " << item.entry.nlri.address);
1170 0 : return false;
1171 : }
1172 25610 : error_code error;
1173 : Ip4Prefix inet_prefix =
1174 25610 : Ip4Prefix::FromString(item.entry.nlri.address, &error);
1175 25610 : if (error) {
1176 4 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1177 : "Bad inet route " << item.entry.nlri.address);
1178 2 : return false;
1179 : }
1180 :
1181 25608 : if (add_change && item.entry.next_hops.next_hop.empty()) {
1182 2 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1183 : "Missing next-hops for inet route " << inet_prefix.ToString());
1184 1 : return false;
1185 : }
1186 :
1187 : // Rules for routes in master instance:
1188 : // - Label must be 0 unless it is INETMPLS
1189 : // - Tunnel encapsulation is not required
1190 : // - Do not add SourceRd and ExtCommunitySpec
1191 25607 : bool master = (vrf_name == BgpConfigManager::kMasterInstance);
1192 : bool subscribe_pending;
1193 : int instance_id;
1194 : uint64_t subscription_gen_id;
1195 : BgpTable *table;
1196 51214 : Address::Family family = BgpAf::AfiSafiToFamily(item.entry.nlri.af,
1197 25607 : item.entry.nlri.safi);
1198 25607 : if (!VerifyMembership(vrf_name, family, &table, &instance_id,
1199 : &subscription_gen_id, &subscribe_pending, add_change)) {
1200 6 : channel_->Close();
1201 6 : return false;
1202 : }
1203 :
1204 25601 : DBRequest req;
1205 25601 : req.key.reset(new InetTable::RequestKey(inet_prefix, peer_.get()));
1206 :
1207 25601 : IpAddress nh_address(Ip4Address(0));
1208 25601 : uint32_t label = 0;
1209 25601 : uint32_t flags = 0;
1210 25601 : ExtCommunitySpec ext;
1211 25601 : LargeCommunitySpec largecomm;
1212 25601 : CommunitySpec comm;
1213 :
1214 25601 : if (add_change) {
1215 15216 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
1216 15216 : BgpAttrSpec attrs;
1217 :
1218 15216 : const NextHopListType &inh_list = item.entry.next_hops;
1219 :
1220 : // Agents should send only one next-hop in the item.
1221 15216 : if (inh_list.next_hop.size() != 1) {
1222 0 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1223 : BGP_LOG_FLAG_ALL,
1224 : "More than one nexthop received for inet route " <<
1225 : inet_prefix.ToString());
1226 0 : return false;
1227 : }
1228 :
1229 15216 : NextHopListType::const_iterator nit = inh_list.begin();
1230 :
1231 15216 : IpAddress nhop_address(Ip4Address(0));
1232 15216 : if (!XmppDecodeAddress(nit->af, nit->address, &nhop_address)) {
1233 6 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1234 : BGP_LOG_FLAG_ALL,
1235 : "Bad nexthop address " << nit->address <<
1236 : " for inet route " << inet_prefix.ToString());
1237 3 : return false;
1238 : }
1239 :
1240 17898 : if (nit->label > EvpnPrefix::kMaxVniSigned ||
1241 2685 : ((master && nit->label) &&
1242 : !(family == Address::INETMPLS))) {
1243 4 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1244 : BGP_LOG_FLAG_ALL,
1245 : "Bad label " << nit->label <<
1246 : " for inet route " << inet_prefix.ToString());
1247 4 : return false;
1248 : }
1249 27743 : if ((!master || (master && (family == Address::INETMPLS))) &&
1250 12534 : !nit->label) {
1251 4 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1252 : BGP_LOG_FLAG_ALL,
1253 : "Bad label " << nit->label <<
1254 : " for inet route in master instance(mpls)/non master instance" <<
1255 : inet_prefix.ToString());
1256 2 : return false;
1257 : }
1258 :
1259 15207 : nh_address = nhop_address;
1260 15207 : label = nit->label;
1261 :
1262 : // Process tunnel encapsulation list.
1263 15207 : bool no_tunnel_encap = true;
1264 15207 : bool no_valid_tunnel_encap = true;
1265 15207 : for (TunnelEncapsulationListType::const_iterator eit =
1266 15207 : nit->tunnel_encapsulation_list.begin();
1267 28608 : eit != nit->tunnel_encapsulation_list.end(); ++eit) {
1268 13402 : no_tunnel_encap = false;
1269 13402 : TunnelEncap tun_encap(*eit);
1270 13402 : if (tun_encap.tunnel_encap() == TunnelEncapType::UNSPEC)
1271 0 : continue;
1272 13402 : no_valid_tunnel_encap = false;
1273 13402 : ext.communities.push_back(tun_encap.GetExtCommunityValue());
1274 : }
1275 :
1276 : // Mark the path as infeasible if all tunnel encaps published
1277 : // by agent are invalid.
1278 15206 : if (!no_tunnel_encap && no_valid_tunnel_encap && !master) {
1279 0 : flags = BgpPath::NoTunnelEncap;
1280 : }
1281 :
1282 : // Process router-mac as ext-community.
1283 15206 : if (!nit->mac.empty()) {
1284 : MacAddress mac_addr =
1285 0 : MacAddress::FromString(nit->mac, &error);
1286 0 : if (error) {
1287 0 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1288 : BGP_LOG_FLAG_ALL,
1289 : "Bad next-hop mac address " << nit->mac);
1290 0 : return false;
1291 : }
1292 0 : if (!mac_addr.IsZero()) {
1293 0 : RouterMac router_mac(mac_addr);
1294 0 : ext.communities.push_back(router_mac.GetExtCommunityValue());
1295 : }
1296 : }
1297 :
1298 : // Process tags list.
1299 15206 : uint64_t tag_val = 0;
1300 15206 : for (TagListType::const_iterator tit = nit->tag_list.begin();
1301 15216 : tit != nit->tag_list.end(); ++tit) {
1302 10 : tag_val = nit->is_new_tags_list ? *tit :
1303 0 : ((0xFFFF0000 & *tit) << 16) | (0x0000FFFF & *tit);
1304 10 : TagLC tag_lc(bgp_server_->autonomous_system(), tag_val);
1305 40 : for (const auto &value_data : tag_lc.GetLargeCommunityValue()) {
1306 30 : largecomm.communities.push_back(value_data);
1307 10 : }
1308 : }
1309 :
1310 : // Process local sequence_number
1311 15206 : if (nit->local_sequence_number) {
1312 0 : LocalSequenceNumber lsn (nit->local_sequence_number);
1313 0 : ext.communities.push_back(lsn.GetExtCommunityValue());
1314 : }
1315 :
1316 15206 : BgpAttrLocalPref local_pref(item.entry.local_preference);
1317 15206 : if (local_pref.local_pref != 0)
1318 12821 : attrs.push_back(&local_pref);
1319 :
1320 : // If there's no explicit med, calculate it automatically from the
1321 : // local pref.
1322 15206 : uint32_t med_value = item.entry.med;
1323 15206 : if (!med_value)
1324 7769 : med_value = GetMedFromLocalPref(local_pref.local_pref);
1325 15206 : BgpAttrMultiExitDisc med(med_value);
1326 15206 : if (med.med != 0)
1327 12822 : attrs.push_back(&med);
1328 :
1329 : // Process community tags.
1330 15207 : const CommunityTagListType &ict_list = item.entry.community_tag_list;
1331 15207 : for (CommunityTagListType::const_iterator cit = ict_list.begin();
1332 15219 : cit != ict_list.end(); ++cit) {
1333 12 : error_code error;
1334 : uint32_t rt_community =
1335 12 : CommunityType::CommunityFromString(*cit, &error);
1336 12 : if (error)
1337 0 : continue;
1338 12 : comm.communities.push_back(rt_community);
1339 : }
1340 :
1341 15207 : uint32_t addr = nh_address.to_v4().to_ulong();
1342 15207 : BgpAttrNextHop nexthop(addr);
1343 15207 : attrs.push_back(&nexthop);
1344 : uint16_t cluster_seed =
1345 15207 : bgp_server_->global_config()->rd_cluster_seed();
1346 15207 : BgpAttrSourceRd source_rd;
1347 15207 : if (!master || primary_instance_id) {
1348 12538 : if (master)
1349 10 : instance_id = primary_instance_id;
1350 12538 : if (cluster_seed) {
1351 6 : source_rd = BgpAttrSourceRd(
1352 9 : RouteDistinguisher(cluster_seed, addr, instance_id));
1353 : } else {
1354 25070 : source_rd = BgpAttrSourceRd(
1355 37605 : RouteDistinguisher(addr, instance_id));
1356 : }
1357 12538 : attrs.push_back(&source_rd);
1358 : }
1359 :
1360 : // Process security group list.
1361 15207 : uint16_t sg_index = 0;
1362 15207 : const SecurityGroupListType &isg_list = item.entry.security_group_list;
1363 15207 : for (SecurityGroupListType::const_iterator sit = isg_list.begin();
1364 30932 : sit != isg_list.end(); ++sit) {
1365 15725 : if (bgp_server_->autonomous_system() <= AS2_MAX) {
1366 15725 : SecurityGroup sg(bgp_server_->autonomous_system(), *sit);
1367 15725 : ext.communities.push_back(sg.GetExtCommunityValue());
1368 : } else {
1369 0 : SecurityGroup sg(sg_index, *sit);
1370 0 : SecurityGroup4ByteAs sg4(bgp_server_->autonomous_system(),
1371 0 : sg_index++);
1372 0 : ext.communities.push_back(sg4.GetExtCommunityValue());
1373 0 : ext.communities.push_back(sg.GetExtCommunityValue());
1374 : }
1375 : }
1376 :
1377 15207 : if (item.entry.mobility.seqno) {
1378 512 : MacMobility mm(item.entry.mobility.seqno,
1379 512 : item.entry.mobility.sticky);
1380 512 : ext.communities.push_back(mm.GetExtCommunityValue());
1381 14695 : } else if (item.entry.sequence_number) {
1382 0 : MacMobility mm(item.entry.sequence_number);
1383 0 : ext.communities.push_back(mm.GetExtCommunityValue());
1384 : }
1385 :
1386 : // Process load-balance extended community.
1387 15207 : LoadBalance load_balance(item.entry.load_balance);
1388 15206 : if (!load_balance.IsDefault())
1389 2 : ext.communities.push_back(load_balance.GetExtCommunityValue());
1390 :
1391 15207 : if (!comm.communities.empty())
1392 7 : attrs.push_back(&comm);
1393 15207 : if (!master && !ext.communities.empty())
1394 12528 : attrs.push_back(&ext);
1395 15206 : if (!master && !largecomm.communities.empty())
1396 3 : attrs.push_back(&largecomm);
1397 :
1398 : // Process sub-protocol(route types)
1399 15206 : BgpAttrSubProtocol sbp(item.entry.sub_protocol);
1400 15206 : attrs.push_back(&sbp);
1401 :
1402 15206 : BgpAttrPtr attr = bgp_server_->attr_db()->Locate(attrs);
1403 15207 : req.data.reset(new BgpTable::RequestData(
1404 15207 : attr, flags, label, 0, subscription_gen_id));
1405 15216 : } else {
1406 10385 : req.oper = DBRequest::DB_ENTRY_DELETE;
1407 : }
1408 :
1409 : // Defer all requests till subscribe is processed.
1410 25592 : if (subscribe_pending) {
1411 453 : DBRequest *request_entry = new DBRequest();
1412 453 : request_entry->Swap(&req);
1413 : string table_name =
1414 453 : RoutingInstance::GetTableName(vrf_name, family);
1415 453 : defer_q_.insert(make_pair(
1416 906 : make_pair(vrf_name, table_name), request_entry));
1417 453 : return true;
1418 453 : }
1419 :
1420 25139 : assert(table);
1421 33946 : BGP_LOG_PEER_INSTANCE(Peer(), vrf_name,
1422 : SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
1423 : "Inet route " << item.entry.nlri.address <<
1424 : " with next-hop " << nh_address << " and label " << label <<
1425 : " enqueued for " << (add_change ? "add/change" : "delete") <<
1426 : " to table " << table->name());
1427 25139 : table->Enqueue(&req);
1428 :
1429 25139 : if (add_change) {
1430 14772 : stats_[RX].reach++;
1431 : } else {
1432 10367 : stats_[RX].unreach++;
1433 : }
1434 :
1435 25139 : return true;
1436 25612 : }
1437 :
1438 9099 : bool BgpXmppChannel::ProcessInet6Item(string vrf_name,
1439 : const pugi::xml_node &node, bool add_change) {
1440 9099 : ItemType item;
1441 9099 : item.Clear();
1442 :
1443 9099 : if (!item.XmlParse(node)) {
1444 2 : error_stats().incr_inet6_rx_bad_xml_token_count();
1445 3 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1446 : "Invalid inet6 route message received");
1447 2 : return false;
1448 : }
1449 :
1450 9097 : if (item.entry.nlri.af != BgpAf::IPv6) {
1451 2 : error_stats().incr_inet6_rx_bad_afi_safi_count();
1452 3 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1453 : "Unsupported address family " << item.entry.nlri.af <<
1454 : " for inet6 route " << item.entry.nlri.address);
1455 2 : return false;
1456 : }
1457 :
1458 9095 : if (item.entry.nlri.safi != BgpAf::Unicast) {
1459 1 : error_stats().incr_inet6_rx_bad_afi_safi_count();
1460 1 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1461 : "Unsupported subsequent address family " << item.entry.nlri.safi <<
1462 : " for inet6 route " << item.entry.nlri.address);
1463 1 : return false;
1464 : }
1465 :
1466 9094 : error_code error;
1467 : Inet6Prefix inet6_prefix =
1468 9094 : Inet6Prefix::FromString(item.entry.nlri.address, &error);
1469 9094 : if (error) {
1470 2 : error_stats().incr_inet6_rx_bad_prefix_count();
1471 3 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1472 : "Bad inet6 route " << item.entry.nlri.address);
1473 2 : return false;
1474 : }
1475 :
1476 9092 : if (add_change && item.entry.next_hops.next_hop.empty()) {
1477 2 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1478 : "Missing next-hops for inet6 route " << inet6_prefix.ToString());
1479 1 : return false;
1480 : }
1481 :
1482 : // Rules for routes in master instance:
1483 : // - Label must be 0
1484 : // - Tunnel encapsulation is not required
1485 : // - Do not add SourceRd and ExtCommunitySpec
1486 9091 : bool master = (vrf_name == BgpConfigManager::kMasterInstance);
1487 :
1488 : // vector<Address::Family> family_list = list_of(Address::INET6)(Address::EVPN);
1489 9091 : vector<Address::Family> family_list = list_of(Address::INET6);
1490 27255 : BOOST_FOREACH(Address::Family family, family_list) {
1491 : bool subscribe_pending;
1492 : int instance_id;
1493 : uint64_t subscription_gen_id;
1494 : BgpTable *table;
1495 9091 : if (!VerifyMembership(vrf_name, family, &table, &instance_id,
1496 : &subscription_gen_id, &subscribe_pending, add_change)) {
1497 6 : channel_->Close();
1498 9 : return false;
1499 : }
1500 :
1501 9085 : DBRequest req;
1502 9085 : if (family == Address::INET6) {
1503 9085 : req.key.reset(new Inet6Table::RequestKey(inet6_prefix, peer_.get()));
1504 : } else {
1505 : EvpnPrefix evpn_prefix(RouteDistinguisher::kZeroRd,
1506 0 : inet6_prefix.addr(), inet6_prefix.prefixlen());
1507 0 : req.key.reset(new EvpnTable::RequestKey(evpn_prefix, peer_.get()));
1508 : }
1509 :
1510 9085 : IpAddress nh_address(Ip4Address(0));
1511 9085 : uint32_t label = 0;
1512 9085 : uint32_t flags = 0;
1513 9085 : ExtCommunitySpec ext;
1514 9085 : LargeCommunitySpec largecomm;
1515 9085 : CommunitySpec comm;
1516 :
1517 9085 : if (add_change) {
1518 6772 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
1519 6772 : BgpAttrSpec attrs;
1520 :
1521 6771 : const NextHopListType &inh_list = item.entry.next_hops;
1522 :
1523 : // Agents should send only one next-hop in the item.
1524 6771 : if (inh_list.next_hop.size() != 1) {
1525 0 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1526 : BGP_LOG_FLAG_ALL,
1527 : "More than one nexthop received for inet6 route " <<
1528 : inet6_prefix.ToString());
1529 0 : return false;
1530 : }
1531 :
1532 6771 : NextHopListType::const_iterator nit = inh_list.begin();
1533 :
1534 6771 : IpAddress nhop_address(Ip4Address(0));
1535 6771 : if (!XmppDecodeAddress(nit->af, nit->address, &nhop_address)) {
1536 3 : error_stats().incr_inet6_rx_bad_nexthop_count();
1537 5 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1538 : BGP_LOG_FLAG_ALL,
1539 : "Bad nexthop address " << nit->address <<
1540 : " for inet6 route " << inet6_prefix.ToString());
1541 3 : return false;
1542 : }
1543 :
1544 6769 : if (family == Address::EVPN) {
1545 0 : if (nit->vni > EvpnPrefix::kMaxVniSigned) {
1546 0 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1547 : BGP_LOG_FLAG_ALL,
1548 : "Bad label " << nit->vni <<
1549 : " for inet6 route " << inet6_prefix.ToString());
1550 0 : return false;
1551 : }
1552 0 : if (!nit->vni)
1553 0 : continue;
1554 0 : if (nit->mac.empty())
1555 0 : continue;
1556 :
1557 : MacAddress mac_addr =
1558 0 : MacAddress::FromString(nit->mac, &error);
1559 0 : if (error) {
1560 0 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1561 : BGP_LOG_FLAG_ALL,
1562 : "Bad next-hop mac address " << nit->mac);
1563 0 : return false;
1564 : }
1565 0 : RouterMac router_mac(mac_addr);
1566 0 : ext.communities.push_back(router_mac.GetExtCommunityValue());
1567 : } else {
1568 6769 : if (nit->label > EvpnPrefix::kMaxVniSigned || (master && nit->label)) {
1569 0 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1570 : BGP_LOG_FLAG_ALL,
1571 : "Bad label " << nit->label <<
1572 : " for inet6 route " << inet6_prefix.ToString());
1573 0 : return false;
1574 : }
1575 6769 : if (!master && !nit->label)
1576 0 : continue;
1577 : }
1578 :
1579 6769 : nh_address = nhop_address;
1580 6769 : if (family == Address::INET6) {
1581 6769 : label = nit->label;
1582 : } else {
1583 0 : label = nit->vni;
1584 : }
1585 :
1586 : // Process tunnel encapsulation list.
1587 6769 : bool no_tunnel_encap = true;
1588 6769 : bool no_valid_tunnel_encap = true;
1589 6769 : for (TunnelEncapsulationListType::const_iterator eit =
1590 6769 : nit->tunnel_encapsulation_list.begin();
1591 16601 : eit != nit->tunnel_encapsulation_list.end(); ++eit) {
1592 9833 : no_tunnel_encap = false;
1593 9833 : TunnelEncap tun_encap(*eit);
1594 9832 : if (tun_encap.tunnel_encap() == TunnelEncapType::UNSPEC)
1595 0 : continue;
1596 9831 : no_valid_tunnel_encap = false;
1597 9831 : ext.communities.push_back(tun_encap.GetExtCommunityValue());
1598 : }
1599 :
1600 : // Mark the path as infeasible if all tunnel encaps published
1601 : // by agent are invalid.
1602 6768 : if (!no_tunnel_encap && no_valid_tunnel_encap && !master) {
1603 0 : flags = BgpPath::NoTunnelEncap;
1604 : }
1605 :
1606 : // Process router-mac as ext-community.
1607 6768 : if (!nit->mac.empty()) {
1608 : MacAddress mac_addr =
1609 0 : MacAddress::FromString(nit->mac, &error);
1610 0 : if (error) {
1611 0 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1612 : BGP_LOG_FLAG_ALL,
1613 : "Bad next-hop mac address " << nit->mac);
1614 0 : return false;
1615 : }
1616 0 : if (!mac_addr.IsZero()) {
1617 0 : RouterMac router_mac(mac_addr);
1618 0 : ext.communities.push_back(router_mac.GetExtCommunityValue());
1619 : }
1620 : }
1621 :
1622 : // Process tags list.
1623 6768 : uint64_t tag_val = 0;
1624 6768 : for (TagListType::const_iterator tit = nit->tag_list.begin();
1625 6770 : tit != nit->tag_list.end(); ++tit) {
1626 2 : tag_val = nit->is_new_tags_list ? *tit :
1627 2 : ((0xFFFF0000 & *tit) << 16) | (0x0000FFFF & *tit);
1628 2 : TagLC tag_lc(bgp_server_->autonomous_system(), tag_val);
1629 2 : for (const auto &value_data :
1630 10 : tag_lc.GetLargeCommunityValue()) {
1631 6 : largecomm.communities.push_back(value_data);
1632 2 : }
1633 : }
1634 :
1635 : // Process local sequence_number
1636 6768 : if (nit->local_sequence_number) {
1637 0 : LocalSequenceNumber lsn (nit->local_sequence_number);
1638 0 : ext.communities.push_back(lsn.GetExtCommunityValue());
1639 : }
1640 :
1641 6768 : BgpAttrLocalPref local_pref(item.entry.local_preference);
1642 6768 : if (local_pref.local_pref != 0)
1643 6768 : attrs.push_back(&local_pref);
1644 :
1645 : // If there's no explicit med, calculate it automatically from the
1646 : // local pref.
1647 6768 : uint32_t med_value = item.entry.med;
1648 6768 : if (!med_value)
1649 230 : med_value = GetMedFromLocalPref(local_pref.local_pref);
1650 6768 : BgpAttrMultiExitDisc med(med_value);
1651 6768 : if (med.med != 0)
1652 6768 : attrs.push_back(&med);
1653 :
1654 : // Process community tags.
1655 6769 : const CommunityTagListType &ict_list =
1656 : item.entry.community_tag_list;
1657 6769 : for (CommunityTagListType::const_iterator cit = ict_list.begin();
1658 6777 : cit != ict_list.end(); ++cit) {
1659 8 : error_code error;
1660 : uint32_t rt_community =
1661 8 : CommunityType::CommunityFromString(*cit, &error);
1662 8 : if (error)
1663 0 : continue;
1664 8 : comm.communities.push_back(rt_community);
1665 : }
1666 :
1667 6769 : BgpAttrNextHop nexthop(nh_address);
1668 6769 : attrs.push_back(&nexthop);
1669 :
1670 6768 : BgpAttrSourceRd source_rd;
1671 6768 : if (!master) {
1672 4103 : uint32_t addr = nh_address.to_v4().to_ulong();
1673 : uint16_t cluster_seed =
1674 4103 : bgp_server_->global_config()->rd_cluster_seed();
1675 4104 : if (cluster_seed) {
1676 6 : source_rd = BgpAttrSourceRd(
1677 9 : RouteDistinguisher(cluster_seed, addr, instance_id));
1678 : } else {
1679 8201 : source_rd = BgpAttrSourceRd(
1680 12302 : RouteDistinguisher(addr, instance_id));
1681 : }
1682 4103 : attrs.push_back(&source_rd);
1683 : }
1684 :
1685 : // Process security group list.
1686 6768 : const SecurityGroupListType &isg_list =
1687 : item.entry.security_group_list;
1688 6768 : uint16_t sg_index = 0;
1689 6768 : for (SecurityGroupListType::const_iterator sit = isg_list.begin();
1690 13547 : sit != isg_list.end(); ++sit) {
1691 6778 : if (bgp_server_->autonomous_system() <= AS2_MAX) {
1692 6778 : SecurityGroup sg(bgp_server_->autonomous_system(), *sit);
1693 6779 : ext.communities.push_back(sg.GetExtCommunityValue());
1694 : } else {
1695 0 : SecurityGroup sg(sg_index, *sit);
1696 0 : SecurityGroup4ByteAs sg4(bgp_server_->autonomous_system(),
1697 0 : sg_index++);
1698 0 : ext.communities.push_back(sg4.GetExtCommunityValue());
1699 0 : ext.communities.push_back(sg.GetExtCommunityValue());
1700 : }
1701 : }
1702 :
1703 6769 : if (item.entry.mobility.seqno) {
1704 18 : MacMobility mm(item.entry.mobility.seqno,
1705 18 : item.entry.mobility.sticky);
1706 18 : ext.communities.push_back(mm.GetExtCommunityValue());
1707 6751 : } else if (item.entry.sequence_number) {
1708 0 : MacMobility mm(item.entry.sequence_number);
1709 0 : ext.communities.push_back(mm.GetExtCommunityValue());
1710 : }
1711 :
1712 : // Process load-balance extended community.
1713 6769 : LoadBalance load_balance(item.entry.load_balance);
1714 6768 : if (!load_balance.IsDefault())
1715 0 : ext.communities.push_back(load_balance.GetExtCommunityValue());
1716 :
1717 : // Process sub-protocol(route types)
1718 6769 : BgpAttrSubProtocol sbp(item.entry.sub_protocol);
1719 6769 : attrs.push_back(&sbp);
1720 :
1721 6768 : if (!comm.communities.empty())
1722 5 : attrs.push_back(&comm);
1723 6768 : if (!master && !ext.communities.empty())
1724 4104 : attrs.push_back(&ext);
1725 6768 : if (!master && !largecomm.communities.empty())
1726 1 : attrs.push_back(&largecomm);
1727 :
1728 6768 : BgpAttrPtr attr = bgp_server_->attr_db()->Locate(attrs);
1729 6769 : req.data.reset(new BgpTable::RequestData(
1730 6769 : attr, flags, label, 0, subscription_gen_id));
1731 6772 : } else {
1732 2313 : req.oper = DBRequest::DB_ENTRY_DELETE;
1733 : }
1734 :
1735 : // Defer all requests till subscribe is processed.
1736 9082 : if (subscribe_pending) {
1737 378 : DBRequest *request_entry = new DBRequest();
1738 378 : request_entry->Swap(&req);
1739 : string table_name =
1740 378 : RoutingInstance::GetTableName(vrf_name, family);
1741 378 : defer_q_.insert(make_pair(
1742 756 : make_pair(vrf_name, table_name), request_entry));
1743 378 : continue;
1744 378 : }
1745 :
1746 8704 : assert(table);
1747 16600 : BGP_LOG_PEER_INSTANCE(Peer(), vrf_name,
1748 : SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
1749 : "Inet6 route " << item.entry.nlri.address <<
1750 : " with next-hop " << nh_address << " and label " << label <<
1751 : " enqueued for " << (add_change ? "add/change" : "delete") <<
1752 : " to table " << table->name());
1753 8704 : table->Enqueue(&req);
1754 10228 : }
1755 :
1756 9082 : if (add_change) {
1757 6769 : stats_[RX].reach++;
1758 : } else {
1759 2313 : stats_[RX].unreach++;
1760 : }
1761 :
1762 9082 : return true;
1763 9099 : }
1764 :
1765 5539 : bool BgpXmppChannel::ProcessEnetItem(string vrf_name,
1766 : const pugi::xml_node &node, bool add_change) {
1767 5539 : EnetItemType item;
1768 5539 : item.Clear();
1769 :
1770 5538 : if (!item.XmlParse(node)) {
1771 2 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1772 : "Invalid enet route message received");
1773 1 : return false;
1774 : }
1775 :
1776 5538 : if (item.entry.nlri.af != BgpAf::L2Vpn) {
1777 2 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1778 : "Unsupported address family " << item.entry.nlri.af <<
1779 : " for enet route " << item.entry.nlri.address);
1780 1 : return false;
1781 : }
1782 :
1783 5537 : if (item.entry.nlri.safi != BgpAf::Enet) {
1784 2 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1785 : "Unsupported subsequent address family " << item.entry.nlri.safi <<
1786 : " for enet route " << item.entry.nlri.mac);
1787 1 : return false;
1788 : }
1789 :
1790 5536 : bool type6 = false;
1791 5536 : error_code error;
1792 5536 : IpAddress group= IpAddress::from_string("0.0.0.0", error);
1793 5535 : if (!item.entry.nlri.group.empty()) {
1794 36 : type6 = true;
1795 36 : if (!XmppDecodeAddress(item.entry.nlri.af,
1796 : item.entry.nlri.group, &group, false)) {
1797 0 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1798 : "Bad group address " << item.entry.nlri.group);
1799 : }
1800 : }
1801 :
1802 5535 : IpAddress source = IpAddress::from_string("0.0.0.0", error);
1803 5535 : if (!item.entry.nlri.source.empty() && !XmppDecodeAddress(
1804 : item.entry.nlri.af, item.entry.nlri.source, &source, true)) {
1805 0 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1806 : "Bad source address " << item.entry.nlri.source);
1807 : }
1808 :
1809 : //error_code error;
1810 5535 : MacAddress mac_addr = MacAddress::FromString(item.entry.nlri.mac, &error);
1811 :
1812 5536 : if (error) {
1813 2 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1814 : "Bad mac address " << item.entry.nlri.mac);
1815 1 : return false;
1816 : }
1817 :
1818 5536 : bool type2 = type6 ? false : !mac_addr.IsZero();
1819 5535 : Ip4Prefix inet_prefix;
1820 5535 : Inet6Prefix inet6_prefix;
1821 5535 : IpAddress ip_addr;
1822 5535 : int prefix_len = 0;
1823 5535 : if (!item.entry.nlri.address.empty()) {
1824 1359 : size_t pos = item.entry.nlri.address.find('/');
1825 1359 : if (pos == string::npos) {
1826 2 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
1827 : "Missing / in address " << item.entry.nlri.address);
1828 1 : return false;
1829 : }
1830 :
1831 1358 : bool ipv6 = item.entry.nlri.address.find(':') != string::npos;
1832 1358 : if (!ipv6) {
1833 : inet_prefix =
1834 1315 : Ip4Prefix::FromString(item.entry.nlri.address, &error);
1835 1316 : if (error) {
1836 2 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1837 : BGP_LOG_FLAG_ALL,
1838 : "Cannot parse inet prefix string " <<
1839 : item.entry.nlri.address);
1840 1 : return false;
1841 : }
1842 :
1843 1320 : if (type2 && inet_prefix.prefixlen() != 32 &&
1844 5 : item.entry.nlri.address != "0.0.0.0/0") {
1845 2 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1846 : BGP_LOG_FLAG_ALL,
1847 : "Bad inet address " << item.entry.nlri.address);
1848 1 : return false;
1849 : }
1850 :
1851 1314 : ip_addr = inet_prefix.ip4_addr();
1852 1313 : prefix_len = inet_prefix.prefixlen();
1853 : } else {
1854 : inet6_prefix =
1855 43 : Inet6Prefix::FromString(item.entry.nlri.address, &error);
1856 :
1857 43 : if (error) {
1858 2 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1859 : BGP_LOG_FLAG_ALL,
1860 : "Cannot parse inet6 prefix string " <<
1861 : item.entry.nlri.address);
1862 1 : return false;
1863 : }
1864 :
1865 42 : if (type2 && inet6_prefix.prefixlen() != 128 &&
1866 0 : item.entry.nlri.address != "::/0") {
1867 0 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1868 : BGP_LOG_FLAG_ALL,
1869 : "Bad inet6 address " << item.entry.nlri.address);
1870 0 : return false;
1871 : }
1872 42 : ip_addr = inet6_prefix.ip6_addr();
1873 42 : prefix_len = inet6_prefix.prefixlen();
1874 : }
1875 : }
1876 :
1877 : bool subscribe_pending;
1878 : int instance_id;
1879 : uint64_t subscription_gen_id;
1880 : BgpTable *table;
1881 5532 : if (!VerifyMembership(vrf_name, Address::EVPN, &table, &instance_id,
1882 : &subscription_gen_id, &subscribe_pending, add_change)) {
1883 11 : channel_->Close();
1884 11 : return false;
1885 : }
1886 :
1887 5520 : RouteDistinguisher rd;
1888 5520 : if (mac_addr.IsBroadcast()) {
1889 709 : rd = RouteDistinguisher(peer_->bgp_identifier(), instance_id);
1890 4811 : } else if (type6) {
1891 72 : rd = RouteDistinguisher(bgp_server_->bgp_identifier(),
1892 72 : table->routing_instance()->index());
1893 : } else {
1894 4775 : rd = RouteDistinguisher::kZeroRd;
1895 : }
1896 :
1897 5518 : uint32_t ethernet_tag = item.entry.nlri.ethernet_tag;
1898 : EvpnPrefix evpn_prefix = type6 ?
1899 : EvpnPrefix(rd, ethernet_tag, source, group,
1900 36 : Ip4Address(bgp_server_->bgp_identifier())) :
1901 : type2 ? EvpnPrefix(rd, ethernet_tag, mac_addr, ip_addr) :
1902 5554 : EvpnPrefix(rd, ip_addr, prefix_len);
1903 :
1904 5517 : DBRequest req;
1905 5519 : ExtCommunitySpec ext;
1906 5518 : LargeCommunitySpec largecomm;
1907 5519 : req.key.reset(new EvpnTable::RequestKey(evpn_prefix, peer_.get()));
1908 :
1909 5517 : IpAddress nh_address(Ip4Address(0));
1910 5516 : uint32_t label = 0;
1911 5516 : uint32_t l3_label = 0;
1912 5516 : uint32_t flags = 0;
1913 :
1914 5516 : if (add_change) {
1915 4369 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
1916 4369 : BgpAttrSpec attrs;
1917 4370 : const EnetNextHopListType &inh_list = item.entry.next_hops;
1918 :
1919 4370 : if (inh_list.next_hop.empty()) {
1920 2 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1921 : BGP_LOG_FLAG_ALL, "Missing next-hops for enet route " <<
1922 : evpn_prefix.ToXmppIdString());
1923 1 : return false;
1924 : }
1925 :
1926 : // Agents should send only one next-hop in the item.
1927 4368 : if (inh_list.next_hop.size() != 1) {
1928 0 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1929 : BGP_LOG_FLAG_ALL,
1930 : "More than one nexthop received for enet route " <<
1931 : evpn_prefix.ToXmppIdString());
1932 0 : return false;
1933 : }
1934 :
1935 4368 : EnetNextHopListType::const_iterator nit = inh_list.begin();
1936 :
1937 4368 : IpAddress nhop_address(Ip4Address(0));
1938 :
1939 4368 : if (!XmppDecodeAddress(nit->af, nit->address, &nhop_address)) {
1940 4 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1941 : BGP_LOG_FLAG_ALL, "Bad nexthop address " << nit->address <<
1942 : " for enet route " << evpn_prefix.ToXmppIdString());
1943 2 : return false;
1944 : }
1945 :
1946 4368 : nh_address = nhop_address;
1947 4368 : label = nit->label;
1948 4368 : l3_label = nit->l3_label;
1949 4368 : if (!nit->mac.empty()) {
1950 : MacAddress rmac_addr =
1951 10 : MacAddress::FromString(nit->mac, &error);
1952 10 : if (error) {
1953 0 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1954 : BGP_LOG_FLAG_ALL,
1955 : "Bad next-hop mac address " << nit->mac <<
1956 : " for enet route " << evpn_prefix.ToXmppIdString());
1957 0 : return false;
1958 : }
1959 10 : RouterMac router_mac(rmac_addr);
1960 10 : ext.communities.push_back(router_mac.GetExtCommunityValue());
1961 : }
1962 :
1963 : // Process tunnel encapsulation list.
1964 4368 : bool no_tunnel_encap = true;
1965 4368 : bool no_valid_tunnel_encap = true;
1966 4368 : for (EnetTunnelEncapsulationListType::const_iterator eit =
1967 4368 : nit->tunnel_encapsulation_list.begin();
1968 8736 : eit != nit->tunnel_encapsulation_list.end(); ++eit) {
1969 4368 : no_tunnel_encap = false;
1970 4368 : TunnelEncap tun_encap(*eit);
1971 4368 : if (tun_encap.tunnel_encap() == TunnelEncapType::UNSPEC)
1972 0 : continue;
1973 4367 : no_valid_tunnel_encap = false;
1974 4367 : ext.communities.push_back(tun_encap.GetExtCommunityValue());
1975 4367 : if (tun_encap.tunnel_encap() == TunnelEncapType::GRE) {
1976 4322 : TunnelEncap alt_tun_encap(TunnelEncapType::MPLS_O_GRE);
1977 4322 : ext.communities.push_back(alt_tun_encap.GetExtCommunityValue());
1978 : }
1979 : }
1980 :
1981 : // Mark the path as infeasible if all tunnel encaps published
1982 : // by agent are invalid.
1983 4368 : if (!no_tunnel_encap && no_valid_tunnel_encap) {
1984 0 : flags = BgpPath::NoTunnelEncap;
1985 : }
1986 :
1987 : // Process tags list.
1988 4368 : uint64_t tag_val = 0;
1989 4368 : for (TagListType::const_iterator tit = nit->tag_list.begin();
1990 4372 : tit != nit->tag_list.end(); ++tit) {
1991 4 : tag_val = nit->is_new_tags_list ? *tit :
1992 4 : ((0x0000FFFF0000 & *tit) << 16) |
1993 4 : (0x00000000FFFF & *tit);
1994 4 : TagLC tag_lc(bgp_server_->autonomous_system(), tag_val);
1995 16 : for (const auto &value_data : tag_lc.GetLargeCommunityValue()) {
1996 12 : largecomm.communities.push_back(value_data);
1997 4 : }
1998 : }
1999 :
2000 : // Process local sequence_number
2001 4368 : if (nit->local_sequence_number) {
2002 0 : LocalSequenceNumber lsn (nit->local_sequence_number);
2003 0 : ext.communities.push_back(lsn.GetExtCommunityValue());
2004 : }
2005 :
2006 4368 : BgpAttrLocalPref local_pref(item.entry.local_preference);
2007 4368 : if (local_pref.local_pref != 0) {
2008 4368 : attrs.push_back(&local_pref);
2009 : }
2010 :
2011 : // If there's no explicit med, calculate it automatically from the
2012 : // local pref.
2013 4367 : uint32_t med_value = item.entry.med;
2014 4367 : if (!med_value)
2015 4367 : med_value = GetMedFromLocalPref(local_pref.local_pref);
2016 4367 : BgpAttrMultiExitDisc med(med_value);
2017 4367 : if (med.med != 0)
2018 4367 : attrs.push_back(&med);
2019 :
2020 4368 : BgpAttrNextHop nexthop(nh_address.to_v4().to_ulong());
2021 4368 : if (type6) {
2022 36 : flags |= BgpPath::CheckGlobalErmVpnRoute;
2023 72 : if (item.entry.replicator_address.empty() &&
2024 36 : item.entry.edge_replication_not_supported) {
2025 : // Only for test to inject remote smet routes
2026 0 : flags &= ~BgpPath::CheckGlobalErmVpnRoute;
2027 0 : attrs.push_back(&nexthop);
2028 : }
2029 : } else {
2030 4332 : attrs.push_back(&nexthop);
2031 : }
2032 :
2033 4368 : uint16_t cluster_seed = bgp_server_->global_config()->rd_cluster_seed();
2034 4368 : BgpAttrSourceRd source_rd;
2035 4368 : if (cluster_seed) {
2036 0 : source_rd = BgpAttrSourceRd(RouteDistinguisher(cluster_seed,
2037 0 : nh_address.to_v4().to_ulong(), instance_id));
2038 : } else {
2039 8735 : source_rd = BgpAttrSourceRd(RouteDistinguisher(
2040 13102 : nh_address.to_v4().to_ulong(), instance_id));
2041 : }
2042 4367 : attrs.push_back(&source_rd);
2043 :
2044 : // Process security group list.
2045 4367 : const EnetSecurityGroupListType &isg_list =
2046 : item.entry.security_group_list;
2047 4367 : uint16_t sg_index = 0;
2048 4367 : for (EnetSecurityGroupListType::const_iterator sit = isg_list.begin();
2049 8739 : sit != isg_list.end(); ++sit) {
2050 4371 : if (bgp_server_->autonomous_system() <= AS2_MAX) {
2051 4371 : SecurityGroup sg(bgp_server_->autonomous_system(), *sit);
2052 4372 : ext.communities.push_back(sg.GetExtCommunityValue());
2053 : } else {
2054 0 : SecurityGroup sg(sg_index, *sit);
2055 0 : SecurityGroup4ByteAs sg4(bgp_server_->autonomous_system(),
2056 0 : sg_index++);
2057 0 : ext.communities.push_back(sg4.GetExtCommunityValue());
2058 0 : ext.communities.push_back(sg.GetExtCommunityValue());
2059 : }
2060 : }
2061 :
2062 4367 : if (item.entry.mobility.seqno) {
2063 6 : MacMobility mm(item.entry.mobility.seqno,
2064 6 : item.entry.mobility.sticky);
2065 6 : ext.communities.push_back(mm.GetExtCommunityValue());
2066 4361 : } else if (item.entry.sequence_number) {
2067 2 : MacMobility mm(item.entry.sequence_number);
2068 2 : ext.communities.push_back(mm.GetExtCommunityValue());
2069 : }
2070 :
2071 4367 : ETree etree(item.entry.etree_leaf);
2072 4367 : ext.communities.push_back(etree.GetExtCommunityValue());
2073 :
2074 4367 : if (!ext.communities.empty())
2075 4367 : attrs.push_back(&ext);
2076 4367 : if (!largecomm.communities.empty())
2077 2 : attrs.push_back(&largecomm);
2078 :
2079 4367 : PmsiTunnelSpec pmsi_spec;
2080 4367 : if (mac_addr.IsBroadcast()) {
2081 355 : if (!item.entry.replicator_address.empty()) {
2082 4 : IpAddress replicator_address;
2083 4 : if (!XmppDecodeAddress(BgpAf::IPv4,
2084 : item.entry.replicator_address, &replicator_address)) {
2085 4 : BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
2086 : BGP_LOG_FLAG_ALL,
2087 : "Bad replicator address " <<
2088 : item.entry.replicator_address <<
2089 : " for enet route " << evpn_prefix.ToXmppIdString());
2090 2 : return false;
2091 : }
2092 2 : pmsi_spec.tunnel_type =
2093 : PmsiTunnelSpec::AssistedReplicationContrail;
2094 2 : pmsi_spec.tunnel_flags = PmsiTunnelSpec::ARLeaf;
2095 2 : pmsi_spec.SetIdentifier(replicator_address.to_v4());
2096 : } else {
2097 351 : pmsi_spec.tunnel_type = PmsiTunnelSpec::IngressReplication;
2098 351 : if (item.entry.assisted_replication_supported) {
2099 0 : pmsi_spec.tunnel_flags |= PmsiTunnelSpec::ARReplicator;
2100 0 : pmsi_spec.tunnel_flags |= PmsiTunnelSpec::LeafInfoRequired;
2101 : }
2102 351 : if (!item.entry.edge_replication_not_supported) {
2103 175 : pmsi_spec.tunnel_flags |=
2104 : PmsiTunnelSpec::EdgeReplicationSupported;
2105 : }
2106 351 : pmsi_spec.SetIdentifier(nh_address.to_v4());
2107 : }
2108 352 : ExtCommunity ext_comm(bgp_server_->extcomm_db(), ext);
2109 353 : pmsi_spec.SetLabel(label, &ext_comm);
2110 353 : attrs.push_back(&pmsi_spec);
2111 353 : }
2112 :
2113 4366 : BgpAttrPtr attr = bgp_server_->attr_db()->Locate(attrs);
2114 :
2115 4366 : req.data.reset(new EvpnTable::RequestData(
2116 4366 : attr, flags, label, l3_label, subscription_gen_id));
2117 4366 : stats_[RX].reach++;
2118 4381 : } else {
2119 1147 : req.oper = DBRequest::DB_ENTRY_DELETE;
2120 1147 : stats_[RX].unreach++;
2121 : }
2122 :
2123 : // Defer all requests till subscribe is processed.
2124 5514 : if (subscribe_pending) {
2125 419 : DBRequest *request_entry = new DBRequest();
2126 419 : request_entry->Swap(&req);
2127 : string table_name =
2128 419 : RoutingInstance::GetTableName(vrf_name, Address::EVPN);
2129 419 : defer_q_.insert(make_pair(
2130 838 : make_pair(vrf_name, table_name), request_entry));
2131 419 : return true;
2132 419 : }
2133 :
2134 5095 : assert(table);
2135 9521 : BGP_LOG_PEER_INSTANCE(Peer(), vrf_name,
2136 : SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
2137 : "Enet route " << evpn_prefix.ToXmppIdString() <<
2138 : " with next-hop " << nh_address <<
2139 : " label " << label << " l3-label " << l3_label <<
2140 : " enqueued for " << (add_change ? "add/change" : "delete"));
2141 5096 : table->Enqueue(&req);
2142 5097 : return true;
2143 5540 : }
2144 :
2145 1060 : void BgpXmppChannel::DequeueRequest(const string &table_name,
2146 : DBRequest *request) {
2147 1060 : unique_ptr<DBRequest> ptr(request);
2148 :
2149 : BgpTable *table = static_cast<BgpTable *>
2150 1060 : (bgp_server_->database()->FindTable(table_name));
2151 1060 : if (table == NULL || table->IsDeleted()) {
2152 5 : return;
2153 : }
2154 :
2155 1055 : BgpMembershipManager *mgr = bgp_server_->membership_mgr();
2156 1055 : if (mgr) {
2157 1055 : int instance_id = -1;
2158 1055 : uint64_t subscription_gen_id = 0;
2159 1055 : bool is_registered = mgr->GetRegistrationInfo(peer_.get(), table,
2160 : &instance_id, &subscription_gen_id);
2161 1055 : if (!is_registered) {
2162 0 : BGP_LOG_PEER_WARNING(Membership, Peer(),
2163 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
2164 : "Not subscribed to table " << table->name());
2165 0 : return;
2166 : }
2167 1055 : if (ptr->oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
2168 1052 : ((BgpTable::RequestData *)ptr->data.get())
2169 1052 : ->set_subscription_gen_id(subscription_gen_id);
2170 : }
2171 : }
2172 :
2173 1055 : table->Enqueue(ptr.get());
2174 1060 : }
2175 :
2176 86 : bool BgpXmppChannel::ResumeClose() {
2177 86 : peer_->Close(true);
2178 86 : return true;
2179 : }
2180 :
2181 68833 : void BgpXmppChannel::RegisterTable(int line, BgpTable *table,
2182 : const TableMembershipRequestState *tmr_state) {
2183 : // Defer if Membership manager is in use (by close manager).
2184 68833 : if (close_manager_->IsMembershipInUse()) {
2185 207 : BGP_LOG_PEER_TABLE(Peer(), SandeshLevel::SYS_DEBUG,
2186 : BGP_LOG_FLAG_ALL, table, "RegisterTable deferred "
2187 : "from :" << line);
2188 69 : return;
2189 : }
2190 :
2191 68767 : BgpMembershipManager *mgr = bgp_server_->membership_mgr();
2192 85058 : BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
2193 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
2194 : "Subscribe to table " << table->name() <<
2195 : (tmr_state->no_ribout ? " (no ribout)" : "") <<
2196 : " with id " << tmr_state->instance_id);
2197 68767 : if (tmr_state->no_ribout) {
2198 59 : mgr->RegisterRibIn(peer_.get(), table);
2199 59 : mgr->SetRegistrationInfo(peer_.get(), table, tmr_state->instance_id,
2200 59 : manager_->get_subscription_gen_id());
2201 59 : channel_stats_.table_subscribe++;
2202 59 : MembershipRequestCallback(table);
2203 : } else {
2204 68708 : mgr->Register(peer_.get(), table, bgp_policy_, tmr_state->instance_id);
2205 68708 : channel_stats_.table_subscribe++;
2206 : }
2207 :
2208 : // If EndOfRib Send timer is running, cancel it and reschedule it after all
2209 : // outstanding membership registrations are complete.
2210 68767 : if (eor_send_timer_->running())
2211 13520 : eor_send_timer_->Cancel();
2212 : }
2213 :
2214 4477 : void BgpXmppChannel::UnregisterTable(int line, BgpTable *table) {
2215 : // Defer if Membership manager is in use (by close manager).
2216 4477 : if (close_manager_->IsMembershipInUse()) {
2217 948 : BGP_LOG_PEER_TABLE(Peer(), SandeshLevel::SYS_DEBUG,
2218 : BGP_LOG_FLAG_ALL, table, "UnregisterTable deferred "
2219 : "from :" << line);
2220 316 : return;
2221 : }
2222 :
2223 4161 : BgpMembershipManager *mgr = bgp_server_->membership_mgr();
2224 5749 : BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
2225 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
2226 : "Unsubscribe to table " << table->name());
2227 4161 : mgr->Unregister(peer_.get(), table);
2228 4161 : channel_stats_.table_unsubscribe++;
2229 : }
2230 :
2231 : #define RegisterTable(table, tmr_state) \
2232 : RegisterTable(__LINE__, table, tmr_state)
2233 : #define UnregisterTable(table) UnregisterTable(__LINE__, table)
2234 :
2235 : // Process all pending membership requests of various tables.
2236 264 : void BgpXmppChannel::ProcessPendingSubscriptions() {
2237 264 : assert(!close_manager_->IsMembershipInUse());
2238 1034 : BOOST_FOREACH(TableMembershipRequestMap::value_type &entry,
2239 : table_membership_request_map_) {
2240 : BgpTable *table = static_cast<BgpTable *>(
2241 385 : bgp_server_->database()->FindTable(entry.first));
2242 385 : const TableMembershipRequestState &tmr_state = entry.second;
2243 385 : if (tmr_state.current_req == SUBSCRIBE) {
2244 69 : RegisterTable(table, &tmr_state);
2245 : } else {
2246 316 : assert(tmr_state.current_req == UNSUBSCRIBE);
2247 316 : UnregisterTable(table);
2248 : }
2249 : }
2250 264 : }
2251 :
2252 10806 : size_t BgpXmppChannel::table_membership_requests() const {
2253 10806 : return table_membership_request_map_.size();
2254 : }
2255 :
2256 141100 : bool BgpXmppChannel::MembershipResponseHandler(string table_name) {
2257 141100 : if (close_manager_->IsMembershipInUse()) {
2258 68185 : close_manager_->MembershipRequestCallback();
2259 68295 : return true;
2260 : }
2261 :
2262 : TableMembershipRequestState *tmr_state =
2263 72922 : GetTableMembershipState(table_name);
2264 72915 : if (!tmr_state) {
2265 0 : BGP_LOG_PEER_INSTANCE_CRITICAL(Peer(), table_name,
2266 : BGP_PEER_DIR_IN, BGP_LOG_FLAG_ALL,
2267 : "Table not in subscribe/unsubscribe request queue");
2268 0 : assert(false);
2269 : }
2270 :
2271 72915 : if (tmr_state->current_req == SUBSCRIBE) {
2272 85045 : BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
2273 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
2274 : "Subscribe to table " << table_name << " completed");
2275 68754 : channel_stats_.table_subscribe_complete++;
2276 : } else {
2277 5749 : BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
2278 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
2279 : "Unsubscribe to table " << table_name << " completed");
2280 4161 : channel_stats_.table_unsubscribe_complete++;
2281 : }
2282 :
2283 72927 : if (defer_peer_close_) {
2284 637 : DeleteTableMembershipState(table_name);
2285 637 : if (table_membership_requests())
2286 551 : return true;
2287 86 : defer_peer_close_ = false;
2288 86 : ResumeClose();
2289 : } else {
2290 72290 : ProcessMembershipResponse(table_name, tmr_state);
2291 : }
2292 :
2293 72367 : assert(channel_stats_.table_subscribe_complete <=
2294 : channel_stats_.table_subscribe);
2295 72370 : assert(channel_stats_.table_unsubscribe_complete <=
2296 : channel_stats_.table_unsubscribe);
2297 :
2298 : // Restart EndOfRib send if necessary.
2299 72370 : ResetEndOfRibSendState();
2300 :
2301 : // If Close manager is waiting to use membership, try now.
2302 72370 : if (close_manager_->IsMembershipInWait())
2303 65 : close_manager_->MembershipRequest();
2304 :
2305 72369 : return true;
2306 : }
2307 :
2308 72291 : bool BgpXmppChannel::ProcessMembershipResponse(string table_name,
2309 : TableMembershipRequestState *tmr_state) {
2310 : BgpTable *table = static_cast<BgpTable *>
2311 72291 : (bgp_server_->database()->FindTable(table_name));
2312 72284 : if (!table) {
2313 116 : DeleteTableMembershipState(table_name);
2314 116 : return true;
2315 : }
2316 72168 : BgpMembershipManager *mgr = bgp_server_->membership_mgr();
2317 :
2318 72166 : if ((tmr_state->current_req == UNSUBSCRIBE) &&
2319 3902 : (tmr_state->pending_req == SUBSCRIBE)) {
2320 : // Process pending subscribe now that unsubscribe has completed.
2321 34 : tmr_state->current_req = SUBSCRIBE;
2322 34 : RegisterTable(table, tmr_state);
2323 34 : return true;
2324 72132 : } else if ((tmr_state->current_req == SUBSCRIBE) &&
2325 68264 : (tmr_state->pending_req == UNSUBSCRIBE)) {
2326 : // Process pending unsubscribe now that subscribe has completed.
2327 50 : tmr_state->current_req = UNSUBSCRIBE;
2328 50 : UnregisterTable(table);
2329 50 : return true;
2330 212387 : } else if ((tmr_state->current_req == SUBSCRIBE) &&
2331 140305 : (tmr_state->pending_req == SUBSCRIBE) &&
2332 68214 : (mgr->IsRibOutRegistered(peer_.get(), table) == tmr_state->no_ribout)) {
2333 : // Trigger an unsubscribe so that we can subsequently subscribe with
2334 : // the updated value of no_ribout.
2335 25 : tmr_state->current_req = UNSUBSCRIBE;
2336 25 : UnregisterTable(table);
2337 25 : return true;
2338 : }
2339 :
2340 72066 : string vrf_name = table->routing_instance()->name();
2341 72064 : VrfTableName vrf_n_table = make_pair(vrf_name, table->name());
2342 :
2343 72060 : if (tmr_state->pending_req == UNSUBSCRIBE) {
2344 3868 : if (!GetInstanceMembershipState(vrf_name))
2345 3867 : assert(defer_q_.count(vrf_n_table) == 0);
2346 3868 : DeleteTableMembershipState(table_name);
2347 3868 : return true;
2348 68192 : } else if (tmr_state->pending_req == SUBSCRIBE) {
2349 68197 : mgr->SetRegistrationInfo(peer_.get(), table, tmr_state->instance_id,
2350 68192 : manager_->get_subscription_gen_id());
2351 68198 : DeleteTableMembershipState(table_name);
2352 : }
2353 :
2354 68193 : for (DeferQ::iterator it = defer_q_.find(vrf_n_table);
2355 69252 : it != defer_q_.end() && it->first.second == table->name(); ++it) {
2356 1060 : DequeueRequest(table->name(), it->second);
2357 : }
2358 :
2359 : // Erase all elements for the table
2360 68191 : defer_q_.erase(vrf_n_table);
2361 :
2362 68186 : return true;
2363 72054 : }
2364 :
2365 141224 : void BgpXmppChannel::MembershipRequestCallback(BgpTable *table) {
2366 141224 : membership_response_worker_.Enqueue(table->name());
2367 141224 : }
2368 :
2369 487 : void BgpXmppChannel::FillCloseInfo(BgpNeighborResp *resp) const {
2370 487 : close_manager_->FillCloseInfo(resp);
2371 487 : }
2372 :
2373 487 : void BgpXmppChannel::FillInstanceMembershipInfo(BgpNeighborResp *resp) const {
2374 487 : vector<BgpNeighborRoutingInstance> instance_list;
2375 4287 : BOOST_FOREACH(const SubscribedRoutingInstanceList::value_type &entry,
2376 : routing_instances_) {
2377 1900 : BgpNeighborRoutingInstance instance;
2378 1900 : instance.set_name(entry.first->name());
2379 1900 : if (entry.second.IsLlgrStale()) {
2380 0 : instance.set_state("subscribed-llgr-stale");
2381 1900 : } else if (entry.second.IsGrStale()) {
2382 0 : instance.set_state("subscribed-gr-stale");
2383 : } else {
2384 1900 : instance.set_state("subscribed");
2385 : }
2386 1900 : instance.set_index(entry.second.index);
2387 1900 : rtarget_manager_->FillInfo(&instance, entry.second.targets);
2388 1900 : instance_list.push_back(instance);
2389 1900 : }
2390 487 : BOOST_FOREACH(const InstanceMembershipRequestMap::value_type &entry,
2391 : instance_membership_request_map_) {
2392 0 : const InstanceMembershipRequestState &imr_state = entry.second;
2393 0 : BgpNeighborRoutingInstance instance;
2394 0 : instance.set_name(entry.first);
2395 0 : instance.set_state("pending");
2396 0 : instance.set_index(imr_state.instance_id);
2397 0 : instance_list.push_back(instance);
2398 0 : }
2399 487 : resp->set_routing_instances(instance_list);
2400 487 : }
2401 :
2402 487 : void BgpXmppChannel::FillTableMembershipInfo(BgpNeighborResp *resp) const {
2403 487 : vector<BgpNeighborRoutingTable> old_table_list = resp->get_routing_tables();
2404 487 : set<string> old_table_set;
2405 487 : vector<BgpNeighborRoutingTable> new_table_list;
2406 :
2407 19487 : BOOST_FOREACH(const BgpNeighborRoutingTable &table, old_table_list) {
2408 9500 : old_table_set.insert(table.get_name());
2409 9500 : if (!GetTableMembershipState(table.get_name()))
2410 9500 : new_table_list.push_back(table);
2411 : }
2412 :
2413 487 : BOOST_FOREACH(const TableMembershipRequestMap::value_type &entry,
2414 : table_membership_request_map_) {
2415 0 : BgpNeighborRoutingTable table;
2416 0 : table.set_name(entry.first);
2417 0 : if (old_table_set.find(entry.first) != old_table_set.end())
2418 0 : table.set_current_state("subscribed");
2419 0 : const TableMembershipRequestState &tmr_state = entry.second;
2420 0 : if (tmr_state.current_req == SUBSCRIBE) {
2421 0 : table.set_current_request("subscribe");
2422 : } else {
2423 0 : table.set_current_request("unsubscribe");
2424 : }
2425 0 : if (tmr_state.pending_req == SUBSCRIBE) {
2426 0 : table.set_pending_request("subscribe");
2427 : } else {
2428 0 : table.set_pending_request("unsubscribe");
2429 : }
2430 0 : new_table_list.push_back(table);
2431 0 : }
2432 487 : resp->set_routing_tables(new_table_list);
2433 487 : }
2434 :
2435 : //
2436 : // Erase all defer_q_ elements with the given (vrf, table).
2437 : //
2438 20 : void BgpXmppChannel::FlushDeferQ(string vrf_name, string table_name) {
2439 20 : for (DeferQ::iterator it =
2440 20 : defer_q_.find(make_pair(vrf_name, table_name)), itnext;
2441 59 : (it != defer_q_.end() && it->first.second == table_name);
2442 39 : it = itnext) {
2443 39 : itnext = it;
2444 39 : itnext++;
2445 39 : delete it->second;
2446 39 : defer_q_.erase(it);
2447 : }
2448 20 : }
2449 :
2450 : //
2451 : // Erase all defer_q_ elements for all tables for the given vrf.
2452 : //
2453 10 : void BgpXmppChannel::FlushDeferQ(string vrf_name) {
2454 10 : for (DeferQ::iterator it =
2455 10 : defer_q_.lower_bound(make_pair(vrf_name, string())), itnext;
2456 25 : (it != defer_q_.end() && it->first.first == vrf_name);
2457 15 : it = itnext) {
2458 15 : itnext = it;
2459 15 : itnext++;
2460 15 : delete it->second;
2461 15 : defer_q_.erase(it);
2462 : }
2463 10 : }
2464 :
2465 : // Mark all current subscriptions as 'stale'. This is called when peer close
2466 : // process is initiated by BgpXmppChannel via PeerCloseManager.
2467 195 : void BgpXmppChannel::StaleCurrentSubscriptions() {
2468 195 : CHECK_CONCURRENCY(peer_close_->GetTaskName());
2469 1675 : BOOST_FOREACH(SubscribedRoutingInstanceList::value_type &entry,
2470 : routing_instances_) {
2471 740 : entry.second.SetGrStale();
2472 740 : rtarget_manager_->UpdateRouteTargetRouteFlag(entry.first,
2473 740 : entry.second.targets, BgpPath::Stale);
2474 : }
2475 195 : }
2476 :
2477 : // Mark all current subscriptions as 'llgr_stale'.
2478 29 : void BgpXmppChannel::LlgrStaleCurrentSubscriptions() {
2479 29 : CHECK_CONCURRENCY(peer_close_->GetTaskName());
2480 271 : BOOST_FOREACH(SubscribedRoutingInstanceList::value_type &entry,
2481 : routing_instances_) {
2482 121 : assert(entry.second.IsGrStale());
2483 121 : entry.second.SetLlgrStale();
2484 121 : rtarget_manager_->UpdateRouteTargetRouteFlag(entry.first,
2485 121 : entry.second.targets, BgpPath::Stale | BgpPath::LlgrStale);
2486 : }
2487 29 : }
2488 :
2489 : // Sweep all current subscriptions which are still marked as 'stale'.
2490 40 : void BgpXmppChannel::SweepCurrentSubscriptions() {
2491 40 : CHECK_CONCURRENCY(peer_close_->GetTaskName());
2492 40 : for (SubscribedRoutingInstanceList::iterator i = routing_instances_.begin();
2493 216 : i != routing_instances_.end();) {
2494 176 : if (i->second.IsGrStale()) {
2495 68 : string name = i->first->name();
2496 :
2497 : // Increment the iterator first as we expect the entry to be
2498 : // soon removed.
2499 68 : i++;
2500 136 : BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
2501 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
2502 : "Instance subscription " << name <<
2503 : " is still stale and hence unsubscribed");
2504 68 : ProcessSubscriptionRequest(name, NULL, false);
2505 68 : } else {
2506 108 : i++;
2507 : }
2508 : }
2509 40 : }
2510 :
2511 : // Clear staled subscription state as new subscription has been received.
2512 251 : void BgpXmppChannel::ClearStaledSubscription(RoutingInstance *rt_instance,
2513 : SubscriptionState *sub_state) {
2514 251 : if (!sub_state->IsGrStale())
2515 0 : return;
2516 :
2517 502 : BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
2518 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
2519 : "Instance subscription " << rt_instance->name() <<
2520 : " stale flag is cleared");
2521 251 : sub_state->ClearStale();
2522 251 : rtarget_manager_->Stale(sub_state->targets);
2523 : }
2524 :
2525 14231 : void BgpXmppChannel::AddSubscriptionState(RoutingInstance *rt_instance,
2526 : int index) {
2527 14231 : SubscriptionState state(rt_instance->GetImportList(), index);
2528 : pair<SubscribedRoutingInstanceList::iterator, bool> ret =
2529 14230 : routing_instances_.insert(pair<RoutingInstance *, SubscriptionState> (
2530 : rt_instance, state));
2531 :
2532 : // During GR, we expect duplicate subscription requests. Clear stale
2533 : // state, as agent did re-subscribe after restart.
2534 14230 : if (!ret.second) {
2535 251 : ClearStaledSubscription(rt_instance, &ret.first->second);
2536 : } else {
2537 13979 : rtarget_manager_->PublishRTargetRoute(rt_instance, true);
2538 : }
2539 14231 : }
2540 :
2541 900 : void BgpXmppChannel::DeleteSubscriptionState(RoutingInstance *rt_instance) {
2542 900 : routing_instances_.erase(rt_instance);
2543 900 : }
2544 :
2545 17236 : BgpXmppChannel::SubscriptionState *BgpXmppChannel::GetSubscriptionState(
2546 : RoutingInstance *rt_instance) {
2547 : SubscribedRoutingInstanceList::iterator loc =
2548 17236 : routing_instances_.find(rt_instance);
2549 17235 : return (loc != routing_instances_.end() ? &loc->second : NULL);
2550 : }
2551 :
2552 0 : const BgpXmppChannel::SubscriptionState *BgpXmppChannel::GetSubscriptionState(
2553 : RoutingInstance *rt_instance) const {
2554 : SubscribedRoutingInstanceList::const_iterator loc =
2555 0 : routing_instances_.find(rt_instance);
2556 0 : return (loc != routing_instances_.end() ? &loc->second : NULL);
2557 : }
2558 :
2559 32 : void BgpXmppChannel::ProcessDeferredSubscribeRequest(RoutingInstance *instance,
2560 : const InstanceMembershipRequestState &imr_state) {
2561 32 : int instance_id = imr_state.instance_id;
2562 32 : bool no_ribout = imr_state.no_ribout;
2563 32 : AddSubscriptionState(instance, instance_id);
2564 32 : RoutingInstance::RouteTableList const rt_list = instance->GetTables();
2565 32 : for (RoutingInstance::RouteTableList::const_iterator it = rt_list.begin();
2566 192 : it != rt_list.end(); ++it) {
2567 160 : BgpTable *table = it->second;
2568 160 : if (table->IsVpnTable() || table->family() == Address::RTARGET)
2569 0 : continue;
2570 :
2571 : TableMembershipRequestState tmr_state(
2572 160 : SUBSCRIBE, instance_id, no_ribout);
2573 160 : AddTableMembershipState(table->name(), tmr_state);
2574 160 : RegisterTable(table, &tmr_state);
2575 : }
2576 32 : }
2577 :
2578 15286 : void BgpXmppChannel::ProcessSubscriptionRequest(
2579 : string vrf_name, const XmppStanza::XmppMessageIq *iq,
2580 : bool add_change) {
2581 15286 : int instance_id = -1;
2582 15286 : bool no_ribout = false;
2583 :
2584 15286 : if (add_change) {
2585 14354 : XmlPugi *pugi = reinterpret_cast<XmlPugi *>(iq->dom.get());
2586 14354 : xml_node options = pugi->FindNode("options");
2587 28711 : for (xml_node node = options.first_child(); node;
2588 14357 : node = node.next_sibling()) {
2589 14357 : if (strcmp(node.name(), "instance-id") == 0) {
2590 14342 : instance_id = node.text().as_int();
2591 : }
2592 14357 : if (strcmp(node.name(), "no-ribout") == 0) {
2593 15 : no_ribout = node.text().as_bool();
2594 : }
2595 : }
2596 : }
2597 :
2598 15286 : RoutingInstanceMgr *instance_mgr = bgp_server_->routing_instance_mgr();
2599 15286 : assert(instance_mgr);
2600 15286 : RoutingInstance *rt_instance = instance_mgr->GetRoutingInstance(vrf_name);
2601 15286 : if (rt_instance == NULL) {
2602 174 : BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_INFO,
2603 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
2604 : "Routing instance " << vrf_name <<
2605 : " not found when processing " <<
2606 : (add_change ? "subscribe" : "unsubscribe"));
2607 146 : if (add_change) {
2608 136 : if (GetInstanceMembershipState(vrf_name)) {
2609 2 : BGP_LOG_PEER_WARNING(Membership, Peer(),
2610 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
2611 : "Duplicate subscribe for routing instance " <<
2612 : vrf_name << ", triggering close");
2613 1 : channel_->Close();
2614 : } else {
2615 135 : AddInstanceMembershipState(vrf_name,
2616 : InstanceMembershipRequestState(instance_id, no_ribout));
2617 135 : channel_stats_.instance_subscribe++;
2618 : }
2619 : } else {
2620 10 : if (DeleteInstanceMembershipState(vrf_name)) {
2621 9 : FlushDeferQ(vrf_name);
2622 9 : channel_stats_.instance_unsubscribe++;
2623 : } else {
2624 2 : BGP_LOG_PEER_WARNING(Membership, Peer(),
2625 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
2626 : "Spurious unsubscribe for routing instance " <<
2627 : vrf_name << ", triggering close");
2628 1 : channel_->Close();
2629 : }
2630 : }
2631 187 : return;
2632 15140 : } else if (rt_instance->deleted()) {
2633 322 : BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
2634 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
2635 : "Routing instance " << vrf_name <<
2636 : " is being deleted when processing " <<
2637 : (add_change ? "subscribe" : "unsubscribe"));
2638 161 : if (add_change) {
2639 10 : if (GetInstanceMembershipState(vrf_name)) {
2640 2 : BGP_LOG_PEER_WARNING(Membership, Peer(),
2641 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
2642 : "Duplicate subscribe for routing instance " <<
2643 : vrf_name << ", triggering close");
2644 1 : channel_->Close();
2645 9 : } else if (GetSubscriptionState(rt_instance)) {
2646 2 : BGP_LOG_PEER_WARNING(Membership, Peer(),
2647 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
2648 : "Duplicate subscribe for routing instance " <<
2649 : vrf_name << ", triggering close");
2650 1 : channel_->Close();
2651 : } else {
2652 8 : AddInstanceMembershipState(vrf_name,
2653 : InstanceMembershipRequestState(instance_id, no_ribout));
2654 8 : channel_stats_.instance_subscribe++;
2655 : }
2656 10 : return;
2657 : } else {
2658 : // If instance is being deleted and agent is trying to unsubscribe
2659 : // we need to process the unsubscribe if vrf is not in the request
2660 : // map. This would be the normal case where we wait for agent to
2661 : // unsubscribe in order to remove routes added by it.
2662 151 : if (DeleteInstanceMembershipState(vrf_name)) {
2663 1 : FlushDeferQ(vrf_name);
2664 1 : channel_stats_.instance_unsubscribe++;
2665 1 : return;
2666 150 : } else if (!GetSubscriptionState(rt_instance)) {
2667 4 : BGP_LOG_PEER_WARNING(Membership, Peer(),
2668 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
2669 : "Spurious unsubscribe for routing instance " <<
2670 : vrf_name << ", triggering close");
2671 2 : channel_->Close();
2672 2 : return;
2673 : }
2674 148 : channel_stats_.instance_unsubscribe++;
2675 : }
2676 : } else {
2677 14979 : if (add_change) {
2678 : const SubscriptionState *sub_state =
2679 14208 : GetSubscriptionState(rt_instance);
2680 14207 : if (sub_state) {
2681 260 : if (!close_manager_->IsCloseInProgress()) {
2682 2 : BGP_LOG_PEER_WARNING(Membership, Peer(),
2683 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
2684 : "Duplicate subscribe for routing instance " <<
2685 : vrf_name << ", triggering close");
2686 1 : channel_->Close();
2687 1 : return;
2688 : }
2689 259 : if (!sub_state->IsGrStale()) {
2690 16 : BGP_LOG_PEER_WARNING(Membership, Peer(),
2691 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
2692 : "Duplicate subscribe for routing instance " <<
2693 : vrf_name << " under GR, triggering close");
2694 8 : channel_->Close();
2695 8 : return;
2696 : }
2697 : }
2698 14198 : channel_stats_.instance_subscribe++;
2699 : } else {
2700 771 : if (!GetSubscriptionState(rt_instance)) {
2701 26 : BGP_LOG_PEER_WARNING(Membership, Peer(),
2702 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
2703 : "Spurious unsubscribe for routing instance " <<
2704 : vrf_name << ", triggering close");
2705 19 : channel_->Close();
2706 19 : return;
2707 : }
2708 752 : channel_stats_.instance_unsubscribe++;
2709 : }
2710 : }
2711 :
2712 15099 : if (add_change) {
2713 14199 : AddSubscriptionState(rt_instance, instance_id);
2714 : } else {
2715 900 : rtarget_manager_->PublishRTargetRoute(rt_instance, false);
2716 900 : DeleteSubscriptionState(rt_instance);
2717 : }
2718 :
2719 15099 : RoutingInstance::RouteTableList const rt_list = rt_instance->GetTables();
2720 15099 : for (RoutingInstance::RouteTableList::const_iterator it = rt_list.begin();
2721 95682 : it != rt_list.end(); ++it) {
2722 80583 : BgpTable *table = it->second;
2723 80583 : if (table->IsVpnTable() || table->family() == Address::RTARGET)
2724 7632 : continue;
2725 :
2726 72951 : if (add_change) {
2727 : TableMembershipRequestState *tmr_state =
2728 68681 : GetTableMembershipState(table->name());
2729 68681 : if (!tmr_state) {
2730 : TableMembershipRequestState tmp_tmr_state(
2731 68573 : SUBSCRIBE, instance_id, no_ribout);
2732 68573 : AddTableMembershipState(table->name(), tmp_tmr_state);
2733 68573 : RegisterTable(table, &tmp_tmr_state);
2734 : } else {
2735 108 : tmr_state->instance_id = instance_id;
2736 108 : tmr_state->pending_req = SUBSCRIBE;
2737 108 : tmr_state->no_ribout = no_ribout;
2738 : }
2739 : } else {
2740 4270 : if (defer_q_.count(make_pair(vrf_name, table->name()))) {
2741 40 : BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
2742 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
2743 : "Flush deferred route requests for table " <<
2744 : table->name() << " on unsubscribe");
2745 20 : FlushDeferQ(vrf_name, table->name());
2746 : }
2747 :
2748 : // Erase all elements for the table.
2749 :
2750 : TableMembershipRequestState *tmr_state =
2751 4270 : GetTableMembershipState(table->name());
2752 4270 : if (!tmr_state) {
2753 4086 : AddTableMembershipState(table->name(),
2754 : TableMembershipRequestState(
2755 : UNSUBSCRIBE, instance_id, no_ribout));
2756 4086 : UnregisterTable(table);
2757 : } else {
2758 184 : tmr_state->instance_id = -1;
2759 184 : tmr_state->pending_req = UNSUBSCRIBE;
2760 184 : tmr_state->no_ribout = false;
2761 : }
2762 : }
2763 : }
2764 15099 : }
2765 :
2766 6344 : void BgpXmppChannel::ClearEndOfRibState() {
2767 6344 : eor_receive_timer_->Cancel();
2768 6343 : eor_send_timer_->Cancel();
2769 6344 : eor_sent_ = false;
2770 6344 : }
2771 :
2772 503 : void BgpXmppChannel::ReceiveEndOfRIB(Address::Family family) {
2773 503 : eor_receive_timer_->Cancel();
2774 503 : close_manager_->ProcessEORMarkerReceived(family);
2775 503 : }
2776 :
2777 0 : void BgpXmppChannel::EndOfRibTimerErrorHandler(string error_name,
2778 : string error_message) {
2779 0 : BGP_LOG_PEER_CRITICAL(Timer, Peer(), BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
2780 : "Timer error: " << error_name << " " << error_message);
2781 0 : }
2782 :
2783 463 : bool BgpXmppChannel::EndOfRibReceiveTimerExpired() {
2784 463 : if (!peer_->IsReady())
2785 0 : return false;
2786 :
2787 463 : uint32_t timeout = manager() && manager()->xmpp_server() ?
2788 463 : manager()->xmpp_server()->GetEndOfRibReceiveTime() :
2789 463 : BgpGlobalSystemConfig::kEndOfRibTime;
2790 :
2791 : // If max timeout has not reached yet, check if we can exit GR sooner by
2792 : // looking at the activity in the channel.
2793 463 : if (UTCTimestamp() - eor_receive_timer_start_time_ < timeout) {
2794 :
2795 : // If there is some send or receive activity in the channel in last few
2796 : // seconds, delay EoR receive event.
2797 0 : if (channel_->LastReceived(kEndOfRibSendRetryTime * 6) ||
2798 0 : channel_->LastSent(kEndOfRibSendRetryTime * 6)) {
2799 0 : eor_receive_timer_->Reschedule(kEndOfRibSendRetryTime * 1000);
2800 0 : BGP_LOG_PEER(Message, Peer(), SandeshLevel::SYS_INFO,
2801 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_IN,
2802 : "EndOfRib Receive timer rescheduled to fire after " <<
2803 : kEndOfRibSendRetryTime << " second(s)");
2804 0 : return true;
2805 : }
2806 : }
2807 :
2808 551 : BGP_LOG_PEER(Message, Peer(), SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
2809 : BGP_PEER_DIR_IN, "EndOfRib Receive timer expired");
2810 463 : ReceiveEndOfRIB(Address::UNSPEC);
2811 463 : return false;
2812 : }
2813 :
2814 9599 : time_t BgpXmppChannel::GetEndOfRibSendTime() const {
2815 9599 : return manager() && manager()->xmpp_server() ?
2816 9599 : manager()->xmpp_server()->GetEndOfRibSendTime() :
2817 9598 : BgpGlobalSystemConfig::kEndOfRibTime;
2818 : }
2819 :
2820 9601 : bool BgpXmppChannel::EndOfRibSendTimerExpired() {
2821 9601 : if (!peer_->IsReady())
2822 0 : return false;
2823 :
2824 : // If max timeout has not reached yet, check if we can exit GR sooner by
2825 : // looking at the activity in the channel.
2826 9601 : if (UTCTimestamp() - eor_send_timer_start_time_ < GetEndOfRibSendTime()) {
2827 :
2828 : // If there is some send or receive activity in the channel in last few
2829 : // seconds, delay EoR send event.
2830 9598 : if (channel_->LastReceived(kEndOfRibSendRetryTime * 6) ||
2831 9941 : channel_->LastSent(kEndOfRibSendRetryTime * 6) ||
2832 343 : manager()->bgp_server()->IsServerStartingUp()) {
2833 9393 : eor_send_timer_->Reschedule(kEndOfRibSendRetryTime * 1000);
2834 10818 : BGP_LOG_PEER(Message, Peer(), SandeshLevel::SYS_INFO,
2835 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_OUT,
2836 : "EndOfRib Send timer rescheduled to fire after " <<
2837 : kEndOfRibSendRetryTime << " second(s)");
2838 9394 : return true;
2839 : }
2840 : }
2841 :
2842 207 : SendEndOfRIB();
2843 207 : return false;
2844 : }
2845 :
2846 6289 : void BgpXmppChannel::StartEndOfRibReceiveTimer() {
2847 6289 : uint32_t timeout = manager() && manager()->xmpp_server() ?
2848 6282 : manager()->xmpp_server()->GetEndOfRibReceiveTime() :
2849 6290 : BgpGlobalSystemConfig::kEndOfRibTime;
2850 6290 : eor_receive_timer_start_time_ = UTCTimestamp();
2851 6289 : eor_receive_timer_->Cancel();
2852 :
2853 7230 : BGP_LOG_PEER(Message, Peer(), SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
2854 : BGP_PEER_DIR_IN, "EndOfRib Receive timer scheduled to fire after " <<
2855 : timeout << " second(s)");
2856 6290 : eor_receive_timer_->Start(timeout * 1000,
2857 : boost::bind(&BgpXmppChannel::EndOfRibReceiveTimerExpired, this),
2858 : boost::bind(&BgpXmppChannel::EndOfRibTimerErrorHandler, this, _1, _2));
2859 6290 : }
2860 :
2861 78662 : void BgpXmppChannel::ResetEndOfRibSendState() {
2862 78662 : if (eor_sent_)
2863 1232 : return;
2864 :
2865 : // If socket is blocked, then wait for it to get unblocked first.
2866 77430 : if (!peer_->send_ready())
2867 1 : return;
2868 :
2869 : // If there is any outstanding subscribe pending, wait for its completion.
2870 77429 : if (channel_stats_.table_subscribe_complete !=
2871 77429 : channel_stats_.table_subscribe)
2872 53875 : return;
2873 :
2874 23554 : eor_send_timer_start_time_ = UTCTimestamp();
2875 23554 : eor_send_timer_->Cancel();
2876 :
2877 28864 : BGP_LOG_PEER(Message, Peer(), SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
2878 : BGP_PEER_DIR_OUT, "EndOfRib Send timer scheduled to fire after " <<
2879 : kEndOfRibSendRetryTime << " second(s)");
2880 23554 : eor_send_timer_->Start(kEndOfRibSendRetryTime * 1000,
2881 : boost::bind(&BgpXmppChannel::EndOfRibSendTimerExpired, this),
2882 : boost::bind(&BgpXmppChannel::EndOfRibTimerErrorHandler, this, _1, _2));
2883 : }
2884 :
2885 : /*
2886 : * Empty items list constitute eor marker.
2887 : */
2888 207 : void BgpXmppChannel::SendEndOfRIB() {
2889 207 : eor_send_timer_->Cancel();
2890 207 : eor_sent_ = true;
2891 :
2892 207 : string msg;
2893 207 : msg += "\n<message from=\"";
2894 207 : msg += XmppInit::kControlNodeJID;
2895 207 : msg += "\" to=\"";
2896 207 : msg += peer_->ToString();
2897 207 : msg += "/";
2898 207 : msg += XmppInit::kBgpPeer;
2899 207 : msg += "\">";
2900 207 : msg += "\n\t<event xmlns=\"http://jabber.org/protocol/pubsub\">";
2901 414 : msg = (msg + "\n<items node=\"") + XmppInit::kEndOfRibMarker +
2902 207 : "\"></items>";
2903 207 : msg += "\n\t</event>\n</message>\n";
2904 :
2905 207 : if (channel_->connection())
2906 205 : channel_->connection()->Send((const uint8_t *) msg.data(), msg.size());
2907 :
2908 207 : stats_[TX].end_of_rib++;
2909 236 : BGP_LOG_PEER(Message, Peer(), SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
2910 : BGP_PEER_DIR_OUT, "EndOfRib marker sent");
2911 207 : }
2912 :
2913 : // Process any associated primary instance-id.
2914 25615 : int BgpXmppChannel::GetPrimaryInstanceID(const string &s,
2915 : bool expect_prefix_len) const {
2916 25615 : if (s.empty())
2917 0 : return 0;
2918 25615 : char *str = const_cast<char *>(s.c_str());
2919 : char *saveptr, *token;
2920 25615 : token = strtok_r(str, "/", &saveptr); // Get afi
2921 25615 : if (!token || !saveptr)
2922 0 : return 0;
2923 25615 : token = strtok_r(NULL, "/", &saveptr); // Get safi
2924 25615 : if (!token || !saveptr)
2925 0 : return 0;
2926 25615 : token = strtok_r(NULL, "/", &saveptr); // vrf name
2927 25615 : if (!token || !saveptr)
2928 0 : return 0;
2929 25615 : token = strtok_r(NULL, "/", &saveptr); // address
2930 25615 : if (!token || !saveptr)
2931 2 : return 0;
2932 25613 : if (expect_prefix_len) {
2933 25609 : token = strtok_r(NULL, "/", &saveptr); // prefix-length
2934 25609 : if (!token || !saveptr)
2935 1 : return 0;
2936 : }
2937 25612 : token = strtok_r(NULL, "/", &saveptr); // primary instance-id
2938 25612 : if (!token)
2939 25596 : return 0;
2940 16 : return strtoul(token, NULL, 0);
2941 : }
2942 :
2943 56884 : void BgpXmppChannel::ReceiveUpdate(const XmppStanza::XmppMessage *msg) {
2944 56884 : CHECK_CONCURRENCY("xmpp::StateMachine");
2945 :
2946 : // Bail if the connection is being deleted. It's not safe to assert
2947 : // because the Delete method can be called from the main thread.
2948 56883 : if (channel_->connection() && channel_->connection()->IsDeleted())
2949 0 : return;
2950 :
2951 : // Make sure that peer is not set for closure already.
2952 56883 : assert(!defer_peer_close_);
2953 56883 : assert(!peer_deleted());
2954 :
2955 56884 : if (msg->type == XmppStanza::IQ_STANZA) {
2956 56884 : const XmppStanza::XmppMessageIq *iq =
2957 : static_cast<const XmppStanza::XmppMessageIq *>(msg);
2958 56884 : if (iq->iq_type.compare("set") == 0) {
2959 56885 : if (iq->action.compare("subscribe") == 0) {
2960 14354 : ProcessSubscriptionRequest(iq->node, iq, true);
2961 42531 : } else if (iq->action.compare("unsubscribe") == 0) {
2962 864 : ProcessSubscriptionRequest(iq->node, iq, false);
2963 41665 : } else if (iq->action.compare("publish") == 0) {
2964 41660 : XmlBase *impl = msg->dom.get();
2965 41661 : stats_[RX].rt_updates++;
2966 41662 : XmlPugi *pugi = reinterpret_cast<XmlPugi *>(impl);
2967 41662 : xml_node item = pugi->FindNode("item");
2968 :
2969 : // Empty items-list can be considered as EOR Marker for all afis
2970 41661 : if (item == 0) {
2971 56 : BGP_LOG_PEER(Message, Peer(), SandeshLevel::SYS_INFO,
2972 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_IN,
2973 : "EndOfRib marker received");
2974 28 : stats_[RX].end_of_rib++;
2975 28 : ReceiveEndOfRIB(Address::UNSPEC);
2976 28 : return;
2977 : }
2978 83264 : for (; item; item = item.next_sibling()) {
2979 41632 : if (strcmp(item.name(), "item") != 0) continue;
2980 :
2981 41632 : string id(iq->as_node.c_str());
2982 41633 : char *str = const_cast<char *>(id.c_str());
2983 : char *saveptr;
2984 41633 : char *af = strtok_r(str, "/", &saveptr);
2985 41633 : char *safi = strtok_r(NULL, "/", &saveptr);
2986 :
2987 41634 : if (atoi(af) == BgpAf::IPv4 &&
2988 27014 : ((atoi(safi) == BgpAf::Unicast) ||
2989 1419 : (atoi(safi) == BgpAf::Mpls))) {
2990 25606 : ProcessItem(iq->node, item, iq->is_as_node,
2991 25606 : GetPrimaryInstanceID(iq->as_node, true));
2992 16028 : } else if (atoi(af) == BgpAf::IPv6 &&
2993 9093 : atoi(safi) == BgpAf::Unicast) {
2994 9093 : ProcessInet6Item(iq->node, item, iq->is_as_node);
2995 6935 : } else if (atoi(af) == BgpAf::IPv4 &&
2996 1408 : atoi(safi) == BgpAf::Mcast) {
2997 1160 : ProcessMcastItem(iq->node, item, iq->is_as_node);
2998 5775 : } else if (atoi(af) == BgpAf::IPv4 &&
2999 248 : atoi(safi) == BgpAf::MVpn) {
3000 248 : ProcessMvpnItem(iq->node, item, iq->is_as_node);
3001 5527 : } else if (atoi(af) == BgpAf::L2Vpn &&
3002 5525 : atoi(safi) == BgpAf::Enet) {
3003 5526 : ProcessEnetItem(iq->node, item, iq->is_as_node);
3004 : }
3005 41633 : }
3006 : }
3007 : }
3008 : }
3009 : }
3010 :
3011 6178 : bool BgpXmppChannelManager::DeleteChannel(BgpXmppChannel *channel) {
3012 6178 : if (!channel->deleted()) {
3013 6178 : channel->set_deleted(true);
3014 6178 : delete channel;
3015 : }
3016 6178 : return true;
3017 : }
3018 :
3019 : // BgpXmppChannelManager routines.
3020 2084 : BgpXmppChannelManager::BgpXmppChannelManager(XmppServer *xmpp_server,
3021 2084 : BgpServer *server)
3022 2084 : : xmpp_server_(xmpp_server),
3023 2084 : bgp_server_(server),
3024 2084 : queue_(TaskScheduler::GetInstance()->GetTaskId("bgp::Config"), 0,
3025 : boost::bind(&BgpXmppChannelManager::DeleteChannel, this, _1)),
3026 2084 : id_(-1),
3027 2084 : asn_listener_id_(-1),
3028 2084 : identifier_listener_id_(-1),
3029 4168 : dscp_listener_id_(-1) {
3030 : // Initialize the gen id counter
3031 2084 : subscription_gen_id_ = 1;
3032 2084 : deleting_count_ = 0;
3033 :
3034 2084 : if (xmpp_server)
3035 2078 : xmpp_server->CreateConfigUpdater(server->config_manager());
3036 2084 : queue_.SetEntryCallback(
3037 : boost::bind(&BgpXmppChannelManager::IsReadyForDeletion, this));
3038 2084 : if (xmpp_server) {
3039 2078 : xmpp_server->RegisterConnectionEvent(xmps::BGP,
3040 : boost::bind(&BgpXmppChannelManager::XmppHandleChannelEvent,
3041 : this, _1, _2));
3042 : }
3043 2084 : admin_down_listener_id_ =
3044 2084 : server->RegisterAdminDownCallback(boost::bind(
3045 : &BgpXmppChannelManager::AdminDownCallback, this));
3046 2084 : asn_listener_id_ =
3047 2084 : server->RegisterASNUpdateCallback(boost::bind(
3048 : &BgpXmppChannelManager::ASNUpdateCallback, this, _1, _2));
3049 2084 : identifier_listener_id_ =
3050 2084 : server->RegisterIdentifierUpdateCallback(boost::bind(
3051 : &BgpXmppChannelManager::IdentifierUpdateCallback, this, _1));
3052 2084 : dscp_listener_id_ =
3053 2084 : server->RegisterDSCPUpdateCallback(boost::bind(
3054 : &BgpXmppChannelManager::DSCPUpdateCallback, this, _1));
3055 :
3056 2084 : id_ = server->routing_instance_mgr()->RegisterInstanceOpCallback(
3057 : boost::bind(&BgpXmppChannelManager::RoutingInstanceCallback,
3058 : this, _1, _2));
3059 2084 : }
3060 :
3061 3540 : BgpXmppChannelManager::~BgpXmppChannelManager() {
3062 2084 : assert(channel_map_.empty());
3063 2084 : assert(channel_name_map_.empty());
3064 2084 : assert(deleting_count_ == 0);
3065 2084 : if (xmpp_server_) {
3066 2078 : xmpp_server_->UnRegisterConnectionEvent(xmps::BGP);
3067 : }
3068 :
3069 2084 : queue_.Shutdown();
3070 2084 : bgp_server_->UnregisterAdminDownCallback(admin_down_listener_id_);
3071 2084 : bgp_server_->UnregisterASNUpdateCallback(asn_listener_id_);
3072 2084 : bgp_server_->routing_instance_mgr()->UnregisterInstanceOpCallback(id_);
3073 2084 : bgp_server_->UnregisterDSCPUpdateCallback(dscp_listener_id_);
3074 3540 : }
3075 :
3076 22461 : bool BgpXmppChannelManager::IsReadyForDeletion() {
3077 22461 : return bgp_server_->IsReadyForDeletion();
3078 : }
3079 :
3080 4 : void BgpXmppChannelManager::SetQueueDisable(bool disabled) {
3081 4 : queue_.set_disable(disabled);
3082 4 : }
3083 :
3084 2 : size_t BgpXmppChannelManager::GetQueueSize() const {
3085 2 : return queue_.Length();
3086 : }
3087 :
3088 16 : void BgpXmppChannelManager::AdminDownCallback() {
3089 16 : xmpp_server_->ClearAllConnections();
3090 16 : }
3091 :
3092 7 : void BgpXmppChannelManager::DSCPUpdateCallback(uint8_t dscp_value) {
3093 7 : xmpp_server_->SetDscpValue(dscp_value);
3094 7 : }
3095 :
3096 2419 : void BgpXmppChannelManager::ASNUpdateCallback(as_t old_asn,
3097 : as_t old_local_asn) {
3098 2419 : CHECK_CONCURRENCY("bgp::Config");
3099 4537 : BOOST_FOREACH(XmppChannelMap::value_type &i, channel_map_) {
3100 1059 : i.second->rtarget_manager()->ASNUpdateCallback(old_asn, old_local_asn);
3101 : }
3102 2419 : if (bgp_server_->autonomous_system() != old_asn) {
3103 2390 : xmpp_server_->ClearAllConnections();
3104 : }
3105 2419 : }
3106 :
3107 2408 : void BgpXmppChannelManager::IdentifierUpdateCallback(
3108 : Ip4Address old_identifier) {
3109 2408 : CHECK_CONCURRENCY("bgp::Config");
3110 2408 : xmpp_server_->ClearAllConnections();
3111 2408 : }
3112 :
3113 24771 : void BgpXmppChannelManager::RoutingInstanceCallback(string vrf_name, int op) {
3114 24771 : CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
3115 30365 : BOOST_FOREACH(XmppChannelMap::value_type &i, channel_map_) {
3116 2797 : i.second->RoutingInstanceCallback(vrf_name, op);
3117 : }
3118 24770 : }
3119 :
3120 297 : void BgpXmppChannelManager::VisitChannels(BgpXmppChannelManager::VisitorFn fn) {
3121 297 : std::scoped_lock lock(mutex_);
3122 327 : BOOST_FOREACH(XmppChannelMap::value_type &i, channel_map_) {
3123 15 : fn(i.second);
3124 : }
3125 297 : }
3126 :
3127 177 : void BgpXmppChannelManager::VisitChannels(BgpXmppChannelManager::VisitorFn fn)
3128 : const {
3129 177 : std::scoped_lock lock(mutex_);
3130 325 : BOOST_FOREACH(const XmppChannelMap::value_type &i, channel_map_) {
3131 74 : fn(i.second);
3132 : }
3133 177 : }
3134 :
3135 21 : BgpXmppChannel *BgpXmppChannelManager::FindChannel(string client) {
3136 21 : BOOST_FOREACH(XmppChannelMap::value_type &i, channel_map_) {
3137 20 : if (i.second->ToString() == client) {
3138 20 : return i.second;
3139 : }
3140 : }
3141 1 : return NULL;
3142 : }
3143 :
3144 28 : BgpXmppChannel *BgpXmppChannelManager::FindChannel(
3145 : const XmppChannel *ch) {
3146 28 : XmppChannelMap::iterator it = channel_map_.find(ch);
3147 28 : if (it == channel_map_.end())
3148 0 : return NULL;
3149 28 : return it->second;
3150 : }
3151 :
3152 6196 : void BgpXmppChannelManager::RemoveChannel(XmppChannel *channel) {
3153 6196 : if (channel->connection() && !channel->connection()->IsActiveChannel()) {
3154 6178 : CHECK_CONCURRENCY("bgp::Config");
3155 : }
3156 6196 : channel_map_.erase(channel);
3157 6196 : channel_name_map_.erase(channel->ToString());
3158 6196 : }
3159 :
3160 4001 : BgpXmppChannel *BgpXmppChannelManager::CreateChannel(XmppChannel *channel) {
3161 4001 : CHECK_CONCURRENCY("xmpp::StateMachine");
3162 4001 : BgpXmppChannel *ch = new BgpXmppChannel(channel, bgp_server_, this);
3163 :
3164 4001 : return ch;
3165 : }
3166 :
3167 12864 : void BgpXmppChannelManager::XmppHandleChannelEvent(XmppChannel *channel,
3168 : xmps::PeerState state) {
3169 12864 : std::scoped_lock lock(mutex_);
3170 :
3171 12867 : XmppChannelMap::iterator it = channel_map_.find(channel);
3172 12864 : BgpXmppChannel *bgp_xmpp_channel = NULL;
3173 12864 : if (state == xmps::READY) {
3174 6289 : if (it == channel_map_.end()) {
3175 6185 : bgp_xmpp_channel = CreateChannel(channel);
3176 6186 : channel_map_.insert(make_pair(channel, bgp_xmpp_channel));
3177 6186 : channel_name_map_.insert(
3178 12372 : make_pair(channel->ToString(), bgp_xmpp_channel));
3179 7022 : BGP_LOG_PEER(Message, bgp_xmpp_channel->Peer(),
3180 : Sandesh::LoggingUtLevel(), BGP_LOG_FLAG_SYSLOG,
3181 : BGP_PEER_DIR_IN,
3182 : "Received XmppChannel up event");
3183 6186 : if (!bgp_server_->HasSelfConfiguration()) {
3184 304 : BGP_LOG_PEER(Message, bgp_xmpp_channel->Peer(),
3185 : SandeshLevel::SYS_INFO, BGP_LOG_FLAG_SYSLOG,
3186 : BGP_PEER_DIR_IN,
3187 : "No BGP configuration for self - closing channel");
3188 296 : if (!getenv("CONTRAIL_CAT_FRAMEWORK"))
3189 296 : channel->Close();
3190 : }
3191 6186 : if (bgp_server_->admin_down()) {
3192 192 : BGP_LOG_PEER(Message, bgp_xmpp_channel->Peer(),
3193 : SandeshLevel::SYS_INFO, BGP_LOG_FLAG_SYSLOG,
3194 : BGP_PEER_DIR_IN,
3195 : "BGP is administratively down - closing channel");
3196 192 : channel->Close();
3197 : }
3198 : } else {
3199 104 : bgp_xmpp_channel = (*it).second;
3200 104 : if (bgp_xmpp_channel->peer_deleted())
3201 0 : return;
3202 :
3203 : // Gracefully close the channel if GR closure is in progress.
3204 : // This can happen if GR timers fire just after session comes
3205 : // back up.
3206 208 : if (bgp_xmpp_channel->close_manager()->IsCloseInProgress() &&
3207 104 : !bgp_xmpp_channel->close_manager()->IsInGRTimerWaitState()) {
3208 0 : BGP_LOG_PEER(Message, bgp_xmpp_channel->Peer(),
3209 : SandeshLevel::SYS_INFO, BGP_LOG_FLAG_SYSLOG,
3210 : BGP_PEER_DIR_IN,
3211 : "Graceful Closure in progress - Closing channel");
3212 0 : channel->Close();
3213 : }
3214 104 : channel->RegisterReceive(xmps::BGP,
3215 : boost::bind(&BgpXmppChannel::ReceiveUpdate, bgp_xmpp_channel,
3216 : _1));
3217 : }
3218 :
3219 6290 : bgp_xmpp_channel->eor_sent_ = false;
3220 6290 : bgp_xmpp_channel->StartEndOfRibReceiveTimer();
3221 6290 : bgp_xmpp_channel->ResetEndOfRibSendState();
3222 6575 : } else if (state == xmps::NOT_READY) {
3223 6575 : if (it != channel_map_.end()) {
3224 6350 : bgp_xmpp_channel = (*it).second;
3225 7352 : BGP_LOG_PEER(Message, bgp_xmpp_channel->Peer(),
3226 : Sandesh::LoggingUtLevel(), BGP_LOG_FLAG_SYSLOG,
3227 : BGP_PEER_DIR_IN,
3228 : "Received XmppChannel down event");
3229 :
3230 : // Trigger closure of this channel
3231 6350 : bgp_xmpp_channel->Close();
3232 : } else {
3233 225 : ostringstream os;
3234 450 : os << "Peer not found for " << channel->ToString() <<
3235 225 : " on channel down event";
3236 225 : BGP_LOG_NOTICE(BgpMessage, BGP_LOG_FLAG_ALL, os.str());
3237 225 : }
3238 : }
3239 12867 : }
3240 :
3241 74 : void BgpXmppChannelManager::FillPeerInfo(const BgpXmppChannel *channel) const {
3242 74 : PeerStatsInfo stats;
3243 74 : PeerStats::FillPeerDebugStats(channel->Peer()->peer_stats(), &stats);
3244 :
3245 148 : XmppPeerInfoData peer_info;
3246 74 : peer_info.set_name(channel->Peer()->ToUVEKey());
3247 74 : peer_info.set_peer_stats_info(stats);
3248 74 : assert(!peer_info.get_name().empty());
3249 74 : BGP_UVE_SEND(XMPPPeerInfo, peer_info);
3250 :
3251 148 : PeerStatsData peer_stats_data;
3252 74 : peer_stats_data.set_name(channel->Peer()->ToUVEKey());
3253 74 : peer_stats_data.set_encoding("XMPP");
3254 74 : PeerStats::FillPeerUpdateStats(channel->Peer()->peer_stats(),
3255 : &peer_stats_data);
3256 74 : assert(!peer_stats_data.get_name().empty());
3257 74 : BGP_UVE_SEND2(PeerStatsUve, peer_stats_data, "ObjectXmppPeerInfo");
3258 74 : }
3259 :
3260 177 : bool BgpXmppChannelManager::CollectStats(BgpRouterState *state, bool first)
3261 : const {
3262 177 : CHECK_CONCURRENCY("bgp::ShowCommand");
3263 :
3264 177 : VisitChannels(boost::bind(&BgpXmppChannelManager::FillPeerInfo, this, _1));
3265 177 : bool change = false;
3266 177 : uint32_t num_xmpp = count();
3267 177 : if (first || num_xmpp != state->get_num_xmpp_peer()) {
3268 15 : state->set_num_xmpp_peer(num_xmpp);
3269 15 : change = true;
3270 : }
3271 :
3272 177 : uint32_t num_up_xmpp = NumUpPeer();
3273 177 : if (first || num_up_xmpp != state->get_num_up_xmpp_peer()) {
3274 15 : state->set_num_up_xmpp_peer(num_up_xmpp);
3275 15 : change = true;
3276 : }
3277 :
3278 177 : uint32_t num_deleting_xmpp = deleting_count();
3279 177 : if (first || num_deleting_xmpp != state->get_num_deleting_xmpp_peer()) {
3280 1 : state->set_num_deleting_xmpp_peer(num_deleting_xmpp);
3281 1 : change = true;
3282 : }
3283 :
3284 177 : return change;
3285 : }
3286 :
3287 10166 : void BgpXmppChannel::Close() {
3288 10166 : instance_membership_request_map_.clear();
3289 10166 : STLDeleteElements(&defer_q_);
3290 :
3291 10165 : if (table_membership_requests()) {
3292 149 : BGP_LOG_PEER(Event, peer_.get(), SandeshLevel::SYS_INFO,
3293 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA, "Close procedure deferred");
3294 86 : defer_peer_close_ = true;
3295 86 : return;
3296 : }
3297 10079 : peer_->Close(true);
3298 : }
3299 :
3300 : //
3301 : // Return connection's remote tcp endpoint if available
3302 : //
3303 2740 : TcpSession::Endpoint BgpXmppChannel::remote_endpoint() const {
3304 2740 : const XmppSession *session = GetSession();
3305 2740 : if (session) {
3306 2668 : return session->remote_endpoint();
3307 : }
3308 72 : return TcpSession::Endpoint();
3309 : }
3310 :
3311 : //
3312 : // Return connection's local tcp endpoint if available
3313 : //
3314 974 : TcpSession::Endpoint BgpXmppChannel::local_endpoint() const {
3315 974 : const XmppSession *session = GetSession();
3316 974 : if (session) {
3317 950 : return session->local_endpoint();
3318 : }
3319 24 : return TcpSession::Endpoint();
3320 : }
3321 :
3322 : //
3323 : // Return connection's remote tcp endpoint string.
3324 : //
3325 974 : string BgpXmppChannel::transport_address_string() const {
3326 974 : TcpSession::Endpoint endpoint = remote_endpoint();
3327 974 : ostringstream oss;
3328 974 : oss << endpoint;
3329 1948 : return oss.str();
3330 974 : }
3331 :
3332 : //
3333 : // Mark the XmppPeer as deleted.
3334 : //
3335 16608 : void BgpXmppChannel::set_peer_closed(bool flag) {
3336 16608 : peer_->SetPeerClosed(flag);
3337 16609 : }
3338 :
3339 : //
3340 : // Return true if the XmppPeer is deleted.
3341 : //
3342 74471 : bool BgpXmppChannel::peer_deleted() const {
3343 74471 : return peer_->IsDeleted();
3344 : }
3345 :
3346 : //
3347 : // Return time stamp of when the XmppPeer delete was initiated.
3348 : //
3349 974 : uint64_t BgpXmppChannel::peer_closed_at() const {
3350 974 : return peer_->closed_at();
3351 : }
3352 :
3353 7790 : bool BgpXmppChannel::IsSubscriptionGrStale(RoutingInstance *instance) const {
3354 : SubscribedRoutingInstanceList::const_iterator it =
3355 7790 : routing_instances_.find(instance);
3356 7790 : assert(it != routing_instances_.end());
3357 15580 : return it->second.IsGrStale();
3358 : }
3359 :
3360 7790 : bool BgpXmppChannel::IsSubscriptionLlgrStale(RoutingInstance *instance) const {
3361 : SubscribedRoutingInstanceList::const_iterator it =
3362 7790 : routing_instances_.find(instance);
3363 7790 : assert(it != routing_instances_.end());
3364 15580 : return it->second.IsLlgrStale();
3365 : }
3366 :
3367 15939 : bool BgpXmppChannel::IsSubscriptionEmpty() const {
3368 15939 : return routing_instances_.empty();
3369 : }
3370 :
3371 14880 : const RoutingInstance::RouteTargetList &BgpXmppChannel::GetSubscribedRTargets(
3372 : RoutingInstance *instance) const {
3373 : SubscribedRoutingInstanceList::const_iterator it =
3374 14880 : routing_instances_.find(instance);
3375 14878 : assert(it != routing_instances_.end());
3376 14878 : return it->second.targets;
3377 : }
|