Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #include <boost/uuid/uuid_io.hpp>
7 :
8 : #include <cmn/agent_cmn.h>
9 : #include <route/route.h>
10 :
11 : #include <oper/ecmp_load_balance.h>
12 : #include <oper/route_common.h>
13 : #include <oper/vrf.h>
14 : #include <oper/tunnel_nh.h>
15 : #include <oper/mpls.h>
16 : #include <oper/mirror_table.h>
17 : #include <controller/controller_export.h>
18 : #include <controller/controller_peer.h>
19 : #include <controller/controller_route_path.h>
20 : #include <oper/agent_sandesh.h>
21 : #include <pkt/pkt_init.h>
22 : #include <pkt/pkt_handler.h>
23 :
24 : using namespace std;
25 : using namespace boost::asio;
26 :
27 : /////////////////////////////////////////////////////////////////////////////
28 : // Utility functions
29 : /////////////////////////////////////////////////////////////////////////////
30 13 : static void EvpnTableEnqueue(Agent *agent, DBRequest *req) {
31 13 : AgentRouteTable *table = agent->fabric_evpn_table();
32 13 : if (table) {
33 13 : table->Enqueue(req);
34 : }
35 13 : }
36 :
37 1991 : static void EvpnTableProcess(Agent *agent, const string &vrf_name,
38 : DBRequest &req) {
39 : AgentRouteTable *table =
40 1991 : agent->vrf_table()->GetEvpnRouteTable(vrf_name);
41 1991 : if (table) {
42 1991 : table->Process(req);
43 : }
44 1991 : }
45 :
46 : /////////////////////////////////////////////////////////////////////////////
47 : // EvpnRouteKey methods
48 : /////////////////////////////////////////////////////////////////////////////
49 0 : string EvpnRouteKey::ToString() const {
50 0 : std::stringstream str;
51 0 : str << ethernet_tag_;
52 0 : str << "-";
53 0 : str << dmac_.ToString();
54 0 : str << "-";
55 0 : str << ip_addr_.to_string();
56 0 : return str.str();
57 0 : }
58 :
59 241 : EvpnRouteKey *EvpnRouteKey::Clone() const {
60 241 : return new EvpnRouteKey(peer(), vrf_name_, dmac_, ip_addr_,
61 241 : plen_, ethernet_tag_);
62 : }
63 :
64 : AgentRoute *
65 3223 : EvpnRouteKey::AllocRouteEntry(VrfEntry *vrf, bool is_multicast) const
66 : {
67 3223 : EvpnRouteEntry *entry = new EvpnRouteEntry(vrf, dmac_, ip_addr_, plen_,
68 3223 : ethernet_tag_, is_multicast);
69 3223 : return static_cast<AgentRoute *>(entry);
70 : }
71 :
72 : /////////////////////////////////////////////////////////////////////////////
73 : // EvpnAgentRouteTable methods
74 : /////////////////////////////////////////////////////////////////////////////
75 74 : DBTableBase *EvpnAgentRouteTable::CreateTable(DB *db,
76 : const std::string &name) {
77 74 : AgentRouteTable *table = new EvpnAgentRouteTable(db, name);
78 74 : table->Init();
79 74 : return table;
80 : }
81 :
82 0 : EvpnRouteEntry *EvpnAgentRouteTable::FindRoute(const MacAddress &mac,
83 : const IpAddress &ip_addr,
84 : uint32_t plen,
85 : uint32_t ethernet_tag) {
86 0 : EvpnRouteKey key(NULL, vrf_name(), mac, ip_addr, plen, ethernet_tag);
87 : EvpnRouteEntry *route =
88 0 : static_cast<EvpnRouteEntry *>(FindActiveEntry(&key));
89 0 : return route;
90 0 : }
91 :
92 27 : EvpnRouteEntry *EvpnAgentRouteTable::FindRouteNoLock(const MacAddress &mac,
93 : const IpAddress &ip_addr,
94 : uint32_t plen,
95 : uint32_t ethernet_tag) {
96 27 : EvpnRouteKey key(NULL, vrf_name(), mac, ip_addr, plen, ethernet_tag);
97 : EvpnRouteEntry *route =
98 27 : static_cast<EvpnRouteEntry *>(FindActiveEntryNoLock(&key));
99 27 : return route;
100 27 : }
101 :
102 0 : EvpnRouteEntry *EvpnAgentRouteTable::FindRoute(const Agent *agent,
103 : const string &vrf_name,
104 : const MacAddress &mac,
105 : const IpAddress &ip_addr,
106 : uint32_t plen,
107 : uint32_t ethernet_tag) {
108 0 : VrfEntry *vrf = agent->vrf_table()->FindVrfFromName(vrf_name);
109 0 : if (vrf == NULL)
110 0 : return NULL;
111 :
112 : EvpnAgentRouteTable *table = static_cast<EvpnAgentRouteTable *>
113 0 : (vrf->GetEvpnRouteTable());
114 0 : return table->FindRoute(mac, ip_addr, plen, ethernet_tag);
115 : }
116 :
117 : /////////////////////////////////////////////////////////////////////////////
118 : // EvpnAgentRouteTable utility methods to add/delete routes
119 : /////////////////////////////////////////////////////////////////////////////
120 0 : void EvpnAgentRouteTable::AddOvsPeerMulticastRouteInternal(const Peer *peer,
121 : uint32_t vxlan_id,
122 : const std::string &vn_name,
123 : Ip4Address tsn,
124 : Ip4Address tor_ip,
125 : bool enqueue,
126 : bool ha_stale) {
127 0 : const VrfEntry *vrf = vrf_entry();
128 0 : DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
129 0 : nh_req.key.reset(new TunnelNHKey(vrf->GetName(), tsn, tor_ip,
130 0 : false, TunnelType::VXLAN));
131 0 : nh_req.data.reset(new TunnelNHData());
132 :
133 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
134 0 : req.key.reset(new EvpnRouteKey(peer,
135 0 : vrf->GetName(),
136 0 : MacAddress::BroadcastMac(),
137 : tor_ip,
138 0 : EvpnAgentRouteTable::ComputeHostIpPlen(tor_ip),
139 0 : vxlan_id));
140 0 : req.data.reset(new MulticastRoute(vn_name, 0, vxlan_id,
141 0 : TunnelType::VxlanType(),
142 : nh_req, Composite::L2COMP,
143 0 : peer->sequence_number(),
144 0 : ha_stale));
145 0 : if (enqueue) {
146 0 : EvpnTableEnqueue(agent(), &req);
147 : } else {
148 0 : EvpnTableProcess(agent(), vrf_name(), req);
149 : }
150 0 : }
151 :
152 0 : void EvpnAgentRouteTable::AddOvsPeerMulticastRoute(const Peer *peer,
153 : uint32_t vxlan_id,
154 : const std::string &vn_name,
155 : Ip4Address tsn,
156 : Ip4Address tor_ip,
157 : bool ha_stale) {
158 0 : AddOvsPeerMulticastRouteInternal(peer, vxlan_id, vn_name, tsn, tor_ip,
159 : false, ha_stale);
160 0 : }
161 :
162 0 : void EvpnAgentRouteTable::AddOvsPeerMulticastRouteReq(const Peer *peer,
163 : uint32_t vxlan_id,
164 : const std::string &vn_name,
165 : Ip4Address tsn,
166 : Ip4Address tor_ip) {
167 0 : AddOvsPeerMulticastRouteInternal(peer, vxlan_id, vn_name, tsn, tor_ip, true,
168 : false);
169 0 : }
170 :
171 0 : void EvpnAgentRouteTable::AddControllerReceiveRouteReq(const Peer *peer,
172 : const string &vrf_name,
173 : uint32_t label,
174 : const MacAddress &mac,
175 : const IpAddress &ip_addr,
176 : uint32_t ethernet_tag,
177 : const string &vn_name,
178 : const PathPreference &path_pref,
179 : uint64_t sequence_number) {
180 0 : const BgpPeer *bgp_peer = dynamic_cast<const BgpPeer *>(peer);
181 0 : assert(bgp_peer != NULL);
182 :
183 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
184 0 : req.key.reset(new EvpnRouteKey(peer, vrf_name, mac, ip_addr,
185 0 : EvpnAgentRouteTable::ComputeHostIpPlen(ip_addr),
186 0 : ethernet_tag));
187 0 : req.data.reset(new L2ReceiveRoute(vn_name, ethernet_tag,
188 : label, path_pref,
189 0 : sequence_number));
190 0 : agent()->fabric_evpn_table()->Enqueue(&req);
191 0 : }
192 :
193 0 : void EvpnAgentRouteTable::AddReceiveRouteReq(const Peer *peer,
194 : const string &vrf_name,
195 : uint32_t label,
196 : const MacAddress &mac,
197 : const IpAddress &ip_addr,
198 : uint32_t ethernet_tag,
199 : const string &vn_name,
200 : const PathPreference &pref) {
201 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
202 0 : req.key.reset(new EvpnRouteKey(peer, vrf_name, mac, ip_addr,
203 0 : EvpnAgentRouteTable::ComputeHostIpPlen(ip_addr),
204 0 : ethernet_tag));
205 0 : req.data.reset(new L2ReceiveRoute(vn_name, ethernet_tag, label, pref,
206 0 : peer->sequence_number()));
207 0 : agent()->fabric_evpn_table()->Enqueue(&req);
208 0 : }
209 :
210 196 : void EvpnAgentRouteTable::AddReceiveRoute(const Peer *peer,
211 : const string &vrf_name,
212 : uint32_t label,
213 : const MacAddress &mac,
214 : const IpAddress &ip_addr,
215 : uint32_t ethernet_tag,
216 : const string &vn_name,
217 : const PathPreference &pref) {
218 196 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
219 196 : req.key.reset(new EvpnRouteKey(peer, vrf_name, mac, ip_addr,
220 196 : EvpnAgentRouteTable::ComputeHostIpPlen(ip_addr),
221 196 : ethernet_tag));
222 196 : req.data.reset(new L2ReceiveRoute(vn_name, ethernet_tag, label, pref,
223 196 : peer->sequence_number()));
224 196 : Process(req);
225 196 : }
226 :
227 0 : void EvpnAgentRouteTable::AddLocalVmRouteReq(const Peer *peer,
228 : const string &vrf_name,
229 : const MacAddress &mac,
230 : const IpAddress &ip_addr,
231 : uint32_t ethernet_tag,
232 : LocalVmRoute *data) {
233 0 : assert(peer);
234 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
235 :
236 0 : req.key.reset(new EvpnRouteKey(peer, vrf_name, mac, ip_addr,
237 0 : EvpnAgentRouteTable::ComputeHostIpPlen(ip_addr),
238 0 : ethernet_tag));
239 0 : data->set_tunnel_bmap(TunnelType::AllType());
240 0 : req.data.reset(data);
241 0 : EvpnTableEnqueue(Agent::GetInstance(), &req);
242 0 : }
243 :
244 1548 : void EvpnAgentRouteTable::AddLocalVmRoute(const Peer *peer,
245 : const string &vrf_name,
246 : const MacAddress &mac,
247 : const VmInterface *intf,
248 : const IpAddress &ip,
249 : uint32_t label,
250 : const string &vn_name,
251 : const SecurityGroupList &sg_id_list,
252 : const TagList &tag_id_list,
253 : const PathPreference &path_pref,
254 : uint32_t ethernet_tag,
255 : bool etree_leaf,
256 : const std::string &name) {
257 1548 : assert(peer);
258 :
259 1548 : Agent *agent = static_cast<AgentDBTable *>(intf->get_table())->agent();
260 1548 : VmInterfaceKey intf_key(AgentKey::ADD_DEL_CHANGE, intf->GetUuid(), name);
261 1548 : VnListType vn_list;
262 1548 : vn_list.insert(vn_name);
263 : LocalVmRoute *data = new LocalVmRoute(intf_key, label,
264 1548 : intf->vxlan_id(), false,
265 : vn_list,
266 : InterfaceNHFlags::BRIDGE,
267 : sg_id_list, tag_id_list,
268 1548 : CommunityList(),
269 : path_pref,
270 1548 : IpAddress(),
271 3096 : EcmpLoadBalance(), false, false,
272 1548 : peer->sequence_number(),
273 1548 : etree_leaf, false);
274 1548 : data->set_tunnel_bmap(TunnelType::AllType());
275 :
276 1548 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
277 1548 : req.key.reset(new EvpnRouteKey(peer, vrf_name, mac, ip,
278 1548 : EvpnAgentRouteTable::ComputeHostIpPlen(ip),
279 1548 : ethernet_tag));
280 1548 : req.data.reset(data);
281 1548 : EvpnTableProcess(agent, vrf_name, req);
282 1548 : }
283 :
284 0 : void EvpnAgentRouteTable::AddLocalVmRouteReq(const Peer *peer,
285 : const string &vrf_name,
286 : const MacAddress &mac,
287 : const VmInterface *intf,
288 : const IpAddress &ip,
289 : uint32_t label,
290 : const string &vn_name,
291 : const SecurityGroupList &sg_id_list,
292 : const TagList &tag_id_list,
293 : const PathPreference &path_pref,
294 : uint32_t ethernet_tag,
295 : bool etree_leaf) {
296 0 : assert(peer);
297 :
298 0 : Agent *agent = static_cast<AgentDBTable *>(intf->get_table())->agent();
299 0 : VmInterfaceKey intf_key(AgentKey::ADD_DEL_CHANGE, intf->GetUuid(), "");
300 0 : VnListType vn_list;
301 0 : vn_list.insert(vn_name);
302 : LocalVmRoute *data = new LocalVmRoute(intf_key, label,
303 0 : intf->vxlan_id(), false,
304 : vn_list,
305 : InterfaceNHFlags::BRIDGE,
306 : sg_id_list, tag_id_list,
307 0 : CommunityList(),
308 : path_pref,
309 0 : IpAddress(),
310 0 : EcmpLoadBalance(), false, false,
311 0 : peer->sequence_number(),
312 0 : etree_leaf, false);
313 0 : data->set_tunnel_bmap(TunnelType::AllType());
314 :
315 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
316 0 : req.key.reset(new EvpnRouteKey(peer, vrf_name, mac, ip,
317 0 : EvpnAgentRouteTable::ComputeHostIpPlen(ip),
318 0 : ethernet_tag));
319 0 : req.data.reset(data);
320 0 : EvpnTableEnqueue(agent, &req);
321 0 : }
322 :
323 0 : void EvpnAgentRouteTable::DeleteOvsPeerMulticastRouteInternal(const Peer *peer,
324 : uint32_t vxlan_id,
325 : const Ip4Address &tor_ip,
326 : bool enqueue) {
327 0 : const VrfEntry *vrf = vrf_entry();
328 0 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
329 0 : req.key.reset(new EvpnRouteKey(peer,
330 0 : vrf->GetName(),
331 0 : MacAddress::BroadcastMac(),
332 : tor_ip,
333 0 : EvpnAgentRouteTable::ComputeHostIpPlen(tor_ip),
334 0 : vxlan_id));
335 0 : req.data.reset(NULL);
336 0 : if (enqueue) {
337 0 : EvpnTableEnqueue(agent(), &req);
338 : } else {
339 0 : EvpnTableProcess(agent(), vrf->GetName(), req);
340 : }
341 0 : }
342 :
343 0 : void EvpnAgentRouteTable::DeleteOvsPeerMulticastRouteReq(const Peer *peer,
344 : uint32_t vxlan_id,
345 : const Ip4Address &tor_ip) {
346 0 : DeleteOvsPeerMulticastRouteInternal(peer, vxlan_id, tor_ip, true);
347 0 : }
348 :
349 0 : void EvpnAgentRouteTable::DeleteOvsPeerMulticastRoute(const Peer *peer,
350 : uint32_t vxlan_id,
351 : const Ip4Address &tor_ip) {
352 0 : DeleteOvsPeerMulticastRouteInternal(peer, vxlan_id, tor_ip, false);
353 0 : }
354 :
355 443 : void EvpnAgentRouteTable::DelLocalVmRoute(const Peer *peer,
356 : const string &vrf_name,
357 : const MacAddress &mac,
358 : const VmInterface *intf,
359 : const IpAddress &ip,
360 : uint32_t ethernet_tag) {
361 443 : assert(peer);
362 443 : Agent *agent = static_cast<AgentDBTable *>(intf->get_table())->agent();
363 443 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
364 886 : req.key.reset(new EvpnRouteKey(peer, vrf_name, mac, IpAddress(ip),
365 443 : EvpnAgentRouteTable::ComputeHostIpPlen(ip),
366 443 : ethernet_tag));
367 443 : req.data.reset(NULL);
368 443 : EvpnTableProcess(agent, vrf_name, req);
369 443 : }
370 :
371 0 : void EvpnAgentRouteTable::ResyncVmRoute(const Peer *peer,
372 : const string &vrf_name,
373 : const MacAddress &mac,
374 : const IpAddress &ip_addr,
375 : uint32_t ethernet_tag,
376 : AgentRouteData *data) {
377 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
378 : EvpnRouteKey *key = new EvpnRouteKey(peer, vrf_name, mac, ip_addr,
379 0 : EvpnAgentRouteTable::ComputeHostIpPlen(ip_addr),
380 0 : ethernet_tag);
381 0 : key->sub_op_ = AgentKey::RESYNC;
382 0 : req.key.reset(key);
383 0 : req.data.reset(data);
384 :
385 0 : EvpnTableProcess(Agent::GetInstance(), vrf_name, req);
386 0 : }
387 :
388 7 : void EvpnAgentRouteTable::AddRemoteVmRouteReq(const Peer *peer,
389 : const string &vrf_name,
390 : const MacAddress &mac,
391 : const IpAddress &ip_addr,
392 : uint32_t plen,
393 : uint32_t ethernet_tag,
394 : AgentRouteData *data) {
395 7 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
396 7 : req.key.reset(new EvpnRouteKey(peer, vrf_name, mac, ip_addr,
397 7 : plen, ethernet_tag));
398 7 : req.data.reset(data);
399 :
400 7 : EvpnTableEnqueue(Agent::GetInstance(), &req);
401 7 : }
402 :
403 0 : void EvpnAgentRouteTable::AddRemoteVmRoute(const Peer *peer,
404 : const string &vrf_name,
405 : const MacAddress &mac,
406 : const IpAddress &ip_addr,
407 : uint32_t plen,
408 : uint32_t ethernet_tag,
409 : AgentRouteData *data) {
410 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
411 0 : req.key.reset(new EvpnRouteKey(peer, vrf_name, mac, ip_addr,
412 0 : plen, ethernet_tag));
413 0 : req.data.reset(data);
414 :
415 0 : EvpnTableProcess(Agent::GetInstance(), vrf_name, req);
416 0 : }
417 :
418 0 : void EvpnAgentRouteTable::AddType5Route(const Peer *peer,
419 : const string &vrf_name,
420 : const IpAddress &ip_addr,
421 : uint32_t ethernet_tag,
422 : EvpnRoutingData *data, uint8_t plen) {
423 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
424 0 : if ( !plen && !ip_addr.is_unspecified()) {
425 0 : req.key.reset(new EvpnRouteKey(peer, vrf_name, MacAddress(), ip_addr,
426 0 : EvpnAgentRouteTable::ComputeHostIpPlen(ip_addr),
427 0 : ethernet_tag));
428 : } else {
429 0 : req.key.reset(new EvpnRouteKey(peer, vrf_name, MacAddress(), ip_addr,
430 : plen,
431 0 : ethernet_tag));
432 : }
433 0 : req.data.reset(data);
434 :
435 0 : EvpnTableEnqueue(agent(), &req);
436 0 : }
437 :
438 6 : void EvpnAgentRouteTable::DeleteReq(const Peer *peer, const string &vrf_name,
439 : const MacAddress &mac,
440 : const IpAddress &ip_addr,
441 : uint32_t plen,
442 : uint32_t ethernet_tag,
443 : AgentRouteData *data) {
444 6 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
445 6 : req.key.reset(new EvpnRouteKey(peer, vrf_name, mac, ip_addr,
446 6 : plen, ethernet_tag));
447 6 : req.data.reset(data);
448 6 : EvpnTableEnqueue(Agent::GetInstance(), &req);
449 6 : }
450 :
451 0 : void EvpnAgentRouteTable::Delete(const Peer *peer, const string &vrf_name,
452 : const MacAddress &mac,
453 : const IpAddress &ip_addr,
454 : uint32_t ethernet_tag) {
455 0 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
456 0 : req.key.reset(new EvpnRouteKey(peer, vrf_name, mac, ip_addr,
457 0 : EvpnAgentRouteTable::ComputeHostIpPlen(ip_addr),
458 0 : ethernet_tag));
459 0 : req.data.reset(NULL);
460 0 : EvpnTableProcess(Agent::GetInstance(), vrf_name, req);
461 0 : }
462 :
463 0 : void EvpnAgentRouteTable::AddClonedLocalPathReq(const Peer *peer,
464 : const string &vrf_name,
465 : const MacAddress &mac,
466 : const IpAddress &ip_addr,
467 : uint32_t ethernet_tag,
468 : ClonedLocalPath *data) {
469 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
470 0 : req.key.reset(new EvpnRouteKey(peer, vrf_name, mac, ip_addr,
471 0 : EvpnAgentRouteTable::ComputeHostIpPlen(ip_addr),
472 0 : ethernet_tag));
473 0 : req.data.reset(data);
474 0 : EvpnTableEnqueue(Agent::GetInstance(), &req);
475 0 : }
476 :
477 2226 : uint32_t EvpnAgentRouteTable::ComputeHostIpPlen(const IpAddress &addr) {
478 2226 : if (addr.is_v4())
479 2226 : return 32;
480 0 : if (addr.is_v6())
481 0 : return 128;
482 :
483 0 : assert(0);
484 : return 0;
485 : }
486 :
487 : /////////////////////////////////////////////////////////////////////////////
488 : // EvpnRouteEntry methods
489 : /////////////////////////////////////////////////////////////////////////////
490 3223 : EvpnRouteEntry::EvpnRouteEntry(VrfEntry *vrf,
491 : const MacAddress &mac,
492 : const IpAddress &ip_addr,
493 : uint8_t plen,
494 : uint32_t ethernet_tag,
495 3223 : bool is_multicast) :
496 : AgentRoute(vrf, is_multicast), AgentRoutePrefix(ip_addr, plen),
497 3223 : mac_(mac),
498 3223 : ethernet_tag_(ethernet_tag),
499 3223 : publish_to_inet_route_table_(true),
500 3223 : publish_to_bridge_route_table_(true) {
501 3223 : if (IsType5()) {
502 0 : publish_to_inet_route_table_ = false;
503 0 : publish_to_bridge_route_table_ = false;
504 : }
505 3223 : }
506 :
507 5934 : string EvpnRouteEntry::ToString() const {
508 5934 : std::stringstream str;
509 5934 : if (is_multicast()) {
510 0 : str << mac_.ToString();
511 : } else {
512 5934 : str << ethernet_tag_;
513 5934 : str << "-";
514 5934 : str << mac_.ToString();
515 5934 : str << "-";
516 5934 : str << prefix_address_.to_string();
517 5934 : str << "/";
518 5934 : str << int(prefix_length());
519 : }
520 11868 : return str.str();
521 5934 : }
522 :
523 11474 : int EvpnRouteEntry::CompareTo(const Route &rhs) const {
524 11474 : const EvpnRouteEntry &a = static_cast<const EvpnRouteEntry &>(rhs);
525 :
526 11474 : if (ethernet_tag_ < a.ethernet_tag_)
527 1 : return -1;
528 :
529 11473 : if (ethernet_tag_ > a.ethernet_tag_)
530 1 : return 1;
531 :
532 11472 : int cmp = mac_.CompareTo(a.mac_);
533 11472 : if (cmp != 0)
534 2838 : return cmp;
535 :
536 8634 : if (prefix_address_ < a.prefix_address_)
537 2148 : return -1;
538 :
539 6486 : if (prefix_address_ > a.prefix_address_)
540 964 : return 1;
541 :
542 5522 : if (prefix_length() < a.prefix_length())
543 0 : return -1;
544 :
545 5522 : if (prefix_length() > a.prefix_length())
546 0 : return 1;
547 :
548 5522 : return 0;
549 : }
550 :
551 641 : DBEntryBase::KeyPtr EvpnRouteEntry::GetDBRequestKey() const {
552 : EvpnRouteKey *key =
553 641 : new EvpnRouteKey(Agent::GetInstance()->local_vm_peer(),
554 641 : vrf()->GetName(), mac_, prefix_address_,
555 641 : prefix_length(), ethernet_tag_);
556 641 : return DBEntryBase::KeyPtr(key);
557 : }
558 :
559 0 : void EvpnRouteEntry::SetKey(const DBRequestKey *key) {
560 0 : const EvpnRouteKey *k = static_cast<const EvpnRouteKey *>(key);
561 0 : SetVrf(Agent::GetInstance()->vrf_table()->FindVrfFromName(k->vrf_name()));
562 0 : mac_ = k->GetMac();
563 0 : prefix_address_ = k->ip_addr();
564 0 : ethernet_tag_ = k->ethernet_tag();
565 0 : }
566 :
567 0 : uint32_t EvpnRouteEntry::GetActiveLabel() const {
568 0 : return GetActivePath()->GetActiveLabel();
569 : }
570 :
571 0 : const AgentPath *EvpnRouteEntry::FindOvsPath() const {
572 0 : for(Route::PathList::const_iterator it = GetPathList().begin();
573 0 : it != GetPathList().end(); it++) {
574 0 : const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
575 0 : if (path->peer()->GetType() == Peer::OVS_PEER) {
576 0 : return const_cast<AgentPath *>(path);
577 : }
578 : }
579 0 : return NULL;
580 : }
581 :
582 : //Notify L2 route corresponding to MAC in evpn route.
583 : //On addition of evpn routes, update bridge route using mac of evpn and inet
584 : //route using ip of evpn.
585 : //NH of bridge route is same as of EVPN as bridge rt is programmed in kernel.
586 : //NH of Inet route will be of subnet route to which it belongs. This makes sure
587 : //that n absence of any directly installed Inet route for this IP packets are
588 : //forwarded as per the subnet route decision.
589 1985 : void EvpnRouteEntry::UpdateDerivedRoutes(AgentRouteTable *table,
590 : const AgentPath *path,
591 : bool active_path_changed) {
592 : //As active path is picked from route, any modification in non-active
593 : //path need not rebake agent route.
594 : //Path is NULL when resync is issued on route, hence no need to check flag
595 1985 : if ((path != NULL) && !active_path_changed)
596 476 : return;
597 :
598 :
599 1509 : if (publish_to_bridge_route_table()) {
600 1509 : BridgeAgentRouteTable *bridge_table = NULL;
601 : bridge_table = static_cast<BridgeAgentRouteTable *>
602 1509 : (table->vrf_entry()->GetBridgeRouteTable());
603 1509 : if (bridge_table)
604 1509 : bridge_table->AddBridgeRoute(this);
605 : }
606 1509 : if (publish_to_inet_route_table()) {
607 : InetUnicastAgentRouteTable *inet_table =
608 1509 : table->vrf_entry()->GetInetUnicastRouteTable(prefix_address());
609 1509 : if (inet_table)
610 1509 : inet_table->AddEvpnRoute(this);
611 : }
612 : }
613 :
614 : //Delete path from L2 route corresponding to MAC+IP in evpn route.
615 338 : void EvpnRouteEntry::DeleteDerivedRoutes(AgentRouteTable *table) {
616 : //Delete from bridge table
617 : BridgeAgentRouteTable *bridge_table = static_cast<BridgeAgentRouteTable *>
618 338 : (table->vrf_entry()->GetBridgeRouteTable());
619 338 : if (bridge_table)
620 338 : bridge_table->DeleteBridgeRoute(this);
621 :
622 : //Delete from Inet table
623 : InetUnicastAgentRouteTable *inet_table =
624 338 : table->vrf_entry()->GetInetUnicastRouteTable(prefix_address());
625 338 : if (inet_table)
626 338 : inet_table->DeleteEvpnRoute(this);
627 338 : }
628 :
629 : /////////////////////////////////////////////////////////////////////////////
630 : // Sandesh related methods
631 : /////////////////////////////////////////////////////////////////////////////
632 0 : void EvpnRouteReq::HandleRequest() const {
633 : VrfEntry *vrf =
634 0 : Agent::GetInstance()->vrf_table()->FindVrfFromId(get_vrf_index());
635 0 : if (!vrf) {
636 0 : ErrorResp *resp = new ErrorResp();
637 0 : resp->set_context(context());
638 0 : resp->Response();
639 0 : return;
640 : }
641 :
642 0 : AgentSandeshPtr sand(new AgentEvpnRtSandesh(vrf, context(), "",
643 0 : get_stale()));
644 0 : sand->DoSandesh(sand);
645 0 : }
646 :
647 0 : AgentSandeshPtr EvpnAgentRouteTable::GetAgentSandesh
648 : (const AgentSandeshArguments *args, const std::string &context) {
649 0 : return AgentSandeshPtr(new AgentEvpnRtSandesh(vrf_entry(), context, "",
650 0 : false));
651 : }
652 :
653 0 : bool EvpnRouteEntry::DBEntrySandesh(Sandesh *sresp, bool stale) const {
654 0 : EvpnRouteResp *resp = static_cast<EvpnRouteResp *>(sresp);
655 0 : RouteEvpnSandeshData data;
656 0 : data.set_mac(ToString());
657 0 : data.set_ip_addr(prefix_address_.to_string());
658 :
659 0 : for (Route::PathList::const_iterator it = GetPathList().begin();
660 0 : it != GetPathList().end(); it++) {
661 0 : const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
662 0 : if (path) {
663 0 : PathSandeshData pdata;
664 0 : path->SetSandeshData(pdata);
665 0 : data.path_list.push_back(pdata);
666 0 : }
667 : }
668 : std::vector<RouteEvpnSandeshData> &list =
669 0 : const_cast<std::vector<RouteEvpnSandeshData>&>(resp->get_route_list());
670 0 : list.push_back(data);
671 0 : return true;
672 0 : }
673 :
674 479 : bool EvpnRouteEntry::ReComputePathDeletion(AgentPath *path) {
675 479 : bool ret = false;
676 479 : Agent *agent = static_cast<AgentRouteTable *>(get_table())->agent();
677 479 : EvpnRoutingPath *evpn_path = dynamic_cast<EvpnRoutingPath *>(path);
678 479 : if (evpn_path) {
679 0 : evpn_path->DeleteEvpnType5Route(agent, this);
680 : }
681 479 : return ret;
682 : }
|