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