OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
vxlan.cc
Go to the documentation of this file.
1 
2 //
3 // vxlan.cc
4 // vnsw/agent
5 //
6 
7 #include <cmn/agent_cmn.h>
9 #include <oper/vrf.h>
10 #include <oper/vn.h>
11 #include <oper/nexthop.h>
12 #include <oper/vxlan.h>
13 #include <oper/mirror_table.h>
14 #include <oper/agent_sandesh.h>
15 #include <oper/mpls.h>
16 
17 using namespace std;
18 
20  if (vxlan_id_ == VxLanTable::kInvalidvxlan_id) {
21  return;
22  }
23 }
24 
26  VxLanIdKey *key = new VxLanIdKey(vxlan_id_);
27  return DBEntryBase::KeyPtr(key);
28 }
29 
30 void VxLanId::SetKey(const DBRequestKey *k) {
31  const VxLanIdKey *key = static_cast<const VxLanIdKey *>(k);
32  vxlan_id_ = key->vxlan_id();
33 }
34 
36  Register();
37 }
38 
40  interface_listener_id_ = agent()->interface_table()->Register(
41  boost::bind(&VxLanTable::VmInterfaceNotify, this, _1, _2));
42 
43 }
44 
46  agent()->interface_table()->Unregister(interface_listener_id_);
47 }
48 
50  const Interface *intf = static_cast<const Interface *>(e);
51  const VmInterface *vm_itf;
52  bool composite_nh_modified = false;
53  if (intf->type() != Interface::VM_INTERFACE) {
54  return;
55  }
56 
57  vm_itf = static_cast<const VmInterface *>(intf);
58 
59  if (vm_itf->vn() == NULL) {
60  return;
61  }
62 
63  const VnEntry *vn = vm_itf->vn();
64  if (!vn->mirror_destination()) {
65  return;
66  }
67 
68  ComponentNHKeyPtr nh_key(new ComponentNHKey(vm_itf->label(),vm_itf->GetUuid(),
70  vm_itf->vm_mac()));
71  // if the interface deleted remove the entry from map
72  // else add it to composite NH list
73  if (intf->IsDeleted() || ((vm_itf->l2_active() == false) &&
74  (vm_itf->ipv4_active() == false) &&
75  (vm_itf->ipv6_active() == false))) {
76  composite_nh_modified = DeleteCompositeNH(vm_itf->vxlan_id(), nh_key);
77  } else {
78  composite_nh_modified = AddCompositeNH(vm_itf->vxlan_id(), nh_key);
79  // In case an older NH exists for the same interface, which was added based on
80  // a different vmi->label(), we need to delete that before adding the new one,
81  // otherwise there traffic will be duplicated on the output interface, since
82  // both the older and newer NH (policy disabled/enabled) point to the same
83  // output interface
84  if (composite_nh_modified && vm_itf->label_op() != MplsTable::kInvalidLabel) {
85  ComponentNHKeyPtr nh_key_op(
86  new ComponentNHKey(vm_itf->label_op(),vm_itf->GetUuid(),
88  vm_itf->vm_mac()));
89  DeleteCompositeNH(vm_itf->vxlan_id(), nh_key_op);
90  }
91  }
92 
93  if (composite_nh_modified) {
94  Create(vm_itf->vxlan_id(), vm_itf->vrf()->GetName(),
96  vm_itf->learning_enabled(), !vn->vxlan_routing_vn());
97  }
98  return;
99 }
100 
101 bool VxLanTable::DeleteCompositeNH(uint32_t vxlan_id,
102  ComponentNHKeyPtr nh_key) {
103  VxlanCompositeNHList::iterator it = vxlan_composite_nh_map_.find(vxlan_id);
104  if (it != vxlan_composite_nh_map_.end()) {
105  ComponentNHKeyList::iterator list_it = it->second.begin();
106  for (; list_it != it->second.end(); list_it++) {
107  if (*list_it == NULL) {
108  continue;
109  }
110  if (**list_it == *nh_key) {
111  // release the ComponentNHKeyPtr
112  (*list_it).reset();
113  it->second.erase(list_it);
114  return true;
115  }
116  }
117  return false;
118  }
119  return false;
120 }
121 
122 bool VxLanTable::AddCompositeNH(uint32_t vxlan_id, ComponentNHKeyPtr nh_key) {
123  VxlanCompositeNHList::iterator it = vxlan_composite_nh_map_.find(vxlan_id);
124  if (it != vxlan_composite_nh_map_.end()) {
125  ComponentNHKeyList::const_iterator list_it = it->second.begin();
126  for (; list_it != it->second.end(); list_it++) {
127  if (*list_it == NULL) {
128  continue;
129  }
130  if (**list_it == *nh_key) {
131  // already there no modification
132  return false;
133  }
134  }
135  it->second.push_back(nh_key);
136  return true;
137  }
138  ComponentNHKeyList list;
139  list.push_back(nh_key);
140  vxlan_composite_nh_map_.insert(VxlanCompositeNHEntry(vxlan_id, list));
141  return true;
142 }
143 
144 
145 std::unique_ptr<DBEntry> VxLanTable::AllocEntry(const DBRequestKey *k) const {
146  const VxLanIdKey *key = static_cast<const VxLanIdKey *>(k);
147  VxLanId *vxlan_id = new VxLanId(key->vxlan_id());
148  return std::unique_ptr<DBEntry>(static_cast<DBEntry *>(vxlan_id));
149 }
150 
152  agent()->ConcurrencyCheck();
153  DBTablePartition *tpart =
154  static_cast<DBTablePartition *>(GetTablePartition(req.key.get()));
155  Input(tpart, NULL, &req);
156 }
157 
159  VxLanIdKey *key = static_cast<VxLanIdKey *>(req->key.get());
160  VxLanId *vxlan_id = new VxLanId(key->vxlan_id());
161 
162  ChangeHandler(vxlan_id, req);
163  vxlan_id->SendObjectLog(this, AgentLogEvent::ADD);
164  return vxlan_id;
165 }
166 
167 bool VxLanTable::OnChange(DBEntry *entry, const DBRequest *req) {
168  bool ret;
169  VxLanId *vxlan_id = static_cast<VxLanId *>(entry);
170  ret = ChangeHandler(vxlan_id, req);
171  vxlan_id->SendObjectLog(this, AgentLogEvent::CHANGE);
172  return ret;
173 }
174 
175 // No Change expected for vxlan_id vxlan_id
176 bool VxLanTable::ChangeHandler(VxLanId *vxlan_id, const DBRequest *req) {
177  bool ret = false;
178  VxLanIdData *data = static_cast<VxLanIdData *>(req->data.get());
179 
181  NextHop *nh;
182  // if VN is enabled with mirror destination point the vxlan nh
183  // to CompositeNH
184  if (data->mirror_destination()) {
185  VxlanCompositeNHList::iterator it =
186  vxlan_composite_nh_map_.find(vxlan_id->vxlan_id());
187  if (it != vxlan_composite_nh_map_.end()) {
188  CompositeNHKey nh_key(Composite::L2INTERFACE, false, it->second,
189  data->vrf_name());
190  nh = static_cast<NextHop *>
192  } else {
193  // vm interface notification arraived at so create dummy CompositeNH
194  ComponentNHKeyPtr nh_ptr;
195  nh_ptr.reset();
196  ComponentNHKeyList list;
197  list.push_back(nh_ptr);
198  CompositeNHKey nh_key(Composite::L2INTERFACE, false, list,
199  data->vrf_name());
200  nh = static_cast<NextHop *>
201  (agent()->nexthop_table()->FindActiveEntry(&nh_key));
202  }
203  } else {
204  VrfNHKey nh_key(data->vrf_name(), false, data->bridge());
205  nh = static_cast<NextHop *>
207  }
208 
209  if (vxlan_id->nh_ != nh) {
210  vxlan_id->nh_ = nh;
211  ret = true;
212  }
213 
214  return ret;
215 }
216 
217 bool VxLanTable::Delete(DBEntry *entry, const DBRequest *req) {
218  VxLanId *vxlan_id = static_cast<VxLanId *>(entry);
219  vxlan_id->SendObjectLog(this, AgentLogEvent::DEL);
220  return true;
221 }
222 
223 VxLanId *VxLanTable::Find(uint32_t vxlan_id) {
224  VxLanIdKey key(vxlan_id);
225  return static_cast<VxLanId *>(FindActiveEntry(&key));
226 }
227 
228 VxLanId *VxLanTable::FindNoLock(uint32_t vxlan_id) {
229  VxLanIdKey key(vxlan_id);
230  return static_cast<VxLanId *>(FindActiveEntryNoLock(&key));
231 }
232 
234  const VxLanId *vxlan_id = static_cast<const VxLanId *>(e);
235  Delete(vxlan_id->vxlan_id());
236 }
237 
238 // Follows semantics defined for the ConfigTree in vxlan.h
239 // Return values:
240 // - vxlan dbentry if "vn" is "active"
241 // - NULL if "vn" is "inactive"
242 VxLanId *VxLanTable::Locate(uint32_t vxlan_id, const boost::uuids::uuid &vn,
243  const std::string &vrf, bool flood_unknown_unicast,
244  bool mirror_destination, bool learning_enabled,
245  bool bridge) {
246  // Treat a request without VRF as delete of config entry
247  if (vrf.empty()) {
248  Delete(vxlan_id, vn);
249  return NULL;
250  }
251 
252  // If there are no config-entries persent for the vxlan,
253  // - Add the config-entry and make it active
254  // - Create VxLan entry
255  ConfigTree::iterator it = config_tree_.lower_bound(
256  ConfigKey(vxlan_id, boost::uuids::nil_uuid()));
257 
258  if (it == config_tree_.end() || it->first.vxlan_id_ != vxlan_id) {
259  config_tree_.insert(make_pair(ConfigKey(vxlan_id, vn),
260  ConfigEntry(vrf, flood_unknown_unicast,
261  true, mirror_destination,
262  bridge)));
263  Create(vxlan_id, vrf, flood_unknown_unicast, mirror_destination,
264  learning_enabled, bridge);
265  return Find(vxlan_id);
266  }
267 
268  // Handle change to existing config-entry
269  it = config_tree_.find(ConfigKey(vxlan_id, vn));
270  if (it != config_tree_.end()) {
271  it->second.vrf_ = vrf;
272  it->second.flood_unknown_unicast_ = flood_unknown_unicast;
273  it->second.mirror_destination_ = mirror_destination;
274  it->second.learning_enabled_ = learning_enabled;
275  it->second.bridge_ = bridge;
276 
277  // If entry is active, update vxlan dbentry with new information
278  if (it->second.active_) {
279  Create(vxlan_id, vrf, flood_unknown_unicast, mirror_destination,
280  learning_enabled, bridge);
281  return Find(vxlan_id);
282  }
283  // If entry inactive, return NULL
284  return NULL;
285  }
286 
287  // Entry not present, add it to config-tree
288  config_tree_.insert(make_pair(ConfigKey(vxlan_id, vn),
289  ConfigEntry(vrf, flood_unknown_unicast,
290  false, mirror_destination,
291  bridge)));
292  // Return NULL since the VN is active
293  return NULL;
294 }
295 
296 VxLanId *VxLanTable::Delete(uint32_t vxlan_id, const boost::uuids::uuid &vn) {
297  ConfigTree::iterator it = config_tree_.find(ConfigKey(vxlan_id, vn));
298  // Entry not found
299  if (it == config_tree_.end()) {
300  return NULL;
301  }
302 
303  // If the entry is active and getting deleted, make new "active" entry
304  bool active = it->second.active_;
305  config_tree_.erase(it);
306  if (active == false)
307  return NULL;
308 
309  // Make first entry as active
310  it = config_tree_.lower_bound(
311  ConfigKey(vxlan_id, boost::uuids::nil_uuid()));
312 
313  if (it == config_tree_.end() || it->first.vxlan_id_ != vxlan_id)
314  return NULL;
315 
316  it->second.active_ = true;
317  Create(vxlan_id, it->second.vrf_, it->second.flood_unknown_unicast_,
318  it->second.mirror_destination_, it->second.learning_enabled_,
319  it->second.bridge_);
320  agent()->vn_table()->ResyncReq(it->first.vn_);
321  return NULL;
322 }
323 
324 DBTableBase *VxLanTable::CreateTable(DB *db, const std::string &name) {
325  VxLanTable *table = new VxLanTable(db, name);
326  table->Init();
327  return table;
328 }
329 
330 void VxLanTable::Create(uint32_t vxlan_id, const string &vrf_name,
331  bool flood_unknown_unicast, bool mirror_destination,
332  bool learning_enable, bool bridge) {
334  if (mirror_destination) {
335  VxlanCompositeNHList::iterator it =
336  vxlan_composite_nh_map_.find(vxlan_id);
337  if (it != vxlan_composite_nh_map_.end()) {
338  nh_req.key.reset(new CompositeNHKey(Composite::L2INTERFACE, false,
339  it->second, vrf_name));
340  } else {
341  ComponentNHKeyPtr nh_ptr;
342  nh_ptr.reset();
343  ComponentNHKeyList list;
344  list.push_back(nh_ptr);
345  nh_req.key.reset(new CompositeNHKey(Composite::L2INTERFACE, false,
346  list, vrf_name));
347  }
348  nh_req.data.reset(new CompositeNHData());
349  } else {
350  nh_req.key.reset(new VrfNHKey(vrf_name, false, bridge));
351  nh_req.data.reset(new VrfNHData(flood_unknown_unicast, learning_enable,
352  false));
353  }
355  req.key.reset(new VxLanIdKey(vxlan_id));
356  req.data.reset(new VxLanIdData(vrf_name, nh_req, mirror_destination,
357  bridge));
358  Process(req);
359  return;
360 }
361 
362 void VxLanTable::Delete(uint32_t vxlan_id) {
364  req.key.reset(new VxLanIdKey(vxlan_id));
365  req.data.reset(NULL);
366  VxlanCompositeNHList::iterator it = vxlan_composite_nh_map_.find(vxlan_id);
367  if (it != vxlan_composite_nh_map_.end()) {
368  vxlan_composite_nh_map_.erase(it);
369  }
370  Process(req);
371 }
372 
373 bool VxLanId::DBEntrySandesh(Sandesh *sresp, std::string &name) const {
374  VxLanResp *resp = static_cast<VxLanResp *>(sresp);
375 
376  VxLanSandeshData data;
377  data.set_vxlan_id(vxlan_id_);
378  nh_->SetNHSandeshData(data.nh);
379  std::vector<VxLanSandeshData> &list =
380  const_cast<std::vector<VxLanSandeshData>&>(resp->get_vxlan_list());
381  list.push_back(data);
382 
383  return true;
384 }
385 
387  AgentLogEvent::type event) const {
388  VxLanObjectLogInfo info;
389  string str, nh_type;
390 
391  info.set_vxlan_id((int)vxlan_id_);
392  switch (event) {
393  case AgentLogEvent::ADD:
394  str.assign("Addition ");
395  break;
396  case AgentLogEvent::DEL:
397  str.assign("Deletion ");
398  info.set_event(str);
399  OPER_TRACE_ENTRY(VxLan, table, info);
400  return;
401  case AgentLogEvent::CHANGE:
402  str.assign("Modification ");
403  break;
404  default:
405  str.assign("Unknown");
406  break;
407  }
408  const NextHop *nh = nexthop();
409  if (nh != NULL) {
410  //const VrfNH *vrf_nh;
411  switch(nh->GetType()) {
412  case NextHop::VRF: {
413  nh_type.assign("VRF");
414  const VrfNH *vrf_nh = static_cast<const VrfNH *>(nh);
415  info.set_vrf_name(vrf_nh->GetVrf()->GetName());
416  break;
417  }
418  default:
419  nh_type.assign("unknown");
420  break;
421  }
422  }
423  info.set_nh_type(nh_type);
424  OPER_TRACE_ENTRY(VxLan, table, info);
425 }
426 
427 void VxLanReq::HandleRequest() const {
428  AgentSandeshPtr sand(new AgentVxLanSandesh(context(), get_vxlan_id()));
429  sand->DoSandesh(sand);
430 }
431 
433  const std::string &context) {
434  return AgentSandeshPtr(new AgentVxLanSandesh(context,
435  args->GetString("vxlan_id")));
436 }
437 
439 // Sandesh routines to dump config tree
441 class VxLanConfigSandeshTask : public Task {
442  public:
443  VxLanConfigSandeshTask(Agent *agent, uint32_t vxlan_id, const string &vn,
444  const string &active, const string &context) :
445  Task(agent->task_scheduler()->GetTaskId(AGENT_SANDESH_TASKNAME), 0),
446  agent_(agent), vxlan_id_(vxlan_id), vn_(vn), active_(active),
447  context_(context) { }
449  virtual bool Run();
450  std::string Description() const { return "VxLanConfigSandeshTask"; }
451 
452  private:
454  uint32_t vxlan_id_;
455  string vn_;
456  string active_;
457  string context_;
459 };
460 
462  VxLanConfigResp *resp = new VxLanConfigResp();
463  vector<VxLanConfigEntry> &list =
464  const_cast<vector<VxLanConfigEntry>&>(resp->get_vxlan_config_entries());
465 
466  boost::uuids::uuid u = boost::uuids::nil_uuid();
467  if (vn_.empty() == false) {
468  u = StringToUuid(vn_);
469  }
470 
471  const VxLanTable::ConfigTree &tree = agent_->vxlan_table()->config_tree();
472  VxLanTable::ConfigTree::const_iterator it = tree.begin();
473  while (it != tree.end()) {
474  VxLanConfigEntry entry;
475  if (vxlan_id_ != 0) {
476  if (vxlan_id_ != it->first.vxlan_id_) {
477  it++;
478  continue;
479  }
480  }
481 
482  if (u != boost::uuids::nil_uuid() && u != it->first.vn_) {
483  it++;
484  continue;
485  }
486 
487  if (active_.empty() == false) {
488  if ((active_ == "true" || active_ == "yes" || active_ == "active")
489  && (it->second.active_ != true)) {
490  it++;
491  continue;
492  }
493 
494  if ((active_ == "false" || active_ == "no" || active_ == "inactive")
495  && (it->second.active_ != false)) {
496  it++;
497  continue;
498  }
499  }
500 
501  entry.set_vxlan_id(it->first.vxlan_id_);
502  entry.set_vn_uuid(UuidToString(it->first.vn_));
503  entry.set_vrf(it->second.vrf_);
504  entry.set_flood_unknown_unicast(it->second.flood_unknown_unicast_);
505  entry.set_active(it->second.active_);
506  list.push_back(entry);
507  it++;
508  }
509  resp->set_context(context_);
510  resp->set_more(false);
511  resp->Response();
512  return true;
513 }
514 
515 void VxLanConfigReq::HandleRequest() const {
516  Agent *agent = Agent::GetInstance();
518  new VxLanConfigSandeshTask(agent, get_vxlan_id(), get_vn(),
519  get_active(), context());
520  agent->task_scheduler()->Enqueue(task);
521 }
bool DeleteCompositeNH(uint32_t vxlan_id, ComponentNHKeyPtr nh_key)
Definition: vxlan.cc:101
virtual void OnZeroRefcount(AgentDBEntry *e)
Definition: vxlan.cc:233
int vxlan_id() const
const MacAddress & vm_mac() const
Type type() const
Definition: interface.h:112
void SendObjectLog(const AgentDBTable *table, AgentLogEvent::type event) const
Definition: vxlan.cc:386
static Agent * GetInstance()
Definition: agent.h:436
static boost::uuids::uuid StringToUuid(const std::string &str)
Definition: string_util.h:145
virtual DBEntry * Add(const DBRequest *req)
Definition: vxlan.cc:158
std::string GetString(const std::string &key) const
const boost::uuids::uuid & GetUuid() const
Definition: interface.h:113
const VrfEntry * GetVrf() const
Definition: nexthop.h:1444
NextHopTable * nexthop_table() const
Definition: agent.h:475
void Register()
Definition: vxlan.cc:39
static DBTableBase * CreateTable(DB *db, const std::string &name)
Definition: vxlan.cc:324
bool IsDeleted() const
Definition: db_entry.h:49
bool l2_active() const
Definition: interface.h:122
std::unique_ptr< DBRequestData > data
Definition: db_table.h:49
AgentDBEntry * FindActiveEntry(const DBEntry *key)
Definition: agent_db.cc:110
boost::uuids::uuid uuid
boost::shared_ptr< const ComponentNHKey > ComponentNHKeyPtr
Definition: nexthop.h:1639
VxLanConfigSandeshTask(Agent *agent, uint32_t vxlan_id, const string &vn, const string &active, const string &context)
Definition: vxlan.cc:443
const string & GetName() const
Definition: vrf.h:100
static std::string UuidToString(const boost::uuids::uuid &id)
Definition: string_util.h:138
std::map< ConfigKey, ConfigEntry, ConfigKey > ConfigTree
Definition: vxlan.h:138
Definition: vxlan.h:14
VrfEntry * vrf() const
Definition: interface.h:115
std::unique_ptr< DBRequestKey > KeyPtr
Definition: db_entry.h:25
Type GetType() const
Definition: nexthop.h:405
bool learning_enabled() const
std::vector< ComponentNHKeyPtr > ComponentNHKeyList
Definition: nexthop.h:1641
bool flood_unknown_unicast() const
Definition: vn.h:199
uint32_t vxlan_id() const
Definition: vxlan.h:50
bool DBEntrySandesh(Sandesh *sresp, std::string &name) const
Definition: vxlan.cc:373
virtual KeyPtr GetDBRequestKey() const
Definition: vxlan.cc:25
uint32_t label() const
Definition: interface.h:127
virtual std::unique_ptr< DBEntry > AllocEntry(const DBRequestKey *k) const
Definition: vxlan.cc:145
Definition: db.h:24
void Process(DBRequest &req)
Definition: vxlan.cc:151
void Init()
Definition: db_table.cc:387
static const uint32_t kInvalidvxlan_id
Definition: vxlan.h:141
TaskScheduler * task_scheduler() const
Definition: agent.h:1120
uint32_t vxlan_id_
Definition: vxlan.cc:454
uint8_t type
Definition: load_balance.h:109
bool mirror_destination() const
Definition: vxlan.h:70
Definition: agent.h:358
virtual bool Run()
Code to execute. Returns true if task is completed. Return false to reschedule the task...
Definition: vxlan.cc:461
void Enqueue(Task *task)
Enqueues a task for running. Starts task if all policy rules are met else puts task in waitq...
Definition: task.cc:636
uint32_t label_op() const
bool ipv4_active() const
Definition: interface.h:116
std::string Description() const
Definition: vxlan.cc:450
std::unique_ptr< DBRequestKey > key
Definition: db_table.h:48
bool vxlan_routing_vn() const
Definition: vn.h:255
void Create(uint32_t vxlan_id, const std::string &vrf_name, bool flood_unknown_unicast, bool mirror_destination, bool learning_enabled, bool bridge)
Definition: vxlan.cc:330
VxLanId * Locate(uint32_t vxlan_id, const boost::uuids::uuid &vn, const std::string &vrf, bool flood_unknown_unicast, bool mirror_destination, bool learning_enabled, bool bridge)
Definition: vxlan.cc:242
std::pair< uint32_t, ComponentNHKeyList > VxlanCompositeNHEntry
Definition: vxlan.h:140
#define OPER_TRACE_ENTRY(obj, table,...)
Definition: agent_db.h:234
void VmInterfaceNotify(DBTablePartBase *partition, DBEntryBase *e)
Definition: vxlan.cc:49
class boost::shared_ptr< AgentSandesh > AgentSandeshPtr
Definition: agent_db.h:18
const VnEntry * vn() const
#define DISALLOW_COPY_AND_ASSIGN(_Class)
Definition: util.h:15
DBRequest & nh_req()
Definition: vxlan.h:69
void Initialize()
Definition: vxlan.cc:35
NextHopRef nh_
Definition: vxlan.h:40
Definition: vn.h:151
static const uint32_t kInvalidLabel
Definition: mpls.h:101
virtual bool Delete(DBEntry *entry, const DBRequest *req)
Definition: vxlan.cc:217
bool bridge() const
Definition: vxlan.h:71
uint32_t vxlan_id() const
Definition: vxlan.h:27
bool AddCompositeNH(uint32_t vxlan_id, ComponentNHKeyPtr nh_key)
Definition: vxlan.cc:122
VxLanId * Find(uint32_t vxlan_id)
Definition: vxlan.cc:223
virtual AgentSandeshPtr GetAgentSandesh(const AgentSandeshArguments *args, const std::string &context)
Definition: vxlan.cc:432
void Process(DBRequest &req)
Definition: nexthop.cc:367
void Shutdown()
Definition: vxlan.cc:45
#define AGENT_SANDESH_TASKNAME
Definition: agent.h:301
virtual ~VxLanId()
Definition: vxlan.cc:19
bool ChangeHandler(VxLanId *vxlan_id, const DBRequest *req)
Definition: vxlan.cc:176
virtual void SetKey(const DBRequestKey *key)
Definition: vxlan.cc:30
string & vrf_name()
Definition: vxlan.h:68
Task is a wrapper over tbb::task to support policies.
Definition: task.h:86
const bool mirror_destination() const
Definition: vn.h:205
VxLanId * FindNoLock(uint32_t vxlan_id)
Definition: vxlan.cc:228
bool ipv6_active() const
Definition: interface.h:117
struct task_ task
virtual bool OnChange(DBEntry *entry, const DBRequest *req)
Definition: vxlan.cc:167