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 274 : RouteKSyncEntry::RouteKSyncEntry(RouteKSyncObject* obj,
40 : const RouteKSyncEntry *entry,
41 274 : uint32_t index) :
42 274 : KSyncNetlinkDBEntry(index), ksync_obj_(obj),
43 274 : rt_type_(entry->rt_type_), vrf_id_(entry->vrf_id_),
44 274 : addr_(entry->addr_), src_addr_(entry->src_addr_), mac_(entry->mac_),
45 274 : prefix_len_(entry->prefix_len_), nh_(entry->nh_), label_(entry->label_),
46 274 : proxy_arp_(false), flood_dhcp_(entry->flood_dhcp_),
47 274 : address_string_(entry->address_string_),
48 274 : tunnel_type_(entry->tunnel_type_),
49 274 : wait_for_traffic_(entry->wait_for_traffic_),
50 274 : local_vm_peer_route_(entry->local_vm_peer_route_),
51 274 : flood_(entry->flood_), ethernet_tag_(entry->ethernet_tag_),
52 274 : layer2_control_word_(entry->layer2_control_word_),
53 274 : is_learnt_route_(entry->is_learnt_route_) {
54 274 : }
55 :
56 145 : RouteKSyncEntry::RouteKSyncEntry(RouteKSyncObject* obj, const AgentRoute *rt) :
57 145 : KSyncNetlinkDBEntry(kInvalidIndex), ksync_obj_(obj),
58 145 : vrf_id_(rt->vrf_id()), mac_(), nh_(NULL), label_(0), proxy_arp_(false),
59 145 : flood_dhcp_(false), tunnel_type_(TunnelType::DefaultType()),
60 145 : wait_for_traffic_(false), local_vm_peer_route_(false),
61 145 : flood_(false), ethernet_tag_(0), layer2_control_word_(false),
62 290 : is_learnt_route_(false) {
63 145 : boost::system::error_code ec;
64 145 : rt_type_ = rt->GetTableType();
65 145 : switch (rt_type_) {
66 55 : case Agent::INET4_UNICAST: {
67 55 : const InetUnicastRouteEntry *uc_rt =
68 : static_cast<const InetUnicastRouteEntry *>(rt);
69 55 : addr_ = uc_rt->prefix_address();
70 55 : src_addr_ = IpAddress::from_string("0.0.0.0", ec).to_v4();
71 55 : prefix_len_ = uc_rt->prefix_length();
72 55 : AgentPath *local_vm_path = uc_rt->FindLocalVmPortPath();
73 55 : if (local_vm_path && local_vm_path->IsDynamicLearntRoute()) {
74 2 : is_learnt_route_ = true;
75 : }
76 :
77 55 : break;
78 : }
79 24 : case Agent::INET6_UNICAST: {
80 24 : const InetUnicastRouteEntry *uc_rt =
81 : static_cast<const InetUnicastRouteEntry *>(rt);
82 24 : addr_ = uc_rt->prefix_address();
83 24 : src_addr_ = Ip6Address();
84 24 : prefix_len_ = uc_rt->prefix_length();
85 24 : 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 66 : case Agent::BRIDGE: {
96 66 : const BridgeRouteEntry *l2_rt =
97 : static_cast<const BridgeRouteEntry *>(rt);
98 66 : mac_ = l2_rt->prefix_address();
99 66 : prefix_len_ = 0;
100 66 : break;
101 : }
102 0 : default: {
103 0 : assert(0);
104 : }
105 : }
106 145 : address_string_ = rt->GetAddressString();
107 145 : }
108 :
109 693 : RouteKSyncEntry::~RouteKSyncEntry() {
110 693 : }
111 :
112 5381 : KSyncDBObject *RouteKSyncEntry::GetObject() const {
113 5381 : return ksync_obj_;
114 : }
115 :
116 12145 : bool RouteKSyncEntry::UcIsLess(const KSyncEntry &rhs) const {
117 12145 : const RouteKSyncEntry &entry = static_cast<const RouteKSyncEntry &>(rhs);
118 12145 : if (vrf_id_ != entry.vrf_id_) {
119 0 : return vrf_id_ < entry.vrf_id_;
120 : }
121 :
122 12145 : if (addr_ != entry.addr_) {
123 11698 : return addr_ < entry.addr_;
124 : }
125 :
126 447 : 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 594 : bool RouteKSyncEntry::L2IsLess(const KSyncEntry &rhs) const {
143 594 : const RouteKSyncEntry &entry = static_cast<const RouteKSyncEntry &>(rhs);
144 :
145 594 : if (vrf_id_ != entry.vrf_id_) {
146 0 : return vrf_id_ < entry.vrf_id_;
147 : }
148 :
149 594 : return mac_ < entry.mac_;
150 : }
151 :
152 12739 : bool RouteKSyncEntry::IsLess(const KSyncEntry &rhs) const {
153 12739 : const RouteKSyncEntry &entry = static_cast<const RouteKSyncEntry &>(rhs);
154 12739 : if (rt_type_ != entry.rt_type_)
155 0 : return rt_type_ < entry.rt_type_;
156 :
157 : //First unicast
158 12739 : if ((rt_type_ == Agent::INET4_UNICAST) ||
159 8513 : (rt_type_ == Agent::INET6_UNICAST)) {
160 12145 : return UcIsLess(rhs);
161 : }
162 :
163 594 : if (rt_type_ == Agent::BRIDGE) {
164 594 : return L2IsLess(rhs);
165 : }
166 :
167 0 : return McIsLess(rhs);
168 : }
169 :
170 1200 : static std::string RouteTypeToString(Agent::RouteTableType type) {
171 1200 : switch (type) {
172 528 : case Agent::INET4_UNICAST:
173 528 : return "INET4_UNICAST";
174 : break;
175 162 : case Agent::INET6_UNICAST:
176 162 : return "INET6_UNICAST";
177 : break;
178 0 : case Agent::INET4_MULTICAST:
179 0 : return "INET_MULTICAST";
180 : break;
181 510 : case Agent::BRIDGE:
182 510 : return "BRIDGE";
183 : break;
184 0 : default:
185 0 : break;
186 : }
187 :
188 0 : assert(0);
189 : return "";
190 : }
191 :
192 861 : std::string RouteKSyncEntry::ToString() const {
193 861 : std::stringstream s;
194 : NHKSyncEntry *nexthop;
195 861 : nexthop = nh();
196 :
197 861 : s << "Type : " << RouteTypeToString(rt_type_) << " ";
198 : const VrfEntry* vrf =
199 861 : ksync_obj_->ksync()->agent()->vrf_table()->FindVrfFromId(vrf_id_);
200 861 : if (vrf) {
201 793 : s << "Route Vrf : " << vrf->GetName() << " ";
202 : }
203 861 : s << address_string_ << "/" << prefix_len_ << " Type:" << rt_type_;
204 :
205 :
206 861 : s << " Label : " << label_;
207 861 : s << " Tunnel Type: " << tunnel_type_;
208 :
209 861 : if (nexthop) {
210 802 : s << nexthop->ToString();
211 : } else {
212 59 : s << " NextHop : <NULL>";
213 : }
214 :
215 861 : s << " Mac: " << mac_.ToString();
216 861 : s << " Flood DHCP:" << flood_dhcp_;
217 1722 : return s.str();
218 861 : }
219 :
220 : // Check if NH points to a service-chain interface or a Gateway interface
221 322 : static bool IsGatewayOrServiceInterface(const NextHop *nh) {
222 420 : if (nh->GetType() != NextHop::INTERFACE &&
223 420 : nh->GetType() != NextHop::VLAN && nh->GetType() != NextHop::ARP)
224 59 : return false;
225 :
226 263 : const Interface *intf = NULL;
227 263 : if (nh->GetType() == NextHop::INTERFACE) {
228 224 : intf = (static_cast<const InterfaceNH *>(nh))->GetInterface();
229 224 : if (intf->type() == Interface::PACKET)
230 57 : return true;
231 39 : } else if (nh->GetType() == NextHop::VLAN) {
232 0 : intf = (static_cast<const VlanNH *>(nh))->GetInterface();
233 39 : } else if (nh->GetType() == NextHop::ARP) {
234 39 : intf = (static_cast<const ArpNH *>(nh))->GetInterface();
235 : }
236 :
237 206 : const VmInterface *vmi = dynamic_cast<const VmInterface *>(intf);
238 206 : if (vmi == NULL)
239 14 : return false;
240 :
241 192 : if (vmi->HasServiceVlan())
242 0 : return true;
243 192 : if (vmi->device_type() == VmInterface::LOCAL_DEVICE)
244 71 : return true;
245 :
246 121 : 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 274 : bool RouteKSyncEntry::BuildArpFlags(const DBEntry *e, const AgentPath *path,
255 : const MacAddress &mac) {
256 274 : bool ret = false;
257 :
258 : //Route flags for inet4 and inet6
259 274 : if ((rt_type_ != Agent::INET6_UNICAST) &&
260 226 : (rt_type_ != Agent::INET4_UNICAST))
261 0 : return false;
262 :
263 274 : Agent *agent = ksync_obj_->ksync()->agent();
264 274 : const InetUnicastRouteEntry *rt =
265 : static_cast<const InetUnicastRouteEntry *>(e);
266 :
267 : // Assume no flood and proxy_arp by default
268 274 : bool flood = false;
269 274 : bool proxy_arp = false;
270 274 : const NextHop *nh = rt->GetActiveNextHop();
271 :
272 274 : if (nh == NULL) {
273 0 : return false;
274 : }
275 274 : switch (nh->GetType()) {
276 9 : 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 9 : if (rt->vrf()->GetName() != agent->fabric_vrf_name()) {
281 0 : proxy_arp = true;
282 : }
283 9 : 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 254 : 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 232 : if (IsGatewayOrServiceInterface(nh) == true) {
323 89 : proxy_arp = true;
324 89 : flood = false;
325 89 : break;
326 : }
327 :
328 143 : AgentPath *local_vm_path = rt->FindLocalVmPortPath();
329 143 : 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 79 : proxy_arp = rt->proxy_arp();
346 79 : flood = rt->ipam_host_route();
347 : }
348 143 : 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 274 : 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 274 : VnEntry *vn= rt->vrf()->vn();
364 124 : if (vn == NULL || !path->dest_vn_match(vn->GetName()) ||
365 398 : (path->dest_vn_list().size() > 1) ||
366 62 : (vn->bridging() == false)) {
367 212 : proxy_arp = true;
368 212 : 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 274 : 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 274 : if (rt->vrf()->GetName() == agent->fabric_vrf_name()) {
380 164 : if (mac != MacAddress() || nh->GetType() == NextHop::INTERFACE ||
381 66 : nh->GetType() == NextHop::COMPOSITE) {
382 32 : proxy_arp = true;
383 : } else {
384 66 : proxy_arp = false;
385 : }
386 98 : flood = false;
387 : }
388 :
389 274 : if (proxy_arp != proxy_arp_) {
390 107 : proxy_arp_ = proxy_arp;
391 107 : ret = true;
392 : }
393 :
394 274 : if (flood != flood_) {
395 5 : flood_ = flood;
396 5 : ret = true;
397 : }
398 274 : return ret;
399 : }
400 :
401 : //Uses internal API to extract path.
402 453 : const NextHop *RouteKSyncEntry::GetActiveNextHop(const AgentRoute *route) const {
403 453 : const AgentPath *path = GetActivePath(route);
404 453 : if (path == NULL)
405 0 : return NULL;
406 453 : 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 906 : const AgentPath *RouteKSyncEntry::GetActivePath(const AgentRoute *route) const {
414 906 : const AgentPath *path = route->GetActivePath();
415 906 : return path;
416 : }
417 :
418 453 : bool RouteKSyncEntry::Sync(DBEntry *e) {
419 453 : bool ret = false;
420 453 : Agent *agent = ksync_obj_->ksync()->agent();
421 453 : const AgentRoute *route = static_cast<AgentRoute *>(e);
422 :
423 453 : const AgentPath *path = GetActivePath(route);
424 453 : if (path->peer() == agent->local_vm_peer())
425 55 : local_vm_peer_route_ = true;
426 : else
427 398 : local_vm_peer_route_ = false;
428 :
429 453 : NHKSyncObject *nh_object = ksync_obj_->ksync()->nh_ksync_obj();
430 453 : NHKSyncEntry *old_nh = nh();
431 :
432 453 : const NextHop *tmp = NULL;
433 453 : 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 1116 : if (tmp == NULL ||
440 663 : ((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 453 : NHKSyncEntry nexthop(nh_object, tmp);
446 453 : nh_ = static_cast<NHKSyncEntry *>(nh_object->GetReference(&nexthop));
447 453 : if (old_nh != nh()) {
448 168 : ret = true;
449 : }
450 :
451 : //Bother for label for unicast and bridge routes
452 453 : if (rt_type_ != Agent::INET4_MULTICAST) {
453 453 : uint32_t old_label = label_;
454 :
455 453 : if (route->is_multicast()) {
456 41 : label_ = path->vxlan_id();
457 : } else {
458 412 : label_ = path->GetActiveLabel();
459 : }
460 453 : if (label_ != old_label) {
461 112 : ret = true;
462 : }
463 :
464 453 : if (tunnel_type_ != path->GetTunnelType()) {
465 19 : tunnel_type_ = path->GetTunnelType();
466 19 : ret = true;
467 : }
468 : }
469 :
470 453 : if (wait_for_traffic_ != route->WaitForTraffic()) {
471 145 : wait_for_traffic_ = route->WaitForTraffic();
472 145 : ret = true;
473 : }
474 :
475 453 : if (route->GetActivePath()) {
476 453 : 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 453 : if (rt_type_ == Agent::INET4_UNICAST || rt_type_ == Agent::INET6_UNICAST) {
483 274 : VrfKSyncObject *obj = ksync_obj_->ksync()->vrf_ksync_obj();
484 274 : const InetUnicastRouteEntry *uc_rt =
485 : static_cast<const InetUnicastRouteEntry *>(e);
486 274 : MacAddress mac = MacAddress::ZeroMac();
487 274 : bool wait_for_traffic = false;
488 :
489 274 : if (obj->RouteNeedsMacBinding(uc_rt)) {
490 47 : mac = obj->GetIpMacBinding(uc_rt->vrf(), addr_, uc_rt);
491 47 : wait_for_traffic = obj->GetIpMacWaitForTraffic(uc_rt->vrf(), addr_);
492 : }
493 :
494 274 : 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 274 : if (mac != mac_) {
501 4 : mac_ = mac;
502 4 : ret = true;
503 : }
504 :
505 274 : if (BuildArpFlags(e, path, mac_))
506 110 : ret = true;
507 : }
508 :
509 453 : if (rt_type_ == Agent::BRIDGE) {
510 179 : const BridgeRouteEntry *l2_rt =
511 : static_cast<const BridgeRouteEntry *>(route);
512 :
513 : //First search for v4
514 179 : const MacVmBindingPath *dhcp_path = l2_rt->FindMacVmBindingPath();
515 179 : bool flood_dhcp = true; // Flood DHCP if MacVmBindingPath is not present
516 179 : if (dhcp_path)
517 57 : flood_dhcp = dhcp_path->flood_dhcp();
518 :
519 179 : if (flood_dhcp_ != flood_dhcp) {
520 47 : flood_dhcp_ = flood_dhcp;
521 47 : ret = true;
522 : }
523 : }
524 :
525 453 : return ret;
526 453 : }
527 :
528 339 : void RouteKSyncEntry::FillObjectLog(sandesh_op::type type,
529 : KSyncRouteInfo &info) const {
530 339 : if (type == sandesh_op::ADD) {
531 202 : info.set_operation("ADD/CHANGE");
532 : } else {
533 137 : info.set_operation("DELETE");
534 : }
535 :
536 339 : info.set_addr(address_string_);
537 339 : info.set_plen(prefix_len_);
538 339 : info.set_vrf(vrf_id_);
539 :
540 339 : if (nh()) {
541 280 : info.set_nh_idx(nh()->nh_id());
542 280 : if (nh()->type() == NextHop::TUNNEL) {
543 13 : info.set_label(label_);
544 : }
545 : } else {
546 59 : info.set_nh_idx(NH_DISCARD_ID);
547 : }
548 :
549 339 : info.set_mac(mac_.ToString());
550 339 : info.set_type(RouteTypeToString(rt_type_));
551 339 : }
552 :
553 339 : int RouteKSyncEntry::Encode(sandesh_op::type op, uint8_t replace_plen,
554 : char *buf, int buf_len) {
555 339 : vr_route_req encoder;
556 : int encode_len;
557 339 : NHKSyncEntry *nexthop = nh();
558 :
559 339 : encoder.set_h_op(op);
560 339 : encoder.set_rtr_rid(0);
561 339 : encoder.set_rtr_vrf_id(vrf_id_);
562 339 : if (rt_type_ != Agent::BRIDGE) {
563 198 : if (addr_.is_v4()) {
564 150 : encoder.set_rtr_family(AF_INET);
565 150 : Ip4Address::bytes_type bytes = addr_.to_v4().to_bytes();
566 150 : std::vector<int8_t> rtr_prefix(bytes.begin(), bytes.end());
567 150 : encoder.set_rtr_prefix(rtr_prefix);
568 198 : } else if (addr_.is_v6()) {
569 48 : encoder.set_rtr_family(AF_INET6);
570 48 : Ip6Address::bytes_type bytes = addr_.to_v6().to_bytes();
571 48 : std::vector<int8_t> rtr_prefix(bytes.begin(), bytes.end());
572 48 : encoder.set_rtr_prefix(rtr_prefix);
573 48 : }
574 198 : encoder.set_rtr_prefix_len(prefix_len_);
575 198 : 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 141 : encoder.set_rtr_family(AF_BRIDGE);
588 : //TODO add support for mac
589 : std::vector<int8_t> mac((int8_t *)mac_,
590 141 : (int8_t *)mac_ + mac_.size());
591 141 : encoder.set_rtr_mac(mac);
592 141 : }
593 :
594 339 : int label = 0;
595 339 : int flags = 0;
596 339 : 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 641 : if (nexthop != NULL && ((nexthop->type() == NextHop::TUNNEL) ||
601 302 : ((nexthop->type() == NextHop::COMPOSITE) &&
602 35 : (nexthop->CompositeType() == Composite::LU_ECMP)))) {
603 13 : label = label_;
604 13 : flags |= VR_RT_LABEL_VALID_FLAG;
605 : }
606 : }
607 :
608 339 : if (rt_type_ == Agent::BRIDGE) {
609 141 : label = label_;
610 252 : if (nexthop != NULL && ((nexthop->type() == NextHop::COMPOSITE) ||
611 111 : (nexthop->type() == NextHop::TUNNEL))) {
612 39 : flags |= VR_BE_LABEL_VALID_FLAG;
613 : }
614 141 : if (flood_dhcp_) {
615 109 : flags |= VR_BE_FLOOD_DHCP_FLAG;
616 : }
617 141 : if (ksync_obj_->ksync()->agent()->tsn_no_forwarding_enabled()) {
618 0 : flags |= VR_BE_EVPN_CONTROL_PROCESSING_FLAG;
619 : }
620 : } else {
621 :
622 198 : if (proxy_arp_) {
623 96 : flags |= VR_RT_ARP_PROXY_FLAG;
624 : }
625 :
626 198 : if (wait_for_traffic_) {
627 122 : flags |= VR_RT_ARP_TRAP_FLAG;
628 : }
629 :
630 198 : if (flood_) {
631 12 : flags |= VR_RT_ARP_FLOOD_FLAG;
632 : }
633 :
634 198 : if (is_learnt_route_) {
635 2 : flags |= VR_RT_MAC_IP_LEARNT_FLAG;
636 : }
637 :
638 : }
639 :
640 339 : if (layer2_control_word_) {
641 0 : flags |= VR_BE_L2_CONTROL_DATA_FLAG;
642 : }
643 :
644 339 : encoder.set_rtr_label_flags(flags);
645 339 : encoder.set_rtr_label(label);
646 339 : if (nexthop != NULL) {
647 280 : encoder.set_rtr_nh_id(nexthop->nh_id());
648 : } else {
649 59 : encoder.set_rtr_nh_id(NH_DISCARD_ID);
650 : }
651 :
652 339 : if (op == sandesh_op::DEL) {
653 137 : encoder.set_rtr_replace_plen(replace_plen);
654 : }
655 :
656 339 : int error = 0;
657 339 : encode_len = encoder.WriteBinary((uint8_t *)buf, buf_len, &error);
658 339 : assert(error == 0);
659 339 : assert(encode_len <= buf_len);
660 339 : return encode_len;
661 339 : }
662 :
663 :
664 137 : int RouteKSyncEntry::AddMsg(char *buf, int buf_len) {
665 137 : KSyncRouteInfo info;
666 137 : FillObjectLog(sandesh_op::ADD, info);
667 137 : KSYNC_TRACE(Route, GetObject(), info);
668 274 : return Encode(sandesh_op::ADD, 0, buf, buf_len);
669 137 : }
670 :
671 65 : int RouteKSyncEntry::ChangeMsg(char *buf, int buf_len){
672 65 : KSyncRouteInfo info;
673 65 : FillObjectLog(sandesh_op::ADD, info);
674 65 : KSYNC_TRACE(Route, GetObject(), info);
675 :
676 130 : return Encode(sandesh_op::ADD, 0, buf, buf_len);
677 65 : }
678 :
679 137 : int RouteKSyncEntry::DeleteMsg(char *buf, int buf_len) {
680 :
681 137 : RouteKSyncEntry key(ksync_obj_, this, KSyncEntry::kInvalidIndex);
682 137 : KSyncEntry *found = NULL;
683 137 : RouteKSyncEntry *route = NULL;
684 137 : NHKSyncEntry *ksync_nh = NULL;
685 :
686 : // IF multicast or bridge delete unconditionally
687 137 : if ((rt_type_ == Agent::BRIDGE) ||
688 79 : (rt_type_ == Agent::INET4_MULTICAST)) {
689 58 : return DeleteInternal(nh(), NULL, buf, buf_len);
690 : }
691 :
692 : // For INET routes, we need to give replacement NH and prefixlen
693 3995 : for (int plen = (prefix_len() - 1); plen >= 0; plen--) {
694 :
695 3936 : if (addr_.is_v4()) {
696 1224 : Ip4Address addr = Address::GetIp4SubnetAddress(addr_.to_v4(), plen);
697 1224 : key.set_ip(addr);
698 2712 : } else if (addr_.is_v6()) {
699 2712 : Ip6Address addr = Address::GetIp6SubnetAddress(addr_.to_v6(), plen);
700 2712 : key.set_ip(addr);
701 : }
702 :
703 3936 : key.set_prefix_len(plen);
704 3936 : found = GetObject()->Find(&key);
705 :
706 3936 : if (found) {
707 28 : route = static_cast<RouteKSyncEntry *>(found);
708 28 : if (route->IsResolved()) {
709 20 : ksync_nh = route->nh();
710 20 : if(ksync_nh) {
711 20 : 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 59 : return DeleteInternal(NULL, NULL, buf, buf_len);
720 137 : }
721 :
722 137 : uint8_t RouteKSyncEntry::CopyReplacementData(NHKSyncEntry *nexthop,
723 : RouteKSyncEntry *new_rt) {
724 137 : uint8_t new_plen = 0;
725 137 : nh_ = nexthop;
726 137 : if (new_rt == NULL) {
727 117 : label_ = 0;
728 117 : proxy_arp_ = false;
729 117 : flood_ = false;
730 117 : 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 117 : if (rt_type_ != Agent::BRIDGE) {
734 59 : mac_ = MacAddress::ZeroMac();
735 : }
736 117 : is_learnt_route_ = false;
737 : } else {
738 20 : label_ = new_rt->label();
739 20 : new_plen = new_rt->prefix_len();
740 20 : proxy_arp_ = new_rt->proxy_arp();
741 20 : flood_ = new_rt->flood();
742 20 : wait_for_traffic_ = new_rt->wait_for_traffic();
743 20 : mac_ = new_rt->mac();
744 20 : is_learnt_route_ = new_rt->IsLearntRoute();
745 : }
746 137 : return new_plen;
747 : }
748 :
749 137 : int RouteKSyncEntry::DeleteInternal(NHKSyncEntry *nexthop,
750 : RouteKSyncEntry *new_rt,
751 : char *buf, int buf_len) {
752 137 : uint8_t replace_plen = CopyReplacementData(nexthop, new_rt);
753 137 : KSyncRouteInfo info;
754 137 : FillObjectLog(sandesh_op::DEL, info);
755 137 : KSYNC_TRACE(Route, GetObject(), info);
756 :
757 274 : return Encode(sandesh_op::DEL, replace_plen, buf, buf_len);
758 137 : }
759 :
760 381 : KSyncEntry *RouteKSyncEntry::UnresolvedReference() {
761 381 : NHKSyncEntry *nexthop = nh();
762 381 : if (!nexthop->IsResolvedAndInSync()) {
763 175 : return nexthop;
764 : }
765 :
766 206 : if ((rt_type_ == Agent::INET4_UNICAST) ||
767 107 : (rt_type_ == Agent::INET6_UNICAST)) {
768 123 : 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 202 : return NULL;
796 : }
797 :
798 48 : RouteKSyncObject::RouteKSyncObject(KSync *ksync, AgentRouteTable *rt_table):
799 48 : KSyncDBObject("KSync Route"), ksync_(ksync), marked_delete_(false),
800 48 : table_delete_ref_(this, rt_table->deleter()) {
801 48 : rt_table_ = rt_table;
802 48 : RegisterDb(rt_table);
803 48 : }
804 :
805 96 : RouteKSyncObject::~RouteKSyncObject() {
806 48 : UnregisterDb(GetDBTable());
807 48 : table_delete_ref_.Reset(NULL);
808 96 : }
809 :
810 : KSyncDBObject::DBFilterResp
811 453 : RouteKSyncObject::DBEntryFilter(const DBEntry *entry,
812 : const KSyncDBEntry *ksync) {
813 453 : const AgentRoute *route = static_cast<const AgentRoute *>(entry);
814 : // Ignore Add/Change notifications when VRF is deleted
815 453 : if (route->vrf()->IsDeleted() == true) {
816 0 : return DBFilterIgnore;
817 : }
818 :
819 453 : if (route->GetActivePath()->inactive())
820 0 : return DBFilterIgnore;
821 453 : return DBFilterAccept;
822 : }
823 :
824 137 : KSyncEntry *RouteKSyncObject::Alloc(const KSyncEntry *entry, uint32_t index) {
825 137 : const RouteKSyncEntry *route = static_cast<const RouteKSyncEntry *>(entry);
826 137 : RouteKSyncEntry *ksync = new RouteKSyncEntry(this, route, index);
827 137 : return static_cast<KSyncEntry *>(ksync);
828 : }
829 :
830 137 : KSyncEntry *RouteKSyncObject::DBToKSyncEntry(const DBEntry *e) {
831 137 : const AgentRoute *route = static_cast<const AgentRoute *>(e);
832 137 : RouteKSyncEntry *key = new RouteKSyncEntry(this, route);
833 137 : return static_cast<KSyncEntry *>(key);
834 : }
835 :
836 58 : void RouteKSyncObject::Unregister() {
837 58 : if (IsEmpty() == true && marked_delete_ == true) {
838 48 : KSYNC_TRACE(Trace, this, "Destroying ksync object: "\
839 : + rt_table_->name());
840 48 : KSyncObjectManager::Unregister(this);
841 : }
842 58 : }
843 :
844 48 : void RouteKSyncObject::ManagedDelete() {
845 48 : marked_delete_ = true;
846 48 : Unregister();
847 48 : }
848 :
849 33 : void RouteKSyncObject::EmptyTable() {
850 33 : if (marked_delete_ == true) {
851 10 : Unregister();
852 : }
853 33 : }
854 :
855 12 : VrfKSyncEntry::VrfKSyncEntry(VrfKSyncObject *obj, const VrfEntry *entry) :
856 12 : KSyncNetlinkDBEntry(kInvalidIndex), ksync_obj_(obj),
857 12 : vrf_id_(entry->vrf_id()), hbf_rintf_(entry->hbf_rintf()),
858 24 : hbf_lintf_(entry->hbf_lintf()) {
859 12 : }
860 :
861 12 : VrfKSyncEntry::VrfKSyncEntry(VrfKSyncObject *obj,
862 : const VrfKSyncEntry *entry,
863 12 : uint32_t index) :
864 : KSyncNetlinkDBEntry(index),
865 12 : vrf_id_(entry->vrf_id()), hbf_rintf_(entry->hbf_rintf()),
866 24 : hbf_lintf_(entry->hbf_lintf()) {
867 12 : ksync_obj_ = static_cast<VrfKSyncObject*>(entry->GetObject());
868 12 : }
869 :
870 48 : VrfKSyncEntry::~VrfKSyncEntry() {
871 48 : }
872 :
873 72 : KSyncDBObject *VrfKSyncEntry::GetObject() const {
874 72 : return ksync_obj_;
875 : }
876 :
877 69 : bool VrfKSyncEntry::IsLess(const KSyncEntry &rhs) const {
878 69 : const VrfKSyncEntry &entry = static_cast<const VrfKSyncEntry &> (rhs);
879 :
880 69 : if (vrf_id_ == entry.vrf_id()) {
881 24 : if (hbf_rintf_ == entry.hbf_rintf()) {
882 24 : return (hbf_lintf_ < entry.hbf_lintf());
883 : } else {
884 0 : return (hbf_rintf_ < entry.hbf_rintf());
885 : }
886 : } else {
887 45 : return (vrf_id_ < entry.vrf_id());
888 : }
889 : }
890 :
891 48 : std::string VrfKSyncEntry::ToString() const {
892 48 : std::stringstream s;
893 48 : s << "Vrf id: " << vrf_id() << " hbf lintf: " << hbf_lintf() <<
894 48 : " hbf rintf: " << hbf_rintf();
895 96 : return s.str();
896 48 : }
897 :
898 6 : bool VrfKSyncEntry::Sync(DBEntry* e) {
899 6 : VrfEntry *vrf = static_cast<VrfEntry *>(e);
900 :
901 12 : if ((vrf->hbf_rintf() != hbf_rintf_) ||
902 6 : (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 6 : return false;
909 : }
910 :
911 24 : int VrfKSyncEntry::Encode(sandesh_op::type op, uint8_t replace_plen,
912 : char *buf, int buf_len) {
913 24 : vr_vrf_req encoder;
914 : int encode_len;
915 :
916 24 : encoder.set_h_op(op);
917 24 : encoder.set_vrf_idx(vrf_id_);
918 24 : encoder.set_vrf_hbfr_vif_idx(hbf_rintf_);
919 24 : encoder.set_vrf_hbfl_vif_idx(hbf_lintf_);
920 24 : encoder.set_vrf_flags(VRF_FLAG_HBF_L_VALID|VRF_FLAG_HBF_R_VALID);
921 :
922 24 : std::stringstream ss;
923 24 : ss << "Encoding VrfKSyncEntry, vrf_id_ " << vrf_id_ <<
924 24 : " hbf_rintf_ " << hbf_rintf_ << " hbf_lintf_ " << hbf_lintf_;
925 24 : HBFTRACE(Trace, ss.str());
926 :
927 24 : int error = 0;
928 24 : encode_len = encoder.WriteBinary((uint8_t *)buf, buf_len, &error);
929 24 : assert(error == 0);
930 24 : assert(encode_len <= buf_len);
931 24 : return encode_len;
932 24 : }
933 :
934 24 : void VrfKSyncEntry::FillObjectLog(sandesh_op::type type,
935 : KSyncVrfInfo &info) const {
936 24 : if (type == sandesh_op::ADD) {
937 12 : info.set_operation("ADD/CHANGE");
938 : } else {
939 12 : info.set_operation("DELETE");
940 : }
941 :
942 24 : info.set_vrf_id(vrf_id_);
943 24 : info.set_hbf_rintf(hbf_rintf_);
944 24 : info.set_hbf_lintf(hbf_lintf_);
945 24 : }
946 :
947 12 : int VrfKSyncEntry::AddMsg(char *buf, int buf_len) {
948 12 : KSyncVrfInfo info;
949 12 : FillObjectLog(sandesh_op::ADD, info);
950 12 : KSYNC_TRACE(Vrf, GetObject(), info);
951 24 : return Encode(sandesh_op::ADD, 0, buf, buf_len);
952 12 : }
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 12 : int VrfKSyncEntry::DeleteMsg(char *buf, int buf_len) {
963 12 : KSyncVrfInfo info;
964 12 : FillObjectLog(sandesh_op::DEL, info);
965 12 : KSYNC_TRACE(Vrf, GetObject(), info);
966 :
967 24 : return Encode(sandesh_op::DEL, 0, buf, buf_len);
968 12 : }
969 :
970 12 : KSyncEntry *VrfKSyncEntry::UnresolvedReference() {
971 12 : return NULL; // TODO: check this
972 : }
973 :
974 12 : VrfKSyncObject::VrfState::VrfState(Agent *agent) :
975 12 : DBState(), seen_(false),
976 12 : evpn_rt_table_listener_id_(DBTableBase::kInvalidId) {
977 12 : ksync_route_walker_.reset(new KSyncRouteWalker(agent, this));
978 : agent->oper_db()->agent_route_walk_manager()->
979 12 : RegisterWalker(static_cast<AgentRouteWalker *>
980 : (ksync_route_walker_.get()));
981 12 : }
982 :
983 12 : KSyncEntry *VrfKSyncObject::Alloc(const KSyncEntry *entry, uint32_t index) {
984 12 : const VrfKSyncEntry *vrf = static_cast<const VrfKSyncEntry *>(entry);
985 12 : VrfKSyncEntry *ksync = new VrfKSyncEntry(this, vrf, index);
986 12 : return static_cast<KSyncEntry *>(ksync);
987 : }
988 :
989 12 : KSyncEntry *VrfKSyncObject::DBToKSyncEntry(const DBEntry* e) {
990 12 : const VrfEntry *vrf = static_cast<const VrfEntry *>(e);
991 12 : VrfKSyncEntry *key = new VrfKSyncEntry(this, vrf);
992 12 : return static_cast<KSyncEntry *>(key);
993 : }
994 :
995 106 : void VrfKSyncObject::VrfNotify(DBTablePartBase *partition, DBEntryBase *e) {
996 106 : VrfEntry *vrf = static_cast<VrfEntry *>(e);
997 : VrfState *state = static_cast<VrfState *>
998 106 : (vrf->GetState(partition->parent(), vrf_listener_id_));
999 106 : if (vrf->IsDeleted()) {
1000 88 : if (state) {
1001 12 : UnRegisterEvpnRouteTableListener(vrf, state);
1002 12 : vrf->ClearState(partition->parent(), vrf_listener_id_);
1003 12 : (static_cast<KSyncRouteWalker *>(state->ksync_route_walker_.get()))->EnqueueDelete();
1004 :
1005 12 : if (state->ksync_->IsDeleted() == false) {
1006 12 : if (state->ksync_->GetDBEntry() != NULL) {
1007 12 : state->ksync_->SetDBEntry(NULL);
1008 : }
1009 12 : NotifyEvent(state->ksync_, KSyncEntry::DEL_REQ);
1010 : }
1011 :
1012 12 : delete state;
1013 : }
1014 88 : return;
1015 : }
1016 :
1017 18 : if (state == NULL) {
1018 12 : state = new VrfState(ksync_->agent());
1019 12 : state->seen_ = true;
1020 :
1021 : // Create ksync entry for VRF
1022 : KSyncEntry *key;
1023 12 : key = DBToKSyncEntry(vrf);
1024 12 : state->ksync_ = static_cast<VrfKSyncEntry *>(CreateImpl(key));
1025 12 : delete key;
1026 12 : vrf->SetState(partition->parent(), vrf_listener_id_, state);
1027 12 : state->ksync_->SetDBEntry(vrf);
1028 12 : 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 12 : GetInet4UnicastRouteTable());
1033 12 : 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 12 : GetInet6UnicastRouteTable());
1038 12 : 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 12 : GetBridgeRouteTable());
1043 12 : 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 12 : GetInet4MulticastRouteTable());
1051 12 : 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 12 : GetEvpnRouteTable());
1056 12 : KSYNC_TRACE(Trace, state->inet4_uc_route_table_,
1057 : "Subscribing to route table "\
1058 : + vrf->GetName());
1059 12 : if (state->evpn_rt_table_listener_id_ == DBTableBase::kInvalidId) {
1060 12 : state->evpn_rt_table_listener_id_ =
1061 12 : rt_table->Register(boost::bind(&VrfKSyncObject::EvpnRouteTableNotify,
1062 : this, _1, _2));
1063 : }
1064 12 : (static_cast<KSyncRouteWalker *>(state->ksync_route_walker_.get()))->
1065 12 : NotifyRoutes(vrf);
1066 : } else {
1067 6 : VrfKSyncEntry* ksync = state->ksync_;
1068 6 : if (ksync->Sync(vrf) || ksync->IsDeleted()) {
1069 0 : NotifyEvent(ksync, KSyncEntry::ADD_CHANGE_REQ);
1070 : }
1071 : }
1072 : }
1073 :
1074 107 : void VrfKSyncObject::EvpnRouteTableNotify(DBTablePartBase *partition,
1075 : DBEntryBase *e) {
1076 107 : const EvpnRouteEntry *evpn_rt = static_cast<const EvpnRouteEntry *>(e);
1077 :
1078 107 : if (evpn_rt->IsType5())
1079 0 : return;
1080 :
1081 107 : if (evpn_rt->IsDeleted()) {
1082 31 : DelIpMacBinding(evpn_rt->vrf(), evpn_rt->prefix_address(),
1083 : evpn_rt->mac(), evpn_rt->ethernet_tag());
1084 : } else {
1085 76 : AddIpMacBinding(evpn_rt->vrf(), evpn_rt->prefix_address(),
1086 : evpn_rt->mac(),
1087 : evpn_rt->ethernet_tag(),
1088 76 : evpn_rt->GetActivePath()->path_preference().preference(),
1089 76 : evpn_rt->WaitForTraffic());
1090 : }
1091 107 : return;
1092 : }
1093 :
1094 12 : void VrfKSyncObject::UnRegisterEvpnRouteTableListener(const VrfEntry *vrf,
1095 : VrfState *state) {
1096 12 : if (state->evpn_rt_table_listener_id_ == DBTableBase::kInvalidId)
1097 0 : return;
1098 :
1099 : AgentRouteTable *rt_table = static_cast<AgentRouteTable *>(vrf->
1100 12 : GetEvpnRouteTable());
1101 12 : rt_table->Unregister(state->evpn_rt_table_listener_id_);
1102 12 : 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 339 : void vr_route_req::Process(SandeshContext *context) {
1124 339 : AgentSandeshContext *ioc = static_cast<AgentSandeshContext *>(context);
1125 339 : ioc->RouteMsgHandler(this);
1126 339 : }
1127 :
1128 24 : void vr_vrf_req::Process(SandeshContext *context) {
1129 24 : AgentSandeshContext *ioc = static_cast<AgentSandeshContext *>(context);
1130 24 : ioc->VrfMsgHandler(this);
1131 24 : }
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 274 : bool VrfKSyncObject::RouteNeedsMacBinding(const InetUnicastRouteEntry *rt) {
1151 274 : if (rt->prefix_address().is_v4() && rt->prefix_length() != 32)
1152 66 : return false;
1153 :
1154 208 : if (rt->prefix_address().is_v6() && rt->prefix_length() != 128)
1155 9 : return false;
1156 :
1157 199 : VnEntry *vn = NULL;
1158 199 : if (rt->vrf() != ksync_->agent()->fabric_vrf()) {
1159 : //Check if VN is enabled for bridging, if not then skip mac binding.
1160 145 : VnEntry *vn= rt->vrf()->vn();
1161 145 : if (vn == NULL || (vn->bridging() == false))
1162 98 : return false;
1163 : }
1164 :
1165 : // If the route crosses a VN, we want packet to be routed. So, override
1166 101 : const NextHop *nh = rt->GetActiveNextHop();
1167 101 : if (nh == NULL)
1168 0 : return false;
1169 :
1170 124 : if (nh->GetType() != NextHop::INTERFACE &&
1171 45 : nh->GetType() != NextHop::TUNNEL &&
1172 44 : nh->GetType() != NextHop::VLAN &&
1173 146 : nh->GetType() != NextHop::VRF &&
1174 22 : nh->GetType() != NextHop::ARP)
1175 11 : return false;
1176 :
1177 90 : if (IsGatewayOrServiceInterface(nh) == true)
1178 39 : return false;
1179 :
1180 55 : if (nh->GetType() == NextHop::ARP &&
1181 55 : rt->GetActivePath()->gw_ip() == Ip4Address(0)) {
1182 4 : return false;
1183 : }
1184 :
1185 47 : 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 47 : 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 47 : return true;
1206 : }
1207 :
1208 : // Notify change to KSync entry of InetUnicast Route
1209 107 : void VrfKSyncObject::NotifyUcRoute(VrfEntry *vrf, VrfState *state,
1210 : const IpAddress &ip) {
1211 107 : InetUnicastAgentRouteTable *table = NULL;
1212 107 : if (ip.is_v4()) {
1213 107 : table = vrf->GetInet4UnicastRouteTable();
1214 : } else {
1215 0 : table = vrf->GetInet6UnicastRouteTable();
1216 : }
1217 :
1218 107 : InetUnicastRouteEntry *rt = table->FindLPM(ip);
1219 107 : if (rt == NULL || rt->IsDeleted())
1220 63 : return;
1221 :
1222 44 : if (rt->GetTableType() == Agent::INET4_UNICAST) {
1223 44 : 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 76 : 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 76 : (vrf->GetState(vrf->get_table(), vrf_listener_id_));
1236 76 : if (state == NULL)
1237 0 : return;
1238 :
1239 : IpToMacBinding::iterator it =
1240 76 : state->ip_mac_binding_.find(std::make_pair(ip, ethernet_tag));
1241 :
1242 76 : PathPreference path_pref(0, pref, wait_for_traffic, false);
1243 76 : if (it == state->ip_mac_binding_.end()) {
1244 20 : MacBinding mac_binding(mac, path_pref);
1245 20 : state->ip_mac_binding_.insert(std::pair<IpToMacBindingKey, MacBinding>
1246 20 : (std::make_pair(ip, ethernet_tag), mac_binding));
1247 20 : } else {
1248 56 : it->second.set_mac(path_pref, mac);
1249 : }
1250 :
1251 76 : NotifyUcRoute(vrf, state, ip);
1252 76 : }
1253 :
1254 31 : void VrfKSyncObject::DelIpMacBinding(VrfEntry *vrf, const IpAddress &ip,
1255 : const MacAddress &mac,
1256 : uint32_t ethernet_tag) {
1257 : VrfState *state = static_cast<VrfState *>
1258 31 : (vrf->GetState(vrf->get_table(), vrf_listener_id_));
1259 31 : if (state == NULL)
1260 0 : return;
1261 :
1262 : IpToMacBinding::iterator it =
1263 31 : state->ip_mac_binding_.find(std::make_pair(ip, ethernet_tag));
1264 31 : if (it != state->ip_mac_binding_.end()) {
1265 31 : it->second.reset_mac(mac);
1266 31 : if (it->second.can_erase()) {
1267 20 : state->ip_mac_binding_.erase(std::make_pair(ip, ethernet_tag));
1268 : }
1269 : }
1270 31 : NotifyUcRoute(vrf, state, ip);
1271 : }
1272 :
1273 47 : bool VrfKSyncObject::GetIpMacWaitForTraffic(VrfEntry *vrf,
1274 : const IpAddress &ip) const {
1275 : VrfState *state = static_cast<VrfState *>
1276 47 : (vrf->GetState(vrf->get_table(), vrf_listener_id_));
1277 47 : if (state == NULL) {
1278 0 : return false;
1279 : }
1280 :
1281 : IpToMacBinding::const_iterator it =
1282 47 : state->ip_mac_binding_.lower_bound(std::make_pair(ip, 0));
1283 69 : if (it == state->ip_mac_binding_.end() ||
1284 22 : (it->first.first != ip)) {
1285 25 : return false;
1286 : }
1287 :
1288 22 : return it->second.WaitForTraffic();
1289 : }
1290 :
1291 47 : MacAddress VrfKSyncObject::GetIpMacBinding(VrfEntry *vrf,
1292 : const IpAddress &ip,
1293 : const InetUnicastRouteEntry *rt)
1294 : const {
1295 : VrfState *state = static_cast<VrfState *>
1296 47 : (vrf->GetState(vrf->get_table(), vrf_listener_id_));
1297 47 : if (state == NULL)
1298 0 : return MacAddress::ZeroMac();
1299 :
1300 47 : if (vrf->GetName() == ksync_->agent()->fabric_vrf_name()) {
1301 24 : 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 47 : state->ip_mac_binding_.lower_bound(std::make_pair(ip, 0));
1312 69 : if (it == state->ip_mac_binding_.end() ||
1313 22 : (it->first.first != ip)) {
1314 25 : return MacAddress::ZeroMac();
1315 : }
1316 :
1317 22 : return it->second.get_mac();
1318 : }
1319 :
1320 12 : KSyncRouteWalker::KSyncRouteWalker(Agent *agent, VrfKSyncObject::VrfState *state) :
1321 12 : AgentRouteWalker("ksyncroutewalker", agent), state_(state),
1322 12 : marked_for_deletion_(false) {
1323 12 : }
1324 :
1325 24 : KSyncRouteWalker::~KSyncRouteWalker() {
1326 24 : }
1327 :
1328 60 : bool IsStatePresent(AgentRoute *route, DBTableBase::ListenerId id,
1329 : DBTablePartBase *partition) {
1330 60 : DBState *state = route->GetState(partition->parent(), id);
1331 60 : return (state != NULL);
1332 : }
1333 :
1334 12 : void KSyncRouteWalker::EnqueueDelete() {
1335 12 : marked_for_deletion_ = true;
1336 12 : mgr()->ReleaseWalker(static_cast<AgentRouteWalker *>(this));
1337 12 : }
1338 :
1339 66 : bool KSyncRouteWalker::RouteWalkNotify(DBTablePartBase *partition,
1340 : DBEntryBase *e) {
1341 66 : if (marked_for_deletion_)
1342 0 : return true;
1343 :
1344 66 : AgentRoute *route = static_cast<AgentRoute *>(e);
1345 :
1346 66 : 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 36 : case Agent::BRIDGE: {
1369 36 : if (IsStatePresent(route, state_->bridge_route_table_->id(),
1370 36 : partition) == false) {
1371 0 : state_->bridge_route_table_->Notify(partition, route);
1372 : }
1373 36 : break;
1374 : }
1375 6 : default: {
1376 6 : break;
1377 : }
1378 : }
1379 66 : return true;
1380 : }
1381 :
1382 12 : void KSyncRouteWalker::NotifyRoutes(VrfEntry *vrf) {
1383 12 : if (marked_for_deletion_ == false)
1384 12 : StartRouteWalk(vrf);
1385 12 : }
|