OpenSDN source code
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 
381  // Bug solution: 1 hypervisor 2 of the network
382  // Does not block incoming icmp/udp traffic, as the acl on the out interface is not checked due to the absence of this interface
383  // Find this interface here
384  const InetUnicastRouteEntry* rt = out->vrf_->GetUcRoute(pkt->ip_daddr);
385  if (rt && rt->GetActiveNextHop()) {
386  const NextHop *rt_nh = rt->GetActiveNextHop();
387  if (rt_nh->GetType() == NextHop::INTERFACE) {
388  out->intf_ = static_cast<const InterfaceNH*>(rt_nh)->GetInterface();
389  if (out->intf_->type() == Interface::VM_INTERFACE) {
390  out->nh_ = out->intf_->flow_key_nh()->id();
391  }
392  }
393  }
394 
395  break;
396  }
397 
398  // ARP Nexthop means outgoing interface is gateway kind of interface with
399  // ARP already resolved
400  case NextHop::ARP: {
401  assert(info->l3_flow == true);
402  const ArpNH *arp_nh = static_cast<const ArpNH *>(nh);
403  if (in->intf_->type() == Interface::VM_INTERFACE) {
404  const VmInterface *vm_intf =
405  static_cast<const VmInterface *>(in->intf_);
406  if (vm_intf->vmi_type() == VmInterface::VHOST) {
407  out->nh_ = in->intf_->flow_key_nh()->id();
408  out->intf_ = in->intf_;
409  } else if (vm_intf->device_type() == VmInterface::LOCAL_DEVICE) {
410  out->nh_ = arp_nh->id();
411  out->intf_ = arp_nh->GetInterface();
412  }
413  } else {
414  out->intf_ = arp_nh->GetInterface();
415  }
416  out->vrf_ = arp_nh->GetVrf();
417  break;
418  }
419 
420  // RESOLVE Nexthop means traffic came from gateway interface and destined
421  // to another gateway interface
422  case NextHop::RESOLVE: {
423  assert(info->l3_flow == true);
424  const ResolveNH *rsl_nh = static_cast<const ResolveNH *>(nh);
425  out->nh_ = rsl_nh->get_interface()->flow_key_nh()->id();
426  out->intf_ = rsl_nh->get_interface();
427  break;
428  }
429 
430  default:
431  out->intf_ = NULL;
432  break;
433  }
434 
435  if (out->intf_) {
436  if (!out->intf_->IsActive()) {
437  out->intf_ = NULL;
438  ret = false;
439  } else if (force_vmport && IsVgwOrVmInterface(out->intf_) == false) {
440  out->intf_ = NULL;
441  out->vrf_ = NULL;
442  ret = true;
443  }
444  }
445 
446  if (out->vrf_ && (out->vrf_->IsActive() == false)) {
447  out->vrf_ = NULL;
448  ret = false;
449  }
450 
451  return ret;
452 }
453 
454 // Decode route and get Interface / ECMP information
455 static bool RouteToOutInfo(const Agent *agent, const AgentRoute *rt,
456  const PktInfo *pkt, PktFlowInfo *info,
457  PktControlInfo *in, PktControlInfo *out) {
458  const AgentPath *path = rt->GetActivePath();
459  if (path == NULL)
460  return false;
461 
462  const NextHop *nh = static_cast<const NextHop *>
463  (path->ComputeNextHop(info->agent));
464  if (nh == NULL)
465  return false;
466 
467  if (nh->IsActive() == false) {
468  return false;
469  }
470 
471  return NhDecode(agent, nh, pkt, info, in, out, false,
472  path->ecmp_load_balance());
473 }
474 
475 static const VnEntry *InterfaceToVn(const Interface *intf) {
476  if (intf->type() != Interface::VM_INTERFACE)
477  return NULL;
478 
479  const VmInterface *vm_port = static_cast<const VmInterface *>(intf);
480  return vm_port->vn();
481 }
482 
483 static bool IntfHasFloatingIp(PktFlowInfo *pkt_info, const Interface *intf,
484  Address::Family family) {
485  if (!intf || intf->type() != Interface::VM_INTERFACE)
486  return false;
487 
488  return static_cast<const VmInterface *>(intf)->HasFloatingIp(family);
489 }
490 
491 static bool IsLinkLocalRoute(Agent *agent, const AgentRoute *rt,
492  uint32_t sport, uint32_t dport) {
493  //Local CN and BGP has been allowed for testing purpose.
494  if ((sport == BgpAsAService::DefaultBgpPort) ||
496  return false;
497 
498  const AgentPath *path = rt->GetActivePath();
499  if (path && path->peer() == agent->link_local_peer())
500  return true;
501 
502  return false;
503 }
504 
506  const AgentRoute *out_rt,
507  const Interface *intf,
508  uint32_t sport,
509  uint32_t dport) {
511  return true;
512 
513  if (intf == NULL || in_rt == NULL || out_rt == NULL)
514  return false;
515 
516  if ((sport != BgpAsAService::DefaultBgpPort) &&
518  return false;
519 
520  if (intf->type() == Interface::VM_INTERFACE) {
521  const VmInterface *vm_intf =
522  dynamic_cast<const VmInterface *>(intf);
523  const InetUnicastRouteEntry *in_inet_rt =
524  dynamic_cast<const InetUnicastRouteEntry *>(in_rt);
525  const InetUnicastRouteEntry *out_inet_rt =
526  dynamic_cast<const InetUnicastRouteEntry *>(out_rt);
527  if (in_inet_rt == NULL || out_inet_rt == NULL)
528  return false;
529  if (agent->oper_db()->bgp_as_a_service()->
530  IsBgpService(vm_intf, in_inet_rt->prefix_address(), out_inet_rt->prefix_address())) {
532  return true;
533  }
534  }
535 
536  return false;
537 }
538 
539 static const VnListType *RouteToVn(const AgentRoute *rt) {
540  const AgentPath *path = NULL;
541  if (rt) {
542  path = rt->GetActivePath();
543  }
544  if (path == NULL) {
545  return &(Agent::NullStringList());
546  }
547 
548  return &path->dest_vn_list();
549 }
550 
552  uint32_t sport,
553  uint32_t dport,
554  const Interface *intf) {
555  // No NAT for bridge routes
556  if (dynamic_cast<const BridgeRouteEntry *>(rt) != NULL)
557  return false;
558 
559  if (rt != NULL && IsLinkLocalRoute(agent, rt, sport, dport)) {
560  // skip NAT lookup if found route has link local peer.
561  return false;
562  }
563 
564  return true;
565 }
566 
568  const AgentRoute *out_rt,
569  uint32_t sport,
570  uint32_t dport,
571  const Interface *intf) {
572  if (RouteAllowNatLookupCommon(out_rt, sport, dport, intf) == false) {
573  return false;
574  }
575 
576  if (IsBgpRouterServiceRoute(in_rt, out_rt, intf, sport, dport)) {
577  // skip NAT lookup if found route has link local peer.
578  return false;
579  }
580 
581  return true;
582 }
583 
585  const AgentRoute *out_rt,
586  uint32_t sport,
587  uint32_t dport,
588  const Interface *intf) {
589  if (RouteAllowNatLookupCommon(out_rt, sport, dport, intf) == false) {
590  return false;
591  }
592 
593  return true;
594 }
595 
597  if (!l3_flow && pkt->ip_daddr.is_v4()) {
598  uint16_t nat_port;
599  Ip4Address nat_server;
600  std::string service_name;
601  GlobalVrouter *global_vrouter = agent->oper_db()->global_vrouter();
602  if (global_vrouter->FindLinkLocalService(pkt->ip_daddr,
603  pkt->dport, &service_name,
604  &nat_server, &nat_port)) {
605  // it is link local service request, treat it as l3
606  l3_flow = true;
607  }
608  }
609 }
610 
612  PktControlInfo *out) {
613 
614  const VmInterface *vm_port =
615  static_cast<const VmInterface *>(in->intf_);
616 
617  uint16_t nat_port;
618  Ip4Address nat_server4;
619  IpAddress nat_server;
620  std::string service_name;
622  (pkt->ip_daddr, pkt->dport, &service_name, &nat_server4,
623  &nat_port)) {
624  // link local service not configured, drop the request
625  in->rt_ = NULL;
626  out->rt_ = NULL;
627  return;
628  }
629 
631  dest_vrf = out->vrf_->vrf_id();
632 
633  MetadataProxy *metadata_proxy = NULL;
634  metadata_proxy = agent ?
635  (agent->services() ? agent->services()->metadataproxy() : NULL) : NULL;
636  if (metadata_proxy && pkt &&
637  pkt->ip_saddr.is_v6() &&
638  pkt->ip_daddr.is_v6()) {
639  Ip6Address ll_ip = pkt->ip_saddr.to_v6();
640  // Announce the route to the interface LL address
641  metadata_proxy->AdvertiseMetaDataLinkLocalRoutes(vm_port,
642  ll_ip, in->vrf_);
643  }
644 
645  // Set NAT flow fields
646  if (pkt->ip_daddr.is_v4()) {
647  linklocal_flow = true;
648  nat_done = true;
649  underlay_flow = false;
650  if (nat_server4 == agent->router_id()) {
651  // In case of metadata or when link local destination is local host,
652  // set VM's metadata address as NAT source address. This is required
653  // to avoid response from the linklocal service being looped back and
654  // the packet not coming to vrouter for reverse NAT.
655  // Destination would be local host (FindLinkLocalService returns this)
656  nat_ip_saddr = vm_port->mdata_ip_addr();
657  // Services such as metadata will run on compute_node_ip. Set nat
658  // address to compute_node_ip
659  nat_server4 = agent->compute_node_ip();
660  nat_sport = pkt->sport;
661  } else {
663  // we bind to a local port & use it as NAT source port (cannot use
664  // incoming src port); init here and bind in Add;
665  nat_sport = 0;
667  }
668  nat_server = nat_server4;
669  } else {
670  if (nat_server4 == agent->router_id()) {
671  linklocal_flow = true;
672  nat_done = true;
673  underlay_flow = false;
674  nat_server = metadata_proxy ?
675  metadata_proxy->Ipv6ServiceAddress() :
676  Ip6Address::from_string("::");
677  nat_ip_saddr = vm_port->mdata_ip6_addr();
678  nat_sport = pkt->sport;
679  }
680  }
681 
682  nat_ip_daddr = nat_server;
683  nat_dport = nat_port;
684 
685  nat_vrf = dest_vrf;
686  nat_dest_vrf = vm_port->vrf_id();
687 
688  out->rt_ = FlowEntry::GetUcRoute(out->vrf_, nat_server);
689  return;
690 }
691 
693  PktControlInfo *out) {
694  if (RouteToOutInfo(agent, out->rt_, pkt, this, in, out) == false) {
695  return;
696  }
697 
698  // Link local services supported only for IPv4 for now
699  if (pkt->family != Address::INET) {
700  in->rt_ = NULL;
701  out->rt_ = NULL;
702  return;
703  }
704 
705  const VmInterface *vm_port =
706  static_cast<const VmInterface *>(out->intf_);
707  if (vm_port == NULL) {
708  // Force implicit deny
709  in->rt_ = NULL;
710  out->rt_ = NULL;
711  return;
712  }
713 
714  // Check if packet is destined to metadata of interface
715  MetaDataIp *mip = vm_port->GetMetaDataIp(pkt->ip_daddr.to_v4());
716  if (mip == NULL) {
717  // Force implicit deny
718  in->rt_ = NULL;
719  out->rt_ = NULL;
720  return;
721  }
722 
723  dest_vrf = vm_port->vrf_id();
724  out->vrf_ = vm_port->vrf();
725 
726  //If the destination route is ECMP set component index
727  //This component index would be used only for forwarding
728  //the first packet in flow (HOLD flow flushing)
729  InetUnicastRouteEntry *out_rt = NULL;
730  if (out->vrf_) {
731  out_rt = static_cast<InetUnicastRouteEntry *>(
733  if (out_rt) {
734  const NextHop *anh = out_rt->GetActiveNextHop();
735  if (anh && anh->GetType() == NextHop::COMPOSITE) {
736  const CompositeNH *comp_nh =
737  static_cast<const CompositeNH *>(anh);
738  ComponentNH component_nh(vm_port->label(), vm_port->flow_key_nh());
739  comp_nh->GetIndex(component_nh, out_component_nh_idx);
740  }
741  }
742  }
743 
744  linklocal_flow = true;
745  nat_done = true;
746  underlay_flow = false;
747  // Get NAT source/destination IP from MetadataIP retrieved from interface
748  nat_ip_saddr = mip->service_ip();
749  nat_ip_daddr = mip->destination_ip();
754  // Failed to find associated source or destination address
755  // Force implicit deny
756  in->rt_ = NULL;
757  out->rt_ = NULL;
758  return;
759  }
760 
761  nat_dport = pkt->dport;
762  if (pkt->sport == agent->metadata_server_port()) {
764  } else {
765  nat_sport = pkt->sport;
766  }
767  nat_vrf = dest_vrf;
768  nat_dest_vrf = pkt->vrf;
769  return;
770 }
771 
773  PktControlInfo *out) {
774  const VmInterface *vm_intf = dynamic_cast<const VmInterface *>(in->intf_);
775  if (vm_intf->vmi_type() != VmInterface::VHOST) {
776  LinkLocalServiceFromVm(pkt, in, out);
777  } else {
778  LinkLocalServiceFromHost(pkt, in, out);
779  }
780 }
781 
783  PktControlInfo *out) {
784 
785  // Link local services supported only for IPv4 for now
786  if (pkt->family != Address::INET) {
787  in->rt_ = NULL;
788  out->rt_ = NULL;
789  return;
790  }
791 
792  const VmInterface *vm_port =
793  static_cast<const VmInterface *>(in->intf_);
794 
795  const VnEntry *vn = static_cast<const VnEntry *>(vm_port->vn());
796  uint32_t sport = 0;
797  uint32_t dport = 0;
798  IpAddress nat_server = IpAddress();
799 
800  if (vn == NULL) {
801  in->rt_ = NULL;
802  out->rt_ = NULL;
803  return;
804  }
805 
806  if (agent->oper_db()->bgp_as_a_service()->
807  GetBgpRouterServiceDestination(vm_port,
808  pkt->ip_saddr.to_v4(),
809  pkt->ip_daddr.to_v4(),
810  &nat_server,
811  &sport, &dport) == false) {
812  return;
813  }
814 
816  dest_vrf = out->vrf_->vrf_id();
817 
818  nat_done = true;
819  //Populate NAT
821  nat_ip_daddr = nat_server;
822  nat_sport = sport;
823  nat_dport = dport;
824  if ((nat_ip_daddr == agent->router_id()) &&
825  (nat_ip_daddr == nat_ip_saddr)) {
826  boost::system::error_code ec;
827  //TODO may be use MDATA well known address.
828  nat_ip_saddr = vm_port->mdata_ip_addr();
829  }
830 
831  nat_vrf = dest_vrf;
832  nat_dest_vrf = vm_port->vrf_id();
833 
834 
835  out->rt_ = FlowEntry::GetUcRoute(out->vrf_, nat_server);
836  out->intf_ = agent->vhost_interface();
837  out->nh_ = out->intf_->flow_key_nh()->id();
838  ttl = pkt->ttl;
839  return;
840 }
841 
843  PktControlInfo *in,
844  PktControlInfo *out) {
845  if (in->intf_->type() == Interface::VM_INTERFACE) {
846  BgpRouterServiceFromVm(pkt, in, out);
847  }
848 }
849 
850 // DestNAT for packets entering into a VM with floating-ip.
851 // Can come here in two paths,
852 // - Packet originated on local vm.
853 // - Packet originated from remote vm
855  PktControlInfo *out) {
856  const VmInterface *vm_port =
857  static_cast<const VmInterface *>(out->intf_);
858  const VmInterface::FloatingIpSet &fip_list =
859  vm_port->floating_ip_list().list_;
860 
861  // We must NAT if the IP-DA is not same as Primary-IP on interface
862  if (pkt->ip_daddr.is_v4()) {
863  if (pkt->ip_daddr.to_v4() == vm_port->primary_ip_addr()) {
864  return;
865  }
866  }
867  if (pkt->ip_daddr.is_v6()) {
868  if (pkt->ip_daddr.to_v6() == vm_port->primary_ip6_addr()) {
869  return;
870  }
871  }
872 
873  // Look for matching floating-ip
874  VmInterface::FloatingIpSet::const_iterator it = fip_list.begin();
875  for ( ; it != fip_list.end(); ++it) {
876 
877  if (it->vrf_.get() == NULL) {
878  continue;
879  }
880 
881  if (pkt->ip_daddr != it->floating_ip_) {
882  continue;
883  }
884 
885  // Check if floating-ip direction matches
886  if (it->AllowDNat() == false) {
887  continue;
888  }
889 
890  break;
891  }
892 
893  if (it == fip_list.end()) {
894  // No matching floating ip for destination-ip
895  return;
896  }
897  in->vn_ = NULL;
898  if (nat_done == false) {
899  // lookup for source route in FIP VRF for egress flows only
900  // because for source route VRF is always present for ingress flows
901  // so there is no need to update source route with route lookup
902  // in FIP's VRF
903  if(!ingress) {
904  UpdateRoute(&in->rt_, it->vrf_.get(), pkt->ip_saddr, pkt->smac,
906  }
907  nat_dest_vrf = it->vrf_.get()->vrf_id();
908  }
909  UpdateRoute(&out->rt_, it->vrf_.get(), pkt->ip_daddr, pkt->dmac,
911  out->vn_ = it->vn_.get();
912  VrfEntry *alias_vrf = vm_port->GetAliasIpVrf(it->GetFixedIp(vm_port));
913  if (alias_vrf == NULL) {
914  dest_vrf = out->intf_->vrf()->vrf_id();
915  } else {
916  dest_vrf = alias_vrf->vrf_id();
917  }
918 
919  underlay_flow = false;
920  if (VrfTranslate(pkt, in, out, pkt->ip_saddr, true) == false) {
921  return;
922  }
923 
924  if (underlay_flow) {
925  if (pkt->ip_daddr.is_v6()) {
926  return;
927  }
928  if (it->vrf_->forwarding_vrf()) {
929  //Pick the underlay ip-fabric VRF for forwarding
930  nat_dest_vrf = it->vrf_->forwarding_vrf()->vrf_id();
931  }
932  if (out->intf_->vrf()->forwarding_vrf()) {
933  dest_vrf = out->intf_->vrf()->forwarding_vrf()->vrf_id();
934  }
935  }
936 
937  // Force packet to be treated as L3-flow in such case
938  // Flow is already marked as l3-flow by the time we are here. But, there is
939  // an exception in case of DNat.
940  // - In normal cases, packet hits bridge entry with receive-nh
941  // - If native-vrf and floating-ip vrf are same, the bridge entry points
942  // to interface-nh instead of receive nh.
943  l3_flow = true;
944  // Translate the Dest-IP
945  if (nat_done == false)
946  nat_ip_saddr = pkt->ip_saddr;
947  nat_ip_daddr = it->fixed_ip_;
948  if (it->port_map_enabled()) {
949  int32_t map_port = it->GetDstPortMap(pkt->ip_proto, pkt->dport);
950  if (map_port < 0) {
951  short_flow = true;
953  } else {
954  nat_dport = map_port;
955  }
956  } else {
957  nat_dport = pkt->dport;
958  }
959  nat_sport = pkt->sport;
960  nat_vrf = dest_vrf;
961  nat_done = true;
962 
963  if (in->rt_) {
964  flow_source_vrf = static_cast<const AgentRoute *>(in->rt_)->vrf_id();
965  } else {
967  }
968  flow_dest_vrf = it->vrf_.get()->vrf_id();
969 
970  // Update fields required for floating-IP stats accounting
971  fip_dnat = true;
972 
973  return;
974 }
975 
977  PktControlInfo *out) {
978  const VmInterface *intf =
979  static_cast<const VmInterface *>(in->intf_);
980  const VmInterface::FloatingIpSet &fip_list = intf->floating_ip_list().list_;
981  VmInterface::FloatingIpSet::const_iterator it = fip_list.begin();
982  VmInterface::FloatingIpSet::const_iterator fip_it = fip_list.end();
983  const AgentRoute *rt = out->rt_;
984  uint8_t rt_plen = 0;
985  if (rt) {
986  rt_plen = RouteToPrefixLen(rt);
987  }
988  bool change = false;
989  // Find Floating-IP matching destination-ip
990  for ( ; it != fip_list.end(); ++it) {
991  if (it->vrf_.get() == NULL) {
992  continue;
993  }
994 
995  if (it->fixed_ip_ != IpAddress() && (pkt->ip_saddr != it->fixed_ip_)) {
996  continue;
997  }
998 
999  // Check if floating-ip direction matches
1000  if (it->AllowSNat() == false) {
1001  continue;
1002  }
1003 
1004  const AgentRoute *rt_match = FlowEntry::GetUcRoute(it->vrf_.get(),
1005  pkt->ip_daddr);
1006  if (rt_match == NULL) {
1007  flow_dest_plen_map[it->vrf_.get()->vrf_id()] = 0;
1008  continue;
1009  }
1010  // found the route match
1011  // prefer the route with longest prefix match
1012  // if prefix length is same prefer route from rt(original out->rt_)
1013  // if routes are from fip of difference VRF, prefer the one with lower name.
1014  // if both the selected and current FIP is from same vrf prefer the one with lower ip addr.
1015  uint8_t rt_match_plen = RouteToPrefixLen(rt_match);
1016  if (rt != NULL && rt_plen >= rt_match_plen) {
1017  flow_dest_plen_map[rt_match->vrf_id()] = rt_match_plen;
1018  continue;
1019  }
1020  uint8_t out_rt_plen = RouteToPrefixLen(out->rt_);
1021  if (out->rt_ == NULL || rt_match_plen > out_rt_plen) {
1022  change = true;
1023  } else if (rt_match_plen == out_rt_plen) {
1024  if (it->port_nat()) {
1025  change = false;
1026  } else if (fip_it == fip_list.end()) {
1027  change = true;
1028  } else if (rt_match->vrf()->GetName() < out->rt_->vrf()->GetName()) {
1029  change = true;
1030  } else if (rt_match->vrf()->GetName() == out->rt_->vrf()->GetName() &&
1031  it->floating_ip_ < fip_it->floating_ip_) {
1032  change = true;
1033  }
1034  }
1035 
1036  if (change) {
1037  if (out->rt_ != NULL) {
1038  flow_dest_plen_map[out->rt_->vrf_id()] = out_rt_plen;
1039  }
1040  out->rt_ = rt_match;
1041  fip_it = it;
1042  change = false;
1043  } else {
1044  flow_dest_plen_map[rt_match->vrf_id()] = rt_match_plen;
1045  }
1046  }
1047 
1048  if (out->rt_ == rt) {
1049  // No change in route, no floating-ip found
1050  return;
1051  }
1052 
1053  //Populate in->vn, used for VRF translate ACL lookup
1054  in->vn_ = fip_it->vn_.get();
1055 
1056  // Floating-ip found. We will change src-ip to floating-ip. Recompute route
1057  // for new source-ip. All policy decisions will be based on this new route
1058  UpdateRoute(&in->rt_, fip_it->vrf_.get(), fip_it->floating_ip_, pkt->smac,
1060  if (in->rt_ == NULL) {
1061  return;
1062  }
1063 
1064  underlay_flow = false;
1065  if (VrfTranslate(pkt, in, out, fip_it->floating_ip_, true) == false) {
1066  return;
1067  }
1068  if (out->rt_ == NULL || in->rt_ == NULL) {
1069  //If After VRF translation, ingress route or
1070  //egress route is NULL, mark the flow as short flow
1071  return;
1072  }
1073 
1074  // Compute out-intf and ECMP info from out-route
1075  if (RouteToOutInfo(agent, out->rt_, pkt, this, in, out) == false) {
1076  return;
1077  }
1078 
1079  dest_vrf = out->rt_->vrf_id();
1080  // Setup reverse flow to translate sip.
1081  nat_done = true;
1082  nat_ip_saddr = fip_it->floating_ip_;
1083  nat_ip_daddr = pkt->ip_daddr;
1084  if (fip_it->port_map_enabled()) {
1085  int32_t map_port = fip_it->GetSrcPortMap(pkt->ip_proto, pkt->sport);
1086  if (map_port < 0) {
1087  short_flow = true;
1089  } else {
1090  nat_sport = map_port;
1091  }
1092  } else if (fip_it->port_nat()) {
1093  FlowKey key(in->nh_, pkt->ip_saddr, pkt->ip_daddr, pkt->ip_proto,
1094  pkt->sport, pkt->dport);
1095  if (fip_it->floating_ip_ == pkt->ip_daddr) {
1096  nat_sport = pkt->sport;
1097  nat_ip_saddr = intf->mdata_ip_addr();
1098  } else {
1099  nat_sport =
1101  if (nat_sport == 0) {
1102  short_flow = true;
1104  nat_done = false;
1105  out->nh_ = in->nh_;
1106  return;
1107  } else {
1108  port_allocated = true;
1109  }
1110  }
1111  out->nh_ = agent->vhost_interface()->flow_key_nh()->id();
1112  } else {
1113  nat_sport = pkt->sport;
1114  }
1115  nat_dport = pkt->dport;
1116 
1117  // Compute VRF for reverse flow
1118  if (out->intf_) {
1119  // Egress-vm present on same compute node, take VRF from vm-port
1120  nat_vrf = out->vrf_->vrf_id();
1121  out->vn_ = InterfaceToVn(out->intf_);
1122  } else {
1123  // Egress-vm is remote. Find VRF from the NH for source-ip
1124  nat_vrf = NhToVrf(in->rt_->GetActiveNextHop());
1125  }
1126 
1127  // Dest VRF for reverse flow is In-Port VRF
1128  nat_dest_vrf = in->vrf_->vrf_id();
1129 
1130  flow_source_vrf = pkt->vrf;
1131  if (out->rt_) {
1133  } else {
1135  }
1136  // Update fields required for floating-IP stats accounting
1138  fip_snat = true;
1139  return;
1140 }
1141 
1142 //Check if both source and destination route support Native Encap
1143 //if yes use underlay forwarding (no change)
1144 //Else Do a VRF translate to interface VRF
1146  const PktInfo *pkt,
1147  PktControlInfo *in,
1148  PktControlInfo *out) {
1149 
1150  if (l3_flow == false) {
1151  return;
1152  }
1153 
1154  bool can_be_underlay_flow = false;
1155  if (intf->vrf() && intf->vrf()->forwarding_vrf() &&
1156  intf->vrf()->forwarding_vrf() != intf->vrf()) {
1157  can_be_underlay_flow = true;
1158  }
1159 
1160  //Route needs to be check because out interface might
1161  //not be populated, if destination uses native forwarding
1162  //then also we need to do vrf translate
1163  if (out->rt_) {
1164  const InterfaceNH *intf_nh =
1165  dynamic_cast<const InterfaceNH *>(out->rt_->GetActiveNextHop());
1166  if (intf_nh) {
1167  const Interface *out_itf = intf_nh->GetInterface();
1168  if (out_itf->vrf() && out_itf->vrf()->forwarding_vrf() &&
1169  out_itf->vrf()->forwarding_vrf() != out_itf->vrf()) {
1170  can_be_underlay_flow = true;
1171  }
1172  }
1173  }
1174 
1175  if (can_be_underlay_flow == false) {
1176  return;
1177  }
1178 
1179  const AgentRoute *src_rt = FlowEntry::GetUcRoute(intf->vrf(),
1180  pkt->ip_saddr);
1181  const AgentRoute *dst_rt = FlowEntry::GetUcRoute(intf->vrf(),
1182  pkt->ip_daddr);
1183 
1184  if (src_rt == NULL || dst_rt == NULL) {
1185  overlay_route_not_found = true;
1186  return;
1187  }
1188 
1189  overlay_route_not_found = false;
1190  uint32_t src_tunnel_bmap = src_rt->GetActivePath()->tunnel_bmap();
1191  uint32_t dst_tunnel_bmap = dst_rt->GetActivePath()->tunnel_bmap();
1192 
1193  if ((src_tunnel_bmap & (1 << TunnelType::NATIVE)) &&
1194  (dst_tunnel_bmap & (1 << TunnelType::NATIVE))) {
1195  underlay_flow = true;
1196  //Set policy VRF for route tracking
1197  src_policy_vrf = intf->vrf()->vrf_id();
1198  dst_policy_vrf = intf->vrf()->vrf_id();
1199  src_vn = RouteToVn(src_rt);
1200  dst_vn = RouteToVn(dst_rt);
1201  return;
1202  }
1203 
1204  const VrfEntry *vrf = intf->vrf();
1205  ChangeVrf(pkt, out, vrf);
1206  dest_vrf = vrf->vrf_id();
1207  alias_ip_flow = true;
1208  UpdateRoute(&out->rt_, vrf, pkt->ip_daddr, pkt->dmac,
1210  UpdateRoute(&in->rt_, vrf, pkt->ip_saddr, pkt->smac,
1212 }
1213 
1215  PktControlInfo *in,
1216  PktControlInfo *out) {
1217  if (in->rt_ == NULL || out->rt_ == NULL) {
1218  return;
1219  }
1220 
1221  overlay_route_not_found = false;
1222  const InetUnicastRouteEntry *src =
1223  static_cast<const InetUnicastRouteEntry *>(in->rt_);
1224  const IpAddress src_ip = src->prefix_address();
1225 
1226  const InetUnicastRouteEntry *dst =
1227  static_cast<const InetUnicastRouteEntry *>(out->rt_);
1228  const IpAddress dst_ip = dst->prefix_address();
1229 
1230  uint32_t src_tunnel_bmap = in->rt_->GetActivePath()->tunnel_bmap();
1231  uint32_t dst_tunnel_bmap = out->rt_->GetActivePath()->tunnel_bmap();
1232 
1233  if ((src_tunnel_bmap & (1 << TunnelType::NATIVE)) &&
1234  (dst_tunnel_bmap & (1 << TunnelType::NATIVE))) {
1235 
1236  underlay_flow = true;
1237  src_vn = RouteToVn(in->rt_);
1238  dst_vn = RouteToVn(out->rt_);
1239 
1240  if (nat_done == false) {
1241  src_policy_vrf = in->rt_->vrf()->vrf_id();
1242  }
1243  dst_policy_vrf = out->rt_->vrf()->vrf_id();
1244  const VrfEntry *vrf = agent->fabric_vrf();
1245  ChangeVrf(pkt, out, vrf);
1246  UpdateRoute(&out->rt_, vrf, dst_ip, pkt->dmac,
1248  UpdateRoute(&in->rt_, vrf, src_ip, pkt->smac,
1250  }
1251 }
1252 
1253 void PktFlowInfo::ChangeEncap(const VmInterface *intf, const PktInfo *pkt,
1254  PktControlInfo *in, PktControlInfo *out,
1255  bool nat_flow) {
1256  if (nat_flow) {
1257  ChangeFloatingIpEncap(pkt, in, out);
1258  } else {
1259  ChangeEncapToOverlay(intf, pkt, in, out);
1260  }
1261 }
1262 
1264  PktControlInfo *out, const IpAddress &src_ip,
1265  bool nat_flow) {
1266  const Interface *intf = NULL;
1267  if (ingress) {
1268  intf = in->intf_;
1269  } else {
1270  intf = out->intf_;
1271  }
1272  if (!intf || intf->type() != Interface::VM_INTERFACE) {
1273  return true;
1274  }
1275 
1276  const VmInterface *vm_intf = static_cast<const VmInterface *>(intf);
1277  //If interface has a VRF assign rule, choose the acl and match the
1278  //packet, else get the acl attached to VN and try matching the packet to
1279  //network acl
1280 
1281  ChangeEncap(vm_intf, pkt, in, out, nat_flow);
1282 
1283  const AclDBEntry *acl = NULL;
1284  if (nat_flow == false) {
1285  acl = vm_intf->vrf_assign_acl();
1286  }
1287  //In case of floating IP translation, dont apply
1288  //interface VRF assign rule
1289  if (acl == NULL) {
1290  if (ingress && in->vn_) {
1291  //Check if the network ACL is present
1292  acl = in->vn_->GetAcl();
1293  } else if (out->vn_) {
1294  acl = out->vn_->GetAcl();
1295  }
1296  }
1297 
1298  if (!acl) {
1299  return true;
1300  }
1301 
1302  PacketHeader hdr;
1303  hdr.vrf = pkt->vrf;
1304  hdr.src_ip = src_ip;
1305  hdr.dst_ip = pkt->ip_daddr;
1306 
1307  hdr.protocol = pkt->ip_proto;
1308  if (hdr.protocol == IPPROTO_UDP || hdr.protocol == IPPROTO_TCP) {
1309  hdr.src_port = pkt->sport;
1310  hdr.dst_port = pkt->dport;
1311  } else {
1312  hdr.src_port = 0;
1313  hdr.dst_port = 0;
1314  }
1315  hdr.src_policy_id = RouteToVn(in->rt_);
1316  hdr.dst_policy_id = RouteToVn(out->rt_);
1317 
1318  if (underlay_flow) {
1319  hdr.src_policy_id = src_vn;
1320  hdr.dst_policy_id = dst_vn;
1321  }
1322 
1323  if (in->rt_) {
1324  const AgentPath *path = in->rt_->GetActivePath();
1325  hdr.src_sg_id_l = &(path->sg_list());
1326  }
1327  if (out->rt_) {
1328  const AgentPath *path = out->rt_->GetActivePath();
1329  hdr.dst_sg_id_l = &(path->sg_list());
1330  }
1331 
1332  MatchAclParams match_acl_param;
1333  if (!acl->PacketMatch(hdr, match_acl_param, NULL)) {
1334  return true;
1335  }
1336 
1337  if (match_acl_param.action_info.vrf_translate_action_.vrf_name() != "") {
1338  VrfKey key(match_acl_param.action_info.vrf_translate_action_.vrf_name());
1339  const VrfEntry *vrf = static_cast<const VrfEntry*>
1340  (agent->vrf_table()->FindActiveEntry(&key));
1341  if (vrf == NULL) {
1342  short_flow = true;
1344  in->rt_ = NULL;
1345  out->rt_ = NULL;
1346  return false;
1347  }
1348 
1349  ChangeVrf(pkt, out, vrf);
1350  UpdateRoute(&out->rt_, vrf, pkt->ip_daddr, pkt->dmac,
1352  UpdateRoute(&in->rt_, vrf, hdr.src_ip, pkt->smac,
1354  underlay_flow = false;
1355  }
1356  return true;
1357 }
1358 
1359 // Changes VRF of in/out routes in case of DNAT and
1360 // VRF NH pointing to Interface NH in the routing VRF instance
1362  PktControlInfo *out) {
1363  if (out == NULL ||
1364  in == NULL ||
1365  out->rt_ == NULL ||
1366  in->vrf_ == NULL ||
1367  in->vrf_->routing_vrf()) {
1368  return;
1369  }
1370 
1371  const NextHop *nh = out->rt_->GetActiveNextHop();
1372  if (nh == NULL || nh->GetType() != NextHop::VRF) {
1373  return;
1374  }
1375 
1376  const VrfNH *vrf_nh = static_cast<const VrfNH *>(nh);
1377  const VrfEntry *vrf = vrf_nh->GetVrf();
1378  if (vrf == NULL || vrf->routing_vrf() == false) {
1379  return;
1380  }
1381 
1382  InetUnicastRouteEntry *inet_rt = vrf->GetUcRoute(pkt->ip_daddr);
1383  const NextHop *rt_nh = inet_rt ?
1384  inet_rt->GetActiveNextHop() : NULL;
1385  if (rt_nh == NULL || (rt_nh->GetType() != NextHop::INTERFACE && rt_nh->GetType() != NextHop::COMPOSITE)) {
1386  return;
1387  }
1388 
1389  if (rt_nh->GetType() == NextHop::INTERFACE){
1390  const Interface *intf = static_cast<const InterfaceNH*>
1391  (rt_nh)->GetInterface();
1392  if (intf == NULL || intf->type() != Interface::VM_INTERFACE ||
1393  static_cast<const VmInterface*>(intf)->FloatingIpCount() == 0) {
1394  return;
1395  }
1396  }
1397  if (rt_nh->GetType() == NextHop::COMPOSITE){
1398  const CompositeNH *composite_nh = static_cast<const CompositeNH*>(rt_nh);
1399  uint32_t comp_nh_count = composite_nh->ComponentNHCount();
1400  for (uint32_t i=0; i < comp_nh_count; i++) {
1401  const NextHop * c_nh = composite_nh->GetNH(i);
1402  if (c_nh == NULL){
1403  continue;
1404  } else {
1405  const Interface *intf = static_cast<const InterfaceNH*>(c_nh)->GetInterface();
1406  if (intf == NULL || intf->type() != Interface::VM_INTERFACE ||
1407  static_cast<const VmInterface*>(intf)->FloatingIpCount() == 0) {
1408  return;
1409  }
1410  }
1411  }
1412  }
1413 
1414  ChangeVrf(pkt, out, vrf);
1415  UpdateRoute(&out->rt_, vrf, pkt->ip_daddr, pkt->dmac,
1417  UpdateRoute(&in->rt_, vrf, pkt->ip_saddr, pkt->smac,
1419 }
1420 
1422  PktControlInfo *out) {
1423  // Flow packets are expected only on VMPort interfaces
1424  if (in->intf_->type() != Interface::VM_INTERFACE &&
1425  in->intf_->type() != Interface::INET) {
1426  LogError(pkt, this, "Unexpected packet on Non-VM interface");
1427  return;
1428  }
1429 
1430  const VmInterface *vm_port =
1431  dynamic_cast<const VmInterface *>(in->intf_);
1432  if (vm_port != NULL) {
1433  VrfEntry *alias_vrf = vm_port->GetAliasIpVrf(pkt->ip_saddr);
1434  if (alias_vrf != NULL) {
1435  in->vrf_ = alias_vrf;
1436  // translate to alias ip vrf for destination, unless overriden by
1437  // translation due to NAT or ACL
1438  dest_vrf = alias_vrf->vrf_id();
1439  alias_ip_flow = true;
1440  }
1441  }
1442 
1443  // We always expect route for source-ip for ingress flows.
1444  // If route not present, return from here so that a short flow is added
1445  UpdateRoute(&in->rt_, in->vrf_, pkt->ip_saddr, pkt->smac,
1447  in->vn_ = InterfaceToVn(in->intf_);
1448 
1449  // Consider linklocal service requests as l3 always
1451 
1452  // Compute Out-VRF and Route for dest-ip
1453  out->vrf_ = in->vrf_;
1454  UpdateRoute(&out->rt_, out->vrf_, pkt->ip_daddr, pkt->dmac,
1456 
1457  // Change VRF if a packet travels between a bridge and the
1458  // routing VRF instances with destination pointed by FIP
1459  NatVxlanVrfTranslate(pkt, in, out);
1460 
1461  //Native VRF of the interface and acl assigned vrf would have
1462  //exact same route with different nexthop, hence if both ingress
1463  //route and egress route are present in native vrf, acl match condition
1464  //can be applied
1465  if (VrfTranslate(pkt, in, out, pkt->ip_saddr, false) == false) {
1466  return;
1467  }
1468 
1469  if (out->rt_) {
1470  // Compute out-intf and ECMP info from out-route
1471  if (RouteToOutInfo(agent, out->rt_, pkt, this, in, out)) {
1472  if (out->intf_) {
1473  out->vn_ = InterfaceToVn(out->intf_);
1474  //In case of alias IP destination VRF would
1475  //be already while NHDecode or if its underlay
1476  //to overlay transition then encap change takes
1477  //care of it.
1478  //In case of VM using ip-fabric for forwarding
1479  //NH would be set with VRF as ip-fabric which
1480  //would mean local IPV6 traffic would be forwarded
1481  //in ip-fabric VRF which is not needed
1482  if (out->vrf_ && alias_ip_flow == false) {
1483  dest_vrf = out->vrf_->vrf_id();
1484  }
1485  }
1486  }
1487  }
1488 
1490  out->rt_,
1491  pkt->sport,
1492  pkt->dport,
1493  in->intf_)) {
1494  // If interface has floating IP, check if we have more specific route in
1495  // public VN (floating IP)
1496  if (l3_flow && IntfHasFloatingIp(this, in->intf_, pkt->family)) {
1497  FloatingIpSNat(pkt, in, out);
1498  }
1499  }
1500 
1501  if (out->rt_ != NULL) {
1502  // Route is present. If IP-DA is a floating-ip, we need DNAT
1503  if (RouteToOutInfo(agent, out->rt_, pkt, this, in, out)) {
1504  if (out->intf_ && IntfHasFloatingIp(this, out->intf_, pkt->family)) {
1505  FloatingIpDNat(pkt, in, out);
1506  }
1507  }
1508  }
1509 
1510  // Packets needing linklocal service will have route added by LinkLocal peer
1511  if ((in->rt_ && IsLinkLocalRoute(agent, in->rt_, pkt->sport, pkt->dport)) ||
1512  (out->rt_ && IsLinkLocalRoute(agent, out->rt_,
1513  pkt->sport, pkt->dport))) {
1514  LinkLocalServiceTranslate(pkt, in, out);
1515  }
1516 
1517  //Packets needing bgp router service handling
1518  if (IsBgpRouterServiceRoute(in->rt_, out->rt_,
1519  in->intf_, pkt->sport,
1520  pkt->dport)) {
1521  BgpRouterServiceTranslate(pkt, in, out);
1522  }
1523 
1524  // If out-interface was not found, get it based on out-route
1525  if (out->intf_ == NULL && out->rt_) {
1526  RouteToOutInfo(agent, out->rt_, pkt, this, in, out);
1527  }
1528  if (out->rt_) {
1529  const NextHop* nh = out->rt_->GetActiveNextHop();
1530  if (nh && nh->GetType() == NextHop::COMPOSITE) {
1531  const CompositeNH *comp_nh = static_cast<const CompositeNH *>(nh);
1532  nh = comp_nh->GetNH(out_component_nh_idx);
1533  }
1534 
1535  if (nh && nh->GetType() == NextHop::TUNNEL) {
1536  const TunnelNH* tunnel_nh = static_cast<const TunnelNH *>(nh);
1537  const Ip4Address *ip = tunnel_nh->GetDip();
1538  if (ip) {
1539  peer_vrouter = ip->to_string();
1540  tunnel_type = tunnel_nh->GetTunnelType();
1541  }
1542  } else {
1543  peer_vrouter = agent->router_id().to_string();
1544  }
1545  }
1546 
1547  //In case of distributed SNAT we dont want policy to be applied based
1548  //on translated FIP route. hence change ingress route to VM's actual
1549  //route and also the source policy VRF
1550  if (port_allocated && short_flow == false) {
1551  UpdateRoute(&in->rt_, in->vrf_, pkt->ip_saddr, pkt->smac,
1553  in->vn_ = InterfaceToVn(in->intf_);
1554  src_policy_vrf = in->intf_->vrf()->vrf_id();
1555  }
1556 
1557  return;
1558 }
1559 
1561  tunnel_type = pkt->tunnel.type;
1564  MplsLabel *mpls = agent->mpls_table()->FindMplsLabel(pkt->tunnel.label);
1565  if (mpls == NULL) {
1566  LogError(pkt, this, "Invalid Label in egress flow");
1567  return NULL;
1568  }
1569  return mpls->nexthop();
1570  } else if (tunnel_type.GetType() == TunnelType::VXLAN) {
1571  VxLanTable *table = static_cast<VxLanTable *>(agent->vxlan_table());
1572  VxLanId *vxlan = table->FindNoLock(pkt->tunnel.vxlan_id);
1573  if (vxlan == NULL) {
1574  LogError(pkt, this, "Invalid vxlan in egress flow");
1575  return NULL;
1576  }
1577 
1578  const VrfNH *nh = dynamic_cast<const VrfNH *>(vxlan->nexthop());
1579  if (nh == NULL)
1580  return NULL;
1581 
1582  const VrfEntry *vrf = nh->GetVrf();
1583  if (vrf == NULL)
1584  return NULL;
1585 
1586  AgentRoute *rt = NULL;
1587  if (vrf->vn()->vxlan_routing_vn()) {
1588  rt = FlowEntry::GetUcRoute(vrf, pkt->ip_daddr);
1589  } else {
1590  // In case of VXLAN, the NH points to VrfNH. Need to do route lookup
1591  // on dmac to find the real nexthop
1592  rt = FlowEntry::GetL2Route(vrf, pkt->dmac);
1593  }
1594  if (rt != NULL) {
1595  return rt->GetActiveNextHop();
1596  }
1597 
1598  return NULL;
1599  } else {
1601  pkt->ip_daddr);
1602  if (rt != NULL) {
1603  return rt->GetActiveNextHop();
1604  }
1605 
1606 
1607  LogError(pkt, this, "Invalid tunnel type in egress flow");
1608  return NULL;
1609  }
1610 
1611  return NULL;
1612 }
1613 
1615  PktControlInfo *out) {
1616  peer_vrouter = Ip4Address(pkt->tunnel.ip_saddr).to_string();
1617 
1618  const NextHop *nh = TunnelToNexthop(pkt);
1619  if (nh == NULL) {
1620  return;
1621  }
1622  if((nh->GetType() == NextHop::ARP) && (l3_flow == false)) {
1623  LOG(ERROR, "PktFlowInfo::EgressProcess: ARP nexthop and l3_flow "
1624  " false, DROP this frame. module " << pkt->module << " type "
1625  << pkt->type << " family " << pkt->family << " vrf " <<pkt->vrf
1626  << " tunnel_type " << pkt->tunnel.type.GetType()<< " ifindex "
1627  << pkt->agent_hdr.ifindex << " sip " << pkt->ip_saddr.to_string()
1628  << " dip " << pkt->ip_daddr.to_string() << " proto " << pkt->ip_proto
1629  << " sport " << pkt->sport << " dport " <<pkt->dport<<" l3_label "
1630  << pkt->l3_label);
1631  return;
1632  }
1633  const CompositeNH *comp_nh = dynamic_cast<const CompositeNH *>(nh);
1634  EcmpLoadBalance ecmp_load_balance;
1635  if (comp_nh != NULL) {
1636  UpdateRoute(&out->rt_, comp_nh->vrf(), pkt->ip_daddr, pkt->dmac,
1638  if (out->rt_ && out->rt_->GetActivePath()) {
1639  ecmp_load_balance = out->rt_->GetActivePath()->ecmp_load_balance();
1640  }
1641  }
1642 
1643  //Delay hash pick up till route is picked.
1644  if (NhDecode(agent, nh, pkt, this, in, out, true,
1645  ecmp_load_balance) == false) {
1646  return;
1647  }
1648 
1649  if (out->intf_ && out->intf_->type() == Interface::VM_INTERFACE) {
1650  const VmInterface *vm_intf = static_cast<const VmInterface *>(out->intf_);
1651  if (vm_intf->IsFloatingIp(pkt->ip_daddr)) {
1652  l3_flow = true;
1653  } else {
1654  VrfEntry *alias_vrf = vm_intf->GetAliasIpVrf(pkt->ip_daddr);
1655  if (alias_vrf != NULL) {
1656  out->vrf_ = alias_vrf;
1657  // translate to alias ip vrf for destination, unless overriden by
1658  // translation due to NAT or ACL
1659  dest_vrf = alias_vrf->vrf_id();
1660  alias_ip_flow = true;
1661  }
1662  }
1663  }
1664 
1665  if (out->vrf_ == NULL) {
1666  return;
1667  }
1668 
1669  UpdateRoute(&out->rt_, out->vrf_, pkt->ip_daddr, pkt->dmac,
1671  UpdateRoute(&in->rt_, out->vrf_, pkt->ip_saddr, pkt->smac,
1673 
1674  if (out->intf_) {
1675  out->vn_ = InterfaceToVn(out->intf_);
1676  }
1677 
1678  //Apply vrf translate ACL to get ingress route
1679  if (VrfTranslate(pkt, in, out, pkt->ip_saddr, false) == false) {
1680  return;
1681  }
1682 
1684  out->rt_,
1685  pkt->sport,
1686  pkt->dport,
1687  out->intf_)) {
1688  // If interface has floating IP, check if destination is one of the
1689  // configured floating IP.
1690  if (IntfHasFloatingIp(this, out->intf_, pkt->family)) {
1691  FloatingIpDNat(pkt, in, out);
1692  }
1693  }
1694 
1695  if (out->rt_) {
1696  if (ecmp && out->rt_->GetActivePath()) {
1697  const CompositeNH *comp_nh = static_cast<const CompositeNH *>(nh);
1699  out_component_nh_idx = comp_nh->hash(pkt->
1700  hash(agent, out->rt_->GetActivePath()->
1701  ecmp_load_balance()), ingress);
1702  }
1703  }
1704  const NextHop *anh = out->rt_->GetActiveNextHop();
1705  if ((anh) && (anh->GetType() == NextHop::ARP ||
1706  anh->GetType() == NextHop::RESOLVE)) {
1707  //If a packet came with mpls label pointing to
1708  //vrf NH, then we need to do a route lookup
1709  //and set the nexthop for reverse flow properly
1710  //as mpls pointed NH would not be used for reverse flow
1711  if (RouteToOutInfo(agent, out->rt_, pkt, this, in, out)) {
1712  if (out->intf_) {
1713  out->vn_ = InterfaceToVn(out->intf_);
1714  }
1715  }
1716  }
1717  }
1718 
1719  return;
1720 }
1721 
1723  const PktControlInfo *in,
1724  const PktControlInfo *out) {
1725  bool ret = false;
1726  if (ingress && out->rt_ == NULL && in->rt_) {
1727  const VmInterface *vm_intf =
1728  static_cast<const VmInterface *>(in->intf_);
1729  //If interface has flag to flood unknown unicast
1730  //and destination route is not present
1731  //mark the flow for forward
1732  if (vm_intf->flood_unknown_unicast()) {
1733  flood_unknown_unicast = true;
1735  static_cast<const AgentRoute *>(in->rt_)->vrf_id();
1736  ret = true;
1737  }
1738  } else if (in->rt_ == NULL && out->rt_) {
1739  //This packet should not be ideally trapped
1740  //from vrouter for flow setup.
1741  //VxLAN nexthop would be set with flag
1742  //to flood multicast, hence we would
1743  //hit all broadcast multicast route and
1744  //packet would never be trapped for flow setup
1745  tunnel_type = pkt->tunnel.type;
1747  VxLanTable *table = static_cast<VxLanTable *>(agent->vxlan_table());
1748  VxLanId *vxlan = table->FindNoLock(pkt->tunnel.vxlan_id);
1749  if (vxlan && vxlan->nexthop()) {
1750  const VrfNH *vrf_nh =
1751  static_cast<const VrfNH *>(vxlan->nexthop());
1752  if (vrf_nh->flood_unknown_unicast()) {
1754  static_cast<const AgentRoute *>(out->rt_)->vrf_id();
1755  flood_unknown_unicast = true;
1756  ret = true;
1757  }
1758  }
1759  }
1760  }
1761  return ret;
1762 }
1763 
1764 // Ignore in case of BFD health check
1765 bool IsValidationDisabled(Agent *agent, const PktInfo *pkt,
1766  const Interface *interface) {
1767  if (!interface)
1768  return false;
1769  return ((agent->pkt()->pkt_handler()->
1770  IsBFDHealthCheckPacket(pkt, interface)) ||
1771  (agent->pkt()->pkt_handler()->
1772  IsSegmentHealthCheckPacket(pkt, interface)));
1773 }
1774 
1775 // Basic config validations for the flow
1778 
1779  if (agent->tsn_enabled()) {
1780  short_flow = true;
1782  return false;
1783  }
1784 
1785  if (in->intf_ == NULL) {
1786  LogError(pkt, this, "Invalid interface");
1787  short_flow = true;
1789  return false;
1790  }
1791 
1792  const VmInterface *vm_intf = dynamic_cast<const VmInterface *>(in->intf_);
1793  if (l3_flow == true && !disable_validation) {
1794  if (vm_intf && in->intf_->ip_active(pkt->family) == false &&
1795  (pkt->ip_saddr.is_v6() && !pkt->ip_saddr.to_v6().is_link_local()) &&
1796  (pkt->ip_daddr.is_v6() && !pkt->ip_daddr.to_v6().is_link_local())) {
1797  in->intf_ = NULL;
1798  LogError(pkt, this, "IP protocol inactive on interface");
1799  short_flow = true;
1801  return false;
1802  }
1803 
1804  if (vm_intf && vm_intf->layer3_forwarding() == false) {
1805  LogError(pkt, this, "IP service not enabled for interface");
1806  short_flow = true;
1808  return false;
1809  }
1810  }
1811 
1812  if (l3_flow == false && !disable_validation) {
1813  if (in->intf_->l2_active() == false) {
1814  in->intf_ = NULL;
1815  LogError(pkt, this, "L2 inactive on interface");
1816  short_flow = true;
1818  return false;
1819  }
1820 
1821  if (vm_intf && vm_intf->bridging() == false) {
1822  LogError(pkt, this, "Bridge service not enabled for interface");
1823  short_flow = true;
1825  return false;
1826  }
1827  }
1828 
1829  if (in->vrf_ == NULL || in->vrf_->IsActive() == false) {
1830  in->vrf_ = NULL;
1831  LogError(pkt, this, "Invalid or Inactive VRF");
1832  short_flow = true;
1834  return false;
1835  }
1836 
1837  return true;
1838 }
1839 
1841  PktControlInfo *out) {
1842  in->intf_ = agent->interface_table()->FindInterface(pkt->agent_hdr.ifindex);
1843  out->nh_ = in->nh_ = pkt->agent_hdr.nh;
1844  in->vrf_ = agent->vrf_table()->FindVrfFromId(pkt->agent_hdr.vrf);
1845 
1846  if (ValidateConfig(pkt, in) == false) {
1847  return false;
1848  }
1849 
1850  //By default assume destination vrf and source vrf to be same
1851  dest_vrf = pkt->vrf;
1852  // Compute direction of flow based on in-interface
1854  if (ingress) {
1855  IngressProcess(pkt, in, out);
1856  } else {
1857  EgressProcess(pkt, in, out);
1858  }
1859 
1860  if (l3_flow == false) {
1861  if (UnknownUnicastFlow(pkt, in, out) == true) {
1862  return true;
1863  }
1864  }
1865 
1866  if (nat_done && ((pkt->ignore_address == VmInterface::IGNORE_SOURCE) ||
1867  (pkt->ignore_address == VmInterface::IGNORE_DESTINATION) || (pkt->is_fat_flow_src_prefix) ||
1868  (pkt->is_fat_flow_dst_prefix))) {
1869  /* Fat flow not supported for NAT flows */
1870  LogError(pkt, this, "Flow : Fat-flow and NAT cannot co-exist");
1871  short_flow = true;
1873  return false;
1874  }
1875 
1876  if (!disable_validation) {
1877  if (in->rt_ == NULL || in->rt_->IsDeleted()) {
1878  LogError(pkt, this, "Flow : No route for Src-IP");
1879  short_flow = true;
1881  return false;
1882  }
1883 
1884  if (out->rt_ == NULL || out->rt_->IsDeleted()) {
1885  LogError(pkt, this, "Flow : No route for Dst-IP");
1886  short_flow = true;
1888  return false;
1889  }
1890 
1891  flow_source_vrf = static_cast<const AgentRoute *>(in->rt_)->vrf_id();
1892  flow_dest_vrf = out->rt_->vrf_id();
1893  } else {
1895  }
1896 
1898  LogError(pkt, this, "Flow : Overlay route not found");
1899  short_flow = true;
1901  return false;
1902  }
1903 
1904  //If source is ECMP, establish a reverse flow pointing
1905  //to the component index
1906  if (in->rt_ && in->rt_->GetActiveNextHop() &&
1908  ecmp = true;
1909  }
1910 
1911  if (out->rt_ && out->rt_->GetActiveNextHop() &&
1913  ecmp = true;
1914  }
1915 
1916  return true;
1917 }
1918 
1919 // A flow can mean that traffic is seen on an interface. The path preference
1920 // module can potentially be interested in this event. Check and generate
1921 // traffic seen event
1923  const PktControlInfo *in) {
1924  // Traffic seen should not be generated for MESSAGE
1925  if (pkt->type == PktType::MESSAGE) {
1926  return;
1927  }
1928 
1929  // Dont generate Traffic seen for egress flows or short or linklocal flows
1930  if (ingress == false || short_flow || linklocal_flow) {
1931  return;
1932  }
1933 
1934  // TODO : No need for one more route lookup
1935  const AgentRoute *rt = NULL;
1936  bool enqueue_traffic_seen = false;
1937  const VmInterface *vm_intf = dynamic_cast<const VmInterface *>(in->intf_);
1938 
1939  IpAddress sip = pkt->ip_saddr;
1940  if (pkt->family == Address::INET ||
1941  pkt->family == Address::INET6) {
1942  if (l3_flow) {
1943  rt = in->rt_;
1944  } else if (in->vrf_) {
1945  rt = FlowEntry::GetUcRoute(in->vrf_, sip);
1946  }
1947  }
1948  uint8_t plen = 0;
1949  // Generate event if route was waiting for traffic
1950  if (rt && rt->WaitForTraffic()) {
1951  enqueue_traffic_seen = true;
1952  plen = rt->prefix_length();
1953  } else if (vm_intf) {
1954  //L3 route is not in wait for traffic state
1955  //EVPN route could be in wait for traffic, if yes
1956  //enqueue traffic seen
1957  rt = FlowEntry::GetEvpnRoute(in->vrf_, pkt->smac, sip,
1958  vm_intf->ethernet_tag());
1959  if (rt && rt->WaitForTraffic()) {
1960  const EvpnRouteEntry *evpn_rt = static_cast<const EvpnRouteEntry *>
1961  (rt);
1962  plen = evpn_rt->prefix_length();
1963  enqueue_traffic_seen = true;
1964  } else {
1965  IpAddress addr;
1966  rt = FlowEntry::GetEvpnRoute(in->vrf_, pkt->smac, addr,
1967  vm_intf->ethernet_tag());
1968  if (rt && rt->WaitForTraffic()) {
1969  plen = 32;
1970  if (pkt->family == Address::INET6) {
1971  plen = 128;
1972  }
1973  enqueue_traffic_seen = true;
1974  }
1975  }
1976 
1977  }
1978 
1979  if (enqueue_traffic_seen) {
1981  EnqueueTrafficSeen(sip, plen, in->intf_->id(),
1982  pkt->vrf, pkt->smac);
1983  }
1984 }
1985 
1986 // Apply flow limits for in and out VMs
1988  const PktControlInfo *out) {
1989  // Ignore flow limit checks for flow-update and short-flows
1990  if (short_flow || pkt->type == PktType::MESSAGE) {
1991  return;
1992  }
1993 
1994  bool limit_exceeded = false;
1995  uint32_t vmi_max_flows;
1996  if (in->intf_ && (in->intf_->type() == Interface::VM_INTERFACE)) {
1997  const VmInterface *vm_intf =
1998  dynamic_cast<const VmInterface *>(in->intf_);
1999  if (vm_intf) {
2000  uint32_t maxv = std::max(vm_intf->max_flows(),
2002  uint32_t minv = std::min(vm_intf->max_flows(),
2004  vmi_max_flows =
2005  minv * (vm_intf->max_flows() != FLOWS_LIMIT_UNLIMITED &&
2007  maxv * ((vm_intf->max_flows() != FLOWS_LIMIT_UNLIMITED) !=
2009  if (vmi_max_flows != FLOWS_LIMIT_UNLIMITED) {
2010  if ((vm_intf->flow_count() + 2) > vmi_max_flows) {
2011  limit_exceeded = true;
2012  }
2013  }
2014  }
2015  }
2016 
2017  if (out->intf_ && (out->intf_->type() == Interface::VM_INTERFACE)) {
2018  const VmInterface *vm_intf =
2019  dynamic_cast<const VmInterface *>(out->intf_);
2020  if (vm_intf) {
2021  uint32_t maxv = std::max(vm_intf->max_flows(),
2023  uint32_t minv = std::min(vm_intf->max_flows(),
2025  vmi_max_flows =
2026  minv * (vm_intf->max_flows() != FLOWS_LIMIT_UNLIMITED &&
2028  maxv * ((vm_intf->max_flows() != FLOWS_LIMIT_UNLIMITED) !=
2030  if (vmi_max_flows != FLOWS_LIMIT_UNLIMITED) {
2031  if ((vm_intf->flow_count() + 2) > vmi_max_flows) {
2032  limit_exceeded = true;
2033  }
2034  }
2035  }
2036  }
2037 
2038  if (agent->max_vm_flows() && (!limit_exceeded) &&
2039  (in->vm_ && ((in->vm_->flow_count() + 2) > agent->max_vm_flows()))) {
2040  limit_exceeded = true;
2041  }
2042 
2043  if (agent->max_vm_flows() && (!limit_exceeded) &&
2044  (out->vm_ && ((out->vm_->flow_count() + 2) > agent->max_vm_flows()))) {
2045  limit_exceeded = true;
2046  }
2047 
2048  if (limit_exceeded) {
2050  short_flow = true;
2052  return;
2053  }
2054 
2055  if (linklocal_bind_local_port == false)
2056  return;
2057 
2058  // Apply limits for link-local flows
2061  limit_exceeded = true;
2062  }
2063 
2064  // Check per-vm linklocal flow-limits if specified
2065  if ((agent->params()->linklocal_vm_flows() !=
2067  if (in->vm_ && in->vm_->linklocal_flow_count() >=
2069  limit_exceeded = true;
2070  }
2071  }
2072 
2073  if (limit_exceeded) {
2075  short_flow = true;
2077  return;
2078  }
2079 
2080  return;
2081 }
2082 
2084  const PktControlInfo *in,
2085  FlowEntry *flow) {
2086  assert(flow->in_vm_flow_ref()->fd() == VmFlowRef::kInvalidFd);
2087  if (linklocal_bind_local_port == false)
2088  return;
2089 
2090  // link-local service flow. Initialize nat-sport to original src-port.
2091  // It will be over-ridden if socket could be allocated later
2092  nat_sport = pkt->sport;
2093 
2094  // Dont allocate FD for short flows
2095  if (short_flow)
2096  return;
2097 
2098  if (flow->in_vm_flow_ref()->AllocateFd(agent, pkt->ip_proto) == false) {
2099  // Could not allocate FD. Make it short flow
2101  short_flow = true;
2103  return;
2104  }
2105  nat_sport = flow->in_vm_flow_ref()->port();
2106 
2107  return;
2108 }
2109 
2111  Agent *agent = flow_table->agent();
2113  FlowEntryPtr flow = imgr->FindByIndex(pkt->agent_hdr.cmd_param);
2115  flow_table->table_index());
2116 
2117  /* Enqueue stats update request with UUID of the flow */
2118  if (flow.get() && flow->deleted() == false) {
2119  mgr->FlowStatsUpdateEvent(flow.get(), pkt->agent_hdr.cmd_param_2,
2120  pkt->agent_hdr.cmd_param_3,
2121  pkt->agent_hdr.cmd_param_4, flow->uuid());
2122  }
2123 }
2124 
2126  PktControlInfo *out) {
2127  bool update = false;
2128  if (pkt->type != PktType::MESSAGE &&
2129  pkt->agent_hdr.cmd == AgentHdr::TRAP_FLOW_MISS) {
2130  if (pkt->agent_hdr.cmd_param != FlowEntry::kInvalidFlowHandle) {
2132  }
2133  }
2134 
2135  if ((pkt->type == PktType::MESSAGE &&
2136  pkt->agent_hdr.cmd == AgentHdr::TRAP_FLOW_MISS)) {
2137  update = true;
2138  }
2139 
2140  // Generate traffic seen event for path preference module
2141  GenerateTrafficSeen(pkt, in);
2142  IpAddress sip = pkt->ip_saddr;
2143  IpAddress dip = pkt->ip_daddr;
2144  if (pkt->ignore_address == VmInterface::IGNORE_SOURCE) {
2145  if (ingress) {
2146  sip = FamilyToAddress(pkt->family);
2147  } else {
2148  dip = FamilyToAddress(pkt->family);
2149  }
2150  } else if (pkt->ignore_address == VmInterface::IGNORE_DESTINATION) {
2151  if (ingress) {
2152  dip = FamilyToAddress(pkt->family);
2153  } else {
2154  sip = FamilyToAddress(pkt->family);
2155  }
2156  }
2157 
2158  if (pkt->is_fat_flow_src_prefix) {
2159  sip = pkt->ip_ff_src_prefix;
2160  }
2161  if (pkt->is_fat_flow_dst_prefix) {
2162  dip = pkt->ip_ff_dst_prefix;
2163  }
2164 
2165  FlowKey key(in->nh_, sip, dip, pkt->ip_proto, pkt->sport, pkt->dport);
2167 
2168  ApplyFlowLimits(in, out);
2169  LinkLocalPortBind(pkt, in, flow.get());
2170 
2171  // rflow for newly allocated entry should always be NULL
2172  FlowEntryPtr rflow = flow->reverse_flow_entry();
2173  assert(rflow == NULL);
2174 
2175  uint16_t r_sport;
2176  uint16_t r_dport;
2177  if ((pkt->family == Address::INET && pkt->ip_proto == IPPROTO_ICMP) ||
2178  (pkt->family == Address::INET6 && pkt->ip_proto == IPPROTO_ICMPV6)) {
2179  r_sport = pkt->sport;
2180  r_dport = pkt->dport;
2181  } else if (nat_done) {
2182  r_sport = nat_dport;
2183  r_dport = nat_sport;
2184  } else {
2185  r_sport = pkt->dport;
2186  r_dport = pkt->sport;
2187  }
2188 
2189  // Allocate reverse flow
2190  if (nat_done) {
2191  FlowKey rkey(out->nh_, nat_ip_daddr, nat_ip_saddr, pkt->ip_proto,
2192  r_sport, r_dport);
2193  rflow = FlowEntry::Allocate(rkey, flow_table);
2194  } else {
2195  if (pkt->same_port_number && (in->nh_ == out->nh_)) {
2196  /* When source and destination ports are same and FatFlow is
2197  * configured for that port, always mask source port for both
2198  * forward and reverse flows */
2199  r_sport = pkt->sport;
2200  r_dport = pkt->dport;
2201  }
2202  FlowKey rkey(out->nh_, dip, sip, pkt->ip_proto, r_sport, r_dport);
2203  rflow = FlowEntry::Allocate(rkey, flow_table);
2204  }
2205 
2206  bool swap_flows = false;
2207  // If this is message processing, then retain forward and reverse flows
2208  if (pkt->type == PktType::MESSAGE && !short_flow &&
2210  // for cases where we need to swap flows rflow should always
2211  // be Non-NULL
2212  assert(rflow != NULL);
2213  swap_flows = true;
2214  }
2215 
2216  tcp_ack = pkt->tcp_ack;
2217  flow->InitFwdFlow(this, pkt, in, out, rflow.get(), agent);
2218  if (rflow != NULL) {
2219  rflow->InitRevFlow(this, pkt, out, in, flow.get(), agent);
2220  }
2221 
2222  flow->GetPolicyInfo();
2223  if (rflow != NULL) {
2224  rflow->GetPolicyInfo();
2225  }
2226 
2227  flow->ResyncFlow();
2228  if (rflow != NULL) {
2229  rflow->ResyncFlow();
2230  }
2231 
2232  // RPF computation can be done only after policy processing.
2233  // Do RPF computation now
2234  flow->RpfUpdate();
2235  if (rflow)
2236  rflow->RpfUpdate();
2237 
2238  /* Fip stats info in not updated in InitFwdFlow and InitRevFlow because
2239  * both forward and reverse flows are not not linked to each other yet.
2240  * We need both forward and reverse flows to update Fip stats info */
2241  UpdateFipStatsInfo(flow.get(), rflow.get(), pkt, in, out);
2242 
2243  FlowEntry *tmp = swap_flows ? rflow.get() : flow.get();
2244  if (update) {
2245  agent->pkt()->get_flow_proto()->UpdateFlow(tmp);
2246  } else {
2247  agent->pkt()->get_flow_proto()->AddFlow(tmp);
2248  }
2249 }
2250 
2252  (FlowEntry *flow, FlowEntry *rflow, const PktInfo *pkt,
2253  const PktControlInfo *in, const PktControlInfo *out) {
2254 
2255  if (pkt->family != Address::INET) {
2256  //TODO: v6 handling
2257  return;
2258  }
2259  uint32_t intf_id, r_intf_id;
2260  uint32_t fip, r_fip;
2261  intf_id = Interface::kInvalidIndex;
2262  r_intf_id = Interface::kInvalidIndex;
2263  fip = 0;
2264  r_fip = 0;
2265  if (fip_snat && fip_dnat && rflow != NULL) {
2266  /* This is the case where Source and Destination VMs (part of
2267  * same compute node) have floating-IP assigned to each of them from
2268  * a common VN and then each of these VMs send traffic to other VM by
2269  * addressing the other VM's Floating IP. In this case both SNAT and
2270  * DNAT flags will be set. We identify SNAT and DNAT flows by
2271  * inspecting IP of forward and reverse flows and update Fip stats
2272  * info based on that. */
2273  const FlowKey *nat_key = &(rflow->key());
2274  if (flow->key().src_addr != nat_key->dst_addr) {
2275  //SNAT case
2276  fip = snat_fip.to_v4().to_ulong();
2277  intf_id = in->intf_->id();
2278  } else if (flow->key().dst_addr != nat_key->src_addr) {
2279  //DNAT case
2280  fip = flow->key().dst_addr.to_v4().to_ulong();
2281  intf_id = out->intf_->id();
2282  }
2283  nat_key = &(flow->key());
2284  if (rflow->key().src_addr != nat_key->dst_addr) {
2285  //SNAT case
2286  r_fip = snat_fip.to_v4().to_ulong();
2287  r_intf_id = in->intf_->id();
2288  } else if (rflow->key().dst_addr != nat_key->src_addr) {
2289  //DNAT case
2290  r_fip = rflow->key().dst_addr.to_v4().to_ulong();
2291  r_intf_id = out->intf_->id();
2292  }
2293  } else if (fip_snat) {
2294  fip = r_fip = nat_ip_saddr.to_v4().to_ulong();
2295  intf_id = r_intf_id = in->intf_->id();
2296  } else if (fip_dnat) {
2297  fip = r_fip = pkt->ip_daddr.to_v4().to_ulong();
2298  intf_id = r_intf_id = out->intf_->id();
2299  }
2300 
2301  if (fip_snat || fip_dnat) {
2302  flow->UpdateFipStatsInfo(fip, intf_id, agent);
2303  if (rflow != NULL) {
2304  rflow->UpdateFipStatsInfo(r_fip, r_intf_id, agent);
2305  }
2306  }
2307 }
2308 
2309 void PktFlowInfo::SetPktInfo(boost::shared_ptr<PktInfo> pkt_info) {
2310  family = pkt_info->family;
2311  pkt = pkt_info;
2312  }
2313 
2315  if (pkt->family == Address::INET6) {
2316  return Ip6Address();
2317  }
2318  return Ip4Address();
2319 }
boost::asio::ip::address_v6 Ip6Address
Definition: address.h:15
boost::asio::ip::address IpAddress
Definition: address.h:13
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
#define FLOWS_LIMIT_UNLIMITED
Definition: agent.h:306
#define METADATA_NAT_PORT
Definition: agent.h:296
std::set< std::string > VnListType
Definition: agent.h:212
Definition: acl.h:92
bool PacketMatch(const PacketHeader &packet_header, MatchAclParams &m_acl, FlowPolicyInfo *info) const
Definition: acl.cc:798
Family
Definition: address.h:24
@ INET
Definition: address.h:26
@ INET6
Definition: address.h:27
bool IsActive() const
Definition: agent_db.cc:27
AgentDBEntry * FindActiveEntry(const DBEntry *key)
Definition: agent_db.cc:110
uint32_t linklocal_vm_flows() const
Definition: agent_param.h:255
uint32_t linklocal_system_flows() const
Definition: agent_param.h:254
const VnListType & dest_vn_list() const
Definition: agent_path.h:258
const EcmpLoadBalance & ecmp_load_balance() const
Definition: agent_path.h:365
const SecurityGroupList & sg_list() const
Definition: agent_path.h:248
uint32_t tunnel_bmap() const
Definition: agent_path.h:267
const Peer * peer() const
Definition: agent_path.h:263
virtual const NextHop * ComputeNextHop(Agent *agent) const
Definition: agent_path.cc:91
virtual const PrefixType & prefix_address() const
Returns the value of a stored prefix address (IPv4, IPv6 or MAC address)
Definition: agent_route.h:389
void set_prefix_length(uint8_t new_plen)
Sets the length of a stored prefix address.
Definition: agent_route.h:392
Base class for all Route entries in agent.
Definition: agent_route.h:224
VrfEntry * vrf_
Definition: agent_route.h:362
const AgentPath * GetActivePath() const
Definition: agent_route.cc:877
VrfEntry * vrf() const
Definition: agent_route.h:275
const NextHop * GetActiveNextHop() const
Definition: agent_route.cc:882
bool WaitForTraffic() const
Definition: agent_route.cc:972
virtual uint8_t prefix_length() const
Returns the length of a stored prefix address.
Definition: agent_route.h:336
uint32_t vrf_id() const
virtual Agent::RouteTableType GetTableType() const =0
void incr_flow_drop_due_to_max_limit()
Definition: agent_stats.h:117
Definition: agent.h:360
InterfaceTable * interface_table() const
Definition: agent.h:467
ServicesModule * services() const
Definition: agent.cc:976
static const std::set< std::string > & NullStringList()
Definition: agent.h:440
OperDB * oper_db() const
Definition: agent.cc:1016
FlowProto * GetFlowProto() const
Definition: agent.h:1001
uint16_t metadata_server_port() const
Definition: agent.h:961
AgentParam * params() const
Definition: agent.h:1226
@ BRIDGE
Definition: agent.h:422
VrfTable * vrf_table() const
Definition: agent.h:487
bool tsn_enabled() const
Definition: agent.h:1164
uint32_t global_max_vmi_flows() const
Definition: agent.h:1211
VxLanTable * vxlan_table() const
Definition: agent.h:537
KSync * ksync() const
Definition: agent.cc:904
Ip4Address compute_node_ip() const
Definition: agent.h:683
VrfEntry * fabric_vrf() const
Definition: agent.h:917
uint32_t max_vm_flows() const
Definition: agent.h:1207
const Peer * link_local_peer() const
Definition: agent.h:1026
const Interface * vhost_interface() const
Definition: agent.h:937
AgentStats * stats() const
Definition: agent.cc:884
const std::string & fabric_vrf_name() const
Definition: agent.h:905
Ip4Address router_id() const
Definition: agent.h:668
PktModule * pkt() const
Definition: agent.cc:968
MplsTable * mpls_table() const
Definition: agent.h:512
Definition: nexthop.h:820
const Interface * GetInterface() const
Definition: nexthop.h:837
const VrfEntry * GetVrf() const
Definition: nexthop.h:841
static const uint32_t DefaultBgpPort
uint32_t hash(uint32_t seed, bool ingress) const
Definition: nexthop.h:1878
const VrfEntry * vrf() const
Definition: nexthop.h:1875
static const uint32_t kInvalidComponentNHIdx
Definition: nexthop.h:1777
size_t ComponentNHCount() const
Definition: nexthop.h:1815
const NextHop * GetNH(uint32_t idx) const
Definition: nexthop.h:1832
COMPOSITETYPE composite_nh_type() const
Definition: nexthop.h:1842
bool GetIndex(ComponentNH &nh, uint32_t &idx) const
Definition: nexthop.cc:2335
uint32_t PickMember(uint32_t seed, uint32_t affinity_index, bool ingress) const
Definition: nexthop.cc:1861
bool IsDeleted() const
Definition: db_entry.h:49
static const NextHop * GetLocalNextHop(const AgentRoute *rt)
Definition: ecmp.cc:496
uint8_t prefix_length() const
!
const FlowKey & key() const
Definition: flow_entry.h:594
static const uint32_t kInvalidFlowHandle
Definition: flow_entry.h:521
bool is_flags_set(const FlowEntryFlags &flags) const
Definition: flow_entry.h:610
static AgentRoute * GetL2Route(const VrfEntry *entry, const MacAddress &mac)
Definition: flow_entry.cc:982
VmFlowRef * in_vm_flow_ref()
Definition: flow_entry.h:654
static FlowEntry * Allocate(const FlowKey &key, FlowTable *flow_table)
Definition: flow_entry.cc:514
void UpdateFipStatsInfo(uint32_t fip, uint32_t id, Agent *agent)
Definition: flow_entry.cc:1032
static AgentRoute * GetUcRoute(const VrfEntry *entry, const IpAddress &addr)
Definition: flow_entry.cc:989
@ SHORT_FAT_FLOW_NAT_CONFLICT
Definition: flow_entry.h:485
@ SHORT_UNAVIALABLE_INTERFACE
Definition: flow_entry.h:466
@ SHORT_LINKLOCAL_SRC_NAT
Definition: flow_entry.h:477
@ SHORT_FLOW_LIMIT
Definition: flow_entry.h:476
@ SHORT_IPV4_FWD_DIS
Definition: flow_entry.h:467
@ SHORT_NO_SRC_ROUTE
Definition: flow_entry.h:469
@ SHORT_PORT_MAP_DROP
Definition: flow_entry.h:483
@ SHORT_NO_DST_ROUTE
Definition: flow_entry.h:470
@ SHORT_UNAVIALABLE_VRF
Definition: flow_entry.h:468
@ SHORT_FLOW_ON_TSN
Definition: flow_entry.h:480
static AgentRoute * GetEvpnRoute(const VrfEntry *entry, const MacAddress &mac, const IpAddress &addr, uint32_t ethernet_tag)
Definition: flow_entry.cc:1005
void FlowStatsUpdateEvent(FlowEntry *flow, uint32_t bytes, uint32_t packets, uint32_t oflow_bytes, const boost::uuids::uuid &u)
Definition: flow_mgmt.cc:174
uint32_t linklocal_flow_count() const
Definition: flow_proto.h:111
bool UpdateFlow(FlowEntry *flow)
Definition: flow_proto.cc:298
PortTableManager * port_table_manager()
Definition: flow_proto.h:126
bool AddFlow(FlowEntry *flow)
Definition: flow_proto.cc:292
Agent * agent() const
Definition: flow_table.h:197
uint16_t table_index() const
Definition: flow_table.h:198
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.
SubType sub_type() const
uint8_t prefix_length() const
!
const Interface * GetInterface() const
Definition: nexthop.h:1293
const Interface * FindInterface(size_t index) const
Definition: interface.cc:323
@ VM_INTERFACE
Definition: interface.h:35
@ PHYSICAL
Definition: interface.h:29
const NextHop * flow_key_nh() const
Definition: interface.h:137
bool l2_active() const
Definition: interface.h:122
bool ip_active(Address::Family family) const
Definition: interface.cc:1476
VrfEntry * vrf() const
Definition: interface.h:115
uint32_t vrf_id() const
Definition: interface.cc:621
uint32_t label() const
Definition: interface.h:127
static const uint32_t kInvalidIndex
Definition: interface.h:70
Type type() const
Definition: interface.h:112
const uint32_t id() const
Definition: interface.h:123
FlowEntryPtr FindByIndex(uint32_t idx)
KSyncFlowIndexManager * ksync_flow_index_manager() const
Definition: ksync_init.h:61
static size_t bit_len()
Definition: mac_address.h:61
IpAddress service_ip() const
Definition: metadata_ip.cc:94
IpAddress destination_ip() const
Definition: metadata_ip.cc:119
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...
const Ip6Address & Ipv6ServiceAddress() const
Returns an IPv6 address of the Metadata TF link local service.
Definition: mpls.h:52
const NextHop * nexthop() const
Definition: mpls.h:80
MplsLabel * FindMplsLabel(uint32_t label)
Definition: mpls.cc:399
uint32_t id() const
Definition: nexthop.h:408
@ VLAN
Definition: nexthop.h:355
@ RECEIVE
Definition: nexthop.h:347
@ RESOLVE
Definition: nexthop.h:348
@ ARP
Definition: nexthop.h:349
@ COMPOSITE
Definition: nexthop.h:354
@ INTERFACE
Definition: nexthop.h:351
@ TUNNEL
Definition: nexthop.h:352
@ VRF
Definition: nexthop.h:350
Type GetType() const
Definition: nexthop.h:405
GlobalVrouter * global_vrouter() const
Definition: operdb_init.h:54
BgpAsAService * bgp_as_a_service() const
Definition: operdb_init.h:77
PathPreferenceModule * route_preference_module() const
Definition: operdb_init.h:58
void Add(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
bool ValidateConfig(const PktInfo *pkt, PktControlInfo *in)
bool Process(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
void CheckLinkLocal(const PktInfo *pkt)
void LinkLocalPortBind(const PktInfo *pkt, const PktControlInfo *in, FlowEntry *flow)
void ChangeVrf(const PktInfo *pkt, PktControlInfo *info, const VrfEntry *vrf)
void LinkLocalServiceFromHost(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
IpAddress nat_ip_saddr
FlowRouteRefMap flow_dest_plen_map
uint32_t src_policy_vrf
boost::shared_ptr< PktInfo > pkt
bool EgressRouteAllowNatLookup(const AgentRoute *in_rt, const AgentRoute *out_rt, uint32_t sport, uint32_t dport, const Interface *intf)
void ChangeEncap(const VmInterface *intf, const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out, bool nat_flow)
bool linklocal_bind_local_port
IpAddress FamilyToAddress(Address::Family family)
bool port_allocated
void ChangeFloatingIpEncap(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
void GenerateTrafficSeen(const PktInfo *pkt, const PktControlInfo *in)
uint8_t RouteToPrefixLen(const AgentRoute *route)
const NextHop * TunnelToNexthop(const PktInfo *pkt)
bool IngressRouteAllowNatLookup(const AgentRoute *in_rt, const AgentRoute *out_rt, uint32_t sport, uint32_t dport, const Interface *intf)
FlowEntry * flow_entry
bool bgp_router_service_flow
IpAddress snat_fip
void IngressProcess(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
bool alias_ip_flow
void UpdateFipStatsInfo(FlowEntry *flow, FlowEntry *rflow, const PktInfo *p, const PktControlInfo *in, const PktControlInfo *o)
uint32_t out_component_nh_idx
static const Ip6Address kDefaultIpv6
Definition: pkt_flow_info.h:41
Address::Family family
void FloatingIpDNat(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
bool disable_validation
void SetPktInfo(boost::shared_ptr< PktInfo > info)
uint32_t dst_policy_vrf
uint32_t nat_vrf
void LinkLocalServiceTranslate(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
uint32_t nat_dest_vrf
bool overlay_route_not_found
bool flood_unknown_unicast
uint32_t flow_source_vrf
bool underlay_flow
void NatVxlanVrfTranslate(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
bool VrfTranslate(const PktInfo *pkt, PktControlInfo *ctrl, PktControlInfo *rev_flow, const IpAddress &src_ip, bool nat_flow)
uint16_t short_flow_reason
void EgressProcess(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
const VnListType * dst_vn
uint32_t nat_sport
void BgpRouterServiceTranslate(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
static const Ip4Address kDefaultIpv4
Definition: pkt_flow_info.h:40
bool IsBgpRouterServiceRoute(const AgentRoute *in_rt, const AgentRoute *out_rt, const Interface *intf, uint32_t sport, uint32_t dport)
void UpdateRoute(const AgentRoute **rt, const VrfEntry *vrf, const IpAddress &addr, const MacAddress &mac, FlowRouteRefMap &ref_map)
bool UnknownUnicastFlow(const PktInfo *p, const PktControlInfo *in_info, const PktControlInfo *out_info)
IpAddress nat_ip_daddr
std::string peer_vrouter
bool linklocal_flow
Agent * agent
TunnelType tunnel_type
const AclDBEntry * acl
void FloatingIpSNat(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
bool RouteAllowNatLookupCommon(const AgentRoute *rt, uint32_t sport, uint32_t dport, const Interface *intf)
FlowRouteRefMap flow_source_plen_map
const VnListType * src_vn
void UpdateEvictedFlowStats(const PktInfo *pkt)
void LinkLocalServiceFromVm(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
void ApplyFlowLimits(const PktControlInfo *in, const PktControlInfo *out)
uint32_t dest_vrf
void BgpRouterServiceFromVm(const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
uint32_t nat_dport
static bool ComputeDirection(const Interface *intf)
void ChangeEncapToOverlay(const VmInterface *intf, const PktInfo *pkt, PktControlInfo *in, PktControlInfo *out)
FlowTable * flow_table
uint32_t flow_dest_vrf
FlowProto * get_flow_proto() const
Definition: pkt_init.h:43
FlowMgmtManager * flow_mgmt_manager(uint16_t index) const
Definition: pkt_init.h:39
PktHandler * pkt_handler() const
Definition: pkt_init.h:31
uint16_t Allocate(const FlowKey &key)
Definition: flow_entry.cc:4139
const Interface * get_interface() const
Definition: nexthop.h:754
MetadataProxy * metadataproxy()
Definition: services_init.h:32
const TunnelType & GetTunnelType() const
Definition: tunnel_nh.h:42
const Ip4Address * GetDip() const
Definition: tunnel_nh.h:37
@ MPLS_UDP
Definition: nexthop.h:242
@ MPLS_GRE
Definition: nexthop.h:241
Type GetType() const
Definition: nexthop.h:303
const Interface * GetInterface() const
Definition: nexthop.h:1543
uint16_t GetVlanTag() const
Definition: nexthop.h:1544
const VrfEntry * GetVrf() const
Definition: nexthop.h:1546
uint32_t linklocal_flow_count() const
Definition: vm.h:58
uint32_t flow_count() const
Definition: vm.h:55
bool AllocateFd(Agent *agent, uint8_t l3_proto)
Definition: flow_entry.cc:218
int fd() const
Definition: flow_entry.h:113
uint16_t port() const
Definition: flow_entry.h:114
static const int kInvalidFd
Definition: flow_entry.h:99
bool layer3_forwarding() const
VmInterface::VmiType vmi_type() const
uint32_t max_flows() const
uint32_t ethernet_tag() const
const FloatingIpList & floating_ip_list() const
uint32_t flow_count() const
std::set< FloatingIp, FloatingIp > FloatingIpSet
Definition: vm_interface.h:567
bool IsFloatingIp(const IpAddress &ip) const
Ip6Address mdata_ip6_addr() const
bool flood_unknown_unicast() const
VmInterface::DeviceType device_type() const
bool bridging() const
const VnEntry * vn() const
const Ip4Address & primary_ip_addr() const
MetaDataIp * GetMetaDataIp(const IpAddress &ip) const
Ip4Address mdata_ip_addr() const
const Ip6Address & primary_ip6_addr() const
VrfEntry * GetAliasIpVrf(const IpAddress &ip) const
const AclDBEntry * vrf_assign_acl() const
Definition: vn.h:151
const AclDBEntry * GetAcl() const
Definition: vn.h:167
bool vxlan_routing_vn() const
Definition: vn.h:256
Definition: vrf.h:86
const string & GetName() const
Definition: vrf.h:100
InetUnicastRouteEntry * GetUcRoute(const IpAddress &addr) const
Definition: vrf.cc:237
static const uint32_t kInvalidIndex
Definition: vrf.h:88
const uint32_t vrf_id() const
Definition: vrf.h:99
bool routing_vrf() const
Definition: vrf.h:223
VrfEntry * forwarding_vrf() const
Definition: vrf.h:217
VnEntry * vn() const
Definition: vrf.h:101
bool flood_unknown_unicast() const
Definition: nexthop.h:1449
const VrfEntry * GetVrf() const
Definition: nexthop.h:1444
VrfEntry * FindVrfFromName(const string &name)
Definition: vrf.cc:873
VrfEntry * FindVrfFromId(size_t index)
Definition: vrf.cc:884
Definition: vxlan.h:14
const NextHop * nexthop() const
Definition: vxlan.h:28
VxLanId * FindNoLock(uint32_t vxlan_id)
Definition: vxlan.cc:228
boost::intrusive_ptr< FlowEntry > FlowEntryPtr
Definition: flow_entry.h:125
#define FLOW_TRACE(obj,...)
Definition: flow_mgmt.h:377
#define LOG(_Level, _Msg)
Definition: logging.h:33
static uint32_t NhToVrf(const NextHop *nh)
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)
static bool IntfHasFloatingIp(PktFlowInfo *pkt_info, const Interface *intf, Address::Family family)
static void LogError(const PktInfo *pkt, const PktFlowInfo *flow_info, const char *str)
static bool IsLinkLocalRoute(Agent *agent, const AgentRoute *rt, uint32_t sport, uint32_t dport)
static bool PickEcmpMember(const Agent *agent, const NextHop **nh, const PktInfo *pkt, PktFlowInfo *info, const EcmpLoadBalance &ecmp_load_balance)
static bool IsVgwOrVmInterface(const Interface *intf)
static const VnListType * RouteToVn(const AgentRoute *rt)
static bool RouteToOutInfo(const Agent *agent, const AgentRoute *rt, const PktInfo *pkt, PktFlowInfo *info, PktControlInfo *in, PktControlInfo *out)
bool IsValidationDisabled(Agent *agent, const PktInfo *pkt, const Interface *interface)
static const VnEntry * InterfaceToVn(const Interface *intf)
map< int, int > FlowRouteRefMap
Definition: pkt_flow_info.h:16
uint32_t cmd_param
Definition: pkt_handler.h:183
uint32_t ifindex
Definition: pkt_handler.h:180
uint32_t vrf
Definition: pkt_handler.h:181
@ TRAP_FLOW_MISS
Definition: pkt_handler.h:137
@ LOCAL_ECMP
Definition: nexthop.h:1593
VrfTranslateActionSpec vrf_translate_action_
Definition: acl.h:48
IpAddress src_addr
Definition: flow_entry.h:213
IpAddress dst_addr
Definition: flow_entry.h:214
FlowAction action_info
Definition: acl.h:58
uint8_t protocol
Definition: packet_header.h:28
const VnListType * src_policy_id
Definition: packet_header.h:20
uint32_t vrf
Definition: packet_header.h:17
const SecurityGroupList * src_sg_id_l
Definition: packet_header.h:21
IpAddress dst_ip
Definition: packet_header.h:24
const VnListType * dst_policy_id
Definition: packet_header.h:25
const SecurityGroupList * dst_sg_id_l
Definition: packet_header.h:26
uint16_t dst_port
Definition: packet_header.h:30
uint16_t src_port
Definition: packet_header.h:29
IpAddress src_ip
Definition: packet_header.h:19
const VnEntry * vn_
Definition: pkt_flow_info.h:29
const AgentRoute * rt_
Definition: pkt_flow_info.h:28
const Interface * intf_
Definition: pkt_flow_info.h:27
const VrfEntry * vrf_
Definition: pkt_flow_info.h:26
uint16_t vlan_tag_
Definition: pkt_flow_info.h:32
const VmEntry * vm_
Definition: pkt_flow_info.h:30
PktType::Type type
Definition: pkt_handler.h:387
IpAddress ip_daddr
Definition: pkt_handler.h:395
std::size_t hash(const Agent *agent, const EcmpLoadBalance &ecmp_has_fields_to_use) const
IpAddress ip_saddr
Definition: pkt_handler.h:394
Address::Family family
Definition: pkt_handler.h:386
AgentHdr agent_hdr
Definition: pkt_handler.h:388
Definition: vrf.h:22
const std::string & vrf_name() const