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