OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
mpls.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <boost/uuid/uuid_io.hpp>
6 #include <cmn/agent_cmn.h>
7 #include <init/agent_param.h>
10 #include <oper/vrf.h>
11 #include <oper/nexthop.h>
12 #include <oper/mpls.h>
13 #include <oper/mirror_table.h>
14 #include <oper/agent_sandesh.h>
18 
19 using namespace std;
20 
22 
23 /****************************************************************************
24  * MplsLabel routines
25  ***************************************************************************/
26 MplsLabel::MplsLabel(Agent *agent, uint32_t label) :
27  agent_(agent), label_(label), free_label_(false) {
28 }
29 
31  if (free_label_) {
33  MplsTable *table = static_cast<MplsTable *>(get_table());
34  table->FreeMplsLabelIndex(label_);
35  }
37  }
38 }
39 
40 bool MplsLabel::IsLess(const DBEntry &rhs) const {
41  const MplsLabel &mpls = static_cast<const MplsLabel &>(rhs);
42  return label_ < mpls.label_;
43 }
44 
45 std::string MplsLabel::ToString() const {
46  return "MPLS";
47 }
48 
50  MplsLabelKey *key = new MplsLabelKey(label_);
51  return DBEntryBase::KeyPtr(key);
52 }
53 
55  const MplsLabelKey *key = static_cast<const MplsLabelKey *>(k);
56  label_ = key->label();
57 }
58 
59 uint32_t MplsLabel::GetRefCount() const {
61 }
62 
63 void MplsLabel::Add(const DBRequest *req) {
64  free_label_ = true;
65  ChangeInternal(req);
66  SendObjectLog(agent_->mpls_table(), AgentLogEvent::ADD);
67  return;
68 }
69 
70 bool MplsLabel::Change(const DBRequest *req) {
71  const AgentDBTable *table = static_cast<const AgentDBTable *>(get_table());
72  bool ret = ChangeInternal(req);
73  SendObjectLog(table, AgentLogEvent::CHANGE);
74  return ret;
75 }
76 
77 void MplsLabel::Delete(const DBRequest *req) {
78  const AgentDBTable *table = static_cast<const AgentDBTable *>(get_table());
79  SendObjectLog(table, AgentLogEvent::DEL);
80  return;
81 }
82 
84  NextHopTable *nh_table = agent_->nexthop_table();
85  MplsLabelData *data = static_cast<MplsLabelData *>(req->data.get());
86  NextHop *nh =
87  static_cast<NextHop *>(nh_table->FindActiveEntry(data->nh_key()));
88  if (!nh) {
89  // NextHop not found, point mpls label to discard
90  DiscardNH key;
91  nh = static_cast<NextHop *>(nh_table->FindActiveEntry(&key));
92  }
93 
94  return ChangeNH(nh);
95 }
96 
98  if (nh_ == nh)
99  return false;
100 
101  assert(nh);
102  nh_ = nh;
103 
105  CompositeNH *cnh = dynamic_cast<CompositeNH*>(nh);
106  if (cnh && cnh->vrf()) {
107  FmgVrfNhMap::iterator it = fmg_nh_list_.begin();
108  while( it != fmg_nh_list_.end()) {
109  if (it->first != cnh->vrf()->GetName()) {
110  FmgVrfNhMap::iterator temp_it;
111  temp_it = it;
112  it++;
113  fmg_nh_list_.erase(temp_it);
114  } else {
115  it++;
116  }
117  }
118  fmg_nh_list_[cnh->vrf()->GetName()] = nh;
119  }
120  }
121 
123  return true;
124 }
125 
127  MPLS_TRACE(MplsTrace, "Syncing routes for label ", label());
128  for (DependentPathList::iterator iter =
129  mpls_label_.begin(); iter != mpls_label_.end(); iter++) {
130  AgentRoute *rt = iter.operator->();
131  rt->EnqueueRouteResync();
132  }
133 }
134 
136  //MplsTable *table = static_cast<MplsTable *>(get_table());
137  MplsTable *table = static_cast<MplsTable *>(agent_->mpls_table());
138  return table->IsFabricMulticastLabel(label_);
139 }
140 
141 /****************************************************************************
142  * MplsLabel Sandesh routines
143  ***************************************************************************/
144 bool MplsLabel::DBEntrySandesh(Sandesh *sresp, std::string &name) const {
145  MplsResp *resp = static_cast<MplsResp *>(sresp);
146 
147  MplsSandeshData data;
148  data.set_label(label_);
149  nh_->SetNHSandeshData(data.nh);
150  std::vector<MplsSandeshData> &list =
151  const_cast<std::vector<MplsSandeshData>&>(resp->get_mpls_list());
152  list.push_back(data);
153 
154  return true;
155 }
156 
158  AgentLogEvent::type event) const {
159  MplsObjectLogInfo info;
160  string str, type_str, nh_type;
161  info.set_type(type_str);
162  info.set_label((int)label_);
163  switch (event) {
164  case AgentLogEvent::ADD:
165  str.assign("Addition ");
166  break;
167  case AgentLogEvent::DEL:
168  str.assign("Deletion ");
169  info.set_event(str);
170  OPER_TRACE_ENTRY(Mpls, table, info);
171  return;
172  case AgentLogEvent::CHANGE:
173  str.assign("Modification ");
174  break;
175  default:
176  str.assign("Unknown");
177  break;
178  }
179  info.set_event(str);
180  const NextHop *nh = nexthop();
181  const Interface *intf = NULL;
182  /* Mpls is not expected to have any other nexthop apart from Interface
183  or Vlan */
184  if (nh != NULL) {
185  string policy_str("Disabled");
186  const InterfaceNH *if_nh;
187  const VlanNH *vlan_nh;
188 
189  switch(nh->GetType()) {
190  case NextHop::INTERFACE:
191  nh_type.assign("INTERFACE");
192  if_nh = static_cast<const InterfaceNH *>(nh);
193  intf = if_nh->GetInterface();
194  if (if_nh->PolicyEnabled()) {
195  policy_str.assign("Enabled");
196  }
197  info.set_policy(policy_str);
198  break;
199  case NextHop::VLAN:
200  nh_type.assign("VLAN");
201  vlan_nh = static_cast<const VlanNH *>(nh);
202  intf = vlan_nh->GetInterface();
203  info.set_vlan_tag(vlan_nh->GetVlanTag());
204  break;
205  case NextHop::COMPOSITE:
206  nh_type.assign("Composite");
207  break;
208  default:
209  nh_type.assign("unknown");
210  break;
211  }
212  }
213  info.set_nh_type(nh_type);
214  /* Interface Nexthop pointed by Mpls object will always be of type VMPORT */
215  if (intf) {
216  string if_type_str;
217  switch(intf->type()) {
219  if_type_str.assign("VM_INTERFACE");
220  break;
221  default:
222  if_type_str.assign("Invalid");
223  break;
224  }
225  info.set_intf_type(if_type_str);
226  info.set_intf_uuid(UuidToString(intf->GetUuid()));
227  info.set_intf_name(intf->name());
228  }
229  OPER_TRACE_ENTRY(Mpls, table, info);
230 }
231 
232 /****************************************************************************
233  * MplsTable routines
234  ***************************************************************************/
235 MplsTable::MplsTable(DB *db, const std::string &name) :
236  AgentDBTable(db, name) {
237 }
238 
240 }
241 
242 DBTableBase *MplsTable::CreateTable(DB *db, const std::string &name) {
243  MplsTable *table = new MplsTable(db, name);
244  table->Init();
245  return table;
246 };
247 
249  agent()->ConcurrencyCheck();
250  DBTablePartition *tpart =
251  static_cast<DBTablePartition *>(GetTablePartition(req.key.get()));
252  tpart->Process(NULL, &req);
253 }
254 
255 /*
256  * Allocates label from resource manager, currently used for evpn and
257  * ecmp labels.
258  */
260  uint32_t label = ((static_cast<IndexResourceData *>(agent()->resource_manager()->
261  Allocate(key).get()))->index());
262  assert(label != MplsTable::kInvalidLabel);
263  return label;
264 }
265 
266 //Free label from resource manager and delete db entry
267 void MplsTable::FreeLabel(uint32_t label) {
268  FreeLabel(label, std::string());
269 }
270 
271 void MplsTable::FreeLabel(uint32_t label, const std::string &vrf_name) {
272  DBRequest req;
274 
275  MplsLabelKey *key = new MplsLabelKey(label);
276  MplsLabelData *data = new MplsLabelData(NULL);
277  data->set_vrf_name(vrf_name);
278  req.key.reset(key);
279  req.data.reset(data);
280 
281  Process(req);
282 }
283 
284 std::unique_ptr<DBEntry> MplsTable::AllocEntry(const DBRequestKey *k) const {
285  const MplsLabelKey *key = static_cast<const MplsLabelKey *>(k);
286  MplsLabel *mpls = new MplsLabel(agent(), key->label());
287  return std::unique_ptr<DBEntry>(static_cast<DBEntry *>(mpls));
288 }
289 
292  MplsLabelKey *key = static_cast<MplsLabelKey *>(req->key.get());
293  assert(key->label() != MplsTable::kInvalidLabel);
294 
295  MplsLabel *mpls = new MplsLabel(agent(), key->label());
296  label_table_.InsertAtIndex(mpls->label(), mpls);
297  mpls->Add(req);
298  return mpls;
299 }
300 
301 bool MplsTable::OnChange(DBEntry *entry, const DBRequest *req) {
302  MplsLabel *mpls = static_cast<MplsLabel *>(entry);
303  return mpls->Change(req);
304 }
305 
306 bool MplsTable::Delete(DBEntry *entry, const DBRequest *req) {
307  MplsLabel *mpls = static_cast<MplsLabel *>(entry);
308  if (IsFabricMulticastLabel(mpls->label())) {
309  MplsLabelData *data = static_cast<MplsLabelData *>(req->data.get());
310  // For multicast labels we not expect to be here
311  // via MplsTable::OnZeroRefcount where data is not set.
312  assert(data);
313  if (mpls->fmg_nh_list().find(data->vrf_name()) !=
314  mpls->fmg_nh_list().end()) {
315  mpls->fmg_nh_list().erase(data->vrf_name());
316  }
317  if (mpls->fmg_nh_list().empty() == false) {
318  if (mpls->ChangeNH(mpls->fmg_nh_list().begin()->second.get())) {
319  DBTablePartBase *tpart =
320  static_cast<DBTablePartition *>(GetTablePartition(mpls));
321  tpart->Notify(mpls);
322  }
323  return false;
324  }
325  }
326  mpls->Delete(req);
328  return true;
329 }
330 
332  agent()->ConcurrencyCheck();
333 
334  //Delete db entry
336  req.key = e->GetDBRequestKey();
337  req.data.reset(NULL);
338  Process(req);
339 }
340 
341 uint32_t MplsTable::CreateRouteLabel(uint32_t label, const NextHopKey *nh_key,
342  const std::string &vrf_name,
343  const std::string &route) {
344  if (label == MplsTable::kInvalidLabel) {
346  resource_manager(), vrf_name,
347  route));
348  label = ((static_cast<IndexResourceData *>(agent()->resource_manager()->
349  Allocate(key).get()))->index());
350  assert(label != MplsTable::kInvalidLabel);
351  assert(FindMplsLabel(label) == NULL);
352  }
353 
354  DBRequest req;
356 
357  MplsLabelKey *key = new MplsLabelKey(label);
358  req.key.reset(key);
359 
360  MplsLabelData *data = new MplsLabelData(nh_key->Clone());
361  data->set_vrf_name(vrf_name);
362  req.data.reset(data);
363 
364  Process(req);
365  return label;
366 }
367 
368 bool MplsTable::IsFabricMulticastLabel(uint32_t label) const {
369  for (uint8_t count = 0; count < MAX_XMPP_SERVERS; count++) {
370  if ((label >= multicast_label_start_[count]) &&
371  (label <= multicast_label_end_[count])) return true;
372  }
373  return false;
374 }
375 
376 void MplsTable::ReserveLabel(uint32_t start, uint32_t end) {
377  // We want to allocate labels from an offset
378  // Pre-allocate entries
379  for (uint32_t i = start; i <= end; i++) {
381  }
382 }
383 
384 void MplsTable::FreeReserveLabel(uint32_t start, uint32_t end) {
385  // We want to allocate labels from an offset
386  // Pre-allocate entries
387  for (uint32_t i = start; i <= end; i++) {
389  }
390 }
391 
392 void MplsTable::ReserveMulticastLabel(uint32_t start, uint32_t end,
393  uint8_t idx) {
394  multicast_label_start_[idx] = start;
395  multicast_label_end_[idx] = end;
396  ReserveLabel(start, end);
397 }
398 
400  MplsLabelKey key(label);
401  return static_cast<MplsLabel *>(Find(&key, false));
402 }
403 
404 // Allocate label for next-hop(interface, vrf, vlan)
406  switch(nh_key->GetType()) {
407  case NextHop::INTERFACE:
408  case NextHop::VLAN:
409  case NextHop::VRF:
410  break;
411  default:
412  assert(0);
413  }
414 
415  // Allocate label from resource manager
417  agent()->resource_manager(),
418  nh_key->Clone()));
419  uint32_t label = ((static_cast<IndexResourceData *>(agent()->resource_manager()->
420  Allocate(rkey).get()))->index());
421  assert(label != MplsTable::kInvalidLabel);
422 
423  // Add MplsLabel db entry
424  DBRequest req;
426 
427  MplsLabelKey *key = new MplsLabelKey(label);
428  req.key.reset(key);
429 
430  MplsLabelData *data = new MplsLabelData(nh_key->Clone());
431  req.data.reset(data);
432 
433  agent()->mpls_table()->Process(req);
434 
435  // Return MplsLabel db entry for nh to hold reference
436  MplsLabel *mpls_label = static_cast<MplsLabel *>
437  (agent()->mpls_table()->FindActiveEntry(key));
438  assert(mpls_label);
439 
440  return mpls_label;
441 }
442 
445  VrLimitExceeded::iterator vr_limit_itr = vr_limits.find("vr_mpls_labels");
446  if (vr_limit_itr->second == "Normal") {
448  agent()->vrouter_max_labels())/100) ) {
449  vr_limit_itr->second.assign(std::string("Exceeded"));
450  LOG(ERROR, "Vrouter Mpls Labels Exceeded.");
451  }
452  } else if ( vr_limit_itr->second == "Exceeded") {
454  vr_limit_itr->second.assign(std::string("TableLimit"));
455  LOG(ERROR, "Vrouter Mpls Lablels Table Limit Reached. Skip Label Add.");
457  agent()->vrouter_max_labels())/100) ) {
458  vr_limit_itr->second.assign(std::string("Normal"));
459  }
460  } else if ( vr_limit_itr->second == "TableLimit" ) {
462  ((agent()->vrouter_max_labels()*95)/100) ) {
463  vr_limit_itr->second.assign(std::string("Exceeded"));
464  LOG(ERROR, "Vrouter Mpls Labels Exceeded.");
465  }
466  }
467  agent()->set_vr_limits_exceeded_map(vr_limits);
468 }
469 
471  const std::string &context) {
473  (context, args->GetString("type"),
474  args->GetString("label")));
475 }
476 
477 void MplsReq::HandleRequest() const {
478  AgentSandeshPtr sand(new AgentMplsSandesh(context(), get_type(),
479  get_label()));
480  sand->DoSandesh(sand);
481 }
virtual bool DBEntrySandesh(Sandesh *sresp, std::string &name) const
Definition: mpls.cc:144
const Interface * GetInterface() const
Definition: nexthop.h:1293
MplsLabel(Agent *agent, uint32_t label)
Definition: mpls.cc:26
void ConcurrencyCheck()
Definition: agent.cc:1044
MplsTable(DB *db, const std::string &name)
Definition: mpls.cc:235
std::string vrf_name() const
Definition: mpls.h:39
Type type() const
Definition: interface.h:112
void Process(DBClient *client, DBRequest *req)
void EnqueueRouteResync() const
Definition: agent_route.cc:913
bool IsFabricMulticastLabel(uint32_t label) const
Definition: mpls.cc:368
uint32_t label() const
Definition: mpls.h:79
uint32_t GetRefCount() const
Definition: agent_db.h:54
virtual void SetKey(const DBRequestKey *key)
Definition: mpls.cc:54
void Delete(const DBRequest *req)
Definition: mpls.cc:77
virtual bool OnChange(DBEntry *entry, const DBRequest *req)
Definition: mpls.cc:301
std::string GetString(const std::string &key) const
const boost::uuids::uuid & GetUuid() const
Definition: interface.h:113
bool ChangeNH(NextHop *nh)
Definition: mpls.cc:97
NextHopTable * nexthop_table() const
Definition: agent.h:475
DBTableBase * get_table() const
Definition: db_entry.cc:119
bool ChangeInternal(const DBRequest *req)
Definition: mpls.cc:83
Agent * agent_
Definition: mpls.h:87
SandeshTraceBufferPtr MplsTraceBuf
void Release(KeyPtr key)
void Add(const DBRequest *req)
Definition: mpls.cc:63
const NextHop * nexthop() const
Definition: mpls.h:80
NextHop * nh_
Definition: mpls.h:90
Agent * agent() const
Definition: agent_db.h:213
std::map< std::string, std::string > VrLimitExceeded
Definition: agent.h:214
std::unique_ptr< DBRequestData > data
Definition: db_table.h:49
boost::shared_ptr< ResourceKey > KeyPtr
uint32_t label_
Definition: mpls.h:88
AgentDBEntry * FindActiveEntry(const DBEntry *key)
Definition: agent_db.cc:110
void ReserveLabel(uint32_t start, uint32_t end)
Definition: mpls.cc:376
const string & GetName() const
Definition: vrf.h:100
static std::string UuidToString(const boost::uuids::uuid &id)
Definition: string_util.h:138
float vr_limit_high_watermark()
Definition: agent.h:1391
void ReleaseIndex(Resource::Type, uint32_t index)
uint16_t GetVlanTag() const
Definition: nexthop.h:1544
void FreeReserveLabel(uint32_t start, uint32_t end)
Definition: mpls.cc:384
size_t InUseIndexCount()
Definition: index_vector.h:89
boost::shared_ptr< TraceBuffer< SandeshTrace > > SandeshTraceBufferPtr
Definition: sandesh_trace.h:18
MplsTable * mpls_table() const
Definition: agent.h:510
std::unique_ptr< DBRequestKey > KeyPtr
Definition: db_entry.h:25
void SetNHSandeshData(NhSandeshData &data) const
Definition: nexthop.cc:3172
Type GetType() const
Definition: nexthop.h:405
Base class for all Route entries in agent.
Definition: agent_route.h:224
const VrfEntry * vrf() const
Definition: nexthop.h:1875
virtual ~MplsTable()
Definition: mpls.cc:239
void ReserveIndex(Resource::Type, uint32_t index)
float vr_limit_low_watermark()
Definition: agent.h:1399
void CheckVrLabelLimit()
Definition: mpls.cc:443
IndexVector< MplsLabel * > label_table_
Definition: mpls.h:141
static DBTableBase * CreateTable(DB *db, const std::string &name)
Definition: mpls.cc:242
NextHop::Type GetType() const
Definition: nexthop.h:499
virtual ~MplsLabel()
Definition: mpls.cc:30
Definition: db.h:24
void Init()
Definition: db_table.cc:387
void FreeMplsLabelIndex(size_t label)
Definition: mpls.h:138
void ReserveMulticastLabel(uint32_t start, uint32_t end, uint8_t idx)
Definition: mpls.cc:392
uint8_t type
Definition: load_balance.h:109
uint32_t label() const
Definition: mpls.h:25
virtual bool IsLess(const DBEntry &rhs) const
Definition: mpls.cc:40
Definition: agent.h:358
MplsLabel * AllocLabel(const NextHopKey *nh_key)
Definition: mpls.cc:405
std::unique_ptr< DBRequestKey > key
Definition: db_table.h:48
uint32_t multicast_label_end_[MAX_XMPP_SERVERS]
Definition: mpls.h:143
DBOperation oper
Definition: db_table.h:42
virtual AgentSandeshPtr GetAgentSandesh(const AgentSandeshArguments *args, const std::string &context)
Definition: mpls.cc:470
virtual KeyPtr GetDBRequestKey() const
Definition: mpls.cc:49
virtual DBEntry * Add(const DBRequest *req)
Definition: mpls.cc:290
#define OPER_TRACE_ENTRY(obj, table,...)
Definition: agent_db.h:234
virtual void Process(DBRequest &req)
Definition: mpls.cc:248
class boost::shared_ptr< AgentSandesh > AgentSandeshPtr
Definition: agent_db.h:18
uint32_t vrouter_max_labels() const
Definition: agent.h:1252
AgentDBEntry * Find(const DBEntry *key, bool ret_del)
Definition: agent_db.cc:134
void SendObjectLog(const AgentDBTable *table, AgentLogEvent::type event) const
Definition: mpls.cc:157
virtual uint32_t GetRefCount() const
Definition: mpls.cc:59
virtual KeyPtr GetDBRequestKey() const =0
FmgVrfNhMap & fmg_nh_list()
Definition: mpls.h:81
bool free_label_
Definition: mpls.h:89
#define MAX_XMPP_SERVERS
Definition: agent.h:291
static const uint32_t kInvalidLabel
Definition: mpls.h:101
void SyncDependentPath()
Definition: mpls.cc:126
void Delete()
Definition: db_entry.cc:131
virtual DBTablePartBase * GetTablePartition(const DBRequestKey *key)
Definition: db_table.cc:436
uint32_t CreateRouteLabel(uint32_t label, const NextHopKey *nh_key, const std::string &vrf_name, const std::string &route)
Definition: mpls.cc:341
void set_vr_limits_exceeded_map(VrLimitExceeded &vr_limit_exceed_map)
Definition: agent.h:1383
#define MPLS_TRACE(obj,...)
Definition: mpls.h:15
Definition: mpls.h:99
virtual std::unique_ptr< DBEntry > AllocEntry(const DBRequestKey *k) const
Definition: mpls.cc:284
uint32_t multicast_label_start_[MAX_XMPP_SERVERS]
Definition: mpls.h:142
Definition: mpls.h:52
VrLimitExceeded & get_vr_limits_exceeded_map()
Definition: agent.h:1379
bool Change(const DBRequest *req)
Definition: mpls.cc:70
bool IsFabricMulticastReservedLabel() const
Definition: mpls.cc:135
FmgVrfNhMap fmg_nh_list_
Definition: mpls.h:91
#define LOG(_Level, _Msg)
Definition: logging.h:33
MplsLabel * FindMplsLabel(uint32_t label)
Definition: mpls.cc:399
const std::string & name() const
Definition: interface.h:114
void set_vrf_name(const std::string &vrf_name)
Definition: mpls.h:40
bool PolicyEnabled() const
Definition: nexthop.h:407
virtual bool Delete(DBEntry *entry, const DBRequest *req)
Definition: mpls.cc:306
void Notify(DBEntryBase *entry)
const Interface * GetInterface() const
Definition: nexthop.h:1543
virtual void OnZeroRefcount(AgentDBEntry *e)
Definition: mpls.cc:331
virtual std::string ToString() const
Definition: mpls.cc:45
virtual NextHopKey * Clone() const =0
ResourceManager * resource_manager() const
Definition: agent.cc:1021
void FreeLabel(uint32_t label)
Definition: mpls.cc:267
SandeshTraceBufferPtr SandeshTraceBufferCreate(const std::string &buf_name, size_t buf_size, bool trace_enable=true)
Definition: sandesh_trace.h:46
size_t InsertAtIndex(uint32_t index, EntryType entry)
Definition: index_vector.h:54
const NextHopKey * nh_key() const
Definition: mpls.h:38