OpenSDN source code
flow_entry.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <atomic>
6 #include <vector>
7 #include <bitset>
8 #include <arpa/inet.h>
9 #include <netinet/in.h>
10 #include <base/os.h>
11 #include <string>
12 
13 #include <boost/date_time/posix_time/posix_time.hpp>
14 #include <boost/assign/list_of.hpp>
15 #include <boost/unordered_map.hpp>
16 #include <sandesh/sandesh_trace.h>
17 #include <base/address_util.h>
18 #include <pkt/flow_table.h>
22 
23 #include <route/route.h>
24 #include <cmn/agent_cmn.h>
25 #include <oper/interface_common.h>
26 #include <oper/nexthop.h>
27 #include <oper/tunnel_nh.h>
28 
29 #include <init/agent_param.h>
30 #include <cmn/agent_cmn.h>
31 #include <cmn/agent_stats.h>
32 #include <oper/route_common.h>
33 #include <oper/vrf.h>
34 #include <oper/vm.h>
35 #include <oper/sg.h>
36 #include <oper/qos_config.h>
37 #include <oper/global_vrouter.h>
38 
39 #include <filter/packet_header.h>
40 #include <filter/acl.h>
41 
42 #include <pkt/proto.h>
43 #include <pkt/proto_handler.h>
44 #include <pkt/pkt_handler.h>
45 #include <pkt/flow_proto.h>
46 #include <pkt/pkt_types.h>
47 #include <pkt/pkt_sandesh_flow.h>
49 #include <pkt/flow_mgmt.h>
50 #include <pkt/flow_event.h>
51 #include <pkt/flow_entry.h>
53 
54 using namespace boost::asio::ip;
55 using boost::uuids::nil_uuid;
56 const std::map<FlowEntry::FlowPolicyState, const char*>
57  FlowEntry::FlowPolicyStateStr = boost::assign::map_list_of
58  (NOT_EVALUATED, "00000000-0000-0000-0000-000000000000")
59  (IMPLICIT_ALLOW, "00000000-0000-0000-0000-000000000001")
60  (IMPLICIT_DENY, "00000000-0000-0000-0000-000000000002")
61  (DEFAULT_GW_ICMP_OR_DNS, "00000000-0000-0000-0000-000000000003")
62  (LINKLOCAL_FLOW, "00000000-0000-0000-0000-000000000004")
63  (MULTICAST_FLOW, "00000000-0000-0000-0000-000000000005")
64  (NON_IP_FLOW, "00000000-0000-0000-0000-000000000006")
65  (BGPROUTERSERVICE_FLOW, "00000000-0000-0000-0000-000000000007");
66 
67 const std::map<uint16_t, const char*>
68  FlowEntry::FlowDropReasonStr = boost::assign::map_list_of
69  ((uint16_t)DROP_UNKNOWN, "UNKNOWN")
70  ((uint16_t)SHORT_UNAVIALABLE_INTERFACE,
71  "Short flow Interface unavialable")
72  ((uint16_t)SHORT_IPV4_FWD_DIS, "Short flow Ipv4 forwarding disabled")
73  ((uint16_t)SHORT_UNAVIALABLE_VRF,
74  "Short flow VRF unavailable")
75  ((uint16_t)SHORT_NO_SRC_ROUTE, "Short flow No Source route")
76  ((uint16_t)SHORT_NO_DST_ROUTE, "Short flow No Destination route")
77  ((uint16_t)SHORT_AUDIT_ENTRY, "Short flow Audit Entry")
78  ((uint16_t)SHORT_VRF_CHANGE, "Short flow VRF CHANGE")
79  ((uint16_t)SHORT_NO_REVERSE_FLOW, "Short flow No Reverse flow")
80  ((uint16_t)SHORT_REVERSE_FLOW_CHANGE,
81  "Short flow Reverse flow change")
82  ((uint16_t)SHORT_NAT_CHANGE, "Short flow NAT Changed")
83  ((uint16_t)SHORT_FLOW_LIMIT, "Short flow Flow Limit Reached")
84  ((uint16_t)SHORT_LINKLOCAL_SRC_NAT,
85  "Short flow Linklocal source NAT failed")
86  ((uint16_t)SHORT_FAILED_VROUTER_INSTALL,
87  "Short flow vrouter install failed")
88  ((uint16_t)SHORT_INVALID_L2_FLOW, "Short flow invalid L2 flow")
89  ((uint16_t)SHORT_FLOW_ON_TSN, "Short flow TSN flow")
90  ((uint16_t)SHORT_NO_MIRROR_ENTRY, "Short flow No mirror entry ")
91  ((uint16_t)SHORT_SAME_FLOW_RFLOW_KEY,"Short flow same flow and rflow")
92  ((uint16_t)DROP_POLICY, "Flow drop Policy")
93  ((uint16_t)DROP_OUT_POLICY, "Flow drop Out Policy")
94  ((uint16_t)DROP_SG, "Flow drop SG")
95  ((uint16_t)DROP_OUT_SG, "Flow drop OUT SG")
96  ((uint16_t)DROP_REVERSE_SG, "Flow drop REVERSE SG")
97  ((uint16_t)DROP_REVERSE_OUT_SG, "Flow drop REVERSE OUT SG")
98  ((uint16_t)DROP_FIREWALL_POLICY, "Flow drop Firewall Policy")
99  ((uint16_t)DROP_OUT_FIREWALL_POLICY, "Flow drop OUT Firewall Policy")
100  ((uint16_t)DROP_REVERSE_FIREWALL_POLICY, "Flow drop REVERSE Firewall Policy")
101  ((uint16_t)DROP_REVERSE_OUT_FIREWALL_POLICY, "Flow drop REVERSE OUT Firewall Policy")
102  ((uint16_t)SHORT_NO_SRC_ROUTE_L2RPF, "Short flow No Source route for RPF NH")
103  ((uint16_t)SHORT_FAT_FLOW_NAT_CONFLICT, "Short flow Conflicting config for NAT and FAT flow")
104  ((uint16_t)DROP_FWAAS_POLICY, "Flow drop FWAAS Policy")
105  ((uint16_t)DROP_FWAAS_OUT_POLICY, "Flow drop OUT FWAAS Policy")
106  ((uint16_t)DROP_FWAAS_REVERSE_POLICY, "Flow drop REVERSE FWAAS Policy")
107  ((uint16_t)DROP_FWAAS_REVERSE_OUT_POLICY, "Flow drop REVERSE OUT FWAAS Policy")
108  ((uint16_t)SHORT_L3MH_PHY_INTF_DOWN, "Short flow l3mh compute physical interface flap");
109 
110 std::atomic<int> FlowEntry::alloc_count_;
112 
114 // VmFlowRef
116 const int VmFlowRef::kInvalidFd;
118  vm_(NULL), fd_(kInvalidFd), port_(0), flow_(NULL) {
119 }
120 
122 
124  port_ = 0;
125  flow_ = NULL;
126 
127  // UPDATE on linklocal flows is not supported. So, fd_ should be invalid
128  assert(fd_ == VmFlowRef::kInvalidFd);
129  assert(rhs.fd_ == VmFlowRef::kInvalidFd);
130  SetVm(rhs.vm_.get());
131 }
132 
134  Reset(true);
135 }
136 
138  flow_ = flow;
139 }
140 
141 void VmFlowRef::operator=(const VmFlowRef &rhs) {
142  assert(rhs.fd_ == VmFlowRef::kInvalidFd);
143  assert(rhs.port_ == 0);
144  // For linklocal flows, we should have called Move already. It would
145  // reset vm_. Validate it
146  if (fd_ != VmFlowRef::kInvalidFd)
147  assert(rhs.vm_.get() == NULL);
148 }
149 
150 // Move is called from Copy() routine when flow is evicted by vrouter and a
151 // new flow-add is received by agent. Use the fd_ and port_ from new flow
152 // since reverse flow will be setup based on these
154  // Release the old values
155  Reset(false);
156 
157  fd_ = rhs->fd_;
158  port_ = rhs->port_;
159  SetVm(rhs->vm_.get());
160 
161  // Ownership for fd_ is transferred. Reset RHS fields
162  // Reset VM first before resetting fd_
163  rhs->SetVm(NULL);
164  rhs->fd_ = VmFlowRef::kInvalidFd;
165  rhs->port_ = 0;
166 }
167 
168 void VmFlowRef::Reset(bool reset_flow) {
169  FreeRef();
170  FreeFd();
171  vm_.reset(NULL);
172  if (reset_flow)
173  flow_ = NULL;
174 }
175 
177  if (vm_.get() == NULL)
178  return;
179 
180  vm_->update_flow_count(-1);
181  if (fd_ != kInvalidFd) {
182  vm_->update_linklocal_flow_count(-1);
183  }
184 }
185 
187  if (fd_ == kInvalidFd) {
188  assert(port_ == 0);
189  return;
190  }
191 
192  FlowProto *proto = flow_->flow_table()->agent()->pkt()->get_flow_proto();
193  proto->update_linklocal_flow_count(-1);
195  close(fd_);
196 
197  fd_ = kInvalidFd;
198  port_ = 0;
199 }
200 
201 void VmFlowRef::SetVm(const VmEntry *vm) {
202  if (vm == vm_.get())
203  return;
204  FreeRef();
205 
206  vm_.reset(vm);
207  if (vm == NULL)
208  return;
209 
210  // update per-vm flow accounting
211  vm->update_flow_count(1);
212  if (fd_ != kInvalidFd) {
213  vm_->update_linklocal_flow_count(1);
214  }
215 
216  return;
217 }
218 
219 bool VmFlowRef::AllocateFd(Agent *agent, uint8_t l3_proto) {
220  if (fd_ != kInvalidFd)
221  return true;
222 
223  port_ = 0;
224  // Short flows are always dropped. Dont allocate FD for short flow
225  if (flow_->IsShortFlow())
226  return false;
227 
228  if (l3_proto == IPPROTO_TCP) {
229  fd_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
230  } else if (l3_proto == IPPROTO_UDP) {
231  fd_ = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
232  }
233 
234  if (fd_ == kInvalidFd) {
235  return false;
236  }
237 
238  // Update agent accounting info
241  flow_->key(), UTCTimestampUsec());
242 
243  // allow the socket to be reused upon close
244  if (l3_proto == IPPROTO_TCP) {
245  int optval = 1;
246  setsockopt(fd_, SOL_SOCKET, SO_REUSEADDR,
247  (const char*)&optval, sizeof(optval));
248  }
249 
250  struct sockaddr_in address;
251  memset(&address, 0, sizeof(address));
252  address.sin_family = AF_INET;
253  if (::bind(fd_, (struct sockaddr*) &address, sizeof(address)) < 0) {
254  FreeFd();
255  return false;
256  }
257 
258  struct sockaddr_in bound_to;
259  socklen_t len = sizeof(bound_to);
260  if (getsockname(fd_, (struct sockaddr*) &bound_to, &len) < 0) {
261  FreeFd();
262  return false;
263  }
264 
265  port_ = ntohs(bound_to.sin_port);
266  return true;
267 }
268 
270 // FlowData constructor/destructor
273  Reset();
274 }
275 
277 }
278 
280  smac = MacAddress();
281  dmac = MacAddress();
282  source_vn_list.clear();
283  source_vn_match = "";
284  dest_vn_match = "";
285  dest_vn_list.clear();
286  origin_vn_dst_list.clear();
287  origin_vn_src_list.clear();
288  origin_vn_src = "";
289  origin_vn_dst = "";
290  source_sg_id_l.clear();
291  dest_sg_id_l.clear();
294  match_p.Reset();
295  vn_entry.reset(NULL);
296  intf_entry.reset(NULL);
297  in_vm_entry.Reset(true);
298  out_vm_entry.Reset(true);
299  src_ip_nh.reset(NULL);
302  dest_vrf = 0;
304  source_plen = 0;
305  dest_plen = 0;
306  drop_reason = 0;
307  vrf_assign_evaluated = false;
308  if_index_info = 0;
309  tunnel_info.Reset();
310  flow_source_plen_map.clear();
311  flow_dest_plen_map.clear();
312  enable_rpf = true;
313  rpf_nh.reset(NULL);
316  disable_validation = false;
317  vm_cfg_name = "";
322  ttl = 0;
324  src_policy_plen = 0;
326  dst_policy_plen = 0;
327  allocated_port_ = 0;
328  underlay_gw_index_ = -1;
329 }
330 
331 static std::vector<std::string> MakeList(const VnListType &ilist) {
332  std::vector<std::string> olist;
333  for (VnListType::const_iterator it = ilist.begin();
334  it != ilist.end(); ++it) {
335  olist.push_back(*it);
336  }
337  return olist;
338 }
339 
340 std::vector<std::string> FlowData::SourceVnList() const {
341  return MakeList(source_vn_list);
342 }
343 
344 std::vector<std::string> FlowData::DestinationVnList() const {
345  return MakeList(dest_vn_list);
346 }
347 
348 std::vector<std::string> FlowData::OriginVnSrcList() const {
350 }
351 
352 std::vector<std::string> FlowData::OriginVnDstList() const {
354 }
355 
357 // MatchPolicy constructor/destructor
360  Reset();
361 }
362 
364 }
365 
367  m_acl_l.clear();
368  policy_action = 0;
369  m_out_acl_l.clear();
370  out_policy_action = 0;
371  sg_policy.Reset();
372  m_mirror_acl_l.clear();
373  mirror_action = 0;
374  m_out_mirror_acl_l.clear();
375  out_mirror_action = 0;
376  m_vrf_assign_acl_l.clear();
378  aps_policy.Reset();
380  action_info.Clear();
381 }
382 
384  m_out_acl_l.clear();
385  out_rule_present = false;
386  out_action = 0;
387 
388  m_acl_l.clear();
389  rule_present = false;
390  action = 0;
391 
392  m_reverse_acl_l.clear();
393  reverse_rule_present = false;
394  reverse_action = 0;
395 
396  m_reverse_out_acl_l.clear();
397  reverse_out_rule_present = false;
398  reverse_out_action = 0;
399 
400  action_summary = 0;
402  acl_name_ = "";
403 }
404 
407  acl_name_ = "";
408 }
409 
411  out_action = 0;
412  action = 0;
413  reverse_action = 0;
414  reverse_out_action = 0;
415  action_summary = 0;
416 }
417 
419  rule_present = false;
420  m_acl_l.clear();
421 
422  out_rule_present = false;
423  m_out_acl_l.clear();
424 
425  reverse_rule_present = false;
426  m_reverse_acl_l.clear();
427 
428  reverse_out_rule_present = false;
429  m_reverse_out_acl_l.clear();
431 }
432 
434 // FlowEventLog constructor/destructor
436 FlowEventLog::FlowEventLog() : time_(0), event_(EVENT_MAXIMUM),
437  flow_handle_(FlowEntry::kInvalidFlowHandle), flow_gen_id_(0),
438  ksync_entry_(NULL), hash_id_(FlowEntry::kInvalidFlowHandle), gen_id_(0),
439  vrouter_flow_handle_(FlowEntry::kInvalidFlowHandle), vrouter_gen_id_(0) {
440 }
441 
443 }
444 
446 // FlowEntry constructor/destructor
449  flow_table_(flow_table), flags_(0),
450  tunnel_type_(TunnelType::INVALID),
451  fip_vmi_(AgentKey::ADD_DEL_CHANGE, nil_uuid(), ""),
452  flow_mgmt_request_(NULL), flow_mgmt_info_() {
453  // ksync entry is set to NULL only on constructor and on flow delete
454  // it should not have any other explicit set to NULL
455  ksync_entry_ = NULL;
456  Reset();
457  alloc_count_++;
458 }
459 
461  assert(refcount_ == 0);
462  Reset();
463  alloc_count_--;
464 }
465 
467  assert(ksync_entry_ == NULL);
471  const VmInterface *vm_intf =
472  dynamic_cast<const VmInterface *>(intf_entry());
473  if (vm_intf) {
474  vm_intf->update_flow_count(-2);
475  }
476  }
477  data_.Reset();
478  l3_flow_ = true;
479  gen_id_ = 0;
481  reverse_flow_entry_ = NULL;
482  deleted_ = false;
483  flags_ = 0;
486  peer_vrouter_ = "";
488  on_tree_ = false;
489  fip_ = 0;
491  refcount_ = 0;
493  fsc_ = NULL;
494  trace_ = false;
495  event_logs_.reset();
496  event_log_index_ = 0;
501  assert(flow_mgmt_request_ == NULL);
502  assert(flow_mgmt_info_.get() == NULL);
503  transaction_id_ = 0;
504 }
505 
506 void FlowEntry::Reset(const FlowKey &k) {
507  Reset();
508  key_ = k;
509 }
510 
512  alloc_count_ = 0;
513 }
514 
515 FlowEntry *FlowEntry::Allocate(const FlowKey &key, FlowTable *flow_table) {
516  // flow_table will be NULL for some UT cases
517  FlowEntry *flow;
518  if (flow_table == NULL) {
519  flow = new FlowEntry(flow_table);
520  flow->Reset(key);
521  } else {
522  flow = flow_table->free_list()->Allocate(key);
523  }
524 
525  flow->data_.in_vm_entry.Init(flow);
526  flow->data_.out_vm_entry.Init(flow);
527  return flow;
528 }
529 
530 // selectively copy fields from RHS
531 // When flow is being updated, rhs will be new flow allocated in PktFlowInfo
532 void FlowEntry::Copy(FlowEntry *rhs, bool update) {
533  if (update) {
534  rhs->data_.in_vm_entry.Reset(false);
535  rhs->data_.out_vm_entry.Reset(false);
536  } else {
537  // The operator= below will call VmFlowRef operator=. In case of flow
538  // eviction, we want to move ownership from rhs to lhs. However rhs is
539  // const ref in operator so, invode Move API to transfer ownership
542  }
543  data_ = rhs->data_;
544  flags_ = rhs->flags_;
545  hbs_intf_ = rhs->hbs_intf_;
547  nw_ace_uuid_ = rhs->nw_ace_uuid_;
549  tunnel_type_ = rhs->tunnel_type_;
550  fip_ = rhs->fip_;
551  fip_vmi_ = rhs->fip_vmi_;
552  last_event_ = rhs->last_event_;
554  trace_ = rhs->trace_;
555  if (update == false) {
556  gen_id_ = rhs->gen_id_;
557  flow_handle_ = rhs->flow_handle_;
558  /* Flow Entry is being re-used. Generate a new UUID for it. */
561  }
562 }
563 
565 // Routines to initialize FlowEntry from PktControlInfo
568  fe->refcount_++;
569 }
570 
572  FlowTable *flow_table = fe->flow_table();
573  int prev = fe->refcount_.fetch_sub(1);
574  if (prev == 1) {
575  if (fe->on_tree()) {
576  if (flow_table->ConcurrencyCheck(flow_table->flow_task_id())
577  == false) {
578  FlowEntryPtr ref(fe);
579  FlowProto *proto=flow_table->agent()->pkt()->get_flow_proto();
580  proto->ForceEnqueueFreeFlowReference(ref);
581  return;
582  }
583  FlowTable::FlowEntryMap::iterator it =
584  flow_table->flow_entry_map_.find(fe->key());
585  assert(it != flow_table->flow_entry_map_.end());
586  flow_table->flow_entry_map_.erase(it);
587  flow_table->agent()->stats()->decr_flow_count();
588  }
589  flow_table->free_list()->Free(fe);
590  }
591 }
592 
593 // Helper Functions
594 static std::size_t HashCombine(std::size_t hash, uint64_t val) {
595  boost::hash_combine(hash, val);
596  return hash;
597 }
598 
599 static std::size_t HashIp(std::size_t hash, const IpAddress &ip) {
600  if (ip.is_v6()) {
601  uint64_t val[2];
602  Ip6AddressToU64Array(ip.to_v6(), val, 2);
603  hash = HashCombine(hash, val[0]);
604  hash = HashCombine(hash, val[1]);
605  } else if (ip.is_v4()) {
606  hash = HashCombine(hash, ip.to_v4().to_ulong());
607  } else {
608  assert(0);
609  }
610  return hash;
611 }
612 bool FlowEntry::InitFlowCmn(const PktFlowInfo *info, const PktControlInfo *ctrl,
613  const PktControlInfo *rev_ctrl,
614  FlowEntry *rflow) {
615  reverse_flow_entry_ = rflow;
617  peer_vrouter_ = info->peer_vrouter;
618  tunnel_type_ = info->tunnel_type;
619 
620  if (info->linklocal_flow) {
622  } else {
624  }
625  if (info->nat_done) {
627  } else {
629  }
630  if (info->short_flow) {
633  } else {
636  }
637  if (info->local_flow) {
639  } else {
641  }
642 
643  if (info->tcp_ack) {
645  } else {
647  }
648  if (info->bgp_router_service_flow) {
652  } else {
656  }
657 
658  if (info->alias_ip_flow) {
660  } else {
662  }
663 
664  if (info->underlay_flow) {
666  } else {
668  }
669 
670  if (IsFabricControlFlow()) {
672  } else {
674  }
675 
676  data_.intf_entry = ctrl->intf_ ? ctrl->intf_ : rev_ctrl->intf_;
677  data_.vn_entry = ctrl->vn_ ? ctrl->vn_ : rev_ctrl->vn_;
678  data_.in_vm_entry.SetVm(ctrl->vm_);
679  data_.out_vm_entry.SetVm(rev_ctrl->vm_);
680  l3_flow_ = info->l3_flow;
682 
683  return true;
684 }
685 
686 void FlowEntry::InitFwdFlow(const PktFlowInfo *info, const PktInfo *pkt,
687  const PktControlInfo *ctrl,
688  const PktControlInfo *rev_ctrl,
689  FlowEntry *rflow, Agent *agent) {
692  if (InitFlowCmn(info, ctrl, rev_ctrl, rflow) == false) {
693  return;
694  }
695  if (info->linklocal_bind_local_port) {
697  } else {
699  }
700  uint32_t intf_in = pkt->GetAgentHdr().ifindex;
701  data_.vm_cfg_name = InterfaceIdToVmCfgName(agent, intf_in);
702 
703  if (info->port_allocated) {
705  }
706 
707  if (info->ingress) {
709  } else {
711  }
713  if (ctrl->rt_ != NULL) {
714  RpfInit(ctrl->rt_, pkt->ip_saddr);
715  }
716  data_.ttl = info->ttl;
717  if (info->bgp_router_service_flow) {
718  if (info->ttl == 1) {
720  }
721  }
722 
727  data_.dest_vrf = info->dest_vrf;
728  data_.vrf = pkt->vrf;
730  data_.tunnel_info = pkt->tunnel;
731 
732  if (info->ecmp) {
734  } else {
736  }
737 
740  if (ctrl->rt_ && ctrl->rt_->is_multicast()) {
742  }
743  if (rev_ctrl->rt_ && rev_ctrl->rt_->is_multicast()) {
745  }
746 
749 
751  if (info->flood_unknown_unicast) {
753  if (info->ingress) {
754  GetSourceRouteInfo(ctrl->rt_);
755  } else {
756  GetSourceRouteInfo(rev_ctrl->rt_);
757  }
759  } else {
760  GetSourceRouteInfo(ctrl->rt_);
761  GetDestRouteInfo(rev_ctrl->rt_);
762  }
763 
764  data_.smac = pkt->smac;
765  data_.dmac = pkt->dmac;
766 
768  const VmInterface *vm_intf =
769  dynamic_cast<const VmInterface *>(intf_entry());
770  if (vm_intf) {
771  vm_intf->update_flow_count(2);
772  }
773  }
774 
776  info->pkt->ip_saddr, info->pkt->ip_daddr,
777  info->pkt->ip_proto, info->pkt->sport, info->pkt->dport);
778 }
779 
780 void FlowEntry::InitRevFlow(const PktFlowInfo *info, const PktInfo *pkt,
781  const PktControlInfo *ctrl,
782  const PktControlInfo *rev_ctrl,
783  FlowEntry *rflow, Agent *agent) {
784  uint32_t intf_in;
785  if (InitFlowCmn(info, ctrl, rev_ctrl, rflow) == false) {
786  return;
787  }
789  if (ctrl->intf_) {
790  intf_in = ctrl->intf_->id();
791  } else {
792  intf_in = Interface::kInvalidIndex;
793  }
794  data_.vm_cfg_name = InterfaceIdToVmCfgName(agent, intf_in);
795 
796  // Compute reverse flow fields
798  if (ctrl->intf_) {
799  if (info->ComputeDirection(ctrl->intf_)) {
801  } else {
803  }
804  }
806  if (ctrl->rt_ != NULL) {
807  RpfInit(ctrl->rt_, pkt->ip_daddr);
808  }
809 
810  if (info->bgp_router_service_flow) {
811  if ((info->ttl == 1)|| (info->ttl == BGP_SERVICE_TTL_FWD_FLOW)) {
813  }
814  }
815 
820  data_.vrf = info->dest_vrf;
821 
822  if (!info->nat_done) {
824  } else {
825  data_.dest_vrf = info->nat_dest_vrf;
826  }
827  if (info->ecmp) {
829  } else {
831  }
833 
836 
838  if (info->flood_unknown_unicast) {
840  if (info->ingress) {
841  GetSourceRouteInfo(rev_ctrl->rt_);
842  } else {
843  GetSourceRouteInfo(ctrl->rt_);
844  }
845  //Set source VN and dest VN to be same
846  //since flooding happens only for layer2 routes
847  //SG id would be left empty, user who wants
848  //unknown unicast to happen should modify the
849  //SG to allow such traffic
851  } else {
852  GetSourceRouteInfo(ctrl->rt_);
853  GetDestRouteInfo(rev_ctrl->rt_);
854  }
855 
856  data_.smac = pkt->dmac;
857  data_.dmac = pkt->smac;
858 
860  const VmInterface *vm_intf =
861  dynamic_cast<const VmInterface *>(intf_entry());
862  if (vm_intf) {
863  vm_intf->update_flow_count(2);
864  }
865  }
866 
868  info->pkt->ip_saddr, info->pkt->ip_daddr,
869  info->pkt->ip_proto, info->pkt->sport, info->pkt->dport);
870 }
871 
872 void FlowEntry::InitAuditFlow(uint32_t flow_idx, uint8_t gen_id) {
873  gen_id_ = gen_id;
874  flow_handle_ = flow_idx;
883 }
884 
885 
886 // Fabric control flows are following,
887 // - XMPP connection to control node
888 // - SSH connection to vhost
889 // - Ping to vhost
890 // - Introspect to vhost
891 // - Port-IPC connection to vhost
892 // - Contrail-Status UVE
893 // TODO : Review this
895  Agent *agent = flow_table()->agent();
896  if (agent->get_vhost_disable_policy()) {
897  return false;
898  }
899 
900  if (key_.dst_addr.is_v4() == false) {
901  return false;
902  }
903 
904  if (IsNatFlow()) {
905  return false;
906  }
907 
908  if (key_.protocol == IPPROTO_TCP) {
909  if (key_.src_addr == agent->router_id()) {
910  for (int i = 0; i < MAX_XMPP_SERVERS; i++) {
911  if (key_.dst_addr.to_string() !=
913  continue;
914  if (key_.dst_port == agent->controller_ifmap_xmpp_port(i)) {
915  return true;
916  }
917  }
918 
919  for (int i = 0; i < MAX_XMPP_SERVERS; i++) {
920  if (key_.dst_addr.to_string() !=
921  agent->dns_server(i))
922  continue;
924  return true;
925  }
926 
927  if (key_.dst_port == agent->dns_server_port(i)) {
928  return true;
929  }
930  }
931 
932  std::ostringstream collector;
933  collector << key_.dst_addr.to_string() << ":" <<
935  std::vector<string>::const_iterator it =
936  agent->GetCollectorlist().begin();
937  for(; it != agent->GetCollectorlist().end(); it++) {
938  if (collector.str() == *it) {
939  return true;
940  }
941  }
942 
943  Ip4Address metadata_fabric_ip;
944  uint16_t metadata_fabric_port = 0;
945  IpAddress local_ip;
946  uint16_t local_port = 0;
947  std::string nova_hostname;
948  agent->oper_db()->global_vrouter()->
949  FindLinkLocalService(GlobalVrouter::kMetadataService,
950  &local_ip, &local_port,
951  &nova_hostname,
952  &metadata_fabric_ip,
953  &metadata_fabric_port);
954  if (key_.dst_addr.to_v4() == metadata_fabric_ip &&
955  key_.dst_port == metadata_fabric_port) {
956  return true;
957  }
958  }
959 
960 
961  if (key_.dst_addr == agent->router_id()) {
962  return (key_.dst_port == 22);
963  }
964 
965  if (key_.src_addr == agent->router_id()) {
966  return (key_.src_port == 22);
967  }
968  return false;
969  }
970 
971  if (key_.protocol == IPPROTO_ICMP) {
972  return (key_.src_addr == agent->router_id() ||
973  key_.dst_addr == agent->router_id());
974  }
975 
976  return false;
977 }
978 
980 // Utility routines
982 // Find L2 Route for the MAC address.
984  const MacAddress &mac) {
985  BridgeAgentRouteTable *table = static_cast<BridgeAgentRouteTable *>
986  (vrf->GetBridgeRouteTable());
987  return table->FindRouteNoLock(mac);
988 }
989 
991  const IpAddress &addr) {
992  AgentRoute *rt = NULL;
993  if (addr.is_v4()) {
994  InetUnicastRouteEntry key(NULL, addr, 32, false);
995  rt = entry->GetUcRoute(key);
996  } else {
997  InetUnicastRouteEntry key(NULL, addr, 128, false);
998  rt = entry->GetUcRoute(key);
999  }
1000  if (rt != NULL && rt->IsRPFInvalid()) {
1001  return NULL;
1002  }
1003  return rt;
1004 }
1005 
1007  const MacAddress &mac,
1008  const IpAddress &ip,
1009  uint32_t ethernet_tag) {
1010  EvpnAgentRouteTable *table = static_cast<EvpnAgentRouteTable *>(
1011  vrf->GetEvpnRouteTable());
1012  return table->FindRouteNoLock(mac, ip,
1014  ethernet_tag);
1015 }
1016 
1018  FlowEntry *rflow = reverse_flow_entry_.get();
1019  if (rflow) {
1020  return rflow->fip();
1021  }
1022  return 0;
1023 }
1024 
1026  FlowEntry *rflow = reverse_flow_entry_.get();
1027  if (rflow) {
1028  return rflow->fip_vmi();
1029  }
1030  return VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, nil_uuid(), "");
1031 }
1032 
1033 void FlowEntry::UpdateFipStatsInfo(uint32_t fip, uint32_t id, Agent *agent) {
1034  fip_ = fip;
1035  fip_vmi_ = InterfaceIdToKey(agent, id);
1036 }
1037 
1038 void FlowEntry::set_flow_handle(uint32_t flow_handle, uint8_t gen_id) {
1039  if (flow_handle_ != flow_handle) {
1040  assert(flow_handle_ == kInvalidFlowHandle);
1042  }
1043  gen_id_ = gen_id;
1044 }
1045 
1046 const std::string& FlowEntry::acl_assigned_vrf() const {
1048 }
1049 
1052  const VrfEntry *vrf = static_cast<const VrfEntry *>(
1053  flow_table()->agent()->vrf_table()->FindActiveEntry(&vrf_key));
1054  if (vrf) {
1056  bool set_dest_vrf = true;
1058  reverse_flow_entry() &&
1060  //Packet is getting DNATed, VRF assign ACL action
1061  //is applied on floating-ip VN and the destination VRF should
1062  //be retained as interface VRF
1063  set_dest_vrf = false;
1064  }
1065 
1066  if (set_dest_vrf) {
1067  data_.dest_vrf = vrf->vrf_id();
1068  }
1069  return;
1070  }
1072 }
1073 
1076 }
1077 
1079  params->sip_ = key().src_addr;
1080  FlowEntry *rev_flow = reverse_flow_entry();
1081  if (rev_flow) {
1082  params->rev_uuid_ = rev_flow->uuid();
1083  params->vm_cfg_name_ = rev_flow->data().vm_cfg_name;
1084  params->sg_uuid_ = rev_flow->sg_rule_uuid();
1085  params->rev_egress_uuid_ = rev_flow->egress_uuid();
1086  params->nw_ace_uuid_ = rev_flow->nw_ace_uuid();
1087  params->drop_reason_ = rev_flow->data().drop_reason;
1088  params->action_info_ = rev_flow->data().match_p.action_info;
1089  if (rev_flow->intf_entry()) {
1090  const VmInterface *vmi =
1091  dynamic_cast<const VmInterface *>(rev_flow->intf_entry());
1092  if (vmi) {
1093  params->vmi_uuid_ = UuidToString(vmi->vmi_cfg_uuid());
1094  } else {
1095  params->vmi_uuid_ = UuidToString(rev_flow->intf_entry()->
1096  GetUuid());
1097  }
1098  }
1099 
1100  if (key().family != Address::INET) {
1101  return;
1102  }
1105  const FlowKey *nat_key = &rev_flow->key();
1106  if (key().src_addr != nat_key->dst_addr) {
1107  params->sip_ = nat_key->dst_addr;
1108  }
1109  }
1110  }
1111 }
1112 
1113 bool FlowEntry::ShouldDrop(uint32_t action) {
1114  if (action & TrafficAction::DROP_FLAGS)
1115  return true;
1116 
1118  return true;
1119 
1120  return false;
1121 }
1122 
1124 // Flow RPF
1125 //
1126 // VRouter enforces RPF check based on RPF-NH programmed in the flow. The RPF
1127 // NH can be of two types,
1128 // - Unicast NH :
1129 // In this case, VRouter matches with incoming interface/tunnel-src with
1130 // RPF NH the flow
1131 //
1132 // - ECMP NH :
1133 // In this case, VRouter picks an ECMP component-nh and matches with incoming
1134 // interface/tunnel-src. The index for component-nh is got from reverse flow.
1135 //
1136 // RPF-NH cases
1137 // ------------
1138 // 1. Baremetals
1139 // Agent is not aware of IP address assigned for baremetals. So, RPF check
1140 // for baremetals is based on the L2-Route
1141 //
1142 // 2. Layer-2 Flows
1143 // If agent know the Inet route for source-ip in packet, RPF is based on
1144 // the Inet route for source-ip. There are some exceptions for this rule,
1145 // - If Inet route for source-ip is ECMP, then RPF is based on layer-2 route
1146 // - If Inet route for source-ip is not-host route, then RPF is based on
1147 // layer-2 routes
1148 //
1149 // If packet is from BMS (egress flow), its possible that agent does not
1150 // know IP address for BMS. In such case, RPF is based on L2-Route
1151 //
1152 // 3. Layer-3 Flows from VMI
1153 // RPF check will be based on the InterfaceNH for VMI
1154 //
1155 // 4. Layer-3 Flows from Fabric with unicast-NH
1156 // The unicast-nh is used as RPF-NH
1157 //
1158 // 5. Layer-3 Flows from Fabric with composite-NH
1159 // VRouter picks NH from flow and the ecmp-index from reverse flow.
1160 //
1161 // The ecmp-index in reverse is computed based on route for dest-ip in
1162 // VRF got post VRF translation if any
1163 //
1164 // Note, the RPF must be picked post VRF translation since order of members
1165 // in Composite-NH may vary across VRF
1166 //
1167 // Route Tracking
1168 // --------------
1169 // Flow Management should track the route for ip1 in vrf4 to update RPF-NH
1170 //
1171 // RPF Computation
1172 // ---------------
1173 // RPF computation happens in two stages
1174 // 1. FlowEntry creation (RpfInit):
1175 // Called during FlowEntry init. Computes src_ip_nh for flow.
1176 //
1177 // For layer-2 flows, RPF-NH Is same as src_ip_nh
1178 // For Non-ECMP layer-3 flows, RPF-NH is same as src_ip_nh
1179 // For ECMP layer-3 flows, RPF-NH must be computed only after VRF
1180 // translation is computed for reverse flow.
1181 //
1182 // 2. Post ACL processing (RpfUpdate):
1183 // Post ACL processing, all VRF translation rules are identified.
1184 // The RPF-NH is computed in this method.
1186 // Utility method to set rpf_vrf and rpf_plen fields
1187 static void SetRpfFieldsInternal(FlowEntry *flow, const AgentRoute *rt) {
1188  // If there is no route, we should track default route
1189  if (rt == NULL) {
1190  flow->data().rpf_vrf = flow->data().vrf;
1191  flow->data().rpf_plen = 0;
1192  return;
1193  }
1194 
1195  const InetUnicastRouteEntry *inet_rt =
1196  dynamic_cast<const InetUnicastRouteEntry *>(rt);
1197  if (inet_rt) {
1198  flow->data().rpf_vrf = inet_rt->vrf()->vrf_id();
1199  flow->data().rpf_plen = inet_rt->prefix_length();
1200  return;
1201  }
1202 
1203  if (!flow->l3_flow()) {
1204  flow->data().rpf_vrf = rt->vrf()->vrf_id();
1205  /*
1206  * For L2 flows also plen is found using GetUCRoute
1207  * plen is stored in L2 route entry
1208  * this changed to address CEM-27722
1209  */
1210  const BridgeRouteEntry *bridge_rt =
1211  dynamic_cast<const BridgeRouteEntry *>(rt);
1212  if (bridge_rt != NULL) {
1213  BridgeRouteEntry *temp = const_cast<BridgeRouteEntry *>(bridge_rt);
1214  flow->data().rpf_plen = temp->prefix_length();
1215  }
1216  return;
1217  }
1218  // Route is not INET. Dont track any route
1220  flow->data().rpf_plen = 0;
1221  return;
1222 }
1223 
1224 // Utility method to set src_ip_nh fields
1226  const NextHop *src_ip_nh) {
1227  data_.src_ip_nh.reset(src_ip_nh);
1228  SetRpfFieldsInternal(this, rt);
1229  return;
1230 }
1231 
1233  data_.rpf_nh.reset(rpf_nh);
1234 }
1235 
1236 // Utility method to set rpf_nh fields
1237 void FlowEntry::RpfSetRpfNhFields(const AgentRoute *rt, const NextHop *rpf_nh) {
1238  data_.rpf_nh.reset(rpf_nh);
1239  SetRpfFieldsInternal(this, rt);
1240  return;
1241 }
1242 
1243 // This method is called when flow is initialized. The RPF-NH cannot be
1244 // computed at this stage since we dont know if reverse flow has VRF
1245 // translation or not.
1246 // This method only sets src_ip_nh field
1247 //
1248 // In case of layer-3 flow "rt" is inet route for source-ip in source-vrf
1249 // In case of layer-2 flow "rt" is l2 route for smac in source-vrf
1250 void FlowEntry::RpfInit(const AgentRoute *rt, const IpAddress &sip) {
1251  // Set src_ip_nh based on rt first
1253 
1254  // RPF enabled?
1255  bool rpf_enable = true;
1256  if (data_.vn_entry && data_.vn_entry->enable_rpf() == false)
1257  rpf_enable = false;
1259  rpf_enable = false;
1260 
1261  // The src_ip_nh can change below only for l2 flows
1262  // For l3-flow, rt will already be a INET route
1263  if (l3_flow())
1264  return;
1265 
1266  // For layer-2 flows, we use l2-route for RPF in following cases
1267  // 1. Interface is of type BAREMETAL (ToR/TSN only)
1268  //
1269  // 2. ECMP is not supported for l2-flows. If src-ip lookup resulted in
1270  // ECMP-NH fallback to the original l2-route
1271  //
1272  // 3. In case of OVS, ToR will export layer-2 route and MX will export a
1273  // layer-3 subnet route covering all the ToRs. In this case, when ToR
1274  // send layer-2 packet the layer-3 route will point to MX and RPF fails.
1275  // Assuming MX only gives subnet-route, use inet-route only if its
1276  // host-route
1277  // 4. Its an egress flow and there is no route for IP address
1278  const VmInterface *vmi =
1279  dynamic_cast<const VmInterface *>(intf_entry());
1280  if (vmi && vmi->vmi_type() == VmInterface::BAREMETAL) {
1281  return;
1282  }
1283 
1284  VrfEntry *vrf = rt->vrf();
1285  const InetUnicastRouteEntry *src_ip_rt =
1286  static_cast<InetUnicastRouteEntry *>
1287  (FlowEntry::GetUcRoute(vrf, sip));
1288 
1289  if (src_ip_rt == NULL) {
1290  // For egress flow, with no l3-route then do rpf based on l2-route
1291  // For ingress flow, with no l3-route, make it short flow
1292  if (rpf_enable && IsIngressFlow()) {
1295  }
1296  return;
1297  }
1298 
1299  if (src_ip_rt->IsHostRoute() == false)
1300  return;
1301 
1302  const NextHop *src_ip_nh = src_ip_rt->GetActiveNextHop();
1303  if ((src_ip_nh != NULL) && src_ip_nh->GetType() == NextHop::COMPOSITE)
1304  return;
1305 
1306  RpfSetSrcIpNhFields(src_ip_rt, src_ip_nh);
1307  return;
1308 }
1309 
1310 // Should src_ip_nh be treated as RPF-NH
1312  // For l2-flows, src_ip_nh is same as RPF-NH
1313  if (l3_flow() == false)
1314  return true;
1315 
1316  // Dont bother about RPF for short-flows
1318  return true;
1319 
1320  // rpf-nh can change only in case of composite
1321  if (data_.src_ip_nh->GetType() != NextHop::COMPOSITE)
1322  return true;
1323 
1324  const FlowEntry *rflow = reverse_flow_entry();
1325  if (rflow == NULL) {
1326  FlowInfo flow_info;
1327  FillFlowInfo(flow_info);
1328  FLOW_TRACE(Trace, "Invalid reverse flow for setting ECMP index",
1329  flow_info);
1330  return true;
1331  }
1332 
1333  return false;
1334 }
1335 
1337  const NextHop *nh = NULL;
1338  // If we are here, its guaranteed that src_ip_nh is composite
1339  const CompositeNH *cnh =
1340  dynamic_cast<const CompositeNH *>(data_.src_ip_nh.get());
1341  assert(cnh != NULL);
1342 
1343  // Use flow_key_nh if VMI is part of composite. Else its guaranteed
1344  // that RPF will fail for flow. So, use discard-nh for RPF
1345  const VmInterface *vmi =
1346  dynamic_cast<const VmInterface *>(intf_entry());
1347  if (cnh->HasVmInterface(vmi)) {
1348  nh = vmi->flow_key_nh();
1349  } else {
1350  nh = data_.src_ip_nh.get();
1351  }
1352 
1353  // Change only the RPF-NH. The vrf and plen dont change here
1354  RpfSetRpfNhFields(nh);
1355  return;
1356 }
1357 
1359  const FlowEntry *rflow = reverse_flow_entry();
1360 
1361  // RPF-NH can change only if VRF in forward flow and translated VRF in
1362  // reverse flow are different
1363  if (rflow->data().flow_dest_vrf == data_.vrf) {
1365  return;
1366  }
1367 
1368  // Find destination VRF from reverse flow
1369  const VrfEntry *vrf = rflow->GetDestinationVrf();
1370  if (vrf == NULL) {
1371  FlowInfo flow_info;
1372  FillFlowInfo(flow_info);
1373  FLOW_TRACE(Trace, "Error setting RPF NH. Destination VRF not found "
1374  "in reverse flow", flow_info);
1375  return;
1376  }
1377 
1378  InetUnicastRouteEntry *rt = static_cast<InetUnicastRouteEntry *>
1379  (FlowEntry::GetUcRoute(vrf, key().src_addr));
1380  if (!rt) {
1381  FlowInfo flow_info;
1382  FillFlowInfo(flow_info);
1383  FLOW_TRACE(Trace, "Error setting RPF NH. Route not found in "
1384  "destination vrf", flow_info);
1385  return;
1386  }
1387 
1389  return;
1390 }
1391 
1392 // Computes RPF-NH for flow based on ip_src_nh
1393 // Must be called after policy lookup is done
1395  // Is RPF check enabled?
1396  data_.enable_rpf = true;
1397  if (data_.vn_entry) {
1398  data_.enable_rpf = data_.vn_entry->enable_rpf();
1399  }
1400 
1401  if (data_.disable_validation) {
1402  data_.enable_rpf = false;
1403  }
1404 
1405  if (data_.enable_rpf == false) {
1406  data_.rpf_nh = NULL;
1407  return;
1408  }
1409 
1410  if (RpfFromSrcIpNh()) {
1412  return;
1413  }
1414 
1417  } else {
1418  RpfComputeEgress();
1419  }
1420 }
1421 
1423  /*
1424  * If the flow is Local + Ingress + Forward
1425  * then it will be considered as client session
1426  */
1430  return true;
1431  }
1432  /*
1433  * If the flow is (Ingress + Forward) OR
1434  * (Egress + Reverse)
1435  * then it will be consideres as client session
1436  */
1439  return true;
1440  }
1441  } else {
1443  return true;
1444  }
1445  }
1446  return false;
1447 }
1448 
1450  /*
1451  * If the flow is Local + Ingress + Reverse
1452  * then it will be considered as server session
1453  */
1457  return true;
1458  }
1459  /*
1460  * If the flow is (Egress + Forward) OR
1461  * (Ingress + Reverse)
1462  * then it will be consideres as server session
1463  */
1466  return true;
1467  }
1468  } else {
1470  return true;
1471  }
1472  }
1473  return false;
1474 }
1476 // Flow entry fileds updation routines
1478 std::string FlowEntry::DropReasonStr(uint16_t reason) {
1479  std::map<uint16_t, const char*>::const_iterator it =
1480  FlowDropReasonStr.find(reason);
1481  if (it != FlowDropReasonStr.end()) {
1482  return string(it->second);
1483  }
1484  return "UNKNOWN";
1485 }
1486 
1487 // Get src-vn/sg-id/plen from route
1488 // src-vn and sg-id are used for policy lookup
1489 // plen is used to track the routes to use by flow_mgmt module
1491  Agent *agent = flow_table()->agent();
1492  const InetUnicastRouteEntry *inet_rt =
1493  dynamic_cast<const InetUnicastRouteEntry *>(rt);
1494 
1495  if (inet_rt && is_flags_set(FlowEntry::FabricFlow)) {
1496  const VrfEntry *policy_vrf =
1497  static_cast<const VrfEntry *>(agent->
1498  vrf_table()->FindVrfFromId(data_.src_policy_vrf));
1499 
1500  //Policy lookup needs to happen in Policy VRF
1501  AgentRoute *new_rt = GetUcRoute(policy_vrf,
1502  inet_rt->prefix_address());
1503  data_.src_policy_plen = 0;
1504  if (new_rt) {
1505  rt = new_rt;
1506  inet_rt = dynamic_cast<const InetUnicastRouteEntry *>(new_rt);
1507  data_.src_policy_plen = inet_rt->prefix_length();
1508  data_.src_policy_vrf = inet_rt->vrf()->vrf_id();
1509  }
1510  }
1511 
1512  const AgentPath *path = NULL;
1513  if (rt) {
1514  path = rt->GetActivePath();
1515  }
1516  if (path == NULL) {
1520  data_.source_plen = 0;
1523  } else {
1524  data_.source_vn_list = path->dest_vn_list();
1525  if (path->dest_vn_list().size())
1526  data_.source_vn_match = *path->dest_vn_list().begin();
1527  data_.origin_vn_src = path->origin_vn();
1528  if (!path->origin_vn().empty()) {
1529  data_.origin_vn_src_list.insert(path->origin_vn());
1530  }
1531  data_.source_sg_id_l = path->sg_list();
1533  data_.source_tag_id_l = path->tag_list();
1534  }
1535  /* Handle case when default route NextHop points to vrf */
1536  if (rt) {
1537  const NextHop *anh = rt->GetActiveNextHop();
1538  if (anh && anh->GetType() == NextHop::VRF) {
1539  const VrfNH *nh =
1540  static_cast<const VrfNH *>(anh);
1541  AgentRoute *new_rt = GetUcRoute(nh->GetVrf(), key_.src_addr);
1542  if (new_rt) {
1543  path = new_rt->GetActivePath();
1544  if (path) {
1545  data_.origin_vn_src = path->origin_vn();
1546  if (!path->origin_vn().empty()) {
1547  data_.origin_vn_src_list.insert(path->origin_vn());
1548  }
1549  }
1550  }
1551  }
1552  }
1553 
1554 }
1555 
1556 // Get dst-vn/sg-id/plen from route
1557 // dst-vn and sg-id are used for policy lookup
1558 // plen is used to track the routes to use by flow_mgmt module
1560  Agent *agent = flow_table()->agent();
1561  const AgentPath *path = NULL;
1562  if (rt) {
1563  path = rt->GetActivePath();
1564  }
1565 
1566  const InetUnicastRouteEntry *inet_rt =
1567  dynamic_cast<const InetUnicastRouteEntry *>(rt);
1568  if (inet_rt && is_flags_set(FlowEntry::FabricFlow)) {
1569  data_.dst_policy_plen = 0;
1570  const VrfEntry *policy_vrf =
1571  static_cast<const VrfEntry *>(agent->
1572  vrf_table()->FindVrfFromId(data_.dst_policy_vrf));
1573 
1574  AgentRoute *new_rt =
1575  GetUcRoute(policy_vrf, inet_rt->prefix_address());
1576  if (new_rt) {
1577  rt = new_rt;
1578  inet_rt = dynamic_cast<const InetUnicastRouteEntry *>(rt);
1579  data_.dst_policy_plen = inet_rt->prefix_length();
1580  data_.dst_policy_vrf = inet_rt->vrf()->vrf_id();
1581  }
1582  }
1583 
1584  if (rt) {
1585  path = rt->GetActivePath();
1586  }
1587 
1588  if (path == NULL) {
1592  data_.dest_plen = 0;
1595  } else {
1596  data_.dest_vn_list = path->dest_vn_list();
1597  if (path->dest_vn_list().size())
1598  data_.dest_vn_match = *path->dest_vn_list().begin();
1599  data_.origin_vn_dst = path->origin_vn();
1600  if (!path->origin_vn().empty()) {
1601  data_.origin_vn_dst_list.insert(path->origin_vn());
1602  }
1603  data_.dest_sg_id_l = path->sg_list();
1604  data_.dest_plen = rt->prefix_length();
1605  data_.dest_tag_id_l = path->tag_list();
1606  }
1607 
1608  /* Handle case when default route NextHop points to vrf */
1609  if (rt) {
1610  const NextHop *anh = rt->GetActiveNextHop();
1611  if (anh && anh->GetType() == NextHop::VRF) {
1612  const VrfNH *nh =
1613  static_cast<const VrfNH *>(anh);
1614  AgentRoute *new_rt = GetUcRoute(nh->GetVrf(), key_.dst_addr);
1615  if (new_rt) {
1616  path = new_rt->GetActivePath();
1617  if (path) {
1618  data_.origin_vn_dst = path->origin_vn();
1619  if (!path->origin_vn().empty()) {
1620  data_.origin_vn_dst_list.insert(path->origin_vn());
1621  }
1622  }
1623  }
1624  }
1625  }
1626 }
1627 
1629  if (id != Interface::kInvalidIndex) {
1630  Interface *itf = agent->interface_table()->FindInterface(id);
1631  if (itf && (itf->type() == Interface::VM_INTERFACE)) {
1633  itf->name());
1634  }
1635  }
1636  return VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, nil_uuid(), "");
1637 }
1638 
1639 uint32_t FlowEntry::InterfaceKeyToId(Agent *agent, const VmInterfaceKey &key) {
1640  const Interface *intf = dynamic_cast<const Interface*>
1641  (agent->interface_table()->FindActiveEntry(&key));
1642  if (intf) {
1643  return intf->id();
1644  }
1645  return Interface::kInvalidIndex;
1646 }
1647 
1648 const std::string FlowEntry::InterfaceIdToVmCfgName(Agent *agent, uint32_t id) {
1649  if (id != Interface::kInvalidIndex) {
1650  const VmInterface *itf = dynamic_cast <const VmInterface *>
1651  (agent->interface_table()->FindInterface(id));
1652  if (itf) {
1653  const VmEntry *vm = itf->vm();
1654  if (vm) {
1655  return vm->GetCfgName();
1656  }
1657  }
1658  }
1659  return "";
1660 }
1662 // Routines to compute ACL to be applied (including network-policy, SG and
1663 // VRF-Assign Rules
1666  /* Reset acl list*/
1667  data_.match_p.m_acl_l.clear();
1668  data_.match_p.m_out_acl_l.clear();
1669  data_.match_p.m_mirror_acl_l.clear();
1671  /* Reset sg acl list*/
1676 }
1677 
1678 // Rebuild all the policy rules to be applied
1679 void FlowEntry::GetPolicyInfo(const VnEntry *vn, const FlowEntry *rflow) {
1680  if (vn == NULL) {
1681  return;
1682  }
1683 
1684  // Reset old values first
1685  ResetPolicy();
1686 
1687  // Short flows means there is some information missing for the flow. Skip
1688  // getting policy information for short flow. When the information is
1689  // complete, GetPolicyInfo is called again
1691  return;
1692  }
1693 
1694  // ACL supported on VMPORT interfaces only
1695  if (data_.intf_entry == NULL)
1696  return;
1697 
1698  bool vgw_pass = true;
1699  if (data_.intf_entry->type() == Interface::INET) {
1700  vgw_pass = false;
1701  InetInterface* inet_intf = (InetInterface*)(data_.intf_entry).get();
1702  if ((inet_intf != NULL) && (inet_intf->sub_type() == InetInterface::SIMPLE_GATEWAY))
1703  vgw_pass = true;
1704  }
1705  if ((data_.intf_entry->type() != Interface::VM_INTERFACE) && !vgw_pass)
1706  return;
1707 
1708  // Get Network policy/mirror cfg policy/mirror policies
1709  GetPolicy(vn, rflow);
1710 
1711  // Get Sg list
1712  GetSgList(data_.intf_entry.get());
1713 
1714  //Get VRF translate ACL
1715  GetVrfAssignAcl();
1716 
1717  //Get Application policy set ACL
1719 
1720 }
1721 
1724 }
1725 
1728 }
1729 
1731  GetPolicyInfo(data_.vn_entry.get(), rflow);
1732 }
1733 
1734 void FlowEntry::GetPolicy(const VnEntry *vn, const FlowEntry *rflow) {
1735  if (vn == NULL)
1736  return;
1737 
1738  MatchAclParams acl;
1739 
1740  // Get Mirror configuration first
1741  if (vn->GetMirrorAcl()) {
1742  acl.acl = vn->GetMirrorAcl();
1743  data_.match_p.m_mirror_acl_l.push_back(acl);
1744  }
1745 
1746  if (vn->GetMirrorCfgAcl()) {
1747  acl.acl = vn->GetMirrorCfgAcl();
1748  data_.match_p.m_mirror_acl_l.push_back(acl);
1749  }
1750 
1751  // Dont apply network-policy for linklocal, bgp router service
1752  // and subnet broadcast flow
1758  return;
1759  }
1760 
1761  if (vn->GetAcl()) {
1762  acl.acl = vn->GetAcl();
1763  data_.match_p.m_acl_l.push_back(acl);
1764  }
1765 
1766  const VnEntry *rvn = NULL;
1767  // For local flows, we have to apply NW Policy from out-vn also
1768  if (!is_flags_set(FlowEntry::LocalFlow) || rflow == NULL) {
1769  // Not local flow
1770  return;
1771  }
1772 
1773  rvn = rflow->vn_entry();
1774  if (rvn == NULL) {
1775  return;
1776  }
1777 
1778  if (rvn->GetAcl()) {
1779  acl.acl = rvn->GetAcl();
1780  data_.match_p.m_out_acl_l.push_back(acl);
1781  }
1782 
1783  if (rvn->GetMirrorAcl()) {
1784  acl.acl = rvn->GetMirrorAcl();
1785  data_.match_p.m_out_mirror_acl_l.push_back(acl);
1786  }
1787 
1788  if (rvn->GetMirrorCfgAcl()) {
1789  acl.acl = rvn->GetMirrorCfgAcl();
1790  data_.match_p.m_out_mirror_acl_l.push_back(acl);
1791  }
1792 }
1793 
1795  // VRF-Assign rules valid only for routed packets
1796  if (l3_flow() == false)
1797  return;
1798 
1799  if (data_.intf_entry == NULL) {
1800  return;
1801  }
1802 
1803  if (data_.intf_entry->type() != Interface::VM_INTERFACE) {
1804  return;
1805  }
1806 
1812  return;
1813  }
1814 
1815  const VmInterface *intf =
1816  static_cast<const VmInterface *>(data_.intf_entry.get());
1817  //If interface has a VRF assign rule, choose the acl and match the
1818  //packet, else get the acl attached to VN and try matching the packet to
1819  //network acl
1820  const AclDBEntry* acl = NULL;
1821  if (is_flags_set(FlowEntry::NatFlow) == false) {
1822  acl = intf->vrf_assign_acl();
1823  }
1824 
1825  if (acl == NULL) {
1826  acl = data_.vn_entry.get()->GetAcl();
1827  }
1828  if (!acl) {
1829  return;
1830  }
1831 
1832  MatchAclParams m_acl;
1833  m_acl.acl = acl;
1834  data_.match_p.m_vrf_assign_acl_l.push_back(m_acl);
1835 }
1836 
1837 void FlowEntry::GetSgList(const Interface *intf) {
1838  // Dont apply network-policy for linklocal and multicast flows
1843  return;
1844  }
1845 
1846  // SG ACL's are reflexive. Skip SG for reverse flow
1848  return;
1849  }
1850 
1851  // Get virtual-machine port for forward flow
1852  const VmInterface *vm_port = NULL;
1853  bool vgw_pass = false;
1854  if (intf != NULL) {
1855  if (intf->type() == Interface::INET) {
1856  const InetInterface* inet_intf = static_cast<const InetInterface *>(intf);
1857  if ((inet_intf != NULL) && (inet_intf->sub_type() == InetInterface::SIMPLE_GATEWAY)) {
1858  vgw_pass = true;
1859  }
1860  }
1861  if (intf->type() == Interface::VM_INTERFACE) {
1862  vm_port = static_cast<const VmInterface *>(intf);
1863  vgw_pass = true;
1864  }
1865  }
1866 
1867  if (!vgw_pass) {
1868  return;
1869  }
1870 
1871  // Get virtual-machine port for reverse flow
1872  FlowEntry *rflow = reverse_flow_entry();
1873  const VmInterface *reverse_vm_port = NULL;
1874  if (rflow != NULL) {
1875  if (rflow->data().intf_entry.get() != NULL) {
1876  if (rflow->data().intf_entry->type() == Interface::VM_INTERFACE) {
1877  reverse_vm_port = static_cast<const VmInterface *>
1878  (rflow->data().intf_entry.get());
1879  }
1880  }
1881  }
1882 
1883  // Get SG-Rules
1885  GetLocalFlowSgList(vm_port, reverse_vm_port);
1886  } else {
1887  GetNonLocalFlowSgList(vm_port);
1888  }
1889 }
1890 
1892  const FlowEntry *rflow) {
1897  return;
1898  }
1899 
1901  return;
1902  }
1903 
1904  const VmInterface *vm_port = NULL;
1905  if (intf != NULL) {
1906  if (intf->type() == Interface::VM_INTERFACE) {
1907  vm_port = static_cast<const VmInterface *>(intf);
1908  }
1909  }
1910 
1911  if (vm_port != NULL) {
1912  MatchAclParams acl;
1913  FirewallPolicyList::const_iterator it =
1914  vm_port->fw_policy_list().begin();
1915  for(; it != vm_port->fw_policy_list().end(); it++) {
1916  acl.acl = *it;
1917  data_.match_p.aps_policy.m_acl_l.push_back(acl);
1921  }
1922 
1923  // Get the ACL for FWAAS
1924  it = vm_port->fwaas_fw_policy_list().begin();
1925  for(; it != vm_port->fwaas_fw_policy_list().end(); it++) {
1926  acl.acl = *it;
1927  data_.match_p.fwaas_policy.m_acl_l.push_back(acl);
1931  }
1932  }
1933 
1934  // For local flows, we have to apply NW Policy from out-vn also
1935  if (!is_flags_set(FlowEntry::LocalFlow) || rflow == NULL) {
1936  // Not local flow
1937  return;
1938  }
1939 
1940  const Interface *r_intf = rflow->data_.intf_entry.get();
1941  if (r_intf == NULL) {
1942  return;
1943  }
1944 
1945  vm_port = dynamic_cast<const VmInterface *>(r_intf);
1946  if (vm_port != NULL) {
1947  MatchAclParams acl;
1948  FirewallPolicyList::const_iterator it =
1949  vm_port->fw_policy_list().begin();
1950  for(; it != vm_port->fw_policy_list().end(); it++) {
1951  acl.acl = *it;
1952  data_.match_p.aps_policy.m_out_acl_l.push_back(acl);
1954  data_.match_p.aps_policy.m_reverse_acl_l.push_back(acl);
1956  }
1957 
1958  // Get the ACL for FWAAS
1959  it = vm_port->fwaas_fw_policy_list().begin();
1960  for(; it != vm_port->fwaas_fw_policy_list().end(); it++) {
1961  acl.acl = *it;
1962  data_.match_p.fwaas_policy.m_out_acl_l.push_back(acl);
1964  data_.match_p.fwaas_policy.m_reverse_acl_l.push_back(acl);
1966  }
1967  }
1968 }
1969 
1970 // Ingress-ACL/Egress-ACL in interface with VM as reference point.
1971 // Ingress : Packet to VM
1972 // Egress : Packet from VM
1973 // The direction stored in flow is defined with vrouter as reference point
1974 // Ingress : Packet to Vrouter from VM
1975 // Egress : Packet from Vrouter to VM
1976 //
1977 // Function takes care of copying right rules
1978 static bool CopySgEntries(const VmInterface *vm_port, bool ingress_acl,
1979  std::list<MatchAclParams> &list) {
1980  /* If policy is NOT enabled on VMI, do not copy SG rules */
1981  if (!vm_port->policy_enabled()) {
1982  return false;
1983  }
1984  bool ret = false;
1985  for (VmInterface::SecurityGroupEntrySet::const_iterator it =
1986  vm_port->sg_list().list_.begin();
1987  it != vm_port->sg_list().list_.end(); ++it) {
1988  if (it->sg_ == NULL)
1989  continue;
1990 
1991  if (it->sg_->IsAclSet()) {
1992  ret = true;
1993  }
1994  MatchAclParams acl;
1995  // As per definition above,
1996  // get EgressACL if flow direction is Ingress
1997  // get IngressACL if flow direction is Egress
1998  if (ingress_acl) {
1999  acl.acl = it->sg_->GetEgressAcl();
2000  } else {
2001  acl.acl = it->sg_->GetIngressAcl();
2002  }
2003  if (acl.acl)
2004  list.push_back(acl);
2005  }
2006 
2007  return ret;
2008 }
2009 
2011  const VmInterface *reverse_vm_port) {
2012  // Get SG-Rule for the forward flow
2013  if (vm_port) {
2015  CopySgEntries(vm_port, true, data_.match_p.sg_policy.m_acl_l);
2016  }
2017  // For local flow, we need to simulate SG lookup at both ends.
2018  // Assume packet is from VM-A to VM-B.
2019  // If we apply Ingress-ACL from VM-A, then apply Egress-ACL from VM-B
2020  // If we apply Egress-ACL from VM-A, then apply Ingress-ACL from VM-B
2021  if (reverse_vm_port) {
2023  CopySgEntries(reverse_vm_port, false, data_.match_p.sg_policy.m_out_acl_l);
2024  }
2026  return;
2027  }
2028  // TCP ACK workaround:
2029  // Ideally TCP State machine should be run to age TCP flows
2030  // Temporary workaound in place of state machine. For TCP ACK packets allow
2031  // the flow if either forward or reverse flow is allowed
2032 
2033  // Copy the SG rules to be applied for reverse flow
2034  if (vm_port) {
2036  CopySgEntries(vm_port, false,
2038  }
2039 
2040  if (reverse_vm_port) {
2042  CopySgEntries(reverse_vm_port, true,
2044  }
2045 }
2046 
2048  // Get SG-Rule for the forward flow
2049  bool ingress = is_flags_set(FlowEntry::IngressDir);
2050  if (vm_port) {
2052  CopySgEntries(vm_port, ingress,
2054  }
2055 
2057 
2059  return;
2060  }
2061 
2062  // TCP ACK workaround:
2063  // Ideally TCP State machine should be run to age TCP flows
2064  // Temporary workaound in place of state machine. For TCP ACK packets allow
2065  // the flow if either forward or reverse flow is allowed
2066 
2067  // Copy the SG rules to be applied for reverse flow
2068  if (vm_port) {
2070  CopySgEntries(vm_port, !ingress,
2072  }
2074 }
2075 
2076 // For an L2-Flow, refresh the vn-list and sg-list from the route used for
2077 // flow
2079  // Skip L3-Flows
2080  if (l3_flow())
2081  return;
2082 
2083  Agent *agent = flow_table()->agent();
2084  // Get VRF for the flow. L2 flow have same in and out-vrf. So, use same
2085  // vrf for both smac and dmac lookup
2086  uint32_t vrf_id = data().flow_source_vrf;
2087  const VrfEntry *vrf = agent->vrf_table()->FindVrfFromId(vrf_id);
2088  if (vrf == NULL || vrf->IsDeleted()) {
2089  return;
2090  }
2091  BridgeAgentRouteTable *table =
2092  static_cast<BridgeAgentRouteTable *>(vrf->GetBridgeRouteTable());
2093 
2094  // Get route-info for smac
2096  // Get route-info for dmac
2097  GetDestRouteInfo(table->FindRoute(data().dmac));
2098 }
2099 
2101 // Flow policy processing routines
2103 
2104 // Set HBS information
2105 // |-------------------------------------------------------------------------|
2106 // | Source | Destination: VMI | Destination: Fabric|
2107 // |--------------------------------------------------------------------------
2108 // | VMI | L (src vif index < dst vif index) | L |
2109 // | | else R | |
2110 // |--------------------------------------------------------------------------
2111 // | Fabric | R | - |
2112 // |-------------------------------------------------------------------------|
2113 //
2115 
2119  return;
2120  }
2121 
2122  const VmInterface *src_intf =
2123  dynamic_cast<const VmInterface *>(intf_entry());
2124  FlowEntry *rev_flow = reverse_flow_entry();
2125  const VmInterface *dst_intf =
2126  dynamic_cast<const VmInterface *>(rev_flow->intf_entry());
2127 
2128  if ( src_intf == NULL || dst_intf == NULL ) {
2131  return;
2132  }
2133 
2134  //Enable HBF flow flag
2135  set_flags(HbfFlow);
2136  if (is_flags_set(LocalFlow)) {
2137  /* Handle Service Chain Traffic for local flow VM <--> SI*/
2138  /* Case 1: Reset the HBS Action if flow source is service interface */
2139  if (!src_intf->service_intf_type().empty()) {
2142  return;
2143  }
2144  /* Case 2: Set appropriate interface left/right based on service interface type */
2145  if (!dst_intf->service_intf_type().empty()) {
2146  if (dst_intf->service_intf_type() == "left") {
2148  } else if (dst_intf->service_intf_type() == "right") {
2150  }
2151  return;
2152  }
2153  // VM <--> VM on same compute
2154  (src_intf->id() < dst_intf->id()) ?
2157  } else {
2158  /* Handle Service chain traffic entering the compute */
2159  if ((!src_intf->service_intf_type().empty() ||
2160  !dst_intf->service_intf_type().empty())) {
2161  if (is_flags_set(IngressDir) == 0) {
2162  if (dst_intf->service_intf_type() == "left") {
2164  } else if (dst_intf->service_intf_type() == "right") {
2166  }
2167  } else {
2170  }
2171  } else {
2172  // VM <--> VM on different compute
2176  }
2177  }
2178 }
2179 
2182  (1 << TrafficAction::VRF_TRANSLATE))) {
2183  //If VRF assign was evaluated and the vrf translate
2184  //action is not present in latest evaluation mark the
2185  //flow as short flow
2188  != Agent::NullString()) {
2190  }
2191  data_.vrf_assign_evaluated = true;
2193  return;
2194  }
2195 
2196  std::string vrf_assigned_name =
2198  std::list<MatchAclParams>::const_iterator acl_it;
2199  for (acl_it = match_p().m_vrf_assign_acl_l.begin();
2200  acl_it != match_p().m_vrf_assign_acl_l.end();
2201  ++acl_it) {
2202  std::string vrf = acl_it->action_info.vrf_translate_action_.vrf_name();
2204  //Check if VRF assign acl says, network ACL and SG action
2205  //to be ignored
2206  bool ignore_acl =
2207  acl_it->action_info.vrf_translate_action_.ignore_acl();
2209  (ignore_acl);
2210  }
2211  if (data_.vrf_assign_evaluated && vrf_assigned_name !=
2214  }
2215 
2219  }
2220  data_.vrf_assign_evaluated = true;
2221 }
2222 
2223 uint32_t FlowEntry::MatchAcl(const PacketHeader &hdr,
2224  std::list<MatchAclParams> &acl,
2225  bool add_implicit_deny, bool add_implicit_allow,
2226  FlowPolicyInfo *info) {
2227  PktHandler *pkt_handler = Agent::GetInstance()->pkt()->pkt_handler();
2228 
2229  // If there are no ACL to match, make it pass
2230  if (acl.size() == 0 && add_implicit_allow) {
2231  if (info) {
2232  /* We are setting UUIDs for linklocal and multicast flows here,
2233  * because even if we move this to the place where acl association
2234  * is being skipped, we still need checks for linklocal and
2235  * multicast flows here to avoid its value being overwritten with
2236  * IMPLICIT_ALLOW
2237  */
2240  } else if (is_flags_set(FlowEntry::Multicast)) {
2244  } else {
2245  /* We need to make sure that info is not already populated
2246  * before setting it to IMPLICIT_ALLOW. This is required
2247  * because info could earlier be set by previous call to
2248  * MatchAcl. We should note here that same 'info' var is passed
2249  * for MatchAcl calls with in_acl and out_acl
2250  */
2251  if (!info->terminal && !info->other) {
2253  }
2254  }
2255  }
2256  return (1 << TrafficAction::PASS);
2257  }
2258 
2259  // PASS default GW traffic, if it is ICMP or DNS
2260  if ((hdr.protocol == IPPROTO_ICMP ||
2261  (hdr.protocol == IPPROTO_UDP &&
2262  (hdr.src_port == DNS_SERVER_PORT ||
2263  hdr.dst_port == DNS_SERVER_PORT))) &&
2264  (pkt_handler->IsGwPacket(data_.intf_entry.get(), hdr.dst_ip) ||
2265  pkt_handler->IsGwPacket(data_.intf_entry.get(), hdr.src_ip))) {
2266  if (info) {
2268  }
2269  return (1 << TrafficAction::PASS);
2270  }
2271 
2272  uint32_t action = 0;
2273  for (std::list<MatchAclParams>::iterator it = acl.begin();
2274  it != acl.end(); ++it) {
2275  if (it->acl.get() == NULL) {
2276  continue;
2277  }
2278 
2279  if (it->acl->PacketMatch(hdr, *it, info)) {
2280  action |= it->action_info.action;
2281  if (it->action_info.action & (1 << TrafficAction::MIRROR)) {
2284  it->action_info.mirror_l.begin(),
2285  it->action_info.mirror_l.end());
2286  }
2287 
2288  if (it->terminal_rule) {
2289  break;
2290  }
2291  }
2292  }
2293 
2294  // If no acl matched, make it imlicit deny
2295  if (action == 0 && add_implicit_deny) {
2296  action = (1 << TrafficAction::DENY) |
2298  if (info) {
2300  info->drop = true;
2301  }
2302  }
2303 
2304  return action;
2305 }
2306 
2308  hdr->vrf = data_.vrf;
2309  hdr->src_ip = key_.src_addr;
2310  hdr->dst_ip = key_.dst_addr;
2311  hdr->protocol = key_.protocol;
2312  if (hdr->protocol == IPPROTO_UDP || hdr->protocol == IPPROTO_TCP) {
2313  hdr->src_port = key_.src_port;
2314  hdr->dst_port = key_.dst_port;
2315  } else {
2316  hdr->src_port = 0;
2317  hdr->dst_port = 0;
2318  }
2320  hdr->dst_policy_id = &(data_.dest_vn_list);
2321  hdr->src_sg_id_l = &(data_.source_sg_id_l);
2322  hdr->dst_sg_id_l = &(data_.dest_sg_id_l);
2324  hdr->dst_tags_ = data_.dest_tag_id_l;
2325  hdr->family = key_.family;
2326 }
2327 
2328 // In case of NAT flows, the key fields can change.
2330  FlowEntry *rflow = reverse_flow_entry();
2331  if (rflow == NULL)
2332  return;
2333 
2334  hdr->vrf = rflow->data().vrf;
2335  hdr->src_ip = rflow->key().dst_addr;
2336  hdr->dst_ip = rflow->key().src_addr;
2337  hdr->protocol = rflow->key().protocol;
2338  if (hdr->protocol == IPPROTO_UDP || hdr->protocol == IPPROTO_TCP) {
2339  hdr->src_port = rflow->key().dst_port;
2340  hdr->dst_port = rflow->key().src_port;
2341  } else {
2342  hdr->src_port = 0;
2343  hdr->dst_port = 0;
2344  }
2345  hdr->src_policy_id = &(rflow->data().dest_vn_list);
2346  hdr->dst_policy_id = &(rflow->data().source_vn_list);
2347  hdr->src_sg_id_l = &(rflow->data().dest_sg_id_l);
2348  hdr->dst_sg_id_l = &(rflow->data().source_sg_id_l);
2349  hdr->src_tags_ = rflow->data_.dest_tag_id_l;
2350  hdr->dst_tags_ = rflow->data_.source_tag_id_l;
2351  hdr->family = key_.family;
2352 }
2353 
2355  const FlowPolicyInfo &fwd_flow_info,
2356  const FlowPolicyInfo &rev_flow_info,
2357  bool tcp_rev, bool is_sg) {
2358 
2359  FlowEntry *rflow = reverse_flow_entry();
2360  if (rflow == NULL) {
2361  return;
2362  }
2363 
2364  sp->rule_uuid_ = fwd_flow_info.uuid;
2365  sp->acl_name_ = fwd_flow_info.acl_name;
2366 
2367  rsp->rule_uuid_ = rev_flow_info.uuid;
2368  rsp->acl_name_ = rev_flow_info.acl_name;
2369 
2370  //If Forward flow SG rule says drop, copy corresponding
2371  //ACE id to both forward and reverse flow
2372  if (fwd_flow_info.drop) {
2373  rsp->rule_uuid_ = fwd_flow_info.uuid;
2374  rsp->acl_name_ = fwd_flow_info.acl_name;
2375  return;
2376  }
2377 
2378  //If reverse flow SG rule says drop, copy corresponding
2379  //ACE id to both forward and reverse flow
2380  if (rev_flow_info.drop) {
2381  sp->rule_uuid_ = rev_flow_info.uuid;
2382  sp->acl_name_ = rev_flow_info.acl_name;
2383  return;
2384  }
2385 
2386  if (tcp_rev == false) {
2387  if (is_sg) {
2388  if (data_.match_p.sg_policy.rule_present == false) {
2389  sp->rule_uuid_ = rev_flow_info.uuid;
2390  sp->acl_name_ = rev_flow_info.acl_name;
2391  }
2392 
2393  if (data_.match_p.sg_policy.out_rule_present == false) {
2394  rsp->rule_uuid_ = fwd_flow_info.uuid;
2395  rsp->acl_name_ = fwd_flow_info.acl_name;
2396  }
2397  } else {
2398  if (data_.match_p.aps_policy.rule_present == false) {
2399  sp->rule_uuid_ = rev_flow_info.uuid;
2400  sp->acl_name_ = rev_flow_info.acl_name;
2401  }
2402 
2403  if (data_.match_p.aps_policy.out_rule_present == false) {
2404  rsp->rule_uuid_ = fwd_flow_info.uuid;
2405  rsp->acl_name_ = fwd_flow_info.acl_name;
2406  }
2407  }
2408  }
2409 
2410  if (tcp_rev == true) {
2411  if (sp->reverse_rule_present == false) {
2412  rsp->rule_uuid_ = fwd_flow_info.uuid;
2413  rsp->acl_name_ = fwd_flow_info.acl_name;
2414  }
2415 
2416  if (sp->reverse_out_rule_present == false) {
2417  sp->rule_uuid_ = rev_flow_info.uuid;
2418  sp->acl_name_ = rev_flow_info.acl_name;
2419  }
2420  }
2421 }
2422 
2424  bool is_sg) {
2425 
2426  FlowEntry *rflow = reverse_flow_entry();
2427  const string value = FlowPolicyStateStr.at(NOT_EVALUATED);
2428  FlowPolicyInfo acl_info(value);
2429  FlowPolicyInfo out_acl_info(value);
2430  FlowPolicyInfo rev_acl_info(value);
2431  FlowPolicyInfo rev_out_acl_info(value);
2432 
2434  sp->acl_name_ = "";
2435 
2436  if (rsp) {
2437  rsp->rule_uuid_ =
2439  rsp->acl_name_ = "";
2440  }
2441 
2442  PacketHeader hdr;
2443  SetPacketHeader(&hdr);
2444 
2445  //Apply ACL configured on ingress interface
2446  sp->action = MatchAcl(hdr, sp->m_acl_l, true, !sp->rule_present, &acl_info);
2447 
2448  //Apply ACL configured on egress interface
2449  PacketHeader out_hdr;
2450  if (ShouldDrop(sp->action) == false && rflow) {
2451  // Key fields for lookup in out-acl can potentially change in case
2452  // of NAT. Form ACL lookup based on post-NAT fields
2453  SetOutPacketHeader(&out_hdr);
2454  sp->out_action = MatchAcl(out_hdr, sp->m_out_acl_l, true,
2455  !sp->out_rule_present, &out_acl_info);
2456  }
2457 
2458  // For TCP-ACK packet, we allow packet if either forward or reverse
2459  // flow says allow. So, continue matching reverse flow even if forward
2460  // flow says drop
2461  if (is_flags_set(FlowEntry::TcpAckFlow) && rflow) {
2462  rflow->SetPacketHeader(&hdr);
2463  sp->reverse_action = MatchAcl(hdr, sp->m_reverse_acl_l, true,
2464  !sp->reverse_rule_present, &rev_acl_info);
2465 
2466  if (ShouldDrop(sp->reverse_action) == false) {
2467  // Key fields for lookup in out-acl can potentially change in
2468  // case of NAT. Form ACL lookup based on post-NAT fields
2469  rflow->SetOutPacketHeader(&out_hdr);
2470  sp->reverse_out_action = MatchAcl(out_hdr, sp->m_reverse_out_acl_l,
2471  true, !sp->reverse_out_rule_present,
2472  &rev_out_acl_info);
2473  }
2474  }
2475 
2476  // Compute summary SG action.
2477  // For Non-TCP-ACK Flows
2478  // DROP if any of policy.action, out_action, policy.reverse_action or
2479  // policy.reverse_out_action says DROP
2480  // Only acl_info which is derived from sp->m_acl_l
2481  // and sp->m_out_acl_l will be populated. Pick the
2482  // UUID specified by acl_info for flow's SG rule UUID
2483  // For TCP-ACK flows
2484  // ALLOW if either ((policy.action && out_action) ||
2485  // (policy.reverse_action & policy.reverse_out_action))
2486  // ALLOW
2487  // For flow's SG rule UUID use the following rules
2488  // --If both acl_info and rev_acl_info has drop set, pick the
2489  // UUID from acl_info.
2490  // --If either of acl_info or rev_acl_info does not have drop
2491  // set, pick the UUID from the one which does not have drop set.
2492  // --If both of them does not have drop set, pick it up from
2493  // acl_info
2494  //
2496  sp->action_summary =
2497  sp->action | sp->out_action | sp->reverse_action | sp->reverse_out_action;
2498  SetAclInfo(sp, rsp, acl_info, out_acl_info, false, is_sg);
2499  } else if (ShouldDrop(sp->action | sp->out_action) &&
2501  //If both ingress ACL and egress ACL of VMI denies the
2502  //packet, then pick ingress ACE uuid to send to UVE
2503  sp->action_summary = (1 << TrafficAction::DENY);
2504  SetAclInfo(sp, rsp, acl_info, out_acl_info, false, is_sg);
2505  } else {
2506  sp->action_summary = (1 << TrafficAction::PASS);
2507  if (sp->action & (1 << TrafficAction::HBS) ||
2508  sp->out_action & (1 << TrafficAction::HBS) ||
2509  sp->reverse_action & (1 << TrafficAction::HBS) ||
2510  sp->reverse_out_action & (1 << TrafficAction::HBS)) {
2511  sp->action_summary|=(1 << TrafficAction::HBS);
2512  }
2513  if (!ShouldDrop(sp->action | sp->out_action)) {
2514  SetAclInfo(sp, rsp, acl_info, out_acl_info, false, is_sg);
2515  } else if (!ShouldDrop(sp->reverse_action | sp->reverse_out_action)) {
2516  SetAclInfo(sp, rsp, rev_out_acl_info, rev_acl_info, true, is_sg);
2517  }
2518  }
2519 }
2520 
2521 // Apply Policy and SG rules for a flow.
2522 //
2523 // Special case of local flows:
2524 // For local-flows, both VM are on same compute and we need to apply SG from
2525 // both the ports. sg_policy.m_acl_l will contain ACL for port in forward flow and
2526 // sg_policy.m_out_acl_l will have ACL from other port
2527 //
2528 // If forward flow goes thru NAT, the key for matching ACL in
2529 // sg_policy.m_out_acl_l can potentially change. The routine SetOutPacketHeader
2530 // takes care of forming header after NAT
2531 //
2532 // Rules applied are based on flow type
2533 // Non-Local Forward Flow
2534 // Network Policy.
2535 // Out-Network Policy will be empty
2536 // SG
2537 // Out-SG will be empty
2538 // Non-Local Reverse Flow
2539 // Network Policy.
2540 // Out-Network Policy will be empty
2541 // SG and out-SG from forward flow
2542 // Local Forward Flow
2543 // Network Policy.
2544 // Out-Network Policy
2545 // SG
2546 // Out-SG
2547 // Local Reverse Flow
2548 // Network Policy.
2549 // Out-Network Policy
2550 // SG and out-SG from forward flow
2553  return true;
2554  }
2560 
2564 
2565  const string value = FlowPolicyStateStr.at(NOT_EVALUATED);
2566  FlowPolicyInfo nw_acl_info(value);
2567 
2568  FlowEntry *rflow = reverse_flow_entry();
2569  PacketHeader hdr;
2570  SetPacketHeader(&hdr);
2571 
2572  //Calculate VRF assign entry, and ignore acl is set
2573  //skip network and SG acl action is set
2575  {
2577  }
2578  else
2579  {
2583  }
2584 
2585  // Mirror is valid even if packet is to be dropped. So, apply it first
2587  false, true, NULL);
2588 
2589  // Apply out-policy. Valid only for local-flow
2591  data_.match_p.m_out_mirror_acl_l, false, true, NULL);
2592 
2593  // Apply network policy
2596  true, &nw_acl_info);
2598  goto done;
2600  true, true, &nw_acl_info);
2602  goto done;
2603  }
2604  else {
2605  if (rflow) {
2606  uint32_t r_policy_action = MatchAcl(hdr,
2607  rflow->data_.match_p.m_acl_l, true, true, &nw_acl_info);
2608  if (ShouldDrop(r_policy_action)) {
2610  goto done;
2611  }
2612  uint32_t r_out_policy_action = MatchAcl(hdr,
2613  rflow->data_.match_p.m_out_acl_l, true, true, &nw_acl_info);
2614  if (ShouldDrop(r_out_policy_action)) {
2616  goto done;
2617  }
2618  }
2619  }
2620 
2621  // Apply sg policy
2623  SessionPolicy *r_sg_policy = NULL;
2624  SessionPolicy *r_aps_policy = NULL;
2625  SessionPolicy *r_fwaas_policy = NULL;
2626 
2627  if (rflow) {
2628  r_sg_policy = &(rflow->data_.match_p.sg_policy);
2629  r_aps_policy = &(rflow->data_.match_p.aps_policy);
2630  r_fwaas_policy = &(rflow->data_.match_p.fwaas_policy);
2631  }
2632 
2633  SessionMatch(&data_.match_p.sg_policy, r_sg_policy, true);
2635  goto done;
2636  }
2637 
2638  SessionMatch(&data_.match_p.fwaas_policy, r_fwaas_policy, false);
2640  goto done;
2641  }
2642 
2643  SessionMatch(&data_.match_p.aps_policy, r_aps_policy, false);
2644  } else {
2645  // SG is reflexive ACL. For reverse-flow, copy SG action from
2646  // forward flow
2648  }
2649 
2650 done:
2651  nw_ace_uuid_ = nw_acl_info.uuid;
2652  if (!nw_acl_info.src_match_vn.empty())
2653  data_.source_vn_match = nw_acl_info.src_match_vn;
2654  if (!nw_acl_info.dst_match_vn.empty())
2655  data_.dest_vn_match = nw_acl_info.dst_match_vn;
2656  // Set mirror vrf after evaluation of actions
2658  //Set VRF assign action
2660  //Set HBS information
2662  // Summarize the actions based on lookups above
2663  ActionRecompute();
2664  return true;
2665 }
2666 
2668 // Flow policy action compute routines
2671  DoPolicy();
2672 
2673  // If this is forward flow, update the SG action for reflexive entry
2674  FlowEntry *rflow = (is_flags_set(FlowEntry::ReverseFlow) == false) ?
2675  reverse_flow_entry() : NULL;
2676  // Dont update reflexive entry for TcpAck Flows. Since it can flip
2677  // Deny state for the reflexive entry.
2678  if (!(is_flags_set(FlowEntry::TcpAckFlow)) && rflow) {
2679  // Update action for reverse flow
2680  rflow->UpdateReflexiveAction();
2681  //Set HBS information
2682  rflow->SetHbsInfofromAction();
2683  rflow->ActionRecompute();
2684  }
2685 }
2686 
2687 const VrfEntry*
2689  const VrfEntry *vrf = NULL;
2690  VrfTable *vrf_table = flow_table()->agent()->vrf_table();
2691 
2693  match_p().action_info.action & (1 << TrafficAction::VRF_TRANSLATE)) {
2694  vrf = vrf_table->FindVrfFromId(data().dest_vrf);
2695  } else {
2696  vrf = vrf_table->FindVrfFromId(data().vrf);
2697  }
2698  return vrf;
2699 }
2700 
2703  MatchAclParamsList::const_iterator it;
2704 
2705  // For reverse flows, first check if we have our own QoS config
2706  // (from interface), and only fall back to forward flow if not
2708  // First, check if reverse flow has its own QoS config from interface
2709  const VmInterface *intf =
2710  dynamic_cast<const VmInterface*>(data_.intf_entry.get());
2711  if (intf && intf->qos_config()) {
2712  i = intf->qos_config()->id();
2713  }
2714 
2715  // If still no QoS config, copy from forward flow
2717  FlowEntry *fwd_flow = reverse_flow_entry();
2718  if (fwd_flow) {
2719  i = fwd_flow->data().qos_config_idx;
2720  }
2721  }
2722 
2723  // If we got a valid QoS config, use it and return early
2725  if (i != data_.qos_config_idx) {
2726  data_.qos_config_idx = i;
2727  return true;
2728  }
2729  return false;
2730  }
2731  // If no QoS config found yet, continue with normal processing
2732  }
2733 
2734  // Priority of QOS config for forward flows (and reverse flows that didn't find config above)
2735  // 1> SG
2736  // 2> Interface
2737  // 3> ACL
2738  // 4> VN (handled through ACLs)
2740  for (it = data_.match_p.sg_policy.m_acl_l.begin();
2741  it != data_.match_p.sg_policy.m_acl_l.end(); it++) {
2742  if (it->action_info.action & 1 << TrafficAction::APPLY_QOS &&
2743  it->action_info.qos_config_action_.id()
2745  i = it->action_info.qos_config_action_.id();
2746  break;
2747  }
2748  }
2750  for (it = data_.match_p.sg_policy.m_out_acl_l.begin();
2751  it != data_.match_p.sg_policy.m_out_acl_l.end(); it++) {
2752  if (it->action_info.action & 1 << TrafficAction::APPLY_QOS &&
2753  it->action_info.qos_config_action_.id() !=
2755  i = it->action_info.qos_config_action_.id();
2756  break;
2757  }
2758  }
2760  for (it = data_.match_p.m_acl_l.begin();
2761  it != data_.match_p.m_acl_l.end(); it++) {
2762  if (it->action_info.action & 1 << TrafficAction::APPLY_QOS &&
2763  it->action_info.qos_config_action_.id() !=
2765  i = it->action_info.qos_config_action_.id();
2766  break;
2767  }
2768  }
2770  for (it = data_.match_p.m_out_acl_l.begin();
2771  it != data_.match_p.m_out_acl_l.end(); it++) {
2772  if (it->action_info.action & 1 << TrafficAction::APPLY_QOS &&
2773  it->action_info.qos_config_action_.id() !=
2775  i = it->action_info.qos_config_action_.id();
2776  break;
2777  }
2778  }
2779  }
2780 
2781  const VmInterface *intf =
2782  dynamic_cast<const VmInterface*>(data_.intf_entry.get());
2783  if (intf && intf->qos_config()) {
2784  if (intf->is_vn_qos_config() == false ||
2786  i = intf->qos_config()->id();
2787  }
2788  }
2789 
2790  if (i != data_.qos_config_idx) {
2791  data_.qos_config_idx = i;
2792  return true;
2793  }
2794 
2795  return false;
2796 }
2797 
2798 // Recompute FlowEntry action based on ACLs already set in the flow
2800  uint32_t action = 0;
2801  uint16_t drop_reason = DROP_UNKNOWN;
2802  bool ret = false;
2803 
2809 
2810  //Only VRF assign acl, can specify action to
2811  //translate VRF. VRF translate action specified
2812  //by egress VN ACL or ingress VN ACL should be ignored
2813  action &= ~(1 << TrafficAction::VRF_TRANSLATE);
2815 
2816  if (action & (1 << TrafficAction::VRF_TRANSLATE) &&
2818  //In case of multi inline service chain, match condition generated on
2819  //each of service instance interface takes higher priority than
2820  //network ACL. Match condition on the interface would have ignore acl
2821  //flag set to avoid applying two ACL for vrf translation
2825 
2826  //Pick mirror action from network ACL
2829  action |= (1 << TrafficAction::MIRROR);
2830  }
2831  }
2832 
2833  action &= ~(1 << TrafficAction::HBS);
2835  action |= (1 << TrafficAction::HBS);
2836  }
2837 
2838  if (SetQosConfigIndex()) {
2839  ret = true;
2840  }
2841 
2842  // check for conflicting actions and remove allowed action
2843  if (ShouldDrop(action)) {
2844  action = (action & ~TrafficAction::DROP_FLAGS &
2845  ~TrafficAction::PASS_FLAGS);
2846  action |= (1 << TrafficAction::DENY);
2848  drop_reason = short_flow_reason_;
2849  } else if (ShouldDrop(data_.match_p.policy_action)) {
2850  drop_reason = DROP_POLICY;
2851  } else if (ShouldDrop(data_.match_p.out_policy_action)) {
2852  drop_reason = DROP_OUT_POLICY;
2853  } else if (ShouldDrop(data_.match_p.sg_policy.action)) {
2854  drop_reason = DROP_SG;
2856  drop_reason = DROP_OUT_SG;
2858  drop_reason = DROP_REVERSE_SG;
2860  drop_reason = DROP_REVERSE_OUT_SG;
2861  } else if (ShouldDrop(data_.match_p.aps_policy.action)) {
2862  drop_reason = DROP_FIREWALL_POLICY;
2864  drop_reason = DROP_OUT_FIREWALL_POLICY;
2866  drop_reason = DROP_REVERSE_FIREWALL_POLICY;
2868  drop_reason = DROP_REVERSE_OUT_FIREWALL_POLICY;
2869  } else if (ShouldDrop(data_.match_p.fwaas_policy.action)) {
2870  drop_reason = DROP_FWAAS_POLICY;
2872  drop_reason = DROP_FWAAS_OUT_POLICY;
2874  drop_reason = DROP_FWAAS_REVERSE_POLICY;
2876  drop_reason = DROP_FWAAS_REVERSE_OUT_POLICY;
2877  } else {
2878  drop_reason = DROP_UNKNOWN;
2879  }
2880  }
2881 
2882  if (action & (1 << TrafficAction::TRAP)) {
2883  action = (1 << TrafficAction::TRAP);
2884  }
2885 
2886  if (action != data_.match_p.action_info.action) {
2887  data_.match_p.action_info.action = action;
2888  ret = true;
2889  }
2890  if (drop_reason != data_.drop_reason) {
2891  data_.drop_reason = drop_reason;
2892  ret = true;
2893  }
2894  return ret;
2895 }
2896 
2897 // SetMirrorVrfFromAction
2898 // For this flow check for mirror action from dynamic ACLs or policy mirroring
2899 // assign the vrf from its Virtual Nework that ACL is used
2900 // If it is a local flow and out mirror action or policy is set
2901 // assign the vrf of the reverse flow, since ACL came from the reverse flow
2905  const VnEntry *vn = vn_entry();
2906  if (vn && vn->GetVrf()) {
2907  SetMirrorVrf(vn->GetVrf()->vrf_id());
2908  }
2909  }
2912  FlowEntry *rflow = reverse_flow_entry_.get();
2913  if (rflow) {
2914  const VnEntry *rvn = rflow->vn_entry();
2915  if (rvn && rvn->GetVrf()) {
2916  SetMirrorVrf(rvn->GetVrf()->vrf_id());
2917  }
2918  }
2919  }
2920 }
2921 
2925  short_flow_reason_ = reason;
2926  }
2927  if (reverse_flow_entry_ &&
2928  !reverse_flow_entry_->is_flags_set(FlowEntry::ShortFlow)) {
2930  reverse_flow_entry_->short_flow_reason_ = reason;
2931  }
2932 }
2933 
2935  FlowEntry *rflow = reverse_flow_entry_.get();
2936  SessionPolicy *r_sg_policy = NULL;
2937  SessionPolicy *r_aps_policy = NULL;
2938  SessionPolicy *r_fwaas_policy = NULL;
2939 
2940  if (rflow) {
2941  r_sg_policy = &(rflow->data_.match_p.sg_policy);
2942  r_aps_policy = &(rflow->data_.match_p.aps_policy);
2943  r_fwaas_policy = &(rflow->data_.match_p.fwaas_policy);
2944  }
2945 
2948  UpdateReflexiveAction(&data_.match_p.fwaas_policy, r_fwaas_policy);
2949 }
2950 
2952  sp->action = (1 << TrafficAction::PASS);
2953  sp->out_action = (1 << TrafficAction::PASS);
2954  sp->reverse_action = (1 << TrafficAction::PASS);;
2956  sp->action_summary = rsp->action_summary;
2957 
2958  if (ShouldDrop(sp->action_summary) == false) {
2959  return;
2960  }
2961 
2963  sp->action |= (1 << TrafficAction::TRAP);
2964 }
2965 
2967 // Routines to manage pending actions on a flow. The pending actions are used
2968 // to state-compress actions trigged due to update of,
2969 // - DBEntries like interface, ACL etc..
2970 // - Routes
2973  Reset();
2974 }
2975 
2977 }
2978 
2980  delete_ = false;
2981  recompute_ = false;
2982  recompute_dbentry_ = false;
2983  revaluate_ = false;
2984 }
2985 
2987  if (delete_)
2988  return false;
2989 
2990  delete_ = true;
2991  return true;
2992 }
2993 
2995  delete_ = false;
2996  recompute_ = false;
2997  recompute_dbentry_ = false;
2998  revaluate_ = false;
2999 }
3000 
3002  return delete_;
3003 }
3004 
3006  if (delete_ || recompute_)
3007  return false;
3008 
3009  recompute_ = true;
3010  return true;
3011 }
3012 
3014  recompute_ = false;
3015  recompute_dbentry_ = false;
3016  revaluate_ = false;
3017 }
3018 
3020  if (delete_)
3021  return false;
3022 
3023  return recompute_;
3024 }
3025 
3028  return false;
3029 
3030  recompute_dbentry_ = true;
3031  return true;
3032 }
3033 
3035  recompute_dbentry_ = false;
3036  revaluate_ = false;
3037 }
3038 
3040  if (delete_ || recompute_)
3041  return false;
3042 
3043  return recompute_dbentry_;
3044 }
3045 
3048  return false;
3049 
3050  revaluate_ = true;
3051  return true;
3052 }
3053 
3055  revaluate_ = false;
3056 }
3057 
3060  return false;
3061 
3062  return revaluate_;
3063 }
3064 
3066 // Introspect routines
3068 void SetActionStr(const FlowAction &action_info,
3069  std::vector<ActionStr> &action_str_l) {
3070  std::bitset<32> bs(action_info.action);
3071  for (unsigned int i = 0; i < bs.size(); i++) {
3072  if (bs[i]) {
3073  ActionStr astr;
3074  astr.action =
3076  action_str_l.push_back(astr);
3078  std::vector<MirrorActionSpec>::const_iterator m_it;
3079  for (m_it = action_info.mirror_l.begin();
3080  m_it != action_info.mirror_l.end();
3081  ++m_it) {
3082  ActionStr mstr;
3083  mstr.action += (*m_it).ip.to_string();
3084  mstr.action += " ";
3085  mstr.action += integerToString((*m_it).port);
3086  mstr.action += " ";
3087  mstr.action += (*m_it).vrf_name;
3088  mstr.action += " ";
3089  mstr.action += (*m_it).encap;
3090  action_str_l.push_back(mstr);
3091  }
3092  }
3094  ActionStr vrf_action_str;
3095  vrf_action_str.action +=
3096  action_info.vrf_translate_action_.vrf_name();
3097  action_str_l.push_back(vrf_action_str);
3098  }
3100  ActionStr hbf_action_str;
3101  hbf_action_str.action += "hbs";
3102  action_str_l.push_back(hbf_action_str);
3103  }
3104  }
3105  }
3106 }
3107 
3108 static void SetAclListAclAction(const std::list<MatchAclParams> &acl_l,
3109  std::vector<AclAction> &acl_action_l,
3110  std::string &acl_type) {
3111  std::list<MatchAclParams>::const_iterator it;
3112  for(it = acl_l.begin(); it != acl_l.end(); ++it) {
3113  AclAction acl_action;
3114  acl_action.set_acl_id(UuidToString((*it).acl->GetUuid()));
3115  acl_action.set_acl_type(acl_type);
3116  std::vector<ActionStr> action_str_l;
3117  SetActionStr((*it).action_info, action_str_l);
3118  acl_action.set_action_l(action_str_l);
3119  acl_action_l.push_back(acl_action);
3120  }
3121 }
3122 
3123 void FlowEntry::SetAclAction(std::vector<AclAction> &acl_action_l) const {
3124  const std::list<MatchAclParams> &acl_l = data_.match_p.m_acl_l;
3125  std::string acl_type("nw policy");
3126  SetAclListAclAction(acl_l, acl_action_l, acl_type);
3127 
3128  const std::list<MatchAclParams> &sg_acl_l = data_.match_p.sg_policy.m_acl_l;
3129  acl_type = "sg";
3130  SetAclListAclAction(sg_acl_l, acl_action_l, acl_type);
3131 
3132  const std::list<MatchAclParams> &m_acl_l = data_.match_p.m_mirror_acl_l;
3133  acl_type = "dynamic";
3134  SetAclListAclAction(m_acl_l, acl_action_l, acl_type);
3135 
3136  const std::list<MatchAclParams> &out_acl_l = data_.match_p.m_out_acl_l;
3137  acl_type = "o nw policy";
3138  SetAclListAclAction(out_acl_l, acl_action_l, acl_type);
3139 
3140  const std::list<MatchAclParams> &out_sg_acl_l =
3142  acl_type = "o sg";
3143  SetAclListAclAction(out_sg_acl_l, acl_action_l, acl_type);
3144 
3145  const std::list<MatchAclParams> &out_m_acl_l =
3147  acl_type = "o dynamic";
3148  SetAclListAclAction(out_m_acl_l, acl_action_l, acl_type);
3149 
3150  const std::list<MatchAclParams> &r_sg_l = data_.match_p.sg_policy.m_reverse_acl_l;
3151  acl_type = "r sg";
3152  SetAclListAclAction(r_sg_l, acl_action_l, acl_type);
3153 
3154  const std::list<MatchAclParams> &r_out_sg_l =
3156  acl_type = "r o sg";
3157  SetAclListAclAction(r_out_sg_l, acl_action_l, acl_type);
3158 
3159  const std::list<MatchAclParams> &vrf_assign_acl_l =
3161  acl_type = "vrf assign";
3162  SetAclListAclAction(vrf_assign_acl_l, acl_action_l, acl_type);
3163 
3164  const std::list<MatchAclParams> &aps_l =
3166  acl_type = "fw acl";
3167  SetAclListAclAction(aps_l, acl_action_l, acl_type);
3168 
3169  const std::list<MatchAclParams> &out_aps_l =
3171  acl_type = "reverse fw acl";
3172  SetAclListAclAction(out_aps_l,
3173  acl_action_l, acl_type);
3174 
3175  const std::list<MatchAclParams> &fwaas_l =
3177  acl_type = "fwaas acl";
3178  SetAclListAclAction(fwaas_l, acl_action_l, acl_type);
3179 
3180  const std::list<MatchAclParams> &out_fwaas_l =
3182  acl_type = "reverse fwaas acl";
3183  SetAclListAclAction(out_fwaas_l,
3184  acl_action_l, acl_type);
3185 }
3186 
3187 void FlowEntry::FillFlowInfo(FlowInfo &info) const {
3188  info.set_gen_id(gen_id_);
3189  info.set_flow_index(flow_handle_);
3190  if (key_.family == Address::INET) {
3191  info.set_source_ip(key_.src_addr.to_v4().to_ulong());
3192  info.set_destination_ip(key_.dst_addr.to_v4().to_ulong());
3193  } else {
3194  uint64_t sip[2], dip[2];
3195  Ip6AddressToU64Array(key_.src_addr.to_v6(), sip, 2);
3196  Ip6AddressToU64Array(key_.dst_addr.to_v6(), dip, 2);
3197  info.set_sip_upper(sip[0]);
3198  info.set_sip_lower(sip[1]);
3199  info.set_dip_upper(dip[0]);
3200  info.set_dip_lower(dip[1]);
3201  info.set_source_ip(0);
3202  info.set_destination_ip(0);
3203  }
3204  info.set_source_port(key_.src_port);
3205  info.set_destination_port(key_.dst_port);
3206  info.set_protocol(key_.protocol);
3207  info.set_hbs_intf_dir(hbs_intf_);
3208  info.set_nh_id(key_.nh);
3209  info.set_vrf(data_.vrf);
3210  info.set_source_vn_list(data_.SourceVnList());
3211  info.set_dest_vn_list(data_.DestinationVnList());
3212  info.set_source_vn_match(data_.source_vn_match);
3213  info.set_dest_vn_match(data_.dest_vn_match);
3214  std::vector<uint32_t> v;
3215  SecurityGroupList::const_iterator it;
3216  for (it = data_.source_sg_id_l.begin();
3217  it != data_.source_sg_id_l.end(); it++) {
3218  v.push_back(*it);
3219  }
3220  info.set_source_sg_id_l(v);
3221  v.clear();
3222  for (it = data_.dest_sg_id_l.begin(); it != data_.dest_sg_id_l.end();
3223  it++) {
3224  v.push_back(*it);
3225  }
3226  info.set_dest_sg_id_l(v);
3227 
3228  uint32_t fe_action = data_.match_p.action_info.action;
3229  if (fe_action & (1 << TrafficAction::DENY)) {
3230  info.set_deny(true);
3231  } else if (fe_action & (1 << TrafficAction::PASS)) {
3232  info.set_allow(true);
3233  }
3234 
3235  if (reverse_flow_entry_.get()) {
3236  info.set_reverse_index(reverse_flow_entry_->flow_handle());
3237  }
3238 
3240  info.set_nat(true);
3241  FlowEntry *nat_flow = reverse_flow_entry_.get();
3242  // TODO : IPv6
3243  if (nat_flow) {
3244  if (key_.src_addr != nat_flow->key().dst_addr) {
3245  if (key_.family == Address::INET) {
3246  info.set_nat_source_ip
3247  (nat_flow->key().dst_addr.to_v4().to_ulong());
3248  } else {
3249  info.set_nat_source_ip(0);
3250  }
3251  }
3252 
3253  if (key_.dst_addr != nat_flow->key().src_addr) {
3254  if (key_.family == Address::INET) {
3255  info.set_nat_destination_ip
3256  (nat_flow->key().src_addr.to_v4().to_ulong());
3257  } else {
3258  info.set_nat_destination_ip(0);
3259  }
3260  }
3261 
3262  if (key_.src_port != nat_flow->key().dst_port) {
3263  info.set_nat_source_port(nat_flow->key().dst_port);
3264  }
3265 
3266  if (key_.dst_port != nat_flow->key().src_port) {
3267  info.set_nat_destination_port(nat_flow->key().src_port);
3268  }
3269  info.set_nat_protocol(nat_flow->key().protocol);
3270  info.set_nat_vrf(data_.dest_vrf);
3271  info.set_nat_mirror_vrf(nat_flow->data().mirror_vrf);
3272  }
3273  }
3274 
3276  info.set_mirror(true);
3277  std::vector<MirrorActionSpec>::const_iterator it;
3278  std::vector<MirrorInfo> mirror_l;
3279  for (it = data_.match_p.action_info.mirror_l.begin();
3280  it != data_.match_p.action_info.mirror_l.end();
3281  ++it) {
3282  MirrorInfo mirror_info;
3283  mirror_info.set_mirror_destination((*it).ip.to_string());
3284  mirror_info.set_mirror_port((*it).port);
3285  mirror_info.set_mirror_vrf((*it).vrf_name);
3286  mirror_info.set_analyzer((*it).analyzer_name);
3287  mirror_l.push_back(mirror_info);
3288  }
3289  info.set_mirror_l(mirror_l);
3290  }
3291  info.set_mirror_vrf(data_.mirror_vrf);
3292  info.set_implicit_deny(ImplicitDenyFlow());
3293  info.set_short_flow(is_flags_set(FlowEntry::ShortFlow));
3296  info.set_ecmp_index(data_.component_nh_idx);
3297  }
3299  info.set_trap(true);
3300  }
3301  info.set_vrf_assign(acl_assigned_vrf());
3302  info.set_l3_flow(l3_flow_);
3303  info.set_smac(data_.smac.ToString());
3304  info.set_dmac(data_.dmac.ToString());
3305  info.set_short_flow_reason(FlowEntry::DropReasonStr(short_flow_reason_));
3306  info.set_drop_reason(FlowEntry::DropReasonStr(data_.drop_reason));
3307  if (flow_table_) {
3308  info.set_table_id(flow_table_->table_index());
3309  }
3310 
3311  if (rpf_nh()) {
3312  info.set_rpf_nh(rpf_nh()->id());
3313  } else {
3314  info.set_rpf_nh(0xFFFFFFFF);
3315  }
3316  if (src_ip_nh()) {
3317  info.set_src_ip_nh(src_ip_nh()->id());
3318  } else {
3319  info.set_src_ip_nh(0xFFFFFFFF);
3320  }
3321 }
3322 
3323 static void SetAclListAceId(const AclDBEntry *acl,
3324  const MatchAclParamsList &acl_l,
3325  std::vector<AceId> &ace_l) {
3326  std::list<MatchAclParams>::const_iterator ma_it;
3327  for (ma_it = acl_l.begin();
3328  ma_it != acl_l.end();
3329  ++ma_it) {
3330  if ((*ma_it).acl != acl) {
3331  continue;
3332  }
3333  AclEntryIDList::const_iterator ait;
3334  for (ait = (*ma_it).ace_id_list.begin();
3335  ait != (*ma_it).ace_id_list.end(); ++ ait) {
3336  AceId ace_id;
3337  ace_id.id = ait->id_;
3338  ace_l.push_back(ace_id);
3339  }
3340  }
3341 }
3342 
3344  FlowSandeshData &fe_sandesh_data, Agent *agent) const {
3345  fe_sandesh_data.set_vrf(integerToString(data_.vrf));
3346  fe_sandesh_data.set_src(key_.src_addr.to_string());
3347  fe_sandesh_data.set_dst(key_.dst_addr.to_string());
3348  fe_sandesh_data.set_src_port(key_.src_port);
3349  fe_sandesh_data.set_dst_port(key_.dst_port);
3350  fe_sandesh_data.set_protocol(key_.protocol);
3351  fe_sandesh_data.set_ingress(is_flags_set(FlowEntry::IngressDir));
3352  std::vector<ActionStr> action_str_l;
3353  SetActionStr(data_.match_p.action_info, action_str_l);
3354  fe_sandesh_data.set_action_l(action_str_l);
3355 
3356  std::vector<AclAction> acl_action_l;
3357  SetAclAction(acl_action_l);
3358  fe_sandesh_data.set_acl_action_l(acl_action_l);
3359 
3360  fe_sandesh_data.set_flow_handle(integerToString(flow_handle_));
3361  if (!data_.origin_vn_src.empty()) {
3362  fe_sandesh_data.set_source_vn(data_.origin_vn_src);
3363  } else {
3364  fe_sandesh_data.set_source_vn(data_.source_vn_match);
3365  }
3366  if (!data_.origin_vn_dst.empty()) {
3367  fe_sandesh_data.set_dest_vn(data_.origin_vn_dst);
3368  } else {
3369  fe_sandesh_data.set_dest_vn(data_.dest_vn_match);
3370  }
3371  if (!data_.OriginVnSrcList().empty()) {
3372  fe_sandesh_data.set_source_vn_list(data_.OriginVnSrcList());
3373  } else {
3374  fe_sandesh_data.set_source_vn_list(data_.SourceVnList());
3375  }
3376  if (!data_.OriginVnDstList().empty()) {
3377  fe_sandesh_data.set_dest_vn_list(data_.OriginVnDstList());
3378  } else {
3379  fe_sandesh_data.set_dest_vn_list(data_.DestinationVnList());
3380  }
3381  std::vector<uint32_t> v;
3382  SecurityGroupList::const_iterator it;
3383  for (it = data_.source_sg_id_l.begin();
3384  it != data_.source_sg_id_l.end(); it++) {
3385  v.push_back(*it);
3386  }
3387  fe_sandesh_data.set_source_sg_id_l(v);
3388  v.clear();
3389  for (it = data_.dest_sg_id_l.begin(); it != data_.dest_sg_id_l.end();
3390  it++) {
3391  v.push_back(*it);
3392  }
3393  fe_sandesh_data.set_dest_sg_id_l(v);
3394  fe_sandesh_data.set_flow_uuid(UuidToString(uuid()));
3395  if (fsc_) {
3396  const FlowExportInfo *info = fsc_->FindFlowExportInfo(this);
3397  if (info) {
3398  fe_sandesh_data.set_bytes(integerToString(info->bytes()));
3399  fe_sandesh_data.set_packets(integerToString(info->packets()));
3400  if (info->teardown_time()) {
3401  fe_sandesh_data.set_teardown_time(
3403  } else {
3404  fe_sandesh_data.set_teardown_time("");
3405  }
3406  }
3407  }
3408  fe_sandesh_data.set_current_time(integerToString(
3410 
3411  SetAclListAceId(acl, data_.match_p.m_acl_l, fe_sandesh_data.ace_l);
3412  SetAclListAceId(acl, data_.match_p.sg_policy.m_acl_l, fe_sandesh_data.ace_l);
3413  SetAclListAceId(acl, data_.match_p.m_mirror_acl_l, fe_sandesh_data.ace_l);
3414  SetAclListAceId(acl, data_.match_p.m_out_acl_l, fe_sandesh_data.ace_l);
3416  fe_sandesh_data.ace_l);
3418  fe_sandesh_data.ace_l);
3419  SetAclListAceId(acl, data_.match_p.sg_policy.m_out_acl_l, fe_sandesh_data.ace_l);
3421  fe_sandesh_data.ace_l);
3423  fe_sandesh_data.ace_l);
3425  fe_sandesh_data.ace_l);
3427  fe_sandesh_data.ace_l);
3429  fe_sandesh_data.ace_l);
3431  fe_sandesh_data.ace_l);
3432 
3433  fe_sandesh_data.set_reverse_flow(is_flags_set(FlowEntry::ReverseFlow) ?
3434  "yes" : "no");
3435  fe_sandesh_data.set_nat(is_flags_set(FlowEntry::NatFlow) ? "yes" : "no");
3436  fe_sandesh_data.set_implicit_deny(ImplicitDenyFlow() ? "yes" : "no");
3437  fe_sandesh_data.set_short_flow(is_flags_set(FlowEntry::ShortFlow) ?
3438  "yes" : "no");
3439  fe_sandesh_data.set_l3_flow(l3_flow_);
3440  fe_sandesh_data.set_smac(data_.smac.ToString());
3441  fe_sandesh_data.set_dmac(data_.dmac.ToString());
3442 }
3443 
3444 string FlowEntry::KeyString() const {
3445  std::ostringstream str;
3447  str << " Idx : " << idx
3448  << " Key : "
3449  << key_.nh << " "
3450  << key_.src_addr.to_string() << ":"
3451  << key_.src_port << " "
3452  << key_.dst_addr.to_string() << ":"
3453  << key_.dst_port << " "
3454  << (uint16_t)key_.protocol;
3455  return str.str();
3456 }
3457 
3458 static std::string EventToString(FlowEventLog::Event event,
3459  std::string &event_str) {
3460  switch (event) {
3462  event_str = "FlowAdd";
3463  break;
3465  event_str = "FlowUpdate";
3466  break;
3468  event_str = "FlowDelete";
3469  break;
3471  event_str = "FlowEvict";
3472  break;
3474  event_str = "FlowHandleAssign";
3475  break;
3477  event_str = "FlowMessageSkippedEvictedFlow";
3478  break;
3479  default:
3480  event_str = "Unknown";
3481  break;
3482  }
3483  return event_str;
3484 }
3485 
3486 void FlowEntry::SetEventSandeshData(SandeshFlowIndexInfo *info) {
3487  KSyncFlowIndexManager *mgr =
3489  info->set_trace_index(event_log_index_);
3490  if (mgr->sm_log_count() == 0) {
3491  return;
3492  }
3493  int start = 0;
3494  int count = event_log_index_;
3495  if (event_log_index_ >= mgr->sm_log_count()) {
3496  start = event_log_index_ % mgr->sm_log_count();
3497  count = mgr->sm_log_count();
3498  }
3499  std::vector<SandeshFlowIndexTrace> trace_list;
3500  for (int i = 0; i < count; i++) {
3501  SandeshFlowIndexTrace trace;
3502  FlowEventLog *log = &event_logs_[((start + i) % mgr->sm_log_count())];
3503  trace.set_timestamp(log->time_);
3504  trace.set_flow_handle(log->flow_handle_);
3505  trace.set_flow_gen_id(log->flow_gen_id_);
3506  string event_str;
3507  trace.set_event(EventToString(log->event_, event_str));
3508  trace.set_ksync_hash_id(log->hash_id_);
3509  trace.set_ksync_gen_id(log->gen_id_);
3510  trace.set_vrouter_flow_handle(log->vrouter_flow_handle_);
3511  trace.set_vrouter_gen_id(log->vrouter_gen_id_);
3512  trace_list.push_back(trace);
3513  }
3514  info->set_flow_index_trace(trace_list);
3515 }
3516 
3518  uint32_t flow_handle, uint8_t gen_id) {
3519  KSyncFlowIndexManager *mgr =
3521  string event_str;
3522  LOG(DEBUG, "Flow event = " << EventToString(event, event_str)
3523  << " flow = " << (void *)this
3524  << " flow->flow_handle = " << flow_handle_
3525  << " flow->gen_id = " << (int)gen_id_
3526  << " ksync = " << (void *)ksync
3527  << " Ksync->hash_id = " << ((ksync != NULL) ? ksync->hash_id() : -1)
3528  << " Ksync->gen_id = " << ((ksync != NULL) ? (int)ksync->gen_id() : 0)
3529  << " new_flow_handle = " << flow_handle
3530  << " new_gen_id = " << (int)gen_id);
3531 
3532  if (mgr->sm_log_count() == 0) {
3533  return;
3534  }
3535 
3536  if (event_logs_ == NULL) {
3537  event_log_index_ = 0;
3538  event_logs_.reset(new FlowEventLog[mgr->sm_log_count()]);
3539  }
3540 
3542  event_log_index_++;
3543 
3544  log->time_ = ClockMonotonicUsec();
3545  log->event_ = event;
3546  log->flow_handle_ = flow_handle_;
3547  log->flow_gen_id_ = gen_id_;
3548  log->ksync_entry_ = ksync;
3549  log->hash_id_ = (ksync != NULL) ? ksync->hash_id() : -1;
3550  log->gen_id_ = (ksync != NULL) ? ksync->gen_id() : 0;
3552  log->vrouter_gen_id_ = gen_id;
3553 }
3554 
3557  return data_.source_tag_id_l;
3558  }
3559  return data_.dest_tag_id_l;
3560 }
3561 
3564  return data_.dest_tag_id_l;
3565  }
3566  return data_.source_tag_id_l;
3567 }
3568 
3569 const std::string FlowEntry::BuildRemotePrefix(const FlowRouteRefMap &rt_list,
3570  uint32_t vrf,
3571  const IpAddress &ip) const {
3572  int plen = -1;
3573  FlowRouteRefMap::const_iterator it;
3574  for (it = rt_list.begin(); it != rt_list.end(); it++) {
3575  if (it->first == static_cast<int>(vrf)) {
3576  plen = it->second;
3577  break;
3578  }
3579  }
3580  if (plen != -1) {
3581  return ip.to_string() + "/" + integerToString(plen);
3582  }
3583  return "";
3584 }
3585 
3586 /* Remote prefix is required only wnen remote_tagset is absent. Returns empty
3587  * string as remote-prefix when remote-tagset is present */
3588 const std::string FlowEntry::RemotePrefix() const {
3589  if (remote_tagset().size() > 0) {
3590  return "";
3591  }
3595  }
3597  key_.src_addr);
3598 }
3599 
3601  const VnEntry *vn = vn_entry();
3602  info->vn_ = vn? vn->GetName() : "";
3603  info->nw_ace_uuid_ = nw_ace_uuid();
3604  if (!info->vn_.empty() && !info->nw_ace_uuid_.empty()) {
3605  info->is_valid_ = true;
3606  }
3607 }
3608 
3610  bool added) const {
3611  info->initiator_ = false;
3613  info->remote_vn_ = data_.dest_vn_match;
3614  info->local_tagset_ = local_tagset();
3615  info->remote_tagset_ = remote_tagset();
3616  info->fw_policy_ = fw_policy_name_uuid();
3617  info->remote_prefix_ = RemotePrefix();
3618  info->added_ = added;
3620  info->short_flow_ = true;
3621  } else {
3622  info->short_flow_ = false;
3623  }
3625  info->action_);
3626  info->is_valid_ = true;
3627 }
3628 
3630  bool added) const {
3632  info->initiator_ = true;
3634  info->remote_vn_ = data_.dest_vn_match;
3635  } else {
3636  info->initiator_ = false;
3637  info->local_vn_ = data_.dest_vn_match;
3639  }
3640  info->local_tagset_ = local_tagset();
3641  info->remote_tagset_ = remote_tagset();
3642  info->fw_policy_ = fw_policy_name_uuid();
3643  info->remote_prefix_ = RemotePrefix();
3644  info->added_ = added;
3646  info->short_flow_ = true;
3647  } else {
3648  info->short_flow_ = false;
3649  }
3651  info->action_);
3652  info->is_valid_ = true;
3653 }
3654 
3656  bool added) const {
3657  /* Endpoint statistics update is not required in the following
3658  * cases
3659  * 1. When flow has empty policy_set_acl_name. One example of this
3660  * case is when matching rule for flow is IMPLICIT_ALLOW
3661  * 2. Link local flows
3662  * 3. Reverse flows. We need session_count and not flow_count. So we
3663  * consider only forward flows.
3664  *
3665  * Also count is updated only for forward-flow as the count
3666  * indicates session_count and NOT flow-count
3667  */
3670  return;
3671  }
3674  FillUveLocalRevFlowStatsInfo(info, added);
3675  } else {
3676  FillUveFwdFlowStatsInfo(info, added);
3677  }
3678  } else {
3679  FillUveFwdFlowStatsInfo(info, added);
3680  }
3681 }
3682 
3683 const std::string FlowEntry::fw_policy_uuid() const {
3685 }
3686 
3687 const std::string FlowEntry::fw_policy_name_uuid() const {
3688  /* If policy-name is empty return only policy UUID. Policy-name will be
3689  * empty when one of the implicit rules match */
3690  if (data_.match_p.aps_policy.acl_name_.empty()) {
3691  return fw_policy_uuid();
3692  }
3693  return data_.match_p.aps_policy.acl_name_ + ":" +
3694  fw_policy_uuid();
3695 }
3696 
3698  flow_mgmt_info_.reset(info);
3699 }
3700 
3701 uint8_t FlowEntry::GetUnderlayGwIndex(uint32_t intf_in, const IpAddress &sip,
3702  const IpAddress &dip, uint8_t proto, uint16_t sport,
3703  uint16_t dport) const {
3704  if ((!flow_table()->agent()->is_l3mh()) || (is_flags_set(FlowEntry::LocalFlow))) {
3705  return -1;
3706  }
3707 
3708  uint8_t underlay_gw_index = -1;
3710  FlowEntry *rflow = reverse_flow_entry_.get();
3711  if (rflow != NULL) {
3712  underlay_gw_index = rflow->data().underlay_gw_index_;
3713  }
3714  return underlay_gw_index;
3715  }
3716 
3717  InetUnicastRouteEntry *rt = static_cast<InetUnicastRouteEntry *>
3719  const TunnelNH *tunnel_nh = rt != nullptr ?
3720  dynamic_cast<const TunnelNH *>(rt->GetActiveNextHop()) : nullptr;
3721 
3722  if (!tunnel_nh && is_flags_set(FlowEntry::EcmpFlow) &&
3724  // For composite nh set underlay gw index to component_nh_idx (same hash is used)
3726  }
3727 
3728  Interface *intf = flow_table()->agent()->interface_table()->
3729  FindInterface(intf_in);
3730  if (intf && intf->type() == Interface::PHYSICAL) {
3731  underlay_gw_index = intf->id();
3732  return underlay_gw_index;
3733  } else {
3734  std::size_t hash = 0;
3735  hash = HashIp(hash, sip);
3736  hash = HashIp(hash, dip);
3737 
3738  hash = HashCombine(hash, sport);
3739  hash = HashCombine(hash, dport);
3740  hash = HashCombine(hash, proto);
3741  underlay_gw_index = hash % (flow_table()->agent()->fabric_interface_name_list().size());
3742  }
3743 
3744  if (rt == nullptr) {
3745  return -1;
3746  }
3747  if ( !(tunnel_nh && (tunnel_nh->IsValid()))) {
3748  return -1;
3749  }
3750  uint8_t index = 0;
3751  TunnelNH::EncapDataList encap_list = tunnel_nh->GetEncapDataList();
3752  while (index < encap_list.size()) {
3753  if (encap_list[index].get()->interface_.get() &&
3754  underlay_gw_index == (encap_list[index].get()->interface_).get()->id()) {
3755  underlay_gw_index = index;
3756  break;
3757  }
3758  index++;
3759  }
3760 
3761  if (tunnel_nh->IsEncapValid(underlay_gw_index)) {
3762  return underlay_gw_index;
3763  } else if ( ((underlay_gw_index +1) < (uint8_t)tunnel_nh->GetEncapDataList().size()) &&
3764  tunnel_nh->IsEncapValid(underlay_gw_index +1)) {
3765  return underlay_gw_index +1;
3766  } else if (((underlay_gw_index +1) >= (uint8_t)tunnel_nh->GetEncapDataList().size()) &&
3767  tunnel_nh->IsEncapValid(underlay_gw_index + 1 - tunnel_nh->GetEncapDataList().size())) {
3768  return (underlay_gw_index + 1 - tunnel_nh->GetEncapDataList().size());
3769  }
3770  return -1;
3771 }
3772 
3774  socket_.close();
3775 }
3776 
3777 uint16_t TcpPort::Bind() {
3778  boost::system::error_code ec;
3779  socket_.open(tcp::v4());
3780  socket_.bind(tcp::endpoint(tcp::v4(), port_), ec);
3781  if (ec.failed()) {
3782  return 0;
3783  }
3784  port_ = socket_.local_endpoint(ec).port();
3785  return port_;
3786 }
3787 
3789  socket_.close();
3790 }
3791 
3792 uint16_t UdpPort::Bind() {
3793  boost::system::error_code ec;
3794  socket_.open(udp::v4());
3795  socket_.bind(udp::endpoint(udp::v4(), port_), ec);
3796  if (ec.failed()) {
3797  return 0;
3798  }
3799  port_ = socket_.local_endpoint(ec).port();
3800  return port_;
3801 }
3802 
3804  return key_.IsLess(rhs.key_);
3805 }
3806 
3808  stale_ = true;
3810 }
3811 
3812 bool PortCacheEntry::CanBeAged(uint64_t current_time, uint64_t timeout) const {
3813  if (stale_ &&
3814  current_time - delete_time_ >= timeout) {
3815  return true;
3816  }
3817 
3818  return false;
3819 }
3820 
3822  port_table_(table),
3823  timer_(TimerManager::CreateTimer(
3824  *(table->agent()->event_manager())->io_service(),
3825  "FlowPortBindTimer",
3826  TaskScheduler::GetInstance()->GetTaskId(kTaskFlowMgmt), -1)),
3827  hash_(0), timeout_(PortCacheTable::kAgingTimeout) {
3829  boost::bind(&PortCacheTable::Age, this));
3830 }
3831 
3833  timer_->Cancel();
3835 }
3836 
3838  if (tree_.size() == 0) {
3839  return false;
3840  }
3841 
3842  std::lock_guard<std::recursive_mutex> lock(port_table_->mutex());
3843  uint16_t no_of_entries = tree_.size() / kCacheAging;
3844  uint16_t entries_processed = 0;
3845  uint64_t current_time = UTCTimestampUsec();
3846 
3847  PortCacheTree::iterator it = tree_.lower_bound(hash_);
3848  while (it != tree_.end() && entries_processed <= no_of_entries) {
3849  //Go thru each entry in particular hash bucket and identify
3850  //if any of them can be released
3851  PortCacheEntryList::iterator pcit = it->second.begin();
3852  while (pcit != it->second.end() && entries_processed <= no_of_entries) {
3853  PortCacheEntryList::iterator saved_pcit = pcit;
3854  pcit++;
3855  if (saved_pcit->CanBeAged(current_time, timeout_)) {
3856  //Release reference to port
3857  //check if port is empty, delete the port
3858  port_table_->Free(saved_pcit->key(), saved_pcit->port(), true);
3859  }
3860  entries_processed++;
3861  }
3862  it++;
3863  }
3864 
3865  if (it == tree_.end()) {
3866  hash_ = 0;
3867  } else {
3868  hash_ = it->first;
3869  hash_++;
3870  }
3871 
3872  return true;
3873 }
3874 
3877  boost::bind(&PortCacheTable::Age, this));
3878 }
3879 
3881  timer_->Cancel();
3882 }
3883 
3884 void PortCacheTable::Add(const PortCacheEntry &cache_entry) {
3885  uint16_t hash = port_table_->HashFlowKey(cache_entry.key());
3886  tree_[hash].insert(cache_entry);
3887 
3888  if (tree_.size() == 1) {
3889  StartTimer();
3890  }
3891 }
3892 
3893 void PortCacheTable::Delete(const PortCacheEntry &cache_entry) {
3894  uint16_t hash = port_table_->HashFlowKey(cache_entry.key());
3895  tree_[hash].erase(cache_entry);
3896  if (tree_[hash].size() == 0) {
3897  tree_.erase(hash);
3898  }
3899 
3900  if (tree_.size() == 0) {
3901  StopTimer();
3902  }
3903 }
3904 
3905 void PortCacheTable::MarkDelete(const PortCacheEntry &cache_entry) {
3906  uint16_t hash = port_table_->HashFlowKey(cache_entry.key());
3907 
3908  PortCacheEntryList::iterator it = tree_[hash].find(cache_entry);
3909  if (it != tree_[hash].end()) {
3910  it->MarkDelete();
3911  }
3912 }
3913 
3914 const PortCacheEntry*
3915 PortCacheTable::Find(const FlowKey &key) const {
3916  PortCacheEntry cache_entry(key, 0);
3917  uint16_t hash = port_table_->HashFlowKey(cache_entry.key());
3918 
3919  PortCacheTree::const_iterator pct_it = tree_.find(hash);
3920  if (pct_it == tree_.end()) {
3921  return NULL;
3922  }
3923 
3924  PortCacheEntryList::const_iterator it = pct_it->second.find(cache_entry);
3925  if (it != pct_it->second.end()) {
3926  return &(*it);
3927  }
3928 
3929  return NULL;
3930 }
3931 
3932 uint16_t PortTable::HashFlowKey(const FlowKey &key) {
3933  std::size_t hash = 0;
3934  boost::hash_combine(hash, key.dst_addr.to_v4().to_ulong());
3935  boost::hash_combine(hash, key.dst_port);
3936 
3937  return (hash % hash_table_size_);
3938 }
3939 
3940 PortTable::PortTable(Agent *agent, uint32_t hash_table_size, uint8_t protocol):
3941  agent_(agent), protocol_(protocol), cache_(this),
3942  hash_table_size_(hash_table_size) {
3943  for (uint32_t i = 0; i < hash_table_size; i++) {
3944  hash_table_.push_back(PortBitMapPtr(new PortBitMap()));
3945  }
3946 }
3947 
3949  if (task_trigger_.get()) {
3950  task_trigger_->Reset();
3951  }
3952 }
3953 
3954 uint16_t PortTable::Allocate(const FlowKey &key) {
3955  if (key.protocol != IPPROTO_TCP && key.protocol != IPPROTO_UDP) {
3956  return key.src_port;
3957  }
3958 
3959  std::lock_guard<std::recursive_mutex> lock(mutex_);
3960  //Check if the entry is present in flow cache tree
3961  const PortCacheEntry *entry = cache_.Find(key);
3962  if (entry) {
3963  entry->set_stale(false);
3964  return entry->port();
3965  }
3966 
3967  uint16_t port_hash = HashFlowKey(key);
3968  uint16_t port = kInvalidPort;
3969 
3970  PortBitMapPtr bit_map = hash_table_[port_hash];
3971 
3972  //Mark the port as used in bit map of hash
3973  uint16_t index = bit_map->Insert(key);
3974  if (index >= port_to_bit_index_.size()) {
3975  bit_map->Remove(index);
3976  return port;
3977  }
3978  //Using the index above get the actual port to be used
3979  port = port_list_.At(index)->port();
3980  PortCacheEntry cache_entry(key, port);
3981  //Add to cache tree
3982  cache_.Add(cache_entry);
3983 
3984  return port;
3985 }
3986 
3988 PortTable::CreatePortEntry(uint16_t port_no) {
3989  switch(protocol_) {
3990  case IPPROTO_TCP:
3991  return PortPtr(new TcpPort(*(agent_->event_manager()->io_service()),
3992  port_no));
3993 
3994  case IPPROTO_UDP:
3995  return PortPtr(new UdpPort(*(agent_->event_manager()->io_service()),
3996  port_no));
3997  }
3998 
3999  return PortPtr();
4000 }
4001 
4002 void PortTable::Free(const FlowKey &key, uint16_t port, bool release) {
4003  std::lock_guard<std::recursive_mutex> lock(mutex_);
4004  PortCacheEntry cache_entry(key, kInvalidPort);
4005  if (release) {
4006  //Delete from cache entry
4007  PortCacheEntry cache_entry(key, kInvalidPort);
4008  cache_.Delete(cache_entry);
4009 
4010  uint16_t port_hash = HashFlowKey(key);
4011  PortBitMapPtr bit_map = hash_table_[port_hash];
4012  if (port_to_bit_index_.find(port) != port_to_bit_index_.end()) {
4013  //Upon config change all the entries in bit map
4014  //are implicitly deleted, hence a duplicate
4015  //delete from flow table needs to be handled
4016  //after cross check if key matches
4017  FlowKey existing_key = bit_map->At(port_to_bit_index_[port]);
4018  if (existing_key.IsEqual(key)) {
4019  bit_map->Remove(port_to_bit_index_[port]);
4020  }
4021  }
4022  } else {
4023  //Mark cache entry for deletion
4024  //after aging timeout
4025  cache_.MarkDelete(cache_entry);
4026  }
4027 }
4028 
4029 void PortTable::Relocate(uint16_t port_no) {
4030  PortToBitIndexMap::iterator it = port_to_bit_index_.find(port_no);
4031  assert(it != port_to_bit_index_.end());
4032 
4033  PortPtr port_ptr = port_list_.At(it->second);
4034  DeleteAllFlow(port_no, it->second);
4035  port_list_.Remove(it->second);
4036  it->second = port_list_.Insert(port_ptr);
4037 }
4038 
4039 void PortTable::AddPort(uint16_t port_no) {
4040  PortToBitIndexMap::iterator it = port_to_bit_index_.find(port_no);
4041  //Port number already present
4042  if (port_no != kInvalidPort && it != port_to_bit_index_.end()) {
4043  if (it->second >= port_config_.port_count) {
4044  Relocate(port_no);
4045  }
4046  return;
4047  }
4048 
4049  PortPtr port_ptr = CreatePortEntry(port_no);
4050  if (port_ptr->Bind() || agent_->test_mode()) {
4051  size_t index = port_list_.Insert(port_ptr);
4052  port_to_bit_index_.insert((PortToBitIndexPair(port_ptr->port(),
4053  (uint16_t)index)));
4054  }
4055 }
4056 
4057 void PortTable::DeleteAllFlow(uint16_t port_no, uint16_t index) {
4058  for (uint16_t i = 0; i < hash_table_size_; i++) {
4059  FlowKey key = hash_table_[i]->At((size_t)index);
4060  if (key.family == Address::UNSPEC) {
4061  continue;
4062  }
4063  hash_table_[i]->Remove(index);
4064  Free(key, port_no, true);
4065  //Enqueue delete of flow
4067  }
4068 }
4069 
4070 void PortTable::DeletePort(uint16_t port_no) {
4071  assert(port_no != kInvalidPort);
4072 
4073  PortToBitIndexMap::const_iterator it = port_to_bit_index_.find(port_no);
4074  assert(it != port_to_bit_index_.end());
4075  uint16_t index = it->second;
4076 
4077  //Delete all the flow using this port
4078  DeleteAllFlow(port_no, index);
4079 
4080  port_list_.Remove(index);
4081  port_to_bit_index_.erase(port_no);
4082 }
4083 
4084 bool PortTable::IsValidPort(uint16_t port, uint16_t count) {
4085  if (port_config_.port_range.size() != 0) {
4086  std::vector<PortConfig::PortRange>::const_iterator it =
4087  port_config_.port_range.begin();
4088  //Go thru each range
4089  for(; it != port_config_.port_range.end(); it++) {
4090  if (port >= it->port_start && port <= it->port_end) {
4091  return true;
4092  }
4093  }
4094  } else {
4095  return (count < port_config_.port_count);
4096  }
4097 
4098  return false;
4099 }
4100 
4102  if (task_trigger_.get()) {
4103  task_trigger_->Reset();
4104  }
4105 
4106  PortConfig new_pc = *pc;
4107 
4109  task_trigger_.reset
4110  (new TaskTrigger(boost::bind(&PortTable::HandlePortConfig, this,
4111  new_pc), task_id, 0));
4112  task_trigger_->Set();
4113 }
4114 
4116  std::lock_guard<std::recursive_mutex> lock(mutex_);
4117  uint16_t old_port_count = port_to_bit_index_.size();
4118  port_config_ = pc;
4119 
4120  uint16_t count = 0;
4121 
4122  for (uint16_t index = 0; index < old_port_count; index++) {
4123  PortPtr port = port_list_.At(index);
4124  if (port.get() && IsValidPort(port->port(), count) == false) {
4125  DeletePort(port->port());
4126  } else {
4127  count++;
4128  //For relocating the port of index is higher than
4129  //port count
4130  AddPort(port->port());
4131  }
4132  }
4133 
4134  if (port_config_.port_range.size()) {
4135  std::vector<PortConfig::PortRange>::const_iterator it =
4136  port_config_.port_range.begin();
4137  //Go thru each range
4138  for(; it != port_config_.port_range.end(); it++) {
4139  //Handle range of port
4140  for (uint16_t port = it->port_start;
4141  it->port_end && port <= it->port_end;
4142  port++) {
4143  AddPort(port);
4144  }
4145  }
4146  } else {
4147  //Handle port count, port_count_ would be set only if range is
4148  //not valid
4149  for (uint16_t port = count; port < port_config_.port_count; port++) {
4150  AddPort(0);
4151  }
4152  }
4153  return true;
4154 }
4155 
4156 uint16_t PortTable::GetPortIndex(uint16_t port) const {
4157  PortToBitIndexMap::const_iterator it = port_to_bit_index_.find(port);
4158  assert(it != port_to_bit_index_.end());
4159  return it->second;
4160 }
4161 
4162 void PortTable::GetFlowKeyList(uint16_t port,
4163  std::vector<FlowKey> &list) const {
4164  std::lock_guard<std::recursive_mutex> lock(mutex_);
4165  if (port_to_bit_index_.find(port) == port_to_bit_index_.end()) {
4166  return;
4167  }
4168 
4169  for (uint16_t hash = 0; hash < hash_table_size_; hash++) {
4170  const PortBitMapPtr bit_map = hash_table_[hash];
4171  FlowKey existing_key = bit_map->At(GetPortIndex(port));
4172  if (existing_key.family != Address::UNSPEC) {
4173  list.push_back(existing_key);
4174  }
4175  }
4176 }
4177 
4178 PortTableManager::PortTableManager(Agent *agent, uint16_t hash_table_size):
4179  agent_(agent) {
4180  port_table_list_[IPPROTO_TCP] =
4181  PortTablePtr(new PortTable(agent, hash_table_size, IPPROTO_TCP));
4182  port_table_list_[IPPROTO_UDP] =
4183  PortTablePtr(new PortTable(agent, hash_table_size, IPPROTO_UDP));
4185 }
4186 
4188  for (uint16_t proto = 0; proto < IPPROTO_MAX; proto++) {
4189  port_table_list_[proto].reset();
4190  }
4191 }
4192 uint16_t PortTableManager::Allocate(const FlowKey &key) {
4193  if (key.protocol != IPPROTO_TCP && key.protocol != IPPROTO_UDP) {
4194  return key.src_port;
4195  }
4196 
4197  return port_table_list_[key.protocol]->Allocate(key);
4198 }
4199 
4200 void PortTableManager::Free(const FlowKey &key, uint16_t port, bool evict) {
4201  if (key.protocol != IPPROTO_TCP && key.protocol != IPPROTO_UDP) {
4202  return;
4203  }
4204 
4205  return port_table_list_[key.protocol]->Free(key, port, evict);
4206 }
4207 
4208 void PortTableManager::UpdatePortConfig(uint8_t protocol, const PortConfig *pc) {
4209  if (port_table_list_[protocol].get() == NULL) {
4210  return;
4211  }
4212 
4213  port_table_list_[protocol]->UpdatePortConfig(pc);
4214 }
4215 
4216 void PortTableManager::PortConfigHandler(Agent *agent, uint8_t protocol,
4217  const PortConfig *pc) {
4218  agent->pkt()->get_flow_proto()->port_table_manager()->
4219  UpdatePortConfig(protocol, pc);
4220 }
boost::asio::ip::address IpAddress
Definition: address.h:13
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
void Ip6AddressToU64Array(const Ip6Address &addr, uint64_t *arr, int size)
#define kTaskFlowMgmt
Definition: agent.h:327
std::vector< int > TagList
Definition: agent.h:202
#define MAX_XMPP_SERVERS
Definition: agent.h:291
std::vector< int > SecurityGroupList
Definition: agent.h:201
#define kTaskFlowEvent
Definition: agent.h:323
std::set< std::string > VnListType
Definition: agent.h:212
#define DNS_SERVER_PORT
Definition: bind_util.h:28
Definition: acl.h:91
static const uint8_t kMaxV4PrefixLen
Definition: address.h:20
@ INET
Definition: address.h:26
@ UNSPEC
Definition: address.h:25
AgentDBEntry * FindActiveEntry(const DBEntry *key)
Definition: agent_db.cc:110
const VnListType & dest_vn_list() const
Definition: agent_path.h:258
const SecurityGroupList & sg_list() const
Definition: agent_path.h:248
const std::string & origin_vn() const
Definition: agent_path.h:259
const TagList & tag_list() const
Definition: agent_path.h:249
static const uint32_t kInvalidIndex
Definition: qos_config.h:144
uint32_t id() const
Definition: qos_config.h:73
virtual const PrefixType & prefix_address() const
Returns the value of a stored prefix address (IPv4, IPv6 or MAC address)
Definition: agent_route.h:389
Base class for all Route entries in agent.
Definition: agent_route.h:224
bool IsRPFInvalid() const
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
virtual uint8_t prefix_length() const
Returns the length of a stored prefix address.
Definition: agent_route.h:336
bool is_multicast() const
Definition: agent_route.h:274
void decr_flow_count()
Definition: agent_stats.h:92
Definition: agent.h:360
InterfaceTable * interface_table() const
Definition: agent.h:467
OperDB * oper_db() const
Definition: agent.cc:1016
const std::string & dns_server(uint8_t idx) const
Definition: agent.h:859
const std::vector< std::string > & fabric_interface_name_list() const
Definition: agent.h:1135
VrfTable * vrf_table() const
Definition: agent.h:487
EventManager * event_manager() const
Definition: agent.h:1105
bool get_vhost_disable_policy()
Definition: agent.h:930
const std::string & controller_ifmap_xmpp_server(uint8_t idx) const
Definition: agent.h:732
const uint16_t dns_server_port(uint8_t idx) const
Definition: agent.h:870
KSync * ksync() const
Definition: agent.cc:904
const uint16_t controller_ifmap_xmpp_port(uint8_t idx) const
Definition: agent.h:759
static const std::string & NullString()
Definition: agent.h:439
void set_port_config_handler(PortConfigHandler handler)
Definition: agent.h:1352
bool test_mode() const
Definition: agent.h:1193
static Agent * GetInstance()
Definition: agent.h:438
AgentStats * stats() const
Definition: agent.cc:884
std::vector< string > & GetCollectorlist()
Definition: agent.h:710
Ip4Address router_id() const
Definition: agent.h:668
PktModule * pkt() const
Definition: agent.cc:968
BridgeRouteEntry * FindRoute(const MacAddress &mac)
Definition: bridge_route.cc:72
BridgeRouteEntry * FindRouteNoLock(const MacAddress &mac)
Definition: bridge_route.cc:77
uint8_t prefix_length() const
The length of L3 IP prefix (if present) associated with this L2 address.
Definition: bridge_route.h:130
static const uint32_t kInvalidComponentNHIdx
Definition: nexthop.h:1777
bool HasVmInterface(const VmInterface *vmi) const
Definition: nexthop.cc:1813
static const uint16_t DnsXmpp()
static const uint16_t CollectorPort()
bool IsDeleted() const
Definition: db_entry.h:48
boost::asio::io_context * io_service()
Definition: event_manager.h:42
EvpnRouteEntry * FindRouteNoLock(const MacAddress &mac, const IpAddress &ip_addr, uint32_t plen, uint32_t ethernet_tag)
static uint32_t ComputeHostIpPlen(const IpAddress &addr)
FlowEntry * Allocate(const FlowKey &key)
Definition: flow_table.cc:994
void Free(FlowEntry *flow)
Definition: flow_table.cc:1016
@ DROP_FWAAS_REVERSE_POLICY
Definition: flow_entry.h:506
@ DROP_FIREWALL_POLICY
Definition: flow_entry.h:500
@ DROP_REVERSE_SG
Definition: flow_entry.h:498
@ DROP_OUT_FIREWALL_POLICY
Definition: flow_entry.h:501
@ DROP_FWAAS_OUT_POLICY
Definition: flow_entry.h:505
@ DROP_UNKNOWN
Definition: flow_entry.h:493
@ DROP_FWAAS_REVERSE_OUT_POLICY
Definition: flow_entry.h:507
@ DROP_REVERSE_FIREWALL_POLICY
Definition: flow_entry.h:502
@ DROP_OUT_POLICY
Definition: flow_entry.h:495
@ DROP_REVERSE_OUT_SG
Definition: flow_entry.h:499
@ DROP_REVERSE_OUT_FIREWALL_POLICY
Definition: flow_entry.h:503
@ DROP_FWAAS_POLICY
Definition: flow_entry.h:504
FlowEntry * reverse_flow_entry()
Definition: flow_entry.h:602
void GetNonLocalFlowSgList(const VmInterface *vm_port)
Definition: flow_entry.cc:2047
void SetVrfAssignEntry()
Definition: flow_entry.cc:2180
const FlowKey & key() const
Definition: flow_entry.h:594
void SetMirrorVrfFromAction()
Definition: flow_entry.cc:2902
bool ImplicitDenyFlow() const
Definition: flow_entry.h:676
void SetAclAction(std::vector< AclAction > &acl_action_l) const
Definition: flow_entry.cc:3123
const boost::uuids::uuid & uuid() const
Definition: flow_entry.h:631
boost::uuids::uuid uuid_
Definition: flow_entry.h:824
uint32_t InterfaceKeyToId(Agent *agent, const VmInterfaceKey &key)
Definition: flow_entry.cc:1639
uint32_t last_event_
Definition: flow_entry.h:845
const std::string fw_policy_uuid() const
Definition: flow_entry.cc:3683
void SetAclFlowSandeshData(const AclDBEntry *acl, FlowSandeshData &fe_sandesh_data, Agent *agent) const
Definition: flow_entry.cc:3343
void GetApplicationPolicySet(const Interface *intf, const FlowEntry *rflow)
Definition: flow_entry.cc:1891
VmInterfaceKey fip_vmi_
Definition: flow_entry.h:837
FlowEntryPtr reverse_flow_entry_
Definition: flow_entry.h:819
bool deleted_
Definition: flow_entry.h:821
const std::string InterfaceIdToVmCfgName(Agent *agent, uint32_t id)
Definition: flow_entry.cc:1648
FlowTableKSyncEntry * ksync_entry_
Definition: flow_entry.h:839
bool ActionRecompute()
Definition: flow_entry.cc:2799
bool IsShortFlow() const
Definition: flow_entry.h:682
uint32_t fip() const
Definition: flow_entry.h:626
void set_flow_handle(uint32_t flow_handle, uint8_t gen_id)
Definition: flow_entry.cc:1038
TunnelType tunnel_type_
Definition: flow_entry.h:832
const Interface * intf_entry() const
Definition: flow_entry.h:652
const NextHop * rpf_nh() const
Definition: flow_entry.h:658
static void Init()
Definition: flow_entry.cc:511
FlowData & data()
Definition: flow_entry.h:595
void SetOutPacketHeader(PacketHeader *hdr)
Definition: flow_entry.cc:2329
const boost::uuids::uuid & egress_uuid() const
Definition: flow_entry.h:632
static const uint32_t kInvalidFlowHandle
Definition: flow_entry.h:521
uint32_t reverse_flow_fip() const
Definition: flow_entry.cc:1017
void LogFlow(FlowEventLog::Event event, FlowTableKSyncEntry *ksync, uint32_t flow_handle, uint8_t gen_id)
Definition: flow_entry.cc:3517
void InitRevFlow(const PktFlowInfo *info, const PktInfo *pkt, const PktControlInfo *ctrl, const PktControlInfo *rev_ctrl, FlowEntry *rflow, Agent *agent)
Definition: flow_entry.cc:780
FlowEntry(FlowTable *flow_table)
Definition: flow_entry.cc:448
const TagList & remote_tagset() const
Definition: flow_entry.cc:3562
bool on_tree() const
Definition: flow_entry.h:648
bool IsNatFlow() const
Definition: flow_entry.h:684
bool is_flags_set(const FlowEntryFlags &flags) const
Definition: flow_entry.h:610
VmInterfaceKey fip_vmi() const
Definition: flow_entry.h:627
uint32_t flow_handle() const
Definition: flow_entry.h:600
static bool ShouldDrop(uint32_t action)
Definition: flow_entry.cc:1113
void set_acl_assigned_vrf_index()
Definition: flow_entry.cc:1050
const MacAddress & smac() const
Definition: flow_entry.h:646
bool trace() const
Definition: flow_entry.h:752
void set_flags(const FlowEntryFlags &flags)
Definition: flow_entry.h:613
uint8_t gen_id() const
Definition: flow_entry.h:599
bool is_flow_on_unresolved_list
Definition: flow_entry.h:852
uint32_t fip_
Definition: flow_entry.h:836
void set_flow_mgmt_info(FlowEntryInfo *info)
Definition: flow_entry.cc:3697
uint32_t MatchAcl(const PacketHeader &hdr, MatchAclParamsList &acl, bool add_implicit_deny, bool add_implicit_allow, FlowPolicyInfo *info)
Definition: flow_entry.cc:2223
const std::string & acl_assigned_vrf() const
Definition: flow_entry.cc:1046
static const std::map< FlowPolicyState, const char * > FlowPolicyStateStr
Definition: flow_entry.h:523
const std::string RemotePrefix() const
Definition: flow_entry.cc:3588
bool IsFabricControlFlow() const
Definition: flow_entry.cc:894
FlowMgmtEntryInfoPtr flow_mgmt_info_
Definition: flow_entry.h:861
static const SecurityGroupList & default_sg_list()
Definition: flow_entry.h:586
const std::string & nw_ace_uuid() const
Definition: flow_entry.h:636
void RpfUpdate()
Definition: flow_entry.cc:1394
void FillUveFwdFlowStatsInfo(FlowUveFwPolicyInfo *info, bool added) const
Definition: flow_entry.cc:3629
void InitAuditFlow(uint32_t flow_idx, uint8_t gen_id)
Definition: flow_entry.cc:872
VmInterfaceKey InterfaceIdToKey(Agent *agent, uint32_t id)
Definition: flow_entry.cc:1628
FlowStatsCollector * fsc_
Definition: flow_entry.h:844
boost::uuids::uuid egress_uuid_
Definition: flow_entry.h:825
void GetPolicy(const VnEntry *vn, const FlowEntry *rflow)
Definition: flow_entry.cc:1734
bool on_tree_
Definition: flow_entry.h:834
const std::string fw_policy_name_uuid() const
Definition: flow_entry.cc:3687
bool RpfFromSrcIpNh() const
Definition: flow_entry.cc:1311
const std::string & sg_rule_uuid() const
Definition: flow_entry.h:633
HbsInterface hbs_intf_
Definition: flow_entry.h:892
bool IsServerFlow()
Definition: flow_entry.cc:1449
static AgentRoute * GetL2Route(const VrfEntry *entry, const MacAddress &mac)
Definition: flow_entry.cc:983
void ResetPolicy()
Definition: flow_entry.cc:1665
bool SetQosConfigIndex()
Definition: flow_entry.cc:2701
void GetVrfAssignAcl()
Definition: flow_entry.cc:1794
void SetEventSandeshData(SandeshFlowIndexInfo *info)
Definition: flow_entry.cc:3486
void SetMirrorVrf(const uint32_t id)
Definition: flow_entry.h:708
uint32_t flags_
Definition: flow_entry.h:822
static FlowEntry * Allocate(const FlowKey &key, FlowTable *flow_table)
Definition: flow_entry.cc:515
uint32_t acl_assigned_vrf_index() const
Definition: flow_entry.cc:1074
void FillUveLocalRevFlowStatsInfo(FlowUveFwPolicyInfo *info, bool added) const
Definition: flow_entry.cc:3609
std::string nw_ace_uuid_
Definition: flow_entry.h:827
uint32_t transaction_id_
Definition: flow_entry.h:870
uint32_t flow_handle_
Definition: flow_entry.h:818
void Reset()
Definition: flow_entry.cc:466
void UpdateFipStatsInfo(uint32_t fip, uint32_t id, Agent *agent)
Definition: flow_entry.cc:1033
@ IMPLICIT_DENY
Definition: flow_entry.h:513
@ LINKLOCAL_FLOW
Definition: flow_entry.h:515
@ MULTICAST_FLOW
Definition: flow_entry.h:516
@ NOT_EVALUATED
Definition: flow_entry.h:511
@ BGPROUTERSERVICE_FLOW
Definition: flow_entry.h:517
@ DEFAULT_GW_ICMP_OR_DNS
Definition: flow_entry.h:514
@ IMPLICIT_ALLOW
Definition: flow_entry.h:512
FlowData data_
Definition: flow_entry.h:815
void RpfSetSrcIpNhFields(const AgentRoute *rt, const NextHop *src_ip_nh)
Definition: flow_entry.cc:1225
uint16_t short_flow_reason_
Definition: flow_entry.h:823
void UpdateReflexiveAction()
Definition: flow_entry.cc:2934
bool IsIngressFlow() const
Definition: flow_entry.h:685
const MacAddress & dmac() const
Definition: flow_entry.h:647
std::string KeyString() const
Definition: flow_entry.cc:3444
const std::string BuildRemotePrefix(const FlowRouteRefMap &rt_list, uint32_t vr, const IpAddress &ip) const
Definition: flow_entry.cc:3569
void SetHbsInfofromAction()
Definition: flow_entry.cc:2114
static AgentRoute * GetUcRoute(const VrfEntry *entry, const IpAddress &addr)
Definition: flow_entry.cc:990
void GetLocalFlowSgList(const VmInterface *vm_port, const VmInterface *reverse_vm_port)
Definition: flow_entry.cc:2010
@ SHORT_NO_SRC_ROUTE_L2RPF
Definition: flow_entry.h:484
@ SHORT_VRF_CHANGE
Definition: flow_entry.h:472
@ SHORT_UNKNOWN
Definition: flow_entry.h:465
@ SHORT_AUDIT_ENTRY
Definition: flow_entry.h:471
void reset_flags(const FlowEntryFlags &flags)
Definition: flow_entry.h:614
void Copy(FlowEntry *rhs, bool update)
Definition: flow_entry.cc:532
static std::atomic< int > alloc_count_
Definition: flow_entry.h:820
const MatchPolicy & match_p() const
Definition: flow_entry.h:670
void FillUveVnAceInfo(FlowUveVnAcePolicyInfo *info) const
Definition: flow_entry.cc:3600
static const std::map< uint16_t, const char * > FlowDropReasonStr
Definition: flow_entry.h:524
void RpfComputeIngress()
Definition: flow_entry.cc:1336
std::atomic< int > refcount_
Definition: flow_entry.h:841
FlowKey key_
Definition: flow_entry.h:813
static SecurityGroupList default_sg_list_
Definition: flow_entry.h:850
void RpfSetRpfNhFields(const NextHop *rpf_nh)
Definition: flow_entry.cc:1232
virtual ~FlowEntry()
Definition: flow_entry.cc:460
FlowTable * flow_table() const
Definition: flow_entry.h:597
void SetHbsInterface(HbsInterface intf)
Definition: flow_entry.h:771
static std::string DropReasonStr(uint16_t reason)
Definition: flow_entry.cc:1478
static AgentRoute * GetEvpnRoute(const VrfEntry *entry, const MacAddress &mac, const IpAddress &addr, uint32_t ethernet_tag)
Definition: flow_entry.cc:1006
void Reset(const FlowKey &k)
Definition: flow_entry.cc:506
const VrfEntry * GetDestinationVrf() const
Definition: flow_entry.cc:2688
void RpfInit(const AgentRoute *rt, const IpAddress &sip)
Definition: flow_entry.cc:1250
std::string peer_vrouter_
Definition: flow_entry.h:830
void GetSgList(const Interface *intf)
Definition: flow_entry.cc:1837
void GetDestRouteInfo(const AgentRoute *rt)
Definition: flow_entry.cc:1559
VmInterfaceKey reverse_flow_vmi() const
Definition: flow_entry.cc:1025
void MakeShortFlow(FlowShortReason reason)
Definition: flow_entry.cc:2922
void InitFwdFlow(const PktFlowInfo *info, const PktInfo *pkt, const PktControlInfo *ctrl, const PktControlInfo *rev_ctrl, FlowEntry *rflow, Agent *agent)
Definition: flow_entry.cc:686
void GetPolicyInfo()
Definition: flow_entry.cc:1722
void SetAclInfo(SessionPolicy *sp, SessionPolicy *rsp, const FlowPolicyInfo &fwd_flow_info, const FlowPolicyInfo &rev_flow_info, bool tcp_rev, bool is_sg)
Definition: flow_entry.cc:2354
uint16_t event_log_index_
Definition: flow_entry.h:848
void RpfComputeEgress()
Definition: flow_entry.cc:1358
const TagList & local_tagset() const
Definition: flow_entry.cc:3555
const VnEntry * vn_entry() const
Definition: flow_entry.h:653
void FillUveFwStatsInfo(FlowUveFwPolicyInfo *info, bool added) const
Definition: flow_entry.cc:3655
void SessionMatch(SessionPolicy *sp, SessionPolicy *rsp, bool is_sg)
Definition: flow_entry.cc:2423
uint8_t gen_id_
Definition: flow_entry.h:817
void FillFlowInfo(FlowInfo &info) const
Definition: flow_entry.cc:3187
bool l3_flow_
Definition: flow_entry.h:816
bool IsClientFlow()
Definition: flow_entry.cc:1422
const NextHop * src_ip_nh() const
Definition: flow_entry.h:657
boost::scoped_array< FlowEventLog > event_logs_
Definition: flow_entry.h:847
void RevFlowDepInfo(RevFlowDepParams *params)
Definition: flow_entry.cc:1078
bool DoPolicy()
Definition: flow_entry.cc:2551
bool trace_
Definition: flow_entry.h:846
@ HBS_INTERFACE_INVALID
Definition: flow_entry.h:557
@ HBS_INTERFACE_RIGHT
Definition: flow_entry.h:559
@ HBS_INTERFACE_LEFT
Definition: flow_entry.h:558
FlowTable * flow_table_
Definition: flow_entry.h:814
uint8_t GetUnderlayGwIndex(uint32_t intf_in, const IpAddress &sip, const IpAddress &dip, uint8_t proto, uint16_t sport, uint16_t dport) const
Definition: flow_entry.cc:3701
bool l3_flow() const
Definition: flow_entry.h:598
void SetPacketHeader(PacketHeader *hdr)
Definition: flow_entry.cc:2307
void UpdateL2RouteInfo()
Definition: flow_entry.cc:2078
void GetSourceRouteInfo(const AgentRoute *rt)
Definition: flow_entry.cc:1490
uint8_t flow_retry_attempts_
Definition: flow_entry.h:851
FlowMgmtRequest * flow_mgmt_request_
Definition: flow_entry.h:857
FlowPendingAction pending_actions_
Definition: flow_entry.h:849
bool InitFlowCmn(const PktFlowInfo *info, const PktControlInfo *ctrl, const PktControlInfo *rev_ctrl, FlowEntry *rflow)
Definition: flow_entry.cc:612
@ LinkLocalFlow
Definition: flow_entry.h:539
@ LinkLocalBindLocalSrcPort
Definition: flow_entry.h:546
@ BgpRouterService
Definition: flow_entry.h:549
@ FabricControlFlow
Definition: flow_entry.h:551
@ UnknownUnicastFlood
Definition: flow_entry.h:548
void ResyncFlow()
Definition: flow_entry.cc:2670
uint64_t packets() const
uint64_t teardown_time() const
uint64_t bytes() const
static const VnListType UnknownVnList()
Definition: flow_handler.h:27
static const std::string UnknownVn()
Definition: flow_handler.h:26
bool SetRecomputeDBEntry()
Definition: flow_entry.cc:3026
bool CanRecomputeDBEntry()
Definition: flow_entry.cc:3039
void ResetRecomputeDBEntry()
Definition: flow_entry.cc:3034
void DeleteFlowRequest(FlowEntry *flow)
Definition: flow_proto.cc:598
void ForceEnqueueFreeFlowReference(FlowEntryPtr &flow)
Definition: flow_proto.cc:662
void update_linklocal_flow_count(int val)
Definition: flow_proto.h:114
PortTableManager * port_table_manager()
Definition: flow_proto.h:128
bool FindFlowExportInfo(const FlowEntry *fe, FlowEntryTree::iterator &it)
uint32_t hash_id() const
Agent * agent() const
Definition: flow_table.h:207
static void GetFlowSandeshActionParams(const FlowAction &action_info, std::string &action_str)
Definition: flow_table.cc:937
void DelLinkLocalFlowInfo(int fd)
Definition: flow_table.cc:759
uint16_t table_index() const
Definition: flow_table.h:208
FlowEntryFreeList * free_list()
Definition: flow_table.h:249
int flow_task_id() const
Definition: flow_table.h:262
boost::uuids::uuid rand_gen()
Definition: flow_table.cc:499
FlowEntryMap flow_entry_map_
Definition: flow_table.h:305
void AddLinkLocalFlowInfo(int fd, uint32_t index, const FlowKey &key, const uint64_t timestamp)
Definition: flow_table.cc:746
bool ConcurrencyCheck(int task_id, bool check_task_instance)
Definition: flow_table.cc:96
static const std::string kMetadataService
size_t Insert(EntryType entry)
Definition: index_vector.h:40
EntryType At(size_t index) const
Definition: index_vector.h:32
void Remove(size_t index)
Definition: index_vector.h:78
SubType sub_type() const
uint8_t prefix_length() const
!
const Interface * FindInterface(size_t index) const
Definition: interface.cc:322
@ VM_INTERFACE
Definition: interface.h:37
@ PHYSICAL
Definition: interface.h:31
const NextHop * flow_key_nh() const
Definition: interface.h:139
const std::string & name() const
Definition: interface.h:116
const AgentQosConfig * qos_config() const
Definition: interface.h:142
static const uint32_t kInvalidIndex
Definition: interface.h:72
const boost::uuids::uuid & GetUuid() const
Definition: interface.h:115
Type type() const
Definition: interface.h:114
const uint32_t id() const
Definition: interface.h:125
KSyncFlowIndexManager * ksync_flow_index_manager() const
Definition: ksync_init.h:61
std::string ToString() const
Definition: mac_address.cc:53
bool IsValid() const
Definition: nexthop.h:406
@ COMPOSITE
Definition: nexthop.h:354
@ VRF
Definition: nexthop.h:350
Type GetType() const
Definition: nexthop.h:405
GlobalVrouter * global_vrouter() const
Definition: operdb_init.h:54
FlowRouteRefMap flow_dest_plen_map
uint32_t src_policy_vrf
boost::shared_ptr< PktInfo > pkt
bool linklocal_bind_local_port
bool port_allocated
bool bgp_router_service_flow
bool alias_ip_flow
uint32_t out_component_nh_idx
bool disable_validation
uint32_t dst_policy_vrf
uint32_t nat_dest_vrf
bool flood_unknown_unicast
uint32_t flow_source_vrf
bool underlay_flow
uint16_t short_flow_reason
uint32_t nat_sport
std::string peer_vrouter
bool linklocal_flow
TunnelType tunnel_type
FlowRouteRefMap flow_source_plen_map
uint32_t dest_vrf
uint32_t nat_dport
static bool ComputeDirection(const Interface *intf)
uint32_t flow_dest_vrf
bool IsGwPacket(const Interface *intf, const IpAddress &dst_ip)
FlowProto * get_flow_proto() const
Definition: pkt_init.h:43
PktHandler * pkt_handler() const
Definition: pkt_init.h:31
bool CanBeAged(uint64_t current_time, uint64_t timeout) const
Definition: flow_entry.cc:3812
void MarkDelete() const
Definition: flow_entry.cc:3807
uint16_t port() const
Definition: flow_entry.h:955
const FlowKey & key() const
Definition: flow_entry.h:951
bool operator<(const PortCacheEntry &rhs) const
Definition: flow_entry.cc:3803
FlowKey key_
Definition: flow_entry.h:967
void set_stale(bool stale) const
Definition: flow_entry.h:959
uint64_t delete_time_
Definition: flow_entry.h:970
const PortCacheEntry * Find(const FlowKey &key) const
Definition: flow_entry.cc:3915
PortTable * port_table_
Definition: flow_entry.h:1003
static const uint64_t kCacheAging
Definition: flow_entry.h:979
uint16_t hash_
Definition: flow_entry.h:1005
PortCacheTable(PortTable *table)
Definition: flow_entry.cc:3821
void MarkDelete(const PortCacheEntry &cache_entry)
Definition: flow_entry.cc:3905
Timer * timer_
Definition: flow_entry.h:1004
uint64_t timeout_
Definition: flow_entry.h:1006
void Add(const PortCacheEntry &cache_entry)
Definition: flow_entry.cc:3884
PortCacheTree tree_
Definition: flow_entry.h:1002
void Delete(const PortCacheEntry &cache_entry)
Definition: flow_entry.cc:3893
PortTablePtr port_table_list_[IPPROTO_MAX]
Definition: flow_entry.h:1120
static void PortConfigHandler(Agent *agent, uint8_t protocol, const PortConfig *pc)
Definition: flow_entry.cc:4216
void Free(const FlowKey &key, uint16_t port, bool release)
Definition: flow_entry.cc:4200
boost::shared_ptr< PortTable > PortTablePtr
Definition: flow_entry.h:1105
void UpdatePortConfig(uint8_t protocol, const PortConfig *config)
Definition: flow_entry.cc:4208
uint16_t Allocate(const FlowKey &key)
Definition: flow_entry.cc:4192
PortTableManager(Agent *agent, uint16_t hash_table_size)
Definition: flow_entry.cc:4178
std::recursive_mutex & mutex()
Definition: flow_entry.h:1043
std::pair< uint16_t, uint16_t > PortToBitIndexPair
Definition: flow_entry.h:1018
uint8_t protocol_
Definition: flow_entry.h:1076
uint16_t hash_table_size_
Definition: flow_entry.h:1084
void GetFlowKeyList(uint16_t port, std::vector< FlowKey > &key) const
Definition: flow_entry.cc:4162
uint16_t HashFlowKey(const FlowKey &key)
Definition: flow_entry.cc:3932
PortList port_list_
Definition: flow_entry.h:1091
void UpdatePortConfig(const PortConfig *port_config)
Definition: flow_entry.cc:4101
boost::shared_ptr< PortBitMap > PortBitMapPtr
Definition: flow_entry.h:1021
static const uint8_t kInvalidPort
Definition: flow_entry.h:1012
uint16_t GetPortIndex(uint16_t port) const
Definition: flow_entry.cc:4156
uint16_t Allocate(const FlowKey &key)
Definition: flow_entry.cc:3954
Agent * agent_
Definition: flow_entry.h:1066
PortToBitIndexMap port_to_bit_index_
Definition: flow_entry.h:1095
void DeletePort(uint16_t port_no)
Definition: flow_entry.cc:4070
std::unique_ptr< TaskTrigger > task_trigger_
Definition: flow_entry.h:1100
IndexVector< FlowKey > PortBitMap
Definition: flow_entry.h:1020
bool HandlePortConfig(const PortConfig &pc)
Definition: flow_entry.cc:4115
boost::shared_ptr< Port > PortPtr
Definition: flow_entry.h:1014
PortConfig port_config_
Definition: flow_entry.h:1098
void Free(const FlowKey &key, uint16_t port, bool release)
Definition: flow_entry.cc:4002
bool IsValidPort(uint16_t port, uint16_t count)
Definition: flow_entry.cc:4084
std::recursive_mutex mutex_
Definition: flow_entry.h:1099
void DeleteAllFlow(uint16_t port, uint16_t index)
Definition: flow_entry.cc:4057
void Relocate(uint16_t port_no)
Definition: flow_entry.cc:4029
void AddPort(uint16_t port_no)
Definition: flow_entry.cc:4039
PortPtr CreatePortEntry(uint16_t port_no)
Definition: flow_entry.cc:3988
PortTable(Agent *agent, uint32_t bucket_size, uint8_t protocol)
Definition: flow_entry.cc:3940
PortCacheTable cache_
Definition: flow_entry.h:1079
PortHashTable hash_table_
Definition: flow_entry.h:1088
uint16_t port_
Definition: flow_entry.h:917
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h:304
int GetTaskId(const std::string &name)
Definition: task.cc:861
static TaskScheduler * GetInstance()
Definition: task.cc:554
virtual uint16_t Bind()
Definition: flow_entry.cc:3777
boost::asio::ip::tcp::socket socket_
Definition: flow_entry.h:928
virtual ~TcpPort()
Definition: flow_entry.cc:3773
static bool DeleteTimer(Timer *Timer)
Definition: timer.cc:221
bool Cancel()
Definition: timer.cc:149
bool Start(int time, Handler handler, ErrorHandler error_handler=NULL)
Definition: timer.cc:107
Definition: trace.h:288
static std::string ActionToString(enum Action at)
static const uint32_t IMPLICIT_DENY_FLAGS
static const uint32_t DROP_FLAGS
std::vector< EncapDataPtr > EncapDataList
Definition: tunnel_nh.h:69
const bool & IsEncapValid(const uint32_t &i) const
Definition: tunnel_nh.h:40
const EncapDataList GetEncapDataList() const
Definition: tunnel_nh.h:70
virtual uint16_t Bind()
Definition: flow_entry.cc:3792
boost::asio::ip::udp::socket socket_
Definition: flow_entry.h:939
virtual ~UdpPort()
Definition: flow_entry.cc:3788
Definition: vm.h:34
void update_flow_count(int val) const
Definition: vm.cc:69
const string & GetCfgName() const
Definition: vm.h:45
void operator=(const VmFlowRef &rhs)
Definition: flow_entry.cc:141
bool AllocateFd(Agent *agent, uint8_t l3_proto)
Definition: flow_entry.cc:219
void SetVm(const VmEntry *vm)
Definition: flow_entry.cc:201
void Reset(bool reset_flow)
Definition: flow_entry.cc:168
void FreeFd()
Definition: flow_entry.cc:186
VmEntryConstRef vm_
Definition: flow_entry.h:119
void FreeRef()
Definition: flow_entry.cc:176
uint16_t port_
Definition: flow_entry.h:121
void Init(FlowEntry *flow)
Definition: flow_entry.cc:137
void Move(VmFlowRef *rhs)
Definition: flow_entry.cc:153
static const int kInvalidFd
Definition: flow_entry.h:99
FlowEntry * flow_
Definition: flow_entry.h:122
const VmEntry * vm() const
Definition: flow_entry.h:115
bool policy_enabled() const
VmInterface::VmiType vmi_type() const
const std::string & service_intf_type() const
const boost::uuids::uuid & vmi_cfg_uuid() const
const FirewallPolicyList & fwaas_fw_policy_list() const
const FirewallPolicyList & fw_policy_list() const
const VmEntry * vm() const
const SecurityGroupEntryList & sg_list() const
bool is_vn_qos_config() const
const AclDBEntry * vrf_assign_acl() const
void update_flow_count(int val) const
Definition: vn.h:151
VrfEntry * GetVrf() const
Definition: vn.h:170
const string & GetName() const
Definition: vn.h:162
const AclDBEntry * GetAcl() const
Definition: vn.h:167
const AclDBEntry * GetMirrorAcl() const
Definition: vn.h:168
const AclDBEntry * GetMirrorCfgAcl() const
Definition: vn.h:169
Definition: vrf.h:89
AgentRouteTable * GetBridgeRouteTable() const
Definition: vrf.cc:334
InetUnicastRouteEntry * GetUcRoute(const IpAddress &addr) const
Definition: vrf.cc:237
static const uint32_t kInvalidIndex
Definition: vrf.h:91
const uint32_t vrf_id() const
Definition: vrf.h:102
AgentRouteTable * GetEvpnRouteTable() const
Definition: vrf.cc:330
const VrfEntry * GetVrf() const
Definition: nexthop.h:1444
Definition: vrf.h:271
VrfEntry * FindVrfFromId(size_t index)
Definition: vrf.cc:884
static void SetAclListAceId(const AclDBEntry *acl, const MatchAclParamsList &acl_l, std::vector< AceId > &ace_l)
Definition: flow_entry.cc:3323
void SetActionStr(const FlowAction &action_info, std::vector< ActionStr > &action_str_l)
Definition: flow_entry.cc:3068
static bool CopySgEntries(const VmInterface *vm_port, bool ingress_acl, std::list< MatchAclParams > &list)
Definition: flow_entry.cc:1978
static void SetAclListAclAction(const std::list< MatchAclParams > &acl_l, std::vector< AclAction > &acl_action_l, std::string &acl_type)
Definition: flow_entry.cc:3108
void intrusive_ptr_release(FlowEntry *fe)
Definition: flow_entry.cc:571
static std::string EventToString(FlowEventLog::Event event, std::string &event_str)
Definition: flow_entry.cc:3458
static std::size_t HashCombine(std::size_t hash, uint64_t val)
Definition: flow_entry.cc:594
static std::size_t HashIp(std::size_t hash, const IpAddress &ip)
Definition: flow_entry.cc:599
void intrusive_ptr_add_ref(FlowEntry *fe)
Definition: flow_entry.cc:567
static std::vector< std::string > MakeList(const VnListType &ilist)
Definition: flow_entry.cc:331
static void SetRpfFieldsInternal(FlowEntry *flow, const AgentRoute *rt)
Definition: flow_entry.cc:1187
boost::intrusive_ptr< FlowEntry > FlowEntryPtr
Definition: flow_entry.h:125
std::list< MatchAclParams > MatchAclParamsList
Definition: flow_entry.h:220
#define FLOW_TRACE(obj,...)
Definition: flow_mgmt.h:377
@ INVALID
Definition: globals.h:147
#define LOG(_Level, _Msg)
Definition: logging.h:34
map< int, int > FlowRouteRefMap
Definition: pkt_flow_info.h:16
#define BGP_SERVICE_TTL_REV_FLOW
Definition: pkt_handler.h:45
#define BGP_SERVICE_TTL_FWD_FLOW
Definition: pkt_handler.h:46
static std::string UuidToString(const boost::uuids::uuid &id)
Definition: string_util.h:138
static const std::string integerToString(const NumberType &num)
Definition: string_util.h:19
uint32_t cmd_param
Definition: pkt_handler.h:182
uint32_t ifindex
Definition: pkt_handler.h:179
uint8_t cmd_param_5
Definition: pkt_handler.h:187
@ ADD_DEL_CHANGE
Definition: agent_db.h:100
Definition: acl.h:34
VrfTranslateActionSpec vrf_translate_action_
Definition: acl.h:47
void Clear()
Definition: acl.h:39
std::vector< MirrorActionSpec > mirror_l
Definition: acl.h:46
uint32_t action
Definition: acl.h:43
uint32_t bgp_as_a_service_dport
Definition: flow_entry.h:320
std::string origin_vn_dst
Definition: flow_entry.h:297
MacAddress smac
Definition: flow_entry.h:292
uint32_t src_policy_vrf
Definition: flow_entry.h:327
uint16_t drop_reason
Definition: flow_entry.h:335
std::vector< std::string > OriginVnSrcList() const
Definition: flow_entry.cc:348
uint8_t rpf_plen
Definition: flow_entry.h:353
NextHopConstRef src_ip_nh
Definition: flow_entry.h:314
uint32_t mirror_vrf
Definition: flow_entry.h:316
MatchPolicy match_p
Definition: flow_entry.h:309
uint8_t underlay_gw_index_
Definition: flow_entry.h:361
uint16_t allocated_port_
Definition: flow_entry.h:360
uint32_t src_policy_plen
Definition: flow_entry.h:328
uint32_t acl_assigned_vrf_index_
Definition: flow_entry.h:358
FlowRouteRefMap flow_dest_plen_map
Definition: flow_entry.h:343
uint32_t flow_dest_vrf
Definition: flow_entry.h:307
void Reset()
Definition: flow_entry.cc:279
uint32_t dst_policy_vrf
Definition: flow_entry.h:329
uint32_t rpf_vrf
Definition: flow_entry.h:352
std::vector< std::string > OriginVnDstList() const
Definition: flow_entry.cc:352
std::string source_vn_match
Definition: flow_entry.h:294
VnListType origin_vn_src_list
Definition: flow_entry.h:300
VnEntryConstRef vn_entry
Definition: flow_entry.h:310
std::vector< std::string > SourceVnList() const
Definition: flow_entry.cc:340
uint32_t component_nh_idx
Definition: flow_entry.h:318
VnListType dest_vn_list
Definition: flow_entry.h:299
FlowRouteRefMap flow_source_plen_map
Definition: flow_entry.h:342
std::string vm_cfg_name
Definition: flow_entry.h:357
TunnelInfo tunnel_info
Definition: flow_entry.h:338
std::vector< std::string > DestinationVnList() const
Definition: flow_entry.cc:344
SecurityGroupList source_sg_id_l
Definition: flow_entry.h:302
VnListType source_vn_list
Definition: flow_entry.h:298
uint32_t dst_policy_plen
Definition: flow_entry.h:330
std::string origin_vn_src
Definition: flow_entry.h:296
uint32_t flow_source_vrf
Definition: flow_entry.h:306
uint32_t qos_config_idx
Definition: flow_entry.h:359
uint32_t ttl
Definition: flow_entry.h:322
bool vrf_assign_evaluated
Definition: flow_entry.h:336
bool disable_validation
Definition: flow_entry.h:355
VmFlowRef in_vm_entry
Definition: flow_entry.h:312
VmFlowRef out_vm_entry
Definition: flow_entry.h:313
uint8_t source_plen
Definition: flow_entry.h:333
bool enable_rpf
Definition: flow_entry.h:346
uint32_t dest_vrf
Definition: flow_entry.h:317
uint32_t bgp_as_a_service_sport
Definition: flow_entry.h:319
TagList dest_tag_id_l
Definition: flow_entry.h:305
uint8_t dest_plen
Definition: flow_entry.h:334
MacAddress dmac
Definition: flow_entry.h:293
uint32_t if_index_info
Definition: flow_entry.h:337
TagList source_tag_id_l
Definition: flow_entry.h:304
std::string dest_vn_match
Definition: flow_entry.h:295
SecurityGroupList dest_sg_id_l
Definition: flow_entry.h:303
InterfaceConstRef intf_entry
Definition: flow_entry.h:311
VnListType origin_vn_dst_list
Definition: flow_entry.h:301
uint32_t vrf
Definition: flow_entry.h:315
NextHopConstRef rpf_nh
Definition: flow_entry.h:348
uint64_t time_
Definition: flow_entry.h:380
@ FLOW_MSG_SKIP_EVICTED
Definition: flow_entry.h:373
@ FLOW_HANDLE_ASSIGN
Definition: flow_entry.h:372
uint32_t vrouter_flow_handle_
Definition: flow_entry.h:387
uint32_t hash_id_
Definition: flow_entry.h:385
uint8_t flow_gen_id_
Definition: flow_entry.h:383
uint8_t gen_id_
Definition: flow_entry.h:386
Event event_
Definition: flow_entry.h:381
FlowTableKSyncEntry * ksync_entry_
Definition: flow_entry.h:384
uint32_t flow_handle_
Definition: flow_entry.h:382
uint8_t vrouter_gen_id_
Definition: flow_entry.h:388
bool IsEqual(const FlowKey &key) const
Definition: flow_entry.h:176
uint8_t protocol
Definition: flow_entry.h:215
bool IsLess(const FlowKey &key) const
Definition: flow_entry.h:154
IpAddress src_addr
Definition: flow_entry.h:213
IpAddress dst_addr
Definition: flow_entry.h:214
uint16_t src_port
Definition: flow_entry.h:216
Address::Family family
Definition: flow_entry.h:211
uint32_t nh
Definition: flow_entry.h:212
uint16_t dst_port
Definition: flow_entry.h:217
std::string dst_match_vn
Definition: acl.h:29
std::string uuid
Definition: acl.h:24
bool other
Definition: acl.h:27
bool terminal
Definition: acl.h:26
std::string src_match_vn
Definition: acl.h:28
bool drop
Definition: acl.h:25
std::string acl_name
Definition: acl.h:30
AclDBEntryConstRef acl
Definition: acl.h:53
FlowAction action_info
Definition: flow_entry.h:277
uint32_t out_mirror_action
Definition: flow_entry.h:272
SessionPolicy sg_policy
Definition: flow_entry.h:264
SessionPolicy aps_policy
Definition: flow_entry.h:265
MatchAclParamsList m_mirror_acl_l
Definition: flow_entry.h:268
MatchAclParamsList m_vrf_assign_acl_l
Definition: flow_entry.h:274
SessionPolicy fwaas_policy
Definition: flow_entry.h:266
uint32_t policy_action
Definition: flow_entry.h:259
uint32_t mirror_action
Definition: flow_entry.h:269
MatchAclParamsList m_out_acl_l
Definition: flow_entry.h:261
MatchAclParamsList m_out_mirror_acl_l
Definition: flow_entry.h:271
void Reset()
Definition: flow_entry.cc:366
MatchAclParamsList m_acl_l
Definition: flow_entry.h:258
uint32_t vrf_assign_acl_action
Definition: flow_entry.h:275
uint32_t out_policy_action
Definition: flow_entry.h:262
uint8_t protocol
Definition: packet_header.h:28
Address::Family family
Definition: packet_header.h:31
const VnListType * src_policy_id
Definition: packet_header.h:20
TagList dst_tags_
Definition: packet_header.h:27
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
TagList src_tags_
Definition: packet_header.h:22
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 VmEntry * vm_
Definition: pkt_flow_info.h:30
MacAddress dmac
Definition: pkt_handler.h:392
uint32_t vrf
Definition: pkt_handler.h:390
IpAddress ip_daddr
Definition: pkt_handler.h:394
IpAddress ip_saddr
Definition: pkt_handler.h:393
TunnelInfo tunnel
Definition: pkt_handler.h:406
MacAddress smac
Definition: pkt_handler.h:391
const AgentHdr & GetAgentHdr() const
AgentHdr agent_hdr
Definition: pkt_handler.h:387
std::vector< PortRange > port_range
uint16_t port_count
boost::uuids::uuid rev_egress_uuid_
Definition: flow_entry.h:59
FlowAction action_info_
Definition: flow_entry.h:66
std::string vm_cfg_name_
Definition: flow_entry.h:63
uint16_t drop_reason_
Definition: flow_entry.h:64
std::string vmi_uuid_
Definition: flow_entry.h:61
IpAddress sip_
Definition: flow_entry.h:60
std::string sg_uuid_
Definition: flow_entry.h:62
boost::uuids::uuid rev_uuid_
Definition: flow_entry.h:58
std::string nw_ace_uuid_
Definition: flow_entry.h:65
uint32_t reverse_out_action
Definition: flow_entry.h:242
uint32_t action
Definition: flow_entry.h:230
uint32_t action_summary
Definition: flow_entry.h:246
void ResetAction()
Definition: flow_entry.cc:410
MatchAclParamsList m_reverse_out_acl_l
Definition: flow_entry.h:240
uint32_t reverse_action
Definition: flow_entry.h:238
bool reverse_out_rule_present
Definition: flow_entry.h:241
std::string acl_name_
Definition: flow_entry.h:245
bool rule_present
Definition: flow_entry.h:229
void ResetRuleMatchInfo()
Definition: flow_entry.cc:405
MatchAclParamsList m_reverse_acl_l
Definition: flow_entry.h:236
MatchAclParamsList m_acl_l
Definition: flow_entry.h:228
MatchAclParamsList m_out_acl_l
Definition: flow_entry.h:232
std::string rule_uuid_
Definition: flow_entry.h:244
void ResetPolicy()
Definition: flow_entry.cc:418
bool reverse_rule_present
Definition: flow_entry.h:237
bool out_rule_present
Definition: flow_entry.h:233
uint32_t out_action
Definition: flow_entry.h:234
void Reset()
Definition: pkt_handler.h:199
Definition: vrf.h:25
void set_ignore_acl(bool ignore_acl)
void set_vrf_name(const std::string &vrf_name)
const std::string & vrf_name() const
static uint64_t ClockMonotonicUsec()
Definition: time_util.h:29
static boost::posix_time::ptime UTCUsecToPTime(uint64_t tusec)
Definition: time_util.h:38
static uint64_t UTCTimestampUsec()
Definition: time_util.h:13