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