OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 (local_vm_port_path == NULL) {
98  // If BGPaaS path with interface (or interface/mixed composite) is
99  // found, then it is extracted and copied into EVPN Type5 table
100  local_vm_port_path = FindBGPaaSPath(inet_rt);
101  if (local_vm_port_path != NULL) {
102  AdvertiseBGPaaSRoute(inet_rt->prefix_address(), inet_rt->prefix_length(),
103  local_vm_port_path, evpn_table);
104  return true;
105  }
106  }
107 
108  // if path with LOCAL_VM_PORT hasn't been found, then
109  // this probably may mean that it was deleted
110  if (local_vm_port_path == NULL) {
112  WhenBridgeInetIntfWasDeleted(inet_rt, routing_vrf);
113  return true;
114  }
115 
116  PathPreference preference = local_vm_port_path->path_preference();
117  preference.set_loc_sequence(GetNewLocalSequence(local_vm_port_path));
118  // preference.set_preference(100);
119  VnListType dest_vns;
120  dest_vns.insert(routing_vrf->vn()->GetName());
121 
122  CopyInterfacePathToEvpnTable(local_vm_port_path,
123  inet_rt->prefix_address(),
124  inet_rt->prefix_length(),
125  routing_vrf_interface_peer_, // agent->local_vm_export_peer(),
126  RouteParameters(IpAddress(), // not needed here
127  MacAddress(), // not needed here ?
128  dest_vns,
129  local_vm_port_path->sg_list(),
130  local_vm_port_path->communities(),
131  local_vm_port_path->tag_list(),
132  preference,
133  local_vm_port_path->ecmp_load_balance(),
135  evpn_table);
136 
137  return true;
138 }
139 
140 /*
141  * Step 2.
142  * Copies a route from the routing VRF EVPN Type 5 table into the
143  * routing VRF Inet table.
144  *
145  */
147  DBEntryBase *e) {
148  const EvpnRouteEntry *evpn_rt =
149  dynamic_cast<const EvpnRouteEntry *>(e);
150 
151  if (evpn_rt->IsType5() == false) {
152  return true;
153  }
154 
155  VrfEntry *vrf = evpn_rt->vrf();
156  const AgentPath *local_vm_port_path = evpn_rt->FindPath(
158 
159  const AgentPath *bgp_path =
161 
162  if (bgp_path) {
164  evpn_rt->prefix_length(), vrf->GetName(), bgp_path);
165  }
166 
167  if (local_vm_port_path) {
168  const NextHop *anh = local_vm_port_path->nexthop();
169  if (anh == NULL) {
170  return true;
171  }
172  CopyPathToInetTable(local_vm_port_path,
173  evpn_rt->prefix_address(),
174  evpn_rt->prefix_length(),
177  MacAddress(),
178  local_vm_port_path->dest_vn_list(),
179  local_vm_port_path->sg_list(),
180  local_vm_port_path->communities(),
181  local_vm_port_path->tag_list(),
182  local_vm_port_path->path_preference(),
183  local_vm_port_path->ecmp_load_balance(),
185  vrf->GetInetUnicastRouteTable(evpn_rt->prefix_address()));
186 
187  LeakRoutesIntoBridgeTables(partition,
188  e, vrf->vn()->logical_router_uuid(), NULL, true);
189  }
190 
191  if (bgp_path == NULL) {
192  // the route might be deleted
195  }
196 
197  if (local_vm_port_path == NULL) {
198  // the route might be deleted
201  // and/or it requires publishing in bridge
202  LeakRoutesIntoBridgeTables(partition, e,
203  vrf->vn()->logical_router_uuid(), NULL, true);
204  return true;
205  }
206 
207  return true;
208 }
209 
210 /*
211  *
212  * Routes Deletion
213  *
214  */
216  InetUnicastRouteEntry *inet_route =
217  dynamic_cast<InetUnicastRouteEntry*>(e);
218  if (inet_route == NULL) {
219  return;
220  }
221  if (inet_route->GetPathList().size() > 1 &&
222  inet_route->FindPath(agent_->evpn_routing_peer())) {
224  inet_route->vrf()->GetName(),
225  inet_route->prefix_address(),
226  inet_route->prefix_length());
227  }
228 }
229 
230 /*
231  *
232  * Step 1. If a route is deleted / changed in a bridge VRF INET,
233  * then schedule deletion of a route / path in a routing VRF EVPN
234  * Type 5.
235  *
236  */
237 
239  const InetUnicastRouteEntry *inet_rt,
240  const VrfEntry* routing_vrf) {
241 
242  if (inet_rt->FindPath(agent_->evpn_routing_peer())) {
243  return;
244  }
245 
246  // Check that this route is present in the routing VRF
247  const EvpnAgentRouteTable *evpn_table =
248  dynamic_cast<const EvpnAgentRouteTable *>
249  (routing_vrf->GetEvpnRouteTable());
250  if (evpn_table == NULL) {
251  return;
252  }
253 
254  const EvpnRouteEntry *evpn_rt =
255  const_cast<EvpnAgentRouteTable *>
256  (evpn_table)->FindRoute(MacAddress(),
257  inet_rt->prefix_address(), inet_rt->prefix_length(), 0);
258  if (RoutePrefixIsEqualTo(evpn_rt, inet_rt->prefix_address(), inet_rt->prefix_length()) == false) {
259  if (inet_rt->IsDeleted()) {
260  // That might be an IPAM route from neighb. bridge VRF instances.
261  if (IsHostRoute(inet_rt->prefix_address(), inet_rt->prefix_length()) == false) {
262  DeleteIpamRoutes(inet_rt->vrf()->vn(),
263  inet_rt->vrf()->GetName(),
264  inet_rt->prefix_address(), inet_rt->prefix_length());
265  }
266  }
267  return;
268  }
269 
270  bool ok_to_delete = inet_rt->IsDeleted() ||
272  if (ok_to_delete) {
273  // Delete EVPN Type 5 record in the routing VRF
276  routing_vrf->GetName(),
277  MacAddress(),
278  inet_rt->prefix_address(),
279  inet_rt->prefix_length(),
280  0, // ethernet_tag = 0 for Type5
281  NULL);
282  }
283 }
284 
285 /*
286  *
287  * Step 2. Delete the routing VRF Inet route
288  *
289  */
291  (const EvpnRouteEntry *routing_evpn_rt, const Peer *delete_from_peer) {
292 
293  if (routing_evpn_rt->FindPath(agent_->evpn_routing_peer())) {
294  // Actually, VRF NH Routes are not allowed here
295  return;
296  }
297 
298  VrfEntry *vrf = routing_evpn_rt->vrf();
299  if (vrf == NULL) {
300  return;
301  }
302  InetUnicastAgentRouteTable *routing_inet_table =
303  vrf->GetInetUnicastRouteTable(routing_evpn_rt->prefix_address());
304  if (routing_inet_table == NULL) {
305  return;
306  }
307 
308  // check that the Inet table holds the corresponding route
309  InetUnicastRouteEntry local_vm_route_key(
310  routing_inet_table->vrf_entry(),
311  routing_evpn_rt->prefix_address(),
312  routing_evpn_rt->prefix_length(), false);
313  InetUnicastRouteEntry *inet_rt =
314  dynamic_cast<InetUnicastRouteEntry *>
315  (routing_inet_table->FindLPM(local_vm_route_key));
316  if (RoutePrefixIsEqualTo(inet_rt, routing_evpn_rt->prefix_address(),
317  routing_evpn_rt->prefix_length()) == false) {
318  return;
319  }
320 
321  bool ok_to_delete = routing_evpn_rt->IsDeleted() ||
322  inet_rt->FindPath(delete_from_peer);
323 
324  if (ok_to_delete) {
325  // Delete EVPN Type 5 record in the routing VRF
327  delete_from_peer,
328  vrf->GetName(),
329  routing_evpn_rt->prefix_address(),
330  routing_evpn_rt->prefix_length(),
331  NULL);
332  }
333 }
334 
336  const VrfEntry *routing_vrf,
337  DBTablePartBase *partition, DBEntryBase *e) {
338 
339  EvpnRouteEntry *evpn_rt = dynamic_cast<EvpnRouteEntry *>(e);
340 
341  if (!routing_vrf || !routing_vrf->GetEvpnRouteTable() || !evpn_rt) {
342  return true;
343  }
344  EvpnAgentRouteTable *routing_evpn = static_cast<EvpnAgentRouteTable*>(
345  routing_vrf->GetEvpnRouteTable());
346  const EvpnRouteEntry *rt_route = routing_evpn->FindRoute(
347  MacAddress(), evpn_rt->prefix_address(), evpn_rt->prefix_length(), 0);
348  if (RoutePrefixIsEqualTo(rt_route, evpn_rt->prefix_address(),
349  evpn_rt->prefix_length())) {
350  // Remove deleted EVPN Type 5 record in the routing VRF
353  routing_vrf->GetName(),
354  MacAddress(),
355  evpn_rt->prefix_address(),
356  evpn_rt->prefix_length(),
357  0, // ethernet_tag = 0 for Type5
358  NULL);
359  }
360  return true;
361 }
362 
365  const VnEntry *vn, bool update) {
366 
367  EvpnRouteEntry *evpn_rt = dynamic_cast<EvpnRouteEntry *>(e);
368  if (!evpn_rt || (evpn_rt->vrf()->vn() == NULL) || (!evpn_rt->IsType5()))
369  return true;
370  if (uuid == boost::uuids::nil_uuid())
371  return true;
372  // Only non-local non-/32 and non-/128 routes are
373  // copied to bridge vrfs
374  if (IsHostRouteFromLocalSubnet(evpn_rt)) { //IsLocalSubnetHostRoute
375  return true;
376  }
377 
379  vrf_mapper_.lr_vrf_info_map_[uuid];
382  if (update && vn != NULL) {
383  update_bridge_vn_list.insert(vn);
384  it = update_bridge_vn_list.find(vn);
385  } else {
386  update_bridge_vn_list = lr_vrf_info.bridge_vn_list_;
387  it = update_bridge_vn_list.begin();
388  }
389  while (it != update_bridge_vn_list.end()) {
390  VrfEntry *bridge_vrf = (*it)->GetVrf();
391 
392  if (bridge_vrf == NULL) {
393  it++;
394  continue;
395  }
396 
397  if (IsVrfLocalRoute(evpn_rt, bridge_vrf)) {
398  it++;
399  continue;
400  }
401 
402  InetUnicastAgentRouteTable *inet_table =
403  bridge_vrf->GetInetUnicastRouteTable(evpn_rt->prefix_address());
404 
405  if (evpn_rt->IsDeleted()) {
406  InetUnicastAgentRouteTable::DeleteReq(agent_->evpn_routing_peer(),
407  bridge_vrf->GetName(),
408  evpn_rt->prefix_address(),
409  evpn_rt->prefix_length(),
410  NULL);
411  } else {
412  const AgentPath *p = evpn_rt->GetActivePath();
413  const VrfEntry *routing_vrf = lr_vrf_info.routing_vrf_;
414  // Now all interface routes in routing vrf have BGP_PEER copies
415  if (routing_vrf == NULL) {
416  return true;
417  }
418 
420  nh_req.key.reset(new VrfNHKey(routing_vrf->GetName(), false, false));
421  nh_req.data.reset(new VrfNHData(false, false, false));
422  inet_table->AddEvpnRoutingRoute(evpn_rt->prefix_address(),
423  evpn_rt->prefix_length(),
424  bridge_vrf,
425  agent_->evpn_routing_peer(),
426  p->sg_list(),
427  p->communities(),
428  p->path_preference(),
429  p->ecmp_load_balance(),
430  p->tag_list(),
431  nh_req,
432  routing_vrf->vxlan_id(),
433  p->dest_vn_list());
434  }
435  it++;
436  }
437  return true;
438 }
439 
440 //
441 //END-OF-FILE
442 //
443 
uint8_t prefix_length() const
!
EvpnRouteEntry * FindRoute(const MacAddress &mac, const IpAddress &ip_addr, uint32_t plen, uint32_t ethernet_tag)
const VnListType & dest_vn_list() const
Definition: agent_path.h:258
static tbb::mutex mutex_
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...
Definition: vrf.h:86
const TagList & tag_list() const
Definition: agent_path.h:249
const PathPreference & path_preference() const
Definition: agent_path.h:329
InetUnicastRouteEntry * FindLPM(const IpAddress &ip)
AgentRouteTable * GetEvpnRouteTable() const
Definition: vrf.cc:330
static bool IsBridgeVrf(const VrfEntry *vrf)
Determines whether the pointer to the VRF instance is of bridge type.
const AgentPath * FindBGPaaSPath(const InetUnicastRouteEntry *rt)
Finds in the given route the path that was announced using BGPaaS. It is expected that this path has ...
std::set< const VnEntry * > BridgeVnList
A typedef to store the list of bridge virtual networks connected to a LR.
void WhenBridgeInetIntfWasDeleted(const InetUnicastRouteEntry *inet_rt, const VrfEntry *routing_vrf)
Handles deletion of a route in the EVPN table of the routing VRF instance.
BridgeVnList bridge_vn_list_
The list of bridge virtual networks (VirtualNetwork) connected to a LR.
bool IsDeleted() const
Definition: db_entry.h:49
boost::asio::ip::address IpAddress
Definition: address.h:13
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)
std::unique_ptr< DBRequestData > data
Definition: db_table.h:49
bool WithdrawEvpnRouteFromRoutingVrf(const VrfEntry *routing_vrf, DBTablePartBase *partition, DBEntryBase *e)
Deletes a given EVPN route from EVPN table of the routing VRF instance.
boost::uuids::uuid uuid
void set_loc_sequence(uint32_t loc_sequence)
Definition: agent_path.h:76
const VrfEntry * GetRoutingVrfUsingAgentRoute(const AgentRoute *rt)
Find the routing VRF instance using a given route (AgentRoute).
const string & GetName() const
Definition: vrf.h:100
A structure to hold path parameters during the transfer (routes leaking) of data between VRF instance...
const VrfEntry * routing_vrf_
A pointer to the routing VRF instance (L3 VRF) connected to a LR.
void AdvertiseBGPaaSRoute(const IpAddress &prefix_ip, uint32_t prefix_len, const AgentPath *path, EvpnAgentRouteTable *evpn_table)
Advertises BGPaaS interface path in the routing VRF instance by selecting corresponding path componen...
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 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...
const AgentPath * GetActivePath() const
Definition: agent_route.cc:876
NextHop * nexthop() const
Definition: agent_path.cc:87
VrfEntry * vrf_entry() const
Definition: agent_route.cc:459
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.
Agent * agent_
A pointer to the Agent instance.
void ClearRedundantVrfPath(DBEntryBase *e)
Removes redundant VrfNH path from a given route. These routes might arise with small chance in a brid...
void AddEvpnRoutingRoute(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 Delete(const Peer *peer, const string &vrf_name, const IpAddress &addr, uint8_t plen)
static bool IsRoutingVrf(const VrfEntry *vrf)
Determines whether the pointer to the VRF instance is of routing type.
static uint32_t GetNewLocalSequence(const AgentPath *)
Auxilliary functions.
bool RouteNotify(DBTablePartBase *partition, DBEntryBase *e)
Handler for changes (new/update/delete) in a route (EVPN or Inet). Main entry point for routes leakin...
InetUnicastAgentRouteTable * GetInetUnicastRouteTable(const IpAddress &addr) const
Definition: vrf.cc:575
std::unique_ptr< DBRequestKey > key
Definition: db_table.h:48
uint64_t sequence_number() const
Definition: peer.h:94
static uint32_t loc_sequence_
An always increasing counter for new paths (used to signal controoler about new routes).
Definition: peer.h:44
std::set< std::string > VnListType
Definition: agent.h:212
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 void DeleteReq(const Peer *peer, const string &vrf_name, const IpAddress &addr, uint8_t plen, AgentRouteData *data)
virtual const PrefixType & prefix_address() const
Returns the value of a stored prefix address (IPv4, IPv6 or MAC address)
Definition: agent_route.h:375
Definition: vn.h:151
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:816
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...
const boost::uuids::uuid & logical_router_uuid() const
Definition: vn.h:256
uint8_t prefix_length() const
!
uint32_t vxlan_id() const
Definition: vrf.h:165
VxlanRoutingVrfMapper vrf_mapper_
A map between LR uuids and associated bridge and routing VRF instances.
VnEntry * vn() const
Definition: vrf.h:101
VrfEntry * vrf() const
Definition: agent_route.h:275
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.
bool InetRouteNotify(DBTablePartBase *partition, DBEntryBase *e)
Routes leaking functions.
The structure holds information about virtual networks connected to a logical router (LR) ...
const string & GetName() const
Definition: vn.h:162
BridgeVnList::iterator BridgeVnListIter
A type for iterator of the list of bridge virtual networks connected to a LR.
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.
static const Peer * routing_vrf_interface_peer_
Internal data of this class.
virtual AgentPath * FindPath(const Peer *peer) const
Definition: agent_route.cc:864
const CommunityList & communities() const
Definition: agent_path.h:250
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. External tunnels and routes with a prefix that is not present in bridge VRF instance are selected for leaking.
static const Peer * routing_vrf_vxlan_bgp_peer_
A pointer to the Peer where all BGP routes are stored.
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.
const SecurityGroupList & sg_list() const
Definition: agent_path.h:248
const EcmpLoadBalance & ecmp_load_balance() const
Definition: agent_path.h:365
const Peer * evpn_routing_peer() const
Definition: agent.h:1027
const PathList & GetPathList() const
Definition: route.h:46