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: 389 645 60.3 %
Date: 2026-06-04 02:06:09 Functions: 220 335 65.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14