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