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