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