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