OpenSDN source code
vxlan_routes_leaking.cc
Go to the documentation of this file.
1 #include <boost/uuid/uuid_io.hpp>
2 #include <boost/lexical_cast.hpp>
3 #include <cmn/agent_cmn.h>
4 
5 #include <base/logging.h>
6 #include <oper/operdb_init.h>
7 #include <oper/route_common.h>
8 #include <oper/vrf.h>
9 #include <oper/bridge_route.h>
11 #include <oper/evpn_route.h>
12 #include <oper/agent_route.h>
14 #include <oper/vn.h>
15 #include <oper/vrf.h>
17 #include <oper/tunnel_nh.h> //for tunnel interception
18 
20 
22 
23 /*
24  *
25  * Routes Leaking
26  *
27  */
28 
30  DBEntryBase *e) {
31  const InetUnicastRouteEntry *inet_rt =
32  dynamic_cast<const InetUnicastRouteEntry*>(e);
33  if (inet_rt) {
34  if (IsBridgeVrf(inet_rt->vrf())) {
35  return InetRouteNotify(partition, e);
36  }
37  // // Deactive redundant bgp paths by moving local peer
38  // // path to top
39  // if (IsRoutingVrf(inet_rt->vrf())) {
40  // const AgentPath * loc_vm_port =
41  // FindInterfacePathWithGivenPeer(inet_rt,
42  // routing_vrf_interface_peer_->GetType(), true);
43  // if (loc_vm_port) {
44  // Route::PathList & path_list =
45  // const_cast<Route::PathList &>(inet_rt->GetPathList());
46  // path_list.reverse();
47  // }
48  // }
49  }
50 
51  const EvpnRouteEntry *evpn_rt =
52  dynamic_cast<const EvpnRouteEntry *>(e);
53  if (evpn_rt && IsRoutingVrf(evpn_rt->vrf())) {
54  return EvpnRouteNotify(partition, e);
55  }
56  return true;
57 }
58 
59 /*
60  *
61  *
62  * Step 1. InetRouteNotify
63  * Handles changes in inet routes originating from a bridge VRF.
64  * Copies new routes to the routing VRF EVPN Type 5 table.
65  * Or deletes old routes from the routing VRF EVPN Type 5 table.
66  *
67  *
68  */
69 //Handles change in NH of local vm port path
70 //For all host routes with non local vm port path, evpn route in routing vrf
71 //need not be added. It should come from CN.
73  DBEntryBase *e) {
74  const InetUnicastRouteEntry *inet_rt =
75  dynamic_cast<const InetUnicastRouteEntry*>(e);
76 
77  if (inet_rt->prefix_address().is_v6() &&
78  inet_rt->prefix_address().to_v6().is_link_local()) {
79  return true;
80  }
81 
82  const VrfEntry *routing_vrf =
84  if (routing_vrf == NULL || routing_vrf == inet_rt->vrf()) {
85  return true;
86  }
87 
88  EvpnAgentRouteTable *evpn_table =
89  dynamic_cast<EvpnAgentRouteTable *>(routing_vrf->GetEvpnRouteTable());
90  if (evpn_table == NULL) {
91  return true;
92  }
93 
94  const AgentPath *local_vm_port_path = NULL;
95  local_vm_port_path = inet_rt->FindIntfOrCompLocalVmPortPath();
96 
97  // if path with LOCAL_VM_PORT hasn't been found, then
98  // this probably may mean that it was deleted
99  if (local_vm_port_path == NULL) {
101  WhenBridgeInetIntfWasDeleted(inet_rt, routing_vrf);
102  return true;
103  }
104 
105  PathPreference preference = local_vm_port_path->path_preference();
106  preference.set_loc_sequence(GetNewLocalSequence(local_vm_port_path));
107  // preference.set_preference(100);
108  VnListType dest_vns;
109  dest_vns.insert(routing_vrf->vn()->GetName());
110 
111  CopyInterfacePathToEvpnTable(local_vm_port_path,
112  inet_rt->prefix_address(),
113  inet_rt->prefix_length(),
114  routing_vrf_interface_peer_, // agent->local_vm_export_peer(),
115  RouteParameters(IpAddress(), // not needed here
116  MacAddress(), // not needed here ?
117  dest_vns,
118  local_vm_port_path->sg_list(),
119  local_vm_port_path->communities(),
120  local_vm_port_path->tag_list(),
121  preference,
122  local_vm_port_path->ecmp_load_balance(),
124  evpn_table);
125 
126  return true;
127 }
128 
129 /*
130  * Step 2.
131  * Copies a route from the routing VRF EVPN Type 5 table into the
132  * routing VRF Inet table.
133  *
134  */
136  DBEntryBase *e) {
137  const EvpnRouteEntry *evpn_rt =
138  dynamic_cast<const EvpnRouteEntry *>(e);
139 
140  if (evpn_rt->IsType5() == false) {
141  return true;
142  }
143 
144  VrfEntry *vrf = evpn_rt->vrf();
145  const AgentPath *local_vm_port_path = evpn_rt->FindPath(
147 
148  const AgentPath *bgp_path =
150 
151  if (bgp_path) {
153  evpn_rt->prefix_length(), vrf->GetName(), bgp_path);
154  }
155 
156  if (local_vm_port_path) {
157  const NextHop *anh = local_vm_port_path->nexthop();
158  if (anh == NULL) {
159  return true;
160  }
161  CopyPathToInetTable(local_vm_port_path,
162  evpn_rt->prefix_address(),
163  evpn_rt->prefix_length(),
166  MacAddress(),
167  local_vm_port_path->dest_vn_list(),
168  local_vm_port_path->sg_list(),
169  local_vm_port_path->communities(),
170  local_vm_port_path->tag_list(),
171  local_vm_port_path->path_preference(),
172  local_vm_port_path->ecmp_load_balance(),
174  vrf->GetInetUnicastRouteTable(evpn_rt->prefix_address()));
175 
176  LeakRoutesIntoBridgeTables(partition,
177  e, vrf->vn()->logical_router_uuid(), NULL, true);
178  }
179 
180  if (bgp_path == NULL) {
181  // the route might be deleted
184  }
185 
186  if (local_vm_port_path == NULL) {
187  // the route might be deleted
190  // and/or it requires publishing in bridge
191  LeakRoutesIntoBridgeTables(partition, e,
192  vrf->vn()->logical_router_uuid(), NULL, true);
193  return true;
194  }
195 
196  return true;
197 }
198 
199 /*
200  *
201  * Routes Deletion
202  *
203  */
205  InetUnicastRouteEntry *inet_route =
206  dynamic_cast<InetUnicastRouteEntry*>(e);
207  if (inet_route == NULL) {
208  return;
209  }
210  if (inet_route->GetPathList().size() > 1 &&
211  inet_route->FindPath(agent_->evpn_routing_peer())) {
213  inet_route->vrf()->GetName(),
214  inet_route->prefix_address(),
215  inet_route->prefix_length());
216  }
217 }
218 
219 /*
220  *
221  * Step 1. If a route is deleted / changed in a bridge VRF INET,
222  * then schedule deletion of a route / path in a routing VRF EVPN
223  * Type 5.
224  *
225  */
226 
228  const InetUnicastRouteEntry *inet_rt,
229  const VrfEntry* routing_vrf) {
230 
231  if (inet_rt->FindPath(agent_->evpn_routing_peer())) {
232  return;
233  }
234 
235  // Check that this route is present in the routing VRF
236  const EvpnAgentRouteTable *evpn_table =
237  dynamic_cast<const EvpnAgentRouteTable *>
238  (routing_vrf->GetEvpnRouteTable());
239  if (evpn_table == NULL) {
240  return;
241  }
242 
243  const EvpnRouteEntry *evpn_rt =
244  const_cast<EvpnAgentRouteTable *>
245  (evpn_table)->FindRoute(MacAddress(),
246  inet_rt->prefix_address(), inet_rt->prefix_length(), 0);
247  if (RoutePrefixIsEqualTo(evpn_rt, inet_rt->prefix_address(), inet_rt->prefix_length()) == false) {
248  if (inet_rt->IsDeleted()) {
249  // That might be an IPAM route from neighb. bridge VRF instances.
250  if (IsHostRoute(inet_rt->prefix_address(), inet_rt->prefix_length()) == false) {
251  DeleteIpamRoutes(inet_rt->vrf()->vn(),
252  inet_rt->vrf()->GetName(),
253  inet_rt->prefix_address(), inet_rt->prefix_length());
254  }
255  }
256  return;
257  }
258 
259  bool ok_to_delete = inet_rt->IsDeleted() ||
261 
262  if ((ok_to_delete) && (!inet_rt->origin_vn_name().empty()) &&
263  (inet_rt->origin_vn_name()!=inet_rt->vrf()->vn()->GetName()) &&
264  (inet_rt->origin_vn_name()!=routing_vrf->vn()->GetName())) {
265  return;
266  }
267 
268  if (ok_to_delete) {
269  // Delete EVPN Type 5 record in the routing VRF
272  routing_vrf->GetName(),
273  MacAddress(),
274  inet_rt->prefix_address(),
275  inet_rt->prefix_length(),
276  0, // ethernet_tag = 0 for Type5
277  NULL);
278  }
279 }
280 
281 /*
282  *
283  * Step 2. Delete the routing VRF Inet route
284  *
285  */
287  (const EvpnRouteEntry *routing_evpn_rt, const Peer *delete_from_peer) {
288 
289  if (routing_evpn_rt->FindPath(agent_->evpn_routing_peer())) {
290  // Actually, VRF NH Routes are not allowed here
291  return;
292  }
293 
294  VrfEntry *vrf = routing_evpn_rt->vrf();
295  if (vrf == NULL) {
296  return;
297  }
298  InetUnicastAgentRouteTable *routing_inet_table =
299  vrf->GetInetUnicastRouteTable(routing_evpn_rt->prefix_address());
300  if (routing_inet_table == NULL) {
301  return;
302  }
303 
304  // check that the Inet table holds the corresponding route
305  InetUnicastRouteEntry local_vm_route_key(
306  routing_inet_table->vrf_entry(),
307  routing_evpn_rt->prefix_address(),
308  routing_evpn_rt->prefix_length(), false);
309  InetUnicastRouteEntry *inet_rt =
310  dynamic_cast<InetUnicastRouteEntry *>
311  (routing_inet_table->FindLPM(local_vm_route_key));
312  if (RoutePrefixIsEqualTo(inet_rt, routing_evpn_rt->prefix_address(),
313  routing_evpn_rt->prefix_length()) == false) {
314  return;
315  }
316 
317  bool ok_to_delete = routing_evpn_rt->IsDeleted() ||
318  inet_rt->FindPath(delete_from_peer);
319 
320  if (ok_to_delete) {
321  // Delete EVPN Type 5 record in the routing VRF
323  delete_from_peer,
324  vrf->GetName(),
325  routing_evpn_rt->prefix_address(),
326  routing_evpn_rt->prefix_length(),
327  NULL);
328  }
329 }
330 
332  const VrfEntry *routing_vrf,
333  DBTablePartBase *partition, DBEntryBase *e) {
334 
335  EvpnRouteEntry *evpn_rt = dynamic_cast<EvpnRouteEntry *>(e);
336 
337  if (!routing_vrf || !routing_vrf->GetEvpnRouteTable() || !evpn_rt) {
338  return true;
339  }
340  EvpnAgentRouteTable *routing_evpn = static_cast<EvpnAgentRouteTable*>(
341  routing_vrf->GetEvpnRouteTable());
342  const EvpnRouteEntry *rt_route = routing_evpn->FindRoute(
343  MacAddress(), evpn_rt->prefix_address(), evpn_rt->prefix_length(), 0);
344  if (RoutePrefixIsEqualTo(rt_route, evpn_rt->prefix_address(),
345  evpn_rt->prefix_length())) {
346  // Remove deleted EVPN Type 5 record in the routing VRF
349  routing_vrf->GetName(),
350  MacAddress(),
351  evpn_rt->prefix_address(),
352  evpn_rt->prefix_length(),
353  0, // ethernet_tag = 0 for Type5
354  NULL);
355  }
356  return true;
357 }
358 
360 (DBTablePartBase *partition, DBEntryBase *e, const boost::uuids::uuid &uuid,
361  const VnEntry *vn, bool update) {
362 
363  EvpnRouteEntry *evpn_rt = dynamic_cast<EvpnRouteEntry *>(e);
364  if (!evpn_rt || (evpn_rt->vrf()->vn() == NULL) || (!evpn_rt->IsType5()))
365  return true;
366  if (uuid == boost::uuids::nil_uuid())
367  return true;
368  // Only non-local non-/32 and non-/128 routes are
369  // copied to bridge vrfs
370  if (IsHostRouteFromLocalSubnet(evpn_rt)) { //IsLocalSubnetHostRoute
371  return true;
372  }
373 
378  if (update && vn != NULL) {
379  update_bridge_vn_list.insert(vn);
380  it = update_bridge_vn_list.find(vn);
381  } else {
382  update_bridge_vn_list = lr_vrf_info.bridge_vn_list_;
383  it = update_bridge_vn_list.begin();
384  }
385  while (it != update_bridge_vn_list.end()) {
386  VrfEntry *bridge_vrf = (*it)->GetVrf();
387 
388  if (bridge_vrf == NULL) {
389  it++;
390  continue;
391  }
392 
393  if (IsVrfLocalRoute(evpn_rt, bridge_vrf)) {
394  it++;
395  continue;
396  }
397 
398  InetUnicastAgentRouteTable *inet_table =
399  bridge_vrf->GetInetUnicastRouteTable(evpn_rt->prefix_address());
400 
401  if (evpn_rt->IsDeleted()) {
403  bridge_vrf->GetName(),
404  evpn_rt->prefix_address(),
405  evpn_rt->prefix_length(),
406  NULL);
407  } else {
408  const AgentPath *p = evpn_rt->GetActivePath();
409  const VrfEntry *routing_vrf = lr_vrf_info.routing_vrf_;
410  // Now all interface routes in routing vrf have BGP_PEER copies
411  if (routing_vrf == NULL) {
412  return true;
413  }
414 
416  nh_req.key.reset(new VrfNHKey(routing_vrf->GetName(), false, false));
417  nh_req.data.reset(new VrfNHData(false, false, false));
418  inet_table->AddEvpnRoutingRouteReq(evpn_rt->prefix_address(),
419  evpn_rt->prefix_length(),
420  bridge_vrf,
422  p->sg_list(),
423  p->communities(),
424  p->path_preference(),
425  p->ecmp_load_balance(),
426  p->tag_list(),
427  nh_req,
428  routing_vrf->vxlan_id(),
429  p->dest_vn_list());
430  }
431  it++;
432  }
433  return true;
434 }
435 
436 //
437 //END-OF-FILE
438 //
439 
boost::asio::ip::address IpAddress
Definition: address.h:13
std::set< std::string > VnListType
Definition: agent.h:212
const VnListType & dest_vn_list() const
Definition: agent_path.h:258
NextHop * nexthop() const
Definition: agent_path.cc:87
const EcmpLoadBalance & ecmp_load_balance() const
Definition: agent_path.h:365
const PathPreference & path_preference() const
Definition: agent_path.h:329
const SecurityGroupList & sg_list() const
Definition: agent_path.h:248
const TagList & tag_list() const
Definition: agent_path.h:249
const CommunityList & communities() const
Definition: agent_path.h:250
virtual const PrefixType & prefix_address() const
Returns the value of a stored prefix address (IPv4, IPv6 or MAC address)
Definition: agent_route.h:389
VrfEntry * vrf_entry() const
Definition: agent_route.cc:459
const std::string & origin_vn_name() const
Definition: agent_route.h:281
const AgentPath * FindIntfOrCompLocalVmPortPath() const
Finds path to an interface or a composite of interfaces and returns it. The priority is given to comp...
Definition: agent_route.cc:817
const AgentPath * GetActivePath() const
Definition: agent_route.cc:877
VrfEntry * vrf() const
Definition: agent_route.h:275
virtual AgentPath * FindPath(const Peer *peer) const
Definition: agent_route.cc:865
const Peer * evpn_routing_peer() const
Definition: agent.h:1029
bool IsDeleted() const
Definition: db_entry.h:49
EvpnRouteEntry * FindRoute(const MacAddress &mac, const IpAddress &ip_addr, uint32_t plen, uint32_t ethernet_tag)
static void DeleteReq(const Peer *peer, const std::string &vrf_name, const MacAddress &mac, const IpAddress &ip_addr, uint32_t plen, uint32_t ethernet_tag, AgentRouteData *data)
uint8_t prefix_length() const
!
static void Delete(const Peer *peer, const string &vrf_name, const IpAddress &addr, uint8_t plen)
InetUnicastRouteEntry * FindLPM(const IpAddress &ip)
void AddEvpnRoutingRouteReq(const IpAddress &ip_addr, uint8_t plen, const VrfEntry *vrf, const Peer *peer, const SecurityGroupList &sg_list, const CommunityList &communities, const PathPreference &path_preference, const EcmpLoadBalance &ecmp_load_balance, const TagList &tag_list, DBRequest &nh_req, uint32_t vxlan_id, const VnListType &vn_list, const std::string &origin_vn="")
static void DeleteReq(const Peer *peer, const string &vrf_name, const IpAddress &addr, uint8_t plen, AgentRouteData *data)
uint8_t prefix_length() const
!
void set_loc_sequence(uint32_t loc_sequence)
Definition: agent_path.h:76
Definition: peer.h:44
@ BGP_PEER
Definition: peer.h:51
uint64_t sequence_number() const
Definition: peer.h:94
const PathList & GetPathList() const
Definition: route.h:46
Definition: vn.h:151
const string & GetName() const
Definition: vn.h:162
const boost::uuids::uuid & logical_router_uuid() const
Definition: vn.h:257
Definition: vrf.h:86
const string & GetName() const
Definition: vrf.h:100
InetUnicastAgentRouteTable * GetInetUnicastRouteTable(const IpAddress &addr) const
Definition: vrf.cc:575
AgentRouteTable * GetEvpnRouteTable() const
Definition: vrf.cc:330
uint32_t vxlan_id() const
Definition: vrf.h:165
VnEntry * vn() const
Definition: vrf.h:101
void DeleteIpamRoutes(const VnEntry *vn, const std::string &vrf_name, const IpAddress &ipam_prefix, const uint32_t plen)
Delete routes to IPAM, specified by IP prefix and prefix length.
bool LeakRoutesIntoBridgeTables(DBTablePartBase *partition, DBEntryBase *e, const boost::uuids::uuid &uuid, const VnEntry *vn, bool update=false)
Performs advertisement and deletion of routing routes (with VrfNH) in bridge VRF instances....
static void CopyInterfacePathToEvpnTable(const AgentPath *path, const IpAddress &prefix_ip, const uint32_t plen, const Peer *peer, const RouteParameters &params, EvpnAgentRouteTable *evpn_table)
Copies the path to the prefix address into the EVPN table with the given Peer. The function is used d...
bool RouteNotify(DBTablePartBase *partition, DBEntryBase *e)
Handler for changes (new/update/delete) in a route (EVPN or Inet). Main entry point for routes leakin...
static bool RoutePrefixIsEqualTo(const EvpnRouteEntry *route, const IpAddress &prefix_ip, const uint32_t prefix_len)
Determines whether route prefix in the EVPN route is equal to the given pair of prefix IP address and...
void ClearRedundantVrfPath(DBEntryBase *e)
Removes redundant VrfNH path from a given route. These routes might arise with small chance in a brid...
static uint32_t loc_sequence_
An always increasing counter for new paths (used to signal controoler about new routes).
static bool IsHostRoute(const IpAddress &prefix_ip, uint32_t prefix_len)
Determines whether the prefix address and the prefix length point to a host route (/32 for IPv4,...
static const AgentPath * FindPathWithGivenPeer(const AgentRoute *inet_rt, const Peer::Type peer_type)
Finds in the given route the path with a specified Peer type.
bool EvpnRouteNotify(DBTablePartBase *partition, DBEntryBase *e)
Performs routes leaking between the EVPN table of the routing VRF instance and the Inet table of the ...
static uint32_t GetNewLocalSequence(const AgentPath *)
Auxilliary functions.
bool WithdrawEvpnRouteFromRoutingVrf(const VrfEntry *routing_vrf, DBTablePartBase *partition, DBEntryBase *e)
Deletes a given EVPN route from EVPN table of the routing VRF instance.
static const Peer * routing_vrf_interface_peer_
Internal data of this class.
static bool IsBridgeVrf(const VrfEntry *vrf)
Determines whether the pointer to the VRF instance is of bridge type.
static const Peer * routing_vrf_vxlan_bgp_peer_
A pointer to the Peer where all BGP routes are stored.
void WhenBridgeInetIntfWasDeleted(const InetUnicastRouteEntry *inet_rt, const VrfEntry *routing_vrf)
Handles deletion of a route in the EVPN table of the routing VRF instance.
bool IsHostRouteFromLocalSubnet(const EvpnRouteEntry *rt)
Determines whether the given EVPN route is a host one and belongs to a subnet of a local bridge VRF....
static bool IsRoutingVrf(const VrfEntry *vrf)
Determines whether the pointer to the VRF instance is of routing type.
Agent * agent_
A pointer to the Agent instance.
void CopyPathToInetTable(const AgentPath *path, const IpAddress &prefix_ip, const uint32_t plen, const Peer *peer, const RouteParameters &params, InetUnicastAgentRouteTable *inet_table)
Copies the path to the prefix address into the EVPN table with the given Peer. The function is used d...
static tbb::mutex mutex_
bool IsVrfLocalRoute(EvpnRouteEntry *routing_evpn_rt, VrfEntry *bridge_vrf)
Determines if the given EVPN route has an interface NH or a composite of interfaces NH that belongs t...
void XmppAdvertiseInetRoute(const IpAddress &prefix_ip, const int prefix_len, uint32_t vxlan_id, const std::string vrf_name, const RouteParameters &params, const Peer *bgp_peer)
Advertises an Inet route received using XMPP channel.
bool InetRouteNotify(DBTablePartBase *partition, DBEntryBase *e)
Routes leaking functions.
VxlanRoutingVrfMapper vrf_mapper_
A map between LR uuids and associated bridge and routing VRF instances.
void WhenRoutingEvpnRouteWasDeleted(const EvpnRouteEntry *routing_evpn_rt, const Peer *delete_from_peer)
Handles deletion of a route in the Inet table of the routing VRF instance.
LrVrfInfoMap lr_vrf_info_map_
The map between Logical router UUID and RoutedVrfInfo.
const VrfEntry * GetRoutingVrfUsingAgentRoute(const AgentRoute *rt)
Find the routing VRF instance using a given route (AgentRoute).
@ DB_ENTRY_ADD_CHANGE
Definition: db_table.h:38
std::unique_ptr< DBRequestKey > key
Definition: db_table.h:48
std::unique_ptr< DBRequestData > data
Definition: db_table.h:49
A structure to hold path parameters during the transfer (routes leaking) of data between VRF instance...
The structure holds information about virtual networks connected to a logical router (LR)
std::set< const VnEntry * > BridgeVnList
A typedef to store the list of bridge virtual networks connected to a LR.
BridgeVnList::iterator BridgeVnListIter
A type for iterator of the list of bridge virtual networks connected to a LR.
BridgeVnList bridge_vn_list_
The list of bridge virtual networks (VirtualNetwork) connected to a LR.
VrfEntry * routing_vrf_
A pointer to the routing VRF instance (L3 VRF) connected to a LR.
boost::uuids::uuid uuid