OpenSDN source code
nexthop_ksync.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <sys/types.h>
6 #include <net/ethernet.h>
7 #include <boost/asio.hpp>
8 #include <boost/bind/bind.hpp>
9 
10 #include <base/logging.h>
11 #include <db/db_entry.h>
12 #include <db/db_table.h>
13 #include <db/db_table_partition.h>
14 #include <ksync/ksync_index.h>
15 #include <ksync/ksync_entry.h>
16 #include <ksync/ksync_object.h>
17 #include <ksync/ksync_netlink.h>
18 #include <ksync/ksync_sock.h>
19 
20 #include "oper/interface_common.h"
21 #include "oper/nexthop.h"
22 #include "oper/mirror_table.h"
23 #include "oper/tunnel_nh.h"
26 #include "vr_types.h"
27 #include "oper/ecmp_load_balance.h"
28 #include "vrouter/ksync/agent_ksync_types.h"
30 
31 using namespace boost::placeholders;
32 
34  uint32_t index) :
35  KSyncNetlinkDBEntry(index), ksync_obj_(obj), type_(entry->type_),
36  vrf_id_(entry->vrf_id_), label_(entry->label_),
37  interface_(entry->interface_), sip_(entry->sip_), dip_(entry->dip_),
38  sport_(entry->sport_), dport_(entry->dport_), smac_(entry->smac_),
39  dmac_(entry->dmac_), rewrite_dmac_(entry->rewrite_dmac_),
40  valid_(entry->valid_), policy_(entry->policy_),
41  is_mcast_nh_(entry->is_mcast_nh_),
42  defer_(entry->defer_), component_nh_list_(entry->component_nh_list_),
43  nh_(entry->nh_), vlan_tag_(entry->vlan_tag_),
44  is_local_ecmp_nh_(entry->is_local_ecmp_nh_),
45  is_bridge_(entry->is_bridge_),
46  is_vxlan_routing_(entry->is_vxlan_routing_),
47  comp_type_(entry->comp_type_),
48  validate_mcast_src_(entry->validate_mcast_src_),
49  tunnel_type_(entry->tunnel_type_), prefix_len_(entry->prefix_len_),
50  nh_id_(entry->nh_id()),
51  component_nh_key_list_(entry->component_nh_key_list_),
52  bridge_nh_(entry->bridge_nh_),
53  flood_unknown_unicast_(entry->flood_unknown_unicast_),
54  ecmp_hash_fieds_(entry->ecmp_hash_fieds_.HashFieldsToUse()),
55  pbb_child_nh_(entry->pbb_child_nh_), isid_(entry->isid_),
56  pbb_label_(entry->pbb_label_), learning_enabled_(entry->learning_enabled_),
57  need_pbb_tunnel_(entry->need_pbb_tunnel_), etree_leaf_(entry->etree_leaf_),
58  layer2_control_word_(entry->layer2_control_word_),
59  crypt_(entry->crypt_), crypt_path_available_(entry->crypt_path_available_),
60  crypt_interface_(entry->crypt_interface_),
61  transport_tunnel_type_(entry->transport_tunnel_type_),
62  interface_list_(entry->interface_list_),
63  encap_valid_list_(entry->encap_valid_list_),
64  dmac_list_(entry->dmac_list_) {
65  }
66 
68  KSyncNetlinkDBEntry(kInvalidIndex), ksync_obj_(obj), type_(nh->GetType()),
69  vrf_id_(0), interface_(NULL), dmac_(), valid_(nh->IsValid()),
70  policy_(nh->PolicyEnabled()), is_mcast_nh_(false), nh_(nh),
71  vlan_tag_(VmInterface::kInvalidVlanId), is_bridge_(false),
72  is_vxlan_routing_(false),
73  tunnel_type_(TunnelType::INVALID), prefix_len_(32), nh_id_(nh->id()),
74  bridge_nh_(false), flood_unknown_unicast_(false),
75  learning_enabled_(nh->learning_enabled()), need_pbb_tunnel_(false),
76  etree_leaf_ (false), layer2_control_word_(false),
77  crypt_(false), crypt_path_available_(false), crypt_interface_(NULL),
78  interface_list_(), encap_valid_list_(), dmac_list_() {
79 
80  switch (type_) {
81  case NextHop::ARP: {
82  const ArpNH *arp = static_cast<const ArpNH *>(nh);
83  vrf_id_ = arp->vrf_id();
84  sip_ = *(arp->GetIp());
85  break;
86  }
87 
88  case NextHop::NDP: {
89  const NdpNH *ndp = static_cast<const NdpNH *>(nh);
90  vrf_id_ = ndp->vrf_id();
91  sip_ = *(ndp->GetIp());
92  break;
93  }
94 
95  case NextHop::INTERFACE: {
96  InterfaceKSyncObject *interface_object =
98  const InterfaceNH *if_nh = static_cast<const InterfaceNH *>(nh);
99  InterfaceKSyncEntry if_ksync(interface_object, if_nh->GetInterface());
100  interface_ = interface_object->GetReference(&if_ksync);
101  assert(interface_);
102  is_mcast_nh_ = if_nh->is_multicastNH();
103  is_bridge_ = if_nh->IsBridge();
105  const VrfEntry * vrf = if_nh->GetVrf();
106  vrf_id_ = (vrf != NULL) ? vrf->vrf_id() : VrfEntry::kInvalidIndex;
107  dmac_ = if_nh->GetDMac();
108  // VmInterface can potentially have vlan-tags. Get tag in such case
109  if (if_nh->GetInterface()->type() == Interface::VM_INTERFACE) {
110  vlan_tag_ = (static_cast<const VmInterface *>
111  (if_nh->GetInterface()))->tx_vlan_id();
112  }
113  break;
114  }
115 
116  case NextHop::VLAN: {
117  InterfaceKSyncObject *interface_object =
119  const VlanNH *vlan_nh = static_cast<const VlanNH *>(nh);
120  InterfaceKSyncEntry if_ksync(interface_object, vlan_nh->GetInterface());
121  interface_ = interface_object->GetReference(&if_ksync);
122  assert(interface_);
123  vlan_tag_ = vlan_nh->GetVlanTag();
124  vrf_id_ = vlan_nh->GetVrf()->vrf_id();
125  break;
126  }
127 
128  case NextHop::TUNNEL: {
129  const TunnelNH *tunnel = static_cast<const TunnelNH *>(nh);
130  vrf_id_ = tunnel->vrf_id();
131  sip_ = *(tunnel->GetSip());
132  dip_ = *(tunnel->GetDip());
133  tunnel_type_ = tunnel->GetTunnelType();
134  crypt_ = tunnel->GetCrypt();
136 
137  if (tunnel->GetCryptInterface()) {
138  InterfaceKSyncObject *crypt_interface_object =
140  InterfaceKSyncEntry if_ksync(crypt_interface_object, tunnel->GetCryptInterface());
141  crypt_interface_ = crypt_interface_object->GetReference(&if_ksync);
142  }
143  rewrite_dmac_ = tunnel->rewrite_dmac();
145  const LabelledTunnelNH *labelled_tunnel =
146  static_cast<const LabelledTunnelNH *>(nh);
147  label_ = labelled_tunnel->GetTransportLabel();
149  labelled_tunnel->GetTransportTunnelType();
150  }
151  break;
152  }
153 
154  case NextHop::DISCARD: {
155  break;
156  }
157 
158  case NextHop::L2_RECEIVE: {
159  break;
160  }
161 
162  case NextHop::RESOLVE: {
163  InterfaceKSyncObject *interface_object =
165  const ResolveNH *rsl_nh = static_cast<const ResolveNH *>(nh);
166  InterfaceKSyncEntry if_ksync(interface_object, rsl_nh->get_interface());
167  interface_ = interface_object->GetReference(&if_ksync);
168  vrf_id_ = rsl_nh->get_interface()->vrf_id();
169  if (rsl_nh->get_interface()->type() == Interface::VM_INTERFACE) {
170  const VmInterface *vm_intf =
171  static_cast<const VmInterface *>(rsl_nh->get_interface());
172  if (vm_intf->vrf()->forwarding_vrf()) {
173  vrf_id_ = vm_intf->vrf()->forwarding_vrf()->vrf_id();
174  }
175  }
176  break;
177  }
178 
179  case NextHop::VRF: {
180  const VrfNH *vrf_nh = static_cast<const VrfNH *>(nh);
181  vrf_id_ = vrf_nh->GetVrf()->vrf_id();
182  bridge_nh_ = vrf_nh->bridge_nh();
183  break;
184  }
185 
186  case NextHop::RECEIVE: {
187  InterfaceKSyncObject *interface_object =
189  const ReceiveNH *rcv_nh = static_cast<const ReceiveNH *>(nh);
190  InterfaceKSyncEntry if_ksync(interface_object, rcv_nh->GetInterface());
191  interface_ = interface_object->GetReference(&if_ksync);
192  vrf_id_ = rcv_nh->GetInterface()->vrf_id();
193  assert(interface_);
194  break;
195  }
196 
197  case NextHop::MIRROR: {
198  const MirrorNH *mirror_nh = static_cast<const MirrorNH *>(nh);
199  vrf_id_ = mirror_nh->vrf_id();
200  sip_ = *(mirror_nh->GetSip());
201  sport_ = mirror_nh->GetSPort();
202  dip_ = *(mirror_nh->GetDip());
203  dport_ = mirror_nh->GetDPort();
204  break;
205  }
206 
207  case NextHop::PBB: {
208  const PBBNH *pbb_nh = static_cast<const PBBNH *>(nh);
209  vrf_id_ = pbb_nh->vrf_id();
210  dmac_ = pbb_nh->dest_bmac();
211  isid_ = pbb_nh->isid();
212  break;
213  }
214 
215  case NextHop::COMPOSITE: {
216  const CompositeNH *comp_nh = static_cast<const CompositeNH *>(nh);
217  component_nh_list_.clear();
218  vrf_id_ = comp_nh->vrf()->vrf_id();
219  comp_type_ = comp_nh->composite_nh_type();
222  const_cast<CompositeNH *>(comp_nh)->CompEcmpHashFields().HashFieldsToUse();
224  ComponentNHList::const_iterator component_nh_it =
225  comp_nh->begin();
226  while (component_nh_it != comp_nh->end()) {
227  const NextHop *component_nh = NULL;
228  uint32_t label = 0;
229  if (*component_nh_it) {
230  component_nh = (*component_nh_it)->nh();
231  label = (*component_nh_it)->label();
232  }
233  KSyncEntry *ksync_nh = NULL;
234  if (component_nh != NULL) {
235  NHKSyncObject *nh_object =
237  NHKSyncEntry nhksync(nh_object, component_nh);
238  ksync_nh = nh_object->GetReference(&nhksync);
239  }
240  KSyncComponentNH ksync_component_nh(label, ksync_nh);
241  component_nh_list_.push_back(ksync_component_nh);
242  component_nh_it++;
243  }
244  break;
245  }
246 
247  default:
248  assert(0);
249  break;
250  }
251 }
252 
254 }
255 
257  return ksync_obj_;
258 }
259 
260 bool NHKSyncEntry::IsLess(const KSyncEntry &rhs) const {
261  const NHKSyncEntry &entry = static_cast<const NHKSyncEntry &>(rhs);
262 
263  if (type_ != entry.type_) {
264  return type_ < entry.type_;
265  }
266 
267  if (type_ == NextHop::DISCARD) {
268  return false;
269  }
270 
271  if (type_ == NextHop::L2_RECEIVE) {
272  return false;
273  }
274 
275  if (type_ == NextHop::ARP || type_ == NextHop::NDP) {
276  //Policy is ignored for ARP NH
277  if (vrf_id_ != entry.vrf_id_) {
278  return vrf_id_ < entry.vrf_id_;
279  }
280  return sip_ < entry.sip_;
281  }
282 
283  if (policy_ != entry.policy_) {
284  return policy_ < entry.policy_;
285  }
286 
287  if (type_ == NextHop::VRF) {
288  if ( vrf_id_ != entry.vrf_id_) {
289  return vrf_id_ < entry.vrf_id_;
290  }
291  return bridge_nh_ < entry.bridge_nh_;
292  }
293 
294  if (type_ == NextHop::INTERFACE) {
295  if (is_mcast_nh_ != entry.is_mcast_nh_) {
296  return is_mcast_nh_ < entry.is_mcast_nh_;
297  }
298  if(is_bridge_ != entry.is_bridge_) {
299  return is_bridge_ < entry.is_bridge_;
300  }
301 
302  if(is_vxlan_routing_ != entry.is_vxlan_routing_) {
303  return is_vxlan_routing_ < entry.is_vxlan_routing_;
304  }
305 
306  if (dmac_ != entry.dmac_) {
307  return dmac_ < entry.dmac_;
308  }
309 
310  return interface() < entry.interface();
311  }
312 
314  return interface() < entry.interface();
315  }
316 
317 
318  if (type_ == NextHop::TUNNEL) {
319  if (vrf_id_ != entry.vrf_id_) {
320  return vrf_id_ < entry.vrf_id_;
321  }
322 
323  if (sip_ != entry.sip_) {
324  return sip_ < entry.sip_;
325  }
326 
327  if (dip_ != entry.dip_) {
328  return dip_ < entry.dip_;
329  }
330 
331  if (crypt_ != entry.crypt_) {
332  return crypt_ < entry.crypt_;
333  }
334 
337  }
338 
339  if (crypt_interface() != entry.crypt_interface()) {
340  return crypt_interface() < entry.crypt_interface();
341  }
342 
343  if (rewrite_dmac_ != entry.rewrite_dmac_) {
344  return rewrite_dmac_ < entry.rewrite_dmac_;
345  }
346  if (tunnel_type_.Compare(entry.tunnel_type_) == false) {
347  return tunnel_type_.IsLess(entry.tunnel_type_);
348  }
350  return label_ < entry.label_;
351  }
352  }
353 
354  if (type_ == NextHop::MIRROR) {
355  if (vrf_id_ != entry.vrf_id_) {
356  return vrf_id_ < entry.vrf_id_;
357  }
358 
359  if (dip_ != entry.dip_) {
360  return dip_ < entry.dip_;
361  }
362 
363  return dport_ < entry.dport_;
364  }
365 
366  if (type_ == NextHop::PBB) {
367  if (vrf_id_ != entry.vrf_id_) {
368  return vrf_id_ < entry.vrf_id_;
369  }
370 
371  if (dmac_ != entry.dmac_) {
372  return dmac_ < entry.dmac_;
373  }
374 
375  return isid_ < entry.isid_;
376  }
377 
378  if (type_ == NextHop::COMPOSITE) {
379  if (comp_type_ != entry.comp_type_) {
380  return comp_type_ < entry.comp_type_;
381  }
382 
383  if (vrf_id_ != entry.vrf_id_) {
384  return vrf_id_ < entry.vrf_id_;
385  }
386 
387  ComponentNHKeyList::const_iterator it =
388  component_nh_key_list_.begin();
389  ComponentNHKeyList::const_iterator entry_it =
390  entry.component_nh_key_list_.begin();
391  for (;it != component_nh_key_list_.end() &&
392  entry_it != entry.component_nh_key_list_.end(); it++, entry_it++) {
393  if (*it == NULL &&
394  *entry_it == NULL) {
395  continue;
396  }
397  //One of the component NH is NULL
398  if ((*it) == NULL ||
399  (*entry_it) == NULL) {
400  return (*it) < (*entry_it);
401  }
402 
403  //Check if the label is different
404  if ((*it)->label() !=
405  (*entry_it)->label()) {
406  return (*it)->label() <
407  (*entry_it)->label();
408  }
409 
410  //Check if the nexthop key is different
411  //Ideally we could find the nexthop and compare pointer alone
412  //it wont work because this is called from Find context itself,
413  //and it would result in deadlock
414  //Hence compare nexthop key alone
415  const NextHopKey *left_nh = (*it)->nh_key();
416  const NextHopKey *right_nh = (*entry_it)->nh_key();
417 
418  if (left_nh->IsEqual(*right_nh) == false) {
419  if (left_nh->GetType() != right_nh->GetType()) {
420  return left_nh->GetType() < right_nh->GetType();
421  }
422  return left_nh->IsLess(*right_nh);
423  }
424 
425  }
426 
427  if (it == component_nh_key_list_.end() &&
428  entry_it == entry.component_nh_key_list_.end()) {
429  return false;
430  }
431 
432  if (it == component_nh_key_list_.end()) {
433  return true;
434  }
435  return false;
436  }
437 
438  if (type_ == NextHop::VLAN) {
439  if (interface() != entry.interface()) {
440  return interface() < entry.interface();
441 
442  }
443 
444  return vlan_tag_ < entry.vlan_tag_;
445  }
446 
447  return false;
448 
449  assert(0);
450 }
451 
452 std::string NHKSyncEntry::ToString() const {
453  std::stringstream s;
454  s << "NextHop Index: " << nh_id() << " Type: ";
455  switch(type_) {
456  case NextHop::DISCARD: {
457  s << "Discard";
458  break;
459  }
460  case NextHop::L2_RECEIVE: {
461  s << "L2-Receive ";
462  break;
463  }
464  case NextHop::RECEIVE: {
465  s << "Receive ";
466  break;
467  }
468  case NextHop::RESOLVE: {
469  s << "Resolve ";
470  break;
471  }
472  case NextHop::ARP: {
473  s << "ARP ";
474  break;
475  }
476  case NextHop::NDP: {
477  s << "NDP ";
478  break;
479  }
480  case NextHop::VRF: {
481  s << "VRF assign to ";
482  const VrfEntry* vrf =
483  ksync_obj_->ksync()->agent()->vrf_table()->
484  FindVrfFromId(vrf_id_);
485  if (vrf) {
486  s << vrf->GetName() << " ";
487  } else {
488  s << "Invalid ";
489  }
490  break;
491  }
492  case NextHop::INTERFACE: {
493  s << "Interface ";
494  break;
495  }
496  case NextHop::TUNNEL: {
497  s << "Tunnel to ";
498  s << dip_.to_string();
499  s << "rewrite_dmac";
500  s << rewrite_dmac_.ToString();
501  break;
502  }
503  case NextHop::MIRROR: {
504  s << "Mirror to ";
505  s << dip_.to_string() << ": " << dport_;
506  break;
507  }
508  case NextHop::VLAN: {
509  s << "VLAN interface ";
510  break;
511  }
512  case NextHop::COMPOSITE: {
513  s << "Composite Child members: ";
514  if (component_nh_list_.size() == 0) {
515  s << "Empty ";
516  }
517  for (KSyncComponentNHList::const_iterator it = component_nh_list_.begin();
518  it != component_nh_list_.end(); it++) {
519  KSyncComponentNH component_nh = *it;
520  if (component_nh.nh()) {
521  s << component_nh.nh()->ToString();
522  }
523  }
524  break;
525  }
526  case NextHop::INVALID: {
527  s << "Invalid ";
528  }
529 
530  case NextHop::PBB: {
531  s << "PBB";
532  break;
533  }
534  }
535 
536  if (interface_) {
537  s << "<" << interface_->ToString() << ">";
538  }
539  return s.str();
540 }
541 
543  bool ret = false;
544  const NextHop *nh = static_cast<NextHop *>(e);
545 
546  if (valid_ != nh->IsValid()) {
547  valid_ = nh->IsValid();
548  ret = true;
549  }
550 
553  ret = true;
554  }
555 
556  if (etree_leaf_ != nh->etree_leaf()) {
558  ret = true;
559  }
560 
561  switch (nh->GetType()) {
562  case NextHop::ARP: {
563  InterfaceKSyncObject *interface_object =
565  ArpNH *arp_nh = static_cast<ArpNH *>(e);
566  if (dmac_ != arp_nh->GetMac()) {
567  dmac_ = arp_nh->GetMac();
568  ret = true;
569  }
570 
571  if (valid_) {
572  InterfaceKSyncEntry if_ksync(interface_object,
573  arp_nh->GetInterface());
574  if (interface_ != interface_object->GetReference(&if_ksync)) {
575  interface_ = interface_object->GetReference(&if_ksync);
576  ret = true;
577  }
578  } else {
579  if (interface_ != NULL) {
580  interface_ = NULL;
581  dmac_.Zero();
582  ret = true;
583  }
584  }
585  break;
586  }
587 
588  case NextHop::NDP: {
589  InterfaceKSyncObject *interface_object =
591  NdpNH *ndp_nh = static_cast<NdpNH *>(e);
592  if (dmac_ != ndp_nh->GetMac()) {
593  dmac_ = ndp_nh->GetMac();
594  ret = true;
595  }
596 
597  if (valid_) {
598  InterfaceKSyncEntry if_ksync(interface_object,
599  ndp_nh->GetInterface());
600  if (interface_ != interface_object->GetReference(&if_ksync)) {
601  interface_ = interface_object->GetReference(&if_ksync);
602  ret = true;
603  }
604  } else {
605  if (interface_ != NULL) {
606  interface_ = NULL;
607  dmac_.Zero();
608  ret = true;
609  }
610  }
611  break;
612  }
613 
614  case NextHop::INTERFACE: {
615  InterfaceNH *intf_nh = static_cast<InterfaceNH *>(e);
616  dmac_ = intf_nh->GetDMac();
617  uint16_t vlan_tag = VmInterface::kInvalidVlanId;
618  if (intf_nh->GetInterface()->type() == Interface::VM_INTERFACE) {
619  vlan_tag = vlan_tag_;
620  vlan_tag_ = (static_cast<const VmInterface *>
621  (intf_nh->GetInterface()))->tx_vlan_id();
622  if (vlan_tag != vlan_tag_) {
623  ret = true;
624  }
625  }
626  if (layer2_control_word_ != intf_nh->layer2_control_word()) {
628  ret = true;
629  }
630 
631  const VrfEntry * vrf = intf_nh->GetVrf();
632  uint32_t vrf_id = (vrf != NULL)? vrf->vrf_id() :VrfEntry::kInvalidIndex;
633  if (vrf_id_ != vrf_id) {
634  vrf_id_ = vrf_id;
635  ret = true;
636  }
637  break;
638  }
639 
640  case NextHop::DISCARD: {
641  ret = false;
642  break;
643  }
644 
645  case NextHop::L2_RECEIVE: {
646  ret = false;
647  break;
648  }
649 
650  case NextHop::TUNNEL: {
651  ret = true;
652 
653  // If the nh IDs of KSyncEntry and NextHop objects dont match, sync them
654  // along with nh_ pointer. It can happen if the NHKSyncEntry got
655  // created in TEMP state with previous incarnation of this Tunnel NH
656  if (nh_id_ != nh->id()) {
657  nh_id_ = nh->id();
658  nh_ = nh;
659  ret = true;
660  }
661 
662  // Invalid nexthop, no valid interface or mac info
663  // present, just return
664  if (valid_ == false) {
665  if (interface_ != NULL) {
666  interface_ = NULL;
667  dmac_.Zero();
668  ret = true;
669  }
670  break;
671  }
672 
673  KSyncEntryPtr interface = NULL;
674  MacAddress dmac;
675  const TunnelNH *tun_nh = static_cast<TunnelNH *>(e);
676  const NextHop *active_nh = tun_nh->GetRt()->GetActiveNextHop();
677  // active nexthop can be NULL as when arp rt is delete marked and
678  // is enqueued for notify.
679  if (active_nh == NULL) {
680  if (interface_ != NULL) {
681  interface_ = NULL;
682  dmac_.Zero();
683  ret = true;
684  }
685  break;
686  }
687 
688  if (active_nh->GetType() == NextHop::ARP) {
689  const ArpNH *arp_nh = static_cast<const ArpNH *>(active_nh);
690  InterfaceKSyncObject *interface_object =
692  InterfaceKSyncEntry if_ksync(interface_object, arp_nh->GetInterface());
693  interface = interface_object->GetReference(&if_ksync);
694  dmac = arp_nh->GetMac();
695  } else if (active_nh->GetType() == NextHop::NDP) {
696  const NdpNH *ndp_nh = static_cast<const NdpNH *>(active_nh);
697  InterfaceKSyncObject *interface_object =
699  InterfaceKSyncEntry if_ksync(interface_object, ndp_nh->GetInterface());
700  interface = interface_object->GetReference(&if_ksync);
701  dmac = ndp_nh->GetMac();
702  } else if (active_nh->GetType() == NextHop::INTERFACE) {
703  const InterfaceNH *intf_nh =
704  static_cast<const InterfaceNH *>(active_nh);
705  const Interface *oper_intf = intf_nh->GetInterface();
706  InterfaceKSyncObject *interface_object =
708  InterfaceKSyncEntry if_ksync(interface_object, oper_intf);
709  interface = interface_object->GetReference(&if_ksync);
710  dmac = oper_intf->mac();
711  } else if (active_nh->GetType() == NextHop::COMPOSITE) {
712  const CompositeNH *cnh =
713  static_cast<const CompositeNH *>(active_nh);
714  interface_list_.clear();
715  encap_valid_list_.clear();
716  dmac_list_.clear();
717  ComponentNHList::const_iterator component_nh_it =
718  cnh->begin();
719  while (component_nh_it != cnh->end()) {
720  const NextHop *component_nh = NULL;
721  if (*component_nh_it) {
722  component_nh = (*component_nh_it)->nh();
723  if (component_nh->GetType() == NextHop::ARP) {
724  const ArpNH *arp_nh = dynamic_cast<const ArpNH*>(component_nh);
725  InterfaceKSyncObject *interface_object =
727  InterfaceKSyncEntry if_ksync(interface_object, arp_nh->GetInterface());
728  interface_list_.push_back(interface_object->GetReference(&if_ksync));
729  encap_valid_list_.push_back(arp_nh->IsValid());
730  dmac_list_.push_back(arp_nh->GetMac());
731  }
732  }
733  component_nh_it++;
734  }
735 
736  /* vRouter expects encap_valid vector should always be size = 3.
737  * It helps in accessing valid enacp_data and oif */
738  while (encap_valid_list_.size() < MAX_VR_PHY_INTF) {
739  encap_valid_list_.push_back(false);
740  }
741  }
742 
743  bool crypt = tun_nh->GetCrypt();
744  if (crypt != crypt_) {
745  crypt_ = crypt;
746  ret = true;
747  }
748 
749  bool crypt_path_available = tun_nh->GetCryptTunnelAvailable();
750  if (crypt_path_available != crypt_path_available_) {
751  crypt_path_available_ = crypt_path_available;
752  ret = true;
753  }
754 
755  const Interface *oper_crypt_intf = tun_nh->GetCryptInterface();
756 
757  if (tun_nh->GetCryptInterface()) {
758  InterfaceKSyncObject *crypt_interface_object =
760  InterfaceKSyncEntry if_ksync(crypt_interface_object, oper_crypt_intf);
761  KSyncEntryPtr crypt_interface = crypt_interface_object->GetReference(&if_ksync);
762 
765  ret = true;
766  }
767  }
769  const LabelledTunnelNH *labelled_tunnel =
770  static_cast<const LabelledTunnelNH *>(nh);
771  if (label_ != labelled_tunnel->GetTransportLabel()) {
772  label_ = labelled_tunnel->GetTransportLabel();
773  ret = true;
774  }
776  labelled_tunnel->GetTransportTunnelType()) {
778  labelled_tunnel->GetTransportTunnelType();
779  ret = true;
780  }
781  }
782 
783  if (dmac != dmac_) {
784  dmac_ = dmac;
785  ret = true;
786  }
787  if (interface_ != interface) {
789  ret = true;
790  }
791  break;
792  }
793 
794  case NextHop::MIRROR: {
795  ret = true;
796  // Invalid nexthop, no valid interface or mac info
797  // present, just return
798  if (valid_ == false || (vrf_id_ == (uint32_t)-1)) {
799  if (interface_ != NULL) {
800  interface_ = NULL;
801  dmac_.Zero();
802  ret = true;
803  }
804  break;
805  }
806 
807  KSyncEntryPtr interface = NULL;
808  MacAddress dmac;
809  bool valid = valid_;
810 
811  const MirrorNH *mirror_nh = static_cast<MirrorNH *>(e);
812  const NextHop *active_nh = mirror_nh->GetRt()->GetActiveNextHop();
813  if (active_nh) {
814  if (active_nh->GetType() == NextHop::ARP) {
815  const ArpNH *arp_nh = static_cast<const ArpNH *>(active_nh);
816  InterfaceKSyncObject *interface_object =
818  InterfaceKSyncEntry if_ksync(interface_object,
819  arp_nh->GetInterface());
820  interface = interface_object->GetReference(&if_ksync);
821  dmac = arp_nh->GetMac();
822  } else if (active_nh->GetType() == NextHop::NDP) {
823  const NdpNH *ndp_nh = static_cast<const NdpNH *>(active_nh);
824  InterfaceKSyncObject *interface_object =
826  InterfaceKSyncEntry if_ksync(interface_object,
827  ndp_nh->GetInterface());
828  interface = interface_object->GetReference(&if_ksync);
829  dmac = ndp_nh->GetMac();
830  } else if (active_nh->GetType() == NextHop::RECEIVE) {
831  const ReceiveNH *rcv_nh = static_cast<const ReceiveNH *>(active_nh);
832  InterfaceKSyncObject *interface_object =
834  InterfaceKSyncEntry if_ksync(interface_object,
835  rcv_nh->GetInterface());
836  interface = interface_object->GetReference(&if_ksync);
837  Agent *agent = ksync_obj_->ksync()->agent();
838  dmac = agent->vhost_interface()->mac();
839  } else if (active_nh->GetType() == NextHop::DISCARD) {
840  valid = false;
841  interface = NULL;
842  }
843  } else {
844  valid = false;
845  interface = NULL;
846  }
847 
848  if (valid_ != valid) {
849  valid_ = valid;
850  ret = true;
851  }
852  if (dmac_ != dmac) {
853  dmac_ = dmac;
854  ret = true;
855  }
856  if (interface_ != interface) {
858  ret = true;
859  }
860  break;
861  }
862 
863  case NextHop::PBB: {
864  PBBNH *pbb_nh = static_cast<PBBNH *>(e);
865  if (pbb_label_ != pbb_nh->label()) {
866  pbb_label_ = pbb_nh->label();
867  ret = true;
868  }
869 
870  NHKSyncObject *nh_object =
872  NHKSyncEntry nhksync(nh_object, pbb_nh->child_nh());
873  KSyncEntry *ksync_nh = nh_object->GetReference(&nhksync);
874  if (ksync_nh != pbb_child_nh_) {
875  pbb_child_nh_ = ksync_nh;
876  ret = true;
877  }
878  break;
879  }
880 
881  case NextHop::COMPOSITE: {
882  ret = true;
883  CompositeNH *comp_nh = static_cast<CompositeNH *>(e);
884  component_nh_list_.clear();
885  ComponentNHList::const_iterator component_nh_it =
886  comp_nh->begin();
887  while (component_nh_it != comp_nh->end()) {
888  const NextHop *component_nh = NULL;
889  uint32_t label = 0;
890  if (*component_nh_it) {
891  component_nh = (*component_nh_it)->nh();
892  label = (*component_nh_it)->label();
893  }
894  KSyncEntry *ksync_nh = NULL;
895  if (component_nh != NULL) {
896  NHKSyncObject *nh_object =
898  NHKSyncEntry nhksync(nh_object, component_nh);
899  ksync_nh = nh_object->GetReference(&nhksync);
900  }
901  KSyncComponentNH ksync_component_nh(label, ksync_nh);
902  component_nh_list_.push_back(ksync_component_nh);
903  component_nh_it++;
904  }
905 
908  ret = true;
909  }
910 
911  if (need_pbb_tunnel_ != comp_nh->pbb_nh()) {
912  need_pbb_tunnel_ = comp_nh->pbb_nh();
913  ret = true;
914  }
915 
916  if (layer2_control_word_ != comp_nh->layer2_control_word()) {
918  ret = true;
919  }
920  break;
921  }
922 
923  case NextHop::VLAN: {
924  VlanNH *vlan_nh = static_cast<VlanNH *>(e);
925  smac_ = vlan_nh->GetSMac();
926  dmac_ = vlan_nh->GetDMac();
927  ret = false;
928  break;
929  }
930 
931  case NextHop::VRF: {
932  VrfNH *vrf_nh = static_cast<VrfNH *>(e);
933  vrf_id_ = vrf_nh->GetVrf()->vrf_id();
934  ret = false;
935  if (bridge_nh_ != vrf_nh->bridge_nh()) {
936  bridge_nh_ = vrf_nh->bridge_nh();
937  ret = true;
938  }
939 
942  ret = true;
943  }
944 
945  if (layer2_control_word_ != vrf_nh->layer2_control_word()) {
947  ret = true;
948  }
949  break;
950  }
951  case NextHop::RECEIVE:
952  case NextHop::RESOLVE: {
953  valid_ = true;
954  ret = true;
955  break;
956  }
957 
958  default:
959  assert(0);
960  }
961 
962  return ret;
963 };
964 int NHKSyncEntry::Encode(sandesh_op::type op, char *buf, int buf_len) {
965  vr_nexthop_req encoder;
966  int encode_len;
967  uint32_t crypt_intf_id = kInvalidIndex;
968  uint32_t intf_id = kInvalidIndex;
969  std::vector<int8_t> encap;
970  InterfaceKSyncEntry *if_ksync = NULL;
971  InterfaceKSyncEntry *crypt_if_ksync = NULL;
972  std::vector<KSyncEntryPtr> if_ksync_list;
973  std::vector<int32_t> nhr_encap_valid_list;
974  std::vector<int32_t> intf_id_list;
975  Agent *agent = ksync_obj_->ksync()->agent();
976 
977  encoder.set_h_op(op);
978  encoder.set_nhr_id(nh_id());
979  if (op == sandesh_op::DEL) {
980  /* For delete only NH-index is required by vrouter */
981  int error = 0;
982  encode_len = encoder.WriteBinary((uint8_t *)buf, buf_len, &error);
983  assert(error == 0);
984  assert(encode_len <= buf_len);
985  return encode_len;
986  }
987  encoder.set_nhr_rid(0);
988  encoder.set_nhr_vrf(vrf_id_);
989  encoder.set_nhr_family(AF_INET);
990  uint32_t flags = 0;
991  if (valid_) {
992  flags |= NH_FLAG_VALID;
993  }
994 
995  if (policy_) {
996  flags |= NH_FLAG_POLICY_ENABLED;
997  }
998 
999  if (etree_leaf_ == false) {
1000  flags |= NH_FLAG_ETREE_ROOT;
1001  }
1002 
1003  if (learning_enabled_) {
1004  flags |= NH_FLAG_MAC_LEARN;
1005  }
1006 
1007  if (layer2_control_word_) {
1008  flags |= NH_FLAG_L2_CONTROL_DATA;
1009  }
1010 
1011  if (crypt_) {
1012  flags |= NH_FLAG_CRYPT_TRAFFIC;
1013  }
1014 
1015  if_ksync = interface();
1016  if_ksync_list = interface_list();
1017  nhr_encap_valid_list = encap_valid_list();
1018  crypt_if_ksync = crypt_interface();
1019 
1020  switch (type_) {
1021  case NextHop::VLAN:
1022  case NextHop::ARP:
1023  case NextHop::NDP:
1024  case NextHop::INTERFACE :
1025  encoder.set_nhr_type(NH_ENCAP);
1026  if (if_ksync) {
1027  intf_id = if_ksync->interface_id();
1028  }
1029  encoder.set_nhr_encap_oif_id(std::vector<int32_t>(1, intf_id));
1030  encoder.set_nhr_encap_family(ETHERTYPE_ARP);
1031 
1032  SetEncap(if_ksync, encap);
1033  encoder.set_nhr_encap(encap);
1034  encoder.set_nhr_tun_sip(0);
1035  encoder.set_nhr_tun_dip(0);
1036  if (is_vxlan_routing_) {
1037  //Set vxlan routing flag
1038  flags |= NH_FLAG_L3_VXLAN;
1039  }
1040  if (is_bridge_) {
1041  encoder.set_nhr_family(AF_BRIDGE);
1042  }
1043  if (is_mcast_nh_) {
1044  flags |= NH_FLAG_MCAST;
1045  }
1046  encoder.set_nhr_flags(flags);
1047  break;
1048 
1049  case NextHop::TUNNEL : {
1050  encoder.set_nhr_type(NH_TUNNEL);
1051  encoder.set_nhr_tun_sip(htonl(sip_.to_v4().to_ulong()));
1052  encoder.set_nhr_tun_dip(htonl(dip_.to_v4().to_ulong()));
1053  encoder.set_nhr_encap_family(ETHERTYPE_ARP);
1054 
1055  if (if_ksync_list.empty() == false) {
1056  flags |= NH_FLAG_TUNNEL_UNDERLAY_ECMP;
1057  uint32_t encap_len = 0;
1058  for (size_t i = 0; i < if_ksync_list.size(); ++i) {
1059  InterfaceKSyncEntry *if_ksync_entry =
1060  static_cast<InterfaceKSyncEntry *>(if_ksync_list[i].get());
1061  intf_id_list.push_back(if_ksync_entry->interface_id());
1062  encap_len = encap.size();
1063  SetEncap(if_ksync_entry, encap, i);
1064  encap_len = encap.size() - encap_len;
1065  }
1066  encoder.set_nhr_encap_len(encap_len);
1067  } else {
1068  SetEncap(if_ksync, encap);
1069  intf_id_list.push_back(0);
1070  }
1071  encoder.set_nhr_encap_oif_id(intf_id_list);
1072  encoder.set_nhr_encap_valid(nhr_encap_valid_list);
1073  encoder.set_nhr_crypt_traffic(crypt_);
1074  encoder.set_nhr_crypt_path_available(crypt_path_available_);
1075  if (crypt_if_ksync && crypt_path_available_) {
1076  crypt_intf_id = crypt_if_ksync->interface_id();
1077  }
1078  encoder.set_nhr_encap_crypt_oif_id(crypt_intf_id);
1079  encoder.set_nhr_encap(encap);
1081  flags |= NH_FLAG_TUNNEL_UDP_MPLS;
1082  } else if (tunnel_type_.GetType() == TunnelType::MPLS_GRE) {
1083  flags |= NH_FLAG_TUNNEL_GRE;
1084  } else if (tunnel_type_.GetType() == TunnelType::NATIVE) {
1085  //Ideally we should have created a new type of
1086  //indirect nexthop to handle NATIVE encap
1087  //reusing tunnel NH as it provides most of
1088  //functionality now
1089  encoder.set_nhr_type(NH_ENCAP);
1090  encoder.set_nhr_encap_oif_id(intf_id_list);
1091  encoder.set_nhr_encap_family(ETHERTYPE_ARP);
1092  encoder.set_nhr_tun_sip(0);
1093  encoder.set_nhr_tun_dip(0);
1095  flags |= NH_FLAG_TUNNEL_MPLS_O_MPLS;
1097  flags |= NH_FLAG_TUNNEL_UDP_MPLS;
1098  } else {
1099  flags |= NH_FLAG_TUNNEL_GRE;
1100  }
1101 
1102  encoder.set_nhr_transport_label(label_);
1103  } else {
1104  flags |= NH_FLAG_TUNNEL_VXLAN;
1105  }
1106  std::vector<int8_t> rewrite_dmac;
1107  for (size_t i = 0 ; i < rewrite_dmac_.size(); i++) {
1108  rewrite_dmac.push_back(rewrite_dmac_[i]);
1109  }
1110  encoder.set_nhr_rw_dst_mac(rewrite_dmac);
1111  //TODO remove set_nhr_pbb_mac
1112  encoder.set_nhr_pbb_mac(rewrite_dmac);
1113  if (rewrite_dmac_.IsZero() == false) {
1114  flags |= NH_FLAG_L3_VXLAN;
1115  }
1116  break;
1117  }
1118  case NextHop::MIRROR :
1119  encoder.set_nhr_type(NH_TUNNEL);
1120  if (sip_.is_v4() && dip_.is_v4()) {
1121  encoder.set_nhr_tun_sip(htonl(sip_.to_v4().to_ulong()));
1122  encoder.set_nhr_tun_dip(htonl(dip_.to_v4().to_ulong()));
1123  } else if (sip_.is_v6() && dip_.is_v6()) {
1124  encoder.set_nhr_family(AF_INET6);
1125  Ip6Address::bytes_type bytes = sip_.to_v6().to_bytes();
1126  std::vector<int8_t> sip_vector(bytes.begin(), bytes.end());
1127  bytes = dip_.to_v6().to_bytes();
1128  std::vector<int8_t> dip_vector(bytes.begin(), bytes.end());
1129  encoder.set_nhr_tun_sip6(sip_vector);
1130  encoder.set_nhr_tun_dip6(dip_vector);
1131  }
1132  encoder.set_nhr_tun_sport(htons(sport_));
1133  encoder.set_nhr_tun_dport(htons(dport_));
1134  encoder.set_nhr_encap_family(ETHERTYPE_ARP);
1135 
1136  if (if_ksync) {
1137  intf_id = if_ksync->interface_id();
1138  }
1139  encoder.set_nhr_encap_oif_id(std::vector<int32_t>(1, intf_id));
1140  SetEncap(NULL,encap);
1141  encoder.set_nhr_encap(encap);
1142  flags |= NH_FLAG_TUNNEL_UDP;
1143  if (vrf_id_ != agent->fabric_vrf()->vrf_id()) {
1144  flags |= NH_FLAG_TUNNEL_SIP_COPY;
1145  }
1146  break;
1147 
1148  case NextHop::L2_RECEIVE:
1149  encoder.set_nhr_type(NH_L2_RCV);
1150  break;
1151 
1152  case NextHop::DISCARD:
1153  encoder.set_nhr_type(NH_DISCARD);
1154  break;
1155 
1156  case NextHop::RECEIVE:
1157  if (!policy_) {
1158  flags |= NH_FLAG_RELAXED_POLICY;
1159  }
1160  intf_id = if_ksync->interface_id();
1161  encoder.set_nhr_encap_oif_id(std::vector<int32_t>(1, intf_id));
1162  encoder.set_nhr_type(NH_RCV);
1163  break;
1164 
1165  case NextHop::RESOLVE:
1166  if (policy_) {
1167  //Policy bit is used in agent to copy over the
1168  //field to ARP nexthop that gets created from
1169  //resolve NH in case of gateway interface,
1170  //but the same is not needed in vrouter.
1171  //If policy bit is enabled then first packet
1172  //resulting flow with key NH of resolve NH
1173  //followed by next packet with ARP NH as key
1174  //resulting in flow drops
1175  flags &= ~NH_FLAG_POLICY_ENABLED;
1176  }
1177  encoder.set_nhr_type(NH_RESOLVE);
1178  break;
1179 
1180  case NextHop::VRF:
1181  encoder.set_nhr_type(NH_VXLAN_VRF);
1182  if (bridge_nh_ == true) {
1183  encoder.set_nhr_family(AF_BRIDGE);
1184  }
1185  if (flood_unknown_unicast_) {
1186  flags |= NH_FLAG_UNKNOWN_UC_FLOOD;
1187  }
1188  break;
1189 
1190  case NextHop::PBB: {
1191  encoder.set_nhr_family(AF_BRIDGE);
1192  encoder.set_nhr_type(NH_TUNNEL);
1193  flags |= (NH_FLAG_TUNNEL_PBB | NH_FLAG_INDIRECT);
1194  std::vector<int8_t> bmac;
1195  for (size_t i = 0 ; i < dmac_.size(); i++) {
1196  bmac.push_back(dmac_[i]);
1197  }
1198  encoder.set_nhr_pbb_mac(bmac);
1199  if (pbb_child_nh_.get()) {
1200  std::vector<int> sub_nh_list;
1201  NHKSyncEntry *child_nh =
1202  static_cast<NHKSyncEntry *>(pbb_child_nh_.get());
1203  sub_nh_list.push_back(child_nh->nh_id());
1204  encoder.set_nhr_nh_list(sub_nh_list);
1205 
1206  std::vector<int> sub_label_list;
1207  sub_label_list.push_back(pbb_label_);
1208  encoder.set_nhr_label_list(sub_label_list);
1209  }
1210  /*
1211  * This is temp fix to handle CEM-25471
1212  * Currently, vRouter doesn't differentiate PBB and MPLSoGRE/MPLSoUDP
1213  * correctly and it uses encap_oif_id for PBB also which is not needed
1214  * So, sending encap_oif_id as ZERO here in case of PBB so that vRouter
1215  * can work in same way as it was working earlier.
1216  */
1217  encoder.set_nhr_encap_oif_id(std::vector<int32_t>(1, 0));
1218  break;
1219  }
1220 
1221  case NextHop::COMPOSITE: {
1222  std::vector<int> sub_nh_id;
1223  std::vector<int> sub_label_list;
1224  std::vector<int> sub_flag_list;
1225  encoder.set_nhr_type(NH_COMPOSITE);
1226  assert(sip_.is_v4());
1227  assert(dip_.is_v4());
1228  /* TODO encoding */
1229  encoder.set_nhr_tun_sip(htonl(sip_.to_v4().to_ulong()));
1230  encoder.set_nhr_tun_dip(htonl(dip_.to_v4().to_ulong()));
1231  encoder.set_nhr_encap_family(ETHERTYPE_ARP);
1232  encoder.set_nhr_ecmp_config_hash(SetEcmpFieldsToUse());
1233  /* Proto encode in Network byte order */
1234  switch (comp_type_) {
1235  case Composite::L2INTERFACE: {
1236  flags |= NH_FLAG_COMPOSITE_ENCAP;
1237  encoder.set_nhr_family(AF_BRIDGE);
1238  break;
1239  }
1240  case Composite::L3INTERFACE: {
1241  flags |= NH_FLAG_COMPOSITE_ENCAP;
1242  break;
1243  }
1244  case Composite::EVPN: {
1245  flags |= NH_FLAG_COMPOSITE_EVPN;
1246  break;
1247  }
1248  case Composite::TOR: {
1249  flags |= NH_FLAG_COMPOSITE_TOR;
1250  break;
1251  }
1252  case Composite::FABRIC: {
1253  encoder.set_nhr_family(AF_BRIDGE);
1254  flags |= NH_FLAG_COMPOSITE_FABRIC;
1255  break;
1256  }
1257  case Composite::L3FABRIC: {
1258  flags |= NH_FLAG_COMPOSITE_FABRIC;
1259  break;
1260  }
1261  case Composite::L2COMP: {
1262  encoder.set_nhr_family(AF_BRIDGE);
1263  flags |= NH_FLAG_MCAST;
1264  if (validate_mcast_src_) {
1265  flags |= NH_FLAG_VALIDATE_MCAST_SRC;
1266  }
1267  break;
1268  }
1269  case Composite::L3COMP: {
1270  flags |= NH_FLAG_MCAST;
1271  if (validate_mcast_src_) {
1272  flags |= NH_FLAG_VALIDATE_MCAST_SRC;
1273  }
1274  break;
1275  }
1276  case Composite::MULTIPROTO: {
1277  encoder.set_nhr_family(AF_UNSPEC);
1278  break;
1279  }
1280  case Composite::ECMP:
1281  case Composite::LOCAL_ECMP: {
1282  flags |= NH_FLAG_COMPOSITE_ECMP;
1283  break;
1284  }
1285  case Composite::LU_ECMP: {
1286  flags |= NH_FLAG_COMPOSITE_ECMP;
1287  flags |= NH_FLAG_COMPOSITE_LU_ECMP;
1288  break;
1289  }
1290  case Composite::INVALID: {
1291  assert(0);
1292  }
1293  }
1294  if (need_pbb_tunnel_) {
1295  flags |= NH_FLAG_TUNNEL_PBB;
1296  }
1297 
1298  encoder.set_nhr_flags(flags);
1299  for (KSyncComponentNHList::iterator it = component_nh_list_.begin();
1300  it != component_nh_list_.end(); it++) {
1301  KSyncComponentNH component_nh = *it;
1302  if (component_nh.nh()) {
1303  sub_nh_id.push_back(component_nh.nh()->nh_id());
1304  sub_label_list.push_back(component_nh.label());
1305  } else {
1306  sub_nh_id.push_back(CompositeNH::kInvalidComponentNHIdx);
1307  sub_label_list.push_back(MplsTable::kInvalidLabel);
1308  }
1309  }
1310  encoder.set_nhr_nh_list(sub_nh_id);
1311  encoder.set_nhr_label_list(sub_label_list);
1312  break;
1313  }
1314  default:
1315  assert(0);
1316  }
1317  encoder.set_nhr_flags(flags);
1318  int error = 0;
1319  encode_len = encoder.WriteBinary((uint8_t *)buf, buf_len, &error);
1320  assert(error == 0);
1321  assert(encode_len <= buf_len);
1322  return encode_len;
1323 }
1324 
1326  const {
1327  info.set_index(nh_id());
1328 
1329  if (op == sandesh_op::ADD) {
1330  info.set_operation("ADD/CHANGE");
1331  } else {
1332  info.set_operation("DELETE");
1333  }
1334 
1335  switch(type_) {
1336  case NextHop::L2_RECEIVE: {
1337  info.set_type("L2-RECEIVE");
1338  break;
1339  }
1340  case NextHop::DISCARD: {
1341  info.set_type("DISCARD");
1342  break;
1343  }
1344 
1345  case NextHop::RECEIVE: {
1346  info.set_type("RECEIVE");
1347  break;
1348  }
1349 
1350  case NextHop::RESOLVE: {
1351  info.set_type("RESOLVE");
1352  break;
1353  }
1354 
1355  case NextHop::ARP: {
1356  info.set_type("ARP");
1357  //Fill dmac and smac???
1358  break;
1359  }
1360 
1361  case NextHop::NDP: {
1362  info.set_type("NDP");
1363  //Fill dmac and smac???
1364  break;
1365  }
1366 
1367  case NextHop::VRF: {
1368  info.set_type("VRF");
1369  info.set_vrf(vrf_id_);
1370  break;
1371  }
1372 
1373  case NextHop::INTERFACE: {
1374  info.set_type("INTERFACE");
1375  break;
1376  }
1377 
1378  case NextHop::TUNNEL: {
1379  info.set_type("TUNNEL");
1380  info.set_sip(sip_.to_string());
1381  info.set_dip(dip_.to_string());
1382  info.set_crypt_path_available(crypt_);
1383 
1384  if (crypt_interface()) {
1385  info.set_crypt_intf_name(crypt_interface()->interface_name());
1386  info.set_crypt_out_if_index(crypt_interface()->interface_id());
1387  } else {
1388  info.set_crypt_intf_name("NULL");
1389  info.set_crypt_out_if_index(kInvalidIndex);
1390  }
1391  info.set_rewrite_dmac(rewrite_dmac_.ToString());
1392  break;
1393  }
1394 
1395  case NextHop::MIRROR: {
1396  info.set_type("MIRROR");
1397  info.set_vrf(vrf_id_);
1398  info.set_sip(sip_.to_string());
1399  info.set_dip(dip_.to_string());
1400  info.set_sport(sport_);
1401  info.set_dport(dport_);
1402  break;
1403  }
1404 
1405  case NextHop::VLAN: {
1406  info.set_type("VLAN");
1407  info.set_vlan_tag(vlan_tag_);
1408  break;
1409  }
1410  case NextHop::COMPOSITE: {
1411  info.set_type("Composite");
1412  info.set_sub_type(comp_type_);
1413  info.set_dip(dip_.to_string());
1414  info.set_vrf(vrf_id_);
1415  std::vector<KSyncComponentNHLog> sub_nh_list;
1416  for (KSyncComponentNHList::const_iterator it =
1417  component_nh_list_.begin();
1418  it != component_nh_list_.end(); it++) {
1419  KSyncComponentNH component_nh = *it;
1420  if (component_nh.nh()) {
1421  KSyncComponentNHLog sub_nh;
1422  sub_nh.set_nh_idx(component_nh.nh()->nh_id());
1423  sub_nh.set_label(component_nh.label());
1424  sub_nh_list.push_back(sub_nh);
1425  }
1426  }
1427  info.set_sub_nh_list(sub_nh_list);
1428  break;
1429  }
1430  default: {
1431  return;
1432  }
1433  }
1434 
1435  info.set_policy(policy_);
1436  info.set_valid(valid_);
1437  if (interface()) {
1438  info.set_intf_name(interface()->interface_name());
1439  info.set_out_if_index(interface()->interface_id());
1440  } else {
1441  info.set_intf_name("NULL");
1442  info.set_out_if_index(kInvalidIndex);
1443  }
1444 }
1445 
1446 int NHKSyncEntry::AddMsg(char *buf, int buf_len) {
1447  KSyncNhInfo info;
1448  FillObjectLog(sandesh_op::ADD, info);
1449  KSYNC_TRACE(NH, GetObject(), info);
1450 
1451  return Encode(sandesh_op::ADD, buf, buf_len);
1452 }
1453 
1454 int NHKSyncEntry::ChangeMsg(char *buf, int buf_len){
1455  KSyncNhInfo info;
1456  FillObjectLog(sandesh_op::ADD, info);
1457  KSYNC_TRACE(NH, GetObject(), info);
1458 
1459  return Encode(sandesh_op::ADD, buf, buf_len);
1460 }
1461 
1462 int NHKSyncEntry::DeleteMsg(char *buf, int buf_len) {
1463  KSyncNhInfo info;
1464  FillObjectLog(sandesh_op::DEL, info);
1465  KSYNC_TRACE(NH, GetObject(), info);
1466 
1467  return Encode(sandesh_op::DEL, buf, buf_len);
1468 }
1469 
1471  KSyncEntry *entry = NULL;
1472  InterfaceKSyncEntry *if_ksync = interface();
1473 
1474  if (valid_ == false) {
1475  //Invalid nexthop has no reference dependency
1476  return NULL;
1477  }
1478 
1479  switch (type_) {
1480  case NextHop::ARP: {
1481  assert(if_ksync);
1482  if (!if_ksync->IsResolved()) {
1483  entry = if_ksync;
1484  }
1485  break;
1486  }
1487 
1488  case NextHop::NDP: {
1489  assert(if_ksync);
1490  if (!if_ksync->IsResolved()) {
1491  entry = if_ksync;
1492  }
1493  break;
1494  }
1495 
1496  case NextHop::VLAN:
1497  case NextHop::INTERFACE: {
1498  assert(if_ksync);
1499  if (!if_ksync->IsResolved()) {
1500  entry = if_ksync;
1501  }
1502  break;
1503  }
1504 
1505  case NextHop::L2_RECEIVE: {
1506  assert(if_ksync == NULL);
1507  break;
1508  }
1509 
1510  case NextHop::DISCARD: {
1511  assert(if_ksync == NULL);
1512  break;
1513  }
1514 
1515  case NextHop::TUNNEL: {
1516  if (crypt_path_available_) {
1517  InterfaceKSyncEntry *crypt_if_ksync = crypt_interface();
1518  assert(crypt_if_ksync);
1519  if (!crypt_if_ksync->IsResolved()) {
1520  entry = crypt_if_ksync;
1521  }
1522  }
1523  break;
1524  }
1525 
1526  case NextHop::MIRROR: {
1527  break;
1528  }
1529 
1530  case NextHop::RECEIVE: {
1531  assert(if_ksync);
1532  if (!if_ksync->IsResolved()) {
1533  entry = if_ksync;
1534  }
1535  break;
1536  }
1537 
1538  case NextHop::VRF: {
1539  break;
1540  }
1541 
1542  case NextHop::RESOLVE: {
1543  break;
1544  }
1545 
1546  case NextHop::PBB: {
1547  if (pbb_child_nh_ && pbb_child_nh_->IsResolved() == false) {
1548  entry = pbb_child_nh_.get();
1549  }
1550  break;
1551  }
1552 
1553  case NextHop::COMPOSITE: {
1554  for (KSyncComponentNHList::const_iterator it =
1555  component_nh_list_.begin();
1556  it != component_nh_list_.end(); it++) {
1557  KSyncComponentNH component_nh = *it;
1558  if (component_nh.nh() && !(component_nh.nh()->IsResolved())) {
1559  entry = component_nh.nh();
1560  break;
1561  }
1562  }
1563  break;
1564  }
1565 
1566  default:
1567  assert(0);
1568  break;
1569  }
1570  return entry;
1571 }
1572 
1573 static bool NeedRewrite(NHKSyncEntry *entry, InterfaceKSyncEntry *if_ksync) {
1574 
1575  // If interface has RAW-IP encapsulation, it doesnt need any rewrite
1576  // information
1577  if (if_ksync && if_ksync->encap_type() == PhysicalInterface::RAW_IP) {
1578  return false;
1579  }
1580 
1581  // For bridge nexthops, only INTERFACE nexthop has rewrite NH
1582  if (entry->is_bridge() == true) {
1583  if (entry->type() == NextHop::INTERFACE)
1584  return true;
1585  return false;
1586  }
1587 
1588  return true;
1589 }
1590 
1592  std::vector<int8_t> &encap,
1593  const int32_t index) {
1594 
1595  if (NeedRewrite(this, if_ksync) == false)
1596  return;
1597 
1598  const MacAddress *smac = &MacAddress::ZeroMac();
1599  /* DMAC encode */
1600  if (type_ == NextHop::TUNNEL && index != -1) {
1601  for (size_t i = 0; i < dmac_list_[index].size(); i++) {
1602  encap.push_back(dmac_list_[index][i]);
1603  }
1604  } else {
1605  for (size_t i = 0 ; i < dmac_.size(); i++) {
1606  encap.push_back(dmac_[i]);
1607  }
1608  }
1609  /* SMAC encode */
1610  if (type_ == NextHop::VLAN) {
1611  smac = &smac_;
1612  } else if ((type_ == NextHop::INTERFACE || type_ == NextHop::ARP ||
1613  type_ == NextHop::NDP) && if_ksync) {
1614  smac = &if_ksync->mac();
1615 
1616  } else {
1617  Agent *agent = ksync_obj_->ksync()->agent();
1618  smac = &agent->vhost_interface()->mac();
1619  }
1620  for (size_t i = 0 ; i < smac->size(); i++) {
1621  encap.push_back((*smac)[i]);
1622  }
1623 
1624  // Add 802.1q header if
1625  // - Nexthop is of type VLAN
1626  // - Nexthop is of type INTERFACE and VLAN configured for it
1627  if (type_ == NextHop::VLAN ||
1628  (type_ == NextHop::INTERFACE &&
1630  encap.push_back(0x81);
1631  encap.push_back(0x00);
1632  encap.push_back((vlan_tag_ & 0xFF00) >> 8);
1633  encap.push_back(vlan_tag_ & 0xFF);
1634  }
1635  /* Proto encode in Network byte order */
1636  encap.push_back(0x08);
1637  encap.push_back(0x00);
1638 }
1639 
1641  uint8_t ecmp_hash_fields_in_use = VR_FLOW_KEY_NONE;
1642  uint8_t fields_in_byte = ecmp_hash_fieds_.HashFieldsToUse();
1643  if (fields_in_byte & 1 << EcmpLoadBalance::SOURCE_IP) {
1644  ecmp_hash_fields_in_use |= VR_FLOW_KEY_SRC_IP;
1645  }
1646  if (fields_in_byte & 1 << EcmpLoadBalance::DESTINATION_IP) {
1647  ecmp_hash_fields_in_use |= VR_FLOW_KEY_DST_IP;
1648  }
1649  if (fields_in_byte & 1 << EcmpLoadBalance::IP_PROTOCOL) {
1650  ecmp_hash_fields_in_use |= VR_FLOW_KEY_PROTO;
1651  }
1652  if (fields_in_byte & 1 << EcmpLoadBalance::SOURCE_PORT) {
1653  ecmp_hash_fields_in_use |= VR_FLOW_KEY_SRC_PORT;
1654  }
1655  if (fields_in_byte & 1 << EcmpLoadBalance::DESTINATION_PORT) {
1656  ecmp_hash_fields_in_use |= VR_FLOW_KEY_DST_PORT;
1657  }
1658 
1659  return ecmp_hash_fields_in_use;
1660 
1661 }
1662 
1664  KSyncDBObject("KSync Nexthop"), ksync_(ksync) {
1665 }
1666 
1668 }
1669 
1672 }
1673 
1674 KSyncEntry *NHKSyncObject::Alloc(const KSyncEntry *entry, uint32_t index) {
1675  const NHKSyncEntry *nh = static_cast<const NHKSyncEntry *>(entry);
1676  NHKSyncEntry *ksync = new NHKSyncEntry(this, nh, index);
1677  return static_cast<KSyncEntry *>(ksync);
1678 }
1679 
1681  const NextHop *nh = static_cast<const NextHop *>(e);
1682  NHKSyncEntry *key = new NHKSyncEntry(this, nh);
1683  return static_cast<KSyncEntry *>(key);
1684 }
1685 
1686 void vr_nexthop_req::Process(SandeshContext *context) {
1687  AgentSandeshContext *ioc = static_cast<AgentSandeshContext *>(context);
1688  ioc->NHMsgHandler(this);
1689 }
1690 
1691 void NHKSyncEntry::SetKSyncNhListSandeshData(KSyncNhListSandeshData *data) const {
1692  data->set_vrf_id(vrf_id_);
1693  data->set_label(label_);
1694  if (valid_) {
1695  data->set_valid("Enable");
1696  } else {
1697  data->set_valid("Disable");
1698  }
1699 
1700  if (policy_) {
1701  data->set_policy("Enable");
1702  } else {
1703  data->set_policy("Disable");
1704  }
1705 
1706  if (is_mcast_nh_) {
1707  data->set_is_mcast_nh("True");
1708  } else {
1709  data->set_is_mcast_nh("False");
1710  }
1711 
1712  if (defer_) {
1713  data->set_defer("Enable");
1714  } else {
1715  data->set_defer("Disable");
1716  }
1717 
1718  data->set_vlan_tag(vlan_tag_);
1719 
1720  if (is_local_ecmp_nh_) {
1721  data->set_is_local_ecmp_nh("True");
1722  } else {
1723  data->set_is_local_ecmp_nh("False");
1724  }
1725 
1726  if (is_bridge_) {
1727  data->set_is_bridge("True");
1728  } else {
1729  data->set_is_bridge("False");
1730  }
1731 
1732  if (bridge_nh_) {
1733  data->set_bridge_nh("Enable");
1734  } else {
1735  data->set_bridge_nh("Disable");
1736  }
1737 
1738  if (flood_unknown_unicast_) {
1739  data->set_flood_unknown_unicast("Enable");
1740  } else {
1741  data->set_flood_unknown_unicast("Disable");
1742  }
1743 
1744  data->set_nh_id(nh_id_);
1745  data->set_isid(isid_);
1746  return;
1747 }
1748 
1750  KSyncNhListResp *resp = static_cast<KSyncNhListResp *> (sresp);
1751 
1752  KSyncNhListSandeshData data;
1754  std::vector<KSyncNhListSandeshData> &list =
1755  const_cast<std::vector<KSyncNhListSandeshData>&>(resp->get_KSyncNhList_list());
1756  list.push_back(data);
1757 
1758  return true;
1759 }
1760 
1761 void KSyncNhListReq::HandleRequest() const {
1762  AgentKsyncSandeshPtr sand(new AgentKsyncNhListSandesh(context()));
1763 
1764  sand->DoKsyncSandesh(sand);
1765 
1766 }
const NextHop * GetActiveNextHop() const
Definition: agent_route.cc:882
virtual void NHMsgHandler(vr_nexthop_req *req)=0
Definition: agent.h:360
VrfTable * vrf_table() const
Definition: agent.h:487
VrfEntry * fabric_vrf() const
Definition: agent.h:917
NextHopTable * nexthop_table() const
Definition: agent.h:477
const Interface * vhost_interface() const
Definition: agent.h:937
Definition: nexthop.h:820
const Ip4Address * GetIp() const
Definition: nexthop.h:840
const Interface * GetInterface() const
Definition: nexthop.h:837
const MacAddress & GetMac() const
Definition: nexthop.h:836
const uint32_t vrf_id() const
Definition: nexthop.cc:505
const VrfEntry * vrf() const
Definition: nexthop.h:1875
static const uint32_t kInvalidComponentNHIdx
Definition: nexthop.h:1777
bool layer2_control_word() const
Definition: nexthop.h:1918
ComponentNHList::const_iterator end() const
Definition: nexthop.h:1811
uint8_t EcmpHashFieldInUse() const
Definition: nexthop.h:1909
COMPOSITETYPE composite_nh_type() const
Definition: nexthop.h:1842
bool validate_mcast_src() const
Definition: nexthop.h:1850
bool pbb_nh() const
Definition: nexthop.h:1914
EcmpHashFields & CompEcmpHashFields()
Definition: nexthop.h:1912
const ComponentNHKeyList & component_nh_key_list() const
Definition: nexthop.h:1872
ComponentNHList::const_iterator begin() const
Definition: nexthop.h:1807
uint8_t HashFieldsToUse() const
const MacAddress & mac() const
uint32_t interface_id() const
PhysicalInterface::EncapType encap_type() const
bool IsBridge() const
Definition: nexthop.h:1299
const VrfEntry * GetVrf() const
Definition: nexthop.h:1302
const Interface * GetInterface() const
Definition: nexthop.h:1293
bool IsVxlanRouting() const
Definition: nexthop.h:1295
bool layer2_control_word() const
Definition: nexthop.h:1359
bool is_multicastNH() const
Definition: nexthop.h:1298
const MacAddress & GetDMac() const
Definition: nexthop.h:1294
@ VM_INTERFACE
Definition: interface.h:37
const MacAddress & mac() const
Definition: interface.h:133
VrfEntry * vrf() const
Definition: interface.h:117
uint32_t vrf_id() const
Definition: interface.cc:620
Type type() const
Definition: interface.h:114
void RegisterDb(DBTableBase *table)
bool IsResolved()
boost::intrusive_ptr< KSyncEntry > KSyncEntryPtr
Definition: ksync_entry.h:68
static const size_t kInvalidIndex
Definition: ksync_entry.h:69
KSyncEntry * GetReference(const KSyncEntry *key)
Agent * agent() const
Definition: ksync_init.h:39
NHKSyncObject * nh_ksync_obj() const
Definition: ksync_init.h:43
InterfaceKSyncObject * interface_ksync_obj() const
Definition: ksync_init.h:46
uint32_t const GetTransportLabel() const
Definition: tunnel_nh.h:100
TunnelType::Type const GetTransportTunnelType() const
Definition: tunnel_nh.h:109
std::string ToString() const
Definition: mac_address.cc:53
static size_t size()
Definition: mac_address.h:57
bool IsZero() const
Definition: mac_address.cc:29
static const MacAddress & ZeroMac()
Definition: mac_address.h:158
void Zero()
Definition: mac_address.h:131
const uint32_t vrf_id() const
Definition: nexthop.cc:1351
const uint16_t GetDPort() const
Definition: tunnel_nh.h:174
const uint16_t GetSPort() const
Definition: tunnel_nh.h:172
const IpAddress * GetSip() const
Definition: tunnel_nh.h:171
const AgentRoute * GetRt() const
Definition: tunnel_nh.h:175
const IpAddress * GetDip() const
Definition: tunnel_nh.h:173
static const uint32_t kInvalidLabel
Definition: mpls.h:101
NHKSyncEntry * nh() const
Definition: nexthop_ksync.h:81
NextHop::Type type() const
Definition: nexthop_ksync.h:37
uint32_t label_
Definition: nexthop_ksync.h:99
uint32_t isid_
void FillObjectLog(sandesh_op::type op, KSyncNhInfo &info) const
bool layer2_control_word_
NHKSyncEntry(NHKSyncObject *obj, const NHKSyncEntry *entry, uint32_t index)
std::vector< KSyncEntryPtr > interface_list_
NextHop::Type type_
Definition: nexthop_ksync.h:97
const NextHop * nh()
Definition: nexthop_ksync.h:36
bool flood_unknown_unicast_
TunnelType::Type transport_tunnel_type_
virtual std::string ToString() const
KSyncEntryPtr interface_
KSyncComponentNHList component_nh_list_
bool need_pbb_tunnel_
uint8_t SetEcmpFieldsToUse()
int Encode(sandesh_op::type op, char *buf, int buf_len)
MacAddress smac_
KSyncEntryPtr pbb_child_nh_
bool learning_enabled_
static const int MAX_VR_PHY_INTF
Definition: nexthop_ksync.h:30
IpAddress sip_
virtual bool Sync(DBEntry *e)
bool KSyncEntrySandesh(Sandesh *resp)
virtual ~NHKSyncEntry()
EcmpHashFields ecmp_hash_fieds_
ComponentNHKeyList component_nh_key_list_
uint16_t vlan_tag_
bool crypt_path_available_
MacAddress rewrite_dmac_
bool validate_mcast_src_
const NextHop * nh_
uint32_t pbb_label_
bool is_local_ecmp_nh_
COMPOSITETYPE comp_type_
uint32_t nh_id() const
Definition: nexthop_ksync.h:60
virtual KSyncEntry * UnresolvedReference()
virtual int DeleteMsg(char *buf, int buf_len)
void SetKSyncNhListSandeshData(KSyncNhListSandeshData *data) const
virtual int AddMsg(char *buf, int buf_len)
std::vector< int32_t > encap_valid_list_
std::vector< int32_t > encap_valid_list() const
Definition: nexthop_ksync.h:44
MacAddress dmac_
KSyncDBObject * GetObject() const
InterfaceKSyncEntry * interface() const
Definition: nexthop_ksync.h:38
std::vector< KSyncEntryPtr > interface_list() const
Definition: nexthop_ksync.h:41
NHKSyncObject * ksync_obj_
Definition: nexthop_ksync.h:96
uint16_t dport_
InterfaceKSyncEntry * crypt_interface() const
Definition: nexthop_ksync.h:47
IpAddress dip_
uint32_t vrf_id_
Definition: nexthop_ksync.h:98
void SetEncap(InterfaceKSyncEntry *if_ksync, std::vector< int8_t > &encap, const int32_t index=-1)
KSyncEntryPtr crypt_interface_
virtual int ChangeMsg(char *buf, int buf_len)
bool is_vxlan_routing_
virtual bool IsLess(const KSyncEntry &rhs) const
uint16_t sport_
uint32_t nh_id_
TunnelType tunnel_type_
bool is_bridge() const
Definition: nexthop_ksync.h:63
std::vector< MacAddress > dmac_list_
virtual KSyncEntry * DBToKSyncEntry(const DBEntry *e)
void RegisterDBClients()
NHKSyncObject(KSync *ksync)
KSync * ksync() const
virtual ~NHKSyncObject()
virtual KSyncEntry * Alloc(const KSyncEntry *entry, uint32_t index)
Definition: nexthop.h:909
const Interface * GetInterface() const
Definition: nexthop.h:926
const uint32_t vrf_id() const
Definition: nexthop.cc:610
const MacAddress & GetMac() const
Definition: nexthop.h:925
const IpAddress * GetIp() const
Definition: nexthop.h:929
bool IsLess(const NextHopKey &rhs) const
Definition: nexthop.h:501
NextHop::Type GetType() const
Definition: nexthop.h:499
bool IsEqual(const NextHopKey &rhs) const
Definition: nexthop.h:481
bool learning_enabled() const
Definition: nexthop.h:423
bool IsValid() const
Definition: nexthop.h:406
bool etree_leaf() const
Definition: nexthop.h:415
uint32_t id() const
Definition: nexthop.h:408
@ MIRROR
Definition: nexthop.h:353
@ L2_RECEIVE
Definition: nexthop.h:346
@ VLAN
Definition: nexthop.h:355
@ DISCARD
Definition: nexthop.h:345
@ PBB
Definition: nexthop.h:356
@ RECEIVE
Definition: nexthop.h:347
@ RESOLVE
Definition: nexthop.h:348
@ ARP
Definition: nexthop.h:349
@ NDP
Definition: nexthop.h:357
@ COMPOSITE
Definition: nexthop.h:354
@ INTERFACE
Definition: nexthop.h:351
@ INVALID
Definition: nexthop.h:344
@ TUNNEL
Definition: nexthop.h:352
@ VRF
Definition: nexthop.h:350
Type GetType() const
Definition: nexthop.h:405
const uint32_t isid() const
Definition: nexthop.h:1148
const uint32_t vrf_id() const
Definition: nexthop.cc:2870
const MacAddress dest_bmac() const
Definition: nexthop.h:1147
uint32_t label() const
Definition: nexthop.h:1163
const NextHop * child_nh() const
Definition: nexthop.h:1167
const Interface * GetInterface() const
Definition: nexthop.h:686
const Interface * get_interface() const
Definition: nexthop.h:754
const TunnelType & GetTunnelType() const
Definition: tunnel_nh.h:42
bool GetCrypt() const
Definition: tunnel_nh.h:44
const Ip4Address * GetDip() const
Definition: tunnel_nh.h:37
const uint32_t vrf_id() const
Definition: nexthop.cc:1065
const Interface * GetCryptInterface() const
Definition: tunnel_nh.h:43
const AgentRoute * GetRt() const
Definition: tunnel_nh.h:38
const Ip4Address * GetSip() const
Definition: tunnel_nh.h:36
const MacAddress & rewrite_dmac() const
Definition: tunnel_nh.h:41
bool GetCryptTunnelAvailable() const
Definition: tunnel_nh.h:45
@ MPLS_UDP
Definition: nexthop.h:242
@ MPLS_OVER_MPLS
Definition: nexthop.h:245
@ MPLS_GRE
Definition: nexthop.h:241
Type GetType() const
Definition: nexthop.h:303
bool IsLess(const TunnelType &rhs) const
Definition: nexthop.h:256
bool Compare(const TunnelType &rhs) const
Definition: nexthop.h:253
const MacAddress & GetDMac() const
Definition: nexthop.h:1548
const Interface * GetInterface() const
Definition: nexthop.h:1543
uint16_t GetVlanTag() const
Definition: nexthop.h:1544
const VrfEntry * GetVrf() const
Definition: nexthop.h:1546
const MacAddress & GetSMac() const
Definition: nexthop.h:1547
static const uint32_t kInvalidVlanId
Definition: vm_interface.h:362
Definition: vrf.h:89
const string & GetName() const
Definition: vrf.h:103
static const uint32_t kInvalidIndex
Definition: vrf.h:91
const uint32_t vrf_id() const
Definition: vrf.h:102
VrfEntry * forwarding_vrf() const
Definition: vrf.h:220
bool flood_unknown_unicast() const
Definition: nexthop.h:1449
bool layer2_control_word() const
Definition: nexthop.h:1461
const VrfEntry * GetVrf() const
Definition: nexthop.h:1444
bool bridge_nh() const
Definition: nexthop.h:1448
@ INVALID
Definition: globals.h:147
class boost::shared_ptr< AgentKsyncSandesh > AgentKsyncSandeshPtr
#define KSYNC_TRACE(obj, parent,...)
Definition: ksync_object.h:304
uint8_t type
Definition: load_balance.h:2
static bool NeedRewrite(NHKSyncEntry *entry, InterfaceKSyncEntry *if_ksync)
@ L3INTERFACE
Definition: nexthop.h:1592
@ LOCAL_ECMP
Definition: nexthop.h:1593
@ L2INTERFACE
Definition: nexthop.h:1591
@ MULTIPROTO
Definition: nexthop.h:1589
@ L3FABRIC
Definition: nexthop.h:1586