Line data Source code
1 : /*
2 : * Copyright (c) 2018 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #include <oper/operdb_init.h>
7 : #include <oper/route_common.h>
8 : #include <oper/vrf.h>
9 : #include <oper/bridge_route.h>
10 : #include <oper/inet_unicast_route.h>
11 : #include <oper/evpn_route.h>
12 : #include <oper/agent_route.h>
13 : #include <oper/vn.h>
14 : #include <oper/vrf.h>
15 : #include <controller/controller_route_path.h>
16 : #include <oper/vxlan_routing_manager.h>
17 : #include <oper/tunnel_nh.h>
18 : #include <oper/bgp_as_service.h>
19 :
20 : template<class RouteTable, class RouteEntry>
21 : static const AgentPath *LocalVmExportInterface(Agent* agent,
22 : RouteTable *table, RouteEntry *route);
23 :
24 0 : TunnelNHKey* VxlanRoutingManager::AllocateTunnelNextHopKey(
25 : const IpAddress& dip, const MacAddress& dmac) const {
26 :
27 0 : const Ip4Address rtr_dip = dip.to_v4();
28 :
29 0 : const std::vector<IpAddress> nh_addresses(1, dip);
30 0 : bool is_zero_mac = dmac.IsZero();
31 :
32 0 : MacAddress rtr_dmac;
33 0 : if (!is_zero_mac) {
34 0 : rtr_dmac = dmac;
35 : } else {
36 0 : rtr_dmac = NbComputeMac(rtr_dip, agent_);
37 : }
38 :
39 0 : TunnelNHKey *tun_nh_key = new TunnelNHKey(agent_->fabric_vrf_name(),
40 0 : agent_->router_id(),
41 : rtr_dip,
42 : false,
43 0 : TunnelType(TunnelType::VXLAN),
44 0 : rtr_dmac);
45 0 : return tun_nh_key;
46 0 : }
47 :
48 0 : void VxlanRoutingManager::XmppAdvertiseEvpnRoute(const IpAddress& prefix_ip,
49 : const int prefix_len, uint32_t vxlan_id, const std::string vrf_name,
50 : const RouteParameters& params, const Peer *bgp_peer,
51 : const std::vector<std::string> &peer_sources) {
52 0 : VrfEntry* vrf = agent_->vrf_table()->FindVrfFromName(vrf_name);
53 : EvpnAgentRouteTable *evpn_table =
54 0 : dynamic_cast<EvpnAgentRouteTable*>(vrf->GetEvpnRouteTable());
55 0 : if (evpn_table == NULL) {
56 0 : return;
57 : }
58 :
59 : // If route is a tunnel
60 0 : if (agent_->router_id() != params.nh_addr_.to_v4()) {
61 0 : XmppAdvertiseEvpnTunnel(evpn_table,
62 : prefix_ip, prefix_len, vxlan_id, vrf_name, params, bgp_peer);
63 0 : return;
64 : }
65 :
66 : // Or this is an interface
67 0 : XmppAdvertiseEvpnInterface(evpn_table,
68 : prefix_ip, prefix_len, vxlan_id, vrf_name, params, bgp_peer, peer_sources);
69 : }
70 :
71 0 : void VxlanRoutingManager::XmppAdvertiseInetRoute(const IpAddress& prefix_ip,
72 : const int prefix_len, const std::string vrf_name,
73 : const AgentPath* path) {
74 :
75 0 : VrfEntry* vrf = agent_->vrf_table()->FindVrfFromName(vrf_name);
76 : InetUnicastAgentRouteTable *inet_table =
77 0 : vrf->GetInetUnicastRouteTable(prefix_ip);
78 :
79 0 : if (path->nexthop() && path->nexthop()->GetType() ==
80 : NextHop::TUNNEL) {
81 0 : XmppAdvertiseInetTunnel(inet_table,
82 : prefix_ip, prefix_len, vrf_name, path);
83 0 : return;
84 : }
85 :
86 0 : if (path->nexthop() &&
87 0 : (path->nexthop()->GetType() == NextHop::INTERFACE ||
88 0 : path->nexthop()->GetType() == NextHop::COMPOSITE)) {
89 0 : XmppAdvertiseInetInterfaceOrComposite(inet_table,
90 : prefix_ip, prefix_len, vrf_name, path);
91 : }
92 : }
93 :
94 0 : void VxlanRoutingManager::XmppAdvertiseEvpnTunnel(
95 : EvpnAgentRouteTable *evpn_table, const IpAddress& prefix_ip,
96 : const int prefix_len, uint32_t vxlan_id, const std::string vrf_name,
97 : const RouteParameters& params, const Peer *peer
98 : ) {
99 0 : const BgpPeer *bgp_peer = dynamic_cast<const BgpPeer*>(peer);
100 0 : if (bgp_peer == NULL) {
101 0 : return;
102 : }
103 0 : DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
104 : std::unique_ptr<TunnelNHKey> tun_nh_key (AllocateTunnelNextHopKey(
105 0 : params.nh_addr_, params.nh_mac_));
106 :
107 : ControllerVmRoute *data =
108 0 : ControllerVmRoute::MakeControllerVmRoute(dynamic_cast<const BgpPeer*>(bgp_peer),
109 0 : agent_->fabric_vrf_name(),
110 0 : agent_->router_id(),
111 : vrf_name,
112 : tun_nh_key->dip(),
113 : TunnelType::VxlanType(),
114 : vxlan_id,
115 : tun_nh_key->rewrite_dmac(),
116 : params.vn_list_,
117 : params.sg_list_,
118 : params.tag_list_,
119 : params.path_preference_,
120 : true,
121 0 : EcmpLoadBalance(),
122 : false);
123 0 : evpn_table->AddRemoteVmRouteReq(bgp_peer,
124 : vrf_name,
125 0 : MacAddress(),
126 : prefix_ip,
127 : prefix_len,
128 : 0, // ethernet_tag is zero for Type5
129 : data);
130 0 : }
131 :
132 0 : void VxlanRoutingManager::XmppAdvertiseEvpnBgpaasInterface(
133 : EvpnAgentRouteTable *evpn_table, const IpAddress& prefix_ip,
134 : const int prefix_len, uint32_t vxlan_id, const std::string vrf_name,
135 : const RouteParameters& params, const Peer *bgp_peer, const NextHop *nh
136 : ) {
137 0 : const InterfaceNH *intf_nh = dynamic_cast<const InterfaceNH *>(nh);
138 0 : const Interface *intf = intf_nh->GetInterface();
139 0 : if (intf->type() != Interface::VM_INTERFACE) {
140 0 : return;
141 : }
142 0 : const VmInterface *vm_intf = dynamic_cast<const VmInterface*>
143 0 : (intf);
144 0 : DBEntryBase::KeyPtr tintf_key_ptr = vm_intf->GetDBRequestKey();
145 : const VmInterfaceKey* intf_key_ptr =
146 0 : dynamic_cast<const VmInterfaceKey *>(tintf_key_ptr.get());
147 :
148 : LocalVmRoute *loc_rt_ptr = new LocalVmRoute(
149 : *intf_key_ptr,
150 : MplsTable::kInvalidLabel, // mpls_label
151 : vxlan_id,
152 : false,
153 : params.vn_list_,
154 0 : intf_nh->GetFlags(), // flags
155 : params.sg_list_,
156 : params.tag_list_,
157 : params.communities_,
158 : params.path_preference_,
159 0 : Ip4Address(0),
160 : params.ecmp_load_balance_,
161 : false,
162 : false,
163 0 : params.sequence_number_,
164 : false,
165 0 : false); // native_encap
166 0 : loc_rt_ptr->set_tunnel_bmap(TunnelType::VxlanType());
167 :
168 : {
169 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
170 :
171 0 : req.key.reset(new EvpnRouteKey(bgp_peer,
172 0 : evpn_table->vrf_entry()->GetName(),
173 0 : MacAddress(),
174 : prefix_ip,
175 : prefix_len,
176 0 : 0));
177 0 : req.data.reset(loc_rt_ptr);
178 0 : evpn_table->Enqueue(&req);
179 0 : }
180 0 : }
181 :
182 0 : void VxlanRoutingManager::XmppAdvertiseEvpnBgpaasComposite(
183 : EvpnAgentRouteTable *evpn_table, const IpAddress& prefix_ip,
184 : const int prefix_len, uint32_t vxlan_id, const std::string vrf_name,
185 : const RouteParameters& params, const Peer *bgp_peer,
186 : ComponentNHKeyList &comp_nh_list ) {
187 0 : DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
188 0 : const bool comp_nh_policy = true;
189 : CompositeNHKey *new_comp_nh_key =
190 : new CompositeNHKey(Composite::LOCAL_ECMP,
191 0 : comp_nh_policy, comp_nh_list, vrf_name);
192 :
193 0 : nh_req.key.reset(new_comp_nh_key);
194 0 : nh_req.data.reset(new CompositeNHData());
195 0 : const BgpPeer *bgp_peer_ecmp = dynamic_cast<const BgpPeer*>(bgp_peer);
196 0 : std::stringstream prefix_str;
197 0 : prefix_str << prefix_ip.to_string();
198 0 : prefix_str << "/";
199 0 : prefix_str << prefix_len;
200 :
201 : ControllerEcmpRoute *rt_data = new ControllerEcmpRoute(
202 : bgp_peer_ecmp,
203 : params.vn_list_,
204 : params.ecmp_load_balance_,
205 : params.tag_list_,
206 : params.sg_list_,
207 : params.path_preference_,
208 0 : TunnelType::VxlanType(),
209 : nh_req,
210 0 : prefix_str.str(),
211 0 : evpn_table->vrf_name());
212 :
213 : ControllerEcmpRoute::ClonedLocalPathListIter iter =
214 0 : rt_data->cloned_local_path_list().begin();
215 0 : while (iter != rt_data->cloned_local_path_list().end()) {
216 0 : evpn_table->AddClonedLocalPathReq(bgp_peer_ecmp, vrf_name,
217 0 : MacAddress(), prefix_ip, 0, (*iter));
218 0 : iter++;
219 : }
220 :
221 0 : evpn_table->AddRemoteVmRouteReq(bgp_peer_ecmp,
222 0 : vrf_name, MacAddress(),
223 : prefix_ip,
224 : prefix_len,
225 : 0, // ethernet tag is 0 for VxLAN
226 : rt_data);
227 0 : }
228 :
229 0 : void VxlanRoutingManager::XmppAdvertiseEvpnBgpaas(
230 : EvpnAgentRouteTable *evpn_table, const IpAddress& prefix_ip,
231 : const int prefix_len, uint32_t vxlan_id, const std::string vrf_name,
232 : const RouteParameters& params, const Peer *bgp_peer,
233 : const std::vector<std::string> &peer_sources
234 : ) {
235 0 : const NextHop *first_intf_nh = nullptr;
236 0 : NextHopKey *nh_key = nullptr;
237 : // Create a new composite
238 0 : ComponentNHKeyList new_comp_nh_list;
239 0 : for (auto &nexthop_addr : peer_sources) {
240 0 : IpAddress nh_ip;
241 0 : boost::system::error_code ec;
242 : int nh_ip_len;
243 0 : if (is_ipv4_string(nexthop_addr)) {
244 0 : nh_ip = Ip4Address::from_string(ipv4_prefix(nexthop_addr), ec);
245 0 : nh_ip_len = ipv4_prefix_len(nexthop_addr);
246 0 : } else if (is_ipv6_string(nexthop_addr)) {
247 0 : nh_ip = Ip6Address::from_string(ipv6_prefix(nexthop_addr), ec);
248 0 : nh_ip_len = ipv6_prefix_len(nexthop_addr);
249 : } else {
250 0 : LOG(ERROR, "Error in VxlanRoutingManager::AddInterfaceComponentToList"
251 : << ", nexthop_addr = " << nexthop_addr
252 : << " is not an IPv4 or IPv6 prefix");
253 0 : return;
254 : }
255 0 : if (ec) {
256 0 : continue;
257 : }
258 0 : EvpnRouteEntry *route =evpn_table->FindRoute(MacAddress(),
259 : nh_ip, nh_ip_len, 0);
260 : const AgentPath *loc_path =
261 0 : LocalVmExportInterface(agent_, evpn_table, route);
262 0 : if (loc_path == nullptr) {
263 0 : continue;
264 : }
265 0 : if (loc_path->nexthop() == nullptr) {
266 0 : continue;
267 : }
268 0 : if (IsBgpaasInterfaceNexthop(agent_, loc_path->nexthop())) {
269 0 : if (first_intf_nh == NULL) {
270 0 : first_intf_nh = loc_path->nexthop();
271 : }
272 0 : DBEntryBase::KeyPtr key = loc_path->nexthop()->
273 0 : GetDBRequestKey();
274 0 : nh_key = static_cast<NextHopKey *>(key.release());
275 :
276 0 : std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
277 : ComponentNHKeyPtr component_nh_key(new ComponentNHKey(
278 0 : MplsTable::kInvalidLabel, std::move(nh_key_ptr)));
279 0 : new_comp_nh_list.push_back(component_nh_key);
280 0 : } else if (IsBgpaasCompositeNexthop(agent_, loc_path->nexthop())) {
281 0 : const CompositeNH *composite_nh = dynamic_cast<const CompositeNH*>(
282 0 : loc_path->nexthop());
283 0 : const ComponentNHList &components = composite_nh->component_nh_list();
284 0 : for (auto &component : components) {
285 0 : if (component.get() &&
286 0 : component->nh() &&
287 0 : component->nh()->GetType() == NextHop::INTERFACE) {
288 0 : if (first_intf_nh == nullptr) {
289 0 : first_intf_nh = component->nh();
290 : }
291 0 : DBEntryBase::KeyPtr key = component->nh()->
292 0 : GetDBRequestKey();
293 0 : nh_key = static_cast<NextHopKey *>(key.release());
294 :
295 0 : std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
296 : ComponentNHKeyPtr component_nh_key(new ComponentNHKey(
297 0 : MplsTable::kInvalidLabel, std::move(nh_key_ptr)));
298 0 : new_comp_nh_list.push_back(component_nh_key);
299 0 : }
300 : }
301 : }
302 : }
303 :
304 0 : if (new_comp_nh_list.size() < 1) {
305 0 : return;
306 0 : } else if (new_comp_nh_list.size() == 1) {
307 0 : XmppAdvertiseEvpnBgpaasInterface(evpn_table, prefix_ip, prefix_len,
308 : vxlan_id, vrf_name, params, bgp_peer, first_intf_nh);
309 : } else {
310 0 : XmppAdvertiseEvpnBgpaasComposite(evpn_table, prefix_ip, prefix_len,
311 : vxlan_id, vrf_name, params, bgp_peer, new_comp_nh_list);
312 : }
313 :
314 0 : }
315 :
316 0 : void VxlanRoutingManager::XmppAdvertiseEvpnInterface(
317 : EvpnAgentRouteTable *evpn_table, const IpAddress& prefix_ip,
318 : const int prefix_len, uint32_t vxlan_id, const std::string vrf_name,
319 : const RouteParameters& params, const Peer *bgp_peer,
320 : const std::vector<std::string> &peer_sources ) {
321 0 : EvpnRouteEntry *route = evpn_table->FindRoute(MacAddress(),
322 : prefix_ip, prefix_len, 0);
323 0 : if (RoutePrefixIsEqualTo(route, prefix_ip, prefix_len) == false) {
324 0 : XmppAdvertiseEvpnBgpaas(evpn_table, prefix_ip, prefix_len, vxlan_id,
325 : vrf_name, params, bgp_peer, peer_sources);
326 0 : return;
327 : }
328 : const AgentPath * path =
329 0 : LocalVmExportInterface(agent_, evpn_table, route);
330 :
331 0 : if (!path ) {
332 0 : XmppAdvertiseEvpnBgpaas(evpn_table, prefix_ip, prefix_len, vxlan_id,
333 : vrf_name, params, bgp_peer, peer_sources);
334 0 : return;
335 : }
336 :
337 0 : CopyInterfacePathToEvpnTable(path,
338 : prefix_ip,
339 : prefix_len,
340 : bgp_peer,
341 0 : RouteParameters(IpAddress(), // NH address, not needed here
342 0 : MacAddress(),
343 : params.vn_list_,
344 : params.sg_list_,
345 : params.communities_,
346 : params.tag_list_,
347 : params.path_preference_,
348 : params.ecmp_load_balance_,
349 0 : params.sequence_number_),
350 : evpn_table);
351 : }
352 :
353 0 : void VxlanRoutingManager::XmppAdvertiseInetTunnel(
354 : InetUnicastAgentRouteTable *inet_table, const IpAddress& prefix_ip,
355 : const int prefix_len, const std::string vrf_name,
356 : const AgentPath* path) {
357 :
358 0 : DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
359 0 : TunnelNH *tun_nh = dynamic_cast<TunnelNH*>(path->nexthop());
360 :
361 0 : TunnelNHKey *tun_nh_key = AllocateTunnelNextHopKey(*(tun_nh->GetDip()),
362 : tun_nh->rewrite_dmac());
363 0 : std::string origin_vn = "";
364 :
365 0 : nh_req.key.reset(tun_nh_key);
366 0 : nh_req.data.reset(new TunnelNHData);
367 :
368 0 : inet_table->AddEvpnRoutingRoute(prefix_ip,
369 : prefix_len,
370 0 : inet_table->vrf_entry(),
371 : routing_vrf_vxlan_bgp_peer_,
372 : path->sg_list(),
373 : path->communities(),
374 : path->path_preference(),
375 : path->ecmp_load_balance(),
376 : path->tag_list(),
377 : nh_req,
378 : path->vxlan_id(),
379 : path->dest_vn_list(),
380 : origin_vn);
381 0 : }
382 :
383 0 : void VxlanRoutingManager::XmppAdvertiseInetInterfaceOrComposite(
384 : InetUnicastAgentRouteTable *inet_table, const IpAddress& prefix_ip,
385 : const int prefix_len, const std::string vrf_name,
386 : const AgentPath* path) {
387 :
388 0 : CopyPathToInetTable(path,
389 : prefix_ip,
390 : prefix_len,
391 : routing_vrf_vxlan_bgp_peer_,
392 0 : RouteParameters(IpAddress(),
393 0 : MacAddress(),
394 : path->dest_vn_list(),
395 : path->sg_list(),
396 : path->communities(),
397 : path->tag_list(),
398 : path->path_preference(),
399 : path->ecmp_load_balance(),
400 : path->peer_sequence_number()),
401 : inet_table);
402 0 : }
403 :
404 : template<class RouteTable, class RouteEntry>
405 0 : static const AgentPath *LocalVmExportInterface(Agent* agent,
406 : RouteTable *table, RouteEntry *route) {
407 0 : if (table == NULL || agent == NULL || route == NULL) {
408 0 : return NULL;
409 : }
410 :
411 0 : const AgentPath *tm_path = NULL;
412 0 : const AgentPath *rt_path = NULL;
413 :
414 0 : for (Route::PathList::const_iterator it =
415 0 : route->GetPathList().begin();
416 0 : it != route->GetPathList().end(); it++) {
417 : tm_path =
418 0 : static_cast<const AgentPath *>(it.operator->());
419 0 : if (tm_path == NULL || tm_path->peer() == NULL) {
420 0 : continue;
421 : }
422 0 : if (tm_path->peer()->GetType() ==
423 0 : agent->local_vm_export_peer()->GetType()) {
424 0 : if (tm_path->nexthop() &&
425 0 : tm_path->nexthop()->GetType() == NextHop::INTERFACE) {
426 0 : rt_path = tm_path;
427 0 : } else if (tm_path->nexthop() &&
428 0 : tm_path->nexthop()->GetType() == NextHop::COMPOSITE) {
429 0 : return tm_path;
430 : }
431 : }
432 : }
433 0 : return rt_path;
434 : }
435 :
436 : //
437 : //END-OF-FILE
438 : //
439 :
|