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