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: 662 1170 56.6 %
Date: 2026-09-07 02:14:47 Functions: 23 27 85.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14