OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
bgp_membership.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include "bgp/bgp_membership.h"
6 
7 #include <boost/foreach.hpp>
8 
10 #include "base/task_trigger.h"
11 #include "bgp/bgp_export.h"
12 #include "bgp/bgp_log.h"
13 #include "bgp/bgp_peer_types.h"
14 #include "bgp/bgp_route.h"
15 #include "bgp/bgp_server.h"
16 #include "bgp/bgp_update_sender.h"
18 
19 using std::list;
20 using std::make_pair;
21 using std::string;
22 using std::vector;
23 
24 //
25 // Constructor for BgpMembershipManager.
26 //
28  : server_(server),
29  walker_(new Walker(this)),
30  event_queue_(new WorkQueue<Event *>(
31  TaskScheduler::GetInstance()->GetTaskId("bgp::PeerMembership"), 0,
32  boost::bind(&BgpMembershipManager::EventCallback, this, _1))) {
35 }
36 
37 //
38 // Destructor for BgpMembershipManager.
39 //
41  assert(current_jobs_count_ == 0);
42  assert(rib_state_map_.empty());
43  assert(peer_state_map_.empty());
44 }
45 
47  PeerRegistrationCallback callback) {
48  tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
49 
50  size_t id = registration_bmap_.find_first();
51  if (id == registration_bmap_.npos) {
52  id = registration_callbacks_.size();
53  registration_callbacks_.push_back(callback);
54  } else {
55  registration_bmap_.reset(id);
56  if (registration_bmap_.none()) {
57  registration_bmap_.clear();
58  }
59  registration_callbacks_[id] = callback;
60  }
61  return id;
62 }
63 
65  tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
66 
67  registration_callbacks_[id] = NULL;
68  if ((size_t) id == registration_callbacks_.size() - 1) {
69  while (!registration_callbacks_.empty() &&
70  registration_callbacks_.back() == NULL) {
71  registration_callbacks_.pop_back();
72  }
73  if (registration_bmap_.size() > registration_callbacks_.size()) {
75  }
76  } else {
77  if ((size_t) id >= registration_bmap_.size()) {
78  registration_bmap_.resize(id + 1);
79  }
80  registration_bmap_.set(id);
81  }
82 }
83 
85  bool unregister) {
86  CHECK_CONCURRENCY("bgp::PeerMembership");
87 
88  if (!peer->IsXmppPeer())
89  return;
90 
91  for (PeerRegistrationListenerList::iterator iter =
93  iter != registration_callbacks_.end(); ++iter) {
94  if (*iter != NULL) {
95  PeerRegistrationCallback callback = *iter;
96  (callback)(peer, table, unregister);
97  }
98  }
99 }
100 
102  if (prs->action() != NONE) {
103  if (do_assert)
104  assert(prs->action() == NONE);
105  return false;
106  }
107 
108  if (prs->ribout_registered()) {
109  if (do_assert)
110  assert(!prs->ribout_registered());
111  return false;
112  }
113 
114  return true;
115 }
116 
117 // Register the IPeer to the BgpTable.
118 // Post a REGISTER_RIB event to deal with concurrency issues with RibOut.
120  const RibExportPolicy &policy, int instance_id) {
121  CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper",
122  "bgp::StateMachine", "xmpp::StateMachine");
123 
124  tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
125  PeerRibState *prs = LocatePeerRibState(peer, table);
126  if (!AssertRegister(prs))
127  return;
130  prs->set_ribin_registered(true);
131  prs->set_action(RIBOUT_ADD);
132  Event *event = new Event(REGISTER_RIB, peer, table, policy, instance_id);
133  EnqueueEvent(event);
134 }
135 
137  bool do_assert) {
138  if (prs->action() != NONE) {
139  if (do_assert)
140  assert(prs->action() == NONE);
141  return false;
142  }
143 
144  if (prs->ribin_registered() && !peer->IsInGRTimerWaitState()) {
145  if (do_assert)
146  assert(!prs->ribin_registered() || peer->IsInGRTimerWaitState());
147  return false;
148  }
149 
150  if (prs->ribout_registered()) {
151  if (do_assert)
152  assert(!prs->ribout_registered());
153  return false;
154  }
155 
156  return true;
157 }
158 
159 // Synchronously register the IPeer to the BgpTable for RIBIN.
161  CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper",
162  "bgp::StateMachine", "xmpp::StateMachine");
163 
164  tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
165  PeerRibState *prs = LocatePeerRibState(peer, table);
166  if (!AssertRegisterRibIn(prs, peer))
167  return;
168  prs->set_ribin_registered(true);
169 }
170 
172  if (!prs || prs->action() != NONE) {
173  if (do_assert)
174  assert(prs && prs->action() == NONE);
175  return false;
176  }
177 
178  if (!prs->ribin_registered()) {
179  if (do_assert)
180  assert(prs->ribin_registered());
181  return false;
182  }
183 
184  return true;
185 }
186 
187 // Unregister the IPeer from the BgpTable.
188 // Post an UNREGISTER_RIB event to deal with concurrency issues with RibOut.
190  CHECK_CONCURRENCY("bgp::Config", "bgp::StateMachine", "xmpp::StateMachine");
191 
192  tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
193  PeerRibState *prs = FindPeerRibState(peer, table);
194  if (!AssertUnregister(prs))
195  return;
196 
199 
200  if (!prs->ribout_registered()) {
202  return;
203  }
204 
206  prs->set_ribin_registered(false);
207  prs->set_instance_id(-1);
208  prs->set_subscription_gen_id(0);
209  Event *event = new Event(UNREGISTER_RIB, peer, table);
210  EnqueueEvent(event);
211 }
212 
213 //
214 // Unregister the IPeer from the BgpTable for RIBIN.
215 //
217  CHECK_CONCURRENCY("bgp::Config", "bgp::StateMachine", "xmpp::StateMachine");
218 
219  tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
222  PeerRibState *prs = FindPeerRibState(peer, table);
223  assert(prs && prs->action() == NONE);
224  assert(prs->ribin_registered() && !prs->ribout_registered());
226 }
227 
228 //
229 // Common routine to handle unregister of IPeer from Table for RIBIN.
230 //
232  prs->set_ribin_registered(false);
233  prs->set_instance_id(-1);
234  prs->set_subscription_gen_id(0);
235  prs->set_action(RIBIN_DELETE);
236  prs->UnregisterRibIn();
237  BGP_LOG_PEER_TABLE(prs->peer(), SandeshLevel::SYS_DEBUG,
238  BGP_LOG_FLAG_SYSLOG, prs->table(),
239  "Unregister table requested for action " << prs->action());
240 }
241 
242 //
243 // Unregister the IPeer from the BgpTable.
244 // Post an UNREGISTER_RIB event to deal with concurrency issues with RibOut.
245 // The action is set to RIBIN_WALK_RIBOUT_DELETE.
246 // This API is to be used when handling graceful restart of the peer.
247 //
249  CHECK_CONCURRENCY("bgp::Config", "bgp::StateMachine", "xmpp::StateMachine");
250 
251  tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
254  PeerRibState *prs = FindPeerRibState(peer, table);
255  assert(prs && prs->action() == NONE);
256  assert(prs->ribin_registered());
257  assert(prs->ribout_registered());
258  prs->set_instance_id(-1);
259  prs->set_subscription_gen_id(0);
261  Event *event = new Event(UNREGISTER_RIB, peer, table);
262  EnqueueEvent(event);
263 }
264 
266  if (!prs || prs->action() != NONE) {
267  if (do_assert)
268  assert(prs && prs->action() == NONE);
269  return false;
270  }
271 
272  if (!prs->ribin_registered()) {
273  if (do_assert)
274  assert(prs->ribin_registered());
275  return false;
276  }
277 
278  return true;
279 }
280 
281 //
282 // Trigger a walk of IPeer's RIBIN for the BgpTable.
283 // This API can be used when sweeping paths as part of graceful restart.
284 // It can also be used in future when re-evaluating import policy for a peer.
285 //
287  CHECK_CONCURRENCY("bgp::Config", "bgp::StateMachine", "xmpp::StateMachine");
288 
289  tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
290  PeerRibState *prs = FindPeerRibState(peer, table);
291  if (!AssertWalkRibIn(prs))
292  return;
295  prs->set_action(RIBIN_WALK);
296  prs->WalkRibIn();
297  BGP_LOG_PEER_TABLE(peer, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_SYSLOG,
298  table, "Walk table requested for action " << prs->action());
299 }
300 
301 //
302 // Fill in the registration info of the IPeer for the BgpTable.
303 // Return true if the IPeer is registered with the BgpTable, false otherwise.
304 //
306  const IPeer *peer, const BgpTable *table,
307  int *instance_id, uint64_t *subscription_gen_id) const {
308  tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
309  const PeerRibState *prs = FindPeerRibState(peer, table);
310  if (!prs)
311  return false;
312  if (instance_id)
313  *instance_id = prs->instance_id();
314  if (subscription_gen_id)
315  *subscription_gen_id = prs->subscription_gen_id();
316  return true;
317 }
318 
319 //
320 // Update the registration info of the IPeer for the BgpTable.
321 //
323  const IPeer *peer, const BgpTable *table,
324  int instance_id, uint64_t subscription_gen_id) {
325  tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
326  PeerRibState *prs = FindPeerRibState(peer, table);
327  if (!prs)
328  return;
329  prs->set_instance_id(instance_id);
330  prs->set_subscription_gen_id(subscription_gen_id);
331 }
332 
333 //
334 // Return true if the IPeer is registered to the BgpTable.
335 //
337  const BgpTable *table) const {
338  tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
339  const PeerRibState *prs = FindPeerRibState(peer, table);
340  return (prs && prs->ribin_registered() && prs->ribout_registered());
341 }
342 
343 //
344 // Return true if the IPeer is registered to the BgpTable for RibIn.
345 //
347  const BgpTable *table) const {
348  tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
349  const PeerRibState *prs = FindPeerRibState(peer, table);
350  return (prs && prs->ribin_registered());
351 }
352 
353 //
354 // Return true if the IPeer is registered to the BgpTable for RibOut.
355 //
357  const BgpTable *table) const {
358  tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
359  const PeerRibState *prs = FindPeerRibState(peer, table);
360  return (prs && prs->ribout_registered());
361 }
362 
363 //
364 // Return RibOut's output queue depth.
365 //
367  const BgpTable *table) const {
368  tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
369  const PeerRibState *prs = FindPeerRibState(peer, table);
370  if (!prs || !prs->ribout_registered())
371  return 0;
372  RibOut *ribout = prs->ribout();
373  if (!ribout)
374  return 0;
375  return ribout->GetQueueSize();
376 }
377 
378 //
379 // Fill in the list of registered BgpTables for given IPeer.
380 //
382  list<BgpTable *> *table_list) const {
383  tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
384  table_list->clear();
385  const PeerState *ps = FindPeerState(peer);
386  if (ps)
387  ps->GetRegisteredRibs(table_list);
388 }
389 
390 //
391 //
392 // Fill membership introspect information for a BgpTable.
393 //
395  ShowRoutingInstanceTable *srit, const BgpTable *table) const {
396  tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
397  BgpTable *nc_table = const_cast<BgpTable *>(table);
398  const RibState *rs = FindRibState(nc_table);
399  if (rs)
401 }
402 
403 //
404 // Fill membership introspect information for an IPeer.
405 //
407  BgpNeighborResp *resp) const {
408  tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
409  assert(resp->get_routing_tables().empty());
410  IPeer *nc_peer = const_cast<IPeer *>(peer);
411 
413  if (sender->PeerIsRegistered(nc_peer)) {
414  resp->set_send_state(
415  sender->PeerInSync(nc_peer) ? "in sync" : "not in sync");
416  } else {
417  resp->set_send_state("not advertising");
418  }
419 
420  const PeerState *ps = FindPeerState(nc_peer);
421  if (ps)
422  ps->FillPeerMembershipInfo(resp);
423 }
424 
425 //
426 // Return true if no pending work in the BgpMembershipManager itself and
427 // in the Walker.
428 //
430  return (event_queue_->IsQueueEmpty() && walker_->IsQueueEmpty());
431 }
432 
433 //
434 // Return number of PeerRibStates.
435 //
437  size_t count = 0;
438  for (PeerStateMap::const_iterator loc = peer_state_map_.begin();
439  loc != peer_state_map_.end(); ++loc) {
440  const PeerState *ps = loc->second;
441  count += ps->GetMembershipCount();
442  }
443  return count;
444 }
445 
446 //
447 // Find or create the PeerState for given IPeer.
448 //
450  IPeer *peer) {
451  PeerStateMap::iterator loc = peer_state_map_.find(peer);
452  if (loc == peer_state_map_.end()) {
453  PeerState *ps = new PeerState(this, peer);
454  peer_state_map_.insert(make_pair(peer, ps));
455  return ps;
456  } else {
457  return loc->second;
458  }
459 }
460 
461 //
462 // Find the PeerState for given IPeer.
463 //
465  const IPeer *peer) {
466  PeerStateMap::iterator loc = peer_state_map_.find(peer);
467  return (loc != peer_state_map_.end() ? loc->second : NULL);
468 }
469 
470 //
471 // Find the PeerState for given IPeer.
472 // Const version.
473 //
475  const IPeer *peer) const {
476  PeerStateMap::const_iterator loc = peer_state_map_.find(peer);
477  return (loc != peer_state_map_.end() ? loc->second : NULL);
478 }
479 
480 //
481 // Destroy the given PeerState.
482 //
484  peer_state_map_.erase(ps->peer());
485  delete ps;
486 }
487 
488 //
489 // Find or create the RibState for given BgpTable.
490 //
492  BgpTable *table) {
493  RibStateMap::iterator loc = rib_state_map_.find(table);
494  if (loc == rib_state_map_.end()) {
495  RibState *rs = new RibState(this, table);
496  rib_state_map_.insert(make_pair(table, rs));
497  return rs;
498  } else {
499  return loc->second;
500  }
501 }
502 
503 //
504 // Find the RibState for given BgpTable.
505 //
507  const BgpTable *table) {
508  RibStateMap::iterator loc = rib_state_map_.find(table);
509  return (loc != rib_state_map_.end() ? loc->second : NULL);
510 }
511 
512 //
513 // Find the RibState for given BgpTable.
514 // Const version.
515 //
517  const BgpTable *table) const {
518  RibStateMap::const_iterator loc = rib_state_map_.find(table);
519  return (loc != rib_state_map_.end() ? loc->second : NULL);
520 }
521 
522 //
523 // Destroy the given RibState.
524 //
526  rib_state_map_.erase(rs->table());
527  delete rs;
528 }
529 
530 //
531 // Request the Walker to schedule a table walk for the given RibState.
532 // Note that the Walker accumulates requests and starts walks asynchronously.
533 //
535  walker_->Enqueue(rs);
536 }
537 
538 //
539 // Find or create the PeerRibState for given (IPeer, BgpTable).
540 //
542  IPeer *peer, BgpTable *table) {
543  PeerState *ps = LocatePeerState(peer);
544  RibState *rs = LocateRibState(table);
545  PeerRibState *prs = ps->LocatePeerRibState(rs);
546  rs->InsertPeerRibState(prs);
547  return prs;
548 }
549 
550 //
551 // Find the PeerRibState for given (IPeer, BgpTable).
552 //
554  const IPeer *peer, const BgpTable *table) {
555  PeerState *ps = FindPeerState(peer);
556  RibState *rs = FindRibState(table);
557  return (ps && rs ? ps->FindPeerRibState(rs) : NULL);
558 }
559 
560 //
561 // Find the PeerRibState for given (IPeer, BgpTable).
562 // Const version.
563 //
566  const IPeer *peer, const BgpTable *table) const {
567  const PeerState *ps = FindPeerState(peer);
568  const RibState *rs = FindRibState(table);
569  return (ps && rs ? ps->FindPeerRibState(rs) : NULL);
570 }
571 
572 //
573 // Destroy the given PeerRibState.
574 // Also destroy the PeerState and/or RibState if they are no longer required.
575 //
577  PeerState *ps = prs->peer_state();
578  RibState *rs = prs->rib_state();
579  if (ps->RemovePeerRibState(prs))
580  DestroyPeerState(ps);
581  if (rs->RemovePeerRibState(prs))
582  DestroyRibState(rs);
583  delete prs;
584 }
585 
586 //
587 // Trigger REGISTER_RIB_COMPLETE event.
588 //
590  BgpTable *table) {
591  Event *event = new Event(REGISTER_RIB_COMPLETE, peer, table);
592  EnqueueEvent(event);
593 }
594 
595 //
596 // Trigger UNREGISTER_RIB_COMPLETE event.
597 //
599  BgpTable *table) {
600  Event *event = new Event(UNREGISTER_RIB_COMPLETE, peer, table);
601  EnqueueEvent(event);
602 }
603 
604 //
605 // Trigger WALK_RIB_COMPLETE event.
606 //
608  BgpTable *table) {
609  Event *event = new Event(WALK_RIB_COMPLETE, peer, table);
610  EnqueueEvent(event);
611 }
612 
613 //
614 // Process REGISTER_RIB event.
615 //
617  IPeer *peer = event->peer;
618  BgpTable *table = event->table;
619  PeerRibState *prs = FindPeerRibState(peer, table);
620  assert(prs && prs->action() == RIBOUT_ADD);
621  assert(prs->ribin_registered());
622  prs->set_instance_id(event->instance_id);
623 
624  // Notify completion right away if the table is marked for deletion.
625  // Mark the ribout as registered even though no RibOut gets created.
626  // The unregister code path handles a PeerRibState without a RibOut.
627  if (table->IsDeleted()) {
628  prs->set_ribout_registered(true);
629  prs->clear_action();
630  peer->MembershipRequestCallback(table);
632  return;
633  }
634 
635  prs->RegisterRibOut(event->policy);
636  BGP_LOG_PEER_TABLE(peer, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_SYSLOG,
637  table, "Register table requested for action " << prs->action());
638 }
639 
640 
641 //
642 // Process REGISTER_RIB_COMPLETE event.
643 //
645  IPeer *peer = event->peer;
646  BgpTable *table = event->table;
647  PeerRibState *prs = FindPeerRibState(peer, table);
648  assert(prs && prs->action() == RIBOUT_ADD);
649  assert(prs->ribin_registered());
650  assert(prs->ribout_registered());
651  BGP_LOG_PEER_TABLE(peer, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_SYSLOG,
652  table, "Register table completed for action " << prs->action());
653  prs->clear_action();
654  peer->MembershipRequestCallback(table);
655  NotifyPeerRegistration(peer, table, false);
657 }
658 
659 //
660 // Process UNREGISTER_RIB event.
661 //
663  IPeer *peer = event->peer;
664  BgpTable *table = event->table;
665  PeerRibState *prs = FindPeerRibState(peer, table);
666  assert(prs);
667  assert(prs->action() == RIBIN_DELETE_RIBOUT_DELETE ||
668  prs->action() == RIBIN_WALK_RIBOUT_DELETE);
669  if (prs->action() == RIBIN_DELETE_RIBOUT_DELETE)
670  assert(!prs->ribin_registered());
671  if (prs->action() == RIBIN_WALK_RIBOUT_DELETE)
672  assert(prs->ribin_registered());
673  assert(prs->ribout_registered());
674 
675  prs->DeactivateRibOut();
676  BGP_LOG_PEER_TABLE(peer, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_SYSLOG,
677  table, "Unregister table requested for action " << prs->action());
678 }
679 
680 //
681 // Process UNREGISTER_RIB_COMPLETE event.
682 //
684  IPeer *peer = event->peer;
685  BgpTable *table = event->table;
686  PeerRibState *prs = FindPeerRibState(peer, table);
687  assert(prs);
688  assert(prs->action() == RIBIN_DELETE_RIBOUT_DELETE ||
689  prs->action() == RIBIN_WALK_RIBOUT_DELETE);
690  if (prs->action() == RIBIN_DELETE_RIBOUT_DELETE)
691  assert(!prs->ribin_registered());
692  if (prs->action() == RIBIN_WALK_RIBOUT_DELETE)
693  assert(prs->ribin_registered());
694 
695  prs->UnregisterRibOut();
696  BGP_LOG_PEER_TABLE(peer, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_SYSLOG,
697  table, "Unregister table completed for action " << prs->action());
698  prs->clear_action();
699  if (!prs->ribin_registered() && !prs->ribout_registered())
700  DestroyPeerRibState(prs);
701 
702  peer->MembershipRequestCallback(table);
703  NotifyPeerRegistration(peer, table, true);
705 }
706 
707 //
708 // Process WALK_RIB_COMPLETE event.
709 //
711  IPeer *peer = event->peer;
712  BgpTable *table = event->table;
713  PeerRibState *prs = FindPeerRibState(peer, table);
714  assert(prs);
715  assert(prs->action() == RIBIN_WALK || prs->action() == RIBIN_DELETE);
716  if (prs->action() == RIBIN_WALK) {
717  assert(prs->ribin_registered());
718  BGP_LOG_PEER_TABLE(peer, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_SYSLOG,
719  table, "Walk table completed for action " << prs->action());
720  } else {
721  assert(!prs->ribin_registered());
722  BGP_LOG_PEER_TABLE(peer, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_SYSLOG,
723  table, "Unregister table completed for action " << prs->action());
724  }
725  prs->clear_action();
726  if (!prs->ribin_registered() && !prs->ribout_registered())
727  DestroyPeerRibState(prs);
728  peer->MembershipRequestCallback(table);
730 }
731 
732 //
733 // Internal handler for an Event.
734 // Exists so that test code can override it.
735 //
737  switch (event->event_type) {
738  case REGISTER_RIB:
740  break;
743  break;
744  case UNREGISTER_RIB:
746  break;
749  break;
750  case WALK_RIB_COMPLETE:
752  break;
753  default:
754  assert(false);
755  break;
756  }
757 
758  delete event;
759  return true;
760 }
761 
762 //
763 // Handler for an Event.
764 //
766  CHECK_CONCURRENCY("bgp::PeerMembership");
767  return EventCallbackInternal(event);
768 }
769 
770 //
771 // Constructor.
772 //`
774  BgpTable *table)
775  : event_type(event_type),
776  peer(peer),
777  table(table),
778  instance_id(-1) {
779 }
780 
781 //
782 // Constructor.
783 //`
785  BgpTable *table, const RibExportPolicy &policy, int instance_id)
786  : event_type(event_type),
787  peer(peer),
788  table(table),
789  policy(policy),
790  instance_id(instance_id) {
791 }
792 
793 //
794 // Constructor.
795 //`
797  IPeer *peer)
798  : manager_(manager),
799  peer_(peer) {
800 }
801 
802 //
803 // Destructor.
804 //`
806  assert(rib_map_.empty());
807 }
808 
809 //
810 // Find or create the PeerRibState for given RibState.
811 //
814  PeerRibStateMap::iterator loc = rib_map_.find(rs);
815  if (loc == rib_map_.end()) {
816  PeerRibState *prs = new PeerRibState(manager_, this, rs);
817  rib_map_.insert(make_pair(rs, prs));
818  return prs;
819  } else {
820  return loc->second;
821  }
822 }
823 
824 //
825 // Find the PeerRibState for given RibState.
826 //
829  PeerRibStateMap::iterator loc = rib_map_.find(rs);
830  return (loc != rib_map_.end() ? loc->second : NULL);
831 }
832 
833 //
834 // Find the PeerRibState for given RibState.
835 // Const version.
836 //
839  PeerRibStateMap::const_iterator loc = rib_map_.find(rs);
840  return (loc != rib_map_.end() ? loc->second : NULL);
841 }
842 
843 //
844 // Remove given PeerRibState from PeerRibStateMap.
845 // Return true if the PeerState itself can we deleted.
846 //
848  PeerRibStateMap::iterator loc = rib_map_.find(prs->rib_state());
849  if (loc != rib_map_.end())
850  rib_map_.erase(loc);
851  return rib_map_.empty();
852 }
853 
854 //
855 // Fill in the list of registered BgpTables.
856 //
858  list<BgpTable *> *table_list) const {
859  for (PeerRibStateMap::const_iterator loc = rib_map_.begin();
860  loc != rib_map_.end(); ++loc) {
861  const RibState *rs = loc->first;
862  table_list->push_back(rs->table());
863  }
864 }
865 
866 //
867 // Fill introspect information.
868 //
870  BgpNeighborResp *resp) const {
871  vector<BgpNeighborRoutingTable> table_list;
872  for (PeerRibStateMap::const_iterator loc = rib_map_.begin();
873  loc != rib_map_.end(); ++loc) {
874  const RibState *rs = loc->first;
875  BgpNeighborRoutingTable table;
876  table.set_name(rs->table()->name());
877  table.set_current_state("subscribed");
878  table_list.push_back(table);
879  }
880  resp->set_routing_tables(table_list);
881 }
882 
883 //
884 // Constructor.
885 //
887  BgpTable *table)
888  : manager_(manager),
889  table_(table),
890  request_count_(0),
891  walk_count_(0),
892  table_delete_ref_(this, table->deleter()) {
893 }
894 
895 //
896 // Destructor.
897 //
899  assert(peer_rib_list_.empty());
900  assert(pending_peer_rib_list_.empty());
901 }
902 
903 //
904 // Enqueue given PeerRibState into the pending PeerRibStateList.
905 //
907  request_count_++;
908  pending_peer_rib_list_.insert(prs);
909  manager_->EnqueueRibState(this);
910 }
911 
912 //
913 // Clear the pending PeerRibStateList.
914 //
916  pending_peer_rib_list_.clear();
917 }
918 
919 //
920 // Insert given PeerRibState into the regular PeerRibStateList.
921 //
923  peer_rib_list_.insert(prs);
924 }
925 
926 //
927 // Remove given PeerRibState from the regular PeerRibStateList.
928 //
930  peer_rib_list_.erase(prs);
931  return peer_rib_list_.empty();
932 }
933 
934 //
935 // Fill introspect information.
936 //
938  ShowRoutingInstanceTable *srit) const {
939  ShowTableMembershipInfo stmi;
940  stmi.set_requests(request_count_);
941  stmi.set_walks(walk_count_);
942  vector<ShowMembershipPeerInfo> peers;
943  for (PeerRibList::const_iterator it = peer_rib_list_.begin();
944  it != peer_rib_list_.end(); ++it) {
945  const PeerRibState *prs = *it;
946  ShowMembershipPeerInfo smpi;
947  prs->FillMembershipInfo(&smpi);
948  peers.push_back(smpi);
949  }
950  stmi.set_peers(peers);
951  srit->set_membership(stmi);
952 }
953 
954 //
955 // Constructor.
956 //
958  PeerState *ps, RibState *rs)
959  : manager_(manager),
960  ps_(ps),
961  rs_(rs),
962  ribout_(NULL),
963  ribout_index_(-1),
964  action_(BgpMembershipManager::NONE),
965  ribin_registered_(false),
966  ribout_registered_(false),
967  instance_id_(-1),
968  subscription_gen_id_(0) {
969 }
970 
971 //
972 // Destructor.
973 //
975  assert(!ribout_);
976  assert(ribout_index_ == -1);
977  assert(action_ == BgpMembershipManager::NONE);
978  assert(!ribin_registered_);
979  assert(!ribout_registered_);
980  assert(instance_id_ == -1);
981  assert(subscription_gen_id_ == 0);
982 }
983 
984 //
985 // Create RibOut for this PeerRibState and registers the RibOut as a listener
986 // for the BgpTable.
987 //
988 // Register the IPeer to the RibOut.
989 // This PeerRibState is added to the pending PeerRibStateList of RibState
990 // so that Join processing is handled when walking the BgpTable.
991 //
993  const RibExportPolicy &policy) {
994  CHECK_CONCURRENCY("bgp::PeerMembership");
995 
996  BgpUpdateSender *sender = manager_->server()->update_sender();
997  ribout_ = rs_->table()->RibOutLocate(sender, policy);
998  ribout_->RegisterListener();
999  ribout_->Register(ps_->peer());
1000  ribout_index_ = ribout_->GetPeerIndex(ps_->peer());
1001  ribout_registered_ = true;
1002  rs_->EnqueuePeerRibState(this);
1003 }
1004 
1005 //
1006 // Deactivate the IPeer in the RibOut.
1007 // This ensures that the IPeer will stop exporting routes from now onwards.
1008 //
1009 // Note that this is called before Leave processing for the IPeer is started.
1010 //
1011 // Bypass the Walker and directly post an UNREGISTER_RIB_COMPLETE event if
1012 // there's no RibOut. This happens if the table was marked deleted when the
1013 // register was processed.
1014 //
1016  CHECK_CONCURRENCY("bgp::PeerMembership");
1017  if (ribout_) {
1018  ribout_->Deactivate(ps_->peer());
1019  rs_->EnqueuePeerRibState(this);
1020  } else {
1021  assert(ribout_index_ == -1);
1022  ribout_registered_ = false;
1023  manager_->TriggerUnregisterRibCompleteEvent(ps_->peer(), rs_->table());
1024  }
1025 }
1026 
1027 //
1028 // Unregister the IPeer from the BgpTable.
1029 // Unregister the IPeer from the RibOut, which may result in deletion of the
1030 // RibOut itself.
1031 //
1032 // Note that this is called only after Leave processing for the IPeer has been
1033 // completed.
1034 //
1036  CHECK_CONCURRENCY("bgp::PeerMembership");
1037 
1038  if (!ribout_)
1039  return;
1040  assert(ribout_index_ != -1);
1041  ribout_->Unregister(ps_->peer());
1042  ribout_ = NULL;
1043  ribout_index_ = -1;
1044  ribout_registered_ = false;
1045 }
1046 
1047 //
1048 // Unregister the RibIn for the IPeer.
1049 //
1051  rs_->EnqueuePeerRibState(this);
1052 }
1053 
1054 //
1055 // Walk the RibIn for the IPeer.
1056 //
1058  rs_->EnqueuePeerRibState(this);
1059 }
1060 
1061 //
1062 // Fill introspect information.
1063 //
1065  ShowMembershipPeerInfo *smpi) const {
1066  smpi->set_peer(ps_->peer()->ToString());
1067  smpi->set_ribin_registered(ribin_registered_);
1068  smpi->set_ribout_registered(ribout_registered_);
1069  smpi->set_instance_id(instance_id_);
1070  smpi->set_generation_id(subscription_gen_id_);
1071 }
1072 
1073 //
1074 // Constructor.
1075 //
1077  : manager_(manager),
1078  trigger_(new TaskTrigger(
1079  boost::bind(&BgpMembershipManager::Walker::WalkTrigger, this),
1080  TaskScheduler::GetInstance()->GetTaskId("bgp::PeerMembership"), 0)),
1081  postpone_walk_(false),
1082  walk_started_(false),
1083  walk_completed_(false),
1084  rs_(NULL),
1085  rib_state_list_size_(0),
1086  ribout_state_list_size_(0) {
1087 }
1088 
1089 //
1090 // Destructor.
1091 //
1093  assert(rib_state_set_.empty());
1094  assert(rib_state_list_.empty());
1095  assert(!postpone_walk_);
1096  assert(!rs_);
1097  assert(walk_ref_ == NULL);
1098  assert(peer_rib_list_.empty());
1099  assert(peer_list_.empty());
1100  assert(ribout_state_map_.empty());
1101  assert(ribout_state_list_.empty());
1102 }
1103 
1104 //
1105 // Add the given RibState to the RibStateList if it's not already present.
1106 // Trigger processing of the RibStateList if a walk is not already in progress.
1107 //
1109  if (rib_state_set_.find(rs) != rib_state_set_.end())
1110  return;
1111  rib_state_set_.insert(rs);
1112  rib_state_list_.push_back(rs);
1113  rib_state_list_size_++;
1114  if (!walk_started_)
1115  trigger_->Set();
1116 }
1117 
1118 //
1119 // Return true if the Walk does not have any pending items.
1120 //
1122  return (rib_state_list_.empty() && !trigger_->IsSet() && !rs_);
1123 }
1124 
1125 //
1126 // Find or create the RibOutState for given RibOut.
1127 //
1130  RibOutStateMap::iterator loc = ribout_state_map_.find(ribout);
1131  if (loc == ribout_state_map_.end()) {
1132  RibOutState *ros = new RibOutState(ribout);
1133  ribout_state_map_.insert(make_pair(ribout, ros));
1134  ribout_state_list_.push_back(ros);
1135  ribout_state_list_size_++;
1136  return ros;
1137  } else {
1138  return loc->second;
1139  }
1140 }
1141 
1142 //
1143 // Process table walk callback from DB infrastructure.
1144 //
1146  DBEntryBase *db_entry) {
1147  CHECK_CONCURRENCY("db::DBTable");
1148 
1149  // Walk all RibOutStates and handle join/leave processing.
1150  for (RibOutStateList::iterator it = ribout_state_list_.begin();
1151  it != ribout_state_list_.end(); ++it) {
1152  RibOutState *ros = *it;
1153  RibOut *ribout = ros->ribout();
1154  ribout->bgp_export()->Join(tpart, ros->join_bitset(), db_entry);
1155  ribout->bgp_export()->Leave(tpart, ros->leave_bitset(), db_entry);
1156  }
1157 
1158  // Bail if there's no peers that need RibIn processing.
1159  if (peer_list_.empty())
1160  return true;
1161 
1162  // Walk through all eligible paths and notify the source peer if needed.
1163  bool notify = false;
1164  BgpRoute *route = static_cast<BgpRoute *>(db_entry);
1165  for (Route::PathList::iterator it = route->GetPathList().begin(), next = it;
1166  it != route->GetPathList().end(); it = next) {
1167  next++;
1168 
1169  BgpPath *path = static_cast<BgpPath *>(it.operator->());
1170  IPeer *peer = path->GetPeer();
1171 
1172  // Skip resolved paths - PathResolver is responsible for them.
1173  if (path->IsResolved())
1174  continue;
1175 
1176  // Skip aliased paths - EvpnManager is responsible for them.
1177  if (path->IsAliased())
1178  continue;
1179 
1180  // Skip secondary paths.
1181  if (dynamic_cast<BgpSecondaryPath *>(path))
1182  continue;
1183 
1184  // Skip if there's no walk requested for this IPeer.
1185  if (!peer || peer_list_.find(peer) == peer_list_.end())
1186  continue;
1187 
1188  notify |= peer->MembershipPathCallback(tpart, route, path);
1189  }
1190 
1191  rs_->table()->InputCommonPostProcess(tpart, route, notify);
1192  return true;
1193 }
1194 
1195 //
1196 // Process table walk done callback from DB infrastructure.
1197 // Just note that the walk has completed and trigger processing from the
1198 // bgp::PeerMembership task.
1199 //
1201  CHECK_CONCURRENCY("db::Walker");
1202  assert(rs_->table() == table_base);
1203  walk_completed_ = true;
1204  trigger_->Set();
1205 }
1206 
1207 //
1208 // Start a walk for the BgpTable corresponding to the next RibState in the
1209 // RibStateList.
1210 //
1212  CHECK_CONCURRENCY("bgp::PeerMembership");
1213 
1214  assert(walk_ref_ == NULL);
1215  assert(!rs_);
1216  assert(peer_rib_list_.empty());
1217  assert(peer_list_.empty());
1218  assert(ribout_state_map_.empty());
1219  assert(ribout_state_list_.empty());
1220  assert(rib_state_list_size_ == rib_state_set_.size());
1221 
1222  // Bail if the list if empty.
1223  if (rib_state_list_.empty())
1224  return;
1225 
1226  // Get and remove the first RibState from the RibStateList.
1227  rs_ = rib_state_list_.front();
1228  rib_state_list_.pop_front();
1229  rib_state_list_size_--;
1230  assert(rib_state_set_.erase(rs_) == 1);
1231 
1232  // Process all pending PeerRibStates for chosen RibState.
1233  // Insert the PeerRibStates into PeerRibList for post processing when
1234  // table walk is complete.
1235  for (RibState::iterator it = rs_->begin(); it != rs_->end(); ++it) {
1236  PeerRibState *prs = *it;
1237  peer_rib_list_.insert(prs);
1238 
1239  // Update PeerList for RIBIN actions and RibOutStateMap for RIBOUT
1240  // actions.
1241  switch (prs->action()) {
1242  case RIBOUT_ADD: {
1243  RibOutState *ros = LocateRibOutState(prs->ribout());
1244  ros->JoinPeer(prs->ribout_index());
1245  break;
1246  }
1247  case RIBIN_DELETE:
1248  case RIBIN_WALK: {
1249  IPeer *peer = prs->peer_state()->peer();
1250  peer_list_.insert(peer);
1251  break;
1252  }
1255  IPeer *peer = prs->peer_state()->peer();
1256  peer_list_.insert(peer);
1257  RibOutState *ros = LocateRibOutState(prs->ribout());
1258  ros->LeavePeer(prs->ribout_index());
1259  break;
1260  }
1261  default: {
1262  assert(false);
1263  break;
1264  }
1265  }
1266  }
1267 
1268  // Clear the pending PeerRibStates in the RibState.
1269  // This allows the RibState to accumulate new PeerRibStates for a future
1270  // walk of it's BgpTable.
1271  rs_->ClearPeerRibStateList();
1272 
1273  // Start the walk.
1274  rs_->increment_walk_count();
1275  BgpTable *table = rs_->table();
1276  walk_ref_ = table->AllocWalker(
1277  boost::bind(&BgpMembershipManager::Walker::WalkCallback, this, _1, _2),
1278  boost::bind(&BgpMembershipManager::Walker::WalkDoneCallback, this, _2));
1279  walk_started_ = true;
1280  if (!postpone_walk_)
1281  table->WalkTable(walk_ref_);
1282 }
1283 
1284 //
1285 // Finish processing of the walk of BgpTable for current RibState.
1286 //
1287 // The walk complete notification is handled by WalkDoneCallback but all the
1288 // book-keeping and triggering of Events is handled by this method since it
1289 // needs to happen in bgp::PeerMembership task.
1290 //
1292  CHECK_CONCURRENCY("bgp::PeerMembership");
1293 
1294  assert(walk_ref_ != NULL);
1295  assert(rs_);
1296  assert(!peer_rib_list_.empty());
1297  assert(!peer_list_.empty() || !ribout_state_map_.empty());
1298  assert(rib_state_list_size_ == rib_state_set_.size());
1299  assert(ribout_state_list_size_ == ribout_state_map_.size());
1300 
1301  BgpTable *table = rs_->table();
1302  for (PeerRibList::iterator it = peer_rib_list_.begin();
1303  it != peer_rib_list_.end(); ++it) {
1304  PeerRibState *prs = *it;
1305  IPeer *peer = prs->peer_state()->peer();
1306 
1307  switch (prs->action()) {
1308  case RIBOUT_ADD:
1309  manager_->TriggerRegisterRibCompleteEvent(peer, table);
1310  break;
1311  case RIBIN_DELETE:
1312  case RIBIN_WALK:
1313  manager_->TriggerWalkRibCompleteEvent(peer, table);
1314  break;
1317  manager_->TriggerUnregisterRibCompleteEvent(peer, table);
1318  break;
1319  default:
1320  assert(false);
1321  break;
1322  }
1323  }
1324 
1325  table->ReleaseWalker(walk_ref_);
1326  rs_ = NULL;
1327  peer_rib_list_.clear();
1328  peer_list_.clear();
1329  ribout_state_list_.clear();
1330  ribout_state_list_size_ = 0;
1331  STLDeleteElements(&ribout_state_map_);
1332 
1333  walk_started_ = false;
1334  walk_completed_ = false;
1335 }
1336 
1337 //
1338 // Handler for TaskTrigger.
1339 // Start a new walk or finish processing for the current walk and start a new
1340 // one.
1341 //
1343  CHECK_CONCURRENCY("bgp::PeerMembership");
1344 
1345  if (!walk_started_) {
1346  assert(!walk_completed_);
1347  WalkStart();
1348  } else if (walk_completed_) {
1349  WalkFinish();
1350  WalkStart();
1351  }
1352  return true;
1353 }
1354 
1355 //
1356 // Disable the TaskTrigger so that the Walker can accumulate RibStates in the
1357 // RibStateList.
1358 // Testing only.
1359 //
1361  if (value) {
1362  trigger_->set_disable();
1363  } else {
1364  trigger_->set_enable();
1365  }
1366 }
1367 
1368 //
1369 // Force the Walker to trigger walks that are postponed.
1370 // Testing only.
1371 //
1373  assert(!walk_started_);
1374  assert(walk_ref_ == NULL);
1375  postpone_walk_ = true;
1376 }
1377 
1378 //
1379 // Tell the DBTableWalkMgr to resume walk that was postponed previously.
1380 // Testing only.
1381 //
1383  assert(walk_started_);
1384  assert(!walk_completed_);
1385  assert(walk_ref_ != NULL);
1386  postpone_walk_ = false;
1387  BgpTable *table = rs_->table();
1388  table->WalkTable(walk_ref_);
1389 }
PeerState(BgpMembershipManager *manager, IPeer *peer)
virtual void UnregisterRibOut(IPeer *peer, BgpTable *table)
void ProcessRegisterRibEvent(Event *event)
void ProcessUnregisterRibEvent(Event *event)
boost::function< void(IPeer *, BgpTable *, bool)> PeerRegistrationCallback
bool PeerIsRegistered(IPeerUpdate *peer) const
void ProcessUnregisterRibCompleteEvent(Event *event)
void EnqueuePeerRibState(PeerRibState *prs)
bool WalkCallback(DBTablePartBase *tpart, DBEntryBase *db_entry)
virtual bool EventCallbackInternal(Event *event)
void WalkTable(DBTableWalkRef walk)
Definition: db_table.cc:625
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h:178
void RegisterRibOut(const RibExportPolicy &policy)
#define BGP_LOG_PEER_TABLE(peer, level, flags, tbl, arg)
Definition: bgp_log.h:205
virtual bool IsXmppPeer() const =0
void EnqueueEvent(Event *event)
tbb::atomic< uint64_t > total_jobs_count_
bool PeerInSync(IPeerUpdate *peer) const
boost::dynamic_bitset registration_bmap_
bool IsQueueEmpty() const
PeerRibState * LocatePeerRibState(RibState *rs)
void EnqueueRibState(RibState *rs)
tbb::spin_rw_mutex rw_mutex_
PeerStateMap peer_state_map_
bool IsRegistered(const IPeer *peer, const BgpTable *table) const
BgpMembershipManager(BgpServer *server)
DBTableWalkRef AllocWalker(WalkFn walk_fn, WalkCompleteFn walk_complete)
Definition: db_table.cc:613
const BgpTable * table() const
bool Join(DBTablePartBase *root, const RibPeerSet &mjoin, DBEntryBase *db_entry)
Definition: bgp_export.cc:178
virtual void Register(IPeer *peer, BgpTable *table, const RibExportPolicy &policy, int instance_id=-1)
PeerRegistrationListenerList registration_callbacks_
void TriggerWalkRibCompleteEvent(IPeer *peer, BgpTable *table)
size_t GetMembershipCount() const
void FillPeerMembershipInfo(const IPeer *peer, BgpNeighborResp *resp) const
Definition: ipeer.h:186
bool RemovePeerRibState(PeerRibState *prs)
virtual bool IsInGRTimerWaitState() const =0
void DestroyPeerState(PeerState *ps)
bool GetRegistrationInfo(const IPeer *peer, const BgpTable *table, int *instance_id=NULL, uint64_t *subscription_gen_id=NULL) const
uint32_t GetQueueSize() const
Definition: bgp_ribout.cc:485
void TriggerUnregisterRibCompleteEvent(IPeer *peer, BgpTable *table)
PeerRibState * LocatePeerRibState(IPeer *peer, BgpTable *table)
bool IsDeleted() const
Definition: bgp_table.h:143
void FillPeerMembershipInfo(BgpNeighborResp *resp) const
RibStateMap rib_state_map_
void WalkRibIn(IPeer *peer, BgpTable *table)
boost::scoped_ptr< Walker > walker_
RibState(BgpMembershipManager *manager, BgpTable *table)
RibOutState * LocateRibOutState(RibOut *ribout)
#define BGP_LOG_FLAG_SYSLOG
Definition: bgp_log.h:42
void DestroyPeerRibState(PeerRibState *prs)
Event
Definition: http_client.h:27
virtual bool AssertRegisterRibIn(PeerRibState *prs, IPeer *peer, bool do_assert=true)
virtual ~BgpMembershipManager()
void RegisterRibIn(IPeer *peer, BgpTable *table)
bool RemovePeerRibState(PeerRibState *prs)
void UnregisterPeerRegistrationCallback(int id)
void STLDeleteElements(Container *container)
Definition: util.h:114
#define CHECK_CONCURRENCY(...)
void DestroyRibState(RibState *ps)
virtual void Unregister(IPeer *peer, BgpTable *table)
boost::scoped_ptr< WorkQueue< Event * > > event_queue_
IPeer * GetPeer()
Definition: bgp_path.h:76
const std::string & name() const
Definition: db_table.h:110
void UnregisterRibIn(IPeer *peer, BgpTable *table)
RibState * LocateRibState(BgpTable *table)
Walker(BgpMembershipManager *manager)
void TriggerRegisterRibCompleteEvent(IPeer *peer, BgpTable *table)
bool IsResolved() const
Definition: bgp_path.h:99
void SetRegistrationInfo(const IPeer *peer, const BgpTable *table, int instance_id, uint64_t subscription_gen_id)
void FillRoutingInstanceTableInfo(ShowRoutingInstanceTable *srit, const BgpTable *table) const
BgpExport * bgp_export()
Definition: bgp_ribout.h:318
void GetRegisteredRibs(std::list< BgpTable * > *table_list) const
void UnregisterRibInUnlocked(PeerRibState *prs)
void WalkDoneCallback(DBTableBase *table)
void set_instance_id(int instance_id)
BgpUpdateSender * update_sender()
Definition: bgp_server.h:98
void ProcessWalkRibCompleteEvent(Event *event)
PeerRibState(BgpMembershipManager *manager, PeerState *ps, RibState *rs)
PeerRibState * FindPeerRibState(const IPeer *peer, const BgpTable *table)
virtual void MembershipRequestCallback(BgpTable *table)=0
virtual bool AssertRegister(PeerRibState *prs, bool do_assert=true)
virtual bool AssertWalkRibIn(PeerRibState *prs, bool do_assert=true)
bool Leave(DBTablePartBase *root, const RibPeerSet &mleave, DBEntryBase *db_entry)
Definition: bgp_export.cc:234
bool IsRibInRegistered(const IPeer *peer, const BgpTable *table) const
void FillRoutingInstanceTableInfo(ShowRoutingInstanceTable *srit) const
RibState * FindRibState(const BgpTable *table)
bool IsAliased() const
Definition: bgp_path.h:98
bool IsRibOutRegistered(const IPeer *peer, const BgpTable *table) const
PeerState * LocatePeerState(IPeer *peer)
tbb::atomic< uint64_t > current_jobs_count_
void set_subscription_gen_id(uint64_t subscription_gen_id)
void ProcessRegisterRibCompleteEvent(Event *event)
PeerRibState * FindPeerRibState(const RibState *rs)
Event(EventType event_type, IPeer *peer, BgpTable *table)
virtual bool MembershipPathCallback(DBTablePartBase *tpart, BgpRoute *route, BgpPath *path)=0
PeerState * FindPeerState(const IPeer *peer)
void GetRegisteredRibs(const IPeer *peer, std::list< BgpTable * > *table_list) const
PeerRibList::iterator iterator
void NotifyPeerRegistration(IPeer *peer, BgpTable *table, bool unregister)
BgpMembershipManager::Action action() const
int RegisterPeerRegistrationCallback(PeerRegistrationCallback callback)
virtual bool AssertUnregister(PeerRibState *prs, bool do_assert=true)
uint32_t GetRibOutQueueDepth(const IPeer *peer, const BgpTable *table) const
void set_action(BgpMembershipManager::Action action)
bool EventCallback(Event *event)
void FillMembershipInfo(ShowMembershipPeerInfo *smpi) const
const PathList & GetPathList() const
Definition: route.h:46
void InsertPeerRibState(PeerRibState *prs)