OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
pkt_flow_info.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2024 Juniper Networks, Inc. All rights reserved.
3  * Copyright (c) 2024 Elena Zizganova
4  */
5 
6 
7 #include "base/os.h"
8 #include <arpa/inet.h>
9 #include <netinet/in.h>
10 
11 #include "base/address_util.h"
12 #include "route/route.h"
13 
14 #include "cmn/agent_cmn.h"
15 #include "init/agent_param.h"
16 #include "oper/ecmp.h"
17 #include "oper/interface_common.h"
18 #include "oper/metadata_ip.h"
19 #include "oper/nexthop.h"
20 #include "oper/route_common.h"
21 #include "oper/path_preference.h"
22 #include "oper/vrf.h"
23 #include "oper/sg.h"
24 #include "oper/global_vrouter.h"
25 #include "oper/operdb_init.h"
26 #include "oper/tunnel_nh.h"
27 #include "oper/bgp_as_service.h"
28 #include "oper/health_check.h"
29 
30 #include "filter/packet_header.h"
31 #include "filter/acl.h"
32 
33 #include "pkt/proto.h"
34 #include "pkt/proto_handler.h"
35 #include "pkt/pkt_handler.h"
36 #include "pkt/flow_mgmt.h"
37 #include "pkt/flow_proto.h"
38 #include "pkt/pkt_sandesh_flow.h"
39 #include "cmn/agent_stats.h"
42 
43 #include <services/services_init.h>
45 
48 
49 static void LogError(const PktInfo *pkt, const PktFlowInfo *flow_info,
50  const char *str) {
51  if (pkt->family == Address::INET || pkt->family == Address::INET6) {
52  FLOW_TRACE(DetailErr, pkt->agent_hdr.cmd_param, pkt->agent_hdr.ifindex,
53  pkt->agent_hdr.vrf, pkt->ip_saddr.to_string(),
54  pkt->ip_daddr.to_string(), str, flow_info->l3_flow);
55  } else {
56  assert(0);
57  }
58 }
59 
60 // VRF changed for the packet. Treat it as Layer3 packet from now.
61 // Note:
62 // Features like service chain are supported only for Layer3. Bridge
63 // entries are not leaked into the new VRF and any bridge entry lookup
64 // into new VRF will also Fail. So, even VRouter will treat packets
65 // as L3 after VRF transaltion.
67  const VrfEntry *vrf) {
68  l3_flow = true;
69 }
70 
71 void PktFlowInfo::UpdateRoute(const AgentRoute **rt, const VrfEntry *vrf,
72  const IpAddress &ip, const MacAddress &mac,
73  FlowRouteRefMap &ref_map) {
74  if (*rt != NULL && (*rt)->GetTableType() != Agent::BRIDGE)
75  ref_map[(*rt)->vrf_id()] = RouteToPrefixLen(*rt);
76  if (l3_flow) {
77  *rt = FlowEntry::GetUcRoute(vrf, ip);
78  } else {
79  *rt = FlowEntry::GetL2Route(vrf, mac);
80  if (*rt != NULL) {
81  const BridgeRouteEntry *bridge_rt =
82  dynamic_cast<const BridgeRouteEntry *>(*rt);
83  if (bridge_rt != NULL) {
84  BridgeRouteEntry *temp = const_cast<BridgeRouteEntry*>(bridge_rt);
85  AgentRoute *route = FlowEntry::GetUcRoute(vrf, ip);
86  const InetUnicastRouteEntry *inet_rt =
87  dynamic_cast<const InetUnicastRouteEntry *>(route);
88  if (inet_rt != NULL) {
89  temp->set_prefix_length(inet_rt->prefix_length());
90  } else {
91  temp->set_prefix_length(-1); // -1 = 255 invalid plen for both v4 and v6
92  }
93  }
94  }
95  }
96  if (*rt == NULL)
97  ref_map[vrf->vrf_id()] = 0;
98 }
99 
101  if (route == NULL) {
102  return 0;
103  }
104 
105  const InetUnicastRouteEntry *inet_rt =
106  dynamic_cast<const InetUnicastRouteEntry *>(route);
107  if (inet_rt != NULL) {
108  return inet_rt->prefix_length();
109  }
110 
111  const BridgeRouteEntry *l2_rt =
112  dynamic_cast<const BridgeRouteEntry *>(route);
113  if (l2_rt) {
114  return l2_rt->prefix_address().bit_len();
115  }
116 
117  assert(0);
118  return -1;
119 }
120 
121 // Traffic from IPFabric to VM is treated as EGRESS
122 // Any other traffic is INGRESS
124  bool ret = true;
125  if (intf->type() == Interface::PHYSICAL) {
126  ret = false;
127  }
128  return ret;
129 }
130 
131 
132 // Get VRF corresponding to a NH
133 static uint32_t NhToVrf(const NextHop *nh) {
134  const VrfEntry *vrf = NULL;
135  if (nh == NULL)
137  switch (nh->GetType()) {
138  case NextHop::COMPOSITE: {
139  vrf = (static_cast<const CompositeNH *>(nh))->vrf();
140  break;
141  }
142  case NextHop::NextHop::INTERFACE: {
143  const Interface *intf =
144  (static_cast<const InterfaceNH *>(nh))->GetInterface();
145  if (intf)
146  vrf = intf->vrf();
147  break;
148  }
149  default:
150  break;
151  }
152 
153  if (vrf == NULL)
155 
156  if (!vrf->IsActive())
158 
159  return vrf->vrf_id();
160 }
161 
162 static bool IsVgwOrVmInterface(const Interface *intf) {
163  if (intf->type() == Interface::VM_INTERFACE)
164  return true;
165 
166  if (intf->type() == Interface::INET) {
167  const InetInterface *inet = static_cast<const InetInterface *>(intf);
169  return true;
170  }
171  return false;
172 }
173 
174 static bool PickEcmpMember(const Agent *agent, const NextHop **nh,
175  const PktInfo *pkt, PktFlowInfo *info,
176  const EcmpLoadBalance &ecmp_load_balance) {
177  const CompositeNH *comp_nh = dynamic_cast<const CompositeNH *>(*nh);
178  // ECMP supported only if composite-type is ECMP or LOCAL_ECMP or LU_ECMP
179  if (comp_nh == NULL ||
180  (comp_nh->composite_nh_type() != Composite::ECMP &&
182  comp_nh->composite_nh_type() != Composite::LU_ECMP)) {
184  return true;
185  }
186  info->ecmp = true;
187  // If this is flow revluation,
188  // 1. If flow transitions from non-ECMP to ECMP, the old-nh will be first
189  // member in the composite-nh. So set affinity-nh index to 0
190  // 2. If flow is already ECMP, the out-component-nh-idx is retained as
191  // affinity
192  if (pkt->type == PktType::MESSAGE &&
194  info->out_component_nh_idx = 0;
195  }
196 
197  // Compute out_component_nh_idx,
198  // 1. In case of non-ECMP to ECMP transition, component-nh-index and
199  // in-turn affinity-nh is set to 0
200  // 2. In case of MESSAGE, the old component-nh-index is used as affinity-nh
201  // 3. In case of new flows, new index is allocated
202  //
203  // If affinity-nh is set but points to deleted NH, then affinity is ignored
204  // and new index is allocated
205  info->out_component_nh_idx =
206  comp_nh->PickMember(pkt->hash(agent, ecmp_load_balance),
207  info->out_component_nh_idx,
208  info->ingress);
209  *nh = comp_nh->GetNH(info->out_component_nh_idx);
210  // nh can be NULL if out_component_nh_index is invalid
211  // this index is returned as invalid from the above function
212  // when composite nexthop is having inactive/NULL
213  // component nexthops or no local nexthops if traffic
214  // is coming from fabric
215  if ((*nh) && ((*nh)->GetType() == NextHop::COMPOSITE)) {
216  // this is suboptimal solution to pick component NH in
217  // 2 level ecmp. ideally hashing should be independent for
218  // VPN level ecmp and label inet ecmp. label inet ecmp relies on
219  // underlay node information which is not available in packet
220  // if pkt originates from local VM, so using same ecmp index
221  // to get component nh for both vpn and label inet ecmp
222  // this results in either (0,0) or (1,1)
223  // TODO:find optimum solution to address this
224  const CompositeNH *comp_composite_nh =
225  static_cast<const CompositeNH *>(*nh);
226  if (comp_composite_nh->composite_nh_type() == Composite::LU_ECMP) {
227  *nh = comp_composite_nh->GetNH(info->out_component_nh_idx);
228  }
229  }
230 
231  // TODO: Should we re-hash here?
232  if (!(*nh) || (*nh)->IsActive() == false) {
233  return false;
234  }
235  return true;
236 }
237 
238 // Get interface from a NH. Also, decode ECMP information from NH
239 // Responsible to set following fields,
240 // out->nh_ : outgoing Nexthop Index. Will also be used to set reverse flow-key
241 // out->vrf_ : VRF to be used after flow processing. Value set here can
242 // potentially get overridden later
243 // TODO: Revisit the use of vrf_, dest_vrf and nat_vrf
244 // force_vmport means, we want destination to be VM_INTERFACE only
245 // This is to avoid routing across fabric interface itself
246 static bool NhDecode(const Agent *agent, const NextHop *nh, const PktInfo *pkt,
247  PktFlowInfo *info, PktControlInfo *in,
248  PktControlInfo *out, bool force_vmport,
249  const EcmpLoadBalance &ecmp_load_balance) {
250  bool ret = true;
251 
252  if (!nh->IsActive())
253  return false;
254 
255  // If nh is Composite, pick the ECMP first. The nh index and vrf used
256  // in reverse flow will depend on the ECMP member picked
257  if (PickEcmpMember(agent, &nh, pkt, info, ecmp_load_balance) == false) {
258  return false;
259  }
260 
261  // Pick out going attributes based on the NH selected above
262  switch (nh->GetType()) {
263  case NextHop::INTERFACE:
264  out->intf_ = static_cast<const InterfaceNH*>(nh)->GetInterface();
265  if (out->intf_->type() == Interface::VM_INTERFACE) {
266  //Local flow, pick destination interface
267  //nexthop as reverse flow key
268  if (out->intf_->flow_key_nh() == NULL)
269  return false;
270  out->nh_ = out->intf_->flow_key_nh()->id();
271  out->vrf_ = static_cast<const InterfaceNH*>(nh)->GetVrf();
272  const VmInterface *vm_port =
273  dynamic_cast<const VmInterface *>(out->intf_);
274  if (vm_port != NULL) {
275  VrfEntry *alias_vrf = vm_port->GetAliasIpVrf(pkt->ip_daddr);
276  if (alias_vrf != NULL) {
277  out->vrf_ = alias_vrf;
278  // translate to alias ip vrf for destination, unless
279  // overriden by translation due to NAT or ACL
280  info->dest_vrf = alias_vrf->vrf_id();
281  info->alias_ip_flow = true;
282  }
283  }
284  } else if (out->intf_->type() == Interface::PACKET) {
285  //Packet destined to pkt interface, packet originating
286  //from pkt0 interface will use destination interface as key
287  out->nh_ = in->nh_;
288  } else {
289  // Most likely a GATEWAY interface.
290  // Remote flow, use source interface as nexthop key
291  out->nh_ = nh->id();
292  out->vrf_ = static_cast<const InterfaceNH*>(nh)->GetVrf();
293  }
294  break;
295 
296  case NextHop::RECEIVE:
297  assert(info->l3_flow == true);
298  out->intf_ = static_cast<const ReceiveNH *>(nh)->GetInterface();
299  out->vrf_ = out->intf_->vrf();
300  if (out->intf_->vrf()->forwarding_vrf()) {
301  out->vrf_ = out->intf_->vrf()->forwarding_vrf();
302  }
303  out->nh_ = out->intf_->flow_key_nh()->id();
304  break;
305 
306  case NextHop::VLAN: {
307  assert(info->l3_flow == true);
308  const VlanNH *vlan_nh = static_cast<const VlanNH*>(nh);
309  out->intf_ = vlan_nh->GetInterface();
310  out->vlan_nh_ = true;
311  out->vlan_tag_ = vlan_nh->GetVlanTag();
312  out->vrf_ = vlan_nh->GetVrf();
313  out->nh_ = nh->id();
314  break;
315  }
316 
317  // Destination present on remote-compute node. The reverse traffic will
318  // have MPLS label. The MPLS label can point to
319  // 1. In case of non-ECMP, label will points to local interface
320  // 2. In case of ECMP, label will point to ECMP of local-composite members
321  // Setup the NH for reverse flow appropriately
322  case NextHop::TUNNEL: {
323  // out->intf_ is invalid for packets going out on tunnel. Reset it.
324  out->intf_ = NULL;
325 
326  // Packet going out on tunnel. Assume NH in reverse flow is same as
327  // that of forward flow. It can be over-written down if route for
328  // source-ip is ECMP
329  if (info->port_allocated == false) {
330  out->nh_ = in->nh_;
331  }
332 
333  // The NH in reverse flow can change only if ECMP-NH is used. There is
334  // no ECMP for layer2 flows
335  if (info->l3_flow == false) {
336  break;
337  }
338 
339  // If source-ip is in ECMP, reverse flow would use ECMP-NH as key
340  const InetUnicastRouteEntry *rt =
341  dynamic_cast<const InetUnicastRouteEntry *>(in->rt_);
342  if (rt == NULL) {
343  break;
344  }
345 
346  // Get only local-NH from route
347  const NextHop *local_nh = EcmpData::GetLocalNextHop(rt);
348  if (local_nh && local_nh->IsActive() == false) {
349  LogError(pkt, info, "Invalid or Inactive local nexthop ");
350  info->short_flow = true;
352  break;
353  }
354 
355  // Change NH in reverse flow if route points to composite-NH
356  const CompositeNH *comp_nh = dynamic_cast<const CompositeNH *>
357  (local_nh);
358  if (comp_nh != NULL) {
359  out->nh_ = comp_nh->id();
360  }
361  break;
362  }
363 
364  // COMPOSITE is valid only for multicast traffic. We simply forward
365  // multicast traffic and its mostly unidirectional. nh_ used in reverse
366  // flow woule not matter really
367  case NextHop::COMPOSITE: {
368  out->nh_ = nh->id();
369  out->intf_ = NULL;
370  break;
371  }
372 
373  // VRF Nexthop means traffic came as tunnelled packet and interface is
374  // gateway kind of interface. It also means ARP is not yet resolved for the
375  // dest-ip (otherwise we should have it ARP-NH). Let out->nh_ to be same as
376  // in->nh_. It will be modified later when ARP is resolved
377  case NextHop::VRF: {
378  const VrfNH *vrf_nh = static_cast<const VrfNH *>(nh);
379  out->vrf_ = vrf_nh->GetVrf();
380  break;
381  }
382 
383  // ARP Nexthop means outgoing interface is gateway kind of interface with
384  // ARP already resolved
385  case NextHop::ARP: {
386  assert(info->l3_flow == true);
387  const ArpNH *arp_nh = static_cast<const ArpNH *>(nh);
388  if (in->intf_->type() == Interface::VM_INTERFACE) {
389  const VmInterface *vm_intf =
390  static_cast<const VmInterface *>(in->intf_);
391  if (vm_intf->vmi_type() == VmInterface::VHOST) {
392  out->nh_ = in->intf_->flow_key_nh()->id();
393  out->intf_ = in->intf_;
394  } else if (vm_intf->device_type() == VmInterface::LOCAL_DEVICE) {
395  out->nh_ = arp_nh->id();
396  out->intf_ = arp_nh->GetInterface();
397  }
398  } else {
399  out->intf_ = arp_nh->GetInterface();
400  }
401  out->vrf_ = arp_nh->GetVrf();
402  break;
403  }
404 
405  // RESOLVE Nexthop means traffic came from gateway interface and destined
406  // to another gateway interface
407  case NextHop::RESOLVE: {
408  assert(info->l3_flow == true);
409  const ResolveNH *rsl_nh = static_cast<const ResolveNH *>(nh);
410  out->nh_ = rsl_nh->get_interface()->flow_key_nh()->id();
411  out->intf_ = rsl_nh->get_interface();
412  break;
413  }
414 
415  default:
416  out->intf_ = NULL;
417  break;
418  }
419 
420  if (out->intf_) {
421  if (!out->intf_->IsActive()) {
422  out->intf_ = NULL;
423  ret = false;
424  } else if (force_vmport && IsVgwOrVmInterface(out->intf_) == false) {
425  out->intf_ = NULL;
426  out->vrf_ = NULL;
427  ret = true;
428  }
429  }
430 
431  if (out->vrf_ && (out->vrf_->IsActive() == false)) {
432  out->vrf_ = NULL;
433  ret = false;
434  }
435 
436  return ret;
437 }
438 
439 // Decode route and get Interface / ECMP information
440 static bool RouteToOutInfo(const Agent *agent, const AgentRoute *rt,
441  const PktInfo *pkt, PktFlowInfo *info,
442  PktControlInfo *in, PktControlInfo *out) {
443  const AgentPath *path = rt->GetActivePath();
444  if (path == NULL)
445  return false;
446 
447  const NextHop *nh = static_cast<const NextHop *>
448  (path->ComputeNextHop(info->agent));
449  if (nh == NULL)
450  return false;
451 
452  if (nh->IsActive() == false) {
453  return false;
454  }
455 
456  return NhDecode(agent, nh, pkt, info, in, out, false,
457  path->ecmp_load_balance());
458 }
459 
460 static const VnEntry *InterfaceToVn(const Interface *intf) {
461  if (intf->type() != Interface::VM_INTERFACE)
462  return NULL;
463 
464  const VmInterface *vm_port = static_cast<const VmInterface *>(intf);
465  return vm_port->vn();
466 }
467 
468 static bool IntfHasFloatingIp(PktFlowInfo *pkt_info, const Interface *intf,
469  Address::Family family) {
470  if (!intf || intf->type() != Interface::VM_INTERFACE)
471  return false;
472 
473  return static_cast<const VmInterface *>(intf)->HasFloatingIp(family);
474 }
475 
476 static bool IsLinkLocalRoute(Agent *agent, const AgentRoute *rt,
477  uint32_t sport, uint32_t dport) {
478  //Local CN and BGP has been allowed for testing purpose.
479  if ((sport == BgpAsAService::DefaultBgpPort) ||
481  return false;
482 
483  const AgentPath *path = rt->GetActivePath();
484  if (path && path->peer() == agent->link_local_peer())
485  return true;
486 
487  return false;
488 }
489 
491  const AgentRoute *out_rt,
492  const Interface *intf,
493  uint32_t sport,
494  uint32_t dport) {
496  return true;
497 
498  if (intf == NULL || in_rt == NULL || out_rt == NULL)
499  return false;
500 
501  if ((sport != BgpAsAService::DefaultBgpPort) &&
503  return false;
504 
505  if (intf->type() == Interface::VM_INTERFACE) {
506  const VmInterface *vm_intf =
507  dynamic_cast<const VmInterface *>(intf);
508  const InetUnicastRouteEntry *in_inet_rt =
509  dynamic_cast<const InetUnicastRouteEntry *>(in_rt);
510  const InetUnicastRouteEntry *out_inet_rt =
511  dynamic_cast<const InetUnicastRouteEntry *>(out_rt);
512  if (in_inet_rt == NULL || out_inet_rt == NULL)
513  return false;
514  if (agent->oper_db()->bgp_as_a_service()->
515  IsBgpService(vm_intf, in_inet_rt->prefix_address(), out_inet_rt->prefix_address())) {
517  return true;
518  }
519  }
520 
521  return false;
522 }
523 
524 static const VnListType *RouteToVn(const AgentRoute *rt) {
525  const AgentPath *path = NULL;
526  if (rt) {
527  path = rt->GetActivePath();
528  }
529  if (path == NULL) {
530  return &(Agent::NullStringList());
531  }
532 
533  return &path->dest_vn_list();
534 }
535 
537  uint32_t sport,
538  uint32_t dport,
539  const Interface *intf) {
540  // No NAT for bridge routes
541  if (dynamic_cast<const BridgeRouteEntry *>(rt) != NULL)
542  return false;
543 
544  if (rt != NULL && IsLinkLocalRoute(agent, rt, sport, dport)) {
545  // skip NAT lookup if found route has link local peer.
546  return false;
547  }
548 
549  return true;
550 }
551 
553  const AgentRoute *out_rt,
554  uint32_t sport,
555  uint32_t dport,
556  const Interface *intf) {
557  if (RouteAllowNatLookupCommon(out_rt, sport, dport, intf) == false) {
558  return false;
559  }
560 
561  if (IsBgpRouterServiceRoute(in_rt, out_rt, intf, sport, dport)) {
562  // skip NAT lookup if found route has link local peer.
563  return false;
564  }
565 
566  return true;
567 }
568 
570  const AgentRoute *out_rt,
571  uint32_t sport,
572  uint32_t dport,
573  const Interface *intf) {
574  if (RouteAllowNatLookupCommon(out_rt, sport, dport, intf) == false) {
575  return false;
576  }
577 
578  return true;
579 }
580 
582  if (!l3_flow && pkt->ip_daddr.is_v4()) {
583  uint16_t nat_port;
584  Ip4Address nat_server;
585  std::string service_name;
586  GlobalVrouter *global_vrouter = agent->oper_db()->global_vrouter();
587  if (global_vrouter->FindLinkLocalService(pkt->ip_daddr,
588  pkt->dport, &service_name,
589  &nat_server, &nat_port)) {
590  // it is link local service request, treat it as l3
591  l3_flow = true;
592  }
593  }
594 }
595 
597  PktControlInfo *out) {
598 
599  const VmInterface *vm_port =
600  static_cast<const VmInterface *>(in->intf_);
601 
602  uint16_t nat_port;
603  Ip4Address nat_server4;
604  IpAddress nat_server;
605  std::string service_name;
607  (pkt->ip_daddr, pkt->dport, &service_name, &nat_server4,
608  &nat_port)) {
609  // link local service not configured, drop the request
610  in->rt_ = NULL;
611  out->rt_ = NULL;
612  return;
613  }
614 
616  dest_vrf = out->vrf_->vrf_id();
617 
618  MetadataProxy *metadata_proxy = NULL;
619  metadata_proxy = agent ?
620  (agent->services() ? agent->services()->metadataproxy() : NULL) : NULL;
621  if (metadata_proxy && pkt &&
622  pkt->ip_saddr.is_v6() &&
623  pkt->ip_daddr.is_v6()) {
624  Ip6Address ll_ip = pkt->ip_saddr.to_v6();
625  // Announce the route to the interface LL address
626  metadata_proxy->AdvertiseMetaDataLinkLocalRoutes(vm_port,
627  ll_ip, in->vrf_);
628  }
629 
630  // Set NAT flow fields
631  if (pkt->ip_daddr.is_v4()) {
632  linklocal_flow = true;
633  nat_done = true;
634  underlay_flow = false;
635  if (nat_server4 == agent->router_id()) {
636  // In case of metadata or when link local destination is local host,
637  // set VM's metadata address as NAT source address. This is required
638  // to avoid response from the linklocal service being looped back and
639  // the packet not coming to vrouter for reverse NAT.
640  // Destination would be local host (FindLinkLocalService returns this)
641  nat_ip_saddr = vm_port->mdata_ip_addr();
642  // Services such as metadata will run on compute_node_ip. Set nat
643  // address to compute_node_ip
644  nat_server4 = agent->compute_node_ip();
645  nat_sport = pkt->sport;
646  } else {
648  // we bind to a local port & use it as NAT source port (cannot use
649  // incoming src port); init here and bind in Add;
650  nat_sport = 0;
652  }
653  nat_server = nat_server4;
654  } else {
655  if (nat_server4 == agent->router_id()) {
656  linklocal_flow = true;
657  nat_done = true;
658  underlay_flow = false;
659  nat_server = metadata_proxy ?
660  metadata_proxy->Ipv6ServiceAddress() :
661  Ip6Address::from_string("::");
662  nat_ip_saddr = vm_port->mdata_ip6_addr();
663  nat_sport = pkt->sport;
664  }
665  }
666 
667  nat_ip_daddr = nat_server;
668  nat_dport = nat_port;
669 
670  nat_vrf = dest_vrf;
671  nat_dest_vrf = vm_port->vrf_id();
672 
673  out->rt_ = FlowEntry::GetUcRoute(out->vrf_, nat_server);
674  return;
675 }
676 
678  PktControlInfo *out) {
679  if (RouteToOutInfo(agent, out->rt_, pkt, this, in, out) == false) {
680  return;
681  }
682 
683  // Link local services supported only for IPv4 for now
684  if (pkt->family != Address::INET) {
685  in->rt_ = NULL;
686  out->rt_ = NULL;
687  return;
688  }
689 
690  const VmInterface *vm_port =
691  static_cast<const VmInterface *>(out->intf_);
692  if (vm_port == NULL) {
693  // Force implicit deny
694  in->rt_ = NULL;
695  out->rt_ = NULL;
696  return;
697  }
698 
699  // Check if packet is destined to metadata of interface
700  MetaDataIp *mip = vm_port->GetMetaDataIp(pkt->ip_daddr.to_v4());
701  if (mip == NULL) {
702  // Force implicit deny
703  in->rt_ = NULL;
704  out->rt_ = NULL;
705  return;
706  }
707 
708  dest_vrf = vm_port->vrf_id();
709  out->vrf_ = vm_port->vrf();
710 
711  //If the destination route is ECMP set component index
712  //This component index would be used only for forwarding
713  //the first packet in flow (HOLD flow flushing)
714  InetUnicastRouteEntry *out_rt = NULL;
715  if (out->vrf_) {
716  out_rt = static_cast<InetUnicastRouteEntry *>(
718  if (out_rt) {
719  const NextHop *anh = out_rt->GetActiveNextHop();
720  if (anh && anh->GetType() == NextHop::COMPOSITE) {
721  const CompositeNH *comp_nh =
722  static_cast<const CompositeNH *>(anh);
723  ComponentNH component_nh(vm_port->label(), vm_port->flow_key_nh());
724  comp_nh->GetIndex(component_nh, out_component_nh_idx);
725  }
726  }
727  }
728 
729  linklocal_flow = true;
730  nat_done = true;
731  underlay_flow = false;
732  // Get NAT source/destination IP from MetadataIP retrieved from interface
733  nat_ip_saddr = mip->service_ip();
734  nat_ip_daddr = mip->destination_ip();
739  // Failed to find associated source or destination address
740  // Force implicit deny
741  in->rt_ = NULL;
742  out->rt_ = NULL;
743  return;
744  }
745 
746  nat_dport = pkt->dport;
747  if (pkt->sport == agent->metadata_server_port()) {
749  } else {
750  nat_sport = pkt->sport;
751  }
752  nat_vrf = dest_vrf;
753  nat_dest_vrf = pkt->vrf;
754  return;
755 }
756 
758  PktControlInfo *out) {
759  const VmInterface *vm_intf = dynamic_cast<const VmInterface *>(in->intf_);
760  if (vm_intf->vmi_type() != VmInterface::VHOST) {
761  LinkLocalServiceFromVm(pkt, in, out);
762  } else {
763  LinkLocalServiceFromHost(pkt, in, out);
764  }
765 }
766 
768  PktControlInfo *out) {
769 
770  // Link local services supported only for IPv4 for now
771  if (pkt->family != Address::INET) {
772  in->rt_ = NULL;
773  out->rt_ = NULL;
774  return;
775  }
776 
777  const VmInterface *vm_port =
778  static_cast<const VmInterface *>(in->intf_);
779 
780  const VnEntry *vn = static_cast<const VnEntry *>(vm_port->vn());
781  uint32_t sport = 0;
782  uint32_t dport = 0;
783  IpAddress nat_server = IpAddress();
784 
785  if (vn == NULL) {
786  in->rt_ = NULL;
787  out->rt_ = NULL;
788  return;
789  }
790 
791  if (agent->oper_db()->bgp_as_a_service()->
792  GetBgpRouterServiceDestination(vm_port,
793  pkt->ip_saddr.to_v4(),
794  pkt->ip_daddr.to_v4(),
795  &nat_server,
796  &sport, &dport) == false) {
797  return;
798  }
799 
801  dest_vrf = out->vrf_->vrf_id();
802 
803  nat_done = true;
804  //Populate NAT
806  nat_ip_daddr = nat_server;
807  nat_sport = sport;
808  nat_dport = dport;
809  if ((nat_ip_daddr == agent->router_id()) &&
810  (nat_ip_daddr == nat_ip_saddr)) {
811  boost::system::error_code ec;
812  //TODO may be use MDATA well known address.
813  nat_ip_saddr = vm_port->mdata_ip_addr();
814  }
815 
816  nat_vrf = dest_vrf;
817  nat_dest_vrf = vm_port->vrf_id();
818 
819 
820  out->rt_ = FlowEntry::GetUcRoute(out->vrf_, nat_server);
821  out->intf_ = agent->vhost_interface();
822  out->nh_ = out->intf_->flow_key_nh()->id();
823  ttl = pkt->ttl;
824  return;
825 }
826 
828  PktControlInfo *in,
829  PktControlInfo *out) {
830  if (in->intf_->type() == Interface::VM_INTERFACE) {
831  BgpRouterServiceFromVm(pkt, in, out);
832  }
833 }
834 
835 // DestNAT for packets entering into a VM with floating-ip.
836 // Can come here in two paths,
837 // - Packet originated on local vm.
838 // - Packet originated from remote vm
840  PktControlInfo *out) {
841  const VmInterface *vm_port =
842  static_cast<const VmInterface *>(out->intf_);
843  const VmInterface::FloatingIpSet &fip_list =
844  vm_port->floating_ip_list().list_;
845 
846  // We must NAT if the IP-DA is not same as Primary-IP on interface
847  if (pkt->ip_daddr.is_v4()) {
848  if (pkt->ip_daddr.to_v4() == vm_port->primary_ip_addr()) {
849  return;
850  }
851  }
852  if (pkt->ip_daddr.is_v6()) {
853  if (pkt->ip_daddr.to_v6() == vm_port->primary_ip6_addr()) {
854  return;
855  }
856  }
857 
858  // Look for matching floating-ip
859  VmInterface::FloatingIpSet::const_iterator it = fip_list.begin();
860  for ( ; it != fip_list.end(); ++it) {
861 
862  if (it->vrf_.get() == NULL) {
863  continue;
864  }
865 
866  if (pkt->ip_daddr != it->floating_ip_) {
867  continue;
868  }
869 
870  // Check if floating-ip direction matches
871  if (it->AllowDNat() == false) {
872  continue;
873  }
874 
875  break;
876  }
877 
878  if (it == fip_list.end()) {
879  // No matching floating ip for destination-ip
880  return;
881  }
882  in->vn_ = NULL;
883  if (nat_done == false) {
884  // lookup for source route in FIP VRF for egress flows only
885  // because for source route VRF is always present for ingress flows
886  // so there is no need to update source route with route lookup
887  // in FIP's VRF
888  if(!ingress) {
889  UpdateRoute(&in->rt_, it->vrf_.get(), pkt->ip_saddr, pkt->smac,
891  }
892  nat_dest_vrf = it->vrf_.get()->vrf_id();
893  }
894  UpdateRoute(&out->rt_, it->vrf_.get(), pkt->ip_daddr, pkt->dmac,
896  out->vn_ = it->vn_.get();
897  VrfEntry *alias_vrf = vm_port->GetAliasIpVrf(it->GetFixedIp(vm_port));
898  if (alias_vrf == NULL) {
899  dest_vrf = out->intf_->vrf()->vrf_id();
900  } else {
901  dest_vrf = alias_vrf->vrf_id();
902  }
903 
904  underlay_flow = false;
905  if (VrfTranslate(pkt, in, out, pkt->ip_saddr, true) == false) {
906  return;
907  }
908 
909  if (underlay_flow) {
910  if (pkt->ip_daddr.is_v6()) {
911  return;
912  }
913  if (it->vrf_->forwarding_vrf()) {
914  //Pick the underlay ip-fabric VRF for forwarding
915  nat_dest_vrf = it->vrf_->forwarding_vrf()->vrf_id();
916  }
917  if (out->intf_->vrf()->forwarding_vrf()) {
918  dest_vrf = out->intf_->vrf()->forwarding_vrf()->vrf_id();
919  }
920  }
921 
922  // Force packet to be treated as L3-flow in such case
923  // Flow is already marked as l3-flow by the time we are here. But, there is
924  // an exception in case of DNat.
925  // - In normal cases, packet hits bridge entry with receive-nh
926  // - If native-vrf and floating-ip vrf are same, the bridge entry points
927  // to interface-nh instead of receive nh.
928  l3_flow = true;
929  // Translate the Dest-IP
930  if (nat_done == false)
931  nat_ip_saddr = pkt->ip_saddr;
932  nat_ip_daddr = it->fixed_ip_;
933  if (it->port_map_enabled()) {
934  int32_t map_port = it->GetDstPortMap(pkt->ip_proto, pkt->dport);
935  if (map_port < 0) {
936  short_flow = true;
938  } else {
939  nat_dport = map_port;
940  }
941  } else {
942  nat_dport = pkt->dport;
943  }
944  nat_sport = pkt->sport;
945  nat_vrf = dest_vrf;
946  nat_done = true;
947 
948  if (in->rt_) {
949  flow_source_vrf = static_cast<const AgentRoute *>(in->rt_)->vrf_id();
950  } else {
952  }
953  flow_dest_vrf = it->vrf_.get()->vrf_id();
954 
955  // Update fields required for floating-IP stats accounting
956  fip_dnat = true;
957 
958  return;
959 }
960 
962  PktControlInfo *out) {
963  const VmInterface *intf =
964  static_cast<const VmInterface *>(in->intf_);
965  const VmInterface::FloatingIpSet &fip_list = intf->floating_ip_list().list_;
966  VmInterface::FloatingIpSet::const_iterator it = fip_list.begin();
967  VmInterface::FloatingIpSet::const_iterator fip_it = fip_list.end();
968  const AgentRoute *rt = out->rt_;
969  uint8_t rt_plen = 0;
970  if (rt) {
971  rt_plen = RouteToPrefixLen(rt);
972  }
973  bool change = false;
974  // Find Floating-IP matching destination-ip
975  for ( ; it != fip_list.end(); ++it) {
976  if (it->vrf_.get() == NULL) {
977  continue;
978  }
979 
980  if (it->fixed_ip_ != IpAddress() && (pkt->ip_saddr != it->fixed_ip_)) {
981  continue;
982  }
983 
984  // Check if floating-ip direction matches
985  if (it->AllowSNat() == false) {
986  continue;
987  }
988 
989  const AgentRoute *rt_match = FlowEntry::GetUcRoute(it->vrf_.get(),
990  pkt->ip_daddr);
991  if (rt_match == NULL) {
992  flow_dest_plen_map[it->vrf_.get()->vrf_id()] = 0;
993  continue;
994  }
995  // found the route match
996  // prefer the route with longest prefix match
997  // if prefix length is same prefer route from rt(original out->rt_)
998  // if routes are from fip of difference VRF, prefer the one with lower name.
999  // if both the selected and current FIP is from same vrf prefer the one with lower ip addr.
1000  uint8_t rt_match_plen = RouteToPrefixLen(rt_match);
1001  if (rt != NULL && rt_plen >= rt_match_plen) {
1002  flow_dest_plen_map[rt_match->vrf_id()] = rt_match_plen;
1003  continue;
1004  }
1005  uint8_t out_rt_plen = RouteToPrefixLen(out->rt_);
1006  if (out->rt_ == NULL || rt_match_plen > out_rt_plen) {
1007  change = true;
1008  } else if (rt_match_plen == out_rt_plen) {
1009  if (it->port_nat()) {
1010  change = false;
1011  } else if (fip_it == fip_list.end()) {
1012  change = true;
1013  } else if (rt_match->vrf()->GetName() < out->rt_->vrf()->GetName()) {
1014  change = true;
1015  } else if (rt_match->vrf()->GetName() == out->rt_->vrf()->GetName() &&
1016  it->floating_ip_ < fip_it->floating_ip_) {
1017  change = true;
1018  }
1019  }
1020 
1021  if (change) {
1022  if (out->rt_ != NULL) {
1023  flow_dest_plen_map[out->rt_->vrf_id()] = out_rt_plen;
1024  }
1025  out->rt_ = rt_match;
1026  fip_it = it;
1027  change = false;
1028  } else {
1029  flow_dest_plen_map[rt_match->vrf_id()] = rt_match_plen;
1030  }
1031  }
1032 
1033  if (out->rt_ == rt) {
1034  // No change in route, no floating-ip found
1035  return;
1036  }
1037 
1038  //Populate in->vn, used for VRF translate ACL lookup
1039  in->vn_ = fip_it->vn_.get();
1040 
1041  // Floating-ip found. We will change src-ip to floating-ip. Recompute route
1042  // for new source-ip. All policy decisions will be based on this new route
1043  UpdateRoute(&in->rt_, fip_it->vrf_.get(), fip_it->floating_ip_, pkt->smac,
1045  if (in->rt_ == NULL) {
1046  return;
1047  }
1048 
1049  underlay_flow = false;
1050  if (VrfTranslate(pkt, in, out, fip_it->floating_ip_, true) == false) {
1051  return;
1052  }
1053  if (out->rt_ == NULL || in->rt_ == NULL) {
1054  //If After VRF translation, ingress route or
1055  //egress route is NULL, mark the flow as short flow
1056  return;
1057  }
1058 
1059  // Compute out-intf and ECMP info from out-route
1060  if (RouteToOutInfo(agent, out->rt_, pkt, this, in, out) == false) {
1061  return;
1062  }
1063 
1064  dest_vrf = out->rt_->vrf_id();
1065  // Setup reverse flow to translate sip.
1066  nat_done = true;
1067  nat_ip_saddr = fip_it->floating_ip_;
1068  nat_ip_daddr = pkt->ip_daddr;
1069  if (fip_it->port_map_enabled()) {
1070  int32_t map_port = fip_it->GetSrcPortMap(pkt->ip_proto, pkt->sport);
1071  if (map_port < 0) {
1072  short_flow = true;
1074  } else {
1075  nat_sport = map_port;
1076  }
1077  } else if (fip_it->port_nat()) {
1078  FlowKey key(in->nh_, pkt->ip_saddr, pkt->ip_daddr, pkt->ip_proto,
1079  pkt->sport, pkt->dport);
1080  if (fip_it->floating_ip_ == pkt->ip_daddr) {
1081  nat_sport = pkt->sport;
1082  nat_ip_saddr = intf->mdata_ip_addr();
1083  } else {
1084  nat_sport =
1086  if (nat_sport == 0) {
1087  short_flow = true;
1089  nat_done = false;
1090  out->nh_ = in->nh_;
1091  return;
1092  } else {
1093  port_allocated = true;
1094  }
1095  }
1096  out->nh_ = agent->vhost_interface()->flow_key_nh()->id();
1097  } else {
1098  nat_sport = pkt->sport;
1099  }
1100  nat_dport = pkt->dport;
1101 
1102  // Compute VRF for reverse flow
1103  if (out->intf_) {
1104  // Egress-vm present on same compute node, take VRF from vm-port
1105  nat_vrf = out->vrf_->vrf_id();
1106  out->vn_ = InterfaceToVn(out->intf_);
1107  } else {
1108  // Egress-vm is remote. Find VRF from the NH for source-ip
1109  nat_vrf = NhToVrf(in->rt_->GetActiveNextHop());
1110  }
1111 
1112  // Dest VRF for reverse flow is In-Port VRF
1113  nat_dest_vrf = in->vrf_->vrf_id();
1114 
1115  flow_source_vrf = pkt->vrf;
1116  if (out->rt_) {
1118  } else {
1120  }
1121  // Update fields required for floating-IP stats accounting
1123  fip_snat = true;
1124  return;
1125 }
1126 
1127 //Check if both source and destination route support Native Encap
1128 //if yes use underlay forwarding (no change)
1129 //Else Do a VRF translate to interface VRF
1131  const PktInfo *pkt,
1132  PktControlInfo *in,
1133  PktControlInfo *out) {
1134 
1135  if (l3_flow == false) {
1136  return;
1137  }
1138 
1139  bool can_be_underlay_flow = false;
1140  if (intf->vrf() && intf->vrf()->forwarding_vrf() &&
1141  intf->vrf()->forwarding_vrf() != intf->vrf()) {
1142  can_be_underlay_flow = true;
1143  }
1144 
1145  //Route needs to be check because out interface might
1146  //not be populated, if destination uses native forwarding
1147  //then also we need to do vrf translate
1148  if (out->rt_) {
1149  const InterfaceNH *intf_nh =
1150  dynamic_cast<const InterfaceNH *>(out->rt_->GetActiveNextHop());
1151  if (intf_nh) {
1152  const Interface *out_itf = intf_nh->GetInterface();
1153  if (out_itf->vrf() && out_itf->vrf()->forwarding_vrf() &&
1154  out_itf->vrf()->forwarding_vrf() != out_itf->vrf()) {
1155  can_be_underlay_flow = true;
1156  }
1157  }
1158  }
1159 
1160  if (can_be_underlay_flow == false) {
1161  return;
1162  }
1163 
1164  const AgentRoute *src_rt = FlowEntry::GetUcRoute(intf->vrf(),
1165  pkt->ip_saddr);
1166  const AgentRoute *dst_rt = FlowEntry::GetUcRoute(intf->vrf(),
1167  pkt->ip_daddr);
1168 
1169  if (src_rt == NULL || dst_rt == NULL) {
1170  overlay_route_not_found = true;
1171  return;
1172  }
1173 
1174  overlay_route_not_found = false;
1175  uint32_t src_tunnel_bmap = src_rt->GetActivePath()->tunnel_bmap();
1176  uint32_t dst_tunnel_bmap = dst_rt->GetActivePath()->tunnel_bmap();
1177 
1178  if ((src_tunnel_bmap & (1 << TunnelType::NATIVE)) &&
1179  (dst_tunnel_bmap & (1 << TunnelType::NATIVE))) {
1180  underlay_flow = true;
1181  //Set policy VRF for route tracking
1182  src_policy_vrf = intf->vrf()->vrf_id();
1183  dst_policy_vrf = intf->vrf()->vrf_id();
1184  src_vn = RouteToVn(src_rt);
1185  dst_vn = RouteToVn(dst_rt);
1186  return;
1187  }
1188 
1189  const VrfEntry *vrf = intf->vrf();
1190  ChangeVrf(pkt, out, vrf);
1191  dest_vrf = vrf->vrf_id();
1192  alias_ip_flow = true;
1193  UpdateRoute(&out->rt_, vrf, pkt->ip_daddr, pkt->dmac,
1195  UpdateRoute(&in->rt_, vrf, pkt->ip_saddr, pkt->smac,
1197 }
1198 
1200  PktControlInfo *in,
1201  PktControlInfo *out) {
1202  if (in->rt_ == NULL || out->rt_ == NULL) {
1203  return;
1204  }
1205 
1206  overlay_route_not_found = false;
1207  const InetUnicastRouteEntry *src =
1208  static_cast<const InetUnicastRouteEntry *>(in->rt_);
1209  const IpAddress src_ip = src->prefix_address();
1210 
1211  const InetUnicastRouteEntry *dst =
1212  static_cast<const InetUnicastRouteEntry *>(out->rt_);
1213  const IpAddress dst_ip = dst->prefix_address();
1214 
1215  uint32_t src_tunnel_bmap = in->rt_->GetActivePath()->tunnel_bmap();
1216  uint32_t dst_tunnel_bmap = out->rt_->GetActivePath()->tunnel_bmap();
1217 
1218  if ((src_tunnel_bmap & (1 << TunnelType::NATIVE)) &&
1219  (dst_tunnel_bmap & (1 << TunnelType::NATIVE))) {
1220 
1221  underlay_flow = true;
1222  src_vn = RouteToVn(in->rt_);
1223  dst_vn = RouteToVn(out->rt_);
1224 
1225  if (nat_done == false) {
1226  src_policy_vrf = in->rt_->vrf()->vrf_id();
1227  }
1228  dst_policy_vrf = out->rt_->vrf()->vrf_id();
1229  const VrfEntry *vrf = agent->fabric_vrf();
1230  ChangeVrf(pkt, out, vrf);
1231  UpdateRoute(&out->rt_, vrf, dst_ip, pkt->dmac,
1233  UpdateRoute(&in->rt_, vrf, src_ip, pkt->smac,
1235  }
1236 }
1237 
1238 void PktFlowInfo::ChangeEncap(const VmInterface *intf, const PktInfo *pkt,
1239  PktControlInfo *in, PktControlInfo *out,
1240  bool nat_flow) {
1241  if (nat_flow) {
1242  ChangeFloatingIpEncap(pkt, in, out);
1243  } else {
1244  ChangeEncapToOverlay(intf, pkt, in, out);
1245  }
1246 }
1247 
1249  PktControlInfo *out, const IpAddress &src_ip,
1250  bool nat_flow) {
1251  const Interface *intf = NULL;
1252  if (ingress) {
1253  intf = in->intf_;
1254  } else {
1255  intf = out->intf_;
1256  }
1257  if (!intf || intf->type() != Interface::VM_INTERFACE) {
1258  return true;
1259  }
1260 
1261  const VmInterface *vm_intf = static_cast<const VmInterface *>(intf);
1262  //If interface has a VRF assign rule, choose the acl and match the
1263  //packet, else get the acl attached to VN and try matching the packet to
1264  //network acl
1265 
1266  ChangeEncap(vm_intf, pkt, in, out, nat_flow);
1267 
1268  const AclDBEntry *acl = NULL;
1269  if (nat_flow == false) {
1270  acl = vm_intf->vrf_assign_acl();
1271  }
1272  //In case of floating IP translation, dont apply
1273  //interface VRF assign rule
1274  if (acl == NULL) {
1275  if (ingress && in->vn_) {
1276  //Check if the network ACL is present
1277  acl = in->vn_->GetAcl();
1278  } else if (out->vn_) {
1279  acl = out->vn_->GetAcl();
1280  }
1281  }
1282 
1283  if (!acl) {
1284  return true;
1285  }
1286 
1287  PacketHeader hdr;
1288  hdr.vrf = pkt->vrf;
1289  hdr.src_ip = src_ip;
1290  hdr.dst_ip = pkt->ip_daddr;
1291 
1292  hdr.protocol = pkt->ip_proto;
1293  if (hdr.protocol == IPPROTO_UDP || hdr.protocol == IPPROTO_TCP) {
1294  hdr.src_port = pkt->sport;
1295  hdr.dst_port = pkt->dport;
1296  } else {
1297  hdr.src_port = 0;
1298  hdr.dst_port = 0;
1299  }
1300  hdr.src_policy_id = RouteToVn(in->rt_);
1301  hdr.dst_policy_id = RouteToVn(out->rt_);
1302 
1303  if (underlay_flow) {
1304  hdr.src_policy_id = src_vn;
1305  hdr.dst_policy_id = dst_vn;
1306  }
1307 
1308  if (in->rt_) {
1309  const AgentPath *path = in->rt_->GetActivePath();
1310  hdr.src_sg_id_l = &(path->sg_list());
1311  }
1312  if (out->rt_) {
1313  const AgentPath *path = out->rt_->GetActivePath();
1314  hdr.dst_sg_id_l = &(path->sg_list());
1315  }
1316 
1317  MatchAclParams match_acl_param;
1318  if (!acl->PacketMatch(hdr, match_acl_param, NULL)) {
1319  return true;
1320  }
1321 
1322  if (match_acl_param.action_info.vrf_translate_action_.vrf_name() != "") {
1323  VrfKey key(match_acl_param.action_info.vrf_translate_action_.vrf_name());
1324  const VrfEntry *vrf = static_cast<const VrfEntry*>
1325  (agent->vrf_table()->FindActiveEntry(&key));
1326  if (vrf == NULL) {
1327  short_flow = true;
1329  in->rt_ = NULL;
1330  out->rt_ = NULL;
1331  return false;
1332  }
1333 
1334  ChangeVrf(pkt, out, vrf);
1335  UpdateRoute(&out->rt_, vrf, pkt->ip_daddr, pkt->dmac,
1337  UpdateRoute(&in->rt_, vrf, hdr.src_ip, pkt->smac,
1339  underlay_flow = false;
1340  }
1341  return true;
1342 }
1343 
1344 // Changes VRF of in/out routes in case of DNAT and
1345 // VRF NH pointing to Interface NH in the routing VRF instance
1347  PktControlInfo *out) {
1348  if (out == NULL ||
1349  in == NULL ||
1350  out->rt_ == NULL ||
1351  in->vrf_ == NULL ||
1352  in->vrf_->routing_vrf()) {
1353  return;
1354  }
1355 
1356  const NextHop *nh = out->rt_->GetActiveNextHop();
1357  if (nh == NULL || nh->GetType() != NextHop::VRF) {
1358  return;
1359  }
1360 
1361  const VrfNH *vrf_nh = static_cast<const VrfNH *>(nh);
1362  const VrfEntry *vrf = vrf_nh->GetVrf();
1363  if (vrf == NULL || vrf->routing_vrf() == false) {
1364  return;
1365  }
1366 
1367  InetUnicastRouteEntry *inet_rt = vrf->GetUcRoute(pkt->ip_daddr);
1368  const NextHop *rt_nh = inet_rt ?
1369  inet_rt->GetActiveNextHop() : NULL;
1370  if (rt_nh == NULL || (rt_nh->GetType() != NextHop::INTERFACE && rt_nh->GetType() != NextHop::COMPOSITE)) {
1371  return;
1372  }
1373 
1374  if (rt_nh->GetType() == NextHop::INTERFACE){
1375  const Interface *intf = static_cast<const InterfaceNH*>
1376  (rt_nh)->GetInterface();
1377  if (intf == NULL || intf->type() != Interface::VM_INTERFACE ||
1378  static_cast<const VmInterface*>(intf)->FloatingIpCount() == 0) {
1379  return;
1380  }
1381  }
1382  if (rt_nh->GetType() == NextHop::COMPOSITE){
1383  const CompositeNH *composite_nh = static_cast<const CompositeNH*>(rt_nh);
1384  uint32_t comp_nh_count = composite_nh->ComponentNHCount();
1385  for (uint32_t i=0; i < comp_nh_count; i++) {
1386  const NextHop * c_nh = composite_nh->GetNH(i);
1387  if (c_nh == NULL){
1388  continue;
1389  } else {
1390  const Interface *intf = static_cast<const InterfaceNH*>(c_nh)->GetInterface();
1391  if (intf == NULL || intf->type() != Interface::VM_INTERFACE ||
1392  static_cast<const VmInterface*>(intf)->FloatingIpCount() == 0) {
1393  return;
1394  }
1395  }
1396  }
1397  }
1398 
1399  ChangeVrf(pkt, out, vrf);
1400  UpdateRoute(&out->rt_, vrf, pkt->ip_daddr, pkt->dmac,
1402  UpdateRoute(&in->rt_, vrf, pkt->ip_saddr, pkt->smac,
1404 }
1405 
1407  PktControlInfo *out) {
1408  // Flow packets are expected only on VMPort interfaces
1409  if (in->intf_->type() != Interface::VM_INTERFACE &&
1410  in->intf_->type() != Interface::INET) {
1411  LogError(pkt, this, "Unexpected packet on Non-VM interface");
1412  return;
1413  }
1414 
1415  const VmInterface *vm_port =
1416  dynamic_cast<const VmInterface *>(in->intf_);
1417  if (vm_port != NULL) {
1418  VrfEntry *alias_vrf = vm_port->GetAliasIpVrf(pkt->ip_saddr);
1419  if (alias_vrf != NULL) {
1420  in->vrf_ = alias_vrf;
1421  // translate to alias ip vrf for destination, unless overriden by
1422  // translation due to NAT or ACL
1423  dest_vrf = alias_vrf->vrf_id();
1424  alias_ip_flow = true;
1425  }
1426  }
1427 
1428  // We always expect route for source-ip for ingress flows.
1429  // If route not present, return from here so that a short flow is added
1430  UpdateRoute(&in->rt_, in->vrf_, pkt->ip_saddr, pkt->smac,
1432  in->vn_ = InterfaceToVn(in->intf_);
1433 
1434  // Consider linklocal service requests as l3 always
1435  CheckLinkLocal(pkt);
1436 
1437  // Compute Out-VRF and Route for dest-ip
1438  out->vrf_ = in->vrf_;
1439  UpdateRoute(&out->rt_, out->vrf_, pkt->ip_daddr, pkt->dmac,
1441 
1442  // Change VRF if a packet travels between a bridge and the
1443  // routing VRF instances with destination pointed by FIP
1444  NatVxlanVrfTranslate(pkt, in, out);
1445 
1446  //Native VRF of the interface and acl assigned vrf would have
1447  //exact same route with different nexthop, hence if both ingress
1448  //route and egress route are present in native vrf, acl match condition
1449  //can be applied
1450  if (VrfTranslate(pkt, in, out, pkt->ip_saddr, false) == false) {
1451  return;
1452  }
1453 
1454  if (out->rt_) {
1455  // Compute out-intf and ECMP info from out-route
1456  if (RouteToOutInfo(agent, out->rt_, pkt, this, in, out)) {
1457  if (out->intf_) {
1458  out->vn_ = InterfaceToVn(out->intf_);
1459  //In case of alias IP destination VRF would
1460  //be already while NHDecode or if its underlay
1461  //to overlay transition then encap change takes
1462  //care of it.
1463  //In case of VM using ip-fabric for forwarding
1464  //NH would be set with VRF as ip-fabric which
1465  //would mean local IPV6 traffic would be forwarded
1466  //in ip-fabric VRF which is not needed
1467  if (out->vrf_ && alias_ip_flow == false) {
1468  dest_vrf = out->vrf_->vrf_id();
1469  }
1470  }
1471  }
1472  }
1473 
1475  out->rt_,
1476  pkt->sport,
1477  pkt->dport,
1478  in->intf_)) {
1479  // If interface has floating IP, check if we have more specific route in
1480  // public VN (floating IP)
1481  if (l3_flow && IntfHasFloatingIp(this, in->intf_, pkt->family)) {
1482  FloatingIpSNat(pkt, in, out);
1483  }
1484  }
1485 
1486  if (out->rt_ != NULL) {
1487  // Route is present. If IP-DA is a floating-ip, we need DNAT
1488  if (RouteToOutInfo(agent, out->rt_, pkt, this, in, out)) {
1489  if (out->intf_ && IntfHasFloatingIp(this, out->intf_, pkt->family)) {
1490  FloatingIpDNat(pkt, in, out);
1491  }
1492  }
1493  }
1494 
1495  // Packets needing linklocal service will have route added by LinkLocal peer
1496  if ((in->rt_ && IsLinkLocalRoute(agent, in->rt_, pkt->sport, pkt->dport)) ||
1497  (out->rt_ && IsLinkLocalRoute(agent, out->rt_,
1498  pkt->sport, pkt->dport))) {
1499  LinkLocalServiceTranslate(pkt, in, out);
1500  }
1501 
1502  //Packets needing bgp router service handling
1503  if (IsBgpRouterServiceRoute(in->rt_, out->rt_,
1504  in->intf_, pkt->sport,
1505  pkt->dport)) {
1506  BgpRouterServiceTranslate(pkt, in, out);
1507  }
1508 
1509  // If out-interface was not found, get it based on out-route
1510  if (out->intf_ == NULL && out->rt_) {
1511  RouteToOutInfo(agent, out->rt_, pkt, this, in, out);
1512  }
1513  if (out->rt_) {
1514  const NextHop* nh = out->rt_->GetActiveNextHop();
1515  if (nh && nh->GetType() == NextHop::COMPOSITE) {
1516  const CompositeNH *comp_nh = static_cast<const CompositeNH *>(nh);
1517  nh = comp_nh->GetNH(out_component_nh_idx);
1518  }
1519 
1520  if (nh && nh->GetType() == NextHop::TUNNEL) {
1521  const TunnelNH* tunnel_nh = static_cast<const TunnelNH *>(nh);
1522  const Ip4Address *ip = tunnel_nh->GetDip();
1523  if (ip) {
1524  peer_vrouter = ip->to_string();
1525  tunnel_type = tunnel_nh->GetTunnelType();
1526  }
1527  } else {
1528  peer_vrouter = agent->router_id().to_string();
1529  }
1530  }
1531 
1532  //In case of distributed SNAT we dont want policy to be applied based
1533  //on translated FIP route. hence change ingress route to VM's actual
1534  //route and also the source policy VRF
1535  if (port_allocated && short_flow == false) {
1536  UpdateRoute(&in->rt_, in->vrf_, pkt->ip_saddr, pkt->smac,
1538  in->vn_ = InterfaceToVn(in->intf_);
1539  src_policy_vrf = in->intf_->vrf()->vrf_id();
1540  }
1541 
1542  return;
1543 }
1544 
1546  tunnel_type = pkt->tunnel.type;
1549  MplsLabel *mpls = agent->mpls_table()->FindMplsLabel(pkt->tunnel.label);
1550  if (mpls == NULL) {
1551  LogError(pkt, this, "Invalid Label in egress flow");
1552  return NULL;
1553  }
1554  return mpls->nexthop();
1555  } else if (tunnel_type.GetType() == TunnelType::VXLAN) {
1556  VxLanTable *table = static_cast<VxLanTable *>(agent->vxlan_table());
1557  VxLanId *vxlan = table->FindNoLock(pkt->tunnel.vxlan_id);
1558  if (vxlan == NULL) {
1559  LogError(pkt, this, "Invalid vxlan in egress flow");
1560  return NULL;
1561  }
1562 
1563  const VrfNH *nh = dynamic_cast<const VrfNH *>(vxlan->nexthop());
1564  if (nh == NULL)
1565  return NULL;
1566 
1567  const VrfEntry *vrf = nh->GetVrf();
1568  if (vrf == NULL)
1569  return NULL;
1570 
1571  AgentRoute *rt = NULL;
1572  if (vrf->vn()->vxlan_routing_vn()) {
1573  rt = FlowEntry::GetUcRoute(vrf, pkt->ip_daddr);
1574  } else {
1575  // In case of VXLAN, the NH points to VrfNH. Need to do route lookup
1576  // on dmac to find the real nexthop
1577  rt = FlowEntry::GetL2Route(vrf, pkt->dmac);
1578  }
1579  if (rt != NULL) {
1580  return rt->GetActiveNextHop();
1581  }
1582 
1583  return NULL;
1584  } else {
1586  pkt->ip_daddr);
1587  if (rt != NULL) {
1588  return rt->GetActiveNextHop();
1589  }
1590 
1591 
1592  LogError(pkt, this, "Invalid tunnel type in egress flow");
1593  return NULL;
1594  }
1595 
1596  return NULL;
1597 }
1598 
1600  PktControlInfo *out) {
1601  peer_vrouter = Ip4Address(pkt->tunnel.ip_saddr).to_string();
1602 
1603  const NextHop *nh = TunnelToNexthop(pkt);
1604  if (nh == NULL) {
1605  return;
1606  }
1607  if((nh->GetType() == NextHop::ARP) && (l3_flow == false)) {
1608  LOG(ERROR, "PktFlowInfo::EgressProcess: ARP nexthop and l3_flow "
1609  " false, DROP this frame. module " << pkt->module << " type "
1610  << pkt->type << " family " << pkt->family << " vrf " <<pkt->vrf
1611  << " tunnel_type " << pkt->tunnel.type.GetType()<< " ifindex "
1612  << pkt->agent_hdr.ifindex << " sip " << pkt->ip_saddr.to_string()
1613  << " dip " << pkt->ip_daddr.to_string() << " proto " << pkt->ip_proto
1614  << " sport " << pkt->sport << " dport " <<pkt->dport<<" l3_label "
1615  << pkt->l3_label);
1616  return;
1617  }
1618  const CompositeNH *comp_nh = dynamic_cast<const CompositeNH *>(nh);
1619  EcmpLoadBalance ecmp_load_balance;
1620  if (comp_nh != NULL) {
1621  UpdateRoute(&out->rt_, comp_nh->vrf(), pkt->ip_daddr, pkt->dmac,
1623  if (out->rt_ && out->rt_->GetActivePath()) {
1624  ecmp_load_balance = out->rt_->GetActivePath()->ecmp_load_balance();
1625  }
1626  }
1627 
1628  //Delay hash pick up till route is picked.
1629  if (NhDecode(agent, nh, pkt, this, in, out, true,
1630  ecmp_load_balance) == false) {
1631  return;
1632  }
1633 
1634  if (out->intf_ && out->intf_->type() == Interface::VM_INTERFACE) {
1635  const VmInterface *vm_intf = static_cast<const VmInterface *>(out->intf_);
1636  if (vm_intf->IsFloatingIp(pkt->ip_daddr)) {
1637  l3_flow = true;
1638  } else {
1639  VrfEntry *alias_vrf = vm_intf->GetAliasIpVrf(pkt->ip_daddr);
1640  if (alias_vrf != NULL) {
1641  out->vrf_ = alias_vrf;
1642  // translate to alias ip vrf for destination, unless overriden by
1643  // translation due to NAT or ACL
1644  dest_vrf = alias_vrf->vrf_id();
1645  alias_ip_flow = true;
1646  }
1647  }
1648  }
1649 
1650  if (out->vrf_ == NULL) {
1651  return;
1652  }
1653 
1654  UpdateRoute(&out->rt_, out->vrf_, pkt->ip_daddr, pkt->dmac,
1656  UpdateRoute(&in->rt_, out->vrf_, pkt->ip_saddr, pkt->smac,
1658 
1659  if (out->intf_) {
1660  out->vn_ = InterfaceToVn(out->intf_);
1661  }
1662 
1663  //Apply vrf translate ACL to get ingress route
1664  if (VrfTranslate(pkt, in, out, pkt->ip_saddr, false) == false) {
1665  return;
1666  }
1667 
1669  out->rt_,
1670  pkt->sport,
1671  pkt->dport,
1672  out->intf_)) {
1673  // If interface has floating IP, check if destination is one of the
1674  // configured floating IP.
1675  if (IntfHasFloatingIp(this, out->intf_, pkt->family)) {
1676  FloatingIpDNat(pkt, in, out);
1677  }
1678  }
1679 
1680  if (out->rt_) {
1681  if (ecmp && out->rt_->GetActivePath()) {
1682  const CompositeNH *comp_nh = static_cast<const CompositeNH *>(nh);
1684  out_component_nh_idx = comp_nh->hash(pkt->
1685  hash(agent, out->rt_->GetActivePath()->
1686  ecmp_load_balance()), ingress);
1687  }
1688  }
1689  const NextHop *anh = out->rt_->GetActiveNextHop();
1690  if ((anh) && (anh->GetType() == NextHop::ARP ||
1691  anh->GetType() == NextHop::RESOLVE)) {
1692  //If a packet came with mpls label pointing to
1693  //vrf NH, then we need to do a route lookup
1694  //and set the nexthop for reverse flow properly
1695  //as mpls pointed NH would not be used for reverse flow
1696  if (RouteToOutInfo(agent, out->rt_, pkt, this, in, out)) {
1697  if (out->intf_) {
1698  out->vn_ = InterfaceToVn(out->intf_);
1699  }
1700  }
1701  }
1702  }
1703 
1704  return;
1705 }
1706 
1708  const PktControlInfo *in,
1709  const PktControlInfo *out) {
1710  bool ret = false;
1711  if (ingress && out->rt_ == NULL && in->rt_) {
1712  const VmInterface *vm_intf =
1713  static_cast<const VmInterface *>(in->intf_);
1714  //If interface has flag to flood unknown unicast
1715  //and destination route is not present
1716  //mark the flow for forward
1717  if (vm_intf->flood_unknown_unicast()) {
1718  flood_unknown_unicast = true;
1720  static_cast<const AgentRoute *>(in->rt_)->vrf_id();
1721  ret = true;
1722  }
1723  } else if (in->rt_ == NULL && out->rt_) {
1724  //This packet should not be ideally trapped
1725  //from vrouter for flow setup.
1726  //VxLAN nexthop would be set with flag
1727  //to flood multicast, hence we would
1728  //hit all broadcast multicast route and
1729  //packet would never be trapped for flow setup
1730  tunnel_type = pkt->tunnel.type;
1732  VxLanTable *table = static_cast<VxLanTable *>(agent->vxlan_table());
1733  VxLanId *vxlan = table->FindNoLock(pkt->tunnel.vxlan_id);
1734  if (vxlan && vxlan->nexthop()) {
1735  const VrfNH *vrf_nh =
1736  static_cast<const VrfNH *>(vxlan->nexthop());
1737  if (vrf_nh->flood_unknown_unicast()) {
1739  static_cast<const AgentRoute *>(out->rt_)->vrf_id();
1740  flood_unknown_unicast = true;
1741  ret = true;
1742  }
1743  }
1744  }
1745  }
1746  return ret;
1747 }
1748 
1749 // Ignore in case of BFD health check
1750 bool IsValidationDisabled(Agent *agent, const PktInfo *pkt,
1751  const Interface *interface) {
1752  if (!interface)
1753  return false;
1754  return ((agent->pkt()->pkt_handler()->
1755  IsBFDHealthCheckPacket(pkt, interface)) ||
1756  (agent->pkt()->pkt_handler()->
1757  IsSegmentHealthCheckPacket(pkt, interface)));
1758 }
1759 
1760 // Basic config validations for the flow
1763 
1764  if (agent->tsn_enabled()) {
1765  short_flow = true;
1767  return false;
1768  }
1769 
1770  if (in->intf_ == NULL) {
1771  LogError(pkt, this, "Invalid interface");
1772  short_flow = true;
1774  return false;
1775  }
1776 
1777  const VmInterface *vm_intf = dynamic_cast<const VmInterface *>(in->intf_);
1778  if (l3_flow == true && !disable_validation) {
1779  if (vm_intf && in->intf_->ip_active(pkt->family) == false &&
1780  (pkt->ip_saddr.is_v6() && !pkt->ip_saddr.to_v6().is_link_local()) &&
1781  (pkt->ip_daddr.is_v6() && !pkt->ip_daddr.to_v6().is_link_local())) {
1782  in->intf_ = NULL;
1783  LogError(pkt, this, "IP protocol inactive on interface");
1784  short_flow = true;
1786  return false;
1787  }
1788 
1789  if (vm_intf && vm_intf->layer3_forwarding() == false) {
1790  LogError(pkt, this, "IP service not enabled for interface");
1791  short_flow = true;
1793  return false;
1794  }
1795  }
1796 
1797  if (l3_flow == false && !disable_validation) {
1798  if (in->intf_->l2_active() == false) {
1799  in->intf_ = NULL;
1800  LogError(pkt, this, "L2 inactive on interface");
1801  short_flow = true;
1803  return false;
1804  }
1805 
1806  if (vm_intf && vm_intf->bridging() == false) {
1807  LogError(pkt, this, "Bridge service not enabled for interface");
1808  short_flow = true;
1810  return false;
1811  }
1812  }
1813 
1814  if (in->vrf_ == NULL || in->vrf_->IsActive() == false) {
1815  in->vrf_ = NULL;
1816  LogError(pkt, this, "Invalid or Inactive VRF");
1817  short_flow = true;
1819  return false;
1820  }
1821 
1822  return true;
1823 }
1824 
1826  PktControlInfo *out) {
1828  out->nh_ = in->nh_ = pkt->agent_hdr.nh;
1829  in->vrf_ = agent->vrf_table()->FindVrfFromId(pkt->agent_hdr.vrf);
1830 
1831  if (ValidateConfig(pkt, in) == false) {
1832  return false;
1833  }
1834 
1835  //By default assume destination vrf and source vrf to be same
1836  dest_vrf = pkt->vrf;
1837  // Compute direction of flow based on in-interface
1839  if (ingress) {
1840  IngressProcess(pkt, in, out);
1841  } else {
1842  EgressProcess(pkt, in, out);
1843  }
1844 
1845  if (l3_flow == false) {
1846  if (UnknownUnicastFlow(pkt, in, out) == true) {
1847  return true;
1848  }
1849  }
1850 
1853  (pkt->is_fat_flow_dst_prefix))) {
1854  /* Fat flow not supported for NAT flows */
1855  LogError(pkt, this, "Flow : Fat-flow and NAT cannot co-exist");
1856  short_flow = true;
1858  return false;
1859  }
1860 
1861  if (!disable_validation) {
1862  if (in->rt_ == NULL || in->rt_->IsDeleted()) {
1863  LogError(pkt, this, "Flow : No route for Src-IP");
1864  short_flow = true;
1866  return false;
1867  }
1868 
1869  if (out->rt_ == NULL || out->rt_->IsDeleted()) {
1870  LogError(pkt, this, "Flow : No route for Dst-IP");
1871  short_flow = true;
1873  return false;
1874  }
1875 
1876  flow_source_vrf = static_cast<const AgentRoute *>(in->rt_)->vrf_id();
1877  flow_dest_vrf = out->rt_->vrf_id();
1878  } else {
1880  }
1881 
1883  LogError(pkt, this, "Flow : Overlay route not found");
1884  short_flow = true;
1886  return false;
1887  }
1888 
1889  //If source is ECMP, establish a reverse flow pointing
1890  //to the component index
1891  if (in->rt_ && in->rt_->GetActiveNextHop() &&
1893  ecmp = true;
1894  }
1895 
1896  if (out->rt_ && out->rt_->GetActiveNextHop() &&
1898  ecmp = true;
1899  }
1900 
1901  return true;
1902 }
1903 
1904 // A flow can mean that traffic is seen on an interface. The path preference
1905 // module can potentially be interested in this event. Check and generate
1906 // traffic seen event
1908  const PktControlInfo *in) {
1909  // Traffic seen should not be generated for MESSAGE
1910  if (pkt->type == PktType::MESSAGE) {
1911  return;
1912  }
1913 
1914  // Dont generate Traffic seen for egress flows or short or linklocal flows
1915  if (ingress == false || short_flow || linklocal_flow) {
1916  return;
1917  }
1918 
1919  // TODO : No need for one more route lookup
1920  const AgentRoute *rt = NULL;
1921  bool enqueue_traffic_seen = false;
1922  const VmInterface *vm_intf = dynamic_cast<const VmInterface *>(in->intf_);
1923 
1924  IpAddress sip = pkt->ip_saddr;
1925  if (pkt->family == Address::INET ||
1926  pkt->family == Address::INET6) {
1927  if (l3_flow) {
1928  rt = in->rt_;
1929  } else if (in->vrf_) {
1930  rt = FlowEntry::GetUcRoute(in->vrf_, sip);
1931  }
1932  }
1933  uint8_t plen = 0;
1934  // Generate event if route was waiting for traffic
1935  if (rt && rt->WaitForTraffic()) {
1936  enqueue_traffic_seen = true;
1937  plen = rt->prefix_length();
1938  } else if (vm_intf) {
1939  //L3 route is not in wait for traffic state
1940  //EVPN route could be in wait for traffic, if yes
1941  //enqueue traffic seen
1942  rt = FlowEntry::GetEvpnRoute(in->vrf_, pkt->smac, sip,
1943  vm_intf->ethernet_tag());
1944  if (rt && rt->WaitForTraffic()) {
1945  const EvpnRouteEntry *evpn_rt = static_cast<const EvpnRouteEntry *>
1946  (rt);
1947  plen = evpn_rt->prefix_length();
1948  enqueue_traffic_seen = true;
1949  } else {
1950  IpAddress addr;
1951  rt = FlowEntry::GetEvpnRoute(in->vrf_, pkt->smac, addr,
1952  vm_intf->ethernet_tag());
1953  if (rt && rt->WaitForTraffic()) {
1954  plen = 32;
1955  if (pkt->family == Address::INET6) {
1956  plen = 128;
1957  }
1958  enqueue_traffic_seen = true;
1959  }
1960  }
1961 
1962  }
1963 
1964  if (enqueue_traffic_seen) {
1966  EnqueueTrafficSeen(sip, plen, in->intf_->id(),
1967  pkt->vrf, pkt->smac);
1968  }
1969 }
1970 
1971 // Apply flow limits for in and out VMs
1973  const PktControlInfo *out) {
1974  // Ignore flow limit checks for flow-update and short-flows
1975  if (short_flow || pkt->type == PktType::MESSAGE) {
1976  return;
1977  }
1978 
1979  bool limit_exceeded = false;
1980  bool interface_max_flow = false;
1981  if (in->intf_ && (in->intf_->type() == Interface::VM_INTERFACE)) {
1982  const VmInterface *vm_intf =
1983  dynamic_cast<const VmInterface *>(in->intf_);
1984  if (vm_intf) {
1985  if (vm_intf->max_flows()) {
1986  interface_max_flow = true;
1987  if ((vm_intf->flow_count() +2) > vm_intf->max_flows())
1988  limit_exceeded = true;
1989  }
1990  }
1991  }
1992 
1993  if (out->intf_ && (out->intf_->type() == Interface::VM_INTERFACE)) {
1994  const VmInterface *vm_intf =
1995  dynamic_cast<const VmInterface *>(out->intf_);
1996  if (vm_intf) {
1997  if (vm_intf->max_flows()) {
1998  interface_max_flow = true;
1999  if ((vm_intf->flow_count() +2) > vm_intf->max_flows())
2000  limit_exceeded = true;
2001  }
2002  }
2003  }
2004 
2005  if (agent->max_vm_flows() && (!interface_max_flow) &&
2006  (in->vm_ && ((in->vm_->flow_count() + 2) > agent->max_vm_flows()))) {
2007  limit_exceeded = true;
2008  }
2009 
2010  if (agent->max_vm_flows() && (!interface_max_flow) &&
2011  (out->vm_ && ((out->vm_->flow_count() + 2) > agent->max_vm_flows()))) {
2012  limit_exceeded = true;
2013  }
2014 
2015  if (limit_exceeded) {
2017  short_flow = true;
2019  return;
2020  }
2021 
2022  if (linklocal_bind_local_port == false)
2023  return;
2024 
2025  // Apply limits for link-local flows
2028  limit_exceeded = true;
2029  }
2030 
2031  // Check per-vm linklocal flow-limits if specified
2032  if ((agent->params()->linklocal_vm_flows() !=
2034  if (in->vm_ && in->vm_->linklocal_flow_count() >=
2036  limit_exceeded = true;
2037  }
2038  }
2039 
2040  if (limit_exceeded) {
2042  short_flow = true;
2044  return;
2045  }
2046 
2047  return;
2048 }
2049 
2051  const PktControlInfo *in,
2052  FlowEntry *flow) {
2053  assert(flow->in_vm_flow_ref()->fd() == VmFlowRef::kInvalidFd);
2054  if (linklocal_bind_local_port == false)
2055  return;
2056 
2057  // link-local service flow. Initialize nat-sport to original src-port.
2058  // It will be over-ridden if socket could be allocated later
2059  nat_sport = pkt->sport;
2060 
2061  // Dont allocate FD for short flows
2062  if (short_flow)
2063  return;
2064 
2065  if (flow->in_vm_flow_ref()->AllocateFd(agent, pkt->ip_proto) == false) {
2066  // Could not allocate FD. Make it short flow
2068  short_flow = true;
2070  return;
2071  }
2072  nat_sport = flow->in_vm_flow_ref()->port();
2073 
2074  return;
2075 }
2076 
2078  Agent *agent = flow_table->agent();
2080  FlowEntryPtr flow = imgr->FindByIndex(pkt->agent_hdr.cmd_param);
2081  FlowMgmtManager *mgr = agent->pkt()->flow_mgmt_manager(
2082  flow_table->table_index());
2083 
2084  /* Enqueue stats update request with UUID of the flow */
2085  if (flow.get() && flow->deleted() == false) {
2086  mgr->FlowStatsUpdateEvent(flow.get(), pkt->agent_hdr.cmd_param_2,
2087  pkt->agent_hdr.cmd_param_3,
2088  pkt->agent_hdr.cmd_param_4, flow->uuid());
2089  }
2090 }
2091 
2093  PktControlInfo *out) {
2094  bool update = false;
2095  if (pkt->type != PktType::MESSAGE &&
2099  }
2100  }
2101 
2102  if ((pkt->type == PktType::MESSAGE &&
2104  update = true;
2105  }
2106 
2107  // Generate traffic seen event for path preference module
2108  GenerateTrafficSeen(pkt, in);
2109  IpAddress sip = pkt->ip_saddr;
2110  IpAddress dip = pkt->ip_daddr;
2112  if (ingress) {
2113  sip = FamilyToAddress(pkt->family);
2114  } else {
2115  dip = FamilyToAddress(pkt->family);
2116  }
2117  } else if (pkt->ignore_address == VmInterface::IGNORE_DESTINATION) {
2118  if (ingress) {
2119  dip = FamilyToAddress(pkt->family);
2120  } else {
2121  sip = FamilyToAddress(pkt->family);
2122  }
2123  }
2124 
2125  if (pkt->is_fat_flow_src_prefix) {
2126  sip = pkt->ip_ff_src_prefix;
2127  }
2128  if (pkt->is_fat_flow_dst_prefix) {
2129  dip = pkt->ip_ff_dst_prefix;
2130  }
2131 
2132  FlowKey key(in->nh_, sip, dip, pkt->ip_proto, pkt->sport, pkt->dport);
2134 
2135  ApplyFlowLimits(in, out);
2136  LinkLocalPortBind(pkt, in, flow.get());
2137 
2138  // rflow for newly allocated entry should always be NULL
2139  FlowEntryPtr rflow = flow->reverse_flow_entry();
2140  assert(rflow == NULL);
2141 
2142  uint16_t r_sport;
2143  uint16_t r_dport;
2144  if ((pkt->family == Address::INET && pkt->ip_proto == IPPROTO_ICMP) ||
2145  (pkt->family == Address::INET6 && pkt->ip_proto == IPPROTO_ICMPV6)) {
2146  r_sport = pkt->sport;
2147  r_dport = pkt->dport;
2148  } else if (nat_done) {
2149  r_sport = nat_dport;
2150  r_dport = nat_sport;
2151  } else {
2152  r_sport = pkt->dport;
2153  r_dport = pkt->sport;
2154  }
2155 
2156  // Allocate reverse flow
2157  if (nat_done) {
2158  FlowKey rkey(out->nh_, nat_ip_daddr, nat_ip_saddr, pkt->ip_proto,
2159  r_sport, r_dport);
2160  rflow = FlowEntry::Allocate(rkey, flow_table);
2161  } else {
2162  if (pkt->same_port_number && (in->nh_ == out->nh_)) {
2163  /* When source and destination ports are same and FatFlow is
2164  * configured for that port, always mask source port for both
2165  * forward and reverse flows */
2166  r_sport = pkt->sport;
2167  r_dport = pkt->dport;
2168  }
2169  FlowKey rkey(out->nh_, dip, sip, pkt->ip_proto, r_sport, r_dport);
2170  rflow = FlowEntry::Allocate(rkey, flow_table);
2171  }
2172 
2173  bool swap_flows = false;
2174  // If this is message processing, then retain forward and reverse flows
2175  if (pkt->type == PktType::MESSAGE && !short_flow &&
2177  // for cases where we need to swap flows rflow should always
2178  // be Non-NULL
2179  assert(rflow != NULL);
2180  swap_flows = true;
2181  }
2182 
2183  tcp_ack = pkt->tcp_ack;
2184  flow->InitFwdFlow(this, pkt, in, out, rflow.get(), agent);
2185  if (rflow != NULL) {
2186  rflow->InitRevFlow(this, pkt, out, in, flow.get(), agent);
2187  }
2188 
2189  flow->GetPolicyInfo();
2190  if (rflow != NULL) {
2191  rflow->GetPolicyInfo();
2192  }
2193 
2194  flow->ResyncFlow();
2195  if (rflow != NULL) {
2196  rflow->ResyncFlow();
2197  }
2198 
2199  // RPF computation can be done only after policy processing.
2200  // Do RPF computation now
2201  flow->RpfUpdate();
2202  if (rflow)
2203  rflow->RpfUpdate();
2204 
2205  /* Fip stats info in not updated in InitFwdFlow and InitRevFlow because
2206  * both forward and reverse flows are not not linked to each other yet.
2207  * We need both forward and reverse flows to update Fip stats info */
2208  UpdateFipStatsInfo(flow.get(), rflow.get(), pkt, in, out);
2209 
2210  FlowEntry *tmp = swap_flows ? rflow.get() : flow.get();
2211  if (update) {
2212  agent->pkt()->get_flow_proto()->UpdateFlow(tmp);
2213  } else {
2214  agent->pkt()->get_flow_proto()->AddFlow(tmp);
2215  }
2216 }
2217 
2219  (FlowEntry *flow, FlowEntry *rflow, const PktInfo *pkt,
2220  const PktControlInfo *in, const PktControlInfo *out) {
2221 
2222  if (pkt->family != Address::INET) {
2223  //TODO: v6 handling
2224  return;
2225  }
2226  uint32_t intf_id, r_intf_id;
2227  uint32_t fip, r_fip;
2228  intf_id = Interface::kInvalidIndex;
2229  r_intf_id = Interface::kInvalidIndex;
2230  fip = 0;
2231  r_fip = 0;
2232  if (fip_snat && fip_dnat && rflow != NULL) {
2233  /* This is the case where Source and Destination VMs (part of
2234  * same compute node) have floating-IP assigned to each of them from
2235  * a common VN and then each of these VMs send traffic to other VM by
2236  * addressing the other VM's Floating IP. In this case both SNAT and
2237  * DNAT flags will be set. We identify SNAT and DNAT flows by
2238  * inspecting IP of forward and reverse flows and update Fip stats
2239  * info based on that. */
2240  const FlowKey *nat_key = &(rflow->key());
2241  if (flow->key().src_addr != nat_key->dst_addr) {
2242  //SNAT case
2243  fip = snat_fip.to_v4().to_ulong();
2244  intf_id = in->intf_->id();
2245  } else if (flow->key().dst_addr != nat_key->src_addr) {
2246  //DNAT case
2247  fip = flow->key().dst_addr.to_v4().to_ulong();
2248  intf_id = out->intf_->id();
2249  }
2250  nat_key = &(flow->key());
2251  if (rflow->key().src_addr != nat_key->dst_addr) {
2252  //SNAT case
2253  r_fip = snat_fip.to_v4().to_ulong();
2254  r_intf_id = in->intf_->id();
2255  } else if (rflow->key().dst_addr != nat_key->src_addr) {
2256  //DNAT case
2257  r_fip = rflow->key().dst_addr.to_v4().to_ulong();
2258  r_intf_id = out->intf_->id();
2259  }
2260  } else if (fip_snat) {
2261  fip = r_fip = nat_ip_saddr.to_v4().to_ulong();
2262  intf_id = r_intf_id = in->intf_->id();
2263  } else if (fip_dnat) {
2264  fip = r_fip = pkt->ip_daddr.to_v4().to_ulong();
2265  intf_id = r_intf_id = out->intf_->id();
2266  }
2267 
2268  if (fip_snat || fip_dnat) {
2269  flow->UpdateFipStatsInfo(fip, intf_id, agent);
2270  if (rflow != NULL) {
2271  rflow->UpdateFipStatsInfo(r_fip, r_intf_id, agent);
2272  }
2273  }
2274 }
2275 
2276 void PktFlowInfo::SetPktInfo(boost::shared_ptr<PktInfo> pkt_info) {
2277  family = pkt_info->family;
2278  pkt = pkt_info;
2279  }
2280 
2282  if (pkt->family == Address::INET6) {
2283  return Ip6Address();
2284  }
2285  return Ip4Address();
2286 }
uint32_t PickMember(uint32_t seed, uint32_t affinity_index, bool ingress) const
Definition: nexthop.cc:1861
VrfEntry * GetAliasIpVrf(const IpAddress &ip) const
uint8_t prefix_length() const
!
std::string peer_vrouter
uint32_t vrf_id() const
uint32_t dport
Definition: pkt_handler.h:398
bool AllocateFd(Agent *agent, uint8_t l3_proto)
Definition: flow_entry.cc:218
void SetPktInfo(boost::shared_ptr< PktInfo > info)
bool linklocal_bind_local_port
IpAddress ip_saddr
Definition: pkt_handler.h:394
static const Ip6Address kDefaultIpv6
Definition: pkt_flow_info.h:41
static bool IsVgwOrVmInterface(const Interface *intf)
const Interface * GetInterface() const
Definition: nexthop.h:1293
Address::Family family
Definition: pkt_handler.h:386
uint32_t flow_count() const
Definition: vm.h:55
const SecurityGroupList * dst_sg_id_l
Definition: packet_header.h:26
bool bgp_router_service_flow
const VnListType & dest_vn_list() const
Definition: agent_path.h:258
bool is_fat_flow_src_prefix
Definition: pkt_handler.h:414
IpAddress src_addr
Definition: flow_entry.h:213
static const VnEntry * InterfaceToVn(const Interface *intf)
ServicesModule * services() const
Definition: agent.cc:973
Type type() const
Definition: interface.h:112
const VrfEntry * GetVrf() const
Definition: nexthop.h:1546
bool tsn_enabled() const
Definition: agent.h:1162
bool flood_unknown_unicast
virtual uint8_t prefix_length() const
Returns the length of a stored prefix address.
Definition: agent_route.h:323
bool ip_active(Address::Family family) const
Definition: interface.cc:1476
uint32_t ifindex
Definition: pkt_handler.h:180
bool UnknownUnicastFlow(const PktInfo *p, const PktControlInfo *in_info, const PktControlInfo *out_info)
Definition: vrf.h:86
bool IsFloatingIp(const IpAddress &ip) const
static const NextHop * GetLocalNextHop(const AgentRoute *rt)
Definition: ecmp.cc:496
static const uint32_t kInvalidComponentNHIdx
Definition: nexthop.h:1777
MetadataProxy * metadataproxy()
Definition: services_init.h:32
VrfEntry * fabric_vrf() const
Definition: agent.h:915
Ip4Address compute_node_ip() const
Definition: agent.h:681
const AclDBEntry * GetAcl() const
Definition: vn.h:167
const VrfEntry * GetVrf() const
Definition: nexthop.h:1444
VrfEntry * FindVrfFromName(const string &name)
Definition: vrf.cc:873
const uint32_t id() const
Definition: interface.h:123
VrfEntry * vrf_
Definition: agent_route.h:349
static const VnListType * RouteToVn(const AgentRoute *rt)
IpAddress dst_addr
Definition: flow_entry.h:214
Ip4Address mdata_ip_addr() const
bool WaitForTraffic() const
Definition: agent_route.cc:971
uint8_t ip_proto
Definition: pkt_handler.h:396
bool IngressRouteAllowNatLookup(const AgentRoute *in_rt, const AgentRoute *out_rt, uint32_t sport, uint32_t dport, const Interface *intf)
PktHandler::PktModuleName module
Definition: pkt_handler.h:378
const Interface * vhost_interface() const
Definition: agent.h:935
static bool RouteToOutInfo(const Agent *agent, const AgentRoute *rt, const PktInfo *pkt, PktFlowInfo *info, PktControlInfo *in, PktControlInfo *out)
VmInterface::DeviceType device_type() const
const VnListType * src_vn
Family
Definition: address.h:24
const NextHop * nexthop() const
Definition: mpls.h:80
bool IsDeleted() const
Definition: db_entry.h:49
uint32_t nat_sport
boost::asio::ip::address IpAddress
Definition: address.h:13
Type GetType() const
Definition: nexthop.h:303
const Ip6Address & Ipv6ServiceAddress() const
Returns an IPv6 address of the Metadata TF link local service.
IpAddress destination_ip() const
Definition: metadata_ip.cc:119
bool l2_active() const
Definition: interface.h:122
bool port_allocated
Agent * agent() const
Definition: flow_table.h:197
void incr_flow_drop_due_to_max_limit()
Definition: agent_stats.h:117
uint32_t nat_vrf
FlowTable * flow_table
AgentStats * stats() const
Definition: agent.cc:881
IpAddress ip_ff_src_prefix
Definition: pkt_handler.h:415
Agent * agent
uint32_t out_component_nh_idx
uint32_t label
Definition: pkt_handler.h:212
uint32_t linklocal_flow_count() const
Definition: flow_proto.h:111
const NextHop * TunnelToNexthop(const PktInfo *pkt)
MacAddress dmac
Definition: pkt_handler.h:393
void BgpRouterServiceFromVm(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
bool EgressRouteAllowNatLookup(const AgentRoute *in_rt, const AgentRoute *out_rt, uint32_t sport, uint32_t dport, const Interface *intf)
uint32_t ip_saddr
Definition: pkt_handler.h:215
AgentDBEntry * FindActiveEntry(const DBEntry *key)
Definition: agent_db.cc:110
InterfaceTable * interface_table() const
Definition: agent.h:465
const Ip4Address * GetDip() const
Definition: tunnel_nh.h:37
const VrfEntry * vrf_
Definition: pkt_flow_info.h:26
FlowRouteRefMap flow_source_plen_map
uint32_t max_vm_flows() const
Definition: agent.h:1205
uint32_t nat_dest_vrf
uint16_t table_index() const
Definition: flow_table.h:198
IpAddress snat_fip
IpAddress service_ip() const
Definition: metadata_ip.cc:94
void set_prefix_length(uint8_t new_plen)
Sets the length of a stored prefix address.
Definition: agent_route.h:378
FlowEntryPtr FindByIndex(uint32_t idx)
const string & GetName() const
Definition: vrf.h:100
static AgentRoute * GetEvpnRoute(const VrfEntry *entry, const MacAddress &mac, const IpAddress &addr, uint32_t ethernet_tag)
Definition: flow_entry.cc:1005
static AgentRoute * GetL2Route(const VrfEntry *entry, const MacAddress &mac)
Definition: flow_entry.cc:982
uint16_t GetVlanTag() const
Definition: nexthop.h:1544
PortTableManager * port_table_manager()
Definition: flow_proto.h:126
const VnListType * src_policy_id
Definition: packet_header.h:20
const SecurityGroupList * src_sg_id_l
Definition: packet_header.h:21
bool linklocal_flow
const std::string & vrf_name() const
uint32_t cmd_param_4
Definition: pkt_handler.h:187
MplsTable * mpls_table() const
Definition: agent.h:510
bool RouteAllowNatLookupCommon(const AgentRoute *rt, uint32_t sport, uint32_t dport, const Interface *intf)
Definition: vxlan.h:14
VrfEntry * vrf() const
Definition: interface.h:115
bool l3_label
Definition: pkt_handler.h:408
void ChangeEncap(const VmInterface *intf, const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out, bool nat_flow)
void UpdateEvictedFlowStats(const PktInfo *pkt)
Type GetType() const
Definition: nexthop.h:405
static FlowEntry * Allocate(const FlowKey &key, FlowTable *flow_table)
Definition: flow_entry.cc:514
Base class for all Route entries in agent.
Definition: agent_route.h:224
const VrfEntry * vrf() const
Definition: nexthop.h:1875
VmFlowRef * in_vm_flow_ref()
Definition: flow_entry.h:654
uint16_t src_port
Definition: packet_header.h:29
static const int kInvalidFd
Definition: flow_entry.h:99
const NextHop * flow_key_nh() const
Definition: interface.h:137
uint16_t Allocate(const FlowKey &key)
Definition: flow_entry.cc:4139
#define METADATA_NAT_PORT
Definition: agent.h:296
void LinkLocalPortBind(const PktInfo *pkt, const PktControlInfo *in, FlowEntry *flow)
void ChangeFloatingIpEncap(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
uint32_t cmd_param_2
Definition: pkt_handler.h:185
boost::shared_ptr< PktInfo > pkt
OperDB * oper_db() const
Definition: agent.cc:1013
bool FindLinkLocalService(const std::string &service_name, IpAddress *service_ip, uint16_t *service_port, std::string *fabric_hostname, Ip4Address *fabric_ip, uint16_t *fabric_port) const
Get link local service configuration info, for a given service name.
void UpdateRoute(const AgentRoute **rt, const VrfEntry *vrf, const IpAddress &addr, const MacAddress &mac, FlowRouteRefMap &ref_map)
const VnListType * dst_vn
bool ValidateConfig(const PktInfo *pkt, PktControlInfo *in)
void IngressProcess(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
uint32_t sport
Definition: pkt_handler.h:397
const Interface * GetInterface() const
Definition: nexthop.h:837
uint32_t label() const
Definition: interface.h:127
const FlowKey & key() const
Definition: flow_entry.h:594
uint32_t vrf
Definition: packet_header.h:17
const std::string & fabric_vrf_name() const
Definition: agent.h:903
IpAddress FamilyToAddress(Address::Family family)
TunnelInfo tunnel
Definition: pkt_handler.h:407
const AgentPath * GetActivePath() const
Definition: agent_route.cc:876
virtual Agent::RouteTableType GetTableType() const =0
BgpAsAService * bgp_as_a_service() const
Definition: operdb_init.h:77
static void LogError(const PktInfo *pkt, const PktFlowInfo *flow_info, const char *str)
const Peer * link_local_peer() const
Definition: agent.h:1024
GlobalVrouter * global_vrouter() const
Definition: operdb_init.h:54
VrfEntry * FindVrfFromId(size_t index)
Definition: vrf.cc:884
IpAddress nat_ip_daddr
void FloatingIpSNat(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
bool is_flags_set(const FlowEntryFlags &flags) const
Definition: flow_entry.h:610
void GenerateTrafficSeen(const PktInfo *pkt, const PktControlInfo *in)
Definition: agent.h:358
bool flood_unknown_unicast() const
VrfTranslateActionSpec vrf_translate_action_
Definition: acl.h:48
uint32_t vrf_id() const
Definition: interface.cc:621
IpAddress src_ip
Definition: packet_header.h:19
bool disable_validation
Definition: vrf.h:22
PathPreferenceModule * route_preference_module() const
Definition: operdb_init.h:58
const TunnelType & GetTunnelType() const
Definition: tunnel_nh.h:42
uint32_t ttl
Definition: pkt_handler.h:399
const NextHop * GetActiveNextHop() const
Definition: agent_route.cc:881
IpAddress ip_ff_dst_prefix
Definition: pkt_handler.h:417
void AdvertiseMetaDataLinkLocalRoutes(const VmInterface *vm, const Ip6Address &ll_ip, const VrfEntry *intf_vrf)
Advertises routes to a given vm-interface via a given IPv6 address. Routes are announced in the fabri...
KSync * ksync() const
Definition: agent.cc:901
boost::asio::ip::address_v6 Ip6Address
Definition: address.h:15
Ip4Address router_id() const
Definition: agent.h:666
bool VrfTranslate(const PktInfo *pkt, PktControlInfo *ctrl, PktControlInfo *rev_flow, const IpAddress &src_ip, bool nat_flow)
map< int, int > FlowRouteRefMap
Definition: pkt_flow_info.h:16
bool tcp_ack
Definition: pkt_handler.h:406
uint32_t linklocal_flow_count() const
Definition: vm.h:58
bool IsValidationDisabled(Agent *agent, const PktInfo *pkt, const Interface *interface)
bool vxlan_routing_vn() const
Definition: vn.h:255
TunnelType type
Definition: pkt_handler.h:211
Definition: nexthop.h:820
bool layer3_forwarding() const
bool IsBgpRouterServiceRoute(const AgentRoute *in_rt, const AgentRoute *out_rt, const Interface *intf, uint32_t sport, uint32_t dport)
uint32_t linklocal_system_flows() const
Definition: agent_param.h:255
bool Process(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
const Peer * peer() const
Definition: agent_path.h:263
uint32_t vrf
Definition: pkt_handler.h:181
static bool ComputeDirection(const Interface *intf)
const AclDBEntry * acl
bool bridging() const
PktHandler * pkt_handler() const
Definition: pkt_init.h:31
void Add(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
#define FLOW_TRACE(obj,...)
Definition: flow_mgmt.h:377
const VnEntry * vn() const
static const uint32_t DefaultBgpPort
static AgentRoute * GetUcRoute(const VrfEntry *entry, const IpAddress &addr)
Definition: flow_entry.cc:989
uint32_t nat_dport
Ip6Address mdata_ip6_addr() const
uint32_t src_policy_vrf
COMPOSITETYPE composite_nh_type() const
Definition: nexthop.h:1842
uint32_t nh
Definition: pkt_handler.h:189
AgentParam * params() const
Definition: agent.h:1218
uint32_t flow_count() const
static const std::set< std::string > & NullStringList()
Definition: agent.h:438
void FlowStatsUpdateEvent(FlowEntry *flow, uint32_t bytes, uint32_t packets, uint32_t oflow_bytes, const boost::uuids::uuid &u)
Definition: flow_mgmt.cc:174
const uint32_t vrf_id() const
Definition: vrf.h:99
std::set< std::string > VnListType
Definition: agent.h:212
uint32_t vrf
Definition: pkt_handler.h:391
bool alias_ip_flow
const AclDBEntry * vrf_assign_acl() const
virtual const PrefixType & prefix_address() const
Returns the value of a stored prefix address (IPv4, IPv6 or MAC address)
Definition: agent_route.h:375
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
FlowProto * get_flow_proto() const
Definition: pkt_init.h:43
const NextHop * nexthop() const
Definition: vxlan.h:28
Definition: vn.h:151
VrfTable * vrf_table() const
Definition: agent.h:485
const Ip4Address & primary_ip_addr() const
const FloatingIpList & floating_ip_list() const
static const Ip4Address kDefaultIpv4
Definition: pkt_flow_info.h:40
uint16_t port() const
Definition: flow_entry.h:114
FlowEntry * flow_entry
bool routing_vrf() const
Definition: vrf.h:223
uint32_t hash(uint32_t seed, bool ingress) const
Definition: nexthop.h:1878
const Interface * intf_
Definition: pkt_flow_info.h:27
bool PacketMatch(const PacketHeader &packet_header, MatchAclParams &m_acl, FlowPolicyInfo *info) const
Definition: acl.cc:798
uint32_t id() const
Definition: nexthop.h:408
uint8_t RouteToPrefixLen(const AgentRoute *route)
IpAddress nat_ip_saddr
uint8_t prefix_length() const
!
FlowProto * GetFlowProto() const
Definition: agent.h:999
VxLanTable * vxlan_table() const
Definition: agent.h:535
VmInterface::VmiType vmi_type() const
static size_t bit_len()
Definition: mac_address.h:61
const VrfEntry * GetVrf() const
Definition: nexthop.h:841
bool underlay_flow
uint16_t short_flow_reason
static const uint32_t kInvalidIndex
Definition: interface.h:70
const Ip6Address & primary_ip6_addr() const
Definition: mpls.h:52
static bool PickEcmpMember(const Agent *agent, const NextHop **nh, const PktInfo *pkt, PktFlowInfo *info, const EcmpLoadBalance &ecmp_load_balance)
Address::Family family
uint32_t max_flows() const
size_t ComponentNHCount() const
Definition: nexthop.h:1815
VnEntry * vn() const
Definition: vrf.h:101
static const uint32_t kInvalidFlowHandle
Definition: flow_entry.h:521
bool same_port_number
Definition: pkt_handler.h:413
uint16_t vlan_tag_
Definition: pkt_flow_info.h:32
std::set< FloatingIp, FloatingIp > FloatingIpSet
Definition: vm_interface.h:567
const Interface * FindInterface(size_t index) const
Definition: interface.cc:323
MacAddress smac
Definition: pkt_handler.h:392
VrfEntry * forwarding_vrf() const
Definition: vrf.h:217
static const uint32_t kInvalidIndex
Definition: vrf.h:88
#define LOG(_Level, _Msg)
Definition: logging.h:33
uint32_t ethernet_tag() const
void BgpRouterServiceTranslate(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
void LinkLocalServiceFromVm(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
VrfEntry * vrf() const
Definition: agent_route.h:275
uint32_t cmd_param_3
Definition: pkt_handler.h:186
const AgentRoute * rt_
Definition: pkt_flow_info.h:28
MplsLabel * FindMplsLabel(uint32_t label)
Definition: mpls.cc:399
bool IsActive() const
Definition: agent_db.cc:27
void ChangeVrf(const PktInfo *pkt, PktControlInfo *info, const VrfEntry *vrf)
FlowAction action_info
Definition: acl.h:58
bool GetIndex(ComponentNH &nh, uint32_t &idx) const
Definition: nexthop.cc:2335
const Interface * get_interface() const
Definition: nexthop.h:754
uint32_t flow_source_vrf
uint32_t dst_policy_vrf
const VnEntry * vn_
Definition: pkt_flow_info.h:29
const VmEntry * vm_
Definition: pkt_flow_info.h:30
const VnListType * dst_policy_id
Definition: packet_header.h:25
bool overlay_route_not_found
virtual const NextHop * ComputeNextHop(Agent *agent) const
Definition: agent_path.cc:91
IpAddress ip_daddr
Definition: pkt_handler.h:395
uint32_t cmd_param
Definition: pkt_handler.h:183
uint32_t linklocal_vm_flows() const
Definition: agent_param.h:256
uint32_t dest_vrf
AgentHdr agent_hdr
Definition: pkt_handler.h:388
void CheckLinkLocal(const PktInfo *pkt)
static uint32_t NhToVrf(const NextHop *nh)
uint16_t cmd
Definition: pkt_handler.h:182
bool is_fat_flow_dst_prefix
Definition: pkt_handler.h:416
static bool IsLinkLocalRoute(Agent *agent, const AgentRoute *rt, uint32_t sport, uint32_t dport)
const NextHop * GetNH(uint32_t idx) const
Definition: nexthop.h:1832
void UpdateFipStatsInfo(uint32_t fip, uint32_t id, Agent *agent)
Definition: flow_entry.cc:1032
void NatVxlanVrfTranslate(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
KSyncFlowIndexManager * ksync_flow_index_manager() const
Definition: ksync_init.h:61
uint16_t dst_port
Definition: packet_header.h:30
uint16_t metadata_server_port() const
Definition: agent.h:959
uint32_t tunnel_bmap() const
Definition: agent_path.h:267
static bool NhDecode(const Agent *agent, const NextHop *nh, const PktInfo *pkt, PktFlowInfo *info, PktControlInfo *in, PktControlInfo *out, bool force_vmport, const EcmpLoadBalance &ecmp_load_balance)
FlowMgmtManager * flow_mgmt_manager(uint16_t index) const
Definition: pkt_init.h:39
VmInterface::FatFlowIgnoreAddressType ignore_address
Definition: pkt_handler.h:412
PktModule * pkt() const
Definition: agent.cc:965
InetUnicastRouteEntry * GetUcRoute(const IpAddress &addr) const
Definition: vrf.cc:237
SubType sub_type() const
FlowRouteRefMap flow_dest_plen_map
void ApplyFlowLimits(const PktControlInfo *in, const PktControlInfo *out)
const Interface * GetInterface() const
Definition: nexthop.h:1543
bool UpdateFlow(FlowEntry *flow)
Definition: flow_proto.cc:298
void ChangeEncapToOverlay(const VmInterface *intf, const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
std::size_t hash(const Agent *agent, const EcmpLoadBalance &ecmp_has_fields_to_use) const
uint32_t vxlan_id
Definition: pkt_handler.h:213
void EgressProcess(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
IpAddress dst_ip
Definition: packet_header.h:24
uint32_t flow_dest_vrf
void LinkLocalServiceTranslate(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
void LinkLocalServiceFromHost(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
VxLanId * FindNoLock(uint32_t vxlan_id)
Definition: vxlan.cc:228
uint8_t protocol
Definition: packet_header.h:28
int fd() const
Definition: flow_entry.h:113
const SecurityGroupList & sg_list() const
Definition: agent_path.h:248
Definition: acl.h:92
MetaDataIp * GetMetaDataIp(const IpAddress &ip) const
const EcmpLoadBalance & ecmp_load_balance() const
Definition: agent_path.h:365
bool AddFlow(FlowEntry *flow)
Definition: flow_proto.cc:292
void UpdateFipStatsInfo(FlowEntry *flow, FlowEntry *rflow, const PktInfo *p, const PktControlInfo *in, const PktControlInfo *o)
TunnelType tunnel_type
bool flood_unknown_unicast() const
Definition: nexthop.h:1449
boost::intrusive_ptr< FlowEntry > FlowEntryPtr
Definition: flow_entry.h:125
void FloatingIpDNat(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
static bool IntfHasFloatingIp(PktFlowInfo *pkt_info, const Interface *intf, Address::Family family)
PktType::Type type
Definition: pkt_handler.h:387