Line data Source code
1 : /* 2 : * Copyright (c) 2017 Juniper Networks, Inc. All rights reserved. 3 : * Copyright Contributors to the OpenSDN project 4 : */ 5 : 6 : #ifndef SRC_VNSW_AGENT_MAC_LEARNING_MAC_LEARNING_H_ 7 : #define SRC_VNSW_AGENT_MAC_LEARNING_MAC_LEARNING_H_ 8 : 9 : #include <mutex> 10 : 11 : #include "cmn/agent.h" 12 : #include "mac_learning_key.h" 13 : #include "mac_learning_base.h" 14 : #include "mac_learning_event.h" 15 : #include "pkt/flow_token.h" 16 : class MacEntryResp; 17 : /* 18 : * High level mac learning modules 19 : * 20 : * MacLearningProto: 21 : * Processes the packet trapped for MAC learning, based on the hash 22 : * of the VRF and MAC particular MAC Learning parition would be chosen 23 : * for further processing 24 : * 25 : * MacLearningPartition: 26 : * A logical context for processing MAC learning requests in parallel 27 : * This modules learns the MAC entry and 28 : * 1> Enqueues a request for route add 29 : * 2> Enqueues a request to MacLearningMgmt for dependency tracking 30 : * 3> Enqueues a request to MacAgingPartiton for aging 31 : * 32 : * MacLearningMgmt: 33 : * This modules builds a dependency tracking for a MAC entry. 34 : * MAC entry would be dependent on interface, VRF and 35 : * a route(in case of PBB tunnel learnt MAC). So given a DB object 36 : * it would have a list of all the MAC learnt on that object so that 37 : * any change can result in resync of MAC entry. 38 : * 39 : * MacLearningDBClient: 40 : * Listens for change on DB object and enqueues a request to MacLearningMgmt 41 : * for revaluation of MAC entry depenedent on this DB object. 42 : * Current DB tables of intereset inclue: 43 : * 1> Interface (For local learnt mac address) 44 : * 2> Route (For mac learnt over PBB) 45 : * 3> VRF 46 : * 47 : * MacAgingPatition: 48 : * For each MacLearningPartition there will be MacAgingPartition, which 49 : * maintains a per VRF list of MAC entries, upon timer expiry based on 50 : * aging timeout configured on VRF and no. of entries in VRF no. of entries 51 : * would be visited for stats and aged if no activity is seen on the entry. 52 : * 53 : * ++++++++++++++++++++ 54 : * + Mac Aging X + 55 : * ++++++++++++++++++++ 56 : * | 57 : * | 58 : * | 59 : * ++++++++++++++++++++++++ 60 : * -->+ MacLearningPartitionX+--| 61 : * | ++++++++++++++++++++++++ | 62 : * +++++++++++++++ | | N:1 +++++++++++++++++++ 63 : * +Packet Proto +-->| |<--->+ MacLearningMgmt + 64 : * +++++++++++++++ | | +++++++++++++++++++ 65 : * | ++++++++++++++++++++++++ | ^ 66 : * -->+ MacLearningPartitionY+--| | 67 : * ++++++++++++++++++++++++ | 68 : * | ++++++++++++++++ 69 : * |1:1 + MacLearning + 70 : * | + DB Client + 71 : * ++++++++++++++++++++ ++++++++++++++++ 72 : * + Mac Aging Y + 73 : * ++++++++++++++++++++ 74 : */ 75 : 76 : class MacLearningPartition; 77 : class MacAgingTable; 78 : class MacAgingPartition; 79 : 80 : class MacPbbLearningEntry : public MacLearningEntry { 81 : public: 82 : typedef std::vector<TokenPtr> TokenList; 83 : MacPbbLearningEntry(MacLearningPartition *table, uint32_t vrf_id, 84 : const MacAddress &mac, uint32_t index); 85 0 : virtual ~MacPbbLearningEntry() {} 86 : virtual bool Add() = 0; 87 : virtual void Delete(); 88 : virtual void Resync(); 89 : virtual void AddWithToken(); 90 : 91 : MacLearningPartition* mac_learning_table() const { 92 : return mac_learning_table_; 93 : } 94 : 95 0 : uint32_t index() const { 96 0 : return index_; 97 : } 98 : 99 0 : const MacAddress& mac() const { 100 0 : return key_.mac_; 101 : } 102 : 103 0 : uint32_t vrf_id() { 104 0 : return key_.vrf_id_; 105 : } 106 : 107 0 : const MacLearningKey& key() const { 108 0 : return key_; 109 : } 110 : 111 0 : void AddToken(TokenPtr ptr) { 112 0 : std::scoped_lock lock(mutex_); 113 0 : list_.push_back(ptr); 114 0 : } 115 : 116 0 : void ReleaseToken() { 117 0 : std::scoped_lock lock(mutex_); 118 0 : list_.clear(); 119 0 : } 120 : 121 0 : void CopyToken(MacLearningEntry *entry) { 122 : MacPbbLearningEntry *entry1 = 123 0 : dynamic_cast<MacPbbLearningEntry *>(entry); 124 0 : std::scoped_lock lock(mutex_); 125 0 : std::scoped_lock lock2(entry1->mutex_); 126 0 : list_ = entry1->list_; 127 0 : entry1->list_.clear(); 128 0 : } 129 : 130 0 : bool HasTokens() { 131 0 : std::scoped_lock lock(mutex_); 132 0 : return list_.size(); 133 0 : } 134 : void EnqueueToTable(MacLearningEntryRequestPtr req); 135 : 136 : protected: 137 : MacLearningPartition *mac_learning_table_; 138 : MacLearningKey key_; 139 : uint32_t index_; 140 : uint32_t ethernet_tag_; 141 : TokenList list_; 142 : std::mutex mutex_; 143 : private: 144 : DISALLOW_COPY_AND_ASSIGN(MacPbbLearningEntry); 145 : }; 146 : //Structure used to hold MAC entry learned 147 : //on local interface 148 : class MacLearningEntryLocal : public MacPbbLearningEntry { 149 : public: 150 : MacLearningEntryLocal(MacLearningPartition *table, uint32_t vrf_id, 151 : const MacAddress &mac, uint32_t index, 152 : InterfaceConstRef intf); 153 0 : virtual ~MacLearningEntryLocal() {} 154 : 155 : bool Add(); 156 : 157 0 : const Interface* intf() { 158 0 : return intf_.get(); 159 : } 160 : 161 : private: 162 : InterfaceConstRef intf_; 163 : DISALLOW_COPY_AND_ASSIGN(MacLearningEntryLocal); 164 : }; 165 : 166 : //Structure used to hold MAC entry learned on 167 : //tunnel packet i.e vxlan scenario for now 168 : class MacLearningEntryRemote : public MacPbbLearningEntry { 169 : public: 170 : MacLearningEntryRemote(MacLearningPartition *table, uint32_t vrf_id, 171 : const MacAddress &mac, uint32_t index, 172 : const IpAddress remote_ip); 173 0 : virtual ~MacLearningEntryRemote() {} 174 : 175 : bool Add(); 176 : 177 : const IpAddress& remote_ip() const { 178 : return remote_ip_; 179 : } 180 : private: 181 : IpAddress remote_ip_; 182 : DISALLOW_COPY_AND_ASSIGN(MacLearningEntryRemote); 183 : }; 184 : 185 : //Structure used to hold MAC entry learned on 186 : //PBB tunnel packet 187 : class MacLearningEntryPBB : public MacPbbLearningEntry { 188 : public: 189 : MacLearningEntryPBB(MacLearningPartition *table, uint32_t vrf_id, 190 : const MacAddress &mac, uint32_t index, 191 : const MacAddress &bmac); 192 0 : virtual ~MacLearningEntryPBB() {} 193 : 194 : bool Add(); 195 : 196 0 : const MacAddress& bmac() const { 197 0 : return bmac_; 198 : } 199 : 200 : private: 201 : const MacAddress bmac_; 202 : DISALLOW_COPY_AND_ASSIGN(MacLearningEntryPBB); 203 : }; 204 : 205 : //Mac learning Parition holds all the mac entries hashed 206 : //based on VRF + MAC, and corresponding to each partition 207 : //there will be a aging partition holding all the MAC entries 208 : //present in this partiton 209 : class MacLearningPartition { 210 : public: 211 : typedef std::pair<MacLearningKey, 212 : MacLearningEntryPtr> MacLearningEntryPair; 213 : typedef std::map<MacLearningKey, 214 : MacLearningEntryPtr, 215 : MacLearningKeyCmp> MacLearningEntryTable; 216 : 217 : MacLearningPartition(Agent *agent, MacLearningProto *proto, 218 : uint32_t id); 219 : virtual ~MacLearningPartition(); 220 : void Add(MacLearningEntryPtr ptr); 221 : void Resync(MacLearningEntryPtr ptr); 222 : void Delete(MacLearningEntryPtr ptr); 223 : void DeleteAll(); 224 : void ReleaseToken(const MacLearningKey &key); 225 : MacLearningEntry* Find(const MacLearningKey &key); 226 : //To be used in test cases only 227 : MacLearningEntryPtr TestGet(const MacLearningKey &key); 228 : bool RequestHandler(MacLearningEntryRequestPtr ptr); 229 : 230 742 : Agent* agent() { 231 742 : return agent_; 232 : } 233 : 234 86 : MacAgingPartition* aging_partition() const { 235 86 : return aging_partition_.get(); 236 : } 237 : 238 6 : uint32_t id() const { 239 6 : return id_; 240 : } 241 : 242 : void Enqueue(MacLearningEntryRequestPtr req); 243 : void EnqueueMgmtReq(MacLearningEntryPtr ptr, bool add); 244 : void MayBeStartRunner(TokenPool *pool); 245 : 246 2 : void SetDeleteQueueDisable(bool disable) { 247 2 : delete_request_queue_.SetQueueDisable(disable); 248 2 : } 249 : 250 : private: 251 : friend class MacLearningSandeshResp; 252 : Agent *agent_; 253 : uint32_t id_; 254 : MacLearningEntryTable mac_learning_table_; 255 : MacLearningRequestQueue add_request_queue_; 256 : MacLearningRequestQueue change_request_queue_; 257 : MacLearningRequestQueue delete_request_queue_; 258 : boost::shared_ptr<MacAgingPartition> aging_partition_; 259 : DISALLOW_COPY_AND_ASSIGN(MacLearningPartition); 260 : }; 261 : 262 : class MacLearningSandeshResp : public Task { 263 : public: 264 : const static uint32_t kMaxResponse = 100; 265 : const static char kDelimiter = '-'; 266 : MacLearningSandeshResp(Agent *agent, MacEntryResp *resp, 267 : std::string resp_ctx, 268 : std::string key, 269 : const MacAddress &mac); 270 : virtual ~MacLearningSandeshResp(); 271 0 : std::string Description() const { return "MacLearningSandeshRespTask"; } 272 : 273 : private: 274 : bool Run(); 275 : bool SetMacKey(string key); 276 : void SendResponse(SandeshResponse *resp); 277 : 278 : const MacLearningPartition* GetPartition(); 279 : std::string GetMacKey(); 280 : 281 : Agent *agent_; 282 : MacEntryResp *resp_; 283 : std::string resp_data_; 284 : uint32_t partition_id_; 285 : uint32_t vrf_id_; 286 : MacAddress mac_; 287 : bool exact_match_; 288 : MacAddress user_given_mac_; 289 : DISALLOW_COPY_AND_ASSIGN(MacLearningSandeshResp); 290 : }; 291 : #endif