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: 661 1170 56.5 %
Date: 2026-08-03 02:19:58 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         160 : NHKSyncEntry::NHKSyncEntry(NHKSyncObject *obj, const NHKSyncEntry *entry,
      34         160 :                            uint32_t index) :
      35         160 :     KSyncNetlinkDBEntry(index), ksync_obj_(obj), type_(entry->type_),
      36         160 :     vrf_id_(entry->vrf_id_), label_(entry->label_),
      37         160 :     interface_(entry->interface_), sip_(entry->sip_), dip_(entry->dip_),
      38         160 :     sport_(entry->sport_), dport_(entry->dport_), smac_(entry->smac_),
      39         160 :     dmac_(entry->dmac_), rewrite_dmac_(entry->rewrite_dmac_),
      40         160 :     valid_(entry->valid_), policy_(entry->policy_),
      41         160 :     is_mcast_nh_(entry->is_mcast_nh_),
      42         160 :     defer_(entry->defer_), component_nh_list_(entry->component_nh_list_),
      43         160 :     nh_(entry->nh_), vlan_tag_(entry->vlan_tag_),
      44         160 :     is_local_ecmp_nh_(entry->is_local_ecmp_nh_),
      45         160 :     is_bridge_(entry->is_bridge_),
      46         160 :     is_vxlan_routing_(entry->is_vxlan_routing_),
      47         160 :     comp_type_(entry->comp_type_),
      48         160 :     validate_mcast_src_(entry->validate_mcast_src_),
      49         160 :     tunnel_type_(entry->tunnel_type_), prefix_len_(entry->prefix_len_),
      50         160 :     nh_id_(entry->nh_id()),
      51         160 :     component_nh_key_list_(entry->component_nh_key_list_),
      52         160 :     bridge_nh_(entry->bridge_nh_),
      53         160 :     flood_unknown_unicast_(entry->flood_unknown_unicast_),
      54         160 :     ecmp_hash_fieds_(entry->ecmp_hash_fieds_.HashFieldsToUse()),
      55         160 :     pbb_child_nh_(entry->pbb_child_nh_), isid_(entry->isid_),
      56         160 :     pbb_label_(entry->pbb_label_), learning_enabled_(entry->learning_enabled_),
      57         160 :     need_pbb_tunnel_(entry->need_pbb_tunnel_), etree_leaf_(entry->etree_leaf_),
      58         160 :     layer2_control_word_(entry->layer2_control_word_),
      59         160 :     crypt_(entry->crypt_), crypt_path_available_(entry->crypt_path_available_),
      60         160 :     crypt_interface_(entry->crypt_interface_),
      61         160 :     transport_tunnel_type_(entry->transport_tunnel_type_),
      62         160 :     interface_list_(entry->interface_list_),
      63         160 :     encap_valid_list_(entry->encap_valid_list_),
      64         320 :     dmac_list_(entry->dmac_list_) {
      65         160 :     }
      66             : 
      67        1087 : NHKSyncEntry::NHKSyncEntry(NHKSyncObject *obj, const NextHop *nh) :
      68        2174 :     KSyncNetlinkDBEntry(kInvalidIndex), ksync_obj_(obj), type_(nh->GetType()),
      69        3261 :     vrf_id_(0), interface_(NULL), dmac_(), valid_(nh->IsValid()),
      70        1087 :     policy_(nh->PolicyEnabled()), is_mcast_nh_(false), nh_(nh),
      71        1087 :     vlan_tag_(VmInterface::kInvalidVlanId), is_bridge_(false),
      72        1087 :     is_vxlan_routing_(false),
      73        1087 :     tunnel_type_(TunnelType::INVALID), prefix_len_(32), nh_id_(nh->id()),
      74        1087 :     bridge_nh_(false), flood_unknown_unicast_(false),
      75        1087 :     learning_enabled_(nh->learning_enabled()), need_pbb_tunnel_(false),
      76        1087 :     etree_leaf_ (false), layer2_control_word_(false),
      77        1087 :     crypt_(false), crypt_path_available_(false), crypt_interface_(NULL),
      78        6522 :     interface_list_(), encap_valid_list_(), dmac_list_() {
      79             : 
      80        1087 :     switch (type_) {
      81          31 :     case NextHop::ARP: {
      82          31 :         const ArpNH *arp = static_cast<const ArpNH *>(nh);
      83          31 :         vrf_id_ = arp->vrf_id();
      84          31 :         sip_ = *(arp->GetIp());
      85          31 :         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         669 :     case NextHop::INTERFACE: {
      96             :         InterfaceKSyncObject *interface_object =
      97         669 :             ksync_obj_->ksync()->interface_ksync_obj();
      98         669 :         const InterfaceNH *if_nh = static_cast<const InterfaceNH *>(nh);
      99         669 :         InterfaceKSyncEntry if_ksync(interface_object, if_nh->GetInterface());
     100         669 :         interface_ = interface_object->GetReference(&if_ksync);
     101         669 :         assert(interface_);
     102         669 :         is_mcast_nh_ = if_nh->is_multicastNH();
     103         669 :         is_bridge_ = if_nh->IsBridge();
     104         669 :         is_vxlan_routing_ = if_nh->IsVxlanRouting();
     105         669 :         const VrfEntry * vrf = if_nh->GetVrf();
     106         669 :         vrf_id_ = (vrf != NULL) ? vrf->vrf_id() : VrfEntry::kInvalidIndex;
     107         669 :         dmac_ = if_nh->GetDMac();
     108             :         // VmInterface can potentially have vlan-tags. Get tag in such case
     109         669 :         if (if_nh->GetInterface()->type() == Interface::VM_INTERFACE) {
     110         600 :             vlan_tag_ = (static_cast<const VmInterface *>
     111         600 :                          (if_nh->GetInterface()))->tx_vlan_id();
     112             :         }
     113         669 :         break;
     114         669 :     }
     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          35 :     case NextHop::DISCARD: {
     155          35 :         break;
     156             :     }
     157             : 
     158          58 :     case NextHop::L2_RECEIVE: {
     159          58 :         break;
     160             :     }
     161             : 
     162          12 :     case NextHop::RESOLVE: {
     163             :         InterfaceKSyncObject *interface_object =
     164          12 :             ksync_obj_->ksync()->interface_ksync_obj();
     165          12 :         const ResolveNH *rsl_nh = static_cast<const ResolveNH *>(nh);
     166          12 :         InterfaceKSyncEntry if_ksync(interface_object, rsl_nh->get_interface());
     167          12 :         interface_ = interface_object->GetReference(&if_ksync);
     168          12 :         vrf_id_ = rsl_nh->get_interface()->vrf_id();
     169          12 :         if (rsl_nh->get_interface()->type() == Interface::VM_INTERFACE) {
     170             :             const VmInterface *vm_intf =
     171          12 :                 static_cast<const VmInterface *>(rsl_nh->get_interface());
     172          12 :             if (vm_intf->vrf()->forwarding_vrf()) {
     173          12 :                 vrf_id_ = vm_intf->vrf()->forwarding_vrf()->vrf_id();
     174             :             }
     175             :         }
     176          12 :         break;
     177          12 :     }
     178             : 
     179           9 :     case NextHop::VRF: {
     180           9 :         const VrfNH *vrf_nh = static_cast<const VrfNH *>(nh);
     181           9 :         vrf_id_ = vrf_nh->GetVrf()->vrf_id();
     182           9 :         bridge_nh_ = vrf_nh->bridge_nh();
     183           9 :         break;
     184             :     }
     185             : 
     186          35 :     case NextHop::RECEIVE: {
     187             :         InterfaceKSyncObject *interface_object =
     188          35 :             ksync_obj_->ksync()->interface_ksync_obj();
     189          35 :         const ReceiveNH *rcv_nh = static_cast<const ReceiveNH *>(nh);
     190          35 :         InterfaceKSyncEntry if_ksync(interface_object, rcv_nh->GetInterface());
     191          35 :         interface_ = interface_object->GetReference(&if_ksync);
     192          35 :         vrf_id_ = rcv_nh->GetInterface()->vrf_id();
     193          35 :         assert(interface_);
     194          35 :         break;
     195          35 :     }
     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         205 :     case NextHop::COMPOSITE: {
     216         205 :         const CompositeNH *comp_nh = static_cast<const CompositeNH *>(nh);
     217         205 :         component_nh_list_.clear();
     218         205 :         vrf_id_ = comp_nh->vrf()->vrf_id();
     219         205 :         comp_type_ = comp_nh->composite_nh_type();
     220         205 :         validate_mcast_src_ = comp_nh->validate_mcast_src();
     221         205 :         ecmp_hash_fieds_ =
     222         205 :             const_cast<CompositeNH *>(comp_nh)->CompEcmpHashFields().HashFieldsToUse();
     223         205 :         component_nh_key_list_ = comp_nh->component_nh_key_list();
     224             :         ComponentNHList::const_iterator component_nh_it =
     225         205 :             comp_nh->begin();
     226         514 :         while (component_nh_it != comp_nh->end()) {
     227         309 :             const NextHop *component_nh = NULL;
     228         309 :             uint32_t label = 0;
     229         309 :             if (*component_nh_it) {
     230         309 :                 component_nh =  (*component_nh_it)->nh();
     231         309 :                 label = (*component_nh_it)->label();
     232             :             }
     233         309 :             KSyncEntry *ksync_nh = NULL;
     234         309 :             if (component_nh != NULL) {
     235             :                 NHKSyncObject *nh_object =
     236         309 :                     ksync_obj_->ksync()->nh_ksync_obj();
     237         309 :                 NHKSyncEntry nhksync(nh_object, component_nh);
     238         309 :                 ksync_nh = nh_object->GetReference(&nhksync);
     239         309 :             }
     240         309 :             KSyncComponentNH ksync_component_nh(label, ksync_nh);
     241         309 :             component_nh_list_.push_back(ksync_component_nh);
     242         309 :             component_nh_it++;
     243         309 :         }
     244         205 :         break;
     245             :     }
     246             : 
     247           0 :     default:
     248           0 :         assert(0);
     249             :         break;
     250             :     }
     251        1087 : }
     252             : 
     253        1567 : NHKSyncEntry::~NHKSyncEntry() {
     254        1567 : }
     255             : 
     256        2084 : KSyncDBObject *NHKSyncEntry::GetObject() const {
     257        2084 :     return ksync_obj_;
     258             : }
     259             : 
     260        9216 : bool NHKSyncEntry::IsLess(const KSyncEntry &rhs) const {
     261        9216 :     const NHKSyncEntry &entry = static_cast<const NHKSyncEntry &>(rhs);
     262             : 
     263        9216 :     if (type_ != entry.type_) {
     264        2399 :         return type_ < entry.type_;
     265             :     }
     266             : 
     267        6817 :     if (type_ == NextHop::DISCARD) {
     268          70 :         return false;
     269             :     }
     270             : 
     271        6747 :     if (type_ == NextHop::L2_RECEIVE) {
     272         116 :         return false;
     273             :     }
     274             : 
     275        6631 :     if (type_ == NextHop::ARP || type_ == NextHop::NDP) {
     276             :         //Policy is ignored for ARP NH
     277          62 :         if (vrf_id_ != entry.vrf_id_) {
     278           0 :             return vrf_id_ < entry.vrf_id_;
     279             :         }
     280          62 :         return sip_ < entry.sip_;
     281             :     }
     282             : 
     283        6569 :     if (policy_ != entry.policy_) {
     284         883 :         return policy_ < entry.policy_;
     285             :     }
     286             : 
     287        5686 :     if (type_ == NextHop::VRF) {
     288          18 :         if ( vrf_id_ != entry.vrf_id_) {
     289           0 :             return vrf_id_ < entry.vrf_id_;
     290             :         }
     291          18 :         return bridge_nh_ < entry.bridge_nh_;
     292             :     }
     293             : 
     294        5668 :     if (type_ == NextHop::INTERFACE) {
     295        4516 :         if (is_mcast_nh_ != entry.is_mcast_nh_) {
     296         568 :             return is_mcast_nh_ < entry.is_mcast_nh_;
     297             :         }
     298        3948 :         if(is_bridge_ != entry.is_bridge_) {
     299         989 :             return is_bridge_ < entry.is_bridge_;
     300             :         }
     301             : 
     302        2959 :         if(is_vxlan_routing_ != entry.is_vxlan_routing_) {
     303           0 :             return is_vxlan_routing_ < entry.is_vxlan_routing_;
     304             :         }
     305             : 
     306        2959 :         if (dmac_ != entry.dmac_) {
     307        1408 :             return dmac_ < entry.dmac_;
     308             :         }
     309             : 
     310        1551 :         return interface() < entry.interface();
     311             :     }
     312             : 
     313        1152 :     if (type_ == NextHop::RECEIVE || type_ == NextHop::RESOLVE) {
     314          94 :         return interface() < entry.interface();
     315             :     }
     316             : 
     317             : 
     318        1058 :     if (type_ == NextHop::TUNNEL) {
     319         121 :         if (vrf_id_ != entry.vrf_id_) {
     320           0 :             return vrf_id_ < entry.vrf_id_;
     321             :         }
     322             : 
     323         121 :         if (sip_ != entry.sip_) {
     324           0 :             return sip_ < entry.sip_;
     325             :         }
     326             : 
     327         121 :         if (dip_ != entry.dip_) {
     328          39 :             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        1003 :     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        1003 :     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        1003 :     if (type_ == NextHop::COMPOSITE) {
     379         937 :         if (comp_type_ != entry.comp_type_) {
     380         262 :             return comp_type_ < entry.comp_type_;
     381             :         }
     382             : 
     383         675 :         if (vrf_id_ != entry.vrf_id_) {
     384           0 :             return vrf_id_ < entry.vrf_id_;
     385             :         }
     386             : 
     387             :         ComponentNHKeyList::const_iterator it =
     388         675 :             component_nh_key_list_.begin();
     389             :         ComponentNHKeyList::const_iterator entry_it =
     390         675 :             entry.component_nh_key_list_.begin();
     391        2396 :         for (;it != component_nh_key_list_.end() &&
     392        3167 :              entry_it != entry.component_nh_key_list_.end(); it++, entry_it++) {
     393         914 :             if (*it == NULL &&
     394           0 :                     *entry_it == NULL) {
     395           0 :                 continue;
     396             :             }
     397             :             //One of the component NH is NULL
     398        1828 :             if ((*it) == NULL ||
     399         914 :                     (*entry_it) == NULL) {
     400           0 :                 return (*it) < (*entry_it);
     401             :             }
     402             : 
     403             :             //Check if the label is different
     404        1828 :             if ((*it)->label() !=
     405         914 :                     (*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         914 :             const NextHopKey *left_nh = (*it)->nh_key();
     416         914 :             const NextHopKey *right_nh = (*entry_it)->nh_key();
     417             : 
     418         914 :             if (left_nh->IsEqual(*right_nh) == false) {
     419         143 :                 if (left_nh->GetType() != right_nh->GetType()) {
     420           0 :                     return left_nh->GetType() < right_nh->GetType();
     421             :                 }
     422         143 :                 return left_nh->IsLess(*right_nh);
     423             :             }
     424             : 
     425             :         }
     426             : 
     427        1028 :         if (it == component_nh_key_list_.end() &&
     428        1028 :             entry_it == entry.component_nh_key_list_.end()) {
     429         410 :             return false;
     430             :         }
     431             : 
     432         122 :         if (it == component_nh_key_list_.end()) {
     433          86 :             return true;
     434             :         }
     435          36 :         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        3250 : std::string NHKSyncEntry::ToString() const {
     453        3250 :     std::stringstream s;
     454        3250 :     s << "NextHop Index: " << nh_id() << " Type: ";
     455        3250 :     switch(type_) {
     456          57 :     case NextHop::DISCARD: {
     457          57 :         s << "Discard";
     458          57 :         break;
     459             :     }
     460         119 :     case NextHop::L2_RECEIVE: {
     461         119 :         s << "L2-Receive ";
     462         119 :         break;
     463             :     }
     464          82 :     case NextHop::RECEIVE: {
     465          82 :         s << "Receive ";
     466          82 :         break;
     467             :     }
     468          24 :     case NextHop::RESOLVE: {
     469          24 :         s << "Resolve ";
     470          24 :         break;
     471             :     }
     472          48 :     case NextHop::ARP: {
     473          48 :         s << "ARP ";
     474          48 :         break;
     475             :     }
     476           0 :     case NextHop::NDP: {
     477           0 :         s << "NDP ";
     478           0 :         break;
     479             :     }
     480          42 :     case NextHop::VRF: {
     481          42 :         s << "VRF assign to ";
     482             :         const VrfEntry* vrf =
     483          42 :             ksync_obj_->ksync()->agent()->vrf_table()->
     484          42 :             FindVrfFromId(vrf_id_);
     485          42 :         if (vrf) {
     486          42 :             s << vrf->GetName() << " ";
     487             :         } else {
     488           0 :             s << "Invalid ";
     489             :         }
     490          42 :         break;
     491             :     }
     492        2032 :     case NextHop::INTERFACE: {
     493        2032 :         s << "Interface ";
     494        2032 :         break;
     495             :     }
     496         107 :     case NextHop::TUNNEL: {
     497         107 :         s << "Tunnel to ";
     498         107 :         s << dip_.to_string();
     499         107 :         s << "rewrite_dmac";
     500         107 :         s << rewrite_dmac_.ToString();
     501         107 :         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         739 :     case NextHop::COMPOSITE: {
     513         739 :         s << "Composite Child members: ";
     514         739 :         if (component_nh_list_.size() == 0) {
     515          37 :             s << "Empty ";
     516             :         }
     517         739 :         for (KSyncComponentNHList::const_iterator it = component_nh_list_.begin();
     518        1805 :              it != component_nh_list_.end(); it++) {
     519        1066 :             KSyncComponentNH component_nh = *it;
     520        1066 :             if (component_nh.nh()) {
     521        1066 :                 s << component_nh.nh()->ToString();
     522             :             }
     523        1066 :         }
     524         739 :         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        3250 :     if (interface_) {
     537        2138 :         s << "<" << interface_->ToString() << ">";
     538             :     }
     539        6500 :     return s.str();
     540        3250 : }
     541             : 
     542         161 : bool NHKSyncEntry::Sync(DBEntry *e) {
     543         161 :     bool ret = false;
     544         161 :     const NextHop *nh = static_cast<NextHop *>(e);
     545             : 
     546         161 :     if (valid_ != nh->IsValid()) {
     547           0 :         valid_ = nh->IsValid();
     548           0 :         ret = true;
     549             :     }
     550             : 
     551         161 :     if (learning_enabled_ != nh->learning_enabled()) {
     552           0 :         learning_enabled_ = nh->learning_enabled();
     553           0 :         ret = true;
     554             :     }
     555             : 
     556         161 :     if (etree_leaf_ != nh->etree_leaf()) {
     557           0 :         etree_leaf_ = nh->etree_leaf();
     558           0 :         ret = true;
     559             :     }
     560             : 
     561         161 :     switch (nh->GetType()) {
     562           4 :     case NextHop::ARP: {
     563             :         InterfaceKSyncObject *interface_object =
     564           4 :             ksync_obj_->ksync()->interface_ksync_obj();
     565           4 :         ArpNH *arp_nh = static_cast<ArpNH *>(e);
     566           4 :         if (dmac_ != arp_nh->GetMac()) {
     567           0 :             dmac_ = arp_nh->GetMac();
     568           0 :             ret = true;
     569             :         }
     570             : 
     571           4 :         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           4 :             if (interface_ != NULL) {
     580           0 :                 interface_ = NULL;
     581           0 :                 dmac_.Zero();
     582           0 :                 ret = true;
     583             :             }
     584             :         }
     585           4 :         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          87 :     case NextHop::INTERFACE: {
     615          87 :         InterfaceNH *intf_nh = static_cast<InterfaceNH *>(e);
     616          87 :         dmac_ = intf_nh->GetDMac();
     617          87 :         uint16_t vlan_tag = VmInterface::kInvalidVlanId;
     618          87 :         if (intf_nh->GetInterface()->type() == Interface::VM_INTERFACE) {
     619          75 :             vlan_tag = vlan_tag_;
     620          75 :             vlan_tag_ = (static_cast<const VmInterface *>
     621          75 :                          (intf_nh->GetInterface()))->tx_vlan_id();
     622          75 :             if (vlan_tag != vlan_tag_) {
     623           0 :                 ret = true;
     624             :             }
     625             :         }
     626          87 :         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          87 :         const VrfEntry * vrf = intf_nh->GetVrf();
     632          87 :         uint32_t vrf_id = (vrf != NULL)? vrf->vrf_id() :VrfEntry::kInvalidIndex;
     633          87 :         if (vrf_id_ != vrf_id) {
     634           0 :             vrf_id_ = vrf_id;
     635           0 :             ret = true;
     636             :         }
     637          87 :         break;
     638             :     }
     639             : 
     640           3 :     case NextHop::DISCARD: {
     641           3 :         ret = false;
     642           3 :         break;
     643             :     }
     644             : 
     645           3 :     case NextHop::L2_RECEIVE: {
     646           3 :         ret = false;
     647           3 :         break;
     648             :     }
     649             : 
     650           9 :     case NextHop::TUNNEL: {
     651           9 :         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           9 :         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           9 :         if (valid_ == false) {
     665           9 :             if (interface_ != NULL) {
     666           0 :                 interface_ = NULL;
     667           0 :                 dmac_.Zero();
     668           0 :                 ret = true;
     669             :             }
     670           9 :             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          43 :     case NextHop::COMPOSITE: {
     882          43 :         ret = true;
     883          43 :         CompositeNH *comp_nh = static_cast<CompositeNH *>(e);
     884          43 :         component_nh_list_.clear();
     885             :         ComponentNHList::const_iterator component_nh_it =
     886          43 :             comp_nh->begin();
     887         102 :         while (component_nh_it != comp_nh->end()) {
     888          59 :             const NextHop *component_nh = NULL;
     889          59 :             uint32_t label = 0;
     890          59 :             if (*component_nh_it) {
     891          59 :                 component_nh =  (*component_nh_it)->nh();
     892          59 :                 label = (*component_nh_it)->label();
     893             :             }
     894          59 :             KSyncEntry *ksync_nh = NULL;
     895          59 :             if (component_nh != NULL) {
     896             :                 NHKSyncObject *nh_object =
     897          59 :                     ksync_obj_->ksync()->nh_ksync_obj();
     898          59 :                 NHKSyncEntry nhksync(nh_object, component_nh);
     899          59 :                 ksync_nh = nh_object->GetReference(&nhksync);
     900          59 :             }
     901          59 :             KSyncComponentNH ksync_component_nh(label, ksync_nh);
     902          59 :             component_nh_list_.push_back(ksync_component_nh);
     903          59 :             component_nh_it++;
     904          59 :         }
     905             : 
     906          43 :         if (comp_nh->EcmpHashFieldInUse() != ecmp_hash_fieds_.HashFieldsToUse()) {
     907           0 :             ecmp_hash_fieds_ = comp_nh->CompEcmpHashFields().HashFieldsToUse();
     908           0 :             ret = true;
     909             :         }
     910             : 
     911          43 :         if (need_pbb_tunnel_ != comp_nh->pbb_nh()) {
     912           0 :             need_pbb_tunnel_ = comp_nh->pbb_nh();
     913           0 :             ret = true;
     914             :         }
     915             : 
     916          43 :         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          43 :         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           3 :     case NextHop::VRF: {
     932           3 :         VrfNH *vrf_nh = static_cast<VrfNH *>(e);
     933           3 :         vrf_id_ = vrf_nh->GetVrf()->vrf_id();
     934           3 :         ret = false;
     935           3 :         if (bridge_nh_ != vrf_nh->bridge_nh()) {
     936           0 :             bridge_nh_ = vrf_nh->bridge_nh();
     937           0 :             ret = true;
     938             :         }
     939             : 
     940           3 :         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           3 :         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           3 :         break;
     950             :     }
     951           9 :     case NextHop::RECEIVE:
     952             :     case NextHop::RESOLVE: {
     953           9 :         valid_ = true;
     954           9 :         ret = true;
     955           9 :         break;
     956             :     }
     957             : 
     958           0 :     default:
     959           0 :         assert(0);
     960             :     }
     961             : 
     962         161 :     return ret;
     963             : };
     964         320 : int NHKSyncEntry::Encode(sandesh_op::type op, char *buf, int buf_len) {
     965         320 :     vr_nexthop_req encoder;
     966             :     int encode_len;
     967         320 :     uint32_t crypt_intf_id = kInvalidIndex;
     968         320 :     uint32_t intf_id = kInvalidIndex;
     969         320 :     std::vector<int8_t> encap;
     970         320 :     InterfaceKSyncEntry *if_ksync = NULL;
     971         320 :     InterfaceKSyncEntry *crypt_if_ksync = NULL;
     972         320 :     std::vector<KSyncEntryPtr> if_ksync_list;
     973         320 :     std::vector<int32_t> nhr_encap_valid_list;
     974         320 :     std::vector<int32_t> intf_id_list;
     975         320 :     Agent *agent = ksync_obj_->ksync()->agent();
     976             : 
     977         320 :     encoder.set_h_op(op);
     978         320 :     encoder.set_nhr_id(nh_id());
     979         320 :     if (op == sandesh_op::DEL) {
     980             :         /* For delete only NH-index is required by vrouter */
     981         160 :         int error = 0;
     982         160 :         encode_len = encoder.WriteBinary((uint8_t *)buf, buf_len, &error);
     983         160 :         assert(error == 0);
     984         160 :         assert(encode_len <= buf_len);
     985         160 :         return encode_len;
     986             :     }
     987         160 :     encoder.set_nhr_rid(0);
     988         160 :     encoder.set_nhr_vrf(vrf_id_);
     989         160 :     encoder.set_nhr_family(AF_INET);
     990         160 :     uint32_t flags = 0;
     991         160 :     if (valid_) {
     992         148 :         flags |= NH_FLAG_VALID;
     993             :     }
     994             : 
     995         160 :     if (policy_) {
     996          37 :         flags |= NH_FLAG_POLICY_ENABLED;
     997             :     }
     998             : 
     999         160 :     if (etree_leaf_ == false) {
    1000         160 :         flags |= NH_FLAG_ETREE_ROOT;
    1001             :     }
    1002             : 
    1003         160 :     if (learning_enabled_) {
    1004           0 :         flags |= NH_FLAG_MAC_LEARN;
    1005             :     }
    1006             : 
    1007         160 :     if (layer2_control_word_) {
    1008           0 :         flags |= NH_FLAG_L2_CONTROL_DATA;
    1009             :     }
    1010             : 
    1011         160 :     if (crypt_) {
    1012           0 :         flags |= NH_FLAG_CRYPT_TRAFFIC;
    1013             :     }
    1014             : 
    1015         160 :     if_ksync = interface();
    1016         160 :     if_ksync_list = interface_list();
    1017         160 :     nhr_encap_valid_list = encap_valid_list();
    1018         160 :     crypt_if_ksync = crypt_interface();
    1019             : 
    1020         160 :     switch (type_) {
    1021          90 :         case NextHop::VLAN:
    1022             :         case NextHop::ARP:
    1023             :         case NextHop::NDP:
    1024             :         case NextHop::INTERFACE :
    1025          90 :             encoder.set_nhr_type(NH_ENCAP);
    1026          90 :             if (if_ksync) {
    1027          87 :                 intf_id = if_ksync->interface_id();
    1028             :             }
    1029          90 :             encoder.set_nhr_encap_oif_id(std::vector<int32_t>(1, intf_id));
    1030          90 :             encoder.set_nhr_encap_family(ETHERTYPE_ARP);
    1031             : 
    1032          90 :             SetEncap(if_ksync, encap);
    1033          90 :             encoder.set_nhr_encap(encap);
    1034          90 :             encoder.set_nhr_tun_sip(0);
    1035          90 :             encoder.set_nhr_tun_dip(0);
    1036          90 :             if (is_vxlan_routing_) {
    1037             :                 //Set vxlan routing flag
    1038           0 :                 flags |= NH_FLAG_L3_VXLAN;
    1039             :             }
    1040          90 :             if (is_bridge_) {
    1041          30 :                 encoder.set_nhr_family(AF_BRIDGE);
    1042             :             }
    1043          90 :             if (is_mcast_nh_) {
    1044          15 :                 flags |= NH_FLAG_MCAST;
    1045             :             }
    1046          90 :             encoder.set_nhr_flags(flags);
    1047          90 :             break;
    1048             : 
    1049           9 :         case NextHop::TUNNEL : {
    1050           9 :             encoder.set_nhr_type(NH_TUNNEL);
    1051           9 :             encoder.set_nhr_tun_sip(htonl(sip_.to_v4().to_ulong()));
    1052           9 :             encoder.set_nhr_tun_dip(htonl(dip_.to_v4().to_ulong()));
    1053           9 :             encoder.set_nhr_encap_family(ETHERTYPE_ARP);
    1054             : 
    1055           9 :             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           9 :                 SetEncap(if_ksync, encap);
    1069           9 :                 intf_id_list.push_back(0);
    1070             :             }
    1071           9 :             encoder.set_nhr_encap_oif_id(intf_id_list);
    1072           9 :             encoder.set_nhr_encap_valid(nhr_encap_valid_list);
    1073           9 :             encoder.set_nhr_crypt_traffic(crypt_);
    1074           9 :             encoder.set_nhr_crypt_path_available(crypt_path_available_);
    1075           9 :             if (crypt_if_ksync && crypt_path_available_) {
    1076           0 :                 crypt_intf_id = crypt_if_ksync->interface_id();
    1077             :             }
    1078           9 :             encoder.set_nhr_encap_crypt_oif_id(crypt_intf_id);
    1079           9 :             encoder.set_nhr_encap(encap);
    1080           9 :             if (tunnel_type_.GetType() == TunnelType::MPLS_UDP) {
    1081           0 :                 flags |= NH_FLAG_TUNNEL_UDP_MPLS;
    1082           9 :             } else if (tunnel_type_.GetType() == TunnelType::MPLS_GRE) {
    1083           5 :                 flags |= NH_FLAG_TUNNEL_GRE;
    1084           4 :             } 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           4 :             } 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           4 :                 flags |= NH_FLAG_TUNNEL_VXLAN;
    1105             :             }
    1106           9 :             std::vector<int8_t> rewrite_dmac;
    1107          63 :             for (size_t i = 0 ; i < rewrite_dmac_.size(); i++) {
    1108          54 :                 rewrite_dmac.push_back(rewrite_dmac_[i]);
    1109             :             }
    1110           9 :             encoder.set_nhr_rw_dst_mac(rewrite_dmac);
    1111             :             //TODO remove set_nhr_pbb_mac
    1112           9 :             encoder.set_nhr_pbb_mac(rewrite_dmac);
    1113           9 :             if (rewrite_dmac_.IsZero() == false) {
    1114           0 :                 flags |= NH_FLAG_L3_VXLAN;
    1115             :             }
    1116           9 :             break;
    1117           9 :         }
    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           3 :         case NextHop::L2_RECEIVE:
    1149           3 :             encoder.set_nhr_type(NH_L2_RCV);
    1150           3 :             break;
    1151             : 
    1152           3 :         case NextHop::DISCARD:
    1153           3 :             encoder.set_nhr_type(NH_DISCARD);
    1154           3 :             break;
    1155             : 
    1156           6 :         case NextHop::RECEIVE:
    1157           6 :             if (!policy_) {
    1158           3 :                 flags |= NH_FLAG_RELAXED_POLICY;
    1159             :             }
    1160           6 :             intf_id = if_ksync->interface_id();
    1161           6 :             encoder.set_nhr_encap_oif_id(std::vector<int32_t>(1, intf_id));
    1162           6 :             encoder.set_nhr_type(NH_RCV);
    1163           6 :             break;
    1164             : 
    1165           3 :         case NextHop::RESOLVE:
    1166           3 :             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           3 :             encoder.set_nhr_type(NH_RESOLVE);
    1178           3 :             break;
    1179             : 
    1180           3 :         case NextHop::VRF:
    1181           3 :             encoder.set_nhr_type(NH_VXLAN_VRF);
    1182           3 :             if (bridge_nh_ == true) {
    1183           3 :                 encoder.set_nhr_family(AF_BRIDGE);
    1184             :             }
    1185           3 :             if (flood_unknown_unicast_) {
    1186           0 :                 flags |= NH_FLAG_UNKNOWN_UC_FLOOD;
    1187             :             }
    1188           3 :             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          43 :         case NextHop::COMPOSITE: {
    1222          43 :             std::vector<int> sub_nh_id;
    1223          43 :             std::vector<int> sub_label_list;
    1224          43 :             std::vector<int> sub_flag_list;
    1225          43 :             encoder.set_nhr_type(NH_COMPOSITE);
    1226          43 :             assert(sip_.is_v4());
    1227          43 :             assert(dip_.is_v4());
    1228             :             /* TODO encoding */
    1229          43 :             encoder.set_nhr_tun_sip(htonl(sip_.to_v4().to_ulong()));
    1230          43 :             encoder.set_nhr_tun_dip(htonl(dip_.to_v4().to_ulong()));
    1231          43 :             encoder.set_nhr_encap_family(ETHERTYPE_ARP);
    1232          43 :             encoder.set_nhr_ecmp_config_hash(SetEcmpFieldsToUse());
    1233             :             /* Proto encode in Network byte order */
    1234          43 :             switch (comp_type_) {
    1235          19 :             case Composite::L2INTERFACE: {
    1236          19 :                 flags |= NH_FLAG_COMPOSITE_ENCAP;
    1237          19 :                 encoder.set_nhr_family(AF_BRIDGE);
    1238          19 :                 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          22 :             case Composite::L2COMP: {
    1262          22 :                 encoder.set_nhr_family(AF_BRIDGE);
    1263          22 :                 flags |= NH_FLAG_MCAST;
    1264          22 :                 if (validate_mcast_src_) {
    1265          22 :                     flags |= NH_FLAG_VALIDATE_MCAST_SRC;
    1266             :                 }
    1267          22 :                 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          43 :             if (need_pbb_tunnel_) {
    1295           0 :                 flags |= NH_FLAG_TUNNEL_PBB;
    1296             :             }
    1297             : 
    1298          43 :             encoder.set_nhr_flags(flags);
    1299          43 :             for (KSyncComponentNHList::iterator it = component_nh_list_.begin();
    1300         102 :                     it != component_nh_list_.end(); it++) {
    1301          59 :                 KSyncComponentNH component_nh = *it;
    1302          59 :                 if (component_nh.nh()) {
    1303          59 :                     sub_nh_id.push_back(component_nh.nh()->nh_id());
    1304          59 :                     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          59 :             }
    1310          43 :             encoder.set_nhr_nh_list(sub_nh_id);
    1311          43 :             encoder.set_nhr_label_list(sub_label_list);
    1312          43 :             break;
    1313          43 :         }
    1314           0 :         default:
    1315           0 :             assert(0);
    1316             :     }
    1317         160 :     encoder.set_nhr_flags(flags);
    1318         160 :     int error = 0;
    1319         160 :     encode_len = encoder.WriteBinary((uint8_t *)buf, buf_len, &error);
    1320         160 :     assert(error == 0);
    1321         160 :     assert(encode_len <= buf_len);
    1322         160 :     return encode_len;
    1323         320 : }
    1324             : 
    1325         320 : void NHKSyncEntry::FillObjectLog(sandesh_op::type op, KSyncNhInfo &info)
    1326             :     const {
    1327         320 :     info.set_index(nh_id());
    1328             : 
    1329         320 :     if (op == sandesh_op::ADD) {
    1330         160 :         info.set_operation("ADD/CHANGE");
    1331             :     } else {
    1332         160 :         info.set_operation("DELETE");
    1333             :     }
    1334             : 
    1335         320 :     switch(type_) {
    1336           6 :     case NextHop::L2_RECEIVE: {
    1337           6 :         info.set_type("L2-RECEIVE");
    1338           6 :         break;
    1339             :     }
    1340           6 :     case NextHop::DISCARD: {
    1341           6 :         info.set_type("DISCARD");
    1342           6 :         break;
    1343             :     }
    1344             : 
    1345          12 :     case NextHop::RECEIVE: {
    1346          12 :         info.set_type("RECEIVE");
    1347          12 :         break;
    1348             :     }
    1349             : 
    1350           6 :     case NextHop::RESOLVE: {
    1351           6 :         info.set_type("RESOLVE");
    1352           6 :         break;
    1353             :     }
    1354             : 
    1355           6 :     case NextHop::ARP: {
    1356           6 :         info.set_type("ARP");
    1357             :         //Fill dmac and smac???
    1358           6 :         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           6 :     case NextHop::VRF: {
    1368           6 :         info.set_type("VRF");
    1369           6 :         info.set_vrf(vrf_id_);
    1370           6 :         break;
    1371             :     }
    1372             : 
    1373         174 :     case NextHop::INTERFACE: {
    1374         174 :         info.set_type("INTERFACE");
    1375         174 :         break;
    1376             :     }
    1377             : 
    1378          18 :     case NextHop::TUNNEL: {
    1379          18 :         info.set_type("TUNNEL");
    1380          18 :         info.set_sip(sip_.to_string());
    1381          18 :         info.set_dip(dip_.to_string());
    1382          18 :         info.set_crypt_path_available(crypt_);
    1383             : 
    1384          18 :         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          18 :             info.set_crypt_intf_name("NULL");
    1389          18 :             info.set_crypt_out_if_index(kInvalidIndex);
    1390             :         }
    1391          18 :         info.set_rewrite_dmac(rewrite_dmac_.ToString());
    1392          18 :         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          86 :     case NextHop::COMPOSITE: {
    1411          86 :         info.set_type("Composite");
    1412          86 :         info.set_sub_type(comp_type_);
    1413          86 :         info.set_dip(dip_.to_string());
    1414          86 :         info.set_vrf(vrf_id_);
    1415          86 :         std::vector<KSyncComponentNHLog> sub_nh_list;
    1416          86 :         for (KSyncComponentNHList::const_iterator it =
    1417          86 :                 component_nh_list_.begin();
    1418         204 :              it != component_nh_list_.end(); it++) {
    1419         118 :             KSyncComponentNH component_nh = *it;
    1420         118 :             if (component_nh.nh()) {
    1421         118 :                 KSyncComponentNHLog sub_nh;
    1422         118 :                 sub_nh.set_nh_idx(component_nh.nh()->nh_id());
    1423         118 :                 sub_nh.set_label(component_nh.label());
    1424         118 :                 sub_nh_list.push_back(sub_nh);
    1425         118 :             }
    1426         118 :         }
    1427          86 :         info.set_sub_nh_list(sub_nh_list);
    1428          86 :         break;
    1429          86 :     }
    1430           0 :     default: {
    1431           0 :         return;
    1432             :     }
    1433             :     }
    1434             : 
    1435         320 :     info.set_policy(policy_);
    1436         320 :     info.set_valid(valid_);
    1437         320 :     if (interface()) {
    1438         192 :         info.set_intf_name(interface()->interface_name());
    1439         192 :         info.set_out_if_index(interface()->interface_id());
    1440             :     } else {
    1441         128 :         info.set_intf_name("NULL");
    1442         128 :         info.set_out_if_index(kInvalidIndex);
    1443             :     }
    1444             : }
    1445             : 
    1446         160 : int NHKSyncEntry::AddMsg(char *buf, int buf_len) {
    1447         160 :     KSyncNhInfo info;
    1448         160 :     FillObjectLog(sandesh_op::ADD, info);
    1449         160 :     KSYNC_TRACE(NH, GetObject(), info);
    1450             : 
    1451         320 :     return Encode(sandesh_op::ADD, buf, buf_len);
    1452         160 : }
    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         160 : int NHKSyncEntry::DeleteMsg(char *buf, int buf_len) {
    1463         160 :     KSyncNhInfo info;
    1464         160 :     FillObjectLog(sandesh_op::DEL, info);
    1465         160 :     KSYNC_TRACE(NH, GetObject(), info);
    1466             : 
    1467         320 :     return Encode(sandesh_op::DEL, buf, buf_len);
    1468         160 : }
    1469             : 
    1470         259 : KSyncEntry *NHKSyncEntry::UnresolvedReference() {
    1471         259 :     KSyncEntry *entry = NULL;
    1472         259 :     InterfaceKSyncEntry *if_ksync = interface();
    1473             : 
    1474         259 :     if (valid_ == false) {
    1475             :         //Invalid nexthop has no reference dependency
    1476          12 :         return NULL;
    1477             :     }
    1478             : 
    1479         247 :     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         140 :     case NextHop::VLAN:
    1497             :     case NextHop::INTERFACE: {
    1498         140 :         assert(if_ksync);
    1499         140 :         if (!if_ksync->IsResolvedAndInSync()) {
    1500          53 :             entry = if_ksync;
    1501             :         }
    1502         140 :         break;
    1503             :     }
    1504             : 
    1505           3 :     case NextHop::L2_RECEIVE: {
    1506           3 :         assert(if_ksync == NULL);
    1507           3 :         break;
    1508             :     }
    1509             : 
    1510           3 :     case NextHop::DISCARD: {
    1511           3 :         assert(if_ksync == NULL);
    1512           3 :         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          18 :     case NextHop::RECEIVE: {
    1531          18 :         assert(if_ksync);
    1532          18 :         if (!if_ksync->IsResolvedAndInSync()) {
    1533          12 :             entry = if_ksync;
    1534             :         }
    1535          18 :         break;
    1536             :     }
    1537             : 
    1538           3 :     case NextHop::VRF: {
    1539           3 :         break;
    1540             :     }
    1541             : 
    1542           3 :     case NextHop::RESOLVE: {
    1543           3 :         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          77 :     case NextHop::COMPOSITE: {
    1554          77 :         for (KSyncComponentNHList::const_iterator it =
    1555          77 :                                 component_nh_list_.begin();
    1556         142 :              it != component_nh_list_.end(); it++) {
    1557          99 :             KSyncComponentNH component_nh = *it;
    1558          99 :             if (component_nh.nh() && !(component_nh.nh()->IsResolvedAndInSync())) {
    1559          34 :                 entry = component_nh.nh();
    1560          34 :                 break;
    1561             :             }
    1562          99 :         }
    1563          77 :         break;
    1564             :     }
    1565             : 
    1566           0 :     default:
    1567           0 :         assert(0);
    1568             :         break;
    1569             :     }
    1570         247 :     return entry;
    1571             : }
    1572             : 
    1573          99 : static bool NeedRewrite(NHKSyncEntry *entry, InterfaceKSyncEntry *if_ksync) {
    1574             : 
    1575             :     // If interface has RAW-IP encapsulation, it doesnt need any rewrite
    1576             :     // information
    1577          99 :     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          99 :     if (entry->is_bridge() == true) {
    1583          30 :         if (entry->type() == NextHop::INTERFACE)
    1584          30 :             return true;
    1585           0 :         return false;
    1586             :     }
    1587             : 
    1588          69 :     return true;
    1589             : }
    1590             : 
    1591          99 : void NHKSyncEntry::SetEncap(InterfaceKSyncEntry *if_ksync,
    1592             :                             std::vector<int8_t> &encap,
    1593             :                             const int32_t index) {
    1594             : 
    1595          99 :     if (NeedRewrite(this, if_ksync) == false)
    1596           0 :         return;
    1597             : 
    1598          99 :     const MacAddress *smac = &MacAddress::ZeroMac();
    1599             :     /* DMAC encode */
    1600          99 :     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         693 :         for (size_t i = 0 ; i < dmac_.size(); i++) {
    1606         594 :             encap.push_back(dmac_[i]);
    1607             :         }
    1608             :     }
    1609             :     /* SMAC encode */
    1610          99 :     if (type_ == NextHop::VLAN) {
    1611           0 :         smac = &smac_;
    1612          99 :     } else if ((type_ == NextHop::INTERFACE || type_ == NextHop::ARP ||
    1613          99 :                 type_ == NextHop::NDP) && if_ksync) {
    1614          87 :         smac = &if_ksync->mac();
    1615             : 
    1616             :     } else {
    1617          12 :         Agent *agent = ksync_obj_->ksync()->agent();
    1618          12 :         smac = &agent->vhost_interface()->mac();
    1619             :     }
    1620         693 :     for (size_t i = 0 ; i < smac->size(); i++) {
    1621         594 :         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          99 :     if (type_ == NextHop::VLAN ||
    1628          99 :             (type_ == NextHop::INTERFACE &&
    1629          87 :              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          99 :     encap.push_back(0x08);
    1637          99 :     encap.push_back(0x00);
    1638             : }
    1639             : 
    1640          43 : uint8_t NHKSyncEntry::SetEcmpFieldsToUse() {
    1641          43 :     uint8_t ecmp_hash_fields_in_use = VR_FLOW_KEY_NONE;
    1642          43 :     uint8_t fields_in_byte = ecmp_hash_fieds_.HashFieldsToUse();
    1643          43 :     if (fields_in_byte & 1 << EcmpLoadBalance::SOURCE_IP) {
    1644          43 :         ecmp_hash_fields_in_use |= VR_FLOW_KEY_SRC_IP;
    1645             :     }
    1646          43 :     if (fields_in_byte & 1 << EcmpLoadBalance::DESTINATION_IP) {
    1647          43 :         ecmp_hash_fields_in_use |= VR_FLOW_KEY_DST_IP;
    1648             :     }
    1649          43 :     if (fields_in_byte & 1 << EcmpLoadBalance::IP_PROTOCOL) {
    1650          43 :         ecmp_hash_fields_in_use |= VR_FLOW_KEY_PROTO;
    1651             :     }
    1652          43 :     if (fields_in_byte & 1 << EcmpLoadBalance::SOURCE_PORT) {
    1653          43 :         ecmp_hash_fields_in_use |= VR_FLOW_KEY_SRC_PORT;
    1654             :     }
    1655          43 :     if (fields_in_byte & 1 << EcmpLoadBalance::DESTINATION_PORT) {
    1656          43 :         ecmp_hash_fields_in_use |= VR_FLOW_KEY_DST_PORT;
    1657             :     }
    1658             : 
    1659          43 :     return ecmp_hash_fields_in_use;
    1660             : 
    1661             : }
    1662             : 
    1663           3 : NHKSyncObject::NHKSyncObject(KSync *ksync) :
    1664           3 :     KSyncDBObject("KSync Nexthop"), ksync_(ksync) {
    1665           3 : }
    1666             : 
    1667           6 : NHKSyncObject::~NHKSyncObject() {
    1668           6 : }
    1669             : 
    1670           3 : void NHKSyncObject::RegisterDBClients() {
    1671           3 :     RegisterDb(ksync_->agent()->nexthop_table());
    1672           3 : }
    1673             : 
    1674         160 : KSyncEntry *NHKSyncObject::Alloc(const KSyncEntry *entry, uint32_t index) {
    1675         160 :     const NHKSyncEntry *nh = static_cast<const NHKSyncEntry *>(entry);
    1676         160 :     NHKSyncEntry *ksync = new NHKSyncEntry(this, nh, index);
    1677         160 :     return static_cast<KSyncEntry *>(ksync);
    1678             : }
    1679             : 
    1680         160 : KSyncEntry *NHKSyncObject::DBToKSyncEntry(const DBEntry *e) {
    1681         160 :     const NextHop *nh = static_cast<const NextHop *>(e);
    1682         160 :     NHKSyncEntry *key = new NHKSyncEntry(this, nh);
    1683         160 :     return static_cast<KSyncEntry *>(key);
    1684             : }
    1685             : 
    1686         320 : void vr_nexthop_req::Process(SandeshContext *context) {
    1687         320 :     AgentSandeshContext *ioc = static_cast<AgentSandeshContext *>(context);
    1688         320 :     ioc->NHMsgHandler(this);
    1689         320 : }
    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