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/asio.hpp>
7 : #include <boost/bind/bind.hpp>
8 :
9 : #include <base/logging.h>
10 : #include <db/db_entry.h>
11 : #include <db/db_table.h>
12 : #include <db/db_table_partition.h>
13 : #include <ksync/ksync_index.h>
14 : #include <ksync/ksync_entry.h>
15 : #include <ksync/ksync_object.h>
16 : #include <ksync/ksync_netlink.h>
17 : #include <ksync/ksync_sock.h>
18 :
19 : #include "cmn/agent.h"
20 : #include "oper/interface_common.h"
21 : #include "oper/tunnel_nh.h"
22 : #include "oper/nexthop.h"
23 : #include "oper/route_common.h"
24 : #include "oper/mirror_table.h"
25 : #include "oper/agent_route_walker.h"
26 : #include "oper/hbf.h"
27 :
28 : #include "vrouter/ksync/interface_ksync.h"
29 : #include "vrouter/ksync/nexthop_ksync.h"
30 : #include "vrouter/ksync/route_ksync.h"
31 :
32 : #include "ksync_init.h"
33 : #include "vr_types.h"
34 : #include "vr_defs.h"
35 : #include "vr_nexthop.h"
36 : #include "vr_vrf_table.h"
37 :
38 : using namespace boost::placeholders;
39 :
40 2858 : RouteKSyncEntry::RouteKSyncEntry(RouteKSyncObject* obj,
41 : const RouteKSyncEntry *entry,
42 2858 : uint32_t index) :
43 2858 : KSyncNetlinkDBEntry(index), ksync_obj_(obj),
44 2858 : rt_type_(entry->rt_type_), vrf_id_(entry->vrf_id_),
45 2858 : addr_(entry->addr_), src_addr_(entry->src_addr_), mac_(entry->mac_),
46 2858 : prefix_len_(entry->prefix_len_), nh_(entry->nh_), label_(entry->label_),
47 2858 : proxy_arp_(false), flood_dhcp_(entry->flood_dhcp_),
48 2858 : address_string_(entry->address_string_),
49 2858 : tunnel_type_(entry->tunnel_type_),
50 2858 : wait_for_traffic_(entry->wait_for_traffic_),
51 2858 : local_vm_peer_route_(entry->local_vm_peer_route_),
52 2858 : flood_(entry->flood_), ethernet_tag_(entry->ethernet_tag_),
53 2858 : layer2_control_word_(entry->layer2_control_word_),
54 2858 : is_learnt_route_(entry->is_learnt_route_) {
55 2858 : }
56 :
57 2059 : RouteKSyncEntry::RouteKSyncEntry(RouteKSyncObject* obj, const AgentRoute *rt) :
58 2059 : KSyncNetlinkDBEntry(kInvalidIndex), ksync_obj_(obj),
59 2059 : vrf_id_(rt->vrf_id()), mac_(), nh_(NULL), label_(0), proxy_arp_(false),
60 2059 : flood_dhcp_(false), tunnel_type_(TunnelType::DefaultType()),
61 2059 : wait_for_traffic_(false), local_vm_peer_route_(false),
62 2059 : flood_(false), ethernet_tag_(0), layer2_control_word_(false),
63 4118 : is_learnt_route_(false) {
64 2059 : boost::system::error_code ec;
65 2059 : rt_type_ = rt->GetTableType();
66 2059 : switch (rt_type_) {
67 571 : case Agent::INET4_UNICAST: {
68 571 : const InetUnicastRouteEntry *uc_rt =
69 : static_cast<const InetUnicastRouteEntry *>(rt);
70 571 : addr_ = uc_rt->prefix_address();
71 571 : src_addr_ = IpAddress::from_string("0.0.0.0", ec).to_v4();
72 571 : prefix_len_ = uc_rt->prefix_length();
73 571 : AgentPath *local_vm_path = uc_rt->FindLocalVmPortPath();
74 571 : if (local_vm_path && local_vm_path->IsDynamicLearntRoute()) {
75 3 : is_learnt_route_ = true;
76 : }
77 :
78 571 : break;
79 : }
80 365 : case Agent::INET6_UNICAST: {
81 365 : const InetUnicastRouteEntry *uc_rt =
82 : static_cast<const InetUnicastRouteEntry *>(rt);
83 365 : addr_ = uc_rt->prefix_address();
84 365 : src_addr_ = Ip6Address();
85 365 : prefix_len_ = uc_rt->prefix_length();
86 365 : break;
87 : }
88 0 : case Agent::INET4_MULTICAST: {
89 0 : const Inet4MulticastRouteEntry *mc_rt =
90 : static_cast<const Inet4MulticastRouteEntry *>(rt);
91 0 : addr_ = mc_rt->dest_ip_addr();
92 0 : src_addr_ = mc_rt->src_ip_addr();
93 0 : prefix_len_ = 32;
94 0 : break;
95 : }
96 1123 : case Agent::BRIDGE: {
97 1123 : const BridgeRouteEntry *l2_rt =
98 : static_cast<const BridgeRouteEntry *>(rt);
99 1123 : mac_ = l2_rt->prefix_address();
100 1123 : prefix_len_ = 0;
101 1123 : break;
102 : }
103 0 : default: {
104 0 : assert(0);
105 : }
106 : }
107 2059 : address_string_ = rt->GetAddressString();
108 2059 : }
109 :
110 7775 : RouteKSyncEntry::~RouteKSyncEntry() {
111 7775 : }
112 :
113 74934 : KSyncDBObject *RouteKSyncEntry::GetObject() const {
114 74934 : return ksync_obj_;
115 : }
116 :
117 194086 : bool RouteKSyncEntry::UcIsLess(const KSyncEntry &rhs) const {
118 194086 : const RouteKSyncEntry &entry = static_cast<const RouteKSyncEntry &>(rhs);
119 194086 : if (vrf_id_ != entry.vrf_id_) {
120 0 : return vrf_id_ < entry.vrf_id_;
121 : }
122 :
123 194086 : if (addr_ != entry.addr_) {
124 188204 : return addr_ < entry.addr_;
125 : }
126 :
127 5882 : return (prefix_len_ < entry.prefix_len_);
128 : }
129 :
130 0 : bool RouteKSyncEntry::McIsLess(const KSyncEntry &rhs) const {
131 0 : const RouteKSyncEntry &entry = static_cast<const RouteKSyncEntry &>(rhs);
132 0 : if (vrf_id_ != entry.vrf_id_) {
133 0 : return vrf_id_ < entry.vrf_id_;
134 : }
135 :
136 0 : if (src_addr_ != entry.src_addr_) {
137 0 : return src_addr_ < entry.src_addr_;
138 : }
139 :
140 0 : return (addr_ < entry.addr_);
141 : }
142 :
143 7416 : bool RouteKSyncEntry::L2IsLess(const KSyncEntry &rhs) const {
144 7416 : const RouteKSyncEntry &entry = static_cast<const RouteKSyncEntry &>(rhs);
145 :
146 7416 : if (vrf_id_ != entry.vrf_id_) {
147 0 : return vrf_id_ < entry.vrf_id_;
148 : }
149 :
150 7416 : return mac_ < entry.mac_;
151 : }
152 :
153 201502 : bool RouteKSyncEntry::IsLess(const KSyncEntry &rhs) const {
154 201502 : const RouteKSyncEntry &entry = static_cast<const RouteKSyncEntry &>(rhs);
155 201502 : if (rt_type_ != entry.rt_type_)
156 0 : return rt_type_ < entry.rt_type_;
157 :
158 : //First unicast
159 201502 : if ((rt_type_ == Agent::INET4_UNICAST) ||
160 153153 : (rt_type_ == Agent::INET6_UNICAST)) {
161 194086 : return UcIsLess(rhs);
162 : }
163 :
164 7416 : if (rt_type_ == Agent::BRIDGE) {
165 7416 : return L2IsLess(rhs);
166 : }
167 :
168 0 : return McIsLess(rhs);
169 : }
170 :
171 13899 : static std::string RouteTypeToString(Agent::RouteTableType type) {
172 13899 : switch (type) {
173 6308 : case Agent::INET4_UNICAST:
174 6308 : return "INET4_UNICAST";
175 : break;
176 2416 : case Agent::INET6_UNICAST:
177 2416 : return "INET6_UNICAST";
178 : break;
179 0 : case Agent::INET4_MULTICAST:
180 0 : return "INET_MULTICAST";
181 : break;
182 5175 : case Agent::BRIDGE:
183 5175 : return "BRIDGE";
184 : break;
185 0 : default:
186 0 : break;
187 : }
188 :
189 0 : assert(0);
190 : return "";
191 : }
192 :
193 9848 : std::string RouteKSyncEntry::ToString() const {
194 9848 : std::stringstream s;
195 : NHKSyncEntry *nexthop;
196 9848 : nexthop = nh();
197 :
198 9848 : s << "Type : " << RouteTypeToString(rt_type_) << " ";
199 : const VrfEntry* vrf =
200 9848 : ksync_obj_->ksync()->agent()->vrf_table()->FindVrfFromId(vrf_id_);
201 9848 : if (vrf) {
202 8451 : s << "Route Vrf : " << vrf->GetName() << " ";
203 : }
204 9848 : s << address_string_ << "/" << prefix_len_ << " Type:" << rt_type_;
205 :
206 :
207 9848 : s << " Label : " << label_;
208 9848 : s << " Tunnel Type: " << tunnel_type_;
209 :
210 9848 : if (nexthop) {
211 9304 : s << nexthop->ToString();
212 : } else {
213 544 : s << " NextHop : <NULL>";
214 : }
215 :
216 9848 : s << " Mac: " << mac_.ToString();
217 9848 : s << " Flood DHCP:" << flood_dhcp_;
218 19696 : return s.str();
219 9848 : }
220 :
221 : // Check if NH points to a service-chain interface or a Gateway interface
222 3221 : static bool IsGatewayOrServiceInterface(const NextHop *nh) {
223 3766 : if (nh->GetType() != NextHop::INTERFACE &&
224 3766 : nh->GetType() != NextHop::VLAN && nh->GetType() != NextHop::ARP)
225 519 : return false;
226 :
227 2702 : const Interface *intf = NULL;
228 2702 : if (nh->GetType() == NextHop::INTERFACE) {
229 2676 : intf = (static_cast<const InterfaceNH *>(nh))->GetInterface();
230 2676 : if (intf->type() == Interface::PACKET)
231 988 : return true;
232 26 : } else if (nh->GetType() == NextHop::VLAN) {
233 0 : intf = (static_cast<const VlanNH *>(nh))->GetInterface();
234 26 : } else if (nh->GetType() == NextHop::ARP) {
235 26 : intf = (static_cast<const ArpNH *>(nh))->GetInterface();
236 : }
237 :
238 1714 : const VmInterface *vmi = dynamic_cast<const VmInterface *>(intf);
239 1714 : if (vmi == NULL)
240 20 : return false;
241 :
242 1694 : if (vmi->HasServiceVlan())
243 0 : return true;
244 1694 : if (vmi->device_type() == VmInterface::LOCAL_DEVICE)
245 20 : return true;
246 :
247 1674 : return false;
248 : }
249 :
250 : // Set the flood_ and proxy_arp_ flag for the route
251 : // flood_ flag says that ARP packets hitting route should be flooded
252 : // proxy_arp_ flag says VRouter should do proxy ARP
253 : //
254 : // The flags are set based on NH and Interface-type
255 2850 : bool RouteKSyncEntry::BuildArpFlags(const DBEntry *e, const AgentPath *path,
256 : const MacAddress &mac) {
257 2850 : bool ret = false;
258 :
259 : //Route flags for inet4 and inet6
260 2850 : if ((rt_type_ != Agent::INET6_UNICAST) &&
261 2279 : (rt_type_ != Agent::INET4_UNICAST))
262 0 : return false;
263 :
264 2850 : Agent *agent = ksync_obj_->ksync()->agent();
265 2850 : const InetUnicastRouteEntry *rt =
266 : static_cast<const InetUnicastRouteEntry *>(e);
267 :
268 : // Assume no flood and proxy_arp by default
269 2850 : bool flood = false;
270 2850 : bool proxy_arp = false;
271 2850 : const NextHop *nh = rt->GetActiveNextHop();
272 :
273 2850 : if (nh == NULL) {
274 0 : return false;
275 : }
276 2850 : switch (nh->GetType()) {
277 4 : case NextHop::RESOLVE:
278 : // RESOLVE NH can be used by Gateway Interface or Fabric VRF
279 : // VRouter does not honour flood_ and proxy_arp_ flag for Fabric VRF
280 : // We dont want to flood ARP on Gateway Interface
281 4 : if (rt->vrf()->GetName() != agent->fabric_vrf_name()) {
282 0 : proxy_arp = true;
283 : }
284 4 : break;
285 :
286 :
287 604 : case NextHop::COMPOSITE:
288 : // ECMP flows have composite NH. We want to do routing for ECMP flows
289 : // So, set proxy_arp flag
290 604 : proxy_arp = true;
291 604 : break;
292 :
293 78 : case NextHop::TUNNEL:
294 : {
295 : // set proxy arp flag for MPLS VPN routes
296 : // these routes' nexthop is either labelled tunnel or
297 : // composite of labelled tunnel nexthops
298 78 : const TunnelNH *tunnel_nh = static_cast<const TunnelNH *>(nh);
299 78 : if (tunnel_nh->GetTunnelType().GetType() ==
300 : TunnelType::MPLS_OVER_MPLS) {
301 0 : proxy_arp = true;
302 0 : break;
303 : // other tunnel cases should be evaluated under
304 : // default case
305 : }
306 : }
307 :
308 : default:
309 :
310 2242 : if (mac != MacAddress::ZeroMac()) {
311 : // Proxy-ARP without flood if mac-stitching is present
312 775 : proxy_arp = true;
313 775 : flood = false;
314 775 : break;
315 : }
316 :
317 : // MAC stitching not present.
318 : // If interface belongs to service-chain or Gateway, we want packet to
319 : // be routed. Following config ensures routing,
320 : // - Enable Proxy
321 : // - Disable Flood-bit
322 : // - Dont do MAC Stitching (in RouteNeedsMacBinding)
323 1467 : if (IsGatewayOrServiceInterface(nh) == true) {
324 521 : proxy_arp = true;
325 521 : flood = false;
326 521 : break;
327 : }
328 :
329 946 : AgentPath *local_vm_path = rt->FindLocalVmPortPath();
330 946 : if (local_vm_path != NULL) {
331 159 : if (local_vm_path->is_health_check_service()) {
332 : // for local vm path exported by health check service
333 : // set proxy arp to be true to arp with vrouter MAC
334 0 : proxy_arp = true;
335 0 : flood = false;
336 : } else {
337 : // Local port without MAC stitching should only be a transition
338 : // case. In the meanwhile, flood ARP so that VM can respond
339 : // Note: In case VN is in L3 forwarding mode flags will be reset
340 : // This is done below when VN entry is extracted.
341 159 : proxy_arp_ = false;
342 159 : flood = true;
343 : }
344 : } else {
345 : // Non local-route. Set flags based on the route
346 787 : proxy_arp = rt->proxy_arp();
347 787 : flood = rt->ipam_host_route();
348 : }
349 946 : break;
350 : }
351 :
352 : // There is an exception for IPAM subnet routes.
353 : // IPAM subnet routes always result in flood of ARP even if the route
354 : // is ECMP (resulting from gateway routes)
355 2850 : if (rt->ipam_subnet_route()) {
356 362 : proxy_arp = false;
357 362 : flood = true;
358 : }
359 :
360 : // If the route crosses a VN, we want packet to be routed. So, override
361 : // the flags set above and set only Proxy flag
362 : // When L2 forwarding mode is disabled, reset the proxy arp to true and flood
363 : // of arp to false.
364 2850 : VnEntry *vn= rt->vrf()->vn();
365 4746 : if (vn == NULL || !path->dest_vn_match(vn->GetName()) ||
366 7596 : (path->dest_vn_list().size() > 1) ||
367 2366 : (vn->bridging() == false)) {
368 484 : proxy_arp = true;
369 484 : flood = false;
370 : }
371 :
372 : //If VN is running in l2 mode, then any l3 route installed should
373 : //have flood flag set for ARP.
374 2850 : if (vn && (vn->layer3_forwarding() == false)) {
375 0 : proxy_arp = false;
376 0 : flood = true;
377 : }
378 :
379 : // VRouter does not honour flood/proxy_arp flags for fabric-vrf
380 2850 : if (rt->vrf()->GetName() == agent->fabric_vrf_name()) {
381 406 : if (mac != MacAddress() || nh->GetType() == NextHop::INTERFACE ||
382 38 : nh->GetType() == NextHop::COMPOSITE) {
383 330 : proxy_arp = true;
384 : } else {
385 38 : proxy_arp = false;
386 : }
387 368 : flood = false;
388 : }
389 :
390 2850 : if (proxy_arp != proxy_arp_) {
391 888 : proxy_arp_ = proxy_arp;
392 888 : ret = true;
393 : }
394 :
395 2850 : if (flood != flood_) {
396 278 : flood_ = flood;
397 278 : ret = true;
398 : }
399 2850 : return ret;
400 : }
401 :
402 : //Uses internal API to extract path.
403 5055 : const NextHop *RouteKSyncEntry::GetActiveNextHop(const AgentRoute *route) const {
404 5055 : const AgentPath *path = GetActivePath(route);
405 5055 : if (path == NULL)
406 0 : return NULL;
407 5055 : return path->ComputeNextHop(ksync_obj_->ksync()->agent());
408 : }
409 :
410 : //Returns the usable path.
411 : //In case of bridge tables the path contains reference path which
412 : //has all the data. This path known as evpn_path is a level of indirection
413 : //to leaked path from MAC+IP route.
414 10110 : const AgentPath *RouteKSyncEntry::GetActivePath(const AgentRoute *route) const {
415 10110 : const AgentPath *path = route->GetActivePath();
416 10110 : return path;
417 : }
418 :
419 5055 : bool RouteKSyncEntry::Sync(DBEntry *e) {
420 5055 : bool ret = false;
421 5055 : Agent *agent = ksync_obj_->ksync()->agent();
422 5055 : const AgentRoute *route = static_cast<AgentRoute *>(e);
423 :
424 5055 : const AgentPath *path = GetActivePath(route);
425 5055 : if (path->peer() == agent->local_vm_peer())
426 291 : local_vm_peer_route_ = true;
427 : else
428 4764 : local_vm_peer_route_ = false;
429 :
430 5055 : NHKSyncObject *nh_object = ksync_obj_->ksync()->nh_ksync_obj();
431 5055 : NHKSyncEntry *old_nh = nh();
432 :
433 5055 : const NextHop *tmp = NULL;
434 5055 : tmp = GetActiveNextHop(route);
435 :
436 : // NHs should not be delete marked here. Interface NHs are an exception. If
437 : // an NH is found to be delete marked here, dont go ahead and initialize the
438 : // ksync entry with a delete marked NH. Make the route ksync entry use the
439 : // Discard NH's ksync entry until an update is received for the route.
440 12313 : if (tmp == NULL ||
441 7258 : ((tmp->GetType() != NextHop::INTERFACE) && tmp->IsDeleted())) {
442 0 : DiscardNHKey key;
443 0 : tmp = static_cast<NextHop *>(agent->nexthop_table()->
444 0 : FindActiveEntry(&key));
445 0 : }
446 5055 : NHKSyncEntry nexthop(nh_object, tmp);
447 5055 : nh_ = static_cast<NHKSyncEntry *>(nh_object->GetReference(&nexthop));
448 5055 : if (old_nh != nh()) {
449 1817 : ret = true;
450 : }
451 :
452 : //Bother for label for unicast and bridge routes
453 5055 : if (rt_type_ != Agent::INET4_MULTICAST) {
454 5055 : uint32_t old_label = label_;
455 :
456 5055 : if (route->is_multicast()) {
457 769 : label_ = path->vxlan_id();
458 : } else {
459 4286 : label_ = path->GetActiveLabel();
460 : }
461 5055 : if (label_ != old_label) {
462 1353 : ret = true;
463 : }
464 :
465 5055 : if (tunnel_type_ != path->GetTunnelType()) {
466 127 : tunnel_type_ = path->GetTunnelType();
467 127 : ret = true;
468 : }
469 : }
470 :
471 5055 : if (wait_for_traffic_ != route->WaitForTraffic()) {
472 2150 : wait_for_traffic_ = route->WaitForTraffic();
473 2150 : ret = true;
474 : }
475 :
476 5055 : if (route->GetActivePath()) {
477 5055 : if (layer2_control_word_ != route->GetActivePath()->layer2_control_word()) {
478 0 : layer2_control_word_ = route->GetActivePath()->layer2_control_word();
479 0 : ret = true;
480 : }
481 : }
482 :
483 5055 : if (rt_type_ == Agent::INET4_UNICAST || rt_type_ == Agent::INET6_UNICAST) {
484 2850 : VrfKSyncObject *obj = ksync_obj_->ksync()->vrf_ksync_obj();
485 2850 : const InetUnicastRouteEntry *uc_rt =
486 : static_cast<const InetUnicastRouteEntry *>(e);
487 2850 : MacAddress mac = MacAddress::ZeroMac();
488 2850 : bool wait_for_traffic = false;
489 :
490 2850 : if (obj->RouteNeedsMacBinding(uc_rt)) {
491 1261 : mac = obj->GetIpMacBinding(uc_rt->vrf(), addr_, uc_rt);
492 1261 : wait_for_traffic = obj->GetIpMacWaitForTraffic(uc_rt->vrf(), addr_);
493 : }
494 :
495 2850 : if (wait_for_traffic_ == false &&
496 1037 : wait_for_traffic_ != wait_for_traffic) {
497 627 : wait_for_traffic_ = wait_for_traffic;
498 627 : ret = true;
499 : }
500 :
501 2850 : if (mac != mac_) {
502 120 : mac_ = mac;
503 120 : ret = true;
504 : }
505 :
506 2850 : if (BuildArpFlags(e, path, mac_))
507 1067 : ret = true;
508 : }
509 :
510 5055 : if (rt_type_ == Agent::BRIDGE) {
511 2205 : const BridgeRouteEntry *l2_rt =
512 : static_cast<const BridgeRouteEntry *>(route);
513 :
514 : //First search for v4
515 2205 : const MacVmBindingPath *dhcp_path = l2_rt->FindMacVmBindingPath();
516 2205 : bool flood_dhcp = true; // Flood DHCP if MacVmBindingPath is not present
517 2205 : if (dhcp_path)
518 763 : flood_dhcp = dhcp_path->flood_dhcp();
519 :
520 2205 : if (flood_dhcp_ != flood_dhcp) {
521 522 : flood_dhcp_ = flood_dhcp;
522 522 : ret = true;
523 : }
524 : }
525 :
526 5055 : return ret;
527 5055 : }
528 :
529 4051 : void RouteKSyncEntry::FillObjectLog(sandesh_op::type type,
530 : KSyncRouteInfo &info) const {
531 4051 : if (type == sandesh_op::ADD) {
532 2622 : info.set_operation("ADD/CHANGE");
533 : } else {
534 1429 : info.set_operation("DELETE");
535 : }
536 :
537 4051 : info.set_addr(address_string_);
538 4051 : info.set_plen(prefix_len_);
539 4051 : info.set_vrf(vrf_id_);
540 :
541 4051 : if (nh()) {
542 3507 : info.set_nh_idx(nh()->nh_id());
543 3507 : if (nh()->type() == NextHop::TUNNEL) {
544 80 : info.set_label(label_);
545 : }
546 : } else {
547 544 : info.set_nh_idx(NH_DISCARD_ID);
548 : }
549 :
550 4051 : info.set_mac(mac_.ToString());
551 4051 : info.set_type(RouteTypeToString(rt_type_));
552 4051 : }
553 :
554 4051 : int RouteKSyncEntry::Encode(sandesh_op::type op, uint8_t replace_plen,
555 : char *buf, int buf_len) {
556 4051 : vr_route_req encoder;
557 : int encode_len;
558 4051 : NHKSyncEntry *nexthop = nh();
559 :
560 4051 : encoder.set_h_op(op);
561 4051 : encoder.set_rtr_rid(0);
562 4051 : encoder.set_rtr_vrf_id(vrf_id_);
563 4051 : if (rt_type_ != Agent::BRIDGE) {
564 2596 : if (addr_.is_v4()) {
565 1866 : encoder.set_rtr_family(AF_INET);
566 1866 : Ip4Address::bytes_type bytes = addr_.to_v4().to_bytes();
567 1866 : std::vector<int8_t> rtr_prefix(bytes.begin(), bytes.end());
568 1866 : encoder.set_rtr_prefix(rtr_prefix);
569 2596 : } else if (addr_.is_v6()) {
570 730 : encoder.set_rtr_family(AF_INET6);
571 730 : Ip6Address::bytes_type bytes = addr_.to_v6().to_bytes();
572 730 : std::vector<int8_t> rtr_prefix(bytes.begin(), bytes.end());
573 730 : encoder.set_rtr_prefix(rtr_prefix);
574 730 : }
575 2596 : encoder.set_rtr_prefix_len(prefix_len_);
576 2596 : if (mac_ != MacAddress::ZeroMac()) {
577 1232 : if ((addr_.is_v4() && prefix_len_ != 32) ||
578 616 : (addr_.is_v6() && prefix_len_ != 128)) {
579 0 : LOG(ERROR, "Unexpected MAC stitching for route "
580 : << ToString());
581 0 : mac_ = MacAddress::ZeroMac();
582 : }
583 : std::vector<int8_t> mac((int8_t *)mac_,
584 616 : (int8_t *)mac_ + mac_.size());
585 616 : encoder.set_rtr_mac(mac);
586 616 : }
587 : } else {
588 1455 : encoder.set_rtr_family(AF_BRIDGE);
589 : //TODO add support for mac
590 : std::vector<int8_t> mac((int8_t *)mac_,
591 1455 : (int8_t *)mac_ + mac_.size());
592 1455 : encoder.set_rtr_mac(mac);
593 1455 : }
594 :
595 4051 : int label = 0;
596 4051 : int flags = 0;
597 4051 : if (rt_type_ != Agent::INET4_MULTICAST) {
598 : // if next hop is tunnel
599 : // or nexthop is composite and composite type is LU_ECMP, then
600 : // label is valid
601 8052 : if (nexthop != NULL && ((nexthop->type() == NextHop::TUNNEL) ||
602 4001 : ((nexthop->type() == NextHop::COMPOSITE) &&
603 574 : (nexthop->CompositeType() == Composite::LU_ECMP)))) {
604 80 : label = label_;
605 80 : flags |= VR_RT_LABEL_VALID_FLAG;
606 : }
607 : }
608 :
609 4051 : if (rt_type_ == Agent::BRIDGE) {
610 1455 : label = label_;
611 2484 : if (nexthop != NULL && ((nexthop->type() == NextHop::COMPOSITE) ||
612 1029 : (nexthop->type() == NextHop::TUNNEL))) {
613 437 : flags |= VR_BE_LABEL_VALID_FLAG;
614 : }
615 1455 : if (flood_dhcp_) {
616 1316 : flags |= VR_BE_FLOOD_DHCP_FLAG;
617 : }
618 1455 : if (ksync_obj_->ksync()->agent()->tsn_no_forwarding_enabled()) {
619 0 : flags |= VR_BE_EVPN_CONTROL_PROCESSING_FLAG;
620 : }
621 : } else {
622 :
623 2596 : if (proxy_arp_) {
624 1480 : flags |= VR_RT_ARP_PROXY_FLAG;
625 : }
626 :
627 2596 : if (wait_for_traffic_) {
628 1961 : flags |= VR_RT_ARP_TRAP_FLAG;
629 : }
630 :
631 2596 : if (flood_) {
632 393 : flags |= VR_RT_ARP_FLOOD_FLAG;
633 : }
634 :
635 2596 : if (is_learnt_route_) {
636 8 : flags |= VR_RT_MAC_IP_LEARNT_FLAG;
637 : }
638 :
639 : }
640 :
641 4051 : if (layer2_control_word_) {
642 0 : flags |= VR_BE_L2_CONTROL_DATA_FLAG;
643 : }
644 :
645 4051 : encoder.set_rtr_label_flags(flags);
646 4051 : encoder.set_rtr_label(label);
647 4051 : if (nexthop != NULL) {
648 3507 : encoder.set_rtr_nh_id(nexthop->nh_id());
649 : } else {
650 544 : encoder.set_rtr_nh_id(NH_DISCARD_ID);
651 : }
652 :
653 4051 : if (op == sandesh_op::DEL) {
654 1429 : encoder.set_rtr_replace_plen(replace_plen);
655 : }
656 :
657 4051 : int error = 0;
658 4051 : encode_len = encoder.WriteBinary((uint8_t *)buf, buf_len, &error);
659 4051 : assert(error == 0);
660 4051 : assert(encode_len <= buf_len);
661 4051 : return encode_len;
662 4051 : }
663 :
664 :
665 1429 : int RouteKSyncEntry::AddMsg(char *buf, int buf_len) {
666 1429 : KSyncRouteInfo info;
667 1429 : FillObjectLog(sandesh_op::ADD, info);
668 1429 : KSYNC_TRACE(Route, GetObject(), info);
669 2858 : return Encode(sandesh_op::ADD, 0, buf, buf_len);
670 1429 : }
671 :
672 1193 : int RouteKSyncEntry::ChangeMsg(char *buf, int buf_len){
673 1193 : KSyncRouteInfo info;
674 1193 : FillObjectLog(sandesh_op::ADD, info);
675 1193 : KSYNC_TRACE(Route, GetObject(), info);
676 :
677 2386 : return Encode(sandesh_op::ADD, 0, buf, buf_len);
678 1193 : }
679 :
680 1429 : int RouteKSyncEntry::DeleteMsg(char *buf, int buf_len) {
681 :
682 1429 : RouteKSyncEntry key(ksync_obj_, this, KSyncEntry::kInvalidIndex);
683 1429 : KSyncEntry *found = NULL;
684 1429 : RouteKSyncEntry *route = NULL;
685 1429 : NHKSyncEntry *ksync_nh = NULL;
686 :
687 : // IF multicast or bridge delete unconditionally
688 1429 : if ((rt_type_ == Agent::BRIDGE) ||
689 936 : (rt_type_ == Agent::INET4_MULTICAST)) {
690 493 : return DeleteInternal(nh(), NULL, buf, buf_len);
691 : }
692 :
693 : // For INET routes, we need to give replacement NH and prefixlen
694 58872 : for (int plen = (prefix_len() - 1); plen >= 0; plen--) {
695 :
696 58328 : if (addr_.is_v4()) {
697 11848 : Ip4Address addr = Address::GetIp4SubnetAddress(addr_.to_v4(), plen);
698 11848 : key.set_ip(addr);
699 46480 : } else if (addr_.is_v6()) {
700 46480 : Ip6Address addr = Address::GetIp6SubnetAddress(addr_.to_v6(), plen);
701 46480 : key.set_ip(addr);
702 : }
703 :
704 58328 : key.set_prefix_len(plen);
705 58328 : found = GetObject()->Find(&key);
706 :
707 58328 : if (found) {
708 400 : route = static_cast<RouteKSyncEntry *>(found);
709 400 : if (route->IsResolved()) {
710 392 : ksync_nh = route->nh();
711 392 : if(ksync_nh) {
712 392 : return DeleteInternal(ksync_nh, route, buf, buf_len);
713 : }
714 0 : ksync_nh = NULL;
715 : }
716 : }
717 : }
718 :
719 : /* If better route is not found, send discardNH for route */
720 544 : return DeleteInternal(NULL, NULL, buf, buf_len);
721 1429 : }
722 :
723 1429 : uint8_t RouteKSyncEntry::CopyReplacementData(NHKSyncEntry *nexthop,
724 : RouteKSyncEntry *new_rt) {
725 1429 : uint8_t new_plen = 0;
726 1429 : nh_ = nexthop;
727 1429 : if (new_rt == NULL) {
728 1037 : label_ = 0;
729 1037 : proxy_arp_ = false;
730 1037 : flood_ = false;
731 1037 : wait_for_traffic_ = false;
732 : // mac_ is key for bridge entries and modifying it will corrut the
733 : // KSync tree. So, reset mac in case of non-bridge entries only
734 1037 : if (rt_type_ != Agent::BRIDGE) {
735 544 : mac_ = MacAddress::ZeroMac();
736 : }
737 1037 : is_learnt_route_ = false;
738 : } else {
739 392 : label_ = new_rt->label();
740 392 : new_plen = new_rt->prefix_len();
741 392 : proxy_arp_ = new_rt->proxy_arp();
742 392 : flood_ = new_rt->flood();
743 392 : wait_for_traffic_ = new_rt->wait_for_traffic();
744 392 : mac_ = new_rt->mac();
745 392 : is_learnt_route_ = new_rt->IsLearntRoute();
746 : }
747 1429 : return new_plen;
748 : }
749 :
750 1429 : int RouteKSyncEntry::DeleteInternal(NHKSyncEntry *nexthop,
751 : RouteKSyncEntry *new_rt,
752 : char *buf, int buf_len) {
753 1429 : uint8_t replace_plen = CopyReplacementData(nexthop, new_rt);
754 1429 : KSyncRouteInfo info;
755 1429 : FillObjectLog(sandesh_op::DEL, info);
756 1429 : KSYNC_TRACE(Route, GetObject(), info);
757 :
758 2858 : return Encode(sandesh_op::DEL, replace_plen, buf, buf_len);
759 1429 : }
760 :
761 4249 : KSyncEntry *RouteKSyncEntry::UnresolvedReference() {
762 4249 : NHKSyncEntry *nexthop = nh();
763 4249 : if (!nexthop->IsResolvedAndInSync()) {
764 1613 : return nexthop;
765 : }
766 :
767 2636 : if ((rt_type_ == Agent::INET4_UNICAST) ||
768 1327 : (rt_type_ == Agent::INET6_UNICAST)) {
769 1674 : if (!mac_.IsZero()) {
770 : //Get Vrf and bridge ksync object
771 630 : VrfKSyncObject *vrf_obj = ksync_obj_->ksync()->vrf_ksync_obj();
772 : VrfEntry* vrf =
773 630 : ksync_obj_->ksync()->agent()->vrf_table()->FindVrfFromId(vrf_id_);
774 630 : if (vrf) {
775 : VrfKSyncObject::VrfState *state =
776 : static_cast<VrfKSyncObject::VrfState *>
777 630 : (vrf->GetState(vrf->get_table(),
778 : vrf_obj->vrf_listener_id()));
779 630 : RouteKSyncObject* bridge_ksync_obj = state->bridge_route_table_;
780 630 : BridgeRouteEntry tmp_l2_rt(vrf, mac_, Peer::EVPN_PEER, false);
781 630 : RouteKSyncEntry key(bridge_ksync_obj, &tmp_l2_rt);
782 : RouteKSyncEntry *mac_route_reference =
783 : static_cast<RouteKSyncEntry *>(bridge_ksync_obj->
784 630 : GetReference(&key));
785 : //Get the ksync entry for stitched mac
786 : //else mark dependancy on same.
787 630 : if (!mac_route_reference->IsResolved())
788 14 : return mac_route_reference;
789 644 : } else {
790 : // clear the mac_ to avoid failure in programming vrouter
791 0 : mac_ = MacAddress::ZeroMac();
792 : }
793 : }
794 : }
795 :
796 2622 : return NULL;
797 : }
798 :
799 296 : RouteKSyncObject::RouteKSyncObject(KSync *ksync, AgentRouteTable *rt_table):
800 296 : KSyncDBObject("KSync Route"), ksync_(ksync), marked_delete_(false),
801 296 : table_delete_ref_(this, rt_table->deleter()) {
802 296 : rt_table_ = rt_table;
803 296 : RegisterDb(rt_table);
804 296 : }
805 :
806 592 : RouteKSyncObject::~RouteKSyncObject() {
807 296 : UnregisterDb(GetDBTable());
808 296 : table_delete_ref_.Reset(NULL);
809 592 : }
810 :
811 : KSyncDBObject::DBFilterResp
812 5057 : RouteKSyncObject::DBEntryFilter(const DBEntry *entry,
813 : const KSyncDBEntry *ksync) {
814 5057 : const AgentRoute *route = static_cast<const AgentRoute *>(entry);
815 : // Ignore Add/Change notifications when VRF is deleted
816 5057 : if (route->vrf()->IsDeleted() == true) {
817 2 : return DBFilterIgnore;
818 : }
819 :
820 5055 : if (route->GetActivePath()->inactive())
821 0 : return DBFilterIgnore;
822 5055 : return DBFilterAccept;
823 : }
824 :
825 1429 : KSyncEntry *RouteKSyncObject::Alloc(const KSyncEntry *entry, uint32_t index) {
826 1429 : const RouteKSyncEntry *route = static_cast<const RouteKSyncEntry *>(entry);
827 1429 : RouteKSyncEntry *ksync = new RouteKSyncEntry(this, route, index);
828 1429 : return static_cast<KSyncEntry *>(ksync);
829 : }
830 :
831 1429 : KSyncEntry *RouteKSyncObject::DBToKSyncEntry(const DBEntry *e) {
832 1429 : const AgentRoute *route = static_cast<const AgentRoute *>(e);
833 1429 : RouteKSyncEntry *key = new RouteKSyncEntry(this, route);
834 1429 : return static_cast<KSyncEntry *>(key);
835 : }
836 :
837 485 : void RouteKSyncObject::Unregister() {
838 485 : if (IsEmpty() == true && marked_delete_ == true) {
839 296 : KSYNC_TRACE(Trace, this, "Destroying ksync object: "\
840 : + rt_table_->name());
841 296 : KSyncObjectManager::Unregister(this);
842 : }
843 485 : }
844 :
845 296 : void RouteKSyncObject::ManagedDelete() {
846 296 : marked_delete_ = true;
847 296 : Unregister();
848 296 : }
849 :
850 217 : void RouteKSyncObject::EmptyTable() {
851 217 : if (marked_delete_ == true) {
852 189 : Unregister();
853 : }
854 217 : }
855 :
856 74 : VrfKSyncEntry::VrfKSyncEntry(VrfKSyncObject *obj, const VrfEntry *entry) :
857 74 : KSyncNetlinkDBEntry(kInvalidIndex), ksync_obj_(obj),
858 74 : vrf_id_(entry->vrf_id()), hbf_rintf_(entry->hbf_rintf()),
859 148 : hbf_lintf_(entry->hbf_lintf()) {
860 74 : }
861 :
862 74 : VrfKSyncEntry::VrfKSyncEntry(VrfKSyncObject *obj,
863 : const VrfKSyncEntry *entry,
864 74 : uint32_t index) :
865 : KSyncNetlinkDBEntry(index),
866 74 : vrf_id_(entry->vrf_id()), hbf_rintf_(entry->hbf_rintf()),
867 148 : hbf_lintf_(entry->hbf_lintf()) {
868 74 : ksync_obj_ = static_cast<VrfKSyncObject*>(entry->GetObject());
869 74 : }
870 :
871 296 : VrfKSyncEntry::~VrfKSyncEntry() {
872 296 : }
873 :
874 444 : KSyncDBObject *VrfKSyncEntry::GetObject() const {
875 444 : return ksync_obj_;
876 : }
877 :
878 670 : bool VrfKSyncEntry::IsLess(const KSyncEntry &rhs) const {
879 670 : const VrfKSyncEntry &entry = static_cast<const VrfKSyncEntry &> (rhs);
880 :
881 670 : if (vrf_id_ == entry.vrf_id()) {
882 148 : if (hbf_rintf_ == entry.hbf_rintf()) {
883 148 : return (hbf_lintf_ < entry.hbf_lintf());
884 : } else {
885 0 : return (hbf_rintf_ < entry.hbf_rintf());
886 : }
887 : } else {
888 522 : return (vrf_id_ < entry.vrf_id());
889 : }
890 : }
891 :
892 296 : std::string VrfKSyncEntry::ToString() const {
893 296 : std::stringstream s;
894 296 : s << "Vrf id: " << vrf_id() << " hbf lintf: " << hbf_lintf() <<
895 296 : " hbf rintf: " << hbf_rintf();
896 592 : return s.str();
897 296 : }
898 :
899 68 : bool VrfKSyncEntry::Sync(DBEntry* e) {
900 68 : VrfEntry *vrf = static_cast<VrfEntry *>(e);
901 :
902 136 : if ((vrf->hbf_rintf() != hbf_rintf_) ||
903 68 : (vrf->hbf_lintf() != hbf_lintf_)) {
904 0 : hbf_rintf_ = vrf->hbf_rintf();
905 0 : hbf_lintf_ = vrf->hbf_lintf();
906 0 : return true;
907 : }
908 :
909 68 : return false;
910 : }
911 :
912 148 : int VrfKSyncEntry::Encode(sandesh_op::type op, uint8_t replace_plen,
913 : char *buf, int buf_len) {
914 148 : vr_vrf_req encoder;
915 : int encode_len;
916 :
917 148 : encoder.set_h_op(op);
918 148 : encoder.set_vrf_idx(vrf_id_);
919 148 : encoder.set_vrf_hbfr_vif_idx(hbf_rintf_);
920 148 : encoder.set_vrf_hbfl_vif_idx(hbf_lintf_);
921 148 : encoder.set_vrf_flags(VRF_FLAG_HBF_L_VALID|VRF_FLAG_HBF_R_VALID);
922 :
923 148 : std::stringstream ss;
924 148 : ss << "Encoding VrfKSyncEntry, vrf_id_ " << vrf_id_ <<
925 148 : " hbf_rintf_ " << hbf_rintf_ << " hbf_lintf_ " << hbf_lintf_;
926 148 : HBFTRACE(Trace, ss.str());
927 :
928 148 : int error = 0;
929 148 : encode_len = encoder.WriteBinary((uint8_t *)buf, buf_len, &error);
930 148 : assert(error == 0);
931 148 : assert(encode_len <= buf_len);
932 148 : return encode_len;
933 148 : }
934 :
935 148 : void VrfKSyncEntry::FillObjectLog(sandesh_op::type type,
936 : KSyncVrfInfo &info) const {
937 148 : if (type == sandesh_op::ADD) {
938 74 : info.set_operation("ADD/CHANGE");
939 : } else {
940 74 : info.set_operation("DELETE");
941 : }
942 :
943 148 : info.set_vrf_id(vrf_id_);
944 148 : info.set_hbf_rintf(hbf_rintf_);
945 148 : info.set_hbf_lintf(hbf_lintf_);
946 148 : }
947 :
948 74 : int VrfKSyncEntry::AddMsg(char *buf, int buf_len) {
949 74 : KSyncVrfInfo info;
950 74 : FillObjectLog(sandesh_op::ADD, info);
951 74 : KSYNC_TRACE(Vrf, GetObject(), info);
952 148 : return Encode(sandesh_op::ADD, 0, buf, buf_len);
953 74 : }
954 :
955 0 : int VrfKSyncEntry::ChangeMsg(char *buf, int buf_len){
956 0 : KSyncVrfInfo info;
957 0 : FillObjectLog(sandesh_op::ADD, info);
958 0 : KSYNC_TRACE(Vrf, GetObject(), info);
959 :
960 0 : return Encode(sandesh_op::ADD, 0, buf, buf_len);
961 0 : }
962 :
963 74 : int VrfKSyncEntry::DeleteMsg(char *buf, int buf_len) {
964 74 : KSyncVrfInfo info;
965 74 : FillObjectLog(sandesh_op::DEL, info);
966 74 : KSYNC_TRACE(Vrf, GetObject(), info);
967 :
968 148 : return Encode(sandesh_op::DEL, 0, buf, buf_len);
969 74 : }
970 :
971 74 : KSyncEntry *VrfKSyncEntry::UnresolvedReference() {
972 74 : return NULL; // TODO: check this
973 : }
974 :
975 74 : VrfKSyncObject::VrfState::VrfState(Agent *agent) :
976 74 : DBState(), seen_(false),
977 74 : evpn_rt_table_listener_id_(DBTableBase::kInvalidId) {
978 74 : ksync_route_walker_.reset(new KSyncRouteWalker(agent, this));
979 : agent->oper_db()->agent_route_walk_manager()->
980 74 : RegisterWalker(static_cast<AgentRouteWalker *>
981 : (ksync_route_walker_.get()));
982 74 : }
983 :
984 74 : KSyncEntry *VrfKSyncObject::Alloc(const KSyncEntry *entry, uint32_t index) {
985 74 : const VrfKSyncEntry *vrf = static_cast<const VrfKSyncEntry *>(entry);
986 74 : VrfKSyncEntry *ksync = new VrfKSyncEntry(this, vrf, index);
987 74 : return static_cast<KSyncEntry *>(ksync);
988 : }
989 :
990 74 : KSyncEntry *VrfKSyncObject::DBToKSyncEntry(const DBEntry* e) {
991 74 : const VrfEntry *vrf = static_cast<const VrfEntry *>(e);
992 74 : VrfKSyncEntry *key = new VrfKSyncEntry(this, vrf);
993 74 : return static_cast<KSyncEntry *>(key);
994 : }
995 :
996 683 : void VrfKSyncObject::VrfNotify(DBTablePartBase *partition, DBEntryBase *e) {
997 683 : VrfEntry *vrf = static_cast<VrfEntry *>(e);
998 : VrfState *state = static_cast<VrfState *>
999 683 : (vrf->GetState(partition->parent(), vrf_listener_id_));
1000 683 : if (vrf->IsDeleted()) {
1001 541 : if (state) {
1002 74 : UnRegisterEvpnRouteTableListener(vrf, state);
1003 74 : vrf->ClearState(partition->parent(), vrf_listener_id_);
1004 74 : (static_cast<KSyncRouteWalker *>(state->ksync_route_walker_.get()))->EnqueueDelete();
1005 :
1006 74 : if (state->ksync_->IsDeleted() == false) {
1007 74 : if (state->ksync_->GetDBEntry() != NULL) {
1008 74 : state->ksync_->SetDBEntry(NULL);
1009 : }
1010 74 : NotifyEvent(state->ksync_, KSyncEntry::DEL_REQ);
1011 : }
1012 :
1013 74 : delete state;
1014 : }
1015 541 : return;
1016 : }
1017 :
1018 142 : if (state == NULL) {
1019 74 : state = new VrfState(ksync_->agent());
1020 74 : state->seen_ = true;
1021 :
1022 : // Create ksync entry for VRF
1023 : KSyncEntry *key;
1024 74 : key = DBToKSyncEntry(vrf);
1025 74 : state->ksync_ = static_cast<VrfKSyncEntry *>(CreateImpl(key));
1026 74 : delete key;
1027 74 : vrf->SetState(partition->parent(), vrf_listener_id_, state);
1028 74 : state->ksync_->SetDBEntry(vrf);
1029 74 : NotifyEvent(state->ksync_, KSyncEntry::ADD_CHANGE_REQ);
1030 :
1031 : // Get Inet4 Route table and register with KSync
1032 : AgentRouteTable *rt_table = static_cast<AgentRouteTable *>(vrf->
1033 74 : GetInet4UnicastRouteTable());
1034 74 : state->inet4_uc_route_table_ = new RouteKSyncObject(ksync_, rt_table);
1035 :
1036 : // Get Inet6 Route table and register with KSync
1037 : rt_table = static_cast<AgentRouteTable *>(vrf->
1038 74 : GetInet6UnicastRouteTable());
1039 74 : state->inet6_uc_route_table_ = new RouteKSyncObject(ksync_, rt_table);
1040 :
1041 : // Get Layer 2 Route table and register with KSync
1042 : rt_table = static_cast<AgentRouteTable *>(vrf->
1043 74 : GetBridgeRouteTable());
1044 74 : state->bridge_route_table_ = new RouteKSyncObject(ksync_, rt_table);
1045 :
1046 : //Now for multicast table. Ksync object for multicast table is
1047 : //not maintained in vrf list
1048 : //TODO Enhance ksyncobject for UC/MC, currently there is only one entry
1049 : //in MC so just use the UC object for time being.
1050 : rt_table = static_cast<AgentRouteTable *>(vrf->
1051 74 : GetInet4MulticastRouteTable());
1052 74 : state->inet4_mc_route_table_ = new RouteKSyncObject(ksync_, rt_table);
1053 :
1054 : //Add EVPN route table listener to update IP MAC binding table.
1055 : rt_table = static_cast<AgentRouteTable *>(vrf->
1056 74 : GetEvpnRouteTable());
1057 74 : KSYNC_TRACE(Trace, state->inet4_uc_route_table_,
1058 : "Subscribing to route table "\
1059 : + vrf->GetName());
1060 74 : if (state->evpn_rt_table_listener_id_ == DBTableBase::kInvalidId) {
1061 74 : state->evpn_rt_table_listener_id_ =
1062 74 : rt_table->Register(boost::bind(&VrfKSyncObject::EvpnRouteTableNotify,
1063 : this, _1, _2));
1064 : }
1065 74 : (static_cast<KSyncRouteWalker *>(state->ksync_route_walker_.get()))->
1066 74 : NotifyRoutes(vrf);
1067 : } else {
1068 68 : VrfKSyncEntry* ksync = state->ksync_;
1069 68 : if (ksync->Sync(vrf) || ksync->IsDeleted()) {
1070 0 : NotifyEvent(ksync, KSyncEntry::ADD_CHANGE_REQ);
1071 : }
1072 : }
1073 : }
1074 :
1075 1847 : void VrfKSyncObject::EvpnRouteTableNotify(DBTablePartBase *partition,
1076 : DBEntryBase *e) {
1077 1847 : const EvpnRouteEntry *evpn_rt = static_cast<const EvpnRouteEntry *>(e);
1078 :
1079 1847 : if (evpn_rt->IsType5())
1080 0 : return;
1081 :
1082 1847 : if (evpn_rt->IsDeleted()) {
1083 338 : DelIpMacBinding(evpn_rt->vrf(), evpn_rt->prefix_address(),
1084 : evpn_rt->mac(), evpn_rt->ethernet_tag());
1085 : } else {
1086 1509 : AddIpMacBinding(evpn_rt->vrf(), evpn_rt->prefix_address(),
1087 : evpn_rt->mac(),
1088 : evpn_rt->ethernet_tag(),
1089 1509 : evpn_rt->GetActivePath()->path_preference().preference(),
1090 1509 : evpn_rt->WaitForTraffic());
1091 : }
1092 1847 : return;
1093 : }
1094 :
1095 74 : void VrfKSyncObject::UnRegisterEvpnRouteTableListener(const VrfEntry *vrf,
1096 : VrfState *state) {
1097 74 : if (state->evpn_rt_table_listener_id_ == DBTableBase::kInvalidId)
1098 0 : return;
1099 :
1100 : AgentRouteTable *rt_table = static_cast<AgentRouteTable *>(vrf->
1101 74 : GetEvpnRouteTable());
1102 74 : rt_table->Unregister(state->evpn_rt_table_listener_id_);
1103 74 : state->evpn_rt_table_listener_id_ = DBTableBase::kInvalidId;
1104 : }
1105 :
1106 2 : VrfKSyncObject::VrfKSyncObject(KSync *ksync) :
1107 2 : KSyncDBObject("KSync Vrf"), ksync_(ksync), marked_delete_(false) {
1108 2 : vrf_table_ = ksync_->agent()->vrf_table();
1109 2 : }
1110 :
1111 4 : VrfKSyncObject::~VrfKSyncObject() {
1112 4 : }
1113 :
1114 2 : void VrfKSyncObject::RegisterDBClients() {
1115 2 : vrf_listener_id_ = ksync_->agent()->vrf_table()->Register
1116 2 : (boost::bind(&VrfKSyncObject::VrfNotify, this, _1, _2));
1117 2 : }
1118 :
1119 0 : void VrfKSyncObject::Shutdown() {
1120 0 : ksync_->agent()->vrf_table()->Unregister(vrf_listener_id_);
1121 0 : vrf_listener_id_ = -1;
1122 0 : }
1123 :
1124 4051 : void vr_route_req::Process(SandeshContext *context) {
1125 4051 : AgentSandeshContext *ioc = static_cast<AgentSandeshContext *>(context);
1126 4051 : ioc->RouteMsgHandler(this);
1127 4051 : }
1128 :
1129 148 : void vr_vrf_req::Process(SandeshContext *context) {
1130 148 : AgentSandeshContext *ioc = static_cast<AgentSandeshContext *>(context);
1131 148 : ioc->VrfMsgHandler(this);
1132 148 : }
1133 :
1134 : /****************************************************************************
1135 : * Methods to stitch IP and MAC addresses. The KSync object maintains mapping
1136 : * between IP <-> MAC in ip_mac_binding_ tree. The table is built based on
1137 : * Evpn routes.
1138 : *
1139 : * When an Inet route is notified, if it needs MAC Stitching, the MAC to
1140 : * stitch is found from the ip_mac_binding_ tree
1141 : *
1142 : * Any change to ip_mac_binding_ tree will also result in re-evaluation of
1143 : * Inet4/Inet6 route that may potentially have stitching changed
1144 : ****************************************************************************/
1145 :
1146 : // Compute if a route needs IP-MAC binding. A route needs IP-MAC binding if,
1147 : // 1. The NH points to interface or Tunnel-NH
1148 : // 2. NH does not belong to Service-Chain Interface
1149 : // 3. NH does not belong to Gateway Interface
1150 : // to interface or tunnel-nh
1151 2850 : bool VrfKSyncObject::RouteNeedsMacBinding(const InetUnicastRouteEntry *rt) {
1152 2850 : if (rt->prefix_address().is_v4() && rt->prefix_length() != 32)
1153 407 : return false;
1154 :
1155 2443 : if (rt->prefix_address().is_v6() && rt->prefix_length() != 128)
1156 4 : return false;
1157 :
1158 2439 : VnEntry *vn = NULL;
1159 2439 : if (rt->vrf() != ksync_->agent()->fabric_vrf()) {
1160 : //Check if VN is enabled for bridging, if not then skip mac binding.
1161 2093 : VnEntry *vn= rt->vrf()->vn();
1162 2093 : if (vn == NULL || (vn->bridging() == false))
1163 92 : return false;
1164 : }
1165 :
1166 : // If the route crosses a VN, we want packet to be routed. So, override
1167 2347 : const NextHop *nh = rt->GetActiveNextHop();
1168 2347 : if (nh == NULL)
1169 0 : return false;
1170 :
1171 3014 : if (nh->GetType() != NextHop::INTERFACE &&
1172 1268 : nh->GetType() != NextHop::TUNNEL &&
1173 1202 : nh->GetType() != NextHop::VLAN &&
1174 3615 : nh->GetType() != NextHop::VRF &&
1175 601 : nh->GetType() != NextHop::ARP)
1176 593 : return false;
1177 :
1178 1754 : if (IsGatewayOrServiceInterface(nh) == true)
1179 487 : return false;
1180 :
1181 1273 : if (nh->GetType() == NextHop::ARP &&
1182 1273 : rt->GetActivePath()->gw_ip() == Ip4Address(0)) {
1183 6 : return false;
1184 : }
1185 :
1186 1261 : if (nh->GetType() == NextHop::ARP && nh->IsValid() == false) {
1187 0 : return false;
1188 : }
1189 :
1190 : //Is this a IPAM gateway? It may happen that better path is present pointing
1191 : //to tunnel. In this case IPAM gateway path will not be active path and
1192 : //identifying same will be missed. Stitching has to be avoided on non-TSN
1193 : //node.
1194 : //This has to be done only when layer3 forwarding is enabled on VN,
1195 : //else mac binding should be done irrespective of IPAM gateway.
1196 1261 : if (vn && vn->layer3_forwarding()) {
1197 0 : const Agent *agent = ksync()->agent();
1198 0 : if (agent->tsn_enabled() == false) {
1199 0 : const AgentPath *path = rt->FindPath(agent->local_peer());
1200 0 : nh = path ? path->nexthop() : NULL;
1201 : }
1202 0 : if (nh && (IsGatewayOrServiceInterface(nh) == true))
1203 0 : return false;
1204 : }
1205 :
1206 1261 : return true;
1207 : }
1208 :
1209 : // Notify change to KSync entry of InetUnicast Route
1210 1847 : void VrfKSyncObject::NotifyUcRoute(VrfEntry *vrf, VrfState *state,
1211 : const IpAddress &ip) {
1212 1847 : InetUnicastAgentRouteTable *table = NULL;
1213 1847 : if (ip.is_v4()) {
1214 1847 : table = vrf->GetInet4UnicastRouteTable();
1215 : } else {
1216 0 : table = vrf->GetInet6UnicastRouteTable();
1217 : }
1218 :
1219 1847 : InetUnicastRouteEntry *rt = table->FindLPM(ip);
1220 1847 : if (rt == NULL || rt->IsDeleted())
1221 1002 : return;
1222 :
1223 845 : if (rt->GetTableType() == Agent::INET4_UNICAST) {
1224 845 : state->inet4_uc_route_table_->Notify(rt->get_table_partition(), rt);
1225 0 : } else if (rt->GetTableType() == Agent::INET6_UNICAST) {
1226 0 : state->inet6_uc_route_table_->Notify(rt->get_table_partition(), rt);
1227 : }
1228 : }
1229 :
1230 1509 : void VrfKSyncObject::AddIpMacBinding(VrfEntry *vrf, const IpAddress &ip,
1231 : const MacAddress &mac,
1232 : uint32_t ethernet_tag,
1233 : uint32_t pref,
1234 : bool wait_for_traffic) {
1235 : VrfState *state = static_cast<VrfState *>
1236 1509 : (vrf->GetState(vrf->get_table(), vrf_listener_id_));
1237 1509 : if (state == NULL)
1238 0 : return;
1239 :
1240 : IpToMacBinding::iterator it =
1241 1509 : state->ip_mac_binding_.find(std::make_pair(ip, ethernet_tag));
1242 :
1243 1509 : PathPreference path_pref(0, pref, wait_for_traffic, false);
1244 1509 : if (it == state->ip_mac_binding_.end()) {
1245 232 : MacBinding mac_binding(mac, path_pref);
1246 232 : state->ip_mac_binding_.insert(std::pair<IpToMacBindingKey, MacBinding>
1247 232 : (std::make_pair(ip, ethernet_tag), mac_binding));
1248 232 : } else {
1249 1277 : it->second.set_mac(path_pref, mac);
1250 : }
1251 :
1252 1509 : NotifyUcRoute(vrf, state, ip);
1253 1509 : }
1254 :
1255 338 : void VrfKSyncObject::DelIpMacBinding(VrfEntry *vrf, const IpAddress &ip,
1256 : const MacAddress &mac,
1257 : uint32_t ethernet_tag) {
1258 : VrfState *state = static_cast<VrfState *>
1259 338 : (vrf->GetState(vrf->get_table(), vrf_listener_id_));
1260 338 : if (state == NULL)
1261 0 : return;
1262 :
1263 : IpToMacBinding::iterator it =
1264 338 : state->ip_mac_binding_.find(std::make_pair(ip, ethernet_tag));
1265 338 : if (it != state->ip_mac_binding_.end()) {
1266 338 : it->second.reset_mac(mac);
1267 338 : if (it->second.can_erase()) {
1268 232 : state->ip_mac_binding_.erase(std::make_pair(ip, ethernet_tag));
1269 : }
1270 : }
1271 338 : NotifyUcRoute(vrf, state, ip);
1272 : }
1273 :
1274 1261 : bool VrfKSyncObject::GetIpMacWaitForTraffic(VrfEntry *vrf,
1275 : const IpAddress &ip) const {
1276 : VrfState *state = static_cast<VrfState *>
1277 1261 : (vrf->GetState(vrf->get_table(), vrf_listener_id_));
1278 1261 : if (state == NULL) {
1279 0 : return false;
1280 : }
1281 :
1282 : IpToMacBinding::const_iterator it =
1283 1261 : state->ip_mac_binding_.lower_bound(std::make_pair(ip, 0));
1284 2036 : if (it == state->ip_mac_binding_.end() ||
1285 775 : (it->first.first != ip)) {
1286 486 : return false;
1287 : }
1288 :
1289 775 : return it->second.WaitForTraffic();
1290 : }
1291 :
1292 1261 : MacAddress VrfKSyncObject::GetIpMacBinding(VrfEntry *vrf,
1293 : const IpAddress &ip,
1294 : const InetUnicastRouteEntry *rt)
1295 : const {
1296 : VrfState *state = static_cast<VrfState *>
1297 1261 : (vrf->GetState(vrf->get_table(), vrf_listener_id_));
1298 1261 : if (state == NULL)
1299 0 : return MacAddress::ZeroMac();
1300 :
1301 1261 : if (vrf->GetName() == ksync_->agent()->fabric_vrf_name()) {
1302 330 : if (rt->GetActivePath()->gw_ip() != Ip4Address(0)) {
1303 : const ArpNH *arp_nh =
1304 0 : dynamic_cast<const ArpNH *>(rt->GetActiveNextHop());
1305 0 : if (arp_nh) {
1306 0 : return arp_nh->GetMac();
1307 : }
1308 : }
1309 : }
1310 :
1311 : IpToMacBinding::const_iterator it =
1312 1261 : state->ip_mac_binding_.lower_bound(std::make_pair(ip, 0));
1313 2036 : if (it == state->ip_mac_binding_.end() ||
1314 775 : (it->first.first != ip)) {
1315 486 : return MacAddress::ZeroMac();
1316 : }
1317 :
1318 775 : return it->second.get_mac();
1319 : }
1320 :
1321 74 : KSyncRouteWalker::KSyncRouteWalker(Agent *agent, VrfKSyncObject::VrfState *state) :
1322 74 : AgentRouteWalker("ksyncroutewalker", agent), state_(state),
1323 74 : marked_for_deletion_(false) {
1324 74 : }
1325 :
1326 148 : KSyncRouteWalker::~KSyncRouteWalker() {
1327 148 : }
1328 :
1329 324 : bool IsStatePresent(AgentRoute *route, DBTableBase::ListenerId id,
1330 : DBTablePartBase *partition) {
1331 324 : DBState *state = route->GetState(partition->parent(), id);
1332 324 : return (state != NULL);
1333 : }
1334 :
1335 74 : void KSyncRouteWalker::EnqueueDelete() {
1336 74 : marked_for_deletion_ = true;
1337 74 : mgr()->ReleaseWalker(static_cast<AgentRouteWalker *>(this));
1338 74 : }
1339 :
1340 331 : bool KSyncRouteWalker::RouteWalkNotify(DBTablePartBase *partition,
1341 : DBEntryBase *e) {
1342 331 : if (marked_for_deletion_)
1343 0 : return true;
1344 :
1345 331 : AgentRoute *route = static_cast<AgentRoute *>(e);
1346 :
1347 331 : switch (route->GetTableType()) {
1348 15 : case Agent::INET4_UNICAST: {
1349 15 : if (IsStatePresent(route, state_->inet4_uc_route_table_->id(),
1350 15 : partition) == false) {
1351 0 : state_->inet4_uc_route_table_->Notify(partition, route);
1352 : }
1353 15 : break;
1354 : }
1355 14 : case Agent::INET6_UNICAST: {
1356 14 : if (IsStatePresent(route, state_->inet6_uc_route_table_->id(),
1357 14 : partition) == false) {
1358 0 : state_->inet6_uc_route_table_->Notify(partition, route);
1359 : }
1360 14 : break;
1361 : }
1362 0 : case Agent::INET4_MULTICAST: {
1363 0 : if (IsStatePresent(route, state_->inet4_mc_route_table_->id(),
1364 0 : partition) == false) {
1365 0 : state_->inet4_mc_route_table_->Notify(partition, route);
1366 : }
1367 0 : break;
1368 : }
1369 295 : case Agent::BRIDGE: {
1370 295 : if (IsStatePresent(route, state_->bridge_route_table_->id(),
1371 295 : partition) == false) {
1372 0 : state_->bridge_route_table_->Notify(partition, route);
1373 : }
1374 295 : break;
1375 : }
1376 7 : default: {
1377 7 : break;
1378 : }
1379 : }
1380 331 : return true;
1381 : }
1382 :
1383 74 : void KSyncRouteWalker::NotifyRoutes(VrfEntry *vrf) {
1384 74 : if (marked_for_deletion_ == false)
1385 74 : StartRouteWalk(vrf);
1386 74 : }
|