LCOV - code coverage report
Current view: top level - vnsw/agent/oper - nexthop.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 399 645 61.9 %
Date: 2026-11-09 02:10:49 Functions: 223 335 66.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #ifndef vnsw_agent_nexthop_hpp
       7             : #define vnsw_agent_nexthop_hpp
       8             : 
       9             : #include <netinet/in.h>
      10             : #include <net/ethernet.h>
      11             : 
      12             : #include <cmn/agent_cmn.h>
      13             : #include <agent_types.h>
      14             : 
      15             : #include <oper/interface_common.h>
      16             : #include <oper/vrf.h>
      17             : #include <oper/ecmp_load_balance.h>
      18             : 
      19             : class NextHopKey;
      20             : class MplsLabel;
      21             : 
      22             : template <typename Member>
      23             : class MemberList {
      24             : public:
      25             :     const static uint32_t kInvalidIndex = 0xffff;
      26             :     MemberList(int max_size) : max_size_(max_size), free_index_(0), hash_id(0) {
      27             :     }
      28             : 
      29             :     MemberList():max_size_(64), free_index_(0), hash_id(0) {
      30             :     }
      31             : 
      32             :     ~MemberList() {
      33             :        for (uint32_t i = 0; i < mbr_list_.size(); i++) {
      34             :            if (mbr_list_[i]) {
      35             :                delete mbr_list_[i];
      36             :            }
      37             :        }
      38             :     }
      39             : 
      40             :     typedef typename std::vector<Member *>::iterator iterator;
      41             :     typedef typename std::vector<Member *>::const_iterator const_iterator;
      42             : 
      43             :     int insert(const Member &mbr) {
      44             :         if (mbr_list_.size() >= kInvalidIndex) {
      45             :             return kInvalidIndex;
      46             :         }
      47             : 
      48             :         if (mbr_list_.size() < free_index_ + 1) {
      49             :             mbr_list_.resize(free_index_ + 1);
      50             :             hash_table_.resize(free_index_ + 1);
      51             :         }
      52             : 
      53             :         Member *entry = new Member(mbr);
      54             :         mbr_list_[free_index_] = entry;
      55             :         UpdateFreeIndex();
      56             :         UpdateHashTable();
      57             :         return free_index_;
      58             :     }
      59             : 
      60             :     bool remove(const Member &mbr) {
      61             :        uint32_t i = 0;
      62             :        for (i = 0; i < mbr_list_.size(); i++) {
      63             :            if (mbr_list_[i] && *mbr_list_[i] == mbr) {
      64             :                delete mbr_list_[i];
      65             :                mbr_list_[i] = NULL;
      66             :                break;
      67             :            }
      68             :        }
      69             : 
      70             :        if (i == mbr_list_.size()) {
      71             :            return false;
      72             :        }
      73             :        UpdateFreeIndex();
      74             :        UpdateHashTable();
      75             :        return true;
      76             :     }
      77             : 
      78             :     bool remove(uint32_t index) {
      79             :         if (index >= mbr_list_.size()) {
      80             :             return false;
      81             :         }
      82             :         if (mbr_list_[index] != NULL) {
      83             :             delete mbr_list_[index];
      84             :             mbr_list_[index] = NULL;
      85             :             UpdateFreeIndex();
      86             :             UpdateHashTable();
      87             :         }
      88             :         return true;
      89             :     }
      90             : 
      91             :     void UpdateHashTable() {
      92             :         hash_table_.clear();
      93             :         for (uint32_t i = 0; i < mbr_list_.size(); i++) {
      94             :             if (mbr_list_[i] == NULL) {
      95             :                 hash_table_.push_back(0xffff);
      96             :                 continue;
      97             :             }
      98             :             hash_table_.push_back(i);
      99             :         }
     100             :     }
     101             : 
     102             :     void UpdateFreeIndex() {
     103             :         uint32_t i;
     104             :         for (i = 0; i < mbr_list_.size(); i++) {
     105             :             if (mbr_list_[i] == NULL) {
     106             :                 free_index_ = i;
     107             :                 return;
     108             :             }
     109             :         }
     110             :         free_index_ = i;
     111             :     }
     112             : 
     113             :     void UpdateFreeIndex(uint32_t index) {
     114             :         if (index > free_index_) {
     115             :             return;
     116             :         }
     117             :         UpdateFreeIndex();
     118             :     }
     119             : 
     120             :     void replace(std::vector<Member> list) {
     121             :         //Add new elements, which are not presnet in member list
     122             :         typename std::vector<Member>::const_iterator it = list.begin();
     123             :         while (it != list.end()) {
     124             :             Member mem = *it;
     125             :             if (!Find(mem)) {
     126             :                 insert(mem);
     127             :             }
     128             :             it++;
     129             :         }
     130             : 
     131             :         //Remove elements present member list, but not in new list
     132             :         iterator mbr_list_iterator = begin();
     133             :         while (mbr_list_iterator != end()) {
     134             :             const Member *member = *mbr_list_iterator;
     135             :             if (!member) {
     136             :                  mbr_list_iterator++;
     137             :                  continue;
     138             :             }
     139             :             it = list.begin();
     140             :             while (it != list.end()) {
     141             :                 const Member *latest_member = &(*it);
     142             :                 if (latest_member && *latest_member == *member) {
     143             :                     break;
     144             :                 }
     145             :                 it++;
     146             :             }
     147             :             if (it == list.end()) {
     148             :                 remove(*member);
     149             :             }
     150             :             mbr_list_iterator++;
     151             :         }
     152             :     }
     153             : 
     154             :     void clear() {
     155             :         hash_table_.clear();
     156             :         for (uint32_t i = 0; i < mbr_list_.size(); i++) {
     157             :             if (mbr_list_[i]) {
     158             :                 delete mbr_list_[i];
     159             :             }
     160             :         }
     161             :         mbr_list_.clear();
     162             :         free_index_ = 0;
     163             :     }
     164             : 
     165             :     size_t HashTableSize() const {
     166             :         return hash_table_.size();
     167             :     }
     168             : 
     169             :     iterator begin() { return iterator(mbr_list_.begin());};
     170             :     iterator end() { return iterator(mbr_list_.end());};
     171             : 
     172             :     const_iterator begin() const {
     173             :         return const_iterator(mbr_list_.begin());
     174             :     }
     175             :     const_iterator end() const {
     176             :         return const_iterator(mbr_list_.end());
     177             :     }
     178             : 
     179             :     Member* Find(const Member &mem) const {
     180             :         for (uint32_t i = 0; i < mbr_list_.size(); i++) {
     181             :             if (mbr_list_[i] && *mbr_list_[i] == mem) {
     182             :                 return mbr_list_[i];
     183             :             }
     184             :         }
     185             :         return NULL;
     186             :     }
     187             : 
     188             :     Member* Find(const Member &mem, uint32_t &index) const{
     189             :         for (uint32_t i = 0; i < mbr_list_.size(); i++) {
     190             :             if (mbr_list_[i] && *mbr_list_[i] == mem) {
     191             :                 index = i;
     192             :                 return mbr_list_[i];
     193             :             }
     194             :         }
     195             :         return NULL;
     196             :     }
     197             : 
     198             :     const Member* Get(uint32_t idx) const {
     199             :         return mbr_list_[idx];
     200             :     }
     201             : 
     202             :     size_t size() const {
     203             :         return mbr_list_.size();
     204             :     }
     205             : 
     206             :     uint32_t hash(size_t hash) const {
     207             :         for (uint32_t i = 0; i < mbr_list_.size(); i++) {
     208             :             if (hash_table_[hash % hash_table_.size()] != 0xffff) {
     209             :                 return hash_table_[hash % hash_table_.size()];
     210             :             }
     211             :             hash++;
     212             :         }
     213             :         return 0;
     214             :     }
     215             : 
     216             :     uint32_t count() const {
     217             :         int cnt = 0;
     218             :         for (uint32_t i = 0; i < mbr_list_.size(); i++) {
     219             :             if (mbr_list_[i] != NULL)
     220             :                 cnt++;
     221             :         }
     222             : 
     223             :         return cnt;
     224             :     }
     225             : 
     226             : private:
     227             :     std::vector<Member *> mbr_list_;
     228             :     std::vector<uint32_t> hash_table_;
     229             :     uint32_t max_size_;
     230             :     uint32_t free_index_;
     231             :     uint32_t hash_id;
     232             : };
     233             : 
     234             : /////////////////////////////////////////////////////////////////////////////
     235             : // Class to manage supported tunnel-types
     236             : /////////////////////////////////////////////////////////////////////////////
     237             : class TunnelType {
     238             : public:
     239             :     // Various tunnel-types supported
     240             :     enum Type {
     241             :         INVALID,
     242             :         MPLS_GRE,
     243             :         MPLS_UDP,
     244             :         VXLAN,
     245             :         NATIVE,
     246             :         MPLS_OVER_MPLS
     247             :     };
     248             :     // Bitmap of supported tunnel types
     249             :     typedef uint32_t TypeBmap;
     250             :     typedef std::list<Type> PriorityList;
     251             : 
     252      104853 :     TunnelType(Type type) : type_(type) { }
     253      107571 :     ~TunnelType() { }
     254        1032 :     bool Compare(const TunnelType &rhs) const {
     255        1032 :         return type_ == rhs.type_;
     256             :     }
     257         718 :     bool IsLess(const TunnelType &rhs) const {
     258         718 :         return type_ < rhs.type_;
     259             :     }
     260             : 
     261         139 :    std::string ToString() const {
     262         139 :        switch (type_) {
     263         127 :        case MPLS_GRE:
     264         127 :            return "MPLSoGRE";
     265           0 :        case MPLS_UDP:
     266           0 :            return "MPLSoUDP";
     267          12 :        case VXLAN:
     268          12 :            return "VXLAN";
     269           0 :        case NATIVE:
     270           0 :            return "Native";
     271           0 :        case MPLS_OVER_MPLS:
     272           0 :            return "MPLSoMPLS";
     273           0 :        default:
     274           0 :            break;
     275             :        }
     276           0 :        return "UNKNOWN";
     277             :    }
     278             : 
     279           0 :     static std::string GetString(uint32_t type) {
     280           0 :         std::ostringstream tunnel_type;
     281           0 :         if (type & (1 << MPLS_GRE)) {
     282           0 :             tunnel_type << "MPLSoGRE ";
     283             :         }
     284             : 
     285           0 :         if (type & (1 << MPLS_UDP)) {
     286           0 :             tunnel_type << "MPLSoUDP ";
     287             :         }
     288             : 
     289           0 :         if (type & ( 1 << VXLAN)) {
     290           0 :             tunnel_type << "VxLAN";
     291             :         }
     292             : 
     293           0 :         if (type & (1 << NATIVE)) {
     294           0 :             tunnel_type << "Underlay";
     295             :         }
     296             : 
     297           0 :         if (type & (1 << MPLS_OVER_MPLS)) {
     298           0 :             tunnel_type << "MPLSoMPLS";
     299             :         }
     300             : 
     301           0 :         return tunnel_type.str();
     302           0 :     }
     303             : 
     304        1017 :     Type GetType() const {return type_;}
     305          53 :     void SetType(TunnelType::Type type) {type_ = type;}
     306             : 
     307           2 :     static void SetDefaultType(Type type) {default_type_ = type;}
     308             :     static Type ComputeType(TypeBmap bmap);
     309             :     static Type DefaultMplsComputeType();
     310        2112 :     static Type DefaultType() {return default_type_;}
     311             :     static TypeBmap DefaultTypeBmap() {return (1 << DefaultType());}
     312         298 :     static TypeBmap VxlanType() {return (1 << VXLAN);};
     313        3736 :     static TypeBmap MplsType() {return ((1 << MPLS_GRE) | (1 << MPLS_UDP));};
     314        2135 :     static TypeBmap MplsoMplsType() {return (1 << MPLS_OVER_MPLS);};
     315          32 :     static TypeBmap GetTunnelBmap(TunnelType::Type type) {
     316          32 :         if (type == MPLS_GRE || type == MPLS_UDP)
     317           8 :             return TunnelType::MplsType();
     318          24 :         if (type == VXLAN)
     319          24 :             return TunnelType::VxlanType();
     320           0 :         return TunnelType::AllType();
     321             :     }
     322       11958 :     static TypeBmap AllType() {return ((1 << MPLS_GRE) | (1 << MPLS_UDP) |
     323       11958 :                                        (1 << VXLAN));}
     324        2018 :     static TypeBmap GREType() {return (1 << MPLS_GRE);}
     325         129 :     static TypeBmap UDPType() {return (1 << MPLS_UDP);}
     326        1104 :     static TypeBmap NativeType() {return (1 << NATIVE);}
     327             :     static TypeBmap MPLSType() {return (1 << MPLS_OVER_MPLS);}
     328             :     static bool EncapPrioritySync(const std::vector<std::string> &cfg_list);
     329             :     static void DeletePriorityList();
     330             : 
     331             : private:
     332             :     Type type_;
     333             :     static PriorityList priority_list_;
     334             :     static Type default_type_;
     335             : };
     336             : 
     337             : /////////////////////////////////////////////////////////////////////////////
     338             : // Base class for NextHop. Implementation of specific NextHop must
     339             : // derive from this class
     340             : /////////////////////////////////////////////////////////////////////////////
     341             : class NextHop : AgentRefCount<NextHop>, public AgentDBEntry {
     342             : public:
     343             :     static const uint32_t kInvalidIndex = 0xFFFFFFFF;
     344             :     enum Type {
     345             :         INVALID,
     346             :         DISCARD,
     347             :         L2_RECEIVE,
     348             :         RECEIVE,
     349             :         RESOLVE,
     350             :         ARP,
     351             :         VRF,
     352             :         INTERFACE,
     353             :         TUNNEL,
     354             :         MIRROR,
     355             :         COMPOSITE,
     356             :         VLAN,
     357             :         PBB,
     358             :         NDP
     359             :     };
     360             : 
     361       12141 :     NextHop(Type type, bool policy) :
     362       12141 :         type_(type), valid_(true), policy_(policy), id_(kInvalidIndex),
     363       12141 :         mpls_label_(), learning_enabled_(false), etree_leaf_(false) {}
     364       25455 :     NextHop(Type type, bool valid, bool policy) :
     365       25455 :         type_(type), valid_(valid), policy_(policy), id_(kInvalidIndex),
     366       25455 :         mpls_label_(), learning_enabled_(false), etree_leaf_(false) {}
     367             :     virtual ~NextHop();
     368             : 
     369           0 :     virtual std::string ToString() const { return "NH";}
     370             :     virtual void Add(Agent *agent, const DBRequest *req);
     371             :     virtual bool ChangeEntry(const DBRequest *req) = 0;
     372             :     virtual void Change(const DBRequest *req);
     373           0 :     virtual void Delete(const DBRequest *req) {};
     374             :     virtual void SetKey(const DBRequestKey *key);
     375             :     virtual bool NextHopIsLess(const DBEntry &rhs) const = 0;
     376             :     virtual void SendObjectLog(const NextHopTable *table,
     377             :                                AgentLogEvent::type event) const;
     378             :     virtual bool CanAdd() const = 0;
     379      329144 :     virtual bool IsLess(const DBEntry &rhs) const {
     380      329144 :         const NextHop &a = static_cast<const NextHop &>(rhs);
     381      329144 :         if (type_ != a.type_) {
     382       65525 :             return type_ < a.type_;
     383             :         }
     384      263619 :         if (policy_ != a.policy_) {
     385       39061 :             return policy_ < a.policy_;
     386             :         }
     387      224558 :         bool ret = NextHopIsLess(rhs);
     388      224558 :         return ret;
     389             :     }
     390             : 
     391           8 :     virtual bool DeleteOnZeroRefCount() const {
     392           8 :         return false;
     393             :     }
     394         118 :     virtual void OnZeroRefCount() {};
     395             : 
     396        1688 :     uint32_t GetRefCount() const {
     397        1688 :         return AgentRefCount<NextHop>::GetRefCount();
     398             :     }
     399             : 
     400        1731 :     void ResetMplsRef() {
     401        1731 :         if (mpls_label_.get() != NULL) {
     402         902 :             mpls_label_.reset();
     403             :         }
     404        1731 :     }
     405             : 
     406      115533 :     Type GetType() const {return type_;}
     407       20229 :     bool IsValid() const {return valid_;};
     408       27244 :     bool PolicyEnabled() const {return policy_;};
     409       38162 :     uint32_t id() const { return id_;}
     410        1688 :     void set_id(uint32_t index) { id_ = index;}
     411             : 
     412             :     void set_etree_leaf(bool val) {
     413             :         etree_leaf_ = val;
     414             :     }
     415             : 
     416        2006 :     bool etree_leaf() const {
     417        2006 :         return etree_leaf_;
     418             :     }
     419             : 
     420             :     void set_learning_flag(bool val) {
     421             :         learning_enabled_ = val;
     422             :     }
     423             : 
     424       19459 :     bool learning_enabled() const {
     425       19459 :         return learning_enabled_;
     426             :     }
     427             : 
     428             :     bool DBEntrySandesh(Sandesh *sresp, std::string &name) const;
     429             :     void SetNHSandeshData(NhSandeshData &data) const;
     430             :     static void FillObjectLogIntf(const Interface *intf,
     431             :                                   NextHopObjectLogInfo &info);
     432             :     static void FillObjectLogMac(const unsigned char *m,
     433             :                                  NextHopObjectLogInfo &info);
     434             :     bool NexthopToInterfacePolicy() const;
     435        6125 :     const MplsLabel *mpls_label() const {
     436        6125 :         return mpls_label_.get();
     437             :     }
     438             : 
     439             :     virtual bool MatchEgressData(const NextHop *nh) const = 0;
     440             :     MplsLabel *AllocateLabel(Agent *agent, const NextHopKey *key);
     441             :     virtual bool NeedMplsLabel() = 0;
     442             :     void PostAdd();
     443             :     void EnqueueResync() const;
     444             : protected:
     445             :     void FillObjectLog(AgentLogEvent::type event,
     446             :                        NextHopObjectLogInfo &info) const;
     447             :     Type type_;
     448             :     bool valid_;
     449             :     bool policy_;
     450             :     uint32_t id_;
     451             :     MplsLabelRef mpls_label_;
     452             :     bool learning_enabled_;
     453             :     bool etree_leaf_;
     454             : private:
     455             :     DISALLOW_COPY_AND_ASSIGN(NextHop);
     456             : };
     457             : 
     458             : class NextHopData : public AgentData {
     459             : public:
     460         720 :     NextHopData() : AgentData(), learning_enabled_(false), etree_leaf_(false) {};
     461        8226 :     NextHopData(bool learning_enabled, bool etree_leaf):
     462        8226 :         learning_enabled_(learning_enabled), etree_leaf_(etree_leaf) {}
     463        8946 :     virtual ~NextHopData() {};
     464             : protected:
     465             :     bool learning_enabled_;
     466             :     bool etree_leaf_;
     467             :     DISALLOW_COPY_AND_ASSIGN(NextHopData);
     468             : };
     469             : 
     470             : class NextHopKey : public AgentKey {
     471             : public:
     472       30244 :     NextHopKey(NextHop::Type type, bool policy) :
     473       30244 :         AgentKey(), type_(type), policy_(policy) { }
     474       29606 :     virtual ~NextHopKey() { };
     475             : 
     476             :     virtual NextHop *AllocEntry() const = 0;
     477             :     virtual NextHopKey *Clone() const = 0;
     478           0 :     virtual bool NextHopKeyIsLess(const NextHopKey &rhs) const {
     479           0 :         assert(0);
     480             :         return false;
     481             :     }
     482      137352 :     bool IsEqual(const NextHopKey &rhs) const {
     483      137352 :         if (type_ != rhs.type_) {
     484           0 :             return false;
     485             :         }
     486      137352 :         if (policy_ != rhs.policy_) {
     487           0 :             return false;
     488             :         }
     489      268922 :         if (NextHopKeyIsLess(rhs) == false &&
     490      131570 :             rhs.NextHopKeyIsLess(*this) == false) {
     491      129447 :             return true;
     492             :         }
     493        7905 :         return false;
     494             :     }
     495             : 
     496         670 :     void SetPolicy(bool policy) {
     497         670 :         policy_ = policy;
     498         670 :     };
     499             : 
     500       14898 :     NextHop::Type GetType() const {return type_;}
     501          37 :     bool GetPolicy() const {return policy_;}
     502       32174 :     bool IsLess(const NextHopKey &rhs) const {
     503       32174 :         if (type_ != rhs.type_) {
     504        1131 :             return type_ < rhs.type_;
     505             :         }
     506       31043 :         if (policy_ != rhs.policy_) {
     507        2021 :             return policy_;
     508             :         }
     509       29022 :         return NextHopKeyIsLess(rhs);
     510             :     }
     511             : protected:
     512             :     friend class NextHop;
     513             :     NextHop::Type type_;
     514             :     bool policy_;
     515             : private:
     516             :     DISALLOW_COPY_AND_ASSIGN(NextHopKey);
     517             : };
     518             : 
     519             : /////////////////////////////////////////////////////////////////////////////
     520             : // Discard NH definition
     521             : /////////////////////////////////////////////////////////////////////////////
     522             : class DiscardNHKey : public NextHopKey {
     523             : public:
     524         359 :     DiscardNHKey() : NextHopKey(NextHop::DISCARD, false) { };
     525         585 :     virtual ~DiscardNHKey() { };
     526           0 :     virtual bool NextHopKeyIsLess(const NextHopKey &rhs) const {
     527             :         // There is single DiscardNH. There is no field to compare
     528           0 :         return false;
     529             :     }
     530             : 
     531         131 :     virtual NextHopKey *Clone() const { return new DiscardNHKey(); }
     532             : private:
     533             : 
     534             :     virtual NextHop *AllocEntry() const;
     535             : private:
     536             :     DISALLOW_COPY_AND_ASSIGN(DiscardNHKey);
     537             : };
     538             : 
     539             : class DiscardNHData : public NextHopData {
     540             : public:
     541           2 :     DiscardNHData() : NextHopData() {};
     542           4 :     virtual ~DiscardNHData() {};
     543             : private:
     544             :     DISALLOW_COPY_AND_ASSIGN(DiscardNHData);
     545             : };
     546             : 
     547             : class DiscardNH : public NextHop {
     548             : public:
     549        2408 :     DiscardNH() : NextHop(DISCARD, true, false) { };
     550        2707 :     virtual ~DiscardNH() { };
     551             : 
     552           0 :     virtual std::string ToString() const { return "DISCARD"; };
     553             :     // No change expected to Discard NH */
     554          82 :     virtual bool ChangeEntry(const DBRequest *req) { return false; };
     555           2 :     virtual void Delete(const DBRequest *req) {};
     556        4816 :     virtual bool NextHopIsLess(const DBEntry &rhs) const { return false; };
     557           0 :     virtual void SetKey(const DBRequestKey *key) { NextHop::SetKey(key); };
     558             :     virtual bool CanAdd() const;
     559          13 :     virtual KeyPtr GetDBRequestKey() const {
     560          13 :         return DBEntryBase::KeyPtr(new DiscardNHKey());
     561             :     };
     562             : 
     563           0 :     virtual bool MatchEgressData(const NextHop *nh) const {
     564           0 :         return false;
     565             :     }
     566          82 :     virtual bool NeedMplsLabel() { return false; }
     567             :     static void Create();
     568             : 
     569             : private:
     570             :     DISALLOW_COPY_AND_ASSIGN(DiscardNH);
     571             : };
     572             : 
     573             : /////////////////////////////////////////////////////////////////////////////
     574             : // Bridge Receive NH definition
     575             : /////////////////////////////////////////////////////////////////////////////
     576             : class L2ReceiveNHKey : public NextHopKey {
     577             : public:
     578          10 :     L2ReceiveNHKey() : NextHopKey(NextHop::L2_RECEIVE, false) { }
     579          18 :     virtual ~L2ReceiveNHKey() { }
     580           0 :     virtual bool NextHopKeyIsLess(const NextHopKey &rhs) const {
     581             :         // There is single Bridge Receive NH. There is no field to compare
     582           0 :         return false;
     583             :     }
     584           0 :     virtual NextHopKey *Clone() const { return new L2ReceiveNHKey(); }
     585             : 
     586             : private:
     587             : 
     588             :     virtual NextHop *AllocEntry() const;
     589             : private:
     590             :     DISALLOW_COPY_AND_ASSIGN(L2ReceiveNHKey);
     591             : };
     592             : 
     593             : class L2ReceiveNHData : public NextHopData {
     594             : public:
     595           2 :     L2ReceiveNHData() : NextHopData() {};
     596           4 :     virtual ~L2ReceiveNHData() {};
     597             : private:
     598             :     DISALLOW_COPY_AND_ASSIGN(L2ReceiveNHData);
     599             : };
     600             : 
     601             : class L2ReceiveNH : public NextHop {
     602             : public:
     603          10 :     L2ReceiveNH() : NextHop(L2_RECEIVE, true, false) { };
     604          20 :     virtual ~L2ReceiveNH() { };
     605             : 
     606           0 :     virtual std::string ToString() const { return "L2-Receive"; };
     607             :     // No change expected to Discard NH */
     608           2 :     virtual bool ChangeEntry(const DBRequest *req) { return false; };
     609           2 :     virtual void Delete(const DBRequest *req) {};
     610          18 :     virtual bool NextHopIsLess(const DBEntry &rhs) const { return false; };
     611           0 :     virtual void SetKey(const DBRequestKey *key) { NextHop::SetKey(key); };
     612             :     virtual bool CanAdd() const;
     613           6 :     virtual KeyPtr GetDBRequestKey() const {
     614           6 :         return DBEntryBase::KeyPtr(new L2ReceiveNHKey());
     615             :     };
     616             : 
     617           0 :     virtual bool MatchEgressData(const NextHop *nh) const {
     618           0 :         return false;
     619             :     }
     620           2 :     virtual bool NeedMplsLabel() { return false; }
     621             :     static void Create();
     622             : 
     623             : private:
     624             :     DISALLOW_COPY_AND_ASSIGN(L2ReceiveNH);
     625             : };
     626             : 
     627             : /////////////////////////////////////////////////////////////////////////////
     628             : // Receive NH definition
     629             : /////////////////////////////////////////////////////////////////////////////
     630             : class ReceiveNHKey : public NextHopKey {
     631             : public:
     632          46 :     ReceiveNHKey(InterfaceKey *intf_key, bool policy) :
     633          46 :         NextHopKey(NextHop::RECEIVE, policy), intf_key_(intf_key) {
     634          46 :     }
     635          74 :     virtual ~ReceiveNHKey() { };
     636             :     virtual NextHop *AllocEntry() const;
     637           0 :     virtual NextHopKey *Clone() const {
     638           0 :         return new ReceiveNHKey(intf_key_->Clone(), policy_);
     639             :     }
     640             : 
     641             : private:
     642             :     friend class ReceiveNH;
     643             :     boost::scoped_ptr<InterfaceKey> intf_key_;
     644             :     DISALLOW_COPY_AND_ASSIGN(ReceiveNHKey);
     645             : };
     646             : 
     647             : class ReceiveNHData : public NextHopData {
     648             : public:
     649           8 :     ReceiveNHData() : NextHopData() {};
     650          16 :     virtual ~ReceiveNHData() {};
     651             : 
     652             : private:
     653             :     friend class ReceiveNH;
     654             :     DISALLOW_COPY_AND_ASSIGN(ReceiveNHData);
     655             : };
     656             : 
     657             : class ReceiveNH : public NextHop {
     658             : public:
     659          46 :     ReceiveNH(Interface *intf, bool policy) :
     660          46 :         NextHop(RECEIVE, true, policy), interface_(intf) { };
     661          92 :     virtual ~ReceiveNH() { };
     662             : 
     663             :     virtual void SetKey(const DBRequestKey *key);
     664           0 :     virtual std::string ToString() const { return "Local Receive"; };
     665             :     // No change expected to Receive NH */
     666          16 :     virtual bool ChangeEntry(const DBRequest *req) { return false;};
     667           4 :     virtual void Delete(const DBRequest *req) {};
     668             :     virtual void SendObjectLog(const NextHopTable *table,
     669             :                                AgentLogEvent::type event) const;
     670             :     virtual bool CanAdd() const;
     671          88 :     virtual bool NextHopIsLess(const DBEntry &rhs) const {
     672          88 :         const ReceiveNH &a = static_cast<const ReceiveNH &>(rhs);
     673          88 :         return interface_.get() < a.interface_.get();
     674             :     };
     675             : 
     676          12 :     virtual KeyPtr GetDBRequestKey() const {
     677             :         return DBEntryBase::KeyPtr
     678          24 :             (new ReceiveNHKey(dynamic_cast<InterfaceKey *>(interface_->GetDBRequestKey().release()),
     679          24 :                               policy_));
     680             :     };
     681             : 
     682             :     static void CreateReq(const string &interface);
     683             :     static void Create(NextHopTable *table, const Interface *intf,
     684             :                        bool policy);
     685             :     static void Delete(NextHopTable *table, const Interface *intf,
     686             :                        bool policy);
     687         100 :     const Interface *GetInterface() const {return interface_.get();};
     688             : 
     689           0 :     virtual bool MatchEgressData(const NextHop *nh) const {
     690           0 :         return false;
     691             :     }
     692             : 
     693          16 :     virtual bool NeedMplsLabel() { return false; }
     694             : private:
     695             :     InterfaceRef interface_;
     696             :     DISALLOW_COPY_AND_ASSIGN(ReceiveNH);
     697             : };
     698             : 
     699             : /////////////////////////////////////////////////////////////////////////////
     700             : // Resolve NH definition
     701             : /////////////////////////////////////////////////////////////////////////////
     702             : class ResolveNHKey : public NextHopKey {
     703             : public:
     704           8 :     ResolveNHKey(const InterfaceKey *intf_key, bool policy) :
     705             :         NextHopKey(NextHop::RESOLVE, policy),
     706           8 :         intf_key_(intf_key->Clone()) { };
     707          14 :     virtual ~ResolveNHKey() { };
     708             : 
     709             :     virtual NextHop *AllocEntry() const;
     710           0 :     virtual NextHopKey *Clone() const {
     711           0 :         return new ResolveNHKey(intf_key_->Clone(), policy_);
     712             :     }
     713             : private:
     714             :     friend class ResolveNH;
     715             :     boost::scoped_ptr<const InterfaceKey> intf_key_;
     716             :     DISALLOW_COPY_AND_ASSIGN(ResolveNHKey);
     717             : };
     718             : 
     719             : class ResolveNHData : public NextHopData {
     720             : public:
     721           2 :     ResolveNHData() : NextHopData() {};
     722           4 :     virtual ~ResolveNHData() { };
     723             : 
     724             : private:
     725             :     friend class ResolveNH;
     726             :     DISALLOW_COPY_AND_ASSIGN(ResolveNHData);
     727             : };
     728             : 
     729             : class ResolveNH : public NextHop {
     730             : public:
     731           8 :     ResolveNH(const Interface *intf, bool policy) :
     732           8 :         NextHop(RESOLVE, true, policy), interface_(intf) { };
     733          16 :     virtual ~ResolveNH() { };
     734             : 
     735           0 :     virtual std::string ToString() const { return "Resolve"; };
     736             :     // No change expected to Resolve NH */
     737           2 :     virtual bool ChangeEntry(const DBRequest *req) { return false;};
     738           2 :     virtual void Delete(const DBRequest *req) {};
     739           0 :     virtual void SetKey(const DBRequestKey *key) { NextHop::SetKey(key); };
     740             :     virtual bool CanAdd() const;
     741          16 :     virtual bool NextHopIsLess(const DBEntry &rhs) const {
     742          16 :         const ResolveNH &a = static_cast<const ResolveNH &>(rhs);
     743          16 :         return interface_.get() < a.interface_.get();
     744             :     };
     745           4 :     virtual KeyPtr GetDBRequestKey() const {
     746             :         boost::scoped_ptr<InterfaceKey> intf_key(
     747           4 :             static_cast<InterfaceKey *>(interface_->GetDBRequestKey().release()));
     748           8 :         return DBEntryBase::KeyPtr(new ResolveNHKey(intf_key.get(), policy_));
     749           4 :     };
     750           2 :     virtual bool DeleteOnZeroRefCount() const {
     751           2 :         return true;
     752             :     }
     753             :     static void Create(const InterfaceKey *intf, bool policy);
     754             :     static void CreateReq(const InterfaceKey *intf, bool policy);
     755          40 :     const Interface* get_interface() const { return interface_.get();}
     756             : 
     757           0 :     virtual bool MatchEgressData(const NextHop *nh) const {
     758           0 :         return false;
     759             :     }
     760           2 :     virtual bool NeedMplsLabel() { return false; }
     761             : 
     762             : private:
     763             :     InterfaceConstRef interface_;
     764             :     DISALLOW_COPY_AND_ASSIGN(ResolveNH);
     765             : };
     766             : 
     767             : /////////////////////////////////////////////////////////////////////////////
     768             : // ARP NH definition
     769             : /////////////////////////////////////////////////////////////////////////////
     770             : class ArpNHKey : public NextHopKey {
     771             : public:
     772          32 :     ArpNHKey(const string &vrf_name, const Ip4Address &ip, bool policy) :
     773          32 :         NextHopKey(NextHop::ARP, policy), vrf_key_(vrf_name), dip_(ip) {
     774          32 :     }
     775          46 :     virtual ~ArpNHKey() { };
     776             : 
     777             :     virtual NextHop *AllocEntry() const;
     778           0 :     virtual NextHopKey *Clone() const {
     779           0 :         return new ArpNHKey(vrf_key_.name_, dip_, policy_);
     780             :     }
     781           0 :     virtual bool NextHopKeyIsLess(const NextHopKey &rhs) const {
     782           0 :         const ArpNHKey &key = static_cast<const ArpNHKey &>(rhs);
     783           0 :         if (vrf_key_.IsEqual(key.vrf_key_) == false) {
     784           0 :             return vrf_key_.IsLess(key.vrf_key_);
     785             :         }
     786             : 
     787           0 :         if (dip_ != key.dip_) {
     788           0 :             return dip_ < key.dip_;
     789             :         }
     790             : 
     791           0 :         return false;
     792             :     }
     793             : private:
     794             :     friend class ArpNH;
     795             :     VrfKey vrf_key_;
     796             :     Ip4Address dip_;
     797             :     DISALLOW_COPY_AND_ASSIGN(ArpNHKey);
     798             : };
     799             : 
     800             : class ArpNHData : public NextHopData {
     801             : public:
     802           4 :     ArpNHData(InterfaceKey *intf_key) :
     803           4 :         NextHopData(), intf_key_(intf_key),
     804           4 :         mac_(), resolved_(false), valid_(false) { };
     805             : 
     806           6 :     ArpNHData(const MacAddress &mac, InterfaceKey *intf_key,
     807           6 :               bool resolved) : NextHopData(), intf_key_(intf_key), mac_(mac),
     808           6 :         resolved_(resolved), valid_(true) {
     809           6 :     }
     810          20 :     virtual ~ArpNHData() { };
     811             : 
     812             : private:
     813             :     friend class ArpNH;
     814             :     boost::scoped_ptr<InterfaceKey> intf_key_;
     815             :     MacAddress mac_;
     816             :     bool resolved_;
     817             :     bool valid_;
     818             :     DISALLOW_COPY_AND_ASSIGN(ArpNHData);
     819             : };
     820             : 
     821             : class ArpNH : public NextHop {
     822             : public:
     823          32 :     ArpNH(VrfEntry *vrf, const Ip4Address &ip) :
     824          32 :         NextHop(ARP, false, false), vrf_(vrf, this), ip_(ip), interface_(), mac_() {};
     825          64 :     virtual ~ArpNH() { };
     826             : 
     827           0 :     virtual std::string ToString() { return "ARP"; }
     828             :     virtual bool NextHopIsLess(const DBEntry &rhs) const;
     829             :     virtual void SetKey(const DBRequestKey *key);
     830             :     virtual bool ChangeEntry(const DBRequest *req);
     831           2 :     virtual void Delete(const DBRequest *req) {};
     832             :     virtual KeyPtr GetDBRequestKey() const;
     833             :     virtual void SendObjectLog(const NextHopTable *table,
     834             :                                AgentLogEvent::type event) const;
     835             :     virtual bool CanAdd() const;
     836             : 
     837          28 :     const MacAddress &GetMac() const {return mac_;};
     838          62 :     const Interface *GetInterface() const {return interface_.get();};
     839             :     const boost::uuids::uuid &GetIfUuid() const;
     840             :     const uint32_t vrf_id() const;
     841          38 :     const Ip4Address *GetIp() const {return &ip_;};
     842          18 :     const VrfEntry *GetVrf() const {return vrf_.get();};
     843           4 :     bool GetResolveState() const {return valid_;}
     844           2 :     virtual bool DeleteOnZeroRefCount() const {
     845           2 :         return true;
     846             :     }
     847             : 
     848           0 :     virtual bool MatchEgressData(const NextHop *nh) const {
     849           0 :         const ArpNH *arp_nh = dynamic_cast<const ArpNH *>(nh);
     850           0 :         if (arp_nh && vrf_ == arp_nh->vrf_ && ip_ == arp_nh->ip_) {
     851           0 :             return true;
     852             :         }
     853           0 :         return false;
     854             :     }
     855           8 :     virtual bool NeedMplsLabel() { return false; }
     856             : 
     857             : private:
     858             :     VrfEntryRef vrf_;
     859             :     Ip4Address ip_;
     860             :     InterfaceRef interface_;
     861             :     MacAddress mac_;
     862             :     DISALLOW_COPY_AND_ASSIGN(ArpNH);
     863             : };
     864             : 
     865             : /////////////////////////////////////////////////////////////////////////////
     866             : // NDP NH definition
     867             : /////////////////////////////////////////////////////////////////////////////
     868             : class NdpNHKey : public NextHopKey {
     869             : public:
     870           0 :     NdpNHKey(const string &vrf_name, const IpAddress &ip, bool policy) :
     871           0 :         NextHopKey(NextHop::NDP, policy), vrf_key_(vrf_name), dip_(ip) {
     872           0 :     }
     873           0 :     virtual ~NdpNHKey() { };
     874             : 
     875             :     virtual NextHop *AllocEntry() const;
     876           0 :     virtual NextHopKey *Clone() const {
     877           0 :         return new NdpNHKey(vrf_key_.name_, dip_, policy_);
     878             :     }
     879             :     string ToString() {
     880             :         return vrf_key_.name_ + dip_.to_string();
     881             :     }
     882             : private:
     883             :     friend class NdpNH;
     884             :     VrfKey vrf_key_;
     885             :     IpAddress dip_;
     886             :     DISALLOW_COPY_AND_ASSIGN(NdpNHKey);
     887             : };
     888             : 
     889             : class NdpNHData : public NextHopData {
     890             : public:
     891             :     NdpNHData(InterfaceKey *intf_key) :
     892             :         NextHopData(), intf_key_(intf_key),
     893             :         mac_(), resolved_(false), valid_(false) { };
     894             : 
     895           0 :     NdpNHData(const MacAddress &mac, InterfaceKey *intf_key,
     896           0 :               bool resolved) : NextHopData(), intf_key_(intf_key), mac_(mac),
     897           0 :         resolved_(resolved), valid_(true) {
     898           0 :     }
     899           0 :     virtual ~NdpNHData() { };
     900             : 
     901             : private:
     902             :     friend class NdpNH;
     903             :     boost::scoped_ptr<InterfaceKey> intf_key_;
     904             :     MacAddress mac_;
     905             :     bool resolved_;
     906             :     bool valid_;
     907             :     DISALLOW_COPY_AND_ASSIGN(NdpNHData);
     908             : };
     909             : 
     910             : class NdpNH : public NextHop {
     911             : public:
     912           0 :     NdpNH(VrfEntry *vrf, const IpAddress &ip) :
     913           0 :         NextHop(NDP, false, false), vrf_(vrf, this), ip_(ip), interface_(), mac_() {};
     914           0 :     virtual ~NdpNH() { };
     915             : 
     916           0 :     virtual std::string ToString() { return "NDP"; }
     917             :     virtual bool NextHopIsLess(const DBEntry &rhs) const;
     918             :     virtual void SetKey(const DBRequestKey *key);
     919             :     virtual bool ChangeEntry(const DBRequest *req);
     920           0 :     virtual void Delete(const DBRequest *req) {};
     921             :     virtual KeyPtr GetDBRequestKey() const;
     922             :     virtual void SendObjectLog(const NextHopTable *table,
     923             :                                AgentLogEvent::type event) const;
     924             :     virtual bool CanAdd() const;
     925             : 
     926           0 :     const MacAddress &GetMac() const {return mac_;};
     927           0 :     const Interface *GetInterface() const {return interface_.get();};
     928             :     const boost::uuids::uuid &GetIfUuid() const;
     929             :     const uint32_t vrf_id() const;
     930           0 :     const IpAddress *GetIp() const {return &ip_;};
     931           0 :     const VrfEntry *GetVrf() const {return vrf_.get();};
     932           0 :     bool GetResolveState() const {return valid_;}
     933           0 :     virtual bool DeleteOnZeroRefCount() const {
     934           0 :         return true;
     935             :     }
     936             : 
     937           0 :     virtual bool MatchEgressData(const NextHop *nh) const {
     938           0 :         const NdpNH *ndp_nh = dynamic_cast<const NdpNH *>(nh);
     939           0 :         if (ndp_nh && vrf_ == ndp_nh->vrf_ && ip_ == ndp_nh->ip_) {
     940           0 :             return true;
     941             :         }
     942           0 :         return false;
     943             :     }
     944           0 :     virtual bool NeedMplsLabel() { return false; }
     945             : 
     946             : private:
     947             :     VrfEntryRef vrf_;
     948             :     IpAddress ip_;
     949             :     InterfaceRef interface_;
     950             :     MacAddress mac_;
     951             :     DISALLOW_COPY_AND_ASSIGN(NdpNH);
     952             : };
     953             : 
     954             : /////////////////////////////////////////////////////////////////////////////
     955             : // Tunnel NH definition
     956             : /////////////////////////////////////////////////////////////////////////////
     957             : class TunnelNHKey : public NextHopKey {
     958             : public:
     959         281 :     TunnelNHKey(const string &vrf_name,
     960             :                 const Ip4Address &sip,
     961             :                 const Ip4Address &dip,
     962             :                 bool policy,
     963             :                 TunnelType type,
     964         281 :                 const MacAddress &rewrite_dmac = MacAddress()) :
     965         281 :         NextHopKey(NextHop::TUNNEL, policy), vrf_key_(vrf_name), sip_(sip),
     966         562 :         dip_(dip), tunnel_type_(type), rewrite_dmac_(rewrite_dmac) {
     967         281 :     };
     968         492 :     virtual ~TunnelNHKey() { };
     969             : 
     970             :     virtual NextHop *AllocEntry() const;
     971          26 :     virtual NextHopKey *Clone() const {
     972          26 :         return new TunnelNHKey(vrf_key_.name_, sip_, dip_,
     973          52 :                                NextHopKey::GetPolicy(), tunnel_type_,
     974          52 :                                rewrite_dmac_);
     975             :     }
     976             : 
     977         683 :     virtual bool NextHopKeyIsLess(const NextHopKey &rhs) const {
     978         683 :         const TunnelNHKey &key = static_cast<const TunnelNHKey &>(rhs);
     979         683 :         if (vrf_key_.IsEqual(key.vrf_key_) == false) {
     980           0 :             return vrf_key_.IsLess(key.vrf_key_);
     981             :         }
     982             : 
     983         683 :         if (sip_ != key.sip_) {
     984           0 :             return sip_ < key.sip_;
     985             :         }
     986             : 
     987         683 :         if (dip_ != key.dip_) {
     988           1 :             return dip_ < key.dip_;
     989             :         }
     990             : 
     991         682 :         if (rewrite_dmac_ != key.rewrite_dmac_) {
     992           0 :             return rewrite_dmac_ < key.rewrite_dmac_;
     993             :         }
     994             : 
     995         682 :         return tunnel_type_.IsLess(key.tunnel_type_);
     996             :     }
     997           5 :     void set_tunnel_type(TunnelType tunnel_type) {
     998           5 :         tunnel_type_ = tunnel_type;
     999           5 :     }
    1000           0 :     const Ip4Address& dip() const {
    1001           0 :         return dip_;
    1002             :     }
    1003           0 :     const MacAddress& rewrite_dmac() {
    1004           0 :         return rewrite_dmac_;
    1005             :     }
    1006             : protected:
    1007             :     friend class TunnelNH;
    1008             :     VrfKey vrf_key_;
    1009             :     Ip4Address sip_;
    1010             :     Ip4Address dip_;
    1011             :     TunnelType tunnel_type_;
    1012             :     MacAddress rewrite_dmac_;
    1013             : private:
    1014             :     DISALLOW_COPY_AND_ASSIGN(TunnelNHKey);
    1015             : };
    1016             : 
    1017             : class TunnelNHData : public NextHopData {
    1018             : public:
    1019          91 :     TunnelNHData() : NextHopData() {};
    1020         182 :     virtual ~TunnelNHData() { };
    1021             : private:
    1022             :     friend class TunnelNH;
    1023             :     DISALLOW_COPY_AND_ASSIGN(TunnelNHData);
    1024             : };
    1025             : 
    1026             : /////////////////////////////////////////////////////////////////////////////
    1027             : // Labelled Tunnel NH definition
    1028             : /////////////////////////////////////////////////////////////////////////////
    1029             : class LabelledTunnelNHKey : public TunnelNHKey {
    1030             : public:
    1031           0 :     LabelledTunnelNHKey(const string &vrf_name,
    1032             :                 const Ip4Address &sip,
    1033             :                 const Ip4Address &dip,
    1034             :                 bool policy,
    1035             :                 TunnelType type,
    1036             :                 const MacAddress &rewrite_dmac = MacAddress(),
    1037           0 :                 uint32_t label = 3) :
    1038             :         TunnelNHKey(vrf_name, sip, dip, policy, type, rewrite_dmac),
    1039           0 :         transport_mpls_label_(label) {
    1040           0 :     };
    1041           0 :     virtual ~LabelledTunnelNHKey() { };
    1042             : 
    1043             :     virtual NextHop *AllocEntry() const;
    1044           0 :     virtual bool NextHopKeyIsLess(const NextHopKey &rhs) const {
    1045           0 :         const LabelledTunnelNHKey &key = static_cast<const LabelledTunnelNHKey &>(rhs);
    1046           0 :             if (vrf_key_.IsEqual(key.vrf_key_) == false) {
    1047           0 :                 return vrf_key_.IsLess(key.vrf_key_);
    1048             :             }
    1049             : 
    1050           0 :             if (sip_ != key.sip_) {
    1051           0 :                 return sip_ < key.sip_;
    1052             :             }
    1053             : 
    1054           0 :             if (dip_ != key.dip_) {
    1055           0 :                 return dip_ < key.dip_;
    1056             :             }
    1057             : 
    1058           0 :             if (rewrite_dmac_ != key.rewrite_dmac_) {
    1059           0 :                 return rewrite_dmac_ < key.rewrite_dmac_;
    1060             :             }
    1061           0 :             return (transport_mpls_label_ < key.transport_mpls_label_);
    1062             :     }
    1063           0 :     virtual NextHopKey *Clone() const {
    1064           0 :         return new LabelledTunnelNHKey(vrf_key_.name_, sip_, dip_,
    1065           0 :                                NextHopKey::GetPolicy(), tunnel_type_,
    1066           0 :                                rewrite_dmac_, transport_mpls_label_);
    1067             :     }
    1068             : private:
    1069             :     uint32_t transport_mpls_label_;
    1070             :     friend class LabelledTunnelNH;
    1071             :     DISALLOW_COPY_AND_ASSIGN(LabelledTunnelNHKey);
    1072             : };
    1073             : 
    1074             : class LabelledTunnelNHData : public TunnelNHData {
    1075             : public:
    1076           0 :     LabelledTunnelNHData() : TunnelNHData() {};
    1077           0 :     virtual ~LabelledTunnelNHData() { };
    1078             : private:
    1079             :     friend class LabelledTunnelNH;
    1080             :     DISALLOW_COPY_AND_ASSIGN(LabelledTunnelNHData);
    1081             : };
    1082             : 
    1083             : class PBBNHKey : public NextHopKey {
    1084             : public:
    1085           0 :     PBBNHKey(const string &vrf_name, const MacAddress &dest_bmac, uint32_t isid):
    1086           0 :         NextHopKey(NextHop::PBB, false), vrf_key_(vrf_name),
    1087           0 :         dest_bmac_(dest_bmac), isid_(isid) {
    1088           0 :     };
    1089           0 :     virtual ~PBBNHKey() { };
    1090             : 
    1091             :     virtual NextHop *AllocEntry() const;
    1092           0 :     virtual NextHopKey *Clone() const {
    1093           0 :         return new PBBNHKey(vrf_key_.name_, dest_bmac_, isid_);
    1094             :     }
    1095             : 
    1096           0 :     virtual bool NextHopKeyIsLess(const NextHopKey &rhs) const {
    1097           0 :         const PBBNHKey &key = static_cast<const PBBNHKey &>(rhs);
    1098           0 :         if (vrf_key_.IsEqual(key.vrf_key_) == false) {
    1099           0 :             return vrf_key_.IsLess(key.vrf_key_);
    1100             :         }
    1101             : 
    1102           0 :         if (dest_bmac_ != key.dest_bmac_) {
    1103           0 :             return dest_bmac_ < key.dest_bmac_;
    1104             :         }
    1105             : 
    1106           0 :         return isid_ < key.isid_;
    1107             :     }
    1108             : 
    1109             :     const MacAddress dest_bmac() const {
    1110             :         return dest_bmac_;
    1111             :     }
    1112             : private:
    1113             :     friend class PBBNH;
    1114             :     VrfKey vrf_key_;
    1115             :     MacAddress dest_bmac_;
    1116             :     uint32_t isid_;
    1117             :     uint32_t label_;
    1118             :     NextHopConstRef nh_;
    1119             :     DISALLOW_COPY_AND_ASSIGN(PBBNHKey);
    1120             : };
    1121             : 
    1122             : class PBBNHData : public NextHopData {
    1123             : public:
    1124           0 :     PBBNHData() : NextHopData() {};
    1125           0 :     virtual ~PBBNHData() { };
    1126             : private:
    1127             :     friend class PBBNH;
    1128             :     DISALLOW_COPY_AND_ASSIGN(PBBNHData);
    1129             : };
    1130             : 
    1131             : class PBBNH : public NextHop {
    1132             : public:
    1133             :     PBBNH(VrfEntry *vrf, const MacAddress &dmac, uint32_t isid);
    1134             :     virtual ~PBBNH();
    1135             : 
    1136           0 :     virtual std::string ToString() const {
    1137           0 :         return "PBB to " + dest_bmac_.ToString();
    1138             :     }
    1139             :     virtual bool NextHopIsLess(const DBEntry &rhs) const;
    1140             :     virtual void SetKey(const DBRequestKey *key);
    1141             :     virtual bool ChangeEntry(const DBRequest *req);
    1142             :     virtual void Delete(const DBRequest *req);
    1143             :     virtual KeyPtr GetDBRequestKey() const;
    1144             :     virtual bool CanAdd() const;
    1145             : 
    1146             :     const uint32_t vrf_id() const;
    1147           0 :     const VrfEntry *vrf() const {return vrf_.get();};
    1148           0 :     const MacAddress dest_bmac() const {return dest_bmac_;};
    1149           0 :     const uint32_t isid() const { return isid_;};
    1150             :     virtual void SendObjectLog(const NextHopTable *table,
    1151             :                                AgentLogEvent::type event) const;
    1152           0 :     virtual bool DeleteOnZeroRefCount() const {
    1153           0 :         return true;
    1154             :     }
    1155             : 
    1156           0 :     virtual bool MatchEgressData(const NextHop *nh) const {
    1157           0 :         const PBBNH *pbb_nh = dynamic_cast<const PBBNH *>(nh);
    1158           0 :         if (pbb_nh && vrf_ == pbb_nh->vrf_ && dest_bmac_ == pbb_nh->dest_bmac_) {
    1159           0 :             return true;
    1160             :         }
    1161           0 :         return false;
    1162             :     }
    1163             : 
    1164           0 :     uint32_t label() const {
    1165           0 :         return label_;
    1166             :     }
    1167             : 
    1168           0 :     const NextHop *child_nh() const {
    1169           0 :         return child_nh_.get();
    1170             :     }
    1171           0 :     virtual bool NeedMplsLabel() { return false; }
    1172             : private:
    1173             :     VrfEntryRef vrf_;
    1174             :     MacAddress dest_bmac_;
    1175             :     uint32_t isid_;
    1176             :     uint32_t label_;
    1177             :     NextHopConstRef child_nh_;
    1178             :     DISALLOW_COPY_AND_ASSIGN(PBBNH);
    1179             : };
    1180             : 
    1181             : 
    1182             : /////////////////////////////////////////////////////////////////////////////
    1183             : // Interface NH definition
    1184             : /////////////////////////////////////////////////////////////////////////////
    1185             : struct InterfaceNHFlags {
    1186             :     enum Type {
    1187             :         INVALID,
    1188             :         INET4 = 1,
    1189             :         BRIDGE = 2,
    1190             :         MULTICAST = 4,
    1191             :         INET6 = 8,
    1192             :         VXLAN_ROUTING = 16
    1193             :     };
    1194             : };
    1195             : 
    1196             : class InterfaceNHKey : public NextHopKey {
    1197             : public:
    1198       20269 :     InterfaceNHKey(InterfaceKey *intf, bool policy, uint8_t flags,
    1199       20269 :                    const MacAddress &mac) :
    1200       20269 :         NextHopKey(NextHop::INTERFACE, policy), intf_key_(intf),
    1201       20269 :         flags_(flags), dmac_(mac) {
    1202             :             //TODO evpn changes remove this, just extra check
    1203       20269 :             assert((flags != (InterfaceNHFlags::INVALID)) ||
    1204             :                     (flags == (InterfaceNHFlags::INET4)) ||
    1205             :                     (flags_ == (InterfaceNHFlags::INET6)) ||
    1206             :                     (flags_ == (InterfaceNHFlags::VXLAN_ROUTING)) ||
    1207             :                     (flags ==
    1208             :                      (InterfaceNHFlags::INET4|InterfaceNHFlags::MULTICAST)));
    1209       20269 :     }
    1210             : 
    1211       32108 :     virtual ~InterfaceNHKey() {};
    1212           0 :     const boost::uuids::uuid &GetUuid() const {return intf_key_->uuid_;};
    1213           0 :     const std::string& name() const { return intf_key_->name_;};
    1214           0 :     const Interface::Type &intf_type() const {return intf_key_->type_;}
    1215             :     const InterfaceKey *intf_key() const { return intf_key_.get(); }
    1216           0 :     void set_flags(uint8_t flags) {flags_ = flags;}
    1217           0 :     const uint8_t &flags() const { return flags_; }
    1218           0 :     const MacAddress &dmac() const { return dmac_; }
    1219             : 
    1220             :     virtual NextHop *AllocEntry() const;
    1221        1672 :     virtual NextHopKey *Clone() const {
    1222             :         //TODO evpn changes remove this, just extra check
    1223        1672 :         assert((flags_ != (InterfaceNHFlags::INVALID)) ||
    1224             :                 (flags_ == (InterfaceNHFlags::INET4)) ||
    1225             :                 (flags_ == (InterfaceNHFlags::INET6)) ||
    1226             :                 (flags_ == (InterfaceNHFlags::VXLAN_ROUTING)) ||
    1227             :                 (flags_ ==
    1228             :                  (InterfaceNHFlags::INET4|InterfaceNHFlags::MULTICAST)));
    1229        1672 :         return new InterfaceNHKey(intf_key_->Clone(), policy_, flags_, dmac_);
    1230             :     }
    1231      267415 :     virtual bool NextHopKeyIsLess(const NextHopKey &rhs) const {
    1232      267415 :         const InterfaceNHKey &key = static_cast<const InterfaceNHKey &>(rhs);
    1233      267415 :         if (intf_key_->IsEqual(*key.intf_key_.get()) == false) {
    1234       24374 :             return intf_key_->IsLess(*key.intf_key_.get());
    1235             :         }
    1236             : 
    1237      243041 :         if (flags_ != key.flags_) {
    1238        3677 :             return flags_ < key.flags_;
    1239             :         }
    1240             : 
    1241      239364 :         return dmac_ < key.dmac_;
    1242             :     }
    1243             : 
    1244             : private:
    1245             :     friend class InterfaceNH;
    1246             :     boost::scoped_ptr<InterfaceKey> intf_key_;
    1247             :     uint8_t flags_;
    1248             :     MacAddress dmac_;
    1249             : };
    1250             : 
    1251             : class InterfaceNHData : public NextHopData {
    1252             : public:
    1253           8 :     InterfaceNHData(const string vrf_name) :
    1254           8 :         NextHopData(), vrf_key_(vrf_name), layer2_control_word_(false) { }
    1255        4970 :     InterfaceNHData(const string vrf_name, bool learning_enabled, bool etree_leaf,
    1256        4970 :                     bool layer2_control_word):
    1257        4970 :         NextHopData(learning_enabled, etree_leaf), vrf_key_(vrf_name),
    1258        4970 :         layer2_control_word_(layer2_control_word) {}
    1259        9956 :     virtual ~InterfaceNHData() { }
    1260             : 
    1261             : private:
    1262             :     friend class InterfaceNH;
    1263             :     VrfKey vrf_key_;
    1264             :     bool layer2_control_word_;
    1265             :     DISALLOW_COPY_AND_ASSIGN(InterfaceNHData);
    1266             : };
    1267             : 
    1268             : class InterfaceNH : public NextHop {
    1269             : public:
    1270       22336 :     InterfaceNH(Interface *intf, bool policy, uint8_t flags,
    1271       22336 :                 const MacAddress &mac) :
    1272       22336 :         NextHop(INTERFACE, true, policy), interface_(intf),
    1273       22336 :         flags_(flags), dmac_(mac), vrf_(NULL, this),
    1274       44672 :         delete_on_zero_refcount_(false) { };
    1275             :     InterfaceNH(Interface *intf, bool policy, const MacAddress &mac) :
    1276             :         NextHop(INTERFACE, true, policy), interface_(intf),
    1277             :         flags_(InterfaceNHFlags::INET4), dmac_(mac), vrf_(NULL, this),
    1278             :         delete_on_zero_refcount_(false) {};
    1279       44672 :     virtual ~InterfaceNH() { };
    1280             : 
    1281           0 :     virtual std::string ToString() const {
    1282           0 :         return "InterfaceNH : " + interface_->name();
    1283             :     };
    1284             :     virtual bool NextHopIsLess(const DBEntry &rhs) const;
    1285             :     virtual void SetKey(const DBRequestKey *key);
    1286             :     virtual bool ChangeEntry(const DBRequest *req);
    1287         844 :     virtual void Delete(const DBRequest *req) {};
    1288             :     virtual KeyPtr GetDBRequestKey() const;
    1289             :     virtual bool CanAdd() const;
    1290             :     virtual bool NeedMplsLabel();
    1291             :     virtual void SendObjectLog(const NextHopTable *table,
    1292             :                                AgentLogEvent::type event) const;
    1293             : 
    1294       73470 :     const Interface *GetInterface() const {return interface_.get();};
    1295       18824 :     const MacAddress &GetDMac() const {return dmac_;};
    1296       11332 :     bool IsVxlanRouting() const {
    1297       11332 :         return flags_ & InterfaceNHFlags::VXLAN_ROUTING;
    1298             :     }
    1299       11332 :     bool is_multicastNH() const { return flags_ & InterfaceNHFlags::MULTICAST; };
    1300       11344 :     bool IsBridge() const { return flags_ & InterfaceNHFlags::BRIDGE; };
    1301           0 :     uint8_t GetFlags() const {return flags_;};
    1302             :     const boost::uuids::uuid &GetIfUuid() const;
    1303       12291 :     const VrfEntry *GetVrf() const {return vrf_.get();};
    1304             : 
    1305             :     static void CreateMulticastVmInterfaceNH(const boost::uuids::uuid &intf_uuid,
    1306             :                                              const MacAddress &dmac,
    1307             :                                              const string &vrf_name,
    1308             :                                              const string &intf_name);
    1309             :     static void DeleteMulticastVmInterfaceNH(const boost::uuids::uuid &intf_uuid,
    1310             :                                              const MacAddress &dmac,
    1311             :                                              const std::string &intf_name);
    1312             :     static void CreateL2VmInterfaceNH(const boost::uuids::uuid &intf_uuid,
    1313             :                                       const MacAddress &dmac,
    1314             :                                       const string &vrf_name,
    1315             :                                       bool learning_enabled,
    1316             :                                       bool etree_leaf,
    1317             :                                       bool layer2_control_word,
    1318             :                                       const std::string &intf_name);
    1319             :     static void DeleteL2InterfaceNH(const boost::uuids::uuid &intf_uuid,
    1320             :                                     const MacAddress &mac,
    1321             :                                     const std::string &intf_name);
    1322             :     static void CreateL3VmInterfaceNH(const boost::uuids::uuid &intf_uuid,
    1323             :                                       const MacAddress &dmac,
    1324             :                                       const string &vrf_name,
    1325             :                                       bool learning_enabled,
    1326             :                                       const std::string &intf_name);
    1327             :     static void DeleteL3InterfaceNH(const boost::uuids::uuid &intf_uuid,
    1328             :                                     const MacAddress &mac,
    1329             :                                     const std::string &intf_name);
    1330             :     static void DeleteNH(const boost::uuids::uuid &intf_uuid,
    1331             :                          bool policy, uint8_t flags,
    1332             :                          const MacAddress &mac, const std::string &intf_name);
    1333             :     static void CreatePacketInterfaceNh(Agent *agent, const string &ifname);
    1334             :     static void CreateInetInterfaceNextHop(const string &ifname,
    1335             :                                            const string &vrf_name,
    1336             :                                            const MacAddress &mac);
    1337             :     static void DeleteInetInterfaceNextHop(const string &ifname,
    1338             :                                            const MacAddress &mac);
    1339             :     static void CreatePhysicalInterfaceNh(const string &ifname,
    1340             :                                           const MacAddress &mac);
    1341             :     static void DeletePhysicalInterfaceNh(const string &ifname,
    1342             :                                           const MacAddress &mac);
    1343         886 :     virtual bool DeleteOnZeroRefCount() const {
    1344         886 :         return delete_on_zero_refcount_;
    1345             :     }
    1346             : 
    1347           0 :     void set_delete_on_zero_refcount(bool val) {
    1348           0 :         delete_on_zero_refcount_ = val;
    1349           0 :     }
    1350             : 
    1351           0 :     virtual bool MatchEgressData(const NextHop *nh) const {
    1352             :         const InterfaceNH *intf_nh =
    1353           0 :             dynamic_cast<const InterfaceNH *>(nh);
    1354           0 :         if (intf_nh && interface_ == intf_nh->interface_) {
    1355           0 :             return true;
    1356             :         }
    1357           0 :         return false;
    1358             :     }
    1359             : 
    1360         850 :     bool layer2_control_word() const {
    1361         850 :         return layer2_control_word_;
    1362             :     }
    1363             : 
    1364             : private:
    1365             :     InterfaceRef interface_;
    1366             :     uint8_t flags_;
    1367             :     MacAddress dmac_;
    1368             :     VrfEntryRef vrf_;
    1369             :     bool delete_on_zero_refcount_;
    1370             :     bool layer2_control_word_;
    1371             :     DISALLOW_COPY_AND_ASSIGN(InterfaceNH);
    1372             : };
    1373             : 
    1374             : /////////////////////////////////////////////////////////////////////////////
    1375             : // VRF NH definition
    1376             : /////////////////////////////////////////////////////////////////////////////
    1377             : class VrfNHKey : public NextHopKey {
    1378             : public:
    1379         398 :     VrfNHKey(const string &vrf_name, bool policy, bool bridge_nh) :
    1380         796 :         NextHopKey(NextHop::VRF, policy), vrf_key_(vrf_name), policy_(policy),
    1381         398 :         bridge_nh_(bridge_nh) {
    1382         398 :     }
    1383         729 :     virtual ~VrfNHKey() { }
    1384             : 
    1385         615 :     virtual bool NextHopKeyIsLess(const NextHopKey &rhs) const {
    1386         615 :         const VrfNHKey &key = static_cast<const VrfNHKey &>(rhs);
    1387         615 :         if (vrf_key_.IsEqual(key.vrf_key_) == false) {
    1388         351 :             return vrf_key_.IsLess(key.vrf_key_);
    1389             :         }
    1390             : 
    1391         264 :         if (policy_ != key.policy_) {
    1392           0 :             return policy_ < key.policy_;
    1393             :         }
    1394         264 :         return bridge_nh_ < key.bridge_nh_;
    1395             :     }
    1396             : 
    1397             :     virtual NextHop *AllocEntry() const;
    1398         132 :     virtual NextHopKey *Clone() const {
    1399         132 :         return new VrfNHKey(vrf_key_.name_, policy_, bridge_nh_);
    1400             :     }
    1401           0 :     const std::string &GetVrfName() const { return vrf_key_.name_; }
    1402           0 :     const bool &GetBridgeNh() const { return bridge_nh_; }
    1403             : 
    1404             : private:
    1405             :     friend class VrfNH;
    1406             :     VrfKey vrf_key_;
    1407             :     bool policy_;
    1408             :     bool bridge_nh_;
    1409             :     DISALLOW_COPY_AND_ASSIGN(VrfNHKey);
    1410             : };
    1411             : 
    1412             : class VrfNHData : public NextHopData {
    1413             : public:
    1414          67 :     VrfNHData(bool flood_unknown_unicast, bool learning_enabled,
    1415          67 :               bool layer2_control_word):
    1416             :               NextHopData(learning_enabled, true),
    1417          67 :               flood_unknown_unicast_(flood_unknown_unicast),
    1418          67 :               layer2_control_word_(layer2_control_word) {}
    1419         134 :     virtual ~VrfNHData() { }
    1420             : private:
    1421             :     friend class VrfNH;
    1422             :     bool flood_unknown_unicast_;
    1423             :     bool layer2_control_word_;
    1424             :     DISALLOW_COPY_AND_ASSIGN(VrfNHData);
    1425             : };
    1426             : 
    1427             : class VrfNH : public NextHop {
    1428             : public:
    1429         332 :     VrfNH(VrfEntry *vrf, bool policy, bool bridge_nh_):
    1430         664 :         NextHop(VRF, true, policy), vrf_(vrf, this), bridge_nh_(bridge_nh_),
    1431         332 :         flood_unknown_unicast_(false) {}
    1432         664 :     virtual ~VrfNH() { };
    1433             : 
    1434           0 :     virtual std::string ToString() const { return "VrfNH"; };
    1435             :     virtual bool NextHopIsLess(const DBEntry &rhs) const;
    1436             :     virtual void SetKey(const DBRequestKey *key);
    1437             :     // No change expected for VRF Nexthop
    1438             :     virtual bool ChangeEntry(const DBRequest *req);
    1439          66 :     virtual void Delete(const DBRequest *req) {};
    1440             :     virtual KeyPtr GetDBRequestKey() const;
    1441             :     virtual void SendObjectLog(const NextHopTable *table,
    1442             :                                AgentLogEvent::type event) const;
    1443             :     virtual bool CanAdd() const;
    1444             : 
    1445         482 :     const VrfEntry *GetVrf() const {return vrf_.get();};
    1446          66 :     virtual bool DeleteOnZeroRefCount() const {
    1447          66 :         return true;
    1448             :     }
    1449         265 :     bool bridge_nh() const { return bridge_nh_; }
    1450          68 :     bool flood_unknown_unicast() const {
    1451          68 :         return flood_unknown_unicast_;
    1452             :     }
    1453             : 
    1454           0 :     virtual bool MatchEgressData(const NextHop *nh) const {
    1455           0 :         const VrfNH *vrf_nh = dynamic_cast<const VrfNH *>(nh);
    1456           0 :         if (vrf_nh && vrf_ == vrf_nh->vrf_) {
    1457           0 :             return true;
    1458             :         }
    1459           0 :         return false;
    1460             :     }
    1461             : 
    1462          66 :     bool layer2_control_word() const {
    1463          66 :         return layer2_control_word_;
    1464             :     }
    1465          67 :     virtual bool NeedMplsLabel() { return true; }
    1466             : 
    1467             : private:
    1468             :     VrfEntryRef vrf_;
    1469             :     // NH created by VXLAN
    1470             :     bool bridge_nh_;
    1471             :     bool flood_unknown_unicast_;
    1472             :     bool layer2_control_word_;
    1473             :     DISALLOW_COPY_AND_ASSIGN(VrfNH);
    1474             : };
    1475             : 
    1476             : /////////////////////////////////////////////////////////////////////////////
    1477             : // VLAN NH definition
    1478             : /////////////////////////////////////////////////////////////////////////////
    1479             : class VlanNHKey : public NextHopKey {
    1480             : public:
    1481           0 :     VlanNHKey(const boost::uuids::uuid &vm_port_uuid, uint16_t vlan_tag) :
    1482             :         NextHopKey(NextHop::VLAN, false),
    1483           0 :         intf_key_(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, vm_port_uuid,
    1484           0 :                                      "")),
    1485           0 :         vlan_tag_(vlan_tag) {
    1486           0 :     }
    1487           0 :     VlanNHKey(InterfaceKey *key, uint16_t vlan_tag) :
    1488           0 :         NextHopKey(NextHop::VLAN, false), intf_key_(key), vlan_tag_(vlan_tag) {
    1489           0 :     }
    1490             : 
    1491           0 :     virtual ~VlanNHKey() {}
    1492             :     virtual NextHop *AllocEntry() const;
    1493           0 :     virtual NextHopKey *Clone() const {
    1494           0 :         return new VlanNHKey(intf_key_->Clone(), vlan_tag_);
    1495             :     }
    1496           0 :     virtual bool NextHopKeyIsLess(const NextHopKey &rhs) const {
    1497           0 :         const VlanNHKey &key = static_cast<const VlanNHKey &>(rhs);
    1498           0 :         if (intf_key_->IsEqual(*key.intf_key_.get()) == false) {
    1499           0 :             return intf_key_->IsLess(*key.intf_key_.get());
    1500             :         }
    1501             : 
    1502           0 :         return vlan_tag_ < key.vlan_tag_;
    1503             :     }
    1504           0 :     const boost::uuids::uuid& GetUuid() const {return intf_key_->uuid_;}
    1505             :     const std::string& name() const { return intf_key_->name_;}
    1506           0 :     const uint16_t vlan_tag() const { return vlan_tag_; }
    1507             : private:
    1508             :     friend class VlanNH;
    1509             :     boost::scoped_ptr<InterfaceKey> intf_key_;
    1510             :     uint16_t vlan_tag_;
    1511             :     DISALLOW_COPY_AND_ASSIGN(VlanNHKey);
    1512             : };
    1513             : 
    1514             : class VlanNHData : public NextHopData {
    1515             : public:
    1516           0 :     VlanNHData(const string vrf_name, const MacAddress &smac,
    1517           0 :                const MacAddress &dmac):
    1518           0 :         NextHopData(), smac_(smac), dmac_(dmac), vrf_key_(vrf_name) {}
    1519           0 :     virtual ~VlanNHData() { }
    1520             : private:
    1521             :     friend class VlanNH;
    1522             :     MacAddress smac_;
    1523             :     MacAddress dmac_;
    1524             :     VrfKey vrf_key_;
    1525             :     DISALLOW_COPY_AND_ASSIGN(VlanNHData);
    1526             : };
    1527             : 
    1528             : class VlanNH : public NextHop {
    1529             : public:
    1530           0 :     VlanNH(Interface *intf, uint32_t vlan_tag):
    1531           0 :         NextHop(VLAN, true, false), interface_(intf), vlan_tag_(vlan_tag),
    1532           0 :         smac_(), dmac_(), vrf_(NULL, this) { };
    1533           0 :     virtual ~VlanNH() { };
    1534             : 
    1535             :     bool NextHopIsLess(const DBEntry &rhs) const;
    1536             :     virtual void SetKey(const DBRequestKey *key);
    1537             :     virtual KeyPtr GetDBRequestKey() const;
    1538           0 :     virtual void Delete(const DBRequest *req) {};
    1539             :     virtual bool ChangeEntry(const DBRequest *req);
    1540             :     virtual void SendObjectLog(const NextHopTable *table,
    1541             :                                AgentLogEvent::type event) const;
    1542             :     virtual bool CanAdd() const;
    1543             : 
    1544           0 :     const Interface *GetInterface() const {return interface_.get();};
    1545           0 :     uint16_t GetVlanTag() const {return vlan_tag_;};
    1546             :     const boost::uuids::uuid &GetIfUuid() const;
    1547           0 :     const VrfEntry *GetVrf() const {return vrf_.get();};
    1548          23 :     const MacAddress &GetSMac() const {return smac_;};
    1549           0 :     const MacAddress &GetDMac() const {return dmac_;};
    1550             :     static VlanNH *Find(const boost::uuids::uuid &intf_uuid, uint16_t vlan_tag);
    1551             : 
    1552             :     static void Create(const boost::uuids::uuid &intf_uuid, uint16_t vlan_tag,
    1553             :                           const std::string &vrf_name, const MacAddress &smac,
    1554             :                           const MacAddress &dmac);
    1555             :     static void Delete(const boost::uuids::uuid &intf_uuid, uint16_t vlan_tag);
    1556             :     static void CreateReq(const boost::uuids::uuid &intf_uuid, uint16_t vlan_tag,
    1557             :                           const std::string &vrf_name, const MacAddress &smac,
    1558             :                           const MacAddress &dmac);
    1559             :     static void DeleteReq(const boost::uuids::uuid &intf_uuid, uint16_t vlan_tag);
    1560             : 
    1561           0 :     virtual bool MatchEgressData(const NextHop *nh) const {
    1562           0 :         const VlanNH *vlan_nh = dynamic_cast<const VlanNH *>(nh);
    1563           0 :         if (vlan_nh && interface_ == vlan_nh->interface_) {
    1564           0 :             return true;
    1565             :         }
    1566           0 :         return false;
    1567             :     }
    1568           0 :     virtual bool NeedMplsLabel() { return true; }
    1569             : 
    1570             : private:
    1571             :     InterfaceRef interface_;
    1572             :     uint16_t vlan_tag_;
    1573             :     MacAddress smac_;
    1574             :     MacAddress dmac_;
    1575             :     VrfEntryRef vrf_;
    1576             :     DISALLOW_COPY_AND_ASSIGN(VlanNH);
    1577             : };
    1578             : 
    1579             : /////////////////////////////////////////////////////////////////////////////
    1580             : // Component NH definition
    1581             : /////////////////////////////////////////////////////////////////////////////
    1582             : //TODO Shift this to class CompositeNH
    1583             : struct Composite {
    1584             :     enum Type {
    1585             :         INVALID,
    1586             :         FABRIC,
    1587             :         L3FABRIC,
    1588             :         L2COMP,
    1589             :         L3COMP,
    1590             :         MULTIPROTO,
    1591             :         ECMP,
    1592             :         L2INTERFACE,
    1593             :         L3INTERFACE,
    1594             :         LOCAL_ECMP,
    1595             :         EVPN,
    1596             :         TOR,
    1597             :         LU_ECMP // label unicast ecmp
    1598             :     };
    1599             : };
    1600             : //TODO remove defines
    1601             : #define COMPOSITETYPE Composite::Type
    1602             : 
    1603             : class ComponentNH {
    1604             : public:
    1605        7515 :     ComponentNH(uint32_t label, const NextHop *nh):
    1606        7515 :         label_(label), nh_(nh) {}
    1607             :     ComponentNH():label_(0), nh_(NULL) {}
    1608             : 
    1609             :     ComponentNH(uint32_t label, NextHop *nh): label_(label), nh_(nh) {
    1610             :     }
    1611             : 
    1612        6414 :     bool operator == (const ComponentNH &rhs) const {
    1613        6414 :         if (label_ == rhs.label_ && nh_.get() == rhs.nh_.get()) {
    1614        6414 :             return true;
    1615             :         }
    1616             : 
    1617           0 :         return false;
    1618             :     }
    1619             : 
    1620             :     std::string ToString() {
    1621             :         return nh_->ToString();
    1622             :     }
    1623             : 
    1624       19261 :     const NextHop* nh() const {
    1625       19261 :         return nh_.get();
    1626             :     }
    1627             : 
    1628       15104 :     uint32_t label() const {
    1629       15104 :         return label_;
    1630             :     }
    1631             : private:
    1632             :     uint32_t label_;
    1633             :     NextHopConstRef nh_;
    1634             :     DISALLOW_COPY_AND_ASSIGN(ComponentNH);
    1635             : };
    1636             : 
    1637             : typedef boost::shared_ptr<const ComponentNH> ComponentNHPtr;
    1638             : typedef std::vector<ComponentNHPtr> ComponentNHList;
    1639             : 
    1640             : class ComponentNHKey;
    1641             : typedef boost::shared_ptr<const ComponentNHKey> ComponentNHKeyPtr;
    1642             : typedef std::vector<ComponentNHKeyPtr> ComponentNHKeyList;
    1643             : 
    1644             : class ComponentNHKey {
    1645             : public:
    1646        1963 :     ComponentNHKey(int label, std::unique_ptr<const NextHopKey> key) :
    1647        1963 :         label_(label), nh_key_(std::move(key)) { }
    1648             :     ComponentNHKey(int label, Composite::Type type, bool policy,
    1649             :                    const ComponentNHKeyList &component_nh_list,
    1650             :                    const std::string &vrf_name);
    1651        3162 :     ComponentNHKey(int label, const boost::uuids::uuid &intf_uuid,
    1652        3162 :                    uint8_t flags, const MacAddress &mac):
    1653        3162 :         label_(label),
    1654        3162 :         nh_key_(new InterfaceNHKey(
    1655        6324 :                     new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, intf_uuid, ""),
    1656        6324 :                     false, flags, mac)) {
    1657        3162 :     }
    1658           3 :     ComponentNHKey(int label, uint8_t tag, const boost::uuids::uuid &intf_uuid):
    1659           3 :         label_(label), nh_key_(new VlanNHKey(intf_uuid, tag)) {
    1660           3 :     }
    1661             : 
    1662          18 :     ComponentNHKey(int label, const string &vrf_name, const Ip4Address &sip,
    1663          18 :             const Ip4Address &dip, bool policy, TunnelType::TypeBmap bmap) :
    1664          36 :         label_(label), nh_key_(new TunnelNHKey(vrf_name, sip, dip, policy,
    1665          36 :                                                TunnelType::ComputeType(bmap))) {
    1666          18 :     }
    1667             : 
    1668        9958 :     virtual ~ComponentNHKey() { }
    1669             : 
    1670          32 :     bool operator == (const ComponentNHKey &rhs) const {
    1671          32 :         if (label_ != rhs.label_) {
    1672          24 :             return false;
    1673             :         }
    1674           8 :         return nh_key_->IsEqual(*(rhs.nh_key_.get()));
    1675             :     }
    1676             : 
    1677      282843 :     uint32_t label() const { return label_; }
    1678      285767 :     const NextHopKey* nh_key() const { return nh_key_.get(); }
    1679             : private:
    1680             :     uint32_t label_;
    1681             :     std::unique_ptr<const NextHopKey> nh_key_;
    1682             :     DISALLOW_COPY_AND_ASSIGN(ComponentNHKey);
    1683             : };
    1684             : 
    1685             : class CompositeNHKey : public NextHopKey {
    1686             : public:
    1687        1898 :     CompositeNHKey(COMPOSITETYPE type, bool policy,
    1688             :                    const ComponentNHKeyList &component_nh_key_list,
    1689        1898 :                    const std::string &vrf_name) :
    1690             :         NextHopKey(NextHop::COMPOSITE, policy),
    1691        1898 :         composite_nh_type_(type), component_nh_key_list_(component_nh_key_list),
    1692        1898 :         vrf_key_(vrf_name){
    1693             : 
    1694        1898 :             validate_mcast_src_ = true;
    1695        1898 :     }
    1696             : 
    1697        6943 :     CompositeNHKey(COMPOSITETYPE type, bool validate_mcast_src, bool policy,
    1698             :                    const ComponentNHKeyList &component_nh_key_list,
    1699        6943 :                    const std::string &vrf_name) :
    1700             :         NextHopKey(NextHop::COMPOSITE, policy),
    1701        6943 :         composite_nh_type_(type), validate_mcast_src_(validate_mcast_src),
    1702        6943 :         component_nh_key_list_(component_nh_key_list), vrf_key_(vrf_name){
    1703        6943 :     }
    1704             : 
    1705             :     virtual CompositeNHKey *Clone() const;
    1706             : 
    1707       16734 :     virtual ~CompositeNHKey() {
    1708       16734 :     }
    1709             :     virtual NextHop *AllocEntry() const;
    1710             :     virtual bool NextHopKeyIsLess(const NextHopKey &rhs) const;
    1711             : 
    1712       58462 :     ComponentNHKeyList::const_iterator begin() const {
    1713       58462 :         return component_nh_key_list_.begin();
    1714             :     }
    1715             : 
    1716      212080 :     ComponentNHKeyList::const_iterator end() const {
    1717      212080 :         return component_nh_key_list_.end();
    1718             :     }
    1719             : 
    1720          14 :     const ComponentNHKeyList& component_nh_key_list() const {
    1721          14 :         return component_nh_key_list_;
    1722             :     }
    1723             :     bool Reorder(Agent *agent, uint32_t label, const NextHop *nh);
    1724             :     void CreateTunnelNH(Agent *agent);
    1725             :     void CreateTunnelNHReq(Agent *agent);
    1726             :     void ChangeTunnelType(TunnelType::Type tunnel_type);
    1727         111 :     COMPOSITETYPE composite_nh_type() const {return composite_nh_type_;}
    1728             :     bool validate_mcast_src() const {return validate_mcast_src_;}
    1729             : 
    1730             :     void ReplaceLocalNexthop(const ComponentNHKeyList &new_comp_nh);
    1731             : private:
    1732             :     friend class CompositeNH;
    1733             :     bool ExpandLocalCompositeNH(Agent *agent);
    1734             :     void insert(ComponentNHKeyPtr nh_key);
    1735             :     void erase(ComponentNHKeyPtr nh_key);
    1736             :     bool find(ComponentNHKeyPtr nh_key);
    1737             : 
    1738             :     COMPOSITETYPE composite_nh_type_;
    1739             :     bool validate_mcast_src_;
    1740             :     ComponentNHKeyList component_nh_key_list_;
    1741             :     VrfKey vrf_key_;
    1742             :     DISALLOW_COPY_AND_ASSIGN(CompositeNHKey);
    1743             : };
    1744             : 
    1745             : class CompositeNHData : public NextHopData {
    1746             : public:
    1747         246 :     CompositeNHData() : NextHopData(), pbb_nh_(false),
    1748         123 :         layer2_control_word_(false),
    1749         123 :         component_nh_key_list_(ComponentNHKeyList()) {}
    1750        3189 :     CompositeNHData(bool pbb_nh, bool learning_enabled, bool layer2_control_word) :
    1751        3189 :         NextHopData(learning_enabled, true), pbb_nh_(pbb_nh),
    1752        3189 :         layer2_control_word_(layer2_control_word),
    1753        3189 :         component_nh_key_list_(ComponentNHKeyList()) {}
    1754         474 :     CompositeNHData(const ComponentNHKeyList &component_nh_key_list) :
    1755         474 :         NextHopData(), pbb_nh_(false), layer2_control_word_(false),
    1756         474 :         component_nh_key_list_(component_nh_key_list) {}
    1757             : private:
    1758             :     friend class CompositeNH;
    1759             :     bool pbb_nh_;
    1760             :     bool layer2_control_word_;
    1761             :     ComponentNHKeyList component_nh_key_list_;
    1762             :     DISALLOW_COPY_AND_ASSIGN(CompositeNHData);
    1763             : };
    1764             : 
    1765             : //Composite NH
    1766             : //* Key of composite NH is list of component NH key(mpls label + Nexthop Key)
    1767             : //* In data part we maintain list of component NH(mpls label + Nexthop reference)
    1768             : //* In case of ECMP composite NH ordering of component NH is important, since
    1769             : //  flows would be pointing to one of component NH, and any change in
    1770             : //  composite NH should not disturb flow which have been already setup.
    1771             : //  If one of the component NH gets deleted, then a empty component NH
    1772             : //  would be installed, which would resulting in kernel trapping flow
    1773             : //  which are pointing to that component NH
    1774             : //* In case of multicast composite NH ordering of the component NH is not
    1775             : //  important
    1776             : class CompositeNH : public NextHop {
    1777             : public:
    1778             :     static const uint32_t kInvalidComponentNHIdx = 0xFFFFFFFF;
    1779             :     CompositeNH(COMPOSITETYPE type, bool policy,
    1780             :         const ComponentNHKeyList &component_nh_key_list, VrfEntry *vrf):
    1781             :         NextHop(COMPOSITE, policy), composite_nh_type_(type),
    1782             :         component_nh_key_list_(component_nh_key_list), vrf_(vrf, this),
    1783             :         pbb_nh_(false) {
    1784             :         validate_mcast_src_= true;
    1785             :         comp_ecmp_hash_fields_.AllocateEcmpFields();
    1786             :     }
    1787             : 
    1788       12141 :     CompositeNH(COMPOSITETYPE type, bool validate_mcast_src, bool policy,
    1789       12141 :         const ComponentNHKeyList &component_nh_key_list, VrfEntry *vrf):
    1790       12141 :         NextHop(COMPOSITE, policy), composite_nh_type_(type),
    1791       12141 :         validate_mcast_src_(validate_mcast_src),
    1792       12141 :         component_nh_key_list_(component_nh_key_list), vrf_(vrf, this),
    1793       24282 :         pbb_nh_(false) {
    1794       12141 :         comp_ecmp_hash_fields_.AllocateEcmpFields();
    1795       12141 :     }
    1796             : 
    1797       24282 :     virtual ~CompositeNH() { };
    1798           0 :     virtual std::string ToString() const { return "Composite NH"; };
    1799             :     virtual bool NextHopIsLess(const DBEntry &rhs) const;
    1800             :     virtual void SetKey(const DBRequestKey *key);
    1801             :     virtual bool ChangeEntry(const DBRequest *req);
    1802             :     virtual void Delete(const DBRequest *req);
    1803             :     virtual KeyPtr GetDBRequestKey() const;
    1804             :     virtual bool CanAdd() const;
    1805             : 
    1806             :     virtual void SendObjectLog(const NextHopTable *table,
    1807             :                                AgentLogEvent::type event) const;
    1808        9201 :     ComponentNHList::const_iterator begin() const {
    1809        9201 :         return component_nh_list_.begin();
    1810             :     }
    1811             : 
    1812       25296 :     ComponentNHList::const_iterator end() const {
    1813       25296 :         return component_nh_list_.end();
    1814             :     }
    1815             : 
    1816        1313 :     size_t ComponentNHCount() const {
    1817        1313 :         return component_nh_list_.size();
    1818             :     }
    1819         133 :     uint32_t ActiveComponentNHCount() const {
    1820         133 :         uint32_t idx = 0;
    1821         133 :         uint32_t active_count = 0;
    1822         372 :         while (idx < component_nh_list_.size()) {
    1823         239 :             if (component_nh_list_[idx].get() != NULL) {
    1824         227 :                 active_count++;
    1825             :             }
    1826         239 :             idx++;
    1827             :         }
    1828         133 :         return active_count;
    1829             :     }
    1830             : 
    1831             :     uint32_t PickMember(uint32_t seed, uint32_t affinity_index,
    1832             :                         bool ingress) const;
    1833          91 :     const NextHop* GetNH(uint32_t idx) const {
    1834          91 :         if (idx >= component_nh_list_.size()) {
    1835           0 :             return NULL;
    1836             :         }
    1837          91 :         if (component_nh_list_[idx].get() == NULL) {
    1838           0 :             return NULL;
    1839             :         }
    1840          91 :         return (*component_nh_list_[idx]).nh();
    1841             :     }
    1842             : 
    1843        6754 :     COMPOSITETYPE composite_nh_type() const {
    1844        6754 :        return composite_nh_type_;
    1845             :     }
    1846             : 
    1847        1254 :     void set_validate_mcast_src(bool validate_mcast_src) {
    1848        1254 :        validate_mcast_src_ = validate_mcast_src;
    1849        1254 :     }
    1850             : 
    1851        3842 :     bool validate_mcast_src() const {
    1852        3842 :        return validate_mcast_src_;
    1853             :     }
    1854             : 
    1855             :     bool GetOldNH(const CompositeNHData *data, ComponentNH &);
    1856             : 
    1857         719 :     virtual bool DeleteOnZeroRefCount() const {
    1858         719 :         return true;
    1859             :     }
    1860         719 :     virtual void OnZeroRefCount() {
    1861         719 :         return;
    1862             :     }
    1863             :     ComponentNHKeyList AddComponentNHKey(ComponentNHKeyPtr component_nh_key,
    1864             :                                          bool &comp_nh_policy) const;
    1865             :     ComponentNHKeyList DeleteComponentNHKey(ComponentNHKeyPtr
    1866             :                                             component_nh_key,
    1867             :                                             bool &comp_nh_new_policy) const;
    1868             :     bool UpdateComponentNHKey(uint32_t label, NextHopKey *nh_key,
    1869             :         ComponentNHKeyList &component_nh_key_list, bool &comp_nh_policy) const;
    1870           0 :     const ComponentNHList& component_nh_list() const {
    1871           0 :         return component_nh_list_;
    1872             :     }
    1873        3842 :     const ComponentNHKeyList& component_nh_key_list() const {
    1874        3842 :         return component_nh_key_list_;
    1875             :     }
    1876        8422 :     const VrfEntry* vrf() const {
    1877        8422 :         return vrf_.get();
    1878             :     }
    1879           0 :    uint32_t hash(uint32_t seed, bool ingress) const {
    1880           0 :        size_t size = component_nh_list_.size();
    1881           0 :        if (size == 0) {
    1882           0 :            return kInvalidComponentNHIdx;
    1883             :        }
    1884           0 :        uint32_t idx = seed % size;
    1885           0 :        while (component_nh_list_[idx].get() == NULL ||
    1886           0 :               component_nh_list_[idx]->nh() == NULL ||
    1887           0 :               component_nh_list_[idx]->nh()->IsActive() == false ||
    1888           0 :               (ingress == false &&
    1889           0 :                component_nh_list_[idx]->nh()->GetType() == NextHop::TUNNEL)) {
    1890           0 :            idx = (idx + 1) % size;
    1891           0 :            if (idx == seed % size) {
    1892           0 :                idx = kInvalidComponentNHIdx;
    1893           0 :                break;
    1894             :            }
    1895             :        }
    1896           0 :        return idx;
    1897             :    }
    1898             :    bool HasVmInterface(const VmInterface *vmi) const;
    1899             :    bool GetIndex(ComponentNH &nh, uint32_t &idx) const;
    1900          72 :    const ComponentNH* Get(uint32_t idx) const {
    1901          72 :        return component_nh_list_[idx].get();
    1902             :    }
    1903             :    CompositeNH* ChangeTunnelType(Agent *agent, TunnelType::Type type) const;
    1904             :    const NextHop *GetLocalNextHop() const;
    1905             : 
    1906           0 :    virtual bool MatchEgressData(const NextHop *nh) const {
    1907           0 :        return false;
    1908             :    }
    1909        3312 :    virtual bool NeedMplsLabel() { return false; }
    1910         928 :    uint8_t EcmpHashFieldInUse() const {
    1911         928 :         return comp_ecmp_hash_fields_.HashFieldsToUse();
    1912             :    }
    1913        3842 :    EcmpHashFields& CompEcmpHashFields() { return comp_ecmp_hash_fields_; }
    1914             :    void UpdateEcmpHashFieldsUponRouteDelete(Agent *agent, const string &vrf_name);
    1915        2052 :    bool pbb_nh() const {
    1916        2052 :        return pbb_nh_;
    1917             :    }
    1918             : 
    1919         798 :    bool layer2_control_word() const {
    1920         798 :        return layer2_control_word_;
    1921             :    }
    1922             : 
    1923             :    const Interface *GetFirstLocalEcmpMemberInterface() const;
    1924             : 
    1925             : private:
    1926             :     void CreateComponentNH(Agent *agent, TunnelType::Type type) const;
    1927             :     void ChangeComponentNHKeyTunnelType(ComponentNHKeyList &component_nh_list,
    1928             :                                         TunnelType::Type type) const;
    1929             :     COMPOSITETYPE composite_nh_type_;
    1930             :     // For relaxing source check in vrouter for mcast data packets
    1931             :     // in R5.1 where support is for source outside contrail for <*,G>.
    1932             :     bool validate_mcast_src_;
    1933             :     ComponentNHKeyList component_nh_key_list_;
    1934             :     ComponentNHList component_nh_list_;
    1935             :     VrfEntryRef vrf_;
    1936             :     EcmpHashFields comp_ecmp_hash_fields_;
    1937             :     bool pbb_nh_;
    1938             :     bool layer2_control_word_;
    1939             :     DISALLOW_COPY_AND_ASSIGN(CompositeNH);
    1940             : };
    1941             : 
    1942             : /////////////////////////////////////////////////////////////////////////////
    1943             : // NextHop DBTable definition
    1944             : /////////////////////////////////////////////////////////////////////////////
    1945             : class NextHopTable : public AgentDBTable {
    1946             : public:
    1947             :     static const uint32_t kRpfDisableIndex = 0;
    1948             :     static const uint32_t kRpfDiscardIndex = 2;
    1949             : 
    1950             :     NextHopTable(DB *db, const std::string &name);
    1951             :     virtual ~NextHopTable();
    1952             : 
    1953             :     virtual std::unique_ptr<DBEntry> AllocEntry(const DBRequestKey *k) const;
    1954       26713 :     virtual size_t Hash(const DBEntry *entry) const {return 0;};
    1955       33789 :     virtual size_t Hash(const DBRequestKey *key) const {return 0;};
    1956             :     virtual AgentSandeshPtr GetAgentSandesh(const AgentSandeshArguments *args,
    1957             :                                             const std::string &context);
    1958             : 
    1959             :     virtual DBEntry *Add(const DBRequest *req);
    1960             :     virtual bool OnChange(DBEntry *entry, const DBRequest *req);
    1961             :     virtual bool Resync(DBEntry *entry, const DBRequest *req);
    1962             :     virtual bool Delete(DBEntry *entry, const DBRequest *req);
    1963             : 
    1964             :     virtual void OnZeroRefcount(AgentDBEntry *e);
    1965             :     void Process(DBRequest &req);
    1966             :     Interface *FindInterface(const InterfaceKey &key) const;
    1967             :     VrfEntry *FindVrfEntry(const VrfKey &key) const;
    1968             :     static DBTableBase *CreateTable(DB *db, const std::string &name);
    1969        8376 :     static NextHopTable *GetInstance() {return nexthop_table_;};
    1970             : 
    1971           4 :     void set_discard_nh(NextHop *nh) { discard_nh_ = nh; }
    1972         996 :     NextHop *discard_nh() const {return discard_nh_;}
    1973             : 
    1974           2 :     void set_l2_receive_nh(NextHop *nh) { l2_receive_nh_ = nh; }
    1975         344 :     NextHop *l2_receive_nh() const {return l2_receive_nh_;}
    1976             :     // NextHop index managing routines
    1977        1690 :     void FreeInterfaceId(size_t index) { index_table_.Remove(index); }
    1978             :     NextHop *FindNextHop(size_t index);
    1979             :     uint32_t ReserveIndex();
    1980             :     void CheckVrNexthopLimit();
    1981          15 :     uint32_t NhIndexCount() { return index_table_.InUseIndexCount(); }
    1982             :     void AddWithoutAlloc(DBEntry *entry);
    1983             :     void RemoveWithoutDelete(DBEntry *entry);
    1984             : private:
    1985             :     NextHop *AllocWithKey(const DBRequestKey *k) const;
    1986             :     virtual std::unique_ptr<DBEntry> GetEntry(const DBRequestKey *key) const;
    1987             : 
    1988             :     NextHop *discard_nh_;
    1989             :     NextHop *l2_receive_nh_;
    1990             :     IndexVector<NextHop *> index_table_;
    1991             :     static NextHopTable *nexthop_table_;
    1992             :     DISALLOW_COPY_AND_ASSIGN(NextHopTable);
    1993             : };
    1994             : #endif // vnsw_agent_nexthop_hpp

Generated by: LCOV version 1.14