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