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