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 <base/address_util.h>
9 : #include <base/task_annotations.h>
10 : #include <boost/foreach.hpp>
11 : #include <cmn/agent_cmn.h>
12 : #include <route/route.h>
13 : #include <oper/ecmp.h>
14 : #include <oper/ecmp_load_balance.h>
15 : #include <oper/route_common.h>
16 : #include <oper/vrf.h>
17 : #include <oper/tunnel_nh.h>
18 : #include <oper/mpls.h>
19 : #include <oper/vxlan.h>
20 : #include <oper/mirror_table.h>
21 : #include <oper/multicast.h>
22 : #include <controller/controller_export.h>
23 : #include <controller/controller_peer.h>
24 : #include <controller/controller_route_path.h>
25 : #include <oper/agent_sandesh.h>
26 :
27 : using namespace std;
28 : using namespace boost::asio;
29 :
30 : AgentRoute *
31 10029 : InetUnicastRouteKey::AllocRouteEntry(VrfEntry *vrf, bool is_multicast) const {
32 : InetUnicastRouteEntry * entry =
33 10029 : new InetUnicastRouteEntry(vrf, dip_, plen_, is_multicast);
34 10029 : return static_cast<AgentRoute *>(entry);
35 : }
36 :
37 857 : AgentRouteKey *InetUnicastRouteKey::Clone() const {
38 857 : return (new InetUnicastRouteKey(peer(), vrf_name_, dip_, plen_));
39 : }
40 :
41 19 : AgentRouteKey *InetMplsUnicastRouteKey::Clone() const {
42 19 : return (new InetMplsUnicastRouteKey(peer(), vrf_name_, dip_, plen_));
43 : }
44 : /////////////////////////////////////////////////////////////////////////////
45 : // InetUnicastAgentRouteTable functions
46 : /////////////////////////////////////////////////////////////////////////////
47 222 : InetUnicastAgentRouteTable::InetUnicastAgentRouteTable(DB *db,
48 222 : const std::string &name) :
49 222 : AgentRouteTable(db, name), walkid_(DBTableWalker::kInvalidWalkerId) {
50 :
51 222 : if (name.find("uc.route.0") != std::string::npos) {
52 74 : type_ = Agent::INET4_UNICAST;
53 148 : } else if (name.find("uc.route.3") != std::string::npos) {
54 74 : type_ = Agent::INET4_MPLS;
55 74 : } else if (name.find("uc.route6.0") != std::string::npos) {
56 74 : type_ = Agent::INET6_UNICAST;
57 0 : } else if (name.find("evpn.route.0") != std::string::npos) {
58 0 : type_ = Agent::EVPN;
59 0 : } else if (name.find("l2.route.0") != std::string::npos) {
60 0 : type_ = Agent::BRIDGE;
61 0 : } else if (name.find("mc.route.0") != std::string::npos) {
62 0 : type_ = Agent::INET4_MULTICAST;
63 : } else {
64 0 : type_ = Agent::INVALID;
65 : }
66 222 : }
67 :
68 : DBTableBase *
69 222 : InetUnicastAgentRouteTable::CreateTable(DB *db, const std::string &name) {
70 222 : AgentRouteTable *table = new InetUnicastAgentRouteTable(db, name);
71 222 : table->Init();
72 222 : return table;
73 : }
74 :
75 : InetUnicastRouteEntry *
76 2060 : InetUnicastAgentRouteTable::FindLPM(const IpAddress &ip) {
77 2060 : uint32_t plen = 128;
78 2060 : if (ip.is_v4()) {
79 2060 : plen = 32;
80 : }
81 2060 : InetUnicastRouteEntry key(NULL, ip, plen, false);
82 4120 : return tree_.LPMFind(&key);
83 2060 : }
84 :
85 : InetUnicastRouteEntry *
86 2620 : InetUnicastAgentRouteTable::FindLPM(const InetUnicastRouteEntry &rt_key) {
87 2620 : return tree_.LPMFind(&rt_key);
88 : }
89 :
90 : InetUnicastRouteEntry *
91 12 : InetUnicastAgentRouteTable::FindResolveRoute(const Ip4Address &ip) {
92 12 : uint8_t plen = 32;
93 12 : InetUnicastRouteEntry *rt = NULL;
94 : do {
95 20 : InetUnicastRouteEntry key(NULL, ip, plen, false);
96 20 : rt = tree_.LPMFind(&key);
97 20 : if (rt) {
98 18 : const NextHop *nh = rt->GetActiveNextHop();
99 18 : if (nh && nh->GetType() == NextHop::RESOLVE)
100 10 : return rt;
101 : }
102 30 : } while (rt && --plen);
103 :
104 2 : return NULL;
105 : }
106 :
107 : InetUnicastRouteEntry *
108 0 : InetUnicastAgentRouteTable::FindResolveRoute(const string &vrf_name,
109 : const Ip4Address &ip) {
110 : VrfEntry *vrf =
111 0 : Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
112 : InetUnicastAgentRouteTable *rt_table =
113 : static_cast<InetUnicastAgentRouteTable *>
114 0 : (vrf->GetInet4UnicastRouteTable());
115 0 : return rt_table->FindResolveRoute(ip);
116 : }
117 :
118 723 : static void Inet4UnicastTableEnqueue(Agent *agent, DBRequest *req) {
119 723 : AgentRouteTable *table = agent->fabric_inet4_unicast_table();
120 723 : if (table) {
121 723 : table->Enqueue(req);
122 : }
123 723 : }
124 :
125 2 : static void Inet4MplsUnicastTableEnqueue(Agent *agent, DBRequest *req) {
126 2 : AgentRouteTable *table = agent->fabric_inet4_mpls_table();
127 2 : if (table) {
128 2 : table->Enqueue(req);
129 : }
130 2 : }
131 :
132 1116 : static void Inet6UnicastTableEnqueue(Agent *agent, const string &vrf_name,
133 : DBRequest *req) {
134 1116 : AgentRouteTable *table = agent->fabric_inet4_unicast_table();
135 1116 : if (table) {
136 1116 : table->Enqueue(req);
137 : }
138 1116 : }
139 :
140 1827 : static void InetUnicastTableEnqueue(Agent *agent, const string &vrf,
141 : DBRequest *req) {
142 1827 : InetUnicastRouteKey *key = static_cast<InetUnicastRouteKey *>(req->key.get());
143 1827 : if (key->addr().is_v4()) {
144 711 : Inet4UnicastTableEnqueue(agent, req);
145 1116 : } else if (key->addr().is_v6()) {
146 1116 : Inet6UnicastTableEnqueue(agent, vrf, req);
147 : }
148 1827 : }
149 :
150 1388 : static void Inet4UnicastTableProcess(Agent *agent, const string &vrf_name,
151 : DBRequest &req) {
152 : AgentRouteTable *table =
153 1388 : agent->vrf_table()->GetInet4UnicastRouteTable(vrf_name);
154 1388 : if (table) {
155 1388 : table->Process(req);
156 : }
157 1388 : }
158 :
159 336 : static void Inet6UnicastTableProcess(Agent *agent, const string &vrf_name,
160 : DBRequest &req) {
161 : AgentRouteTable *table =
162 336 : agent->vrf_table()->GetInet6UnicastRouteTable(vrf_name);
163 336 : if (table) {
164 336 : table->Process(req);
165 : }
166 336 : }
167 :
168 1704 : static void InetUnicastTableProcess(Agent *agent, const string &vrf_name,
169 : DBRequest &req) {
170 1704 : InetUnicastRouteKey *key = static_cast<InetUnicastRouteKey *>(req.key.get());
171 1704 : if (key->addr().is_v4()) {
172 1370 : Inet4UnicastTableProcess(agent, vrf_name, req);
173 334 : } else if (key->addr().is_v6()) {
174 334 : Inet6UnicastTableProcess(agent, vrf_name, req);
175 : }
176 1704 : }
177 :
178 : /*
179 : * Traverse all smaller subnets w.r.t. route sent and mark the arp flood flag
180 : * accordingly.
181 : */
182 160 : bool InetUnicastAgentRouteTable::ResyncSubnetRoutes
183 : (const InetUnicastRouteEntry *rt, bool val) {
184 160 : const IpAddress addr = rt->prefix_address();
185 160 : uint16_t plen = rt->prefix_length();
186 160 : InetUnicastRouteEntry *lpm_rt = GetNextNonConst(rt);
187 :
188 160 : Ip4Address v4_parent_mask;
189 160 : Ip6Address v6_parent_mask;
190 :
191 160 : if (GetTableType() == Agent::INET4_UNICAST) {
192 320 : v4_parent_mask = Address::GetIp4SubnetAddress(addr.to_v4(),
193 160 : plen);
194 0 : } else if (GetTableType() == Agent::INET6_UNICAST) {
195 0 : v6_parent_mask = Address::GetIp6SubnetAddress(addr.to_v6(),
196 0 : plen);
197 : } else {
198 : // skip processing for inet4_mpls table
199 : // not expected
200 0 : return false;
201 : }
202 :
203 :
204 : // Iterate thru all the routes under this subnet and update route flags
205 172 : while ((lpm_rt != NULL) && (plen < lpm_rt->prefix_length())) {
206 53 : if (GetTableType() == Agent::INET4_UNICAST) {
207 : Ip4Address node_mask =
208 53 : Address::GetIp4SubnetAddress(lpm_rt->prefix_address().to_v4(),
209 106 : plen);
210 53 : if (v4_parent_mask != node_mask)
211 41 : break;
212 :
213 0 : } else if (GetTableType() == Agent::INET6_UNICAST) {
214 : Ip6Address node_mask =
215 0 : Address::GetIp6SubnetAddress(lpm_rt->prefix_address().to_v6(),
216 0 : plen);
217 0 : if (v6_parent_mask != node_mask)
218 0 : break;
219 : }
220 :
221 : // Update ipam_host_route_ and proxy_arp_ flags for host-routes
222 12 : bool notify = false;
223 12 : if (lpm_rt->UpdateIpamHostFlags(val)) {
224 12 : notify = true;
225 : }
226 :
227 12 : if (notify) {
228 12 : NotifyEntry(lpm_rt);
229 : }
230 :
231 12 : lpm_rt = GetNextNonConst(lpm_rt);
232 : }
233 160 : return false;
234 : }
235 :
236 : //Null peer means sync is done on routes.
237 : //If peer is specified then path belonging to peer will be resync'd
238 : //Functions in TraverseHostRoutesInSubnet:
239 : //1) If subnet rt added does not have any supernet then visit all unresolved
240 : // routes and resync them.
241 : //2) If supernet route is present then traverse lpm routes under this newly
242 : // added subnet and resync all host routes pointing to supernet route of this
243 : // subnet.
244 : //3) Skip all the host routes present under this subnet belonging to a better
245 : // subnet(better subnet is the one which comes under subnet being added).
246 : // e.g. 1.1.1.10/24 is a better subnet in 1.1.1.10/16 while supernet can be
247 : // 1.1.1.0/8
248 : void
249 103 : InetUnicastAgentRouteTable::TraverseHostRoutesInSubnet(InetUnicastRouteEntry *rt,
250 : const Peer *peer)
251 : {
252 103 : const IpAddress addr = rt->prefix_address();
253 103 : uint16_t plen = rt->prefix_length();
254 103 : InetUnicastRouteEntry *supernet_rt = GetSuperNetRoute(rt->prefix_address());
255 :
256 : //If supernet route is NULL, then this is the default route and visit to
257 : //unresolved route for resync should suffice.
258 103 : if (supernet_rt == NULL) {
259 : //Resync all unresolved routes.
260 0 : EvaluateUnresolvedRoutes();
261 0 : return;
262 : }
263 : //So suernet route is present and this subnet route is a better route.
264 : //Look for all routes which were pointing to supernet route and move them
265 : //to this subnet route, if they fall in same subnet.
266 103 : IpAddress parent_mask = GetSubnetAddress(addr, plen);
267 103 : for (InetUnicastRouteEntry *lpm_rt = GetNextNonConst(rt);
268 134 : (lpm_rt != NULL) && (plen < lpm_rt->prefix_length());
269 31 : lpm_rt= GetNextNonConst(lpm_rt)) {
270 31 : IpAddress node_mask = GetSubnetAddress(lpm_rt->prefix_address(), plen);
271 31 : if (parent_mask != node_mask)
272 0 : break;
273 :
274 : //Non host route, lets continue as this route will have its own NH and it
275 : //need not be modified.
276 31 : if (lpm_rt->IsHostRoute() == false) {
277 31 : continue;
278 : }
279 :
280 : //If supernet route of this subnet route is not parent of lpm_rt added,
281 : //then skip as its not lpm_rt dependant as well.
282 : //There may be some other subnet which is handling it.
283 : //e.g. 1.1.0.0/8, 1.1.0.0/16, 1.1.1.0/24, 1.1.1.1, 1.1.0.1
284 : //Here parent of 1.1.1.1 will be 1.1.1.0/24 and not 1.1.0.0/16.
285 : //So if subnet route getting added is 1.1.0.0/16 in presence of 1.1.1.0/24
286 : //then 1.1.1.1 should not be modified.
287 25 : if (lpm_rt->GetActivePath()->dependant_rt() != supernet_rt)
288 25 : continue;
289 :
290 :
291 : //Proceed only for host route
292 : //Resync will ensure that subnet route is added to lpm host route
293 : //dependant rt(gw_ip).
294 0 : lpm_rt->EnqueueRouteResync();
295 : }
296 : }
297 :
298 : IpAddress
299 134 : InetUnicastAgentRouteTable::GetSubnetAddress(const IpAddress &addr,
300 : uint16_t plen) const {
301 134 : if (type_ == Agent::INET4_UNICAST) {
302 132 : return (Address::GetIp4SubnetAddress(addr.to_v4(), plen));
303 2 : } else if (type_ == Agent::INET6_UNICAST) {
304 2 : return (Address::GetIp6SubnetAddress(addr.to_v6(), plen));
305 : }
306 0 : return IpAddress(Ip4Address());
307 : }
308 :
309 : //Tries searching for subnet route to which this route belongs.
310 : //Route itself can be a subnet/host. To search for supernet plen is reduced by
311 : //one and findlpm is issued.
312 : InetUnicastRouteEntry *
313 2148 : InetUnicastAgentRouteTable::GetSuperNetRoute(const IpAddress &addr) {
314 2148 : InetUnicastRouteEntry key(NULL, addr, (GetHostPlen(addr) - 1),
315 2148 : false);
316 2148 : InetUnicastRouteEntry *parent_key = FindLPM(key);
317 2148 : return parent_key;
318 2148 : }
319 :
320 : /////////////////////////////////////////////////////////////////////////////
321 : // Inet4UnicastAgentRouteEntry functions
322 : /////////////////////////////////////////////_////////////////////////////////
323 14729 : InetUnicastRouteEntry::InetUnicastRouteEntry(VrfEntry *vrf,
324 : const IpAddress &addr,
325 : uint8_t plen,
326 14729 : bool is_multicast) :
327 : AgentRoute(vrf, is_multicast), AgentRoutePrefix(addr, plen),
328 14729 : ipam_subnet_route_(false),
329 14729 : ipam_host_route_(false), proxy_arp_(false) {
330 14729 : if (addr.is_v4()) {
331 11964 : prefix_address_ = Address::GetIp4SubnetAddress(addr.to_v4(), plen);
332 : } else {
333 2765 : prefix_address_ = Address::GetIp6SubnetAddress(addr.to_v6(), plen);
334 : }
335 14729 : }
336 :
337 0 : string InetUnicastRouteKey::ToString() const {
338 0 : ostringstream str;
339 0 : str << dip_.to_string();
340 0 : str << "/";
341 0 : str << (int)plen_;
342 0 : return str.str();
343 0 : }
344 :
345 10809 : string InetUnicastRouteEntry::ToString() const {
346 10809 : ostringstream str;
347 10809 : str << prefix_address_.to_string();
348 10809 : str << "/";
349 10809 : str << (int)prefix_length();
350 21618 : return str.str();
351 10809 : }
352 :
353 :
354 5534 : Agent::RouteTableType InetUnicastRouteEntry::GetTableType() const {
355 5534 : return ((InetUnicastAgentRouteTable *)get_table())->GetTableType();
356 : }
357 :
358 42084 : int InetUnicastRouteEntry::CompareTo(const Route &rhs) const {
359 42084 : const InetUnicastRouteEntry &a =
360 : static_cast<const InetUnicastRouteEntry &>(rhs);
361 :
362 42084 : if (prefix_address_ < a.prefix_address_) {
363 15512 : return -1;
364 : }
365 :
366 26572 : if (prefix_address_ > a.prefix_address_) {
367 8472 : return 1;
368 : }
369 :
370 18100 : if (prefix_length() < a.prefix_length()) {
371 1 : return -1;
372 : }
373 :
374 18099 : if (prefix_length() > a.prefix_length()) {
375 0 : return 1;
376 : }
377 :
378 18099 : return 0;
379 : }
380 :
381 3719 : DBEntryBase::KeyPtr InetUnicastRouteEntry::GetDBRequestKey() const {
382 : InetUnicastAgentRouteTable *table =
383 3719 : (static_cast<InetUnicastAgentRouteTable *>(get_table()));
384 3719 : Agent *agent = table->agent();
385 3719 : InetUnicastRouteKey *key = NULL;
386 3719 : if ((table->GetTableType() == Agent::INET4_MPLS)) {
387 23 : key =
388 23 : new InetMplsUnicastRouteKey(agent->local_peer(),
389 23 : vrf()->GetName(), prefix_address_, prefix_length());
390 : } else {
391 3696 : key =
392 3696 : new InetUnicastRouteKey(agent->local_peer(),
393 3696 : vrf()->GetName(), prefix_address_, prefix_length());
394 : }
395 :
396 3719 : return DBEntryBase::KeyPtr(key);
397 : }
398 :
399 0 : void InetUnicastRouteEntry::SetKey(const DBRequestKey *key) {
400 : Agent *agent =
401 0 : (static_cast<InetUnicastAgentRouteTable *>(get_table()))->agent();
402 0 : const InetUnicastRouteKey *k =
403 : static_cast<const InetUnicastRouteKey*>(key);
404 0 : SetVrf(agent->vrf_table()->FindVrfFromName(k->vrf_name()));
405 0 : IpAddress tmp(k->addr());
406 0 : set_addr(tmp);
407 0 : set_prefix_length(k->plen());
408 0 : }
409 :
410 4158 : bool InetUnicastRouteEntry::IsHostRoute() const {
411 : InetUnicastAgentRouteTable *table =
412 4158 : static_cast<InetUnicastAgentRouteTable *>(get_table());
413 4158 : if (table->GetTableType() == Agent::INET4_UNICAST) {
414 3424 : if (prefix_length() != Address::kMaxV4PrefixLen)
415 210 : return false;
416 734 : } else if (table->GetTableType() == Agent::INET6_UNICAST) {
417 730 : if (prefix_length() != Address::kMaxV6PrefixLen)
418 4 : return false;
419 : }
420 3944 : return true;
421 : }
422 :
423 : /*
424 : * This routine finds out if there is supernet for this subnet route and that
425 : * is used to inherit flood flag. In case supernet is pointing to resolve i.e.
426 : * gateway without having Ipam path, then search continues further
427 : */
428 63 : bool InetUnicastRouteEntry::IpamSubnetRouteAvailable() const {
429 63 : return (GetIpamSuperNetRoute() != NULL);
430 : }
431 :
432 : InetUnicastRouteEntry *
433 63 : InetUnicastRouteEntry::GetIpamSuperNetRoute() const {
434 63 : if (prefix_length() == 0)
435 5 : return NULL;
436 :
437 : //Local path present means that this route itself was programmed
438 : //because of IPAM add as well and hence its eligible for flood in
439 : //all paths where NH is tunnel.
440 : InetUnicastAgentRouteTable *table =
441 58 : static_cast<InetUnicastAgentRouteTable *>(get_table());
442 :
443 : //Search for supernet, if none then dont flood else again search for
444 : //local path. If found then mark for flood otherwise check for active path
445 : //and retain flood flag from that path.
446 58 : uint16_t plen = prefix_length() - 1;
447 58 : while (plen != 0) {
448 58 : assert(plen < prefix_length());
449 58 : InetUnicastRouteEntry key(vrf(), prefix_address_, plen, false);
450 : // Find next highest matching route
451 58 : InetUnicastRouteEntry *supernet_rt = table->FindRouteUsingKey(key);
452 :
453 58 : if (supernet_rt == NULL)
454 56 : return NULL;
455 :
456 2 : if (supernet_rt->ipam_subnet_route())
457 2 : return supernet_rt;
458 :
459 0 : plen--;
460 58 : }
461 :
462 0 : return NULL;
463 : }
464 :
465 2692 : bool InetUnicastRouteEntry::ReComputePathAdd(AgentPath *path) {
466 2692 : bool ret = false;
467 : InetUnicastAgentRouteTable *uc_rt_table =
468 2692 : static_cast<InetUnicastAgentRouteTable *>(get_table());
469 2692 : if (IsHostRoute() == false)
470 103 : uc_rt_table->TraverseHostRoutesInSubnet(this,
471 : uc_rt_table->agent()->
472 : inet_evpn_peer());
473 :
474 4540 : if (path->nexthop() && path->nexthop()->IsValid() &&
475 1848 : path->nexthop()->GetType() == NextHop::ARP) {
476 : //Add bridge route for IP fabric ARP routes, so that
477 : //MAC stitching can be done for VM routes based on corresponding
478 : //compute node
479 0 : const ArpNH *arp_nh = static_cast<const ArpNH *>(path->nexthop());
480 : BridgeAgentRouteTable *table =
481 0 : static_cast<BridgeAgentRouteTable *>(vrf()->GetBridgeRouteTable());
482 0 : table->AddMacVmBindingRoute(path->peer(), vrf()->GetName(), arp_nh->GetMac(),
483 : NULL, false);
484 : }
485 :
486 : // ECMP path are managed by route module. Update ECMP path with
487 : // addition of new path
488 2692 : EcmpData ecmp_data(uc_rt_table->agent(), vrf()->GetName(), ToString(),
489 2692 : path, false);
490 2692 : ret |= ecmp_data.Update(this);
491 2692 : return ret;
492 2692 : }
493 :
494 1278 : bool InetUnicastRouteEntry::ReComputePathDeletion(AgentPath *path) {
495 1278 : if (IsHostRoute() == false) {
496 : //TODO merge both evpn inet and subnet routes handling
497 100 : UpdateDependantRoutes();
498 : }
499 :
500 :
501 1278 : if (path->nexthop() && path->nexthop()->GetType() == NextHop::ARP) {
502 : const ArpNH *arp_nh =
503 2 : static_cast<const ArpNH *>(path->nexthop());
504 : BridgeAgentRouteTable *table =
505 2 : static_cast<BridgeAgentRouteTable *>(vrf()->GetBridgeRouteTable());
506 2 : table->DeleteMacVmBindingRoute(path->peer(), vrf()->GetName(),
507 : arp_nh->GetMac(), NULL);
508 : }
509 :
510 : InetUnicastAgentRouteTable *uc_rt_table =
511 1278 : static_cast<InetUnicastAgentRouteTable *>(get_table());
512 : //Subnet discard = Ipam subnet route.
513 : //Ipam path is getting deleted so all the smaller subnets should be
514 : //resynced to remove the arp flood marking.
515 1278 : if (path->is_subnet_discard()) {
516 : // Reset flag on route as ipam is going off.
517 80 : UpdateRouteFlags(false, false, false);
518 80 : uc_rt_table->ResyncSubnetRoutes(this, false);
519 80 : return true;
520 : }
521 : // ECMP path are managed by route module. Update ECMP path with
522 : // deletion of new path
523 1198 : EcmpData ecmp_data(uc_rt_table->agent(), vrf()->GetName(), ToString(),
524 1198 : path, true);
525 1198 : return ecmp_data.Update(this);
526 1198 : }
527 :
528 : // ipam_host_route_ flag:
529 : // ipam_host_route_ is set if this is host-route and falls in ipam-subnet range
530 : //
531 : // proxy_arp_ flag:
532 : // For hosts within subnet, we assume ARP must not be proxied and should be
533 : // flooded instead. If we get EVPN route, in KSYNC the EVPN path processing
534 : // will take preference and KSYNC will set Proxy flag
535 75 : bool InetUnicastRouteEntry::UpdateIpamHostFlags(bool ipam_host_route) {
536 : // For non-host routes, set proxy always
537 75 : if (IsHostRoute() == false) {
538 5 : return UpdateRouteFlags(false, false, true);
539 : }
540 :
541 70 : bool proxy_arp = ipam_host_route ? false : true;
542 70 : return UpdateRouteFlags(false, ipam_host_route, proxy_arp);
543 : }
544 :
545 609 : bool InetUnicastRouteEntry::UpdateRouteFlags(bool ipam_subnet_route,
546 : bool ipam_host_route,
547 : bool proxy_arp) {
548 609 : bool ret = false;
549 609 : if (ipam_subnet_route_ != ipam_subnet_route) {
550 160 : ipam_subnet_route_ = ipam_subnet_route;
551 160 : ret = true;
552 : }
553 :
554 609 : if (ipam_host_route_ != ipam_host_route) {
555 11 : ipam_host_route_ = ipam_host_route;
556 11 : ret = true;
557 : }
558 :
559 609 : if (proxy_arp_ != proxy_arp) {
560 359 : proxy_arp_ = proxy_arp;
561 359 : ret = true;
562 : }
563 :
564 609 : return ret;
565 : }
566 769 : AgentPath *InetUnicastRouteEntry::FindEvpnPathUsingKeyData
567 : (const AgentRouteKey *key, const AgentRouteData *data) const {
568 769 : const Peer *peer = key->peer();
569 769 : const InetEvpnPeer *evpn_peer = dynamic_cast<const InetEvpnPeer*>(peer);
570 769 : assert(evpn_peer != NULL);
571 :
572 : Route::PathList::const_iterator it;
573 6179 : for (it = GetPathList().begin(); it != GetPathList().end(); it++) {
574 2482 : const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
575 2482 : if (path->peer() != key->peer())
576 1734 : continue;
577 :
578 : //Handle mac route added via evpn route.
579 : const InetEvpnRoutePath *evpn_path =
580 748 : dynamic_cast<const InetEvpnRoutePath *>(path);
581 : const InetEvpnRouteData *evpn_data =
582 748 : dynamic_cast<const InetEvpnRouteData *>(data);
583 748 : assert(evpn_path != NULL);
584 748 : assert(evpn_data != NULL);
585 748 : if (evpn_path->MacAddr() != evpn_data->MacAddr())
586 202 : continue;
587 546 : return const_cast<AgentPath *>(path);
588 : }
589 223 : return NULL;
590 : }
591 2395 : AgentPath *InetUnicastRouteEntry::FindPathUsingKeyData
592 : (const AgentRouteKey *key, const AgentRouteData *data) const {
593 2395 : const Peer *peer = key->peer();
594 : const InetEvpnPeer *inet_evpn_peer =
595 2395 : dynamic_cast<const InetEvpnPeer*>(peer);
596 2395 : if (inet_evpn_peer != NULL)
597 769 : return FindEvpnPathUsingKeyData(key, data);
598 :
599 1626 : return FindPath(peer);
600 : }
601 :
602 : /////////////////////////////////////////////////////////////////////////////
603 : // AgentRouteData virtual functions
604 : /////////////////////////////////////////////////////////////////////////////
605 :
606 8 : bool Inet4UnicastArpRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
607 : const AgentRoute *rt) {
608 8 : bool ret = true;
609 :
610 8 : ArpNHKey key(vrf_name_, addr_, policy_);
611 : NextHop *nh =
612 8 : static_cast<NextHop *>(agent->nexthop_table()->FindActiveEntry(&key));
613 8 : path->set_unresolved(false);
614 :
615 8 : if (path->dest_vn_list() != vn_list_) {
616 2 : path->set_dest_vn_list(vn_list_);
617 2 : ret = true;
618 : }
619 :
620 8 : if (path->sg_list() != sg_list_) {
621 0 : path->set_sg_list(sg_list_);
622 0 : ret = true;
623 : }
624 :
625 8 : if (path->tag_list() != tag_list_) {
626 0 : path->set_tag_list(tag_list_);
627 0 : ret = true;
628 : }
629 :
630 8 : if (path->ChangeNH(agent, nh) == true)
631 2 : ret = true;
632 :
633 8 : if (nh) {
634 8 : if (path->CopyArpData()) {
635 4 : ret = true;
636 : }
637 : }
638 :
639 8 : path->set_tunnel_bmap(1 << TunnelType::NATIVE);
640 :
641 8 : return ret;
642 8 : }
643 :
644 0 : bool InetUnicastNdpRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
645 : const AgentRoute *rt) {
646 0 : bool ret = true;
647 :
648 0 : NdpNHKey key(vrf_name_, addr_, policy_);
649 : NextHop *nh =
650 0 : static_cast<NextHop *>(agent->nexthop_table()->FindActiveEntry(&key));
651 0 : path->set_unresolved(false);
652 :
653 0 : if (path->dest_vn_list() != vn_list_) {
654 0 : path->set_dest_vn_list(vn_list_);
655 0 : ret = true;
656 : }
657 :
658 0 : if (path->sg_list() != sg_list_) {
659 0 : path->set_sg_list(sg_list_);
660 0 : ret = true;
661 : }
662 :
663 0 : if (path->tag_list() != tag_list_) {
664 0 : path->set_tag_list(tag_list_);
665 0 : ret = true;
666 : }
667 :
668 0 : if (path->ChangeNH(agent, nh) == true)
669 0 : ret = true;
670 :
671 0 : if (nh) {
672 0 : if (path->CopyNdpData()) {
673 0 : ret = true;
674 : }
675 : }
676 :
677 0 : path->set_tunnel_bmap(1 << TunnelType::NATIVE);
678 :
679 0 : return ret;
680 0 : }
681 :
682 4 : bool Inet4UnicastGatewayRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
683 : const AgentRoute *agent_rt) {
684 4 : path->set_vrf_name(vrf_name_);
685 4 : NextHop *nh = NULL;
686 4 : InetUnicastRouteEntry *rt = NULL;
687 :
688 4 : if (gw_list_.empty() || gw_list_.size() == 1) { /* SH case */
689 4 : InetUnicastAgentRouteTable *table = NULL;
690 : table = static_cast<InetUnicastAgentRouteTable *>
691 4 : (agent->vrf_table()->GetInet4UnicastRouteTable(vrf_name_));
692 4 : IpAddress gw_ip = gw_list_.empty() ? Ip4Address(0) : gw_list_[0];
693 4 : rt = table->FindRoute(gw_ip);
694 : const NextHop *anh;
695 4 : if (rt == NULL || rt->prefix_length() == 0 || (anh = rt->GetActiveNextHop()) == NULL) {
696 4 : path->set_unresolved(true);
697 0 : } else if (anh->GetType() == NextHop::RESOLVE) {
698 0 : const ResolveNH *nh =
699 : static_cast<const ResolveNH *>(anh);
700 0 : path->set_unresolved(true);
701 0 : std::string nexthop_vrf = nh->get_interface()->vrf()->GetName();
702 0 : if (nh->get_interface()->vrf()->forwarding_vrf()) {
703 0 : nexthop_vrf = nh->get_interface()->vrf()->forwarding_vrf()->GetName();
704 : }
705 0 : InetUnicastAgentRouteTable::AddArpReq(vrf_name_, gw_ip.to_v4(),
706 : nexthop_vrf,
707 0 : nh->get_interface(), nh->PolicyEnabled(),
708 0 : vn_list_, sg_list_, tag_list_);
709 0 : } else {
710 0 : path->set_unresolved(false);
711 : }
712 : } else { /* MH case */
713 : CompositeNHKey *comp_key;
714 0 : bool comp_nh_policy = false;
715 0 : DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
716 :
717 : InetUnicastAgentRouteTable *table = static_cast<InetUnicastAgentRouteTable *>
718 0 : (agent->vrf_table()->GetInet4UnicastRouteTable(vrf_name_));
719 :
720 0 : ComponentNHKeyList comp_nh_list;
721 0 : AddressList::const_iterator ptr;
722 0 : for (ptr = gw_list_.begin(); ptr < gw_list_.end(); ptr++) {
723 0 : InetUnicastRouteEntry *uc_rt = table->FindRoute(*ptr);
724 0 : rt = uc_rt;
725 0 : if (uc_rt == NULL || uc_rt->prefix_length() == 0) {
726 0 : path->set_unresolved(true);
727 0 : break;
728 0 : } else if (uc_rt->GetActiveNextHop()->GetType() == NextHop::RESOLVE) {
729 0 : path->set_unresolved(true);
730 : const ResolveNH *nh =
731 0 : static_cast<const ResolveNH *>(uc_rt->GetActiveNextHop());
732 0 : path->set_unresolved(true);
733 0 : std::string nexthop_vrf = nh->get_interface()->vrf()->GetName();
734 0 : if (nh->get_interface()->vrf()->forwarding_vrf()) {
735 0 : nexthop_vrf = nh->get_interface()->vrf()->forwarding_vrf()->GetName();
736 : }
737 0 : InetUnicastAgentRouteTable::AddArpReq(vrf_name_, *ptr,
738 0 : nexthop_vrf, nh->get_interface(), nh->PolicyEnabled(),
739 0 : vn_list_, sg_list_, tag_list_);
740 0 : } else {
741 : DBEntryBase::KeyPtr key =
742 0 : uc_rt->GetActiveNextHop()->GetDBRequestKey();
743 0 : NextHopKey *nh_key = static_cast<NextHopKey *>(key.release());
744 0 : std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
745 : ComponentNHKeyPtr component_nh_key(new ComponentNHKey(-1,
746 0 : std::move(nh_key_ptr)));
747 0 : comp_nh_list.push_back(component_nh_key);
748 0 : }
749 : }
750 :
751 0 : if (comp_nh_list.size() == gw_list_.size()) {
752 0 : path->set_unresolved(false);
753 0 : nh_req.key.reset(new CompositeNHKey(Composite::ECMP, comp_nh_policy,
754 0 : comp_nh_list, vrf_name_));
755 0 : nh_req.data.reset(new CompositeNHData());
756 : comp_key =
757 0 : static_cast<CompositeNHKey *>(nh_req.key.get());
758 0 : nh = static_cast<NextHop *>(agent->nexthop_table()->
759 0 : FindActiveEntry(comp_key));
760 0 : if (!nh) {
761 0 : agent->nexthop_table()->Process(nh_req);
762 0 : nh = static_cast<NextHop *>(agent->nexthop_table()->
763 0 : FindActiveEntry(comp_key));
764 : }
765 : }
766 0 : }
767 :
768 4 : if (path->label() != mpls_label_) {
769 0 : path->set_label(mpls_label_);
770 : }
771 :
772 4 : if (agent->is_l3mh() == false) {
773 4 : path->set_nexthop(nh);
774 : }
775 :
776 4 : SecurityGroupList path_sg_list;
777 4 : path_sg_list = path->sg_list();
778 4 : if (path_sg_list != sg_list_) {
779 0 : path->set_sg_list(sg_list_);
780 : }
781 :
782 4 : TagList path_tag_list;
783 4 : path_tag_list = path->tag_list();
784 4 : if (path_tag_list != tag_list_) {
785 0 : path->set_tag_list(tag_list_);
786 : }
787 :
788 4 : CommunityList path_communities;
789 4 : path_communities = path->communities();
790 4 : if (path_communities != communities_) {
791 0 : path->set_communities(communities_);
792 : }
793 :
794 : //Reset to new gateway route, no nexthop for indirect route
795 4 : if (agent->is_l3mh() == false) {
796 4 : IpAddress gw_ip = gw_list_.empty() ? Ip4Address(0) : gw_list_[0];
797 4 : path->set_gw_ip(gw_ip);
798 4 : path->ResetDependantRoute(rt);
799 : }
800 :
801 4 : if (rt) {
802 4 : path->set_tunnel_bmap(rt->GetActivePath()->tunnel_bmap());
803 : }
804 :
805 4 : if (native_encap_) {
806 4 : path->set_tunnel_bmap(path->tunnel_bmap() | (1 << TunnelType::NATIVE));
807 : }
808 :
809 4 : if (path->dest_vn_list() != vn_list_) {
810 4 : path->set_dest_vn_list(vn_list_);
811 : }
812 :
813 4 : if (agent->is_l3mh() && (path->unresolved() == false) &&
814 0 : path->ChangeNH(agent, nh) == true) {
815 0 : return true;
816 : }
817 :
818 4 : return true;
819 4 : }
820 :
821 223 : InetEvpnRoutePath::InetEvpnRoutePath(const Peer *peer,
822 : const MacAddress& mac,
823 : const std::string& parent,
824 223 : AgentRoute *rt) :
825 223 : AgentPath(peer, rt), mac_(mac), parent_(parent) {
826 223 : }
827 :
828 9 : const AgentPath *InetEvpnRoutePath::UsablePath() const {
829 : //In InetEvpnRoutePath nexthop will always be NULL.
830 : //Valid NH is dependant on parent route(subnet).
831 9 : if (dependant_rt()) {
832 3 : const AgentPath *path = dependant_rt()->GetActivePath();
833 3 : if (path != NULL)
834 3 : return path;
835 : }
836 6 : return this;
837 : }
838 :
839 2045 : bool InetEvpnRoutePath::SyncDependantRoute(const AgentRoute *sync_route) {
840 : const InetUnicastRouteEntry *dependant_route =
841 2045 : dynamic_cast<const InetUnicastRouteEntry *>(dependant_rt());
842 : InetUnicastAgentRouteTable *table =
843 2045 : static_cast<InetUnicastAgentRouteTable *>(sync_route->get_table());
844 : InetUnicastRouteEntry *parent_subnet_route =
845 2045 : table->GetSuperNetRoute(dynamic_cast<const InetUnicastRouteEntry *>
846 4090 : (sync_route)->prefix_address());
847 :
848 2045 : if (parent_subnet_route != dependant_route) {
849 244 : set_gw_ip(parent_subnet_route ? parent_subnet_route->prefix_address() :
850 : IpAddress());
851 244 : if (parent_subnet_route) {
852 218 : ResetDependantRoute(parent_subnet_route);
853 218 : set_unresolved(false);
854 : } else {
855 : //Clear old dependant route
856 26 : ClearDependantRoute();
857 26 : set_unresolved(true);
858 : }
859 244 : return true;
860 : }
861 1801 : return false;
862 : }
863 :
864 1276 : bool InetEvpnRoutePath::Sync(AgentRoute *sync_route) {
865 1276 : return SyncDependantRoute(sync_route);
866 : }
867 :
868 992 : const NextHop* InetEvpnRoutePath::ComputeNextHop(Agent *agent) const {
869 : //InetEvpnRoutePath is deleted when parent evpn route is going off.
870 : //Now it may happen that supernet route which was used as dependant_rt in
871 : //this path has been deleted.
872 1888 : if ((dependant_rt() == NULL) ||
873 896 : (dependant_rt()->GetActiveNextHop() == NULL)) {
874 96 : DiscardNH key;
875 96 : return static_cast<NextHop *>
876 96 : (agent->nexthop_table()->FindActiveEntry(&key));
877 96 : }
878 :
879 896 : return AgentPath::ComputeNextHop(agent);
880 : }
881 :
882 6784 : bool InetEvpnRoutePath::IsLess(const AgentPath &r_path) const {
883 6784 : const InetEvpnRoutePath *r_evpn_path =
884 6784 : dynamic_cast<const InetEvpnRoutePath *>(&r_path);
885 6784 : if (r_evpn_path != NULL) {
886 1066 : if (r_evpn_path->MacAddr() != mac_) {
887 1066 : return (mac_ < r_evpn_path->MacAddr());
888 : }
889 : }
890 :
891 5718 : return peer()->IsLess(r_path.peer());
892 : }
893 1107 : InetEvpnRouteData::InetEvpnRouteData(const EvpnRouteEntry *evpn_rt):
894 : AgentRouteData(AgentRouteData::ADD_DEL_CHANGE,
895 1107 : evpn_rt->is_multicast(), 0),
896 1107 : mac_(evpn_rt->mac()) {
897 1107 : std::stringstream s;
898 1107 : s << evpn_rt->ToString();
899 1107 : s << " ";
900 1107 : parent_ = s.str();
901 1107 : }
902 :
903 223 : AgentPath *InetEvpnRouteData::CreateAgentPath(const Peer *peer,
904 : AgentRoute *rt) const {
905 223 : return (new InetEvpnRoutePath(peer, mac_, parent_, rt));
906 : }
907 :
908 769 : bool InetEvpnRouteData::AddChangePathExtended(Agent *agent,
909 : AgentPath *path,
910 : const AgentRoute *route) {
911 769 : return dynamic_cast<InetEvpnRoutePath *>(path)->SyncDependantRoute(route);
912 : }
913 :
914 280 : bool InetEvpnRouteData::CanDeletePath(Agent *agent, AgentPath *path,
915 : const AgentRoute *rt) const {
916 : const InetEvpnRoutePath *evpn_path =
917 280 : dynamic_cast<const InetEvpnRoutePath *>(path);
918 280 : if (evpn_path == NULL) {
919 0 : return true;
920 : }
921 280 : return (evpn_path->MacAddr() == MacAddr());
922 : }
923 :
924 0 : Inet4UnicastInterfaceRoute::Inet4UnicastInterfaceRoute
925 0 : (const PhysicalInterface *intrface, const std::string &vn_name) :
926 : AgentRouteData(AgentRouteData::ADD_DEL_CHANGE, false, 0),
927 0 : interface_key_(new PhysicalInterfaceKey(intrface->name())),
928 0 : vn_name_(vn_name) {
929 0 : }
930 :
931 0 : bool Inet4UnicastInterfaceRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
932 : const AgentRoute *rt) {
933 0 : bool ret = false;
934 :
935 0 : path->set_unresolved(false);
936 0 : VnListType vn_list;
937 0 : vn_list.insert(agent->fabric_vn_name());
938 0 : if (path->dest_vn_list() != vn_list) {
939 0 : path->set_dest_vn_list(vn_list);
940 0 : ret = true;
941 : }
942 :
943 0 : Interface *intf = static_cast<Interface *>(
944 0 : agent->interface_table()->FindActiveEntry(interface_key_.get()));
945 0 : assert(intf);
946 0 : InterfaceNHKey key(interface_key_->Clone(), false,
947 0 : InterfaceNHFlags::INET4, intf->mac());
948 0 : NextHop *nh = static_cast<NextHop *>
949 0 : (agent->nexthop_table()->FindActiveEntry(&key));
950 0 : assert(nh);
951 0 : if (path->ChangeNH(agent, nh) == true) {
952 0 : ret = true;
953 : }
954 :
955 0 : return ret;
956 0 : }
957 :
958 : /////////////////////////////////////////////////////////////////////////////
959 : // Sandesh functions
960 : /////////////////////////////////////////////////////////////////////////////
961 :
962 0 : bool InetUnicastRouteEntry::DBEntrySandesh(Sandesh *sresp, bool stale) const {
963 :
964 0 : RouteUcSandeshData data;
965 0 : data.set_src_ip(prefix_address_.to_string());
966 0 : data.set_src_plen(prefix_length());
967 0 : data.set_ipam_subnet_route(ipam_subnet_route_);
968 0 : data.set_ipam_host_route(ipam_host_route_);
969 0 : data.set_proxy_arp(proxy_arp_);
970 0 : data.set_src_vrf(vrf()->GetName());
971 0 : data.set_multicast(AgentRoute::is_multicast());
972 0 : data.set_intf_route_type(AgentRoute::intf_route_type());
973 0 : for (Route::PathList::const_iterator it = GetPathList().begin();
974 0 : it != GetPathList().end(); it++) {
975 0 : const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
976 0 : if (path) {
977 0 : PathSandeshData pdata;
978 0 : path->SetSandeshData(pdata);
979 0 : if (vrf()->GetName() == Agent::GetInstance()->fabric_vrf_name()
980 0 : && (path->tunnel_bmap() & TunnelType::NativeType())) {
981 0 : pdata.set_active_tunnel_type("Native");
982 : }
983 0 : data.path_list.push_back(pdata);
984 0 : }
985 : }
986 :
987 0 : if (prefix_address_.is_v4()) {
988 0 : Inet4UcRouteResp *v4_resp = static_cast<Inet4UcRouteResp *>(sresp);
989 : std::vector<RouteUcSandeshData> &list =
990 0 : const_cast<std::vector<RouteUcSandeshData>&>(v4_resp->get_route_list());
991 0 : list.push_back(data);
992 : } else {
993 0 : Inet6UcRouteResp *v6_resp = static_cast<Inet6UcRouteResp *>(sresp);
994 : std::vector<RouteUcSandeshData> &list =
995 0 : const_cast<std::vector<RouteUcSandeshData>&>(v6_resp->get_route_list());
996 0 : list.push_back(data);
997 : }
998 0 : return true;
999 0 : }
1000 :
1001 0 : bool InetUnicastRouteEntry::DBEntrySandesh(Sandesh *sresp, IpAddress addr,
1002 : uint8_t plen, bool stale) const {
1003 0 : if (prefix_address_ == addr && prefix_length() == plen) {
1004 0 : return DBEntrySandesh(sresp, stale);
1005 : }
1006 :
1007 0 : return false;
1008 : }
1009 :
1010 0 : void UnresolvedRoute::HandleRequest() const {
1011 0 : VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromId(0);
1012 0 : if (!vrf) {
1013 0 : ErrorResp *resp = new ErrorResp();
1014 0 : resp->set_context(context());
1015 0 : resp->Response();
1016 0 : return;
1017 : }
1018 :
1019 0 : int count = 0;
1020 0 : Inet4UcRouteResp *resp = new Inet4UcRouteResp();
1021 :
1022 : //TODO - Convert inet4ucroutetable to agentroutetable
1023 : AgentRouteTable *rt_table = static_cast<AgentRouteTable *>
1024 0 : (vrf->GetInet4UnicastRouteTable());
1025 0 : InetUnicastAgentRouteTable::UnresolvedRouteTree::const_iterator it;
1026 0 : it = rt_table->unresolved_route_begin();
1027 0 : for (;it != rt_table->unresolved_route_end(); it++) {
1028 0 : count++;
1029 0 : const AgentRoute *rt = *it;
1030 0 : rt->DBEntrySandesh(resp, false);
1031 0 : if (count == 1) {
1032 0 : resp->set_context(context()+"$");
1033 0 : resp->Response();
1034 0 : count = 0;
1035 0 : resp = new Inet4UcRouteResp();
1036 : }
1037 : }
1038 :
1039 0 : resp->set_context(context());
1040 0 : resp->Response();
1041 0 : return;
1042 : }
1043 :
1044 0 : void Inet4UcRouteReq::HandleRequest() const {
1045 : VrfEntry *vrf =
1046 0 : Agent::GetInstance()->vrf_table()->FindVrfFromId(get_vrf_index());
1047 0 : if (!vrf) {
1048 0 : ErrorResp *resp = new ErrorResp();
1049 0 : resp->set_context(context());
1050 0 : resp->Response();
1051 0 : return;
1052 : }
1053 :
1054 0 : AgentSandeshPtr sand;
1055 0 : if (get_src_ip().empty()) {
1056 0 : sand.reset(new AgentInet4UcRtSandesh(vrf, context(), get_stale()));
1057 : } else {
1058 0 : boost::system::error_code ec;
1059 0 : Ip4Address src_ip = Ip4Address::from_string(get_src_ip(), ec);
1060 0 : sand.reset(new AgentInet4UcRtSandesh(vrf, context(), src_ip,
1061 0 : (uint8_t)get_prefix_len(),
1062 0 : get_stale()));
1063 : }
1064 0 : sand->DoSandesh(sand);
1065 0 : }
1066 :
1067 0 : void Inet4MplsUcRouteReq::HandleRequest() const {
1068 : VrfEntry *vrf =
1069 0 : Agent::GetInstance()->vrf_table()->FindVrfFromId(get_vrf_index());
1070 0 : if (!vrf) {
1071 0 : ErrorResp *resp = new ErrorResp();
1072 0 : resp->set_context(context());
1073 0 : resp->Response();
1074 0 : return;
1075 : }
1076 :
1077 0 : AgentSandeshPtr sand;
1078 0 : if (get_src_ip().empty()) {
1079 0 : sand.reset(new AgentInet4MplsUcRtSandesh(vrf, context(), get_stale()));
1080 : } else {
1081 0 : boost::system::error_code ec;
1082 0 : Ip4Address src_ip = Ip4Address::from_string(get_src_ip(), ec);
1083 0 : sand.reset(new AgentInet4MplsUcRtSandesh(vrf, context(), src_ip,
1084 0 : (uint8_t)get_prefix_len(),
1085 0 : get_stale()));
1086 : }
1087 0 : sand->DoSandesh(sand);
1088 0 : }
1089 :
1090 0 : AgentSandeshPtr InetUnicastAgentRouteTable::GetAgentSandesh
1091 : (const AgentSandeshArguments *args, const std::string &context) {
1092 0 : if (type_ == Agent::INET4_UNICAST) {
1093 0 : return AgentSandeshPtr(new AgentInet4UcRtSandesh(vrf_entry(), context,
1094 0 : false));
1095 0 : } else if (type_ == Agent::INET4_MPLS) {
1096 0 : return AgentSandeshPtr(new AgentInet4MplsUcRtSandesh(vrf_entry(), context,
1097 0 : false));
1098 : } else {
1099 0 : return AgentSandeshPtr(new AgentInet6UcRtSandesh(vrf_entry(), context,
1100 0 : false));
1101 : }
1102 : }
1103 :
1104 0 : void Inet6UcRouteReq::HandleRequest() const {
1105 : VrfEntry *vrf =
1106 0 : Agent::GetInstance()->vrf_table()->FindVrfFromId(get_vrf_index());
1107 0 : if (!vrf) {
1108 0 : ErrorResp *resp = new ErrorResp();
1109 0 : resp->set_context(context());
1110 0 : resp->Response();
1111 0 : return;
1112 : }
1113 :
1114 0 : AgentSandeshPtr sand;
1115 0 : if (get_src_ip().empty()) {
1116 0 : sand.reset(new AgentInet6UcRtSandesh(vrf, context(), get_stale()));
1117 : } else {
1118 0 : boost::system::error_code ec;
1119 0 : Ip6Address src_ip = Ip6Address::from_string(get_src_ip(), ec);
1120 0 : sand.reset(new AgentInet6UcRtSandesh(vrf, context(), src_ip,
1121 0 : (uint8_t)get_prefix_len(),
1122 0 : get_stale()));
1123 : }
1124 0 : sand->DoSandesh(sand);
1125 0 : }
1126 :
1127 : /////////////////////////////////////////////////////////////////////////////
1128 : // Helper functions to enqueue request or process inline
1129 : /////////////////////////////////////////////////////////////////////////////
1130 :
1131 : // Request to delete an entry
1132 : void
1133 1063 : InetUnicastAgentRouteTable::DeleteReq(const Peer *peer, const string &vrf_name,
1134 : const IpAddress &addr, uint8_t plen,
1135 : AgentRouteData *data) {
1136 1063 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
1137 1063 : req.key.reset(new InetUnicastRouteKey(peer, vrf_name, addr, plen));
1138 1063 : req.data.reset(data);
1139 1063 : InetUnicastTableEnqueue(Agent::GetInstance(), vrf_name, &req);
1140 :
1141 1063 : }
1142 :
1143 : // Inline delete request
1144 : void
1145 952 : InetUnicastAgentRouteTable::Delete(const Peer *peer, const string &vrf_name,
1146 : const IpAddress &addr, uint8_t plen) {
1147 952 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
1148 952 : req.key.reset(new InetUnicastRouteKey(peer, vrf_name, addr, plen));
1149 952 : req.data.reset(NULL);
1150 952 : InetUnicastTableProcess(Agent::GetInstance(), vrf_name, req);
1151 952 : }
1152 :
1153 : void
1154 0 : InetUnicastAgentRouteTable::Delete(const Peer *peer, const string &vrf_name,
1155 : const IpAddress &addr, uint8_t plen,
1156 : AgentRouteData *data) {
1157 0 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
1158 0 : req.key.reset(new InetUnicastRouteKey(peer, vrf_name, addr, plen));
1159 0 : req.data.reset(data);
1160 0 : InetUnicastTableProcess(Agent::GetInstance(), vrf_name, req);
1161 0 : }
1162 :
1163 : void
1164 0 : InetUnicastAgentRouteTable::DeleteMplsRouteReq(const Peer *peer, const string &vrf_name,
1165 : const IpAddress &addr, uint8_t plen,
1166 : AgentRouteData *data) {
1167 0 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
1168 0 : req.key.reset(new InetMplsUnicastRouteKey(peer, vrf_name, addr, plen));
1169 0 : req.data.reset(data);
1170 0 : Inet4MplsUnicastTableEnqueue(Agent::GetInstance(), &req);
1171 0 : }
1172 :
1173 : // Utility function to create a route to trap packets to agent.
1174 : // Assumes that Interface-NH for "HOST Interface" is already present
1175 : void
1176 358 : InetUnicastAgentRouteTable::AddHostRoute(const string &vrf_name,
1177 : const IpAddress &addr,
1178 : uint8_t plen,
1179 : const std::string &dest_vn_name,
1180 : bool policy) {
1181 358 : Agent *agent = Agent::GetInstance();
1182 358 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
1183 716 : req.key.reset(new InetUnicastRouteKey(agent->local_peer(), vrf_name,
1184 358 : addr, plen));
1185 :
1186 0 : PacketInterfaceKey intf_key(boost::uuids::nil_uuid(),
1187 358 : agent->GetHostInterfaceName());
1188 358 : HostRoute *data = new HostRoute(intf_key, dest_vn_name);
1189 358 : data->set_policy(policy);
1190 358 : req.data.reset(data);
1191 :
1192 358 : InetUnicastTableEnqueue(Agent::GetInstance(), vrf_name, &req);
1193 358 : }
1194 :
1195 : // Create Route with VLAN NH
1196 : void
1197 0 : InetUnicastAgentRouteTable::AddVlanNHRouteReq(const Peer *peer,
1198 : const string &vm_vrf,
1199 : const IpAddress &addr,
1200 : uint8_t plen,
1201 : VlanNhRoute *data) {
1202 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
1203 0 : req.key.reset(new InetUnicastRouteKey(peer, vm_vrf, addr, plen));
1204 0 : req.data.reset(data);
1205 0 : InetUnicastTableEnqueue(Agent::GetInstance(), vm_vrf, &req);
1206 0 : }
1207 :
1208 : void
1209 0 : InetUnicastAgentRouteTable::AddVlanNHRouteReq(const Peer *peer,
1210 : const string &vm_vrf,
1211 : const IpAddress &addr,
1212 : uint8_t plen,
1213 : const boost::uuids::uuid &intf_uuid,
1214 : uint16_t tag,
1215 : uint32_t label,
1216 : const VnListType &dest_vn_list,
1217 : const SecurityGroupList &sg_list,
1218 : const TagList &tag_list,
1219 : const PathPreference
1220 : &path_preference) {
1221 0 : VmInterfaceKey intf_key(AgentKey::ADD_DEL_CHANGE, intf_uuid, "");
1222 : VlanNhRoute *data = new VlanNhRoute(intf_key, tag, label, dest_vn_list,
1223 : sg_list, tag_list, path_preference,
1224 0 : peer->sequence_number());
1225 0 : AddVlanNHRouteReq(peer, vm_vrf, addr, plen, data);
1226 0 : }
1227 :
1228 : // Create Route with VLAN NH
1229 : void
1230 0 : InetUnicastAgentRouteTable::AddVlanNHRoute(const Peer *peer,
1231 : const string &vm_vrf,
1232 : const IpAddress &addr,
1233 : uint8_t plen,
1234 : const boost::uuids::uuid &intf_uuid,
1235 : uint16_t tag,
1236 : uint32_t label,
1237 : const VnListType &dest_vn_list,
1238 : const SecurityGroupList &sg_list,
1239 : const TagList &tag_list,
1240 : const PathPreference
1241 : &path_preference) {
1242 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
1243 0 : req.key.reset(new InetUnicastRouteKey(peer, vm_vrf, addr, plen));
1244 :
1245 0 : VmInterfaceKey intf_key(AgentKey::ADD_DEL_CHANGE, intf_uuid, "");
1246 0 : req.data.reset(new VlanNhRoute(intf_key, tag, label, dest_vn_list,
1247 : sg_list, tag_list, path_preference,
1248 0 : peer->sequence_number()));
1249 0 : InetUnicastTableProcess(Agent::GetInstance(), vm_vrf, req);
1250 0 : }
1251 :
1252 : void
1253 330 : InetUnicastAgentRouteTable::AddLocalVmRouteReq(const Peer *peer,
1254 : const string &vm_vrf,
1255 : const IpAddress &addr,
1256 : uint8_t plen,
1257 : LocalVmRoute *data) {
1258 330 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
1259 330 : req.key.reset(new InetUnicastRouteKey(peer, vm_vrf, addr, plen));
1260 :
1261 330 : req.data.reset(data);
1262 :
1263 330 : InetUnicastTableEnqueue(Agent::GetInstance(), vm_vrf, &req);
1264 330 : }
1265 :
1266 : void
1267 330 : InetUnicastAgentRouteTable::AddLocalVmRouteReq(const Peer *peer,
1268 : const string &vm_vrf,
1269 : const IpAddress &addr,
1270 : uint8_t plen,
1271 : const boost::uuids::uuid &intf_uuid,
1272 : const VnListType &vn_list,
1273 : uint32_t label,
1274 : const SecurityGroupList &sg_list,
1275 : const TagList &tag_list,
1276 : const CommunityList &communities,
1277 : bool force_policy,
1278 : const PathPreference
1279 : &path_preference,
1280 : const IpAddress &subnet_service_ip,
1281 : const EcmpLoadBalance &ecmp_load_balance,
1282 : bool is_local,
1283 : bool is_health_check_service,
1284 : bool native_encap,
1285 : const std::string &intf_name,
1286 : bool is_learnt_route)
1287 : {
1288 330 : VmInterfaceKey intf_key(AgentKey::ADD_DEL_CHANGE, intf_uuid, intf_name);
1289 : LocalVmRoute *data = new LocalVmRoute(intf_key, label,
1290 : VxLanTable::kInvalidvxlan_id, force_policy,
1291 : vn_list, InterfaceNHFlags::INET4, sg_list,
1292 : tag_list, communities, path_preference,
1293 : subnet_service_ip, ecmp_load_balance,
1294 : is_local, is_health_check_service,
1295 330 : peer->sequence_number(),
1296 330 : false, native_encap);
1297 :
1298 330 : AddLocalVmRouteReq(peer, vm_vrf, addr, plen, data);
1299 330 : }
1300 :
1301 2 : void InetUnicastAgentRouteTable::ResyncRoute(const Peer *peer,
1302 : const string &vrf,
1303 : const IpAddress &addr,
1304 : uint8_t plen) {
1305 2 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
1306 :
1307 2 : InetUnicastRouteKey *key = new InetUnicastRouteKey(peer, vrf, addr, plen);
1308 2 : key->sub_op_ = AgentKey::RESYNC;
1309 2 : req.key.reset(key);
1310 2 : req.data.reset(NULL);
1311 2 : InetUnicastTableEnqueue(Agent::GetInstance(), vrf, &req);
1312 2 : }
1313 :
1314 : void
1315 0 : InetUnicastAgentRouteTable::AddClonedLocalPathReq(const Peer *peer,
1316 : const string &vm_vrf,
1317 : const IpAddress &addr,
1318 : uint8_t plen,
1319 : ClonedLocalPath *data) {
1320 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
1321 0 : req.key.reset(new InetUnicastRouteKey(peer, vm_vrf, addr, plen));
1322 0 : req.data.reset(data);
1323 0 : InetUnicastTableEnqueue(Agent::GetInstance(), vm_vrf, &req);
1324 0 : }
1325 :
1326 : // Create Route for a local VM
1327 : // Assumes that Interface-NH for "VM Port" is already present
1328 : void
1329 752 : InetUnicastAgentRouteTable::AddLocalVmRoute(const Peer *peer,
1330 : const string &vm_vrf,
1331 : const IpAddress &addr,
1332 : uint8_t plen,
1333 : const boost::uuids::uuid &intf_uuid,
1334 : const VnListType &vn_list,
1335 : uint32_t label,
1336 : const SecurityGroupList &sg_list,
1337 : const TagList &tag_list,
1338 : const CommunityList &communities,
1339 : bool force_policy,
1340 : const PathPreference
1341 : &path_preference,
1342 : const IpAddress &subnet_service_ip,
1343 : const EcmpLoadBalance &ecmp_load_balance,
1344 : bool is_local,
1345 : bool is_health_check_service,
1346 : const std::string &intf_name,
1347 : bool native_encap,
1348 : const std::string &intf_route_type,
1349 : bool is_learnt_route)
1350 : {
1351 752 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
1352 752 : req.key.reset(new InetUnicastRouteKey(peer, vm_vrf, addr, plen));
1353 :
1354 752 : VmInterfaceKey intf_key(AgentKey::ADD_DEL_CHANGE, intf_uuid, intf_name);
1355 752 : req.data.reset(new LocalVmRoute(intf_key, label, VxLanTable::kInvalidvxlan_id,
1356 : force_policy, vn_list,
1357 : InterfaceNHFlags::INET4, sg_list, tag_list,
1358 : communities, path_preference,
1359 : subnet_service_ip,
1360 : ecmp_load_balance, is_local,
1361 : is_health_check_service,
1362 752 : peer->sequence_number(), false, native_encap,
1363 : intf_route_type,
1364 752 : is_learnt_route));
1365 752 : InetUnicastTableProcess(Agent::GetInstance(), vm_vrf, req);
1366 752 : }
1367 :
1368 : void
1369 74 : InetUnicastAgentRouteTable::AddRemoteVmRouteReq(const Peer *peer,
1370 : const string &vm_vrf,
1371 : const IpAddress &vm_addr,
1372 : uint8_t plen,
1373 : AgentRouteData *data) {
1374 74 : if (Agent::GetInstance()->simulate_evpn_tor())
1375 0 : return;
1376 74 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
1377 74 : req.key.reset(new InetUnicastRouteKey(peer, vm_vrf, vm_addr, plen));
1378 74 : req.data.reset(data);
1379 74 : InetUnicastTableEnqueue(Agent::GetInstance(), vm_vrf, &req);
1380 74 : }
1381 :
1382 : void
1383 4 : InetUnicastAgentRouteTable::AddArpReq(const string &route_vrf_name,
1384 : const Ip4Address &ip,
1385 : const string &nexthop_vrf_name,
1386 : const Interface *intf, bool policy,
1387 : const VnListType &vn_list,
1388 : const SecurityGroupList &sg_list,
1389 : const TagList &tag_list) {
1390 4 : Agent *agent = Agent::GetInstance();
1391 4 : ArpNHKey key(route_vrf_name, ip, policy);
1392 : NextHop *nh =
1393 4 : static_cast<NextHop *>(agent->nexthop_table()->FindActiveEntry(&key));
1394 4 : if (!nh) {
1395 4 : DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
1396 4 : nh_req.key.reset(new ArpNHKey(route_vrf_name, ip, policy));
1397 4 : nh_req.data.reset(new ArpNHData(
1398 8 : static_cast<InterfaceKey *>(intf->GetDBRequestKey().release())));
1399 4 : agent->nexthop_table()->Enqueue(&nh_req);
1400 4 : }
1401 4 : DBRequest rt_req(DBRequest::DB_ENTRY_ADD_CHANGE);
1402 8 : rt_req.key.reset(new InetUnicastRouteKey(agent->local_peer(),
1403 4 : route_vrf_name, ip, 32));
1404 4 : rt_req.data.reset(new Inet4UnicastArpRoute(nexthop_vrf_name, ip, policy,
1405 4 : vn_list, sg_list, tag_list));
1406 4 : Inet4UnicastTableEnqueue(agent, &rt_req);
1407 4 : }
1408 :
1409 : void
1410 6 : InetUnicastAgentRouteTable::ArpRoute(DBRequest::DBOperation op,
1411 : const string &route_vrf_name,
1412 : const Ip4Address &ip,
1413 : const MacAddress &mac,
1414 : const string &nexthop_vrf_name,
1415 : const Interface &intf,
1416 : bool resolved,
1417 : const uint8_t plen,
1418 : bool policy,
1419 : const VnListType &vn_list,
1420 : const SecurityGroupList &sg,
1421 : const TagList &tag) {
1422 6 : Agent *agent = Agent::GetInstance();
1423 6 : DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
1424 6 : ArpNHKey *nh_key = new ArpNHKey(nexthop_vrf_name, ip, policy);
1425 6 : if (op == DBRequest::DB_ENTRY_DELETE) {
1426 : //In case of delete we want to set the
1427 : //nexthop as invalid, hence use resync operation
1428 : //We dont want the nexthop to created again
1429 : //in case of duplicate delete
1430 2 : nh_key->sub_op_ = AgentKey::RESYNC;
1431 : }
1432 6 : nh_req.key.reset(nh_key);
1433 : ArpNHData *arp_data = new ArpNHData(mac,
1434 6 : static_cast<InterfaceKey *>(intf.GetDBRequestKey().release()),
1435 6 : resolved);
1436 6 : nh_req.data.reset(arp_data);
1437 :
1438 6 : DBRequest rt_req(op);
1439 : InetUnicastRouteKey *rt_key =
1440 6 : new InetUnicastRouteKey(agent->local_peer(), route_vrf_name, ip, plen);
1441 6 : Inet4UnicastArpRoute *data = NULL;
1442 :
1443 6 : switch(op) {
1444 4 : case DBRequest::DB_ENTRY_ADD_CHANGE:
1445 4 : agent->nexthop_table()->Enqueue(&nh_req);
1446 4 : data = new Inet4UnicastArpRoute(nexthop_vrf_name, ip, policy,
1447 4 : vn_list, sg, tag);
1448 4 : break;
1449 :
1450 2 : case DBRequest::DB_ENTRY_DELETE: {
1451 2 : VrfEntry *vrf = agent->vrf_table()->FindVrfFromName(route_vrf_name);
1452 : InetUnicastRouteEntry *rt =
1453 : static_cast<InetUnicastRouteEntry *>(vrf->
1454 2 : GetInet4UnicastRouteTable()->Find(rt_key));
1455 2 : assert(resolved==false);
1456 2 : agent->nexthop_table()->Enqueue(&nh_req);
1457 :
1458 : // If no other route is dependent on this, remove the route; else ignore
1459 2 : if (rt && rt->IsDependantRouteEmpty() && rt->IsTunnelNHListEmpty()) {
1460 2 : data = new Inet4UnicastArpRoute(nexthop_vrf_name, ip, policy,
1461 2 : vn_list, sg, tag);
1462 : } else {
1463 0 : rt_key->sub_op_ = AgentKey::RESYNC;
1464 0 : rt_req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
1465 : }
1466 2 : break;
1467 : }
1468 :
1469 0 : default:
1470 0 : assert(0);
1471 : }
1472 :
1473 6 : rt_req.key.reset(rt_key);
1474 6 : rt_req.data.reset(data);
1475 6 : Inet4UnicastTableEnqueue(agent, &rt_req);
1476 6 : }
1477 :
1478 : void
1479 0 : InetUnicastAgentRouteTable::NdpRoute(DBRequest::DBOperation op,
1480 : const string &route_vrf_name,
1481 : const IpAddress &ip,
1482 : const MacAddress &mac,
1483 : const string &nexthop_vrf_name,
1484 : const Interface &intf,
1485 : bool resolved,
1486 : const uint8_t plen,
1487 : bool policy,
1488 : const VnListType &vn_list,
1489 : const SecurityGroupList &sg,
1490 : const TagList &tag) {
1491 0 : Agent *agent = Agent::GetInstance();
1492 0 : DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
1493 0 : NdpNHKey *nh_key = new NdpNHKey(nexthop_vrf_name, ip, policy);
1494 0 : if (op == DBRequest::DB_ENTRY_DELETE) {
1495 : //In case of delete we want to set the
1496 : //nexthop as invalid, hence use resync operation
1497 : //We dont want the nexthop to created again
1498 : //in case of duplicate delete
1499 0 : nh_key->sub_op_ = AgentKey::RESYNC;
1500 : }
1501 0 : nh_req.key.reset(nh_key);
1502 : NdpNHData *ndp_data = new NdpNHData(mac,
1503 0 : static_cast<InterfaceKey *>(intf.GetDBRequestKey().release()),
1504 0 : resolved);
1505 0 : nh_req.data.reset(ndp_data);
1506 :
1507 0 : DBRequest rt_req(op);
1508 : InetUnicastRouteKey *rt_key =
1509 0 : new InetUnicastRouteKey(agent->local_peer(), route_vrf_name, ip, plen);
1510 0 : InetUnicastNdpRoute *data = NULL;
1511 :
1512 0 : switch(op) {
1513 0 : case DBRequest::DB_ENTRY_ADD_CHANGE:
1514 0 : agent->nexthop_table()->Enqueue(&nh_req);
1515 0 : data = new InetUnicastNdpRoute(nexthop_vrf_name, ip, policy,
1516 0 : vn_list, sg, tag);
1517 0 : break;
1518 :
1519 0 : case DBRequest::DB_ENTRY_DELETE: {
1520 0 : VrfEntry *vrf = agent->vrf_table()->FindVrfFromName(route_vrf_name);
1521 : InetUnicastRouteEntry *rt =
1522 : static_cast<InetUnicastRouteEntry *>(vrf->
1523 0 : GetInet6UnicastRouteTable()->Find(rt_key));
1524 0 : assert(resolved==false);
1525 0 : agent->nexthop_table()->Enqueue(&nh_req);
1526 :
1527 : // If no other route is dependent on this, remove the route; else ignore
1528 0 : if (rt && rt->IsDependantRouteEmpty() && rt->IsTunnelNHListEmpty()) {
1529 0 : data = new InetUnicastNdpRoute(nexthop_vrf_name, ip, policy,
1530 0 : vn_list, sg, tag);
1531 : } else {
1532 0 : rt_key->sub_op_ = AgentKey::RESYNC;
1533 0 : rt_req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
1534 : }
1535 0 : break;
1536 : }
1537 :
1538 0 : default:
1539 0 : assert(0);
1540 : }
1541 :
1542 0 : rt_req.key.reset(rt_key);
1543 0 : rt_req.data.reset(data);
1544 0 : Inet6UnicastTableEnqueue(agent, route_vrf_name, &rt_req);
1545 0 : }
1546 :
1547 0 : bool InetUnicastAgentRouteTable::ShouldAddArp(const Ip4Address &ip) {
1548 0 : if (ip == Agent::GetInstance()->router_id() ||
1549 0 : !IsIp4SubnetMember(ip, Agent::GetInstance()->router_id(),
1550 0 : Agent::GetInstance()->vhost_prefix_len())) {
1551 : // TODO: add Arp request for GW
1552 : // Currently, default GW Arp is added during init
1553 0 : return false;
1554 : }
1555 :
1556 0 : return true;
1557 : }
1558 :
1559 : void
1560 0 : InetUnicastAgentRouteTable::CheckAndAddArpRoute(const string &route_vrf_name,
1561 : const Ip4Address &ip,
1562 : const MacAddress &mac,
1563 : const Interface *intf,
1564 : bool resolved,
1565 : const VnListType &vn_list,
1566 : const SecurityGroupList &sg,
1567 : const TagList &tag) {
1568 0 : if (!ShouldAddArp(ip)) {
1569 0 : return;
1570 : }
1571 0 : std::string nexthop_vrf = intf->vrf()->GetName();
1572 0 : if (intf->vrf()->forwarding_vrf()) {
1573 0 : nexthop_vrf = intf->vrf()->forwarding_vrf()->GetName();
1574 : }
1575 0 : ArpRoute(DBRequest::DB_ENTRY_ADD_CHANGE, route_vrf_name, ip, mac,
1576 : nexthop_vrf, *intf, resolved, 32, false, vn_list, sg, tag);
1577 0 : }
1578 :
1579 : void
1580 0 : InetUnicastAgentRouteTable::CheckAndAddArpReq(const string &vrf_name,
1581 : const Ip4Address &ip,
1582 : const Interface *intf,
1583 : const VnListType &vn_list,
1584 : const SecurityGroupList &sg,
1585 : const TagList &tag) {
1586 :
1587 0 : if (!ShouldAddArp(ip)) {
1588 0 : return;
1589 : }
1590 0 : std::string nexthop_vrf = intf->vrf()->GetName();
1591 0 : if (intf->vrf()->forwarding_vrf()) {
1592 0 : nexthop_vrf = intf->vrf()->forwarding_vrf()->GetName();
1593 : }
1594 0 : AddArpReq(vrf_name, ip, nexthop_vrf, intf, false, vn_list, sg, tag);
1595 0 : }
1596 :
1597 2 : void InetUnicastAgentRouteTable::AddResolveRoute(const Peer *peer,
1598 : const string &vrf_name,
1599 : const Ip4Address &ip,
1600 : const uint8_t plen,
1601 : const InterfaceKey &intf,
1602 : const uint32_t label,
1603 : bool policy,
1604 : const std::string &vn_name,
1605 : const SecurityGroupList
1606 : &sg_list,
1607 : const TagList
1608 : &tag_list) {
1609 2 : Agent *agent = Agent::GetInstance();
1610 2 : ResolveNH::CreateReq(&intf, policy);
1611 2 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
1612 4 : req.key.reset(new InetUnicastRouteKey(peer, vrf_name, ip,
1613 2 : plen));
1614 2 : req.data.reset(new ResolveRoute(&intf, policy, label, vn_name, sg_list, tag_list));
1615 2 : Inet4UnicastTableEnqueue(agent, &req);
1616 2 : }
1617 :
1618 : // Create Route for a interface NH.
1619 : // Used to create interface-nh pointing routes to vhost interfaces
1620 0 : void InetUnicastAgentRouteTable::AddInetInterfaceRouteReq(const Peer *peer,
1621 : const string &vm_vrf,
1622 : const Ip4Address &addr,
1623 : uint8_t plen,
1624 : const string &interface,
1625 : uint32_t label,
1626 : const VnListType &vn_list) {
1627 0 : InetInterfaceKey intf_key(interface);
1628 : InetInterfaceRoute *data = new InetInterfaceRoute
1629 0 : (intf_key, label, TunnelType::MplsType(), vn_list,
1630 0 : peer->sequence_number());
1631 :
1632 0 : AddInetInterfaceRouteReq(peer, vm_vrf, addr, plen, data);
1633 0 : }
1634 :
1635 0 : void InetUnicastAgentRouteTable::AddInetInterfaceRouteReq(const Peer *peer,
1636 : const string &vm_vrf,
1637 : const Ip4Address &addr,
1638 : uint8_t plen,
1639 : InetInterfaceRoute *data) {
1640 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
1641 0 : req.key.reset(new InetUnicastRouteKey(peer, vm_vrf, addr, plen));
1642 0 : req.data.reset(data);
1643 :
1644 0 : Inet4UnicastTableEnqueue(Agent::GetInstance(), &req);
1645 0 : }
1646 :
1647 16 : static void AddVHostRecvRouteInternal(DBRequest *req, const Peer *peer,
1648 : const string &vrf,
1649 : const InterfaceKey &intf_key,
1650 : const IpAddress &addr, uint8_t plen,
1651 : const string &vn_name, bool policy,
1652 : bool native_encap) {
1653 16 : req->oper = DBRequest::DB_ENTRY_ADD_CHANGE;
1654 16 : req->key.reset(new InetUnicastRouteKey(peer, vrf, addr, plen));
1655 :
1656 16 : int tunnel_bmap = TunnelType::AllType();
1657 16 : if (native_encap) {
1658 16 : tunnel_bmap |= TunnelType::NativeType();
1659 : }
1660 :
1661 16 : req->data.reset(new ReceiveRoute(intf_key, MplsTable::kInvalidExportLabel,
1662 16 : tunnel_bmap, policy, vn_name));
1663 16 : }
1664 :
1665 2 : static void AddVHostMplsRecvRouteInternal(DBRequest *req, const Peer *peer,
1666 : const string &vrf,
1667 : const InterfaceKey &intf_key,
1668 : const IpAddress &addr, uint8_t plen,
1669 : const string &vn_name, bool policy,
1670 : bool native_encap) {
1671 2 : req->oper = DBRequest::DB_ENTRY_ADD_CHANGE;
1672 2 : req->key.reset(new InetMplsUnicastRouteKey(peer, vrf, addr, plen));
1673 :
1674 2 : int tunnel_bmap = TunnelType::AllType();
1675 2 : if (native_encap) {
1676 0 : tunnel_bmap |= TunnelType::NativeType();
1677 : }
1678 :
1679 2 : req->data.reset(new ReceiveRoute(intf_key, MplsTable::kImplicitNullLabel,
1680 2 : tunnel_bmap, policy, vn_name));
1681 2 : }
1682 2 : void InetUnicastAgentRouteTable::AddVHostMplsRecvRouteReq
1683 : (const Peer *peer, const string &vrf, const InterfaceKey &intf_key,
1684 : const IpAddress &addr, uint8_t plen, const string &vn_name, bool policy,
1685 : bool native_encap) {
1686 2 : DBRequest req;
1687 2 : AddVHostMplsRecvRouteInternal(&req, peer, vrf, intf_key, addr, plen,
1688 : vn_name, policy, native_encap);
1689 2 : Inet4MplsUnicastTableEnqueue(Agent::GetInstance(), &req);
1690 2 : }
1691 16 : void InetUnicastAgentRouteTable::AddVHostRecvRoute(const Peer *peer,
1692 : const string &vrf,
1693 : const InterfaceKey &intf_key,
1694 : const IpAddress &addr,
1695 : uint8_t plen,
1696 : const string &vn_name,
1697 : bool policy, bool native_encap, bool ipam_host_route) {
1698 16 : DBRequest req;
1699 16 : AddVHostRecvRouteInternal(&req, peer, vrf, intf_key, addr, plen,
1700 : vn_name, policy, native_encap);
1701 16 : static_cast<ReceiveRoute *>(req.data.get())->SetProxyArp(true);
1702 16 : static_cast<ReceiveRoute *>(req.data.get())->SetIpamHostRoute(ipam_host_route);
1703 16 : if (addr.is_v4()) {
1704 14 : Inet4UnicastTableProcess(Agent::GetInstance(), vrf, req);
1705 2 : } else if (addr.is_v6()) {
1706 2 : Inet6UnicastTableProcess(Agent::GetInstance(), vrf, req);
1707 : }
1708 16 : }
1709 :
1710 0 : void InetUnicastAgentRouteTable::AddVHostRecvRouteReq
1711 : (const Peer *peer, const string &vrf, const InterfaceKey &intf_key,
1712 : const IpAddress &addr, uint8_t plen, const string &vn_name, bool policy,
1713 : bool native_encap) {
1714 0 : DBRequest req;
1715 0 : AddVHostRecvRouteInternal(&req, peer, vrf, intf_key, addr, plen,
1716 : vn_name, policy, native_encap);
1717 0 : static_cast<ReceiveRoute *>(req.data.get())->SetProxyArp(true);
1718 0 : static_cast<ReceiveRoute *>(req.data.get())->SetIpamHostRoute(true);
1719 0 : if (addr.is_v4()) {
1720 0 : Inet4UnicastTableEnqueue(Agent::GetInstance(), &req);
1721 0 : } else if (addr.is_v6()) {
1722 0 : Inet6UnicastTableEnqueue(Agent::GetInstance(), vrf, &req);
1723 : }
1724 0 : }
1725 :
1726 : void
1727 0 : InetUnicastAgentRouteTable::AddVHostSubnetRecvRoute(const Peer *peer,
1728 : const string &vrf,
1729 : const InterfaceKey &intf_key,
1730 : const Ip4Address &addr,
1731 : uint8_t plen,
1732 : const string &vn_name,
1733 : bool policy) {
1734 0 : DBRequest req;
1735 0 : AddVHostRecvRouteInternal(&req, peer, vrf, intf_key, addr, plen,
1736 : vn_name, policy, true);
1737 0 : Inet4UnicastTableProcess(Agent::GetInstance(), vrf, req);
1738 0 : }
1739 :
1740 0 : void InetUnicastAgentRouteTable::AddDropRoute(const string &vm_vrf,
1741 : const Ip4Address &addr,
1742 : uint8_t plen,
1743 : const string &vn_name) {
1744 0 : Agent *agent = Agent::GetInstance();
1745 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
1746 0 : req.key.reset(new InetUnicastRouteKey(agent->local_peer(), vm_vrf,
1747 0 : Address::GetIp4SubnetAddress(addr, plen),
1748 0 : plen));
1749 0 : req.data.reset(new DropRoute(vn_name));
1750 0 : Inet4UnicastTableEnqueue(agent, &req);
1751 0 : }
1752 :
1753 0 : void InetUnicastAgentRouteTable::DelVHostSubnetRecvRoute(const string &vm_vrf,
1754 : const Ip4Address &addr,
1755 : uint8_t plen) {
1756 0 : DeleteReq(Agent::GetInstance()->local_peer(), vm_vrf,
1757 0 : Address::GetIp4SubnetAddress(addr, plen), 32, NULL);
1758 0 : }
1759 :
1760 4 : static void AddGatewayRouteInternal(const Peer *peer,
1761 : DBRequest *req, const string &vrf_name,
1762 : const Ip4Address &dst_addr, uint8_t plen,
1763 : const AddressList &gw_list,
1764 : const VnListType &vn_name, uint32_t label,
1765 : const SecurityGroupList &sg_list,
1766 : const TagList &tag_list,
1767 : const CommunityList &communities,
1768 : bool native_encap) {
1769 4 : req->oper = DBRequest::DB_ENTRY_ADD_CHANGE;
1770 8 : req->key.reset(new InetUnicastRouteKey(peer,
1771 4 : vrf_name, dst_addr, plen));
1772 4 : req->data.reset(new Inet4UnicastGatewayRoute(gw_list, vrf_name,
1773 : vn_name, label, sg_list,
1774 : tag_list, communities,
1775 4 : native_encap));
1776 4 : }
1777 :
1778 4 : void InetUnicastAgentRouteTable::AddGatewayRoute(const Peer *peer,
1779 : const string &vrf_name,
1780 : const Ip4Address &dst_addr,
1781 : uint8_t plen,
1782 : const AddressList &gw_list,
1783 : const VnListType &vn_name,
1784 : uint32_t label,
1785 : const SecurityGroupList
1786 : &sg_list,
1787 : const TagList
1788 : &tag_list,
1789 : const CommunityList
1790 : &communities,
1791 : bool native_encap) {
1792 4 : DBRequest req;
1793 4 : AddGatewayRouteInternal(peer, &req, vrf_name, dst_addr, plen, gw_list, vn_name,
1794 : label, sg_list, tag_list, communities, native_encap);
1795 4 : Inet4UnicastTableProcess(Agent::GetInstance(), vrf_name, req);
1796 4 : }
1797 :
1798 : void
1799 0 : InetUnicastAgentRouteTable::AddGatewayRouteReq(const Peer *peer,
1800 : const string &vrf_name,
1801 : const Ip4Address &dst_addr,
1802 : uint8_t plen,
1803 : const AddressList &gw_list,
1804 : const VnListType &vn_list,
1805 : uint32_t label,
1806 : const SecurityGroupList
1807 : &sg_list,
1808 : const TagList
1809 : &tag_list,
1810 : const CommunityList
1811 : &communities,
1812 : bool native_encap) {
1813 0 : DBRequest req;
1814 0 : AddGatewayRouteInternal(peer, &req, vrf_name, dst_addr, plen, gw_list,
1815 : vn_list, label, sg_list, tag_list, communities,
1816 : native_encap);
1817 0 : Inet4UnicastTableEnqueue(Agent::GetInstance(), &req);
1818 0 : }
1819 :
1820 : void
1821 0 : InetUnicastAgentRouteTable::AddMplsRouteReq(const Peer *peer,
1822 : const string &vrf_name,
1823 : const IpAddress &dst_addr,
1824 : uint8_t plen,
1825 : AgentRouteData *data ) {
1826 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
1827 0 : req.key.reset(new InetMplsUnicastRouteKey(peer, vrf_name, dst_addr, plen));
1828 0 : req.data.reset(data);
1829 0 : Inet4MplsUnicastTableEnqueue(Agent::GetInstance(), &req);
1830 0 : }
1831 : void
1832 80 : InetUnicastAgentRouteTable::AddIpamSubnetRoute(const string &vrf_name,
1833 : const IpAddress &dst_addr,
1834 : uint8_t plen,
1835 : const string &vn_name) {
1836 80 : Agent *agent_ptr = agent();
1837 80 : AgentRouteTable *table = NULL;
1838 80 : if (dst_addr.is_v4()) {
1839 80 : table = agent_ptr->vrf_table()->GetInet4UnicastRouteTable(vrf_name);
1840 0 : } else if (dst_addr.is_v6()) {
1841 0 : table = agent_ptr->vrf_table()->GetInet6UnicastRouteTable(vrf_name);
1842 : }
1843 :
1844 : //Add local peer path with discard NH
1845 80 : DBRequest dscd_nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
1846 80 : dscd_nh_req.key.reset(new DiscardNHKey());
1847 80 : dscd_nh_req.data.reset(NULL);
1848 :
1849 80 : DBRequest req;
1850 80 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
1851 160 : req.key.reset(new InetUnicastRouteKey(agent_ptr->local_peer(),
1852 80 : vrf_name, dst_addr, plen));
1853 80 : req.data.reset(new IpamSubnetRoute(dscd_nh_req, vn_name));
1854 80 : if (table) {
1855 80 : table->Process(req);
1856 : }
1857 80 : }
1858 :
1859 : void
1860 0 : InetUnicastAgentRouteTable::AddVrouterSubnetRoute(const IpAddress &dst_addr,
1861 : uint8_t plen) {
1862 : /* Only IPv4 is supported */
1863 0 : if (!dst_addr.is_v4()) {
1864 0 : return;
1865 : }
1866 0 : const string &vrf_name = agent()->fabric_vrf_name();
1867 0 : InetUnicastAgentRouteTable *table = NULL;
1868 0 : table = agent()->vrf_table()->GetInet4UnicastRouteTable(vrf_name);
1869 0 : const Peer *peer = agent()->fabric_rt_export_peer();
1870 :
1871 0 : VnListType vn_list;
1872 0 : vn_list.insert(agent()->fabric_vn_name());
1873 0 : const Ip4Address &gw = agent()->router_id();
1874 0 : table->AddGatewayRoute(peer, vrf_name, dst_addr.to_v4(), plen, AddressList(1, gw), vn_list, /* PKC: Make it as a list */
1875 0 : MplsTable::kInvalidExportLabel, SecurityGroupList(),
1876 0 : TagList(), CommunityList(), true);
1877 0 : }
1878 :
1879 : void
1880 2 : InetUnicastAgentRouteTable::AddVhostMplsRoute(const IpAddress &vhost_addr,
1881 : const Peer *peer) {
1882 : /* Only IPv4 is supported */
1883 2 : if (!vhost_addr.is_v4()) {
1884 0 : return;
1885 : }
1886 2 : const string &vrf_name = agent()->fabric_vrf_name();
1887 2 : InetUnicastAgentRouteTable *table = NULL;
1888 2 : table = agent()->vrf_table()->GetInet4MplsUnicastRouteTable(vrf_name);
1889 :
1890 0 : VmInterfaceKey vmi_key(AgentKey::ADD_DEL_CHANGE, boost::uuids::nil_uuid(),
1891 2 : agent()->vhost_interface_name());
1892 2 : table->AddVHostMplsRecvRouteReq(peer, vrf_name, vmi_key, vhost_addr,
1893 : 32, agent()->fabric_vn_name(), false, false);
1894 2 : }
1895 3255 : uint8_t InetUnicastAgentRouteTable::GetHostPlen(const IpAddress &ip_addr) const {
1896 3255 : if (ip_addr.is_v4()) {
1897 3253 : return Address::kMaxV4PrefixLen;
1898 : } else {
1899 2 : return Address::kMaxV6PrefixLen;
1900 : }
1901 : }
1902 :
1903 : void
1904 0 : InetUnicastAgentRouteTable::AddInterfaceRouteReq(Agent *agent, const Peer *peer,
1905 : const string &vrf_name,
1906 : const Ip4Address &ip,
1907 : uint8_t plen,
1908 : const Interface *intrface,
1909 : const string &vn_name) {
1910 :
1911 0 : assert(intrface->type() == Interface::PHYSICAL);
1912 0 : DBRequest rt_req(DBRequest::DB_ENTRY_ADD_CHANGE);
1913 0 : rt_req.key.reset(new InetUnicastRouteKey(agent->local_peer(),
1914 0 : vrf_name, ip, plen));
1915 0 : const PhysicalInterface *phy_intf = static_cast<const PhysicalInterface *>
1916 : (intrface);
1917 0 : rt_req.data.reset(new Inet4UnicastInterfaceRoute(phy_intf, vn_name));
1918 0 : Inet4UnicastTableEnqueue(agent, &rt_req);
1919 0 : }
1920 :
1921 1509 : void InetUnicastAgentRouteTable::AddEvpnRoute(const AgentRoute *route) {
1922 : const EvpnRouteEntry *evpn_route =
1923 1509 : dynamic_cast<const EvpnRouteEntry *>(route);
1924 1509 : const IpAddress &ip_addr = evpn_route->prefix_address();
1925 : //No installation for evpn route with zero Ip prefix.
1926 1509 : if (ip_addr.is_unspecified())
1927 740 : return;
1928 :
1929 : //label and parent-ip for NH need to be picket from parent route
1930 769 : DBRequest req;
1931 769 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
1932 1538 : const uint32_t plen = evpn_route->IsType5() ?
1933 769 : evpn_route->prefix_length() : GetHostPlen(ip_addr);
1934 : //Set key and data
1935 1538 : req.key.reset(new InetUnicastRouteKey(agent()->inet_evpn_peer(),
1936 769 : evpn_route->vrf()->GetName(),
1937 : ip_addr,
1938 769 : plen));
1939 769 : req.data.reset(new InetEvpnRouteData(evpn_route));
1940 769 : Process(req);
1941 769 : }
1942 :
1943 338 : void InetUnicastAgentRouteTable::DeleteEvpnRoute(const AgentRoute *rt) {
1944 338 : const EvpnRouteEntry *evpn_route =
1945 : static_cast<const EvpnRouteEntry *>(rt);
1946 338 : const IpAddress &ip_addr = evpn_route->prefix_address();
1947 338 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
1948 338 : const Peer *peer = agent()->inet_evpn_peer();
1949 338 : if (evpn_route->IsType5()) {
1950 0 : peer = agent()->evpn_routing_peer();
1951 : }
1952 676 : const uint32_t plen = evpn_route->IsType5() ?
1953 338 : evpn_route->prefix_length() : GetHostPlen(ip_addr);
1954 338 : req.key.reset(new InetUnicastRouteKey(peer,
1955 338 : evpn_route->vrf()->GetName(),
1956 : ip_addr,
1957 338 : plen));
1958 338 : req.data.reset(new InetEvpnRouteData(evpn_route));
1959 338 : Process(req);
1960 338 : }
1961 :
1962 0 : void InetUnicastAgentRouteTable::AddEvpnRoutingRoute(const IpAddress &ip_addr,
1963 : uint8_t plen,
1964 : const VrfEntry *vrf,
1965 : const Peer *peer,
1966 : const SecurityGroupList &sg_list,
1967 : const CommunityList &communities,
1968 : const PathPreference &path_preference,
1969 : const EcmpLoadBalance &ecmp_load_balance,
1970 : const TagList &tag_list,
1971 : DBRequest &nh_req,
1972 : uint32_t vxlan_id,
1973 : const VnListType& vn_list,
1974 : const std::string& origin_vn) {
1975 0 : DBRequest req;
1976 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
1977 : //Set key and data
1978 0 : req.key.reset(new InetUnicastRouteKey(peer,
1979 0 : vrf_entry()->GetName(),
1980 : ip_addr,
1981 0 : plen));
1982 0 : req.data.reset(new EvpnRoutingData(nh_req,
1983 : sg_list,
1984 : communities,
1985 : path_preference,
1986 : ecmp_load_balance,
1987 : tag_list,
1988 : vrf,
1989 : vxlan_id,
1990 : vn_list,
1991 0 : origin_vn));
1992 0 : Process(req);
1993 0 : }
1994 :
1995 0 : void InetUnicastAgentRouteTable::AddEvpnRoutingRouteReq(const IpAddress &ip_addr,
1996 : uint8_t plen,
1997 : const VrfEntry *vrf,
1998 : const Peer *peer,
1999 : const SecurityGroupList &sg_list,
2000 : const CommunityList &communities,
2001 : const PathPreference &path_preference,
2002 : const EcmpLoadBalance &ecmp_load_balance,
2003 : const TagList &tag_list,
2004 : DBRequest &nh_req,
2005 : uint32_t vxlan_id,
2006 : const VnListType& vn_list,
2007 : const std::string& origin_vn) {
2008 0 : DBRequest req;
2009 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
2010 : //Set key and data
2011 0 : req.key.reset(new InetUnicastRouteKey(peer,
2012 0 : vrf_entry()->GetName(),
2013 : ip_addr,
2014 0 : plen));
2015 0 : req.data.reset(new EvpnRoutingData(nh_req,
2016 : sg_list,
2017 : communities,
2018 : path_preference,
2019 : ecmp_load_balance,
2020 : tag_list,
2021 : vrf,
2022 : vxlan_id,
2023 : vn_list,
2024 0 : origin_vn));
2025 0 : InetUnicastTableEnqueue(Agent::GetInstance(), vrf->GetName(), &req);
2026 0 : }
|