OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ha_stale_l2_route.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 extern "C" {
6 #include <ovsdb_wrapper.h>
7 };
9 #include <ovsdb_client.h>
10 #include <ovsdb_route_peer.h>
12 #include <ha_stale_dev_vn.h>
13 #include <ha_stale_l2_route.h>
14 
15 #include <oper/vn.h>
16 #include <oper/vrf.h>
17 #include <oper/nexthop.h>
18 #include <oper/tunnel_nh.h>
19 #include <oper/agent_path.h>
20 #include <oper/bridge_route.h>
21 
22 #include <ovsdb_sandesh.h>
23 #include <ovsdb_types.h>
24 
25 using namespace OVSDB;
26 std::string empty_string("");
27 
29  const std::string &mac) : OvsdbDBEntry(table), mac_(mac),
30  path_preference_(0), vxlan_id_(0), time_stamp_(0), sip_(), dip_(),
31  is_multicast_(false) {
32 }
33 
35 }
36 
38  // Stop stale clear timer on add/change/delete req
41  static_cast<HaStaleL2RouteTable *>(table_);
42  if (table->vn_name_.empty()) {
43  // donot reexport the route if dest VN is not available
44  OVSDB_TRACE(Trace, std::string("Skipping Route export dest VN name ") +
45  "not available vrf " + table->vrf_->GetName() +
46  ", VxlanId " + integerToString(table->vxlan_id_) + ", MAC "+
47  mac_ + ", dest ip " + table->dev_ip_.to_string());
48  return true;
49  }
50 
52  // donot reexport the route if path preference is HA_STALE
53  return true;
54  }
55  HaStaleDevVnEntry *dev_vn = table->dev_vn_;
56  vxlan_id_ = table->vxlan_id_;
57  if (is_multicast_) {
58  dev_vn->route_peer()->AddOvsPeerMulticastRoute(table->vrf_.get(),
59  vxlan_id_,
60  table->vn_name_,
61  sip_,
62  table->dev_ip_);
63  } else {
64  dev_vn->route_peer()->AddOvsRoute(table->vrf_.get(), vxlan_id_,
65  table->vn_name_, MacAddress(mac_),
66  table->dev_ip_);
67  }
68  OVSDB_TRACE(Trace, std::string("Adding Ha Stale route vrf ") +
69  table->vrf_->GetName() + ", VxlanId " +
70  integerToString(vxlan_id_) + ", MAC " + mac_ + ", dest ip " +
71  table->dev_ip_.to_string());
72  return true;
73 }
74 
77  static_cast<HaStaleL2RouteTable *>(table_);
78  if (vxlan_id_ != 0 && vxlan_id_ != table->vxlan_id_) {
79  // for change in vxlan id delete the previously exported
80  // route before calling AddMsg
81  Delete();
82  vxlan_id_ = 0;
83  }
84  return Add();
85 }
86 
88  // Stop stale clear timer on add/change/delete req
91  static_cast<HaStaleL2RouteTable *>(table_);
92  HaStaleDevVnEntry *dev_vn = table->dev_vn_;
93  OVSDB_TRACE(Trace, std::string("withdrawing Ha Stale route vrf ") +
94  table->vrf_->GetName() + ", VxlanId " +
95  integerToString(vxlan_id_) + ", MAC " + mac_);
96  if (is_multicast_) {
97  dev_vn->route_peer()->DeleteOvsPeerMulticastRoute(table->vrf_.get(),
98  vxlan_id_,
99  table->dev_ip_);
100  } else {
101  dev_vn->route_peer()->DeleteOvsRoute(table->vrf_.get(), vxlan_id_,
102  MacAddress(mac_));
103  }
104  return true;
105 }
106 
108  // Cancel timer if running
109  if (time_stamp_ != 0) {
111  static_cast<HaStaleL2RouteTable *>(table_);
112  HaStaleDevVnEntry *dev_vn = table->dev_vn_;
113  HaStaleDevVnTable *dev_vn_table =
114  static_cast<HaStaleDevVnTable*>(dev_vn->table());
115  dev_vn_table->StaleClearDelEntry(time_stamp_, this);
116  time_stamp_ = 0;
117  }
118 }
119 
121  const BridgeRouteEntry *entry =
122  static_cast<const BridgeRouteEntry *>(db_entry);
123  const AgentPath *path = entry->GetActivePath();
124  bool change = false;
125  if (path != NULL && path_preference_ != path->preference()) {
126  path_preference_ = path->preference();
128  // Active Path gone, start the timer to delete path
129  if (time_stamp_ == 0) {
131  static_cast<HaStaleL2RouteTable *>(table_);
132  HaStaleDevVnEntry *dev_vn = table->dev_vn_;
133  HaStaleDevVnTable *dev_vn_table =
134  static_cast<HaStaleDevVnTable*>(dev_vn->table());
135  time_stamp_ = dev_vn_table->time_stamp();
136  dev_vn_table->StaleClearAddEntry(time_stamp_, this,
137  boost::bind(&HaStaleL2RouteEntry::StaleClearCb, this));
138  }
139  } else {
140  change = true;
141  }
142  }
143 
144  //Extract sip_/dip_ if tunnel nh
145  if (path != NULL) {
146  TunnelNH *tnh = dynamic_cast<TunnelNH *>(path->nexthop());
147  if (tnh) {
148  sip_ = *tnh->GetSip();
149  dip_ = *tnh->GetDip();
150  }
151  }
152  is_multicast_ = entry->is_multicast();
153 
155  if (vxlan_id_ != table->vxlan_id_) {
156  // update of vxlan id is done after withdrawing previously
157  // exported route
158  change = true;
159  }
160 
161  return change;
162 }
163 
164 bool HaStaleL2RouteEntry::IsLess(const KSyncEntry &entry) const {
165  const HaStaleL2RouteEntry &ucast =
166  static_cast<const HaStaleL2RouteEntry&>(entry);
167  return mac_ < ucast.mac_;
168 }
169 
171  return NULL;
172 }
173 
174 const std::string &HaStaleL2RouteEntry::mac() const {
175  return mac_;
176 }
177 
179  return vxlan_id_;
180 }
181 
183  return (time_stamp_ != 0);
184 }
185 
187  // set timer to NULL as it will be deleted due to completion
188  table_->Delete(this);
189 }
190 
192  HaStaleDevVnEntry *dev_vn, AgentRouteTable *table) :
193  OvsdbDBObject(NULL, false), table_delete_ref_(this, table->deleter()),
194  dev_vn_(dev_vn), state_(dev_vn->state()),
195  dev_ip_(dev_vn->dev_ip().to_v4()), vxlan_id_(dev_vn->vxlan_id()),
196  vrf_(table->vrf_entry(), this), vn_name_(dev_vn->vn_name()) {
197  OvsdbRegisterDBTable(table);
198 }
199 
201  // Table unregister will be done by Destructor of KSyncDBObject
202  table_delete_ref_.Reset(NULL);
203 }
204 
205 KSyncEntry *HaStaleL2RouteTable::Alloc(const KSyncEntry *key, uint32_t index) {
206  const HaStaleL2RouteEntry *k_entry =
207  static_cast<const HaStaleL2RouteEntry *>(key);
208  HaStaleL2RouteEntry *entry = new HaStaleL2RouteEntry(this, k_entry->mac_);
209  return entry;
210 }
211 
213  const BridgeRouteEntry *entry =
214  static_cast<const BridgeRouteEntry *>(db_entry);
215  HaStaleL2RouteEntry *key =
216  new HaStaleL2RouteEntry(this, entry->prefix_address().ToString());
217  return static_cast<KSyncEntry *>(key);
218 }
219 
221  const DBEntry *db_entry, const OvsdbDBEntry *ovsdb_entry) {
222  const BridgeRouteEntry *entry =
223  static_cast<const BridgeRouteEntry *>(db_entry);
224  if (entry->vrf()->IsDeleted()) {
225  // if notification comes for a entry with deleted vrf,
226  // trigger delete since we donot resue same vrf object
227  // so this entry has to be deleted eventually.
228  return DBFilterDelete;
229  }
230 
231  const NextHop *nh = entry->GetActiveNextHop();
232  if (nh == NULL || nh->GetType() != NextHop::TUNNEL) {
233  return DBFilterDelete;
234  }
235 
236  const TunnelNH *tunnel = static_cast<const TunnelNH *>(nh);
237  if (tunnel && (*tunnel->GetDip() != dev_ip_)) {
238  // its not a route to replicate, return delete
239  // need to return delete to handle MAC move scenarios
240  // as well
241  return DBFilterDelete;
242  }
243 
244  const AgentPath *path = entry->GetActivePath();
245  if (path != NULL) {
246  // if connection is active and preference is
247  // PathPreference::HA_STALE trigger delete
248  if (path->preference() == PathPreference::HA_STALE
249  && state_->IsConnectionActive()) {
250  return DBFilterDelete;
251  }
252  } else {
253  return DBFilterDelete;
254  }
255 
256  return DBFilterAccept;
257 }
258 
260  return dev_vn_->agent();
261 }
262 
264  // We do rely on follow up notification of VRF Delete
265  // to handle delete of this route table
266 }
267 
270  // unregister the object if emptytable is called with
271  // object being scheduled for delete
272  if (delete_scheduled()) {
273  // trigger Ack for Dev Vn entry and reset to NULL
274  dev_vn_->TriggerAck(this);
275  dev_vn_ = NULL;
277  }
278 }
279 
281  return dev_ip_;
282 }
283 
285  return vxlan_id_;
286 }
287 
288 const std::string &HaStaleL2RouteTable::vn_name() const {
289  return vn_name_;
290 }
291 
292 const std::string &HaStaleL2RouteTable::vrf_name() const {
293  if (vrf_ == NULL) {
294  return empty_string;
295  }
296  return vrf_->GetName();
297 }
298 
300  // update params and start resync walk
301  bool change = false;
302  if (vxlan_id_ != dev_vn->vxlan_id()) {
303  vxlan_id_ = dev_vn->vxlan_id();
304  change = true;
305  }
306 
307  if (vn_name_ != dev_vn->vn_name()) {
308  vn_name_ = dev_vn->vn_name();
309  change = true;
310  }
311 
312  if (dev_ip_ != dev_vn->dev_ip().to_v4()) {
313  dev_ip_ = dev_vn->dev_ip().to_v4();
314  change = true;
315  }
316 
317  if (change) {
319  }
320 }
321 
323 // Sandesh routines
326  std::string resp_ctx, AgentSandeshArguments &args) :
327  OvsdbSandeshTask(resp_ctx, args), dev_name_(""), vn_uuid_("") {
328  if (false == args.Get("dev_name", &dev_name_)) {
329  dev_name_ = "";
330  }
331  if (false == args.Get("vn_uuid", &vn_uuid_)) {
332  vn_uuid_ = "";
333  }
334  if (false == args.Get("mac", &mac_)) {
335  mac_ = "";
336  }
337 }
338 
340  const std::string &dev,
341  const std::string &vn_uuid,
342  const std::string &mac) :
343  OvsdbSandeshTask(resp_ctx, "0.0.0.0", 0), dev_name_(dev), vn_uuid_(vn_uuid),
344  mac_(mac) {
345 }
346 
348 }
349 
351  if (!dev_name_.empty()) {
352  args.Add("dev_name", dev_name_);
353  }
354  if (!vn_uuid_.empty()) {
355  args.Add("vn_uuid", vn_uuid_);
356  }
357  if (!mac_.empty()) {
358  args.Add("mac", mac_);
359  }
360 }
361 
364  if (!vn_uuid_.empty()) {
365  HaStaleL2RouteEntry *entry = static_cast<HaStaleL2RouteEntry *>(kentry);
366  if (entry->mac().find(mac_) != std::string::npos) {
367  return FilterAllow;
368  }
369  return FilterDeny;
370  }
371  return FilterAllow;
372 }
373 
375  SandeshResponse *resp) {
376  HaStaleL2RouteEntry *entry = static_cast<HaStaleL2RouteEntry *>(kentry);
377  HaStaleL2RouteTable *table =
378  static_cast<HaStaleL2RouteTable *>(entry->table());
379  OvsdbHaStaleL2RouteExport lentry;
380  lentry.set_state(entry->StateString());
381  lentry.set_dev_ip(table->dev_ip().to_string());
382  lentry.set_vn_name(table->vn_name());
383  lentry.set_vrf_name(table->vrf_name());
384  lentry.set_mac(entry->mac());
385  lentry.set_vxlan_id(entry->vxlan_id());
386  if (entry->IsStale()) {
387  lentry.set_status("stale");
388  } else {
389  lentry.set_status("active");
390  }
391 
392  OvsdbHaStaleL2RouteExportResp *l_resp =
393  static_cast<OvsdbHaStaleL2RouteExportResp *>(resp);
394  std::vector<OvsdbHaStaleL2RouteExport> &l2_route =
395  const_cast<std::vector<OvsdbHaStaleL2RouteExport>&>(
396  l_resp->get_l2_route());
397  l2_route.push_back(lentry);
398 }
399 
401  return static_cast<SandeshResponse *>(new OvsdbHaStaleL2RouteExportResp());
402 }
403 
405  ConnectionStateTable *con_table =
407  ConnectionStateEntry *con_entry = con_table->Find(dev_name_);
408  if (con_entry == NULL) {
409  return NULL;
410  }
411  HaStaleDevVnTable *dev_vn_table = con_entry->ha_stale_dev_vn_table();
412  HaStaleDevVnEntry dev_vn_key(dev_vn_table, StringToUuid(vn_uuid_));
413  HaStaleDevVnEntry *dev_vn_entry =
414  static_cast<HaStaleDevVnEntry*>(dev_vn_table->Find(&dev_vn_key));
415  if (dev_vn_entry == NULL) {
416  return NULL;
417  }
418  return static_cast<KSyncObject *>(dev_vn_entry->l2_table());
419 }
420 
421 void OvsdbHaStaleL2RouteExportReq::HandleRequest() const {
423  new HaStaleL2RouteSandeshTask(context(), get_dev_name(),
424  get_vn_uuid(), get_mac());
426  scheduler->Enqueue(task);
427 }
428 
HaStaleL2RouteSandeshTask(std::string resp_ctx, AgentSandeshArguments &args)
FilterResp Filter(KSyncEntry *entry)
OVSDB::OvsdbClient * ovsdb_client() const
Definition: agent.h:1126
#define OVSDB_TRACE(obj,...)
OvsdbDBObject * table()
Definition: ovsdb_entry.h:96
OvsPeer * route_peer() const
static Agent * GetInstance()
Definition: agent.h:436
static boost::uuids::uuid StringToUuid(const std::string &str)
Definition: string_util.h:145
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h:178
HaStaleL2RouteTable * l2_table() const
virtual void EmptyTable(void)
Agent supports multiple route tables - Inet-unicast (IPv4/IPv6), Inet-multicast, bridge, EVPN (Type2/Type5). This base class contains common code for all types of route tables.
Definition: agent_route.h:109
DBFilterResp OvsdbDBEntryFilter(const DBEntry *entry, const OvsdbDBEntry *ovsdb_entry)
std::string StateString() const
bool IsDeleted() const
Definition: db_entry.h:49
void StaleClearAddEntry(uint64_t time_stamp, HaStaleL2RouteEntry *entry, StaleClearL2EntryCb cb)
bool is_multicast() const
Definition: agent_route.h:274
void Delete(KSyncEntry *entry)
virtual void OvsdbRegisterDBTable(DBTable *tbl)
Definition: ovsdb_object.cc:76
const Ip4Address * GetDip() const
Definition: tunnel_nh.h:37
HaStaleL2RouteTable(HaStaleDevVnEntry *dev_vn, AgentRouteTable *table)
static void Unregister(KSyncObject *)
bool delete_scheduled()
Definition: ksync_object.h:146
Type GetType() const
Definition: nexthop.h:405
void EncodeArgs(AgentSandeshArguments &args)
std::string ToString() const
Definition: mac_address.cc:53
const std::string & vn_name() const
const AgentPath * GetActivePath() const
Definition: agent_route.cc:876
HaStaleDevVnTable * ha_stale_dev_vn_table() const
NextHop * nexthop() const
Definition: agent_path.cc:87
static const std::string integerToString(const NumberType &num)
Definition: string_util.h:19
bool Get(const std::string &key, std::string *val) const
Definition: agent.h:358
static TaskScheduler * GetInstance()
Definition: task.cc:547
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
const NextHop * GetActiveNextHop() const
Definition: agent_route.cc:881
ConnectionStateEntry * state_
Definition: trace.h:220
bool AddOvsRoute(const VrfEntry *vrf, uint32_t vxlan_id, const std::string &dest_vn, const MacAddress &mac, Ip4Address &tor_ip)
void TriggerAck(HaStaleL2RouteTable *table)
const Ip4Address * GetSip() const
Definition: tunnel_nh.h:36
KSyncEntry * Find(const KSyncEntry *key)
Definition: ksync_object.cc:99
LifetimeRef< HaStaleL2RouteTable > table_delete_ref_
bool Add(const std::string &key, const std::string &val)
KSyncObject * GetObject(OvsdbClientSession *session)
KSyncEntry * Alloc(const KSyncEntry *key, uint32_t index)
HaStaleL2RouteEntry(HaStaleL2RouteTable *table, const std::string &mac)
virtual const PrefixType & prefix_address() const
Returns the value of a stored prefix address (IPv4, IPv6 or MAC address)
Definition: agent_route.h:375
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
ConnectionStateEntry * Find(const std::string &device_name)
uint32_t vxlan_id() const
void AddOvsPeerMulticastRoute(const VrfEntry *vrf, uint32_t vxlan_id, const std::string &vn_name_, const Ip4Address &tsn_ip, const Ip4Address &tor_ip)
ConnectionStateTable * connection_table()
Definition: ovsdb_client.cc:40
uint64_t time_stamp() const
void StaleClearDelEntry(uint64_t time_stamp, HaStaleL2RouteEntry *entry)
std::string empty_string("")
void DeleteOvsRoute(VrfEntry *vrf, uint32_t vxlan, const MacAddress &mac)
const std::string & mac() const
VrfEntry * vrf() const
Definition: agent_route.h:275
KSyncEntry * DBToKSyncEntry(const DBEntry *)
void UpdateResp(KSyncEntry *kentry, SandeshResponse *resp)
uint32_t preference() const
Definition: agent_path.h:327
IpAddress dev_ip() const
const std::string & vn_name() const
OvsdbDBObject * table_
Definition: ovsdb_entry.h:110
void DeleteOvsPeerMulticastRoute(const VrfEntry *vrf, uint32_t vxlan_id, const Ip4Address &tor_ip)
const std::string & vrf_name() const
struct task_ task
HaStaleDevVnEntry * dev_vn_
void UpdateParams(HaStaleDevVnEntry *dev_vn)
bool IsLess(const KSyncEntry &) const