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 tag list.
1298  uint16_t tag_index = 0;
1299  for (TagListType::const_iterator tit = nit->tag_list.begin();
1300  tit != nit->tag_list.end(); ++tit) {
1301  if (bgp_server_->autonomous_system() <= 0xFFFF) {
1302  Tag tag(bgp_server_->autonomous_system(), *tit);
1303  ext.communities.push_back(tag.GetExtCommunityValue());
1304  TagLC tag_lc(bgp_server_->autonomous_system(), *tit);
1305  for (auto value_data : tag_lc.GetLargeCommunityValue()) {
1306  largecomm.communities.push_back(value_data);
1307  }
1308  } else {
1309  Tag tag(tag_index, *tit);
1310  Tag4ByteAs tag4(bgp_server_->autonomous_system(), tag_index++);
1311  ext.communities.push_back(tag4.GetExtCommunityValue());
1312  ext.communities.push_back(tag.GetExtCommunityValue());
1313  TagLC tag_lc(bgp_server_->autonomous_system(), *tit);
1314  for (auto value_data : tag_lc.GetLargeCommunityValue()) {
1315  largecomm.communities.push_back(value_data);
1316  }
1317  }
1318  }
1319 
1320  // Process local sequence_number
1321  if (nit->local_sequence_number) {
1322  LocalSequenceNumber lsn (nit->local_sequence_number);
1323  ext.communities.push_back(lsn.GetExtCommunityValue());
1324  }
1325 
1326  BgpAttrLocalPref local_pref(item.entry.local_preference);
1327  if (local_pref.local_pref != 0)
1328  attrs.push_back(&local_pref);
1329 
1330  // If there's no explicit med, calculate it automatically from the
1331  // local pref.
1332  uint32_t med_value = item.entry.med;
1333  if (!med_value)
1334  med_value = GetMedFromLocalPref(local_pref.local_pref);
1335  BgpAttrMultiExitDisc med(med_value);
1336  if (med.med != 0)
1337  attrs.push_back(&med);
1338 
1339  // Process community tags.
1340  const CommunityTagListType &ict_list = item.entry.community_tag_list;
1341  for (CommunityTagListType::const_iterator cit = ict_list.begin();
1342  cit != ict_list.end(); ++cit) {
1343  error_code error;
1344  uint32_t rt_community =
1345  CommunityType::CommunityFromString(*cit, &error);
1346  if (error)
1347  continue;
1348  comm.communities.push_back(rt_community);
1349  }
1350 
1351  uint32_t addr = nh_address.to_v4().to_ulong();
1352  BgpAttrNextHop nexthop(addr);
1353  attrs.push_back(&nexthop);
1354  uint16_t cluster_seed =
1356  BgpAttrSourceRd source_rd;
1357  if (!master || primary_instance_id) {
1358  if (master)
1359  instance_id = primary_instance_id;
1360  if (cluster_seed) {
1361  source_rd = BgpAttrSourceRd(
1362  RouteDistinguisher(cluster_seed, addr, instance_id));
1363  } else {
1364  source_rd = BgpAttrSourceRd(
1365  RouteDistinguisher(addr, instance_id));
1366  }
1367  attrs.push_back(&source_rd);
1368  }
1369 
1370  // Process security group list.
1371  uint16_t sg_index = 0;
1372  const SecurityGroupListType &isg_list = item.entry.security_group_list;
1373  for (SecurityGroupListType::const_iterator sit = isg_list.begin();
1374  sit != isg_list.end(); ++sit) {
1375  if (bgp_server_->autonomous_system() <= 0xFFFF) {
1377  ext.communities.push_back(sg.GetExtCommunityValue());
1378  } else {
1379  SecurityGroup sg(sg_index, *sit);
1381  sg_index++);
1382  ext.communities.push_back(sg4.GetExtCommunityValue());
1383  ext.communities.push_back(sg.GetExtCommunityValue());
1384  }
1385  }
1386 
1387  if (item.entry.mobility.seqno) {
1388  MacMobility mm(item.entry.mobility.seqno,
1389  item.entry.mobility.sticky);
1390  ext.communities.push_back(mm.GetExtCommunityValue());
1391  } else if (item.entry.sequence_number) {
1392  MacMobility mm(item.entry.sequence_number);
1393  ext.communities.push_back(mm.GetExtCommunityValue());
1394  }
1395 
1396  // Process load-balance extended community.
1397  LoadBalance load_balance(item.entry.load_balance);
1398  if (!load_balance.IsDefault())
1399  ext.communities.push_back(load_balance.GetExtCommunityValue());
1400 
1401  if (!comm.communities.empty())
1402  attrs.push_back(&comm);
1403  if (!master && !ext.communities.empty())
1404  attrs.push_back(&ext);
1405  if (!master && !largecomm.communities.empty())
1406  attrs.push_back(&largecomm);
1407 
1408  // Process sub-protocol(route types)
1409  BgpAttrSubProtocol sbp(item.entry.sub_protocol);
1410  attrs.push_back(&sbp);
1411 
1412  BgpAttrPtr attr = bgp_server_->attr_db()->Locate(attrs);
1413  req.data.reset(new BgpTable::RequestData(
1414  attr, flags, label, 0, subscription_gen_id));
1415  } else {
1417  }
1418 
1419  // Defer all requests till subscribe is processed.
1420  if (subscribe_pending) {
1421  DBRequest *request_entry = new DBRequest();
1422  request_entry->Swap(&req);
1423  string table_name =
1424  RoutingInstance::GetTableName(vrf_name, family);
1425  defer_q_.insert(make_pair(
1426  make_pair(vrf_name, table_name), request_entry));
1427  return true;
1428  }
1429 
1430  assert(table);
1431  BGP_LOG_PEER_INSTANCE(Peer(), vrf_name,
1432  SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
1433  "Inet route " << item.entry.nlri.address <<
1434  " with next-hop " << nh_address << " and label " << label <<
1435  " enqueued for " << (add_change ? "add/change" : "delete") <<
1436  " to table " << table->name());
1437  table->Enqueue(&req);
1438 
1439  if (add_change) {
1440  stats_[RX].reach++;
1441  } else {
1442  stats_[RX].unreach++;
1443  }
1444 
1445  return true;
1446 }
1447 
1449  const pugi::xml_node &node, bool add_change) {
1450  ItemType item;
1451  item.Clear();
1452 
1453  if (!item.XmlParse(node)) {
1456  "Invalid inet6 route message received");
1457  return false;
1458  }
1459 
1460  if (item.entry.nlri.af != BgpAf::IPv6) {
1463  "Unsupported address family " << item.entry.nlri.af <<
1464  " for inet6 route " << item.entry.nlri.address);
1465  return false;
1466  }
1467 
1468  if (item.entry.nlri.safi != BgpAf::Unicast) {
1471  "Unsupported subsequent address family " << item.entry.nlri.safi <<
1472  " for inet6 route " << item.entry.nlri.address);
1473  return false;
1474  }
1475 
1476  error_code error;
1477  Inet6Prefix inet6_prefix =
1478  Inet6Prefix::FromString(item.entry.nlri.address, &error);
1479  if (error) {
1482  "Bad inet6 route " << item.entry.nlri.address);
1483  return false;
1484  }
1485 
1486  if (add_change && item.entry.next_hops.next_hop.empty()) {
1488  "Missing next-hops for inet6 route " << inet6_prefix.ToString());
1489  return false;
1490  }
1491 
1492  // Rules for routes in master instance:
1493  // - Label must be 0
1494  // - Tunnel encapsulation is not required
1495  // - Do not add SourceRd and ExtCommunitySpec
1496  bool master = (vrf_name == BgpConfigManager::kMasterInstance);
1497 
1498  // vector<Address::Family> family_list = list_of(Address::INET6)(Address::EVPN);
1499  vector<Address::Family> family_list = list_of(Address::INET6);
1500  BOOST_FOREACH(Address::Family family, family_list) {
1501  bool subscribe_pending;
1502  int instance_id;
1503  uint64_t subscription_gen_id;
1504  BgpTable *table;
1505  if (!VerifyMembership(vrf_name, family, &table, &instance_id,
1506  &subscription_gen_id, &subscribe_pending, add_change)) {
1507  channel_->Close();
1508  return false;
1509  }
1510 
1511  DBRequest req;
1512  if (family == Address::INET6) {
1513  req.key.reset(new Inet6Table::RequestKey(inet6_prefix, peer_.get()));
1514  } else {
1516  inet6_prefix.addr(), inet6_prefix.prefixlen());
1517  req.key.reset(new EvpnTable::RequestKey(evpn_prefix, peer_.get()));
1518  }
1519 
1520  IpAddress nh_address(Ip4Address(0));
1521  uint32_t label = 0;
1522  uint32_t flags = 0;
1523  ExtCommunitySpec ext;
1524  LargeCommunitySpec largecomm;
1525  CommunitySpec comm;
1526 
1527  if (add_change) {
1529  BgpAttrSpec attrs;
1530 
1531  const NextHopListType &inh_list = item.entry.next_hops;
1532 
1533  // Agents should send only one next-hop in the item.
1534  if (inh_list.next_hop.size() != 1) {
1535  BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1537  "More than one nexthop received for inet6 route " <<
1538  inet6_prefix.ToString());
1539  return false;
1540  }
1541 
1542  NextHopListType::const_iterator nit = inh_list.begin();
1543 
1544  IpAddress nhop_address(Ip4Address(0));
1545  if (!XmppDecodeAddress(nit->af, nit->address, &nhop_address)) {
1547  BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1549  "Bad nexthop address " << nit->address <<
1550  " for inet6 route " << inet6_prefix.ToString());
1551  return false;
1552  }
1553 
1554  if (family == Address::EVPN) {
1555  if (nit->vni > EvpnPrefix::kMaxVniSigned) {
1556  BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1558  "Bad label " << nit->vni <<
1559  " for inet6 route " << inet6_prefix.ToString());
1560  return false;
1561  }
1562  if (!nit->vni)
1563  continue;
1564  if (nit->mac.empty())
1565  continue;
1566 
1567  MacAddress mac_addr =
1568  MacAddress::FromString(nit->mac, &error);
1569  if (error) {
1570  BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1572  "Bad next-hop mac address " << nit->mac);
1573  return false;
1574  }
1575  RouterMac router_mac(mac_addr);
1576  ext.communities.push_back(router_mac.GetExtCommunityValue());
1577  } else {
1578  if (nit->label > EvpnPrefix::kMaxVniSigned || (master && nit->label)) {
1579  BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1581  "Bad label " << nit->label <<
1582  " for inet6 route " << inet6_prefix.ToString());
1583  return false;
1584  }
1585  if (!master && !nit->label)
1586  continue;
1587  }
1588 
1589  nh_address = nhop_address;
1590  if (family == Address::INET6) {
1591  label = nit->label;
1592  } else {
1593  label = nit->vni;
1594  }
1595 
1596  // Process tunnel encapsulation list.
1597  bool no_tunnel_encap = true;
1598  bool no_valid_tunnel_encap = true;
1599  for (TunnelEncapsulationListType::const_iterator eit =
1600  nit->tunnel_encapsulation_list.begin();
1601  eit != nit->tunnel_encapsulation_list.end(); ++eit) {
1602  no_tunnel_encap = false;
1603  TunnelEncap tun_encap(*eit);
1604  if (tun_encap.tunnel_encap() == TunnelEncapType::UNSPEC)
1605  continue;
1606  no_valid_tunnel_encap = false;
1607  ext.communities.push_back(tun_encap.GetExtCommunityValue());
1608  }
1609 
1610  // Mark the path as infeasible if all tunnel encaps published
1611  // by agent are invalid.
1612  if (!no_tunnel_encap && no_valid_tunnel_encap && !master) {
1613  flags = BgpPath::NoTunnelEncap;
1614  }
1615 
1616  // Process router-mac as ext-community.
1617  if (!nit->mac.empty()) {
1618  MacAddress mac_addr =
1619  MacAddress::FromString(nit->mac, &error);
1620  if (error) {
1621  BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1623  "Bad next-hop mac address " << nit->mac);
1624  return false;
1625  }
1626  if (!mac_addr.IsZero()) {
1627  RouterMac router_mac(mac_addr);
1628  ext.communities.push_back(router_mac.GetExtCommunityValue());
1629  }
1630  }
1631 
1632  // Process tag list.
1633  uint16_t tag_index = 0;
1634  for (TagListType::const_iterator tit = nit->tag_list.begin();
1635  tit != nit->tag_list.end(); ++tit) {
1636  if (bgp_server_->autonomous_system() <= 0xFFFF) {
1637  Tag tag(bgp_server_->autonomous_system(), *tit);
1638  ext.communities.push_back(tag.GetExtCommunityValue());
1639  TagLC tag_lc(bgp_server_->autonomous_system(), *tit);
1640  for (auto value_data : tag_lc.GetLargeCommunityValue()) {
1641  largecomm.communities.push_back(value_data);
1642  }
1643  } else {
1644  Tag tag(tag_index, *tit);
1646  tag_index++);
1647  ext.communities.push_back(tag.GetExtCommunityValue());
1648  ext.communities.push_back(tag4.GetExtCommunityValue());
1649  TagLC tag_lc(bgp_server_->autonomous_system(), *tit);
1650  for (auto value_data : tag_lc.GetLargeCommunityValue()) {
1651  largecomm.communities.push_back(value_data);
1652  }
1653  }
1654  }
1655 
1656  // Process local sequence_number
1657  if (nit->local_sequence_number) {
1658  LocalSequenceNumber lsn (nit->local_sequence_number);
1659  ext.communities.push_back(lsn.GetExtCommunityValue());
1660  }
1661 
1662  BgpAttrLocalPref local_pref(item.entry.local_preference);
1663  if (local_pref.local_pref != 0)
1664  attrs.push_back(&local_pref);
1665 
1666  // If there's no explicit med, calculate it automatically from the
1667  // local pref.
1668  uint32_t med_value = item.entry.med;
1669  if (!med_value)
1670  med_value = GetMedFromLocalPref(local_pref.local_pref);
1671  BgpAttrMultiExitDisc med(med_value);
1672  if (med.med != 0)
1673  attrs.push_back(&med);
1674 
1675  // Process community tags.
1676  const CommunityTagListType &ict_list =
1677  item.entry.community_tag_list;
1678  for (CommunityTagListType::const_iterator cit = ict_list.begin();
1679  cit != ict_list.end(); ++cit) {
1680  error_code error;
1681  uint32_t rt_community =
1682  CommunityType::CommunityFromString(*cit, &error);
1683  if (error)
1684  continue;
1685  comm.communities.push_back(rt_community);
1686  }
1687 
1688  BgpAttrNextHop nexthop(nh_address);
1689  attrs.push_back(&nexthop);
1690 
1691  BgpAttrSourceRd source_rd;
1692  if (!master) {
1693  uint32_t addr = nh_address.to_v4().to_ulong();
1694  uint16_t cluster_seed =
1696  if (cluster_seed) {
1697  source_rd = BgpAttrSourceRd(
1698  RouteDistinguisher(cluster_seed, addr, instance_id));
1699  } else {
1700  source_rd = BgpAttrSourceRd(
1701  RouteDistinguisher(addr, instance_id));
1702  }
1703  attrs.push_back(&source_rd);
1704  }
1705 
1706  // Process security group list.
1707  const SecurityGroupListType &isg_list =
1708  item.entry.security_group_list;
1709  uint16_t sg_index = 0;
1710  for (SecurityGroupListType::const_iterator sit = isg_list.begin();
1711  sit != isg_list.end(); ++sit) {
1714  ext.communities.push_back(sg.GetExtCommunityValue());
1715  } else {
1716  SecurityGroup sg(sg_index, *sit);
1718  sg_index++);
1719  ext.communities.push_back(sg4.GetExtCommunityValue());
1720  ext.communities.push_back(sg.GetExtCommunityValue());
1721  }
1722  }
1723 
1724  if (item.entry.mobility.seqno) {
1725  MacMobility mm(item.entry.mobility.seqno,
1726  item.entry.mobility.sticky);
1727  ext.communities.push_back(mm.GetExtCommunityValue());
1728  } else if (item.entry.sequence_number) {
1729  MacMobility mm(item.entry.sequence_number);
1730  ext.communities.push_back(mm.GetExtCommunityValue());
1731  }
1732 
1733  // Process load-balance extended community.
1734  LoadBalance load_balance(item.entry.load_balance);
1735  if (!load_balance.IsDefault())
1736  ext.communities.push_back(load_balance.GetExtCommunityValue());
1737 
1738  // Process sub-protocol(route types)
1739  BgpAttrSubProtocol sbp(item.entry.sub_protocol);
1740  attrs.push_back(&sbp);
1741 
1742  if (!comm.communities.empty())
1743  attrs.push_back(&comm);
1744  if (!master && !ext.communities.empty())
1745  attrs.push_back(&ext);
1746  if (!master && !largecomm.communities.empty())
1747  attrs.push_back(&largecomm);
1748 
1749  BgpAttrPtr attr = bgp_server_->attr_db()->Locate(attrs);
1750  req.data.reset(new BgpTable::RequestData(
1751  attr, flags, label, 0, subscription_gen_id));
1752  } else {
1754  }
1755 
1756  // Defer all requests till subscribe is processed.
1757  if (subscribe_pending) {
1758  DBRequest *request_entry = new DBRequest();
1759  request_entry->Swap(&req);
1760  string table_name =
1761  RoutingInstance::GetTableName(vrf_name, family);
1762  defer_q_.insert(make_pair(
1763  make_pair(vrf_name, table_name), request_entry));
1764  continue;
1765  }
1766 
1767  assert(table);
1768  BGP_LOG_PEER_INSTANCE(Peer(), vrf_name,
1769  SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
1770  "Inet6 route " << item.entry.nlri.address <<
1771  " with next-hop " << nh_address << " and label " << label <<
1772  " enqueued for " << (add_change ? "add/change" : "delete") <<
1773  " to table " << table->name());
1774  table->Enqueue(&req);
1775  }
1776 
1777  if (add_change) {
1778  stats_[RX].reach++;
1779  } else {
1780  stats_[RX].unreach++;
1781  }
1782 
1783  return true;
1784 }
1785 
1786 bool BgpXmppChannel::ProcessEnetItem(string vrf_name,
1787  const pugi::xml_node &node, bool add_change) {
1788  EnetItemType item;
1789  item.Clear();
1790 
1791  if (!item.XmlParse(node)) {
1793  "Invalid enet route message received");
1794  return false;
1795  }
1796 
1797  if (item.entry.nlri.af != BgpAf::L2Vpn) {
1799  "Unsupported address family " << item.entry.nlri.af <<
1800  " for enet route " << item.entry.nlri.address);
1801  return false;
1802  }
1803 
1804  if (item.entry.nlri.safi != BgpAf::Enet) {
1806  "Unsupported subsequent address family " << item.entry.nlri.safi <<
1807  " for enet route " << item.entry.nlri.mac);
1808  return false;
1809  }
1810 
1811  bool type6 = false;
1812  error_code error;
1813  IpAddress group= IpAddress::from_string("0.0.0.0", error);
1814  if (!item.entry.nlri.group.empty()) {
1815  type6 = true;
1816  if (!XmppDecodeAddress(item.entry.nlri.af,
1817  item.entry.nlri.group, &group, false)) {
1819  "Bad group address " << item.entry.nlri.group);
1820  }
1821  }
1822 
1823  IpAddress source = IpAddress::from_string("0.0.0.0", error);
1824  if (!item.entry.nlri.source.empty() && !XmppDecodeAddress(
1825  item.entry.nlri.af, item.entry.nlri.source, &source, true)) {
1827  "Bad source address " << item.entry.nlri.source);
1828  }
1829 
1830  //error_code error;
1831  MacAddress mac_addr = MacAddress::FromString(item.entry.nlri.mac, &error);
1832 
1833  if (error) {
1835  "Bad mac address " << item.entry.nlri.mac);
1836  return false;
1837  }
1838 
1839  bool type2 = type6 ? false : !mac_addr.IsZero();
1840  Ip4Prefix inet_prefix;
1841  Inet6Prefix inet6_prefix;
1842  IpAddress ip_addr;
1843  int prefix_len = 0;
1844  if (!item.entry.nlri.address.empty()) {
1845  size_t pos = item.entry.nlri.address.find('/');
1846  if (pos == string::npos) {
1848  "Missing / in address " << item.entry.nlri.address);
1849  return false;
1850  }
1851 
1852  bool ipv6 = item.entry.nlri.address.find(':') != string::npos;
1853  if (!ipv6) {
1854  inet_prefix =
1855  Ip4Prefix::FromString(item.entry.nlri.address, &error);
1856  if (error) {
1857  BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1859  "Cannot parse inet prefix string " <<
1860  item.entry.nlri.address);
1861  return false;
1862  }
1863 
1864  if (type2 && inet_prefix.prefixlen() != 32 &&
1865  item.entry.nlri.address != "0.0.0.0/0") {
1866  BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1868  "Bad inet address " << item.entry.nlri.address);
1869  return false;
1870  }
1871 
1872  ip_addr = inet_prefix.ip4_addr();
1873  prefix_len = inet_prefix.prefixlen();
1874  } else {
1875  inet6_prefix =
1876  Inet6Prefix::FromString(item.entry.nlri.address, &error);
1877 
1878  if (error) {
1879  BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1881  "Cannot parse inet6 prefix string " <<
1882  item.entry.nlri.address);
1883  return false;
1884  }
1885 
1886  if (type2 && inet6_prefix.prefixlen() != 128 &&
1887  item.entry.nlri.address != "::/0") {
1888  BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1890  "Bad inet6 address " << item.entry.nlri.address);
1891  return false;
1892  }
1893  ip_addr = inet6_prefix.ip6_addr();
1894  prefix_len = inet6_prefix.prefixlen();
1895  }
1896  }
1897 
1898  bool subscribe_pending;
1899  int instance_id;
1900  uint64_t subscription_gen_id;
1901  BgpTable *table;
1902  if (!VerifyMembership(vrf_name, Address::EVPN, &table, &instance_id,
1903  &subscription_gen_id, &subscribe_pending, add_change)) {
1904  channel_->Close();
1905  return false;
1906  }
1907 
1908  RouteDistinguisher rd;
1909  if (mac_addr.IsBroadcast()) {
1910  rd = RouteDistinguisher(peer_->bgp_identifier(), instance_id);
1911  } else if (type6) {
1913  table->routing_instance()->index());
1914  } else {
1916  }
1917 
1918  uint32_t ethernet_tag = item.entry.nlri.ethernet_tag;
1919  EvpnPrefix evpn_prefix = type6 ?
1920  EvpnPrefix(rd, ethernet_tag, source, group,
1922  type2 ? EvpnPrefix(rd, ethernet_tag, mac_addr, ip_addr) :
1923  EvpnPrefix(rd, ip_addr, prefix_len);
1924 
1925  DBRequest req;
1926  ExtCommunitySpec ext;
1927  LargeCommunitySpec largecomm;
1928  req.key.reset(new EvpnTable::RequestKey(evpn_prefix, peer_.get()));
1929 
1930  IpAddress nh_address(Ip4Address(0));
1931  uint32_t label = 0;
1932  uint32_t l3_label = 0;
1933  uint32_t flags = 0;
1934 
1935  if (add_change) {
1937  BgpAttrSpec attrs;
1938  const EnetNextHopListType &inh_list = item.entry.next_hops;
1939 
1940  if (inh_list.next_hop.empty()) {
1941  BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1942  BGP_LOG_FLAG_ALL, "Missing next-hops for enet route " <<
1943  evpn_prefix.ToXmppIdString());
1944  return false;
1945  }
1946 
1947  // Agents should send only one next-hop in the item.
1948  if (inh_list.next_hop.size() != 1) {
1949  BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1951  "More than one nexthop received for enet route " <<
1952  evpn_prefix.ToXmppIdString());
1953  return false;
1954  }
1955 
1956  EnetNextHopListType::const_iterator nit = inh_list.begin();
1957 
1958  IpAddress nhop_address(Ip4Address(0));
1959 
1960  if (!XmppDecodeAddress(nit->af, nit->address, &nhop_address)) {
1961  BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1962  BGP_LOG_FLAG_ALL, "Bad nexthop address " << nit->address <<
1963  " for enet route " << evpn_prefix.ToXmppIdString());
1964  return false;
1965  }
1966 
1967  nh_address = nhop_address;
1968  label = nit->label;
1969  l3_label = nit->l3_label;
1970  if (!nit->mac.empty()) {
1971  MacAddress rmac_addr =
1972  MacAddress::FromString(nit->mac, &error);
1973  if (error) {
1974  BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
1976  "Bad next-hop mac address " << nit->mac <<
1977  " for enet route " << evpn_prefix.ToXmppIdString());
1978  return false;
1979  }
1980  RouterMac router_mac(rmac_addr);
1981  ext.communities.push_back(router_mac.GetExtCommunityValue());
1982  }
1983 
1984  // Process tunnel encapsulation list.
1985  bool no_tunnel_encap = true;
1986  bool no_valid_tunnel_encap = true;
1987  for (EnetTunnelEncapsulationListType::const_iterator eit =
1988  nit->tunnel_encapsulation_list.begin();
1989  eit != nit->tunnel_encapsulation_list.end(); ++eit) {
1990  no_tunnel_encap = false;
1991  TunnelEncap tun_encap(*eit);
1992  if (tun_encap.tunnel_encap() == TunnelEncapType::UNSPEC)
1993  continue;
1994  no_valid_tunnel_encap = false;
1995  ext.communities.push_back(tun_encap.GetExtCommunityValue());
1996  if (tun_encap.tunnel_encap() == TunnelEncapType::GRE) {
1998  ext.communities.push_back(alt_tun_encap.GetExtCommunityValue());
1999  }
2000  }
2001 
2002  // Mark the path as infeasible if all tunnel encaps published
2003  // by agent are invalid.
2004  if (!no_tunnel_encap && no_valid_tunnel_encap) {
2005  flags = BgpPath::NoTunnelEncap;
2006  }
2007 
2008  // Process tag list.
2009  uint16_t tag_index = 0;
2010  for (TagListType::const_iterator tit = nit->tag_list.begin();
2011  tit != nit->tag_list.end(); ++tit) {
2012  if (bgp_server_->autonomous_system() <= 0xFFFF) {
2013  Tag tag(bgp_server_->autonomous_system(), *tit);
2014  ext.communities.push_back(tag.GetExtCommunityValue());
2015  TagLC tag_lc(bgp_server_->autonomous_system(), *tit);
2016  for (auto value_data : tag_lc.GetLargeCommunityValue()) {
2017  largecomm.communities.push_back(value_data);
2018  }
2019  } else {
2020  Tag tag(tag_index, *tit);
2021  Tag4ByteAs tag4(bgp_server_->autonomous_system(), tag_index++);
2022  ext.communities.push_back(tag.GetExtCommunityValue());
2023  ext.communities.push_back(tag4.GetExtCommunityValue());
2024  TagLC tag_lc(bgp_server_->autonomous_system(), *tit);
2025  for (auto value_data : tag_lc.GetLargeCommunityValue()) {
2026  largecomm.communities.push_back(value_data);
2027  }
2028  }
2029  }
2030 
2031  // Process local sequence_number
2032  if (nit->local_sequence_number) {
2033  LocalSequenceNumber lsn (nit->local_sequence_number);
2034  ext.communities.push_back(lsn.GetExtCommunityValue());
2035  }
2036 
2037  BgpAttrLocalPref local_pref(item.entry.local_preference);
2038  if (local_pref.local_pref != 0) {
2039  attrs.push_back(&local_pref);
2040  }
2041 
2042  // If there's no explicit med, calculate it automatically from the
2043  // local pref.
2044  uint32_t med_value = item.entry.med;
2045  if (!med_value)
2046  med_value = GetMedFromLocalPref(local_pref.local_pref);
2047  BgpAttrMultiExitDisc med(med_value);
2048  if (med.med != 0)
2049  attrs.push_back(&med);
2050 
2051  BgpAttrNextHop nexthop(nh_address.to_v4().to_ulong());
2052  if (type6) {
2054  if (item.entry.replicator_address.empty() &&
2055  item.entry.edge_replication_not_supported) {
2056  // Only for test to inject remote smet routes
2057  flags &= ~BgpPath::CheckGlobalErmVpnRoute;
2058  attrs.push_back(&nexthop);
2059  }
2060  } else {
2061  attrs.push_back(&nexthop);
2062  }
2063 
2064  uint16_t cluster_seed = bgp_server_->global_config()->rd_cluster_seed();
2065  BgpAttrSourceRd source_rd;
2066  if (cluster_seed) {
2067  source_rd = BgpAttrSourceRd(RouteDistinguisher(cluster_seed,
2068  nh_address.to_v4().to_ulong(), instance_id));
2069  } else {
2070  source_rd = BgpAttrSourceRd(RouteDistinguisher(
2071  nh_address.to_v4().to_ulong(), instance_id));
2072  }
2073  attrs.push_back(&source_rd);
2074 
2075  // Process security group list.
2076  const EnetSecurityGroupListType &isg_list =
2077  item.entry.security_group_list;
2078  uint16_t sg_index = 0;
2079  for (EnetSecurityGroupListType::const_iterator sit = isg_list.begin();
2080  sit != isg_list.end(); ++sit) {
2083  ext.communities.push_back(sg.GetExtCommunityValue());
2084  } else {
2085  SecurityGroup sg(sg_index, *sit);
2087  sg_index++);
2088  ext.communities.push_back(sg4.GetExtCommunityValue());
2089  ext.communities.push_back(sg.GetExtCommunityValue());
2090  }
2091  }
2092 
2093  if (item.entry.mobility.seqno) {
2094  MacMobility mm(item.entry.mobility.seqno,
2095  item.entry.mobility.sticky);
2096  ext.communities.push_back(mm.GetExtCommunityValue());
2097  } else if (item.entry.sequence_number) {
2098  MacMobility mm(item.entry.sequence_number);
2099  ext.communities.push_back(mm.GetExtCommunityValue());
2100  }
2101 
2102  ETree etree(item.entry.etree_leaf);
2103  ext.communities.push_back(etree.GetExtCommunityValue());
2104 
2105  if (!ext.communities.empty())
2106  attrs.push_back(&ext);
2107  if (!largecomm.communities.empty())
2108  attrs.push_back(&largecomm);
2109 
2110  PmsiTunnelSpec pmsi_spec;
2111  if (mac_addr.IsBroadcast()) {
2112  if (!item.entry.replicator_address.empty()) {
2113  IpAddress replicator_address;
2115  item.entry.replicator_address, &replicator_address)) {
2116  BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
2118  "Bad replicator address " <<
2119  item.entry.replicator_address <<
2120  " for enet route " << evpn_prefix.ToXmppIdString());
2121  return false;
2122  }
2123  pmsi_spec.tunnel_type =
2126  pmsi_spec.SetIdentifier(replicator_address.to_v4());
2127  } else {
2129  if (item.entry.assisted_replication_supported) {
2132  }
2133  if (!item.entry.edge_replication_not_supported) {
2134  pmsi_spec.tunnel_flags |=
2136  }
2137  pmsi_spec.SetIdentifier(nh_address.to_v4());
2138  }
2139  ExtCommunity ext_comm(bgp_server_->extcomm_db(), ext);
2140  pmsi_spec.SetLabel(label, &ext_comm);
2141  attrs.push_back(&pmsi_spec);
2142  }
2143 
2144  BgpAttrPtr attr = bgp_server_->attr_db()->Locate(attrs);
2145 
2146  req.data.reset(new EvpnTable::RequestData(
2147  attr, flags, label, l3_label, subscription_gen_id));
2148  stats_[RX].reach++;
2149  } else {
2151  stats_[RX].unreach++;
2152  }
2153 
2154  // Defer all requests till subscribe is processed.
2155  if (subscribe_pending) {
2156  DBRequest *request_entry = new DBRequest();
2157  request_entry->Swap(&req);
2158  string table_name =
2160  defer_q_.insert(make_pair(
2161  make_pair(vrf_name, table_name), request_entry));
2162  return true;
2163  }
2164 
2165  assert(table);
2166  BGP_LOG_PEER_INSTANCE(Peer(), vrf_name,
2167  SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
2168  "Enet route " << evpn_prefix.ToXmppIdString() <<
2169  " with next-hop " << nh_address <<
2170  " label " << label << " l3-label " << l3_label <<
2171  " enqueued for " << (add_change ? "add/change" : "delete"));
2172  table->Enqueue(&req);
2173  return true;
2174 }
2175 
2176 void BgpXmppChannel::DequeueRequest(const string &table_name,
2177  DBRequest *request) {
2178  unique_ptr<DBRequest> ptr(request);
2179 
2180  BgpTable *table = static_cast<BgpTable *>
2181  (bgp_server_->database()->FindTable(table_name));
2182  if (table == NULL || table->IsDeleted()) {
2183  return;
2184  }
2185 
2187  if (mgr) {
2188  int instance_id = -1;
2189  uint64_t subscription_gen_id = 0;
2190  bool is_registered = mgr->GetRegistrationInfo(peer_.get(), table,
2191  &instance_id, &subscription_gen_id);
2192  if (!is_registered) {
2193  BGP_LOG_PEER_WARNING(Membership, Peer(),
2195  "Not subscribed to table " << table->name());
2196  return;
2197  }
2198  if (ptr->oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
2199  ((BgpTable::RequestData *)ptr->data.get())
2200  ->set_subscription_gen_id(subscription_gen_id);
2201  }
2202  }
2203 
2204  table->Enqueue(ptr.get());
2205 }
2206 
2208  peer_->Close(true);
2209  return true;
2210 }
2211 
2213  const TableMembershipRequestState *tmr_state) {
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, "RegisterTable deferred "
2218  "from :" << line);
2219  return;
2220  }
2221 
2223  BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
2225  "Subscribe to table " << table->name() <<
2226  (tmr_state->no_ribout ? " (no ribout)" : "") <<
2227  " with id " << tmr_state->instance_id);
2228  if (tmr_state->no_ribout) {
2229  mgr->RegisterRibIn(peer_.get(), table);
2230  mgr->SetRegistrationInfo(peer_.get(), table, tmr_state->instance_id,
2234  } else {
2235  mgr->Register(peer_.get(), table, bgp_policy_, tmr_state->instance_id);
2237  }
2238 
2239  // If EndOfRib Send timer is running, cancel it and reschedule it after all
2240  // outstanding membership registrations are complete.
2241  if (eor_send_timer_->running())
2243 }
2244 
2246  // Defer if Membership manager is in use (by close manager).
2247  if (close_manager_->IsMembershipInUse()) {
2248  BGP_LOG_PEER_TABLE(Peer(), SandeshLevel::SYS_DEBUG,
2249  BGP_LOG_FLAG_ALL, table, "UnregisterTable deferred "
2250  "from :" << line);
2251  return;
2252  }
2253 
2255  BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
2257  "Unsubscribe to table " << table->name());
2258  mgr->Unregister(peer_.get(), table);
2260 }
2261 
2262 #define RegisterTable(table, tmr_state) \
2263  RegisterTable(__LINE__, table, tmr_state)
2264 #define UnregisterTable(table) UnregisterTable(__LINE__, table)
2265 
2266 // Process all pending membership requests of various tables.
2268  assert(!close_manager_->IsMembershipInUse());
2269  BOOST_FOREACH(TableMembershipRequestMap::value_type &entry,
2271  BgpTable *table = static_cast<BgpTable *>(
2272  bgp_server_->database()->FindTable(entry.first));
2273  const TableMembershipRequestState &tmr_state = entry.second;
2274  if (tmr_state.current_req == SUBSCRIBE) {
2275  RegisterTable(table, &tmr_state);
2276  } else {
2277  assert(tmr_state.current_req == UNSUBSCRIBE);
2278  UnregisterTable(table);
2279  }
2280  }
2281 }
2282 
2284  return table_membership_request_map_.size();
2285 }
2286 
2288  if (close_manager_->IsMembershipInUse()) {
2289  close_manager_->MembershipRequestCallback();
2290  return true;
2291  }
2292 
2293  TableMembershipRequestState *tmr_state =
2294  GetTableMembershipState(table_name);
2295  if (!tmr_state) {
2296  BGP_LOG_PEER_INSTANCE_CRITICAL(Peer(), table_name,
2298  "Table not in subscribe/unsubscribe request queue");
2299  assert(false);
2300  }
2301 
2302  if (tmr_state->current_req == SUBSCRIBE) {
2303  BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
2305  "Subscribe to table " << table_name << " completed");
2307  } else {
2308  BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
2310  "Unsubscribe to table " << table_name << " completed");
2312  }
2313 
2314  if (defer_peer_close_) {
2315  DeleteTableMembershipState(table_name);
2317  return true;
2318  defer_peer_close_ = false;
2319  ResumeClose();
2320  } else {
2321  ProcessMembershipResponse(table_name, tmr_state);
2322  }
2323 
2328 
2329  // Restart EndOfRib send if necessary.
2331 
2332  // If Close manager is waiting to use membership, try now.
2333  if (close_manager_->IsMembershipInWait())
2334  close_manager_->MembershipRequest();
2335 
2336  return true;
2337 }
2338 
2340  TableMembershipRequestState *tmr_state) {
2341  BgpTable *table = static_cast<BgpTable *>
2342  (bgp_server_->database()->FindTable(table_name));
2343  if (!table) {
2344  DeleteTableMembershipState(table_name);
2345  return true;
2346  }
2348 
2349  if ((tmr_state->current_req == UNSUBSCRIBE) &&
2350  (tmr_state->pending_req == SUBSCRIBE)) {
2351  // Process pending subscribe now that unsubscribe has completed.
2352  tmr_state->current_req = SUBSCRIBE;
2353  RegisterTable(table, tmr_state);
2354  return true;
2355  } else if ((tmr_state->current_req == SUBSCRIBE) &&
2356  (tmr_state->pending_req == UNSUBSCRIBE)) {
2357  // Process pending unsubscribe now that subscribe has completed.
2358  tmr_state->current_req = UNSUBSCRIBE;
2359  UnregisterTable(table);
2360  return true;
2361  } else if ((tmr_state->current_req == SUBSCRIBE) &&
2362  (tmr_state->pending_req == SUBSCRIBE) &&
2363  (mgr->IsRibOutRegistered(peer_.get(), table) == tmr_state->no_ribout)) {
2364  // Trigger an unsubscribe so that we can subsequently subscribe with
2365  // the updated value of no_ribout.
2366  tmr_state->current_req = UNSUBSCRIBE;
2367  UnregisterTable(table);
2368  return true;
2369  }
2370 
2371  string vrf_name = table->routing_instance()->name();
2372  VrfTableName vrf_n_table = make_pair(vrf_name, table->name());
2373 
2374  if (tmr_state->pending_req == UNSUBSCRIBE) {
2375  if (!GetInstanceMembershipState(vrf_name))
2376  assert(defer_q_.count(vrf_n_table) == 0);
2377  DeleteTableMembershipState(table_name);
2378  return true;
2379  } else if (tmr_state->pending_req == SUBSCRIBE) {
2380  mgr->SetRegistrationInfo(peer_.get(), table, tmr_state->instance_id,
2382  DeleteTableMembershipState(table_name);
2383  }
2384 
2385  for (DeferQ::iterator it = defer_q_.find(vrf_n_table);
2386  it != defer_q_.end() && it->first.second == table->name(); ++it) {
2387  DequeueRequest(table->name(), it->second);
2388  }
2389 
2390  // Erase all elements for the table
2391  defer_q_.erase(vrf_n_table);
2392 
2393  return true;
2394 }
2395 
2398 }
2399 
2400 void BgpXmppChannel::FillCloseInfo(BgpNeighborResp *resp) const {
2401  close_manager_->FillCloseInfo(resp);
2402 }
2403 
2404 void BgpXmppChannel::FillInstanceMembershipInfo(BgpNeighborResp *resp) const {
2405  vector<BgpNeighborRoutingInstance> instance_list;
2406  BOOST_FOREACH(const SubscribedRoutingInstanceList::value_type &entry,
2408  BgpNeighborRoutingInstance instance;
2409  instance.set_name(entry.first->name());
2410  if (entry.second.IsLlgrStale()) {
2411  instance.set_state("subscribed-llgr-stale");
2412  } else if (entry.second.IsGrStale()) {
2413  instance.set_state("subscribed-gr-stale");
2414  } else {
2415  instance.set_state("subscribed");
2416  }
2417  instance.set_index(entry.second.index);
2418  rtarget_manager_->FillInfo(&instance, entry.second.targets);
2419  instance_list.push_back(instance);
2420  }
2421  BOOST_FOREACH(const InstanceMembershipRequestMap::value_type &entry,
2423  const InstanceMembershipRequestState &imr_state = entry.second;
2424  BgpNeighborRoutingInstance instance;
2425  instance.set_name(entry.first);
2426  instance.set_state("pending");
2427  instance.set_index(imr_state.instance_id);
2428  instance_list.push_back(instance);
2429  }
2430  resp->set_routing_instances(instance_list);
2431 }
2432 
2433 void BgpXmppChannel::FillTableMembershipInfo(BgpNeighborResp *resp) const {
2434  vector<BgpNeighborRoutingTable> old_table_list = resp->get_routing_tables();
2435  set<string> old_table_set;
2436  vector<BgpNeighborRoutingTable> new_table_list;
2437 
2438  BOOST_FOREACH(const BgpNeighborRoutingTable &table, old_table_list) {
2439  old_table_set.insert(table.get_name());
2440  if (!GetTableMembershipState(table.get_name()))
2441  new_table_list.push_back(table);
2442  }
2443 
2444  BOOST_FOREACH(const TableMembershipRequestMap::value_type &entry,
2446  BgpNeighborRoutingTable table;
2447  table.set_name(entry.first);
2448  if (old_table_set.find(entry.first) != old_table_set.end())
2449  table.set_current_state("subscribed");
2450  const TableMembershipRequestState &tmr_state = entry.second;
2451  if (tmr_state.current_req == SUBSCRIBE) {
2452  table.set_current_request("subscribe");
2453  } else {
2454  table.set_current_request("unsubscribe");
2455  }
2456  if (tmr_state.pending_req == SUBSCRIBE) {
2457  table.set_pending_request("subscribe");
2458  } else {
2459  table.set_pending_request("unsubscribe");
2460  }
2461  new_table_list.push_back(table);
2462  }
2463  resp->set_routing_tables(new_table_list);
2464 }
2465 
2466 //
2467 // Erase all defer_q_ elements with the given (vrf, table).
2468 //
2469 void BgpXmppChannel::FlushDeferQ(string vrf_name, string table_name) {
2470  for (DeferQ::iterator it =
2471  defer_q_.find(make_pair(vrf_name, table_name)), itnext;
2472  (it != defer_q_.end() && it->first.second == table_name);
2473  it = itnext) {
2474  itnext = it;
2475  itnext++;
2476  delete it->second;
2477  defer_q_.erase(it);
2478  }
2479 }
2480 
2481 //
2482 // Erase all defer_q_ elements for all tables for the given vrf.
2483 //
2484 void BgpXmppChannel::FlushDeferQ(string vrf_name) {
2485  for (DeferQ::iterator it =
2486  defer_q_.lower_bound(make_pair(vrf_name, string())), itnext;
2487  (it != defer_q_.end() && it->first.first == vrf_name);
2488  it = itnext) {
2489  itnext = it;
2490  itnext++;
2491  delete it->second;
2492  defer_q_.erase(it);
2493  }
2494 }
2495 
2496 // Mark all current subscriptions as 'stale'. This is called when peer close
2497 // process is initiated by BgpXmppChannel via PeerCloseManager.
2499  CHECK_CONCURRENCY(peer_close_->GetTaskName());
2500  BOOST_FOREACH(SubscribedRoutingInstanceList::value_type &entry,
2502  entry.second.SetGrStale();
2503  rtarget_manager_->UpdateRouteTargetRouteFlag(entry.first,
2504  entry.second.targets, BgpPath::Stale);
2505  }
2506 }
2507 
2508 // Mark all current subscriptions as 'llgr_stale'.
2510  CHECK_CONCURRENCY(peer_close_->GetTaskName());
2511  BOOST_FOREACH(SubscribedRoutingInstanceList::value_type &entry,
2513  assert(entry.second.IsGrStale());
2514  entry.second.SetLlgrStale();
2515  rtarget_manager_->UpdateRouteTargetRouteFlag(entry.first,
2516  entry.second.targets, BgpPath::Stale | BgpPath::LlgrStale);
2517  }
2518 }
2519 
2520 // Sweep all current subscriptions which are still marked as 'stale'.
2522  CHECK_CONCURRENCY(peer_close_->GetTaskName());
2523  for (SubscribedRoutingInstanceList::iterator i = routing_instances_.begin();
2524  i != routing_instances_.end();) {
2525  if (i->second.IsGrStale()) {
2526  string name = i->first->name();
2527 
2528  // Increment the iterator first as we expect the entry to be
2529  // soon removed.
2530  i++;
2531  BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
2533  "Instance subscription " << name <<
2534  " is still stale and hence unsubscribed");
2535  ProcessSubscriptionRequest(name, NULL, false);
2536  } else {
2537  i++;
2538  }
2539  }
2540 }
2541 
2542 // Clear staled subscription state as new subscription has been received.
2544  SubscriptionState *sub_state) {
2545  if (!sub_state->IsGrStale())
2546  return;
2547 
2548  BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
2550  "Instance subscription " << rt_instance->name() <<
2551  " stale flag is cleared");
2552  sub_state->ClearStale();
2553  rtarget_manager_->Stale(sub_state->targets);
2554 }
2555 
2557  int index) {
2558  SubscriptionState state(rt_instance->GetImportList(), index);
2559  pair<SubscribedRoutingInstanceList::iterator, bool> ret =
2560  routing_instances_.insert(pair<RoutingInstance *, SubscriptionState> (
2561  rt_instance, state));
2562 
2563  // During GR, we expect duplicate subscription requests. Clear stale
2564  // state, as agent did re-subscribe after restart.
2565  if (!ret.second) {
2566  ClearStaledSubscription(rt_instance, &ret.first->second);
2567  } else {
2568  rtarget_manager_->PublishRTargetRoute(rt_instance, true);
2569  }
2570 }
2571 
2573  routing_instances_.erase(rt_instance);
2574 }
2575 
2577  RoutingInstance *rt_instance) {
2578  SubscribedRoutingInstanceList::iterator loc =
2579  routing_instances_.find(rt_instance);
2580  return (loc != routing_instances_.end() ? &loc->second : NULL);
2581 }
2582 
2584  RoutingInstance *rt_instance) const {
2585  SubscribedRoutingInstanceList::const_iterator loc =
2586  routing_instances_.find(rt_instance);
2587  return (loc != routing_instances_.end() ? &loc->second : NULL);
2588 }
2589 
2591  const InstanceMembershipRequestState &imr_state) {
2592  int instance_id = imr_state.instance_id;
2593  bool no_ribout = imr_state.no_ribout;
2594  AddSubscriptionState(instance, instance_id);
2595  RoutingInstance::RouteTableList const rt_list = instance->GetTables();
2596  for (RoutingInstance::RouteTableList::const_iterator it = rt_list.begin();
2597  it != rt_list.end(); ++it) {
2598  BgpTable *table = it->second;
2599  if (table->IsVpnTable() || table->family() == Address::RTARGET)
2600  continue;
2601 
2602  TableMembershipRequestState tmr_state(
2603  SUBSCRIBE, instance_id, no_ribout);
2604  AddTableMembershipState(table->name(), tmr_state);
2605  RegisterTable(table, &tmr_state);
2606  }
2607 }
2608 
2610  string vrf_name, const XmppStanza::XmppMessageIq *iq,
2611  bool add_change) {
2612  int instance_id = -1;
2613  bool no_ribout = false;
2614 
2615  if (add_change) {
2616  XmlPugi *pugi = reinterpret_cast<XmlPugi *>(iq->dom.get());
2617  xml_node options = pugi->FindNode("options");
2618  for (xml_node node = options.first_child(); node;
2619  node = node.next_sibling()) {
2620  if (strcmp(node.name(), "instance-id") == 0) {
2621  instance_id = node.text().as_int();
2622  }
2623  if (strcmp(node.name(), "no-ribout") == 0) {
2624  no_ribout = node.text().as_bool();
2625  }
2626  }
2627  }
2628 
2630  assert(instance_mgr);
2631  RoutingInstance *rt_instance = instance_mgr->GetRoutingInstance(vrf_name);
2632  if (rt_instance == NULL) {
2633  BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_INFO,
2635  "Routing instance " << vrf_name <<
2636  " not found when processing " <<
2637  (add_change ? "subscribe" : "unsubscribe"));
2638  if (add_change) {
2639  if (GetInstanceMembershipState(vrf_name)) {
2640  BGP_LOG_PEER_WARNING(Membership, Peer(),
2642  "Duplicate subscribe for routing instance " <<
2643  vrf_name << ", triggering close");
2644  channel_->Close();
2645  } else {
2646  AddInstanceMembershipState(vrf_name,
2647  InstanceMembershipRequestState(instance_id, no_ribout));
2649  }
2650  } else {
2651  if (DeleteInstanceMembershipState(vrf_name)) {
2652  FlushDeferQ(vrf_name);
2654  } else {
2655  BGP_LOG_PEER_WARNING(Membership, Peer(),
2657  "Spurious unsubscribe for routing instance " <<
2658  vrf_name << ", triggering close");
2659  channel_->Close();
2660  }
2661  }
2662  return;
2663  } else if (rt_instance->deleted()) {
2664  BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
2666  "Routing instance " << vrf_name <<
2667  " is being deleted when processing " <<
2668  (add_change ? "subscribe" : "unsubscribe"));
2669  if (add_change) {
2670  if (GetInstanceMembershipState(vrf_name)) {
2671  BGP_LOG_PEER_WARNING(Membership, Peer(),
2673  "Duplicate subscribe for routing instance " <<
2674  vrf_name << ", triggering close");
2675  channel_->Close();
2676  } else if (GetSubscriptionState(rt_instance)) {
2677  BGP_LOG_PEER_WARNING(Membership, Peer(),
2679  "Duplicate subscribe for routing instance " <<
2680  vrf_name << ", triggering close");
2681  channel_->Close();
2682  } else {
2683  AddInstanceMembershipState(vrf_name,
2684  InstanceMembershipRequestState(instance_id, no_ribout));
2686  }
2687  return;
2688  } else {
2689  // If instance is being deleted and agent is trying to unsubscribe
2690  // we need to process the unsubscribe if vrf is not in the request
2691  // map. This would be the normal case where we wait for agent to
2692  // unsubscribe in order to remove routes added by it.
2693  if (DeleteInstanceMembershipState(vrf_name)) {
2694  FlushDeferQ(vrf_name);
2696  return;
2697  } else if (!GetSubscriptionState(rt_instance)) {
2698  BGP_LOG_PEER_WARNING(Membership, Peer(),
2700  "Spurious unsubscribe for routing instance " <<
2701  vrf_name << ", triggering close");
2702  channel_->Close();
2703  return;
2704  }
2706  }
2707  } else {
2708  if (add_change) {
2709  const SubscriptionState *sub_state =
2710  GetSubscriptionState(rt_instance);
2711  if (sub_state) {
2712  if (!close_manager_->IsCloseInProgress()) {
2713  BGP_LOG_PEER_WARNING(Membership, Peer(),
2715  "Duplicate subscribe for routing instance " <<
2716  vrf_name << ", triggering close");
2717  channel_->Close();
2718  return;
2719  }
2720  if (!sub_state->IsGrStale()) {
2721  BGP_LOG_PEER_WARNING(Membership, Peer(),
2723  "Duplicate subscribe for routing instance " <<
2724  vrf_name << " under GR, triggering close");
2725  channel_->Close();
2726  return;
2727  }
2728  }
2730  } else {
2731  if (!GetSubscriptionState(rt_instance)) {
2732  BGP_LOG_PEER_WARNING(Membership, Peer(),
2734  "Spurious unsubscribe for routing instance " <<
2735  vrf_name << ", triggering close");
2736  channel_->Close();
2737  return;
2738  }
2740  }
2741  }
2742 
2743  if (add_change) {
2744  AddSubscriptionState(rt_instance, instance_id);
2745  } else {
2746  rtarget_manager_->PublishRTargetRoute(rt_instance, false);
2747  DeleteSubscriptionState(rt_instance);
2748  }
2749 
2750  RoutingInstance::RouteTableList const rt_list = rt_instance->GetTables();
2751  for (RoutingInstance::RouteTableList::const_iterator it = rt_list.begin();
2752  it != rt_list.end(); ++it) {
2753  BgpTable *table = it->second;
2754  if (table->IsVpnTable() || table->family() == Address::RTARGET)
2755  continue;
2756 
2757  if (add_change) {
2758  TableMembershipRequestState *tmr_state =
2759  GetTableMembershipState(table->name());
2760  if (!tmr_state) {
2761  TableMembershipRequestState tmp_tmr_state(
2762  SUBSCRIBE, instance_id, no_ribout);
2763  AddTableMembershipState(table->name(), tmp_tmr_state);
2764  RegisterTable(table, &tmp_tmr_state);
2765  } else {
2766  tmr_state->instance_id = instance_id;
2767  tmr_state->pending_req = SUBSCRIBE;
2768  tmr_state->no_ribout = no_ribout;
2769  }
2770  } else {
2771  if (defer_q_.count(make_pair(vrf_name, table->name()))) {
2772  BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
2774  "Flush deferred route requests for table " <<
2775  table->name() << " on unsubscribe");
2776  FlushDeferQ(vrf_name, table->name());
2777  }
2778 
2779  // Erase all elements for the table.
2780 
2781  TableMembershipRequestState *tmr_state =
2782  GetTableMembershipState(table->name());
2783  if (!tmr_state) {
2784  AddTableMembershipState(table->name(),
2786  UNSUBSCRIBE, instance_id, no_ribout));
2787  UnregisterTable(table);
2788  } else {
2789  tmr_state->instance_id = -1;
2790  tmr_state->pending_req = UNSUBSCRIBE;
2791  tmr_state->no_ribout = false;
2792  }
2793  }
2794  }
2795 }
2796 
2800  eor_sent_ = false;
2801 }
2802 
2805  close_manager_->ProcessEORMarkerReceived(family);
2806 }
2807 
2809  string error_message) {
2811  "Timer error: " << error_name << " " << error_message);
2812 }
2813 
2815  if (!peer_->IsReady())
2816  return false;
2817 
2818  uint32_t timeout = manager() && manager()->xmpp_server() ?
2821 
2822  // If max timeout has not reached yet, check if we can exit GR sooner by
2823  // looking at the activity in the channel.
2824  if (UTCTimestamp() - eor_receive_timer_start_time_ < timeout) {
2825 
2826  // If there is some send or receive activity in the channel in last few
2827  // seconds, delay EoR receive event.
2831  BGP_LOG_PEER(Message, Peer(), SandeshLevel::SYS_INFO,
2833  "EndOfRib Receive timer rescheduled to fire after " <<
2834  kEndOfRibSendRetryTime << " second(s)");
2835  return true;
2836  }
2837  }
2838 
2839  BGP_LOG_PEER(Message, Peer(), SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
2840  BGP_PEER_DIR_IN, "EndOfRib Receive timer expired");
2842  return false;
2843 }
2844 
2846  return manager() && manager()->xmpp_server() ?
2849 }
2850 
2852  if (!peer_->IsReady())
2853  return false;
2854 
2855  // If max timeout has not reached yet, check if we can exit GR sooner by
2856  // looking at the activity in the channel.
2858 
2859  // If there is some send or receive activity in the channel in last few
2860  // seconds, delay EoR send event.
2863  manager()->bgp_server()->IsServerStartingUp()) {
2865  BGP_LOG_PEER(Message, Peer(), SandeshLevel::SYS_INFO,
2867  "EndOfRib Send timer rescheduled to fire after " <<
2868  kEndOfRibSendRetryTime << " second(s)");
2869  return true;
2870  }
2871  }
2872 
2873  SendEndOfRIB();
2874  return false;
2875 }
2876 
2878  uint32_t timeout = manager() && manager()->xmpp_server() ?
2883 
2884  BGP_LOG_PEER(Message, Peer(), SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
2885  BGP_PEER_DIR_IN, "EndOfRib Receive timer scheduled to fire after " <<
2886  timeout << " second(s)");
2887  eor_receive_timer_->Start(timeout * 1000,
2888  boost::bind(&BgpXmppChannel::EndOfRibReceiveTimerExpired, this),
2889  boost::bind(&BgpXmppChannel::EndOfRibTimerErrorHandler, this, _1, _2));
2890 }
2891 
2893  if (eor_sent_)
2894  return;
2895 
2896  // If socket is blocked, then wait for it to get unblocked first.
2897  if (!peer_->send_ready())
2898  return;
2899 
2900  // If there is any outstanding subscribe pending, wait for its completion.
2903  return;
2904 
2907 
2908  BGP_LOG_PEER(Message, Peer(), SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
2909  BGP_PEER_DIR_OUT, "EndOfRib Send timer scheduled to fire after " <<
2910  kEndOfRibSendRetryTime << " second(s)");
2912  boost::bind(&BgpXmppChannel::EndOfRibSendTimerExpired, this),
2913  boost::bind(&BgpXmppChannel::EndOfRibTimerErrorHandler, this, _1, _2));
2914 }
2915 
2916 /*
2917  * Empty items list constitute eor marker.
2918  */
2921  eor_sent_ = true;
2922 
2923  string msg;
2924  msg += "\n<message from=\"";
2926  msg += "\" to=\"";
2927  msg += peer_->ToString();
2928  msg += "/";
2929  msg += XmppInit::kBgpPeer;
2930  msg += "\">";
2931  msg += "\n\t<event xmlns=\"http://jabber.org/protocol/pubsub\">";
2932  msg = (msg + "\n<items node=\"") + XmppInit::kEndOfRibMarker +
2933  "\"></items>";
2934  msg += "\n\t</event>\n</message>\n";
2935 
2936  if (channel_->connection())
2937  channel_->connection()->Send((const uint8_t *) msg.data(), msg.size());
2938 
2939  stats_[TX].end_of_rib++;
2940  BGP_LOG_PEER(Message, Peer(), SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
2941  BGP_PEER_DIR_OUT, "EndOfRib marker sent");
2942 }
2943 
2944 // Process any associated primary instance-id.
2946  bool expect_prefix_len) const {
2947  if (s.empty())
2948  return 0;
2949  char *str = const_cast<char *>(s.c_str());
2950  char *saveptr, *token;
2951  token = strtok_r(str, "/", &saveptr); // Get afi
2952  if (!token || !saveptr)
2953  return 0;
2954  token = strtok_r(NULL, "/", &saveptr); // Get safi
2955  if (!token || !saveptr)
2956  return 0;
2957  token = strtok_r(NULL, "/", &saveptr); // vrf name
2958  if (!token || !saveptr)
2959  return 0;
2960  token = strtok_r(NULL, "/", &saveptr); // address
2961  if (!token || !saveptr)
2962  return 0;
2963  if (expect_prefix_len) {
2964  token = strtok_r(NULL, "/", &saveptr); // prefix-length
2965  if (!token || !saveptr)
2966  return 0;
2967  }
2968  token = strtok_r(NULL, "/", &saveptr); // primary instance-id
2969  if (!token)
2970  return 0;
2971  return strtoul(token, NULL, 0);
2972 }
2973 
2975  CHECK_CONCURRENCY("xmpp::StateMachine");
2976 
2977  // Bail if the connection is being deleted. It's not safe to assert
2978  // because the Delete method can be called from the main thread.
2980  return;
2981 
2982  // Make sure that peer is not set for closure already.
2983  assert(!defer_peer_close_);
2984  assert(!peer_deleted());
2985 
2986  if (msg->type == XmppStanza::IQ_STANZA) {
2987  const XmppStanza::XmppMessageIq *iq =
2988  static_cast<const XmppStanza::XmppMessageIq *>(msg);
2989  if (iq->iq_type.compare("set") == 0) {
2990  if (iq->action.compare("subscribe") == 0) {
2991  ProcessSubscriptionRequest(iq->node, iq, true);
2992  } else if (iq->action.compare("unsubscribe") == 0) {
2993  ProcessSubscriptionRequest(iq->node, iq, false);
2994  } else if (iq->action.compare("publish") == 0) {
2995  XmlBase *impl = msg->dom.get();
2996  stats_[RX].rt_updates++;
2997  XmlPugi *pugi = reinterpret_cast<XmlPugi *>(impl);
2998  xml_node item = pugi->FindNode("item");
2999 
3000  // Empty items-list can be considered as EOR Marker for all afis
3001  if (item == 0) {
3002  BGP_LOG_PEER(Message, Peer(), SandeshLevel::SYS_INFO,
3004  "EndOfRib marker received");
3005  stats_[RX].end_of_rib++;
3007  return;
3008  }
3009  for (; item; item = item.next_sibling()) {
3010  if (strcmp(item.name(), "item") != 0) continue;
3011 
3012  string id(iq->as_node.c_str());
3013  char *str = const_cast<char *>(id.c_str());
3014  char *saveptr;
3015  char *af = strtok_r(str, "/", &saveptr);
3016  char *safi = strtok_r(NULL, "/", &saveptr);
3017 
3018  if (atoi(af) == BgpAf::IPv4 &&
3019  ((atoi(safi) == BgpAf::Unicast) ||
3020  (atoi(safi) == BgpAf::Mpls))) {
3021  ProcessItem(iq->node, item, iq->is_as_node,
3022  GetPrimaryInstanceID(iq->as_node, true));
3023  } else if (atoi(af) == BgpAf::IPv6 &&
3024  atoi(safi) == BgpAf::Unicast) {
3025  ProcessInet6Item(iq->node, item, iq->is_as_node);
3026  } else if (atoi(af) == BgpAf::IPv4 &&
3027  atoi(safi) == BgpAf::Mcast) {
3028  ProcessMcastItem(iq->node, item, iq->is_as_node);
3029  } else if (atoi(af) == BgpAf::IPv4 &&
3030  atoi(safi) == BgpAf::MVpn) {
3031  ProcessMvpnItem(iq->node, item, iq->is_as_node);
3032  } else if (atoi(af) == BgpAf::L2Vpn &&
3033  atoi(safi) == BgpAf::Enet) {
3034  ProcessEnetItem(iq->node, item, iq->is_as_node);
3035  }
3036  }
3037  }
3038  }
3039  }
3040 }
3041 
3043  if (!channel->deleted()) {
3044  channel->set_deleted(true);
3045  delete channel;
3046  }
3047  return true;
3048 }
3049 
3050 // BgpXmppChannelManager routines.
3052  BgpServer *server)
3053  : xmpp_server_(xmpp_server),
3054  bgp_server_(server),
3055  queue_(TaskScheduler::GetInstance()->GetTaskId("bgp::Config"), 0,
3056  boost::bind(&BgpXmppChannelManager::DeleteChannel, this, _1)),
3057  id_(-1),
3058  asn_listener_id_(-1),
3059  identifier_listener_id_(-1),
3060  dscp_listener_id_(-1) {
3061  // Initialize the gen id counter
3063  deleting_count_ = 0;
3064 
3065  if (xmpp_server)
3068  boost::bind(&BgpXmppChannelManager::IsReadyForDeletion, this));
3069  if (xmpp_server) {
3072  this, _1, _2));
3073  }
3075  server->RegisterAdminDownCallback(boost::bind(
3078  server->RegisterASNUpdateCallback(boost::bind(
3081  server->RegisterIdentifierUpdateCallback(boost::bind(
3084  server->RegisterDSCPUpdateCallback(boost::bind(
3086 
3089  this, _1, _2));
3090 }
3091 
3093  assert(channel_map_.empty());
3094  assert(channel_name_map_.empty());
3095  assert(deleting_count_ == 0);
3096  if (xmpp_server_) {
3098  }
3099 
3100  queue_.Shutdown();
3105 }
3106 
3108  return bgp_server_->IsReadyForDeletion();
3109 }
3110 
3112  queue_.set_disable(disabled);
3113 }
3114 
3116  return queue_.Length();
3117 }
3118 
3121 }
3122 
3124  xmpp_server_->SetDscpValue(dscp_value);
3125 }
3126 
3128  as_t old_local_asn) {
3129  CHECK_CONCURRENCY("bgp::Config");
3130  BOOST_FOREACH(XmppChannelMap::value_type &i, channel_map_) {
3131  i.second->rtarget_manager()->ASNUpdateCallback(old_asn, old_local_asn);
3132  }
3133  if (bgp_server_->autonomous_system() != old_asn) {
3135  }
3136 }
3137 
3139  Ip4Address old_identifier) {
3140  CHECK_CONCURRENCY("bgp::Config");
3142 }
3143 
3144 void BgpXmppChannelManager::RoutingInstanceCallback(string vrf_name, int op) {
3145  CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
3146  BOOST_FOREACH(XmppChannelMap::value_type &i, channel_map_) {
3147  i.second->RoutingInstanceCallback(vrf_name, op);
3148  }
3149 }
3150 
3152  std::scoped_lock lock(mutex_);
3153  BOOST_FOREACH(XmppChannelMap::value_type &i, channel_map_) {
3154  fn(i.second);
3155  }
3156 }
3157 
3159  const {
3160  std::scoped_lock lock(mutex_);
3161  BOOST_FOREACH(const XmppChannelMap::value_type &i, channel_map_) {
3162  fn(i.second);
3163  }
3164 }
3165 
3167  BOOST_FOREACH(XmppChannelMap::value_type &i, channel_map_) {
3168  if (i.second->ToString() == client) {
3169  return i.second;
3170  }
3171  }
3172  return NULL;
3173 }
3174 
3176  const XmppChannel *ch) {
3177  XmppChannelMap::iterator it = channel_map_.find(ch);
3178  if (it == channel_map_.end())
3179  return NULL;
3180  return it->second;
3181 }
3182 
3184  if (channel->connection() && !channel->connection()->IsActiveChannel()) {
3185  CHECK_CONCURRENCY("bgp::Config");
3186  }
3187  channel_map_.erase(channel);
3188  channel_name_map_.erase(channel->ToString());
3189 }
3190 
3192  CHECK_CONCURRENCY("xmpp::StateMachine");
3193  BgpXmppChannel *ch = new BgpXmppChannel(channel, bgp_server_, this);
3194 
3195  return ch;
3196 }
3197 
3199  xmps::PeerState state) {
3200  std::scoped_lock lock(mutex_);
3201 
3202  XmppChannelMap::iterator it = channel_map_.find(channel);
3203  BgpXmppChannel *bgp_xmpp_channel = NULL;
3204  if (state == xmps::READY) {
3205  if (it == channel_map_.end()) {
3206  bgp_xmpp_channel = CreateChannel(channel);
3207  channel_map_.insert(make_pair(channel, bgp_xmpp_channel));
3208  channel_name_map_.insert(
3209  make_pair(channel->ToString(), bgp_xmpp_channel));
3210  BGP_LOG_PEER(Message, bgp_xmpp_channel->Peer(),
3213  "Received XmppChannel up event");
3215  BGP_LOG_PEER(Message, bgp_xmpp_channel->Peer(),
3216  SandeshLevel::SYS_INFO, BGP_LOG_FLAG_SYSLOG,
3218  "No BGP configuration for self - closing channel");
3219  if (!getenv("CONTRAIL_CAT_FRAMEWORK"))
3220  channel->Close();
3221  }
3222  if (bgp_server_->admin_down()) {
3223  BGP_LOG_PEER(Message, bgp_xmpp_channel->Peer(),
3224  SandeshLevel::SYS_INFO, BGP_LOG_FLAG_SYSLOG,
3226  "BGP is administratively down - closing channel");
3227  channel->Close();
3228  }
3229  } else {
3230  bgp_xmpp_channel = (*it).second;
3231  if (bgp_xmpp_channel->peer_deleted())
3232  return;
3233 
3234  // Gracefully close the channel if GR closure is in progress.
3235  // This can happen if GR timers fire just after session comes
3236  // back up.
3237  if (bgp_xmpp_channel->close_manager()->IsCloseInProgress() &&
3238  !bgp_xmpp_channel->close_manager()->IsInGRTimerWaitState()) {
3239  BGP_LOG_PEER(Message, bgp_xmpp_channel->Peer(),
3240  SandeshLevel::SYS_INFO, BGP_LOG_FLAG_SYSLOG,
3242  "Graceful Closure in progress - Closing channel");
3243  channel->Close();
3244  }
3245  channel->RegisterReceive(xmps::BGP,
3246  boost::bind(&BgpXmppChannel::ReceiveUpdate, bgp_xmpp_channel,
3247  _1));
3248  }
3249 
3250  bgp_xmpp_channel->eor_sent_ = false;
3251  bgp_xmpp_channel->StartEndOfRibReceiveTimer();
3252  bgp_xmpp_channel->ResetEndOfRibSendState();
3253  } else if (state == xmps::NOT_READY) {
3254  if (it != channel_map_.end()) {
3255  bgp_xmpp_channel = (*it).second;
3256  BGP_LOG_PEER(Message, bgp_xmpp_channel->Peer(),
3259  "Received XmppChannel down event");
3260 
3261  // Trigger closure of this channel
3262  bgp_xmpp_channel->Close();
3263  } else {
3264  ostringstream os;
3265  os << "Peer not found for " << channel->ToString() <<
3266  " on channel down event";
3268  }
3269  }
3270 }
3271 
3273  PeerStatsInfo stats;
3274  PeerStats::FillPeerDebugStats(channel->Peer()->peer_stats(), &stats);
3275 
3276  XmppPeerInfoData peer_info;
3277  peer_info.set_name(channel->Peer()->ToUVEKey());
3278  peer_info.set_peer_stats_info(stats);
3279  assert(!peer_info.get_name().empty());
3280  BGP_UVE_SEND(XMPPPeerInfo, peer_info);
3281 
3282  PeerStatsData peer_stats_data;
3283  peer_stats_data.set_name(channel->Peer()->ToUVEKey());
3284  peer_stats_data.set_encoding("XMPP");
3286  &peer_stats_data);
3287  assert(!peer_stats_data.get_name().empty());
3288  BGP_UVE_SEND2(PeerStatsUve, peer_stats_data, "ObjectXmppPeerInfo");
3289 }
3290 
3291 bool BgpXmppChannelManager::CollectStats(BgpRouterState *state, bool first)
3292  const {
3293  CHECK_CONCURRENCY("bgp::ShowCommand");
3294 
3295  VisitChannels(boost::bind(&BgpXmppChannelManager::FillPeerInfo, this, _1));
3296  bool change = false;
3297  uint32_t num_xmpp = count();
3298  if (first || num_xmpp != state->get_num_xmpp_peer()) {
3299  state->set_num_xmpp_peer(num_xmpp);
3300  change = true;
3301  }
3302 
3303  uint32_t num_up_xmpp = NumUpPeer();
3304  if (first || num_up_xmpp != state->get_num_up_xmpp_peer()) {
3305  state->set_num_up_xmpp_peer(num_up_xmpp);
3306  change = true;
3307  }
3308 
3309  uint32_t num_deleting_xmpp = deleting_count();
3310  if (first || num_deleting_xmpp != state->get_num_deleting_xmpp_peer()) {
3311  state->set_num_deleting_xmpp_peer(num_deleting_xmpp);
3312  change = true;
3313  }
3314 
3315  return change;
3316 }
3317 
3321 
3322  if (table_membership_requests()) {
3323  BGP_LOG_PEER(Event, peer_.get(), SandeshLevel::SYS_INFO,
3324  BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA, "Close procedure deferred");
3325  defer_peer_close_ = true;
3326  return;
3327  }
3328  peer_->Close(true);
3329 }
3330 
3331 //
3332 // Return connection's remote tcp endpoint if available
3333 //
3335  const XmppSession *session = GetSession();
3336  if (session) {
3337  return session->remote_endpoint();
3338  }
3339  return TcpSession::Endpoint();
3340 }
3341 
3342 //
3343 // Return connection's local tcp endpoint if available
3344 //
3346  const XmppSession *session = GetSession();
3347  if (session) {
3348  return session->local_endpoint();
3349  }
3350  return TcpSession::Endpoint();
3351 }
3352 
3353 //
3354 // Return connection's remote tcp endpoint string.
3355 //
3358  ostringstream oss;
3359  oss << endpoint;
3360  return oss.str();
3361 }
3362 
3363 //
3364 // Mark the XmppPeer as deleted.
3365 //
3367  peer_->SetPeerClosed(flag);
3368 }
3369 
3370 //
3371 // Return true if the XmppPeer is deleted.
3372 //
3374  return peer_->IsDeleted();
3375 }
3376 
3377 //
3378 // Return time stamp of when the XmppPeer delete was initiated.
3379 //
3381  return peer_->closed_at();
3382 }
3383 
3385  SubscribedRoutingInstanceList::const_iterator it =
3386  routing_instances_.find(instance);
3387  assert(it != routing_instances_.end());
3388  return it->second.IsGrStale();
3389 }
3390 
3392  SubscribedRoutingInstanceList::const_iterator it =
3393  routing_instances_.find(instance);
3394  assert(it != routing_instances_.end());
3395  return it->second.IsLlgrStale();
3396 }
3397 
3399  return routing_instances_.empty();
3400 }
3401 
3403  RoutingInstance *instance) const {
3404  SubscribedRoutingInstanceList::const_iterator it =
3405  routing_instances_.find(instance);
3406  assert(it != routing_instances_.end());
3407  return it->second.targets;
3408 }
boost::asio::ip::address IpAddress
Definition: address.h:13
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
std::vector< BgpAttribute * > BgpAttrSpec
Definition: bgp_attr.h:822
boost::intrusive_ptr< const BgpAttr > BgpAttrPtr
Definition: bgp_attr.h:997
#define AS2_MAX
Definition: bgp_common.h:24
uint32_t as_t
Definition: bgp_common.h:21
#define BGP_LOG_NOTICE(obj, flags,...)
Definition: bgp_log.h:73
#define BGP_LOG_FLAG_ALL
Definition: bgp_log.h:44
#define BGP_LOG_FLAG_SYSLOG
Definition: bgp_log.h:42
#define BGP_LOG_PEER(type, peer, level, flags, dir, arg)
Definition: bgp_log.h:159
#define BGP_LOG_PEER_INSTANCE_WARNING(peer, instance, flags, arg)
Definition: bgp_log.h:227
#define BGP_LOG_PEER_INSTANCE(peer, instance, level, flags, arg)
Definition: bgp_log.h:218
#define BGP_LOG_PEER_WARNING(type, peer, flags, dir, arg)
Definition: bgp_log.h:182
#define BGP_PEER_DIR_IN
Definition: bgp_log.h:139
#define BGP_LOG_PEER_TABLE(peer, level, flags, tbl, arg)
Definition: bgp_log.h:205
#define BGP_UVE_SEND2(type, object, arg)
Definition: bgp_log.h:52
#define BGP_PEER_DIR_NA
Definition: bgp_log.h:140
#define BGP_LOG_FLAG_TRACE
Definition: bgp_log.h:43
#define BGP_UVE_SEND(type, object)
Definition: bgp_log.h:46
#define BGP_LOG_PEER_CRITICAL(type, peer, flags, dir, arg)
Definition: bgp_log.h:194
#define BGP_LOG_PEER_INSTANCE_CRITICAL(peer, instance, dir, flags, arg)
Definition: bgp_log.h:237
#define BGP_PEER_DIR_OUT
Definition: bgp_log.h:138
static uint32_t GetMedFromLocalPref(uint32_t local_pref)
Family
Definition: address.h:24
@ EVPN
Definition: address.h:31
@ RTARGET
Definition: address.h:30
@ ERMVPN
Definition: address.h:32
@ INET6
Definition: address.h:27
@ MVPN
Definition: address.h:33
@ INETMPLS
Definition: address.h:34
@ UNSPEC
Definition: address.h:25
@ Enet
Definition: bgp_af.h:32
@ Unicast
Definition: bgp_af.h:25
@ MVpn
Definition: bgp_af.h:27
@ Mcast
Definition: bgp_af.h:31
@ Mpls
Definition: bgp_af.h:26
@ L2Vpn
Definition: bgp_af.h:21
@ IPv4
Definition: bgp_af.h:19
@ IPv6
Definition: bgp_af.h:20
static Address::Family AfiSafiToFamily(uint16_t afi, uint8_t safi)
Definition: bgp_af.cc:71
static const char * kMasterInstance
Definition: bgp_config.h:778
uint16_t rd_cluster_seed() const
Definition: bgp_config.h:670
static const int kEndOfRibTime
Definition: bgp_config.h:615
void SetRegistrationInfo(const IPeer *peer, const BgpTable *table, int instance_id, uint64_t subscription_gen_id)
void RegisterRibIn(IPeer *peer, BgpTable *table)
virtual void Unregister(IPeer *peer, BgpTable *table)
virtual void Register(IPeer *peer, BgpTable *table, const RibExportPolicy &policy, int instance_id=-1)
bool GetRegistrationInfo(const IPeer *peer, const BgpTable *table, int *instance_id=NULL, uint64_t *subscription_gen_id=NULL) const
bool IsRibOutRegistered(const IPeer *peer, const BgpTable *table) const
TypePtr Locate(Type *attr)
@ Stale
Definition: bgp_path.h:24
@ LlgrStale
Definition: bgp_path.h:30
@ CheckGlobalErmVpnRoute
Definition: bgp_path.h:33
@ ResolveNexthop
Definition: bgp_path.h:27
@ NoTunnelEncap
Definition: bgp_path.h:25
ExtCommunityDB * extcomm_db()
Definition: bgp_server.h: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:532
const bool IsDefault() const
const uint64_t GetExtCommunityValue() const
Definition: load_balance.h:120
const uint64_t GetExtCommunityValue() const
bool IsBroadcast() const
Definition: mac_address.cc:33
bool IsZero() const
Definition: mac_address.cc:29
static MacAddress FromString(const std::string &str, boost::system::error_code *error=NULL)
Definition: mac_address.cc:71
const uint64_t GetExtCommunityValue() const
Definition: mac_mobility.h:31
@ SourceTreeJoinRoute
Definition: mvpn_route.h:46
@ SourceActiveADRoute
Definition: mvpn_route.h:44
bool IsCloseInProgress() const
bool IsInGRTimerWaitState() const
static void FillPeerUpdateStats(const IPeerDebugStats *peer_stats, PeerStatsData *peer_stats_data)
Definition: peer_stats.cc:54
static void FillPeerDebugStats(const IPeerDebugStats *peer_stats, PeerStatsInfo *stats)
Definition: peer_stats.cc:64
static RouteDistinguisher kZeroRd
Definition: rd.h:14
const uint64_t GetExtCommunityValue() const
Definition: router_mac.h:29
RoutingInstance * GetRoutingInstance(const std::string &name)
void UnregisterInstanceOpCallback(int id)
int RegisterInstanceOpCallback(RoutingInstanceCb cb)
const std::string & name() const
bool deleted() const
static std::string GetTableName(std::string instance_name, Address::Family fmly)
std::map< std::string, BgpTable * > RouteTableList
RouteTableList & GetTables()
const RouteTargetList & GetImportList() const
std::set< RouteTarget > RouteTargetList
BgpTable * GetTable(Address::Family fmly)
static SandeshLevel::type LoggingUtLevel()
Definition: cpp/sandesh.h:224
const uint64_t GetExtCommunityValue() const
const uint64_t GetExtCommunityValue() const
const uint64_t GetExtCommunityValue() const
Represents a single BGP Large Community tag.
const std::vector< uint32_t > GetLargeCommunityValue() const
Returns the community value as a vector of 3 32-bit integers.
const uint64_t GetExtCommunityValue() const
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h: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