LCOV - code coverage report
Current view: top level - vnsw/agent/vrouter/ksync - nexthop_ksync.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 677 1170 57.9 %
Date: 2026-11-09 02:10:49 Functions: 24 27 88.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14