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 <vector>
6 #include <bitset>
7 #include <arpa/inet.h>
8 #include <netinet/in.h>
9 #include <base/os.h>
10 #include <string>
11 
12 #include <boost/date_time/posix_time/posix_time.hpp>
13 #include <boost/assign/list_of.hpp>
14 #include <boost/unordered_map.hpp>
15 #include <sandesh/sandesh_trace.h>
16 #include <base/address_util.h>
17 #include <pkt/flow_table.h>
21 
22 #include <route/route.h>
23 #include <cmn/agent_cmn.h>
24 #include <oper/interface_common.h>
25 #include <oper/nexthop.h>
26 #include <oper/tunnel_nh.h>
27 
28 #include <init/agent_param.h>
29 #include <cmn/agent_cmn.h>
30 #include <cmn/agent_stats.h>
31 #include <oper/route_common.h>
32 #include <oper/vrf.h>
33 #include <oper/vm.h>
34 #include <oper/sg.h>
35 #include <oper/qos_config.h>
36 #include <oper/global_vrouter.h>
37 
38 #include <filter/packet_header.h>
39 #include <filter/acl.h>
40 
41 #include <pkt/proto.h>
42 #include <pkt/proto_handler.h>
43 #include <pkt/pkt_handler.h>
44 #include <pkt/flow_proto.h>
45 #include <pkt/pkt_types.h>
46 #include <pkt/pkt_sandesh_flow.h>
48 #include <pkt/flow_mgmt.h>
49 #include <pkt/flow_event.h>
50 #include <pkt/flow_entry.h>
52 
53 using namespace boost::asio::ip;
54 using boost::uuids::nil_uuid;
55 const std::map<FlowEntry::FlowPolicyState, const char*>
56  FlowEntry::FlowPolicyStateStr = boost::assign::map_list_of
57  (NOT_EVALUATED, "00000000-0000-0000-0000-000000000000")
58  (IMPLICIT_ALLOW, "00000000-0000-0000-0000-000000000001")
59  (IMPLICIT_DENY, "00000000-0000-0000-0000-000000000002")
60  (DEFAULT_GW_ICMP_OR_DNS, "00000000-0000-0000-0000-000000000003")
61  (LINKLOCAL_FLOW, "00000000-0000-0000-0000-000000000004")
62  (MULTICAST_FLOW, "00000000-0000-0000-0000-000000000005")
63  (NON_IP_FLOW, "00000000-0000-0000-0000-000000000006")
64  (BGPROUTERSERVICE_FLOW, "00000000-0000-0000-0000-000000000007");
65 
66 const std::map<uint16_t, const char*>
67  FlowEntry::FlowDropReasonStr = boost::assign::map_list_of
68  ((uint16_t)DROP_UNKNOWN, "UNKNOWN")
69  ((uint16_t)SHORT_UNAVIALABLE_INTERFACE,
70  "Short flow Interface unavialable")
71  ((uint16_t)SHORT_IPV4_FWD_DIS, "Short flow Ipv4 forwarding disabled")
72  ((uint16_t)SHORT_UNAVIALABLE_VRF,
73  "Short flow VRF unavailable")
74  ((uint16_t)SHORT_NO_SRC_ROUTE, "Short flow No Source route")
75  ((uint16_t)SHORT_NO_DST_ROUTE, "Short flow No Destination route")
76  ((uint16_t)SHORT_AUDIT_ENTRY, "Short flow Audit Entry")
77  ((uint16_t)SHORT_VRF_CHANGE, "Short flow VRF CHANGE")
78  ((uint16_t)SHORT_NO_REVERSE_FLOW, "Short flow No Reverse flow")
79  ((uint16_t)SHORT_REVERSE_FLOW_CHANGE,
80  "Short flow Reverse flow change")
81  ((uint16_t)SHORT_NAT_CHANGE, "Short flow NAT Changed")
82  ((uint16_t)SHORT_FLOW_LIMIT, "Short flow Flow Limit Reached")
83  ((uint16_t)SHORT_LINKLOCAL_SRC_NAT,
84  "Short flow Linklocal source NAT failed")
85  ((uint16_t)SHORT_FAILED_VROUTER_INSTALL,
86  "Short flow vrouter install failed")
87  ((uint16_t)SHORT_INVALID_L2_FLOW, "Short flow invalid L2 flow")
88  ((uint16_t)SHORT_FLOW_ON_TSN, "Short flow TSN flow")
89  ((uint16_t)SHORT_NO_MIRROR_ENTRY, "Short flow No mirror entry ")
90  ((uint16_t)SHORT_SAME_FLOW_RFLOW_KEY,"Short flow same flow and rflow")
91  ((uint16_t)DROP_POLICY, "Flow drop Policy")
92  ((uint16_t)DROP_OUT_POLICY, "Flow drop Out Policy")
93  ((uint16_t)DROP_SG, "Flow drop SG")
94  ((uint16_t)DROP_OUT_SG, "Flow drop OUT SG")
95  ((uint16_t)DROP_REVERSE_SG, "Flow drop REVERSE SG")
96  ((uint16_t)DROP_REVERSE_OUT_SG, "Flow drop REVERSE OUT SG")
97  ((uint16_t)DROP_FIREWALL_POLICY, "Flow drop Firewall Policy")
98  ((uint16_t)DROP_OUT_FIREWALL_POLICY, "Flow drop OUT Firewall Policy")
99  ((uint16_t)DROP_REVERSE_FIREWALL_POLICY, "Flow drop REVERSE Firewall Policy")
100  ((uint16_t)DROP_REVERSE_OUT_FIREWALL_POLICY, "Flow drop REVERSE OUT Firewall Policy")
101  ((uint16_t)SHORT_NO_SRC_ROUTE_L2RPF, "Short flow No Source route for RPF NH")
102  ((uint16_t)SHORT_FAT_FLOW_NAT_CONFLICT, "Short flow Conflicting config for NAT and FAT flow")
103  ((uint16_t)DROP_FWAAS_POLICY, "Flow drop FWAAS Policy")
104  ((uint16_t)DROP_FWAAS_OUT_POLICY, "Flow drop OUT FWAAS Policy")
105  ((uint16_t)DROP_FWAAS_REVERSE_POLICY, "Flow drop REVERSE FWAAS Policy")
106  ((uint16_t)DROP_FWAAS_REVERSE_OUT_POLICY, "Flow drop REVERSE OUT FWAAS Policy")
107  ((uint16_t)SHORT_L3MH_PHY_INTF_DOWN, "Short flow l3mh compute physical interface flap");
108 
109 tbb::atomic<int> FlowEntry::alloc_count_;
111 
113 // VmFlowRef
115 const int VmFlowRef::kInvalidFd;
117  vm_(NULL), fd_(kInvalidFd), port_(0), flow_(NULL) {
118 }
119 
121 
123  port_ = 0;
124  flow_ = NULL;
125 
126  // UPDATE on linklocal flows is not supported. So, fd_ should be invalid
127  assert(fd_ == VmFlowRef::kInvalidFd);
128  assert(rhs.fd_ == VmFlowRef::kInvalidFd);
129  SetVm(rhs.vm_.get());
130 }
131 
133  Reset(true);
134 }
135 
137  flow_ = flow;
138 }
139 
140 void VmFlowRef::operator=(const VmFlowRef &rhs) {
141  assert(rhs.fd_ == VmFlowRef::kInvalidFd);
142  assert(rhs.port_ == 0);
143  // For linklocal flows, we should have called Move already. It would
144  // reset vm_. Validate it
145  if (fd_ != VmFlowRef::kInvalidFd)
146  assert(rhs.vm_.get() == NULL);
147 }
148 
149 // Move is called from Copy() routine when flow is evicted by vrouter and a
150 // new flow-add is received by agent. Use the fd_ and port_ from new flow
151 // since reverse flow will be setup based on these
153  // Release the old values
154  Reset(false);
155 
156  fd_ = rhs->fd_;
157  port_ = rhs->port_;
158  SetVm(rhs->vm_.get());
159 
160  // Ownership for fd_ is transferred. Reset RHS fields
161  // Reset VM first before resetting fd_
162  rhs->SetVm(NULL);
163  rhs->fd_ = VmFlowRef::kInvalidFd;
164  rhs->port_ = 0;
165 }
166 
167 void VmFlowRef::Reset(bool reset_flow) {
168  FreeRef();
169  FreeFd();
170  vm_.reset(NULL);
171  if (reset_flow)
172  flow_ = NULL;
173 }
174 
176  if (vm_.get() == NULL)
177  return;
178 
179  vm_->update_flow_count(-1);
180  if (fd_ != kInvalidFd) {
181  vm_->update_linklocal_flow_count(-1);
182  }
183 }
184 
186  if (fd_ == kInvalidFd) {
187  assert(port_ == 0);
188  return;
189  }
190 
191  FlowProto *proto = flow_->flow_table()->agent()->pkt()->get_flow_proto();
192  proto->update_linklocal_flow_count(-1);
194  close(fd_);
195 
196  fd_ = kInvalidFd;
197  port_ = 0;
198 }
199 
200 void VmFlowRef::SetVm(const VmEntry *vm) {
201  if (vm == vm_.get())
202  return;
203  FreeRef();
204 
205  vm_.reset(vm);
206  if (vm == NULL)
207  return;
208 
209  // update per-vm flow accounting
210  vm->update_flow_count(1);
211  if (fd_ != kInvalidFd) {
212  vm_->update_linklocal_flow_count(1);
213  }
214 
215  return;
216 }
217 
218 bool VmFlowRef::AllocateFd(Agent *agent, uint8_t l3_proto) {
219  if (fd_ != kInvalidFd)
220  return true;
221 
222  port_ = 0;
223  // Short flows are always dropped. Dont allocate FD for short flow
224  if (flow_->IsShortFlow())
225  return false;
226 
227  if (l3_proto == IPPROTO_TCP) {
228  fd_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
229  } else if (l3_proto == IPPROTO_UDP) {
230  fd_ = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
231  }
232 
233  if (fd_ == kInvalidFd) {
234  return false;
235  }
236 
237  // Update agent accounting info
240  flow_->key(), UTCTimestampUsec());
241 
242  // allow the socket to be reused upon close
243  if (l3_proto == IPPROTO_TCP) {
244  int optval = 1;
245  setsockopt(fd_, SOL_SOCKET, SO_REUSEADDR,
246  (const char*)&optval, sizeof(optval));
247  }
248 
249  struct sockaddr_in address;
250  memset(&address, 0, sizeof(address));
251  address.sin_family = AF_INET;
252  if (::bind(fd_, (struct sockaddr*) &address, sizeof(address)) < 0) {
253  FreeFd();
254  return false;
255  }
256 
257  struct sockaddr_in bound_to;
258  socklen_t len = sizeof(bound_to);
259  if (getsockname(fd_, (struct sockaddr*) &bound_to, &len) < 0) {
260  FreeFd();
261  return false;
262  }
263 
264  port_ = ntohs(bound_to.sin_port);
265  return true;
266 }
267 
269 // FlowData constructor/destructor
272  Reset();
273 }
274 
276 }
277 
279  smac = MacAddress();
280  dmac = MacAddress();
281  source_vn_list.clear();
282  source_vn_match = "";
283  dest_vn_match = "";
284  dest_vn_list.clear();
285  origin_vn_dst_list.clear();
286  origin_vn_src_list.clear();
287  origin_vn_src = "";
288  origin_vn_dst = "";
289  source_sg_id_l.clear();
290  dest_sg_id_l.clear();
293  match_p.Reset();
294  vn_entry.reset(NULL);
295  intf_entry.reset(NULL);
296  in_vm_entry.Reset(true);
297  out_vm_entry.Reset(true);
298  src_ip_nh.reset(NULL);
301  dest_vrf = 0;
303  source_plen = 0;
304  dest_plen = 0;
305  drop_reason = 0;
306  vrf_assign_evaluated = false;
307  if_index_info = 0;
308  tunnel_info.Reset();
309  flow_source_plen_map.clear();
310  flow_dest_plen_map.clear();
311  enable_rpf = true;
312  rpf_nh.reset(NULL);
315  disable_validation = false;
316  vm_cfg_name = "";
321  ttl = 0;
323  src_policy_plen = 0;
325  dst_policy_plen = 0;
326  allocated_port_ = 0;
327  underlay_gw_index_ = -1;
328 }
329 
330 static std::vector<std::string> MakeList(const VnListType &ilist) {
331  std::vector<std::string> olist;
332  for (VnListType::const_iterator it = ilist.begin();
333  it != ilist.end(); ++it) {
334  olist.push_back(*it);
335  }
336  return olist;
337 }
338 
339 std::vector<std::string> FlowData::SourceVnList() const {
340  return MakeList(source_vn_list);
341 }
342 
343 std::vector<std::string> FlowData::DestinationVnList() const {
344  return MakeList(dest_vn_list);
345 }
346 
347 std::vector<std::string> FlowData::OriginVnSrcList() const {
349 }
350 
351 std::vector<std::string> FlowData::OriginVnDstList() const {
353 }
354 
356 // MatchPolicy constructor/destructor
359  Reset();
360 }
361 
363 }
364 
366  m_acl_l.clear();
367  policy_action = 0;
368  m_out_acl_l.clear();
369  out_policy_action = 0;
370  sg_policy.Reset();
371  m_mirror_acl_l.clear();
372  mirror_action = 0;
373  m_out_mirror_acl_l.clear();
374  out_mirror_action = 0;
375  m_vrf_assign_acl_l.clear();
377  aps_policy.Reset();
379  action_info.Clear();
380 }
381 
383  m_out_acl_l.clear();
384  out_rule_present = false;
385  out_action = 0;
386 
387  m_acl_l.clear();
388  rule_present = false;
389  action = 0;
390 
391  m_reverse_acl_l.clear();
392  reverse_rule_present = false;
393  reverse_action = 0;
394 
395  m_reverse_out_acl_l.clear();
396  reverse_out_rule_present = false;
397  reverse_out_action = 0;
398 
399  action_summary = 0;
401  acl_name_ = "";
402 }
403 
406  acl_name_ = "";
407 }
408 
410  out_action = 0;
411  action = 0;
412  reverse_action = 0;
413  reverse_out_action = 0;
414  action_summary = 0;
415 }
416 
418  rule_present = false;
419  m_acl_l.clear();
420 
421  out_rule_present = false;
422  m_out_acl_l.clear();
423 
424  reverse_rule_present = false;
425  m_reverse_acl_l.clear();
426 
427  reverse_out_rule_present = false;
428  m_reverse_out_acl_l.clear();
430 }
431 
433 // FlowEventLog constructor/destructor
435 FlowEventLog::FlowEventLog() : time_(0), event_(EVENT_MAXIMUM),
436  flow_handle_(FlowEntry::kInvalidFlowHandle), flow_gen_id_(0),
437  ksync_entry_(NULL), hash_id_(FlowEntry::kInvalidFlowHandle), gen_id_(0),
438  vrouter_flow_handle_(FlowEntry::kInvalidFlowHandle), vrouter_gen_id_(0) {
439 }
440 
442 }
443 
445 // FlowEntry constructor/destructor
448  flow_table_(flow_table), flags_(0),
449  tunnel_type_(TunnelType::INVALID),
450  fip_vmi_(AgentKey::ADD_DEL_CHANGE, nil_uuid(), ""),
451  flow_mgmt_request_(NULL), flow_mgmt_info_() {
452  // ksync entry is set to NULL only on constructor and on flow delete
453  // it should not have any other explicit set to NULL
454  ksync_entry_ = NULL;
455  Reset();
456  alloc_count_.fetch_and_increment();
457 }
458 
460  assert(refcount_ == 0);
461  Reset();
462  alloc_count_.fetch_and_decrement();
463 }
464 
466  assert(ksync_entry_ == NULL);
470  const VmInterface *vm_intf =
471  dynamic_cast<const VmInterface *>(intf_entry());
472  if (vm_intf) {
473  vm_intf->update_flow_count(-2);
474  }
475  }
476  data_.Reset();
477  l3_flow_ = true;
478  gen_id_ = 0;
480  reverse_flow_entry_ = NULL;
481  deleted_ = false;
482  flags_ = 0;
485  peer_vrouter_ = "";
487  on_tree_ = false;
488  fip_ = 0;
490  refcount_ = 0;
492  fsc_ = NULL;
493  trace_ = false;
494  event_logs_.reset();
495  event_log_index_ = 0;
500  assert(flow_mgmt_request_ == NULL);
501  assert(flow_mgmt_info_.get() == NULL);
502  transaction_id_ = 0;
503 }
504 
505 void FlowEntry::Reset(const FlowKey &k) {
506  Reset();
507  key_ = k;
508 }
509 
511  alloc_count_ = 0;
512 }
513 
514 FlowEntry *FlowEntry::Allocate(const FlowKey &key, FlowTable *flow_table) {
515  // flow_table will be NULL for some UT cases
516  FlowEntry *flow;
517  if (flow_table == NULL) {
518  flow = new FlowEntry(flow_table);
519  flow->Reset(key);
520  } else {
521  flow = flow_table->free_list()->Allocate(key);
522  }
523 
524  flow->data_.in_vm_entry.Init(flow);
525  flow->data_.out_vm_entry.Init(flow);
526  return flow;
527 }
528 
529 // selectively copy fields from RHS
530 // When flow is being updated, rhs will be new flow allocated in PktFlowInfo
531 void FlowEntry::Copy(FlowEntry *rhs, bool update) {
532  if (update) {
533  rhs->data_.in_vm_entry.Reset(false);
534  rhs->data_.out_vm_entry.Reset(false);
535  } else {
536  // The operator= below will call VmFlowRef operator=. In case of flow
537  // eviction, we want to move ownership from rhs to lhs. However rhs is
538  // const ref in operator so, invode Move API to transfer ownership
541  }
542  data_ = rhs->data_;
543  flags_ = rhs->flags_;
544  hbs_intf_ = rhs->hbs_intf_;
546  nw_ace_uuid_ = rhs->nw_ace_uuid_;
548  tunnel_type_ = rhs->tunnel_type_;
549  fip_ = rhs->fip_;
550  fip_vmi_ = rhs->fip_vmi_;
551  last_event_ = rhs->last_event_;
553  trace_ = rhs->trace_;
554  if (update == false) {
555  gen_id_ = rhs->gen_id_;
556  flow_handle_ = rhs->flow_handle_;
557  /* Flow Entry is being re-used. Generate a new UUID for it. */
560  }
561 }
562 
564 // Routines to initialize FlowEntry from PktControlInfo
567  fe->refcount_.fetch_and_increment();
568 }
569 
571  FlowTable *flow_table = fe->flow_table();
572  int prev = fe->refcount_.fetch_and_decrement();
573  if (prev == 1) {
574  if (fe->on_tree()) {
575  if (flow_table->ConcurrencyCheck(flow_table->flow_task_id())
576  == false) {
577  FlowEntryPtr ref(fe);
578  FlowProto *proto=flow_table->agent()->pkt()->get_flow_proto();
579  proto->ForceEnqueueFreeFlowReference(ref);
580  return;
581  }
582  FlowTable::FlowEntryMap::iterator it =
583  flow_table->flow_entry_map_.find(fe->key());
584  assert(it != flow_table->flow_entry_map_.end());
585  flow_table->flow_entry_map_.erase(it);
586  flow_table->agent()->stats()->decr_flow_count();
587  }
588  flow_table->free_list()->Free(fe);
589  }
590 }
591 
592 // Helper Functions
593 static std::size_t HashCombine(std::size_t hash, uint64_t val) {
594  boost::hash_combine(hash, val);
595  return hash;
596 }
597 
598 static std::size_t HashIp(std::size_t hash, const IpAddress &ip) {
599  if (ip.is_v6()) {
600  uint64_t val[2];
601  Ip6AddressToU64Array(ip.to_v6(), val, 2);
602  hash = HashCombine(hash, val[0]);
603  hash = HashCombine(hash, val[1]);
604  } else if (ip.is_v4()) {
605  hash = HashCombine(hash, ip.to_v4().to_ulong());
606  } else {
607  assert(0);
608  }
609  return hash;
610 }
611 bool FlowEntry::InitFlowCmn(const PktFlowInfo *info, const PktControlInfo *ctrl,
612  const PktControlInfo *rev_ctrl,
613  FlowEntry *rflow) {
614  reverse_flow_entry_ = rflow;
616  peer_vrouter_ = info->peer_vrouter;
617  tunnel_type_ = info->tunnel_type;
618 
619  if (info->linklocal_flow) {
621  } else {
623  }
624  if (info->nat_done) {
626  } else {
628  }
629  if (info->short_flow) {
632  } else {
635  }
636  if (info->local_flow) {
638  } else {
640  }
641 
642  if (info->tcp_ack) {
644  } else {
646  }
647  if (info->bgp_router_service_flow) {
651  } else {
655  }
656 
657  if (info->alias_ip_flow) {
659  } else {
661  }
662 
663  if (info->underlay_flow) {
665  } else {
667  }
668 
669  if (IsFabricControlFlow()) {
671  } else {
673  }
674 
675  data_.intf_entry = ctrl->intf_ ? ctrl->intf_ : rev_ctrl->intf_;
676  data_.vn_entry = ctrl->vn_ ? ctrl->vn_ : rev_ctrl->vn_;
677  data_.in_vm_entry.SetVm(ctrl->vm_);
678  data_.out_vm_entry.SetVm(rev_ctrl->vm_);
679  l3_flow_ = info->l3_flow;
681 
682  return true;
683 }
684 
685 void FlowEntry::InitFwdFlow(const PktFlowInfo *info, const PktInfo *pkt,
686  const PktControlInfo *ctrl,
687  const PktControlInfo *rev_ctrl,
688  FlowEntry *rflow, Agent *agent) {
691  if (InitFlowCmn(info, ctrl, rev_ctrl, rflow) == false) {
692  return;
693  }
694  if (info->linklocal_bind_local_port) {
696  } else {
698  }
699  uint32_t intf_in = pkt->GetAgentHdr().ifindex;
700  data_.vm_cfg_name = InterfaceIdToVmCfgName(agent, intf_in);
701 
702  if (info->port_allocated) {
704  }
705 
706  if (info->ingress) {
708  } else {
710  }
712  if (ctrl->rt_ != NULL) {
713  RpfInit(ctrl->rt_, pkt->ip_saddr);
714  }
715  data_.ttl = info->ttl;
716  if (info->bgp_router_service_flow) {
717  if (info->ttl == 1) {
719  }
720  }
721 
726  data_.dest_vrf = info->dest_vrf;
727  data_.vrf = pkt->vrf;
729  data_.tunnel_info = pkt->tunnel;
730 
731  if (info->ecmp) {
733  } else {
735  }
736 
739  if (ctrl->rt_ && ctrl->rt_->is_multicast()) {
741  }
742  if (rev_ctrl->rt_ && rev_ctrl->rt_->is_multicast()) {
744  }
745 
748 
750  if (info->flood_unknown_unicast) {
752  if (info->ingress) {
753  GetSourceRouteInfo(ctrl->rt_);
754  } else {
755  GetSourceRouteInfo(rev_ctrl->rt_);
756  }
758  } else {
759  GetSourceRouteInfo(ctrl->rt_);
760  GetDestRouteInfo(rev_ctrl->rt_);
761  }
762 
763  data_.smac = pkt->smac;
764  data_.dmac = pkt->dmac;
765 
767  const VmInterface *vm_intf =
768  dynamic_cast<const VmInterface *>(intf_entry());
769  if (vm_intf) {
770  vm_intf->update_flow_count(2);
771  }
772  }
773 
775  info->pkt->ip_saddr, info->pkt->ip_daddr,
776  info->pkt->ip_proto, info->pkt->sport, info->pkt->dport);
777 }
778 
779 void FlowEntry::InitRevFlow(const PktFlowInfo *info, const PktInfo *pkt,
780  const PktControlInfo *ctrl,
781  const PktControlInfo *rev_ctrl,
782  FlowEntry *rflow, Agent *agent) {
783  uint32_t intf_in;
784  if (InitFlowCmn(info, ctrl, rev_ctrl, rflow) == false) {
785  return;
786  }
788  if (ctrl->intf_) {
789  intf_in = ctrl->intf_->id();
790  } else {
791  intf_in = Interface::kInvalidIndex;
792  }
793  data_.vm_cfg_name = InterfaceIdToVmCfgName(agent, intf_in);
794 
795  // Compute reverse flow fields
797  if (ctrl->intf_) {
798  if (info->ComputeDirection(ctrl->intf_)) {
800  } else {
802  }
803  }
805  if (ctrl->rt_ != NULL) {
806  RpfInit(ctrl->rt_, pkt->ip_daddr);
807  }
808 
809  if (info->bgp_router_service_flow) {
810  if ((info->ttl == 1)|| (info->ttl == BGP_SERVICE_TTL_FWD_FLOW)) {
812  }
813  }
814 
819  data_.vrf = info->dest_vrf;
820 
821  if (!info->nat_done) {
823  } else {
824  data_.dest_vrf = info->nat_dest_vrf;
825  }
826  if (info->ecmp) {
828  } else {
830  }
832 
835 
837  if (info->flood_unknown_unicast) {
839  if (info->ingress) {
840  GetSourceRouteInfo(rev_ctrl->rt_);
841  } else {
842  GetSourceRouteInfo(ctrl->rt_);
843  }
844  //Set source VN and dest VN to be same
845  //since flooding happens only for layer2 routes
846  //SG id would be left empty, user who wants
847  //unknown unicast to happen should modify the
848  //SG to allow such traffic
850  } else {
851  GetSourceRouteInfo(ctrl->rt_);
852  GetDestRouteInfo(rev_ctrl->rt_);
853  }
854 
855  data_.smac = pkt->dmac;
856  data_.dmac = pkt->smac;
857 
859  const VmInterface *vm_intf =
860  dynamic_cast<const VmInterface *>(intf_entry());
861  if (vm_intf) {
862  vm_intf->update_flow_count(2);
863  }
864  }
865 
867  info->pkt->ip_saddr, info->pkt->ip_daddr,
868  info->pkt->ip_proto, info->pkt->sport, info->pkt->dport);
869 }
870 
871 void FlowEntry::InitAuditFlow(uint32_t flow_idx, uint8_t gen_id) {
872  gen_id_ = gen_id;
873  flow_handle_ = flow_idx;
882 }
883 
884 
885 // Fabric control flows are following,
886 // - XMPP connection to control node
887 // - SSH connection to vhost
888 // - Ping to vhost
889 // - Introspect to vhost
890 // - Port-IPC connection to vhost
891 // - Contrail-Status UVE
892 // TODO : Review this
894  Agent *agent = flow_table()->agent();
895  if (agent->get_vhost_disable_policy()) {
896  return false;
897  }
898 
899  if (key_.dst_addr.is_v4() == false) {
900  return false;
901  }
902 
903  if (IsNatFlow()) {
904  return false;
905  }
906 
907  if (key_.protocol == IPPROTO_TCP) {
908  if (key_.src_addr == agent->router_id()) {
909  for (int i = 0; i < MAX_XMPP_SERVERS; i++) {
910  if (key_.dst_addr.to_string() !=
912  continue;
913  if (key_.dst_port == agent->controller_ifmap_xmpp_port(i)) {
914  return true;
915  }
916  }
917 
918  for (int i = 0; i < MAX_XMPP_SERVERS; i++) {
919  if (key_.dst_addr.to_string() !=
920  agent->dns_server(i))
921  continue;
923  return true;
924  }
925 
926  if (key_.dst_port == agent->dns_server_port(i)) {
927  return true;
928  }
929  }
930 
931  std::ostringstream collector;
932  collector << key_.dst_addr.to_string() << ":" <<
934  std::vector<string>::const_iterator it =
935  agent->GetCollectorlist().begin();
936  for(; it != agent->GetCollectorlist().end(); it++) {
937  if (collector.str() == *it) {
938  return true;
939  }
940  }
941 
942  Ip4Address metadata_fabric_ip;
943  uint16_t metadata_fabric_port = 0;
944  IpAddress local_ip;
945  uint16_t local_port = 0;
946  std::string nova_hostname;
947  agent->oper_db()->global_vrouter()->
948  FindLinkLocalService(GlobalVrouter::kMetadataService,
949  &local_ip, &local_port,
950  &nova_hostname,
951  &metadata_fabric_ip,
952  &metadata_fabric_port);
953  if (key_.dst_addr.to_v4() == metadata_fabric_ip &&
954  key_.dst_port == metadata_fabric_port) {
955  return true;
956  }
957  }
958 
959 
960  if (key_.dst_addr == agent->router_id()) {
961  return (key_.dst_port == 22);
962  }
963 
964  if (key_.src_addr == agent->router_id()) {
965  return (key_.src_port == 22);
966  }
967  return false;
968  }
969 
970  if (key_.protocol == IPPROTO_ICMP) {
971  return (key_.src_addr == agent->router_id() ||
972  key_.dst_addr == agent->router_id());
973  }
974 
975  return false;
976 }
977 
979 // Utility routines
981 // Find L2 Route for the MAC address.
983  const MacAddress &mac) {
984  BridgeAgentRouteTable *table = static_cast<BridgeAgentRouteTable *>
985  (vrf->GetBridgeRouteTable());
986  return table->FindRouteNoLock(mac);
987 }
988 
990  const IpAddress &addr) {
991  AgentRoute *rt = NULL;
992  if (addr.is_v4()) {
993  InetUnicastRouteEntry key(NULL, addr, 32, false);
994  rt = entry->GetUcRoute(key);
995  } else {
996  InetUnicastRouteEntry key(NULL, addr, 128, false);
997  rt = entry->GetUcRoute(key);
998  }
999  if (rt != NULL && rt->IsRPFInvalid()) {
1000  return NULL;
1001  }
1002  return rt;
1003 }
1004 
1006  const MacAddress &mac,
1007  const IpAddress &ip,
1008  uint32_t ethernet_tag) {
1009  EvpnAgentRouteTable *table = static_cast<EvpnAgentRouteTable *>(
1010  vrf->GetEvpnRouteTable());
1011  return table->FindRouteNoLock(mac, ip,
1013  ethernet_tag);
1014 }
1015 
1017  FlowEntry *rflow = reverse_flow_entry_.get();
1018  if (rflow) {
1019  return rflow->fip();
1020  }
1021  return 0;
1022 }
1023 
1025  FlowEntry *rflow = reverse_flow_entry_.get();
1026  if (rflow) {
1027  return rflow->fip_vmi();
1028  }
1029  return VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, nil_uuid(), "");
1030 }
1031 
1032 void FlowEntry::UpdateFipStatsInfo(uint32_t fip, uint32_t id, Agent *agent) {
1033  fip_ = fip;
1034  fip_vmi_ = InterfaceIdToKey(agent, id);
1035 }
1036 
1037 void FlowEntry::set_flow_handle(uint32_t flow_handle, uint8_t gen_id) {
1038  if (flow_handle_ != flow_handle) {
1039  assert(flow_handle_ == kInvalidFlowHandle);
1041  }
1042  gen_id_ = gen_id;
1043 }
1044 
1045 const std::string& FlowEntry::acl_assigned_vrf() const {
1047 }
1048 
1051  const VrfEntry *vrf = static_cast<const VrfEntry *>(
1052  flow_table()->agent()->vrf_table()->FindActiveEntry(&vrf_key));
1053  if (vrf) {
1055  bool set_dest_vrf = true;
1057  reverse_flow_entry() &&
1059  //Packet is getting DNATed, VRF assign ACL action
1060  //is applied on floating-ip VN and the destination VRF should
1061  //be retained as interface VRF
1062  set_dest_vrf = false;
1063  }
1064 
1065  if (set_dest_vrf) {
1066  data_.dest_vrf = vrf->vrf_id();
1067  }
1068  return;
1069  }
1071 }
1072 
1075 }
1076 
1078  params->sip_ = key().src_addr;
1079  FlowEntry *rev_flow = reverse_flow_entry();
1080  if (rev_flow) {
1081  params->rev_uuid_ = rev_flow->uuid();
1082  params->vm_cfg_name_ = rev_flow->data().vm_cfg_name;
1083  params->sg_uuid_ = rev_flow->sg_rule_uuid();
1084  params->rev_egress_uuid_ = rev_flow->egress_uuid();
1085  params->nw_ace_uuid_ = rev_flow->nw_ace_uuid();
1086  params->drop_reason_ = rev_flow->data().drop_reason;
1087  params->action_info_ = rev_flow->data().match_p.action_info;
1088  if (rev_flow->intf_entry()) {
1089  const VmInterface *vmi =
1090  dynamic_cast<const VmInterface *>(rev_flow->intf_entry());
1091  if (vmi) {
1092  params->vmi_uuid_ = UuidToString(vmi->vmi_cfg_uuid());
1093  } else {
1094  params->vmi_uuid_ = UuidToString(rev_flow->intf_entry()->
1095  GetUuid());
1096  }
1097  }
1098 
1099  if (key().family != Address::INET) {
1100  return;
1101  }
1104  const FlowKey *nat_key = &rev_flow->key();
1105  if (key().src_addr != nat_key->dst_addr) {
1106  params->sip_ = nat_key->dst_addr;
1107  }
1108  }
1109  }
1110 }
1111 
1112 bool FlowEntry::ShouldDrop(uint32_t action) {
1113  if (action & TrafficAction::DROP_FLAGS)
1114  return true;
1115 
1117  return true;
1118 
1119  return false;
1120 }
1121 
1123 // Flow RPF
1124 //
1125 // VRouter enforces RPF check based on RPF-NH programmed in the flow. The RPF
1126 // NH can be of two types,
1127 // - Unicast NH :
1128 // In this case, VRouter matches with incoming interface/tunnel-src with
1129 // RPF NH the flow
1130 //
1131 // - ECMP NH :
1132 // In this case, VRouter picks an ECMP component-nh and matches with incoming
1133 // interface/tunnel-src. The index for component-nh is got from reverse flow.
1134 //
1135 // RPF-NH cases
1136 // ------------
1137 // 1. Baremetals
1138 // Agent is not aware of IP address assigned for baremetals. So, RPF check
1139 // for baremetals is based on the L2-Route
1140 //
1141 // 2. Layer-2 Flows
1142 // If agent know the Inet route for source-ip in packet, RPF is based on
1143 // the Inet route for source-ip. There are some exceptions for this rule,
1144 // - If Inet route for source-ip is ECMP, then RPF is based on layer-2 route
1145 // - If Inet route for source-ip is not-host route, then RPF is based on
1146 // layer-2 routes
1147 //
1148 // If packet is from BMS (egress flow), its possible that agent does not
1149 // know IP address for BMS. In such case, RPF is based on L2-Route
1150 //
1151 // 3. Layer-3 Flows from VMI
1152 // RPF check will be based on the InterfaceNH for VMI
1153 //
1154 // 4. Layer-3 Flows from Fabric with unicast-NH
1155 // The unicast-nh is used as RPF-NH
1156 //
1157 // 5. Layer-3 Flows from Fabric with composite-NH
1158 // VRouter picks NH from flow and the ecmp-index from reverse flow.
1159 //
1160 // The ecmp-index in reverse is computed based on route for dest-ip in
1161 // VRF got post VRF translation if any
1162 //
1163 // Note, the RPF must be picked post VRF translation since order of members
1164 // in Composite-NH may vary across VRF
1165 //
1166 // Route Tracking
1167 // --------------
1168 // Flow Management should track the route for ip1 in vrf4 to update RPF-NH
1169 //
1170 // RPF Computation
1171 // ---------------
1172 // RPF computation happens in two stages
1173 // 1. FlowEntry creation (RpfInit):
1174 // Called during FlowEntry init. Computes src_ip_nh for flow.
1175 //
1176 // For layer-2 flows, RPF-NH Is same as src_ip_nh
1177 // For Non-ECMP layer-3 flows, RPF-NH is same as src_ip_nh
1178 // For ECMP layer-3 flows, RPF-NH must be computed only after VRF
1179 // translation is computed for reverse flow.
1180 //
1181 // 2. Post ACL processing (RpfUpdate):
1182 // Post ACL processing, all VRF translation rules are identified.
1183 // The RPF-NH is computed in this method.
1185 // Utility method to set rpf_vrf and rpf_plen fields
1186 static void SetRpfFieldsInternal(FlowEntry *flow, const AgentRoute *rt) {
1187  // If there is no route, we should track default route
1188  if (rt == NULL) {
1189  flow->data().rpf_vrf = flow->data().vrf;
1190  flow->data().rpf_plen = 0;
1191  return;
1192  }
1193 
1194  const InetUnicastRouteEntry *inet_rt =
1195  dynamic_cast<const InetUnicastRouteEntry *>(rt);
1196  if (inet_rt) {
1197  flow->data().rpf_vrf = inet_rt->vrf()->vrf_id();
1198  flow->data().rpf_plen = inet_rt->prefix_length();
1199  return;
1200  }
1201 
1202  if (!flow->l3_flow()) {
1203  flow->data().rpf_vrf = rt->vrf()->vrf_id();
1204  /*
1205  * For L2 flows also plen is found using GetUCRoute
1206  * plen is stored in L2 route entry
1207  * this changed to address CEM-27722
1208  */
1209  const BridgeRouteEntry *bridge_rt =
1210  dynamic_cast<const BridgeRouteEntry *>(rt);
1211  if (bridge_rt != NULL) {
1212  BridgeRouteEntry *temp = const_cast<BridgeRouteEntry *>(bridge_rt);
1213  flow->data().rpf_plen = temp->prefix_length();
1214  }
1215  return;
1216  }
1217  // Route is not INET. Dont track any route
1219  flow->data().rpf_plen = 0;
1220  return;
1221 }
1222 
1223 // Utility method to set src_ip_nh fields
1225  const NextHop *src_ip_nh) {
1226  data_.src_ip_nh.reset(src_ip_nh);
1227  SetRpfFieldsInternal(this, rt);
1228  return;
1229 }
1230 
1232  data_.rpf_nh.reset(rpf_nh);
1233 }
1234 
1235 // Utility method to set rpf_nh fields
1236 void FlowEntry::RpfSetRpfNhFields(const AgentRoute *rt, const NextHop *rpf_nh) {
1237  data_.rpf_nh.reset(rpf_nh);
1238  SetRpfFieldsInternal(this, rt);
1239  return;
1240 }
1241 
1242 // This method is called when flow is initialized. The RPF-NH cannot be
1243 // computed at this stage since we dont know if reverse flow has VRF
1244 // translation or not.
1245 // This method only sets src_ip_nh field
1246 //
1247 // In case of layer-3 flow "rt" is inet route for source-ip in source-vrf
1248 // In case of layer-2 flow "rt" is l2 route for smac in source-vrf
1249 void FlowEntry::RpfInit(const AgentRoute *rt, const IpAddress &sip) {
1250  // Set src_ip_nh based on rt first
1252 
1253  // RPF enabled?
1254  bool rpf_enable = true;
1255  if (data_.vn_entry && data_.vn_entry->enable_rpf() == false)
1256  rpf_enable = false;
1258  rpf_enable = false;
1259 
1260  // The src_ip_nh can change below only for l2 flows
1261  // For l3-flow, rt will already be a INET route
1262  if (l3_flow())
1263  return;
1264 
1265  // For layer-2 flows, we use l2-route for RPF in following cases
1266  // 1. Interface is of type BAREMETAL (ToR/TSN only)
1267  //
1268  // 2. ECMP is not supported for l2-flows. If src-ip lookup resulted in
1269  // ECMP-NH fallback to the original l2-route
1270  //
1271  // 3. In case of OVS, ToR will export layer-2 route and MX will export a
1272  // layer-3 subnet route covering all the ToRs. In this case, when ToR
1273  // send layer-2 packet the layer-3 route will point to MX and RPF fails.
1274  // Assuming MX only gives subnet-route, use inet-route only if its
1275  // host-route
1276  // 4. Its an egress flow and there is no route for IP address
1277  const VmInterface *vmi =
1278  dynamic_cast<const VmInterface *>(intf_entry());
1279  if (vmi && vmi->vmi_type() == VmInterface::BAREMETAL) {
1280  return;
1281  }
1282 
1283  VrfEntry *vrf = rt->vrf();
1284  const InetUnicastRouteEntry *src_ip_rt =
1285  static_cast<InetUnicastRouteEntry *>
1286  (FlowEntry::GetUcRoute(vrf, sip));
1287 
1288  if (src_ip_rt == NULL) {
1289  // For egress flow, with no l3-route then do rpf based on l2-route
1290  // For ingress flow, with no l3-route, make it short flow
1291  if (rpf_enable && IsIngressFlow()) {
1294  }
1295  return;
1296  }
1297 
1298  if (src_ip_rt->IsHostRoute() == false)
1299  return;
1300 
1301  const NextHop *src_ip_nh = src_ip_rt->GetActiveNextHop();
1302  if ((src_ip_nh != NULL) && src_ip_nh->GetType() == NextHop::COMPOSITE)
1303  return;
1304 
1305  RpfSetSrcIpNhFields(src_ip_rt, src_ip_nh);
1306  return;
1307 }
1308 
1309 // Should src_ip_nh be treated as RPF-NH
1311  // For l2-flows, src_ip_nh is same as RPF-NH
1312  if (l3_flow() == false)
1313  return true;
1314 
1315  // Dont bother about RPF for short-flows
1317  return true;
1318 
1319  // rpf-nh can change only in case of composite
1320  if (data_.src_ip_nh->GetType() != NextHop::COMPOSITE)
1321  return true;
1322 
1323  const FlowEntry *rflow = reverse_flow_entry();
1324  if (rflow == NULL) {
1325  FlowInfo flow_info;
1326  FillFlowInfo(flow_info);
1327  FLOW_TRACE(Trace, "Invalid reverse flow for setting ECMP index",
1328  flow_info);
1329  return true;
1330  }
1331 
1332  return false;
1333 }
1334 
1336  const NextHop *nh = NULL;
1337  // If we are here, its guaranteed that src_ip_nh is composite
1338  const CompositeNH *cnh =
1339  dynamic_cast<const CompositeNH *>(data_.src_ip_nh.get());
1340  assert(cnh != NULL);
1341 
1342  // Use flow_key_nh if VMI is part of composite. Else its guaranteed
1343  // that RPF will fail for flow. So, use discard-nh for RPF
1344  const VmInterface *vmi =
1345  dynamic_cast<const VmInterface *>(intf_entry());
1346  if (cnh->HasVmInterface(vmi)) {
1347  nh = vmi->flow_key_nh();
1348  } else {
1349  nh = data_.src_ip_nh.get();
1350  }
1351 
1352  // Change only the RPF-NH. The vrf and plen dont change here
1353  RpfSetRpfNhFields(nh);
1354  return;
1355 }
1356 
1358  const FlowEntry *rflow = reverse_flow_entry();
1359 
1360  // RPF-NH can change only if VRF in forward flow and translated VRF in
1361  // reverse flow are different
1362  if (rflow->data().flow_dest_vrf == data_.vrf) {
1364  return;
1365  }
1366 
1367  // Find destination VRF from reverse flow
1368  const VrfEntry *vrf = rflow->GetDestinationVrf();
1369  if (vrf == NULL) {
1370  FlowInfo flow_info;
1371  FillFlowInfo(flow_info);
1372  FLOW_TRACE(Trace, "Error setting RPF NH. Destination VRF not found "
1373  "in reverse flow", flow_info);
1374  return;
1375  }
1376 
1377  InetUnicastRouteEntry *rt = static_cast<InetUnicastRouteEntry *>
1378  (FlowEntry::GetUcRoute(vrf, key().src_addr));
1379  if (!rt) {
1380  FlowInfo flow_info;
1381  FillFlowInfo(flow_info);
1382  FLOW_TRACE(Trace, "Error setting RPF NH. Route not found in "
1383  "destination vrf", flow_info);
1384  return;
1385  }
1386 
1388  return;
1389 }
1390 
1391 // Computes RPF-NH for flow based on ip_src_nh
1392 // Must be called after policy lookup is done
1394  // Is RPF check enabled?
1395  data_.enable_rpf = true;
1396  if (data_.vn_entry) {
1397  data_.enable_rpf = data_.vn_entry->enable_rpf();
1398  }
1399 
1400  if (data_.disable_validation) {
1401  data_.enable_rpf = false;
1402  }
1403 
1404  if (data_.enable_rpf == false) {
1405  data_.rpf_nh = NULL;
1406  return;
1407  }
1408 
1409  if (RpfFromSrcIpNh()) {
1411  return;
1412  }
1413 
1416  } else {
1417  RpfComputeEgress();
1418  }
1419 }
1420 
1422  /*
1423  * If the flow is Local + Ingress + Forward
1424  * then it will be considered as client session
1425  */
1429  return true;
1430  }
1431  /*
1432  * If the flow is (Ingress + Forward) OR
1433  * (Egress + Reverse)
1434  * then it will be consideres as client session
1435  */
1438  return true;
1439  }
1440  } else {
1442  return true;
1443  }
1444  }
1445  return false;
1446 }
1447 
1449  /*
1450  * If the flow is Local + Ingress + Reverse
1451  * then it will be considered as server session
1452  */
1456  return true;
1457  }
1458  /*
1459  * If the flow is (Egress + Forward) OR
1460  * (Ingress + Reverse)
1461  * then it will be consideres as server session
1462  */
1465  return true;
1466  }
1467  } else {
1469  return true;
1470  }
1471  }
1472  return false;
1473 }
1475 // Flow entry fileds updation routines
1477 std::string FlowEntry::DropReasonStr(uint16_t reason) {
1478  std::map<uint16_t, const char*>::const_iterator it =
1479  FlowDropReasonStr.find(reason);
1480  if (it != FlowDropReasonStr.end()) {
1481  return string(it->second);
1482  }
1483  return "UNKNOWN";
1484 }
1485 
1486 // Get src-vn/sg-id/plen from route
1487 // src-vn and sg-id are used for policy lookup
1488 // plen is used to track the routes to use by flow_mgmt module
1490  Agent *agent = flow_table()->agent();
1491  const InetUnicastRouteEntry *inet_rt =
1492  dynamic_cast<const InetUnicastRouteEntry *>(rt);
1493 
1494  if (inet_rt && is_flags_set(FlowEntry::FabricFlow)) {
1495  const VrfEntry *policy_vrf =
1496  static_cast<const VrfEntry *>(agent->
1497  vrf_table()->FindVrfFromId(data_.src_policy_vrf));
1498 
1499  //Policy lookup needs to happen in Policy VRF
1500  AgentRoute *new_rt = GetUcRoute(policy_vrf,
1501  inet_rt->prefix_address());
1502  data_.src_policy_plen = 0;
1503  if (new_rt) {
1504  rt = new_rt;
1505  inet_rt = dynamic_cast<const InetUnicastRouteEntry *>(new_rt);
1506  data_.src_policy_plen = inet_rt->prefix_length();
1507  data_.src_policy_vrf = inet_rt->vrf()->vrf_id();
1508  }
1509  }
1510 
1511  const AgentPath *path = NULL;
1512  if (rt) {
1513  path = rt->GetActivePath();
1514  }
1515  if (path == NULL) {
1519  data_.source_plen = 0;
1522  } else {
1523  data_.source_vn_list = path->dest_vn_list();
1524  if (path->dest_vn_list().size())
1525  data_.source_vn_match = *path->dest_vn_list().begin();
1526  data_.origin_vn_src = path->origin_vn();
1527  if (!path->origin_vn().empty()) {
1528  data_.origin_vn_src_list.insert(path->origin_vn());
1529  }
1530  data_.source_sg_id_l = path->sg_list();
1532  data_.source_tag_id_l = path->tag_list();
1533  }
1534  /* Handle case when default route NextHop points to vrf */
1535  if (rt) {
1536  const NextHop *anh = rt->GetActiveNextHop();
1537  if (anh && anh->GetType() == NextHop::VRF) {
1538  const VrfNH *nh =
1539  static_cast<const VrfNH *>(anh);
1540  AgentRoute *new_rt = GetUcRoute(nh->GetVrf(), key_.src_addr);
1541  if (new_rt) {
1542  path = new_rt->GetActivePath();
1543  if (path) {
1544  data_.origin_vn_src = path->origin_vn();
1545  if (!path->origin_vn().empty()) {
1546  data_.origin_vn_src_list.insert(path->origin_vn());
1547  }
1548  }
1549  }
1550  }
1551  }
1552 
1553 }
1554 
1555 // Get dst-vn/sg-id/plen from route
1556 // dst-vn and sg-id are used for policy lookup
1557 // plen is used to track the routes to use by flow_mgmt module
1559  Agent *agent = flow_table()->agent();
1560  const AgentPath *path = NULL;
1561  if (rt) {
1562  path = rt->GetActivePath();
1563  }
1564 
1565  const InetUnicastRouteEntry *inet_rt =
1566  dynamic_cast<const InetUnicastRouteEntry *>(rt);
1567  if (inet_rt && is_flags_set(FlowEntry::FabricFlow)) {
1568  data_.dst_policy_plen = 0;
1569  const VrfEntry *policy_vrf =
1570  static_cast<const VrfEntry *>(agent->
1571  vrf_table()->FindVrfFromId(data_.dst_policy_vrf));
1572 
1573  AgentRoute *new_rt =
1574  GetUcRoute(policy_vrf, inet_rt->prefix_address());
1575  if (new_rt) {
1576  rt = new_rt;
1577  inet_rt = dynamic_cast<const InetUnicastRouteEntry *>(rt);
1578  data_.dst_policy_plen = inet_rt->prefix_length();
1579  data_.dst_policy_vrf = inet_rt->vrf()->vrf_id();
1580  }
1581  }
1582 
1583  if (rt) {
1584  path = rt->GetActivePath();
1585  }
1586 
1587  if (path == NULL) {
1591  data_.dest_plen = 0;
1594  } else {
1595  data_.dest_vn_list = path->dest_vn_list();
1596  if (path->dest_vn_list().size())
1597  data_.dest_vn_match = *path->dest_vn_list().begin();
1598  data_.origin_vn_dst = path->origin_vn();
1599  if (!path->origin_vn().empty()) {
1600  data_.origin_vn_dst_list.insert(path->origin_vn());
1601  }
1602  data_.dest_sg_id_l = path->sg_list();
1603  data_.dest_plen = rt->prefix_length();
1604  data_.dest_tag_id_l = path->tag_list();
1605  }
1606 
1607  /* Handle case when default route NextHop points to vrf */
1608  if (rt) {
1609  const NextHop *anh = rt->GetActiveNextHop();
1610  if (anh && anh->GetType() == NextHop::VRF) {
1611  const VrfNH *nh =
1612  static_cast<const VrfNH *>(anh);
1613  AgentRoute *new_rt = GetUcRoute(nh->GetVrf(), key_.dst_addr);
1614  if (new_rt) {
1615  path = new_rt->GetActivePath();
1616  if (path) {
1617  data_.origin_vn_dst = path->origin_vn();
1618  if (!path->origin_vn().empty()) {
1619  data_.origin_vn_dst_list.insert(path->origin_vn());
1620  }
1621  }
1622  }
1623  }
1624  }
1625 }
1626 
1628  if (id != Interface::kInvalidIndex) {
1629  Interface *itf = agent->interface_table()->FindInterface(id);
1630  if (itf && (itf->type() == Interface::VM_INTERFACE)) {
1632  itf->name());
1633  }
1634  }
1635  return VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, nil_uuid(), "");
1636 }
1637 
1638 uint32_t FlowEntry::InterfaceKeyToId(Agent *agent, const VmInterfaceKey &key) {
1639  const Interface *intf = dynamic_cast<const Interface*>
1640  (agent->interface_table()->FindActiveEntry(&key));
1641  if (intf) {
1642  return intf->id();
1643  }
1644  return Interface::kInvalidIndex;
1645 }
1646 
1647 const std::string FlowEntry::InterfaceIdToVmCfgName(Agent *agent, uint32_t id) {
1648  if (id != Interface::kInvalidIndex) {
1649  const VmInterface *itf = dynamic_cast <const VmInterface *>
1650  (agent->interface_table()->FindInterface(id));
1651  if (itf) {
1652  const VmEntry *vm = itf->vm();
1653  if (vm) {
1654  return vm->GetCfgName();
1655  }
1656  }
1657  }
1658  return "";
1659 }
1661 // Routines to compute ACL to be applied (including network-policy, SG and
1662 // VRF-Assign Rules
1665  /* Reset acl list*/
1666  data_.match_p.m_acl_l.clear();
1667  data_.match_p.m_out_acl_l.clear();
1668  data_.match_p.m_mirror_acl_l.clear();
1670  /* Reset sg acl list*/
1675 }
1676 
1677 // Rebuild all the policy rules to be applied
1678 void FlowEntry::GetPolicyInfo(const VnEntry *vn, const FlowEntry *rflow) {
1679  if (vn == NULL) {
1680  return;
1681  }
1682 
1683  // Reset old values first
1684  ResetPolicy();
1685 
1686  // Short flows means there is some information missing for the flow. Skip
1687  // getting policy information for short flow. When the information is
1688  // complete, GetPolicyInfo is called again
1690  return;
1691  }
1692 
1693  // ACL supported on VMPORT interfaces only
1694  if (data_.intf_entry == NULL)
1695  return;
1696 
1697  bool vgw_pass = true;
1698  if (data_.intf_entry->type() == Interface::INET) {
1699  vgw_pass = false;
1700  InetInterface* inet_intf = (InetInterface*)(data_.intf_entry).get();
1701  if ((inet_intf != NULL) && (inet_intf->sub_type() == InetInterface::SIMPLE_GATEWAY))
1702  vgw_pass = true;
1703  }
1704  if ((data_.intf_entry->type() != Interface::VM_INTERFACE) && !vgw_pass)
1705  return;
1706 
1707  // Get Network policy/mirror cfg policy/mirror policies
1708  GetPolicy(vn, rflow);
1709 
1710  // Get Sg list
1711  GetSgList(data_.intf_entry.get());
1712 
1713  //Get VRF translate ACL
1714  GetVrfAssignAcl();
1715 
1716  //Get Application policy set ACL
1718 
1719 }
1720 
1723 }
1724 
1727 }
1728 
1730  GetPolicyInfo(data_.vn_entry.get(), rflow);
1731 }
1732 
1733 void FlowEntry::GetPolicy(const VnEntry *vn, const FlowEntry *rflow) {
1734  if (vn == NULL)
1735  return;
1736 
1737  MatchAclParams acl;
1738 
1739  // Get Mirror configuration first
1740  if (vn->GetMirrorAcl()) {
1741  acl.acl = vn->GetMirrorAcl();
1742  data_.match_p.m_mirror_acl_l.push_back(acl);
1743  }
1744 
1745  if (vn->GetMirrorCfgAcl()) {
1746  acl.acl = vn->GetMirrorCfgAcl();
1747  data_.match_p.m_mirror_acl_l.push_back(acl);
1748  }
1749 
1750  // Dont apply network-policy for linklocal, bgp router service
1751  // and subnet broadcast flow
1757  return;
1758  }
1759 
1760  if (vn->GetAcl()) {
1761  acl.acl = vn->GetAcl();
1762  data_.match_p.m_acl_l.push_back(acl);
1763  }
1764 
1765  const VnEntry *rvn = NULL;
1766  // For local flows, we have to apply NW Policy from out-vn also
1767  if (!is_flags_set(FlowEntry::LocalFlow) || rflow == NULL) {
1768  // Not local flow
1769  return;
1770  }
1771 
1772  rvn = rflow->vn_entry();
1773  if (rvn == NULL) {
1774  return;
1775  }
1776 
1777  if (rvn->GetAcl()) {
1778  acl.acl = rvn->GetAcl();
1779  data_.match_p.m_out_acl_l.push_back(acl);
1780  }
1781 
1782  if (rvn->GetMirrorAcl()) {
1783  acl.acl = rvn->GetMirrorAcl();
1784  data_.match_p.m_out_mirror_acl_l.push_back(acl);
1785  }
1786 
1787  if (rvn->GetMirrorCfgAcl()) {
1788  acl.acl = rvn->GetMirrorCfgAcl();
1789  data_.match_p.m_out_mirror_acl_l.push_back(acl);
1790  }
1791 }
1792 
1794  // VRF-Assign rules valid only for routed packets
1795  if (l3_flow() == false)
1796  return;
1797 
1798  if (data_.intf_entry == NULL) {
1799  return;
1800  }
1801 
1802  if (data_.intf_entry->type() != Interface::VM_INTERFACE) {
1803  return;
1804  }
1805 
1811  return;
1812  }
1813 
1814  const VmInterface *intf =
1815  static_cast<const VmInterface *>(data_.intf_entry.get());
1816  //If interface has a VRF assign rule, choose the acl and match the
1817  //packet, else get the acl attached to VN and try matching the packet to
1818  //network acl
1819  const AclDBEntry* acl = NULL;
1820  if (is_flags_set(FlowEntry::NatFlow) == false) {
1821  acl = intf->vrf_assign_acl();
1822  }
1823 
1824  if (acl == NULL) {
1825  acl = data_.vn_entry.get()->GetAcl();
1826  }
1827  if (!acl) {
1828  return;
1829  }
1830 
1831  MatchAclParams m_acl;
1832  m_acl.acl = acl;
1833  data_.match_p.m_vrf_assign_acl_l.push_back(m_acl);
1834 }
1835 
1836 void FlowEntry::GetSgList(const Interface *intf) {
1837  // Dont apply network-policy for linklocal and multicast flows
1842  return;
1843  }
1844 
1845  // SG ACL's are reflexive. Skip SG for reverse flow
1847  return;
1848  }
1849 
1850  // Get virtual-machine port for forward flow
1851  const VmInterface *vm_port = NULL;
1852  bool vgw_pass = false;
1853  if (intf != NULL) {
1854  if (intf->type() == Interface::INET) {
1855  const InetInterface* inet_intf = static_cast<const InetInterface *>(intf);
1856  if ((inet_intf != NULL) && (inet_intf->sub_type() == InetInterface::SIMPLE_GATEWAY)) {
1857  vgw_pass = true;
1858  }
1859  }
1860  if (intf->type() == Interface::VM_INTERFACE) {
1861  vm_port = static_cast<const VmInterface *>(intf);
1862  vgw_pass = true;
1863  }
1864  }
1865 
1866  if (!vgw_pass) {
1867  return;
1868  }
1869 
1870  // Get virtual-machine port for reverse flow
1871  FlowEntry *rflow = reverse_flow_entry();
1872  const VmInterface *reverse_vm_port = NULL;
1873  if (rflow != NULL) {
1874  if (rflow->data().intf_entry.get() != NULL) {
1875  if (rflow->data().intf_entry->type() == Interface::VM_INTERFACE) {
1876  reverse_vm_port = static_cast<const VmInterface *>
1877  (rflow->data().intf_entry.get());
1878  }
1879  }
1880  }
1881 
1882  // Get SG-Rules
1884  GetLocalFlowSgList(vm_port, reverse_vm_port);
1885  } else {
1886  GetNonLocalFlowSgList(vm_port);
1887  }
1888 }
1889 
1891  const FlowEntry *rflow) {
1896  return;
1897  }
1898 
1900  return;
1901  }
1902 
1903  MatchAclParams acl;
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  tbb::recursive_mutex::scoped_lock 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  tbb::recursive_mutex::scoped_lock 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  tbb::recursive_mutex::scoped_lock 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  tbb::recursive_mutex::scoped_lock 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  tbb::recursive_mutex::scoped_lock 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:92
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:49
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:1009
void Free(FlowEntry *flow)
Definition: flow_table.cc:1031
@ 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:1638
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:1890
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:1647
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:1037
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:510
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:1016
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:779
FlowEntry(FlowTable *flow_table)
Definition: flow_entry.cc:447
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:1112
void set_acl_assigned_vrf_index()
Definition: flow_entry.cc:1049
const MacAddress & smac() const
Definition: flow_entry.h:646
bool trace() const
Definition: flow_entry.h:752
tbb::atomic< int > refcount_
Definition: flow_entry.h:841
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:1045
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:893
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:1393
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:871
VmInterfaceKey InterfaceIdToKey(Agent *agent, uint32_t id)
Definition: flow_entry.cc:1627
FlowStatsCollector * fsc_
Definition: flow_entry.h:844
static tbb::atomic< int > alloc_count_
Definition: flow_entry.h:820
boost::uuids::uuid egress_uuid_
Definition: flow_entry.h:825
void GetPolicy(const VnEntry *vn, const FlowEntry *rflow)
Definition: flow_entry.cc:1733
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:1310
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:1448
static AgentRoute * GetL2Route(const VrfEntry *entry, const MacAddress &mac)
Definition: flow_entry.cc:982
void ResetPolicy()
Definition: flow_entry.cc:1664
bool SetQosConfigIndex()
Definition: flow_entry.cc:2701
void GetVrfAssignAcl()
Definition: flow_entry.cc:1793
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:514
uint32_t acl_assigned_vrf_index() const
Definition: flow_entry.cc:1073
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:465
void UpdateFipStatsInfo(uint32_t fip, uint32_t id, Agent *agent)
Definition: flow_entry.cc:1032
@ 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:1224
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:989
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:531
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:1335
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:1231
virtual ~FlowEntry()
Definition: flow_entry.cc:459
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:1477
static AgentRoute * GetEvpnRoute(const VrfEntry *entry, const MacAddress &mac, const IpAddress &addr, uint32_t ethernet_tag)
Definition: flow_entry.cc:1005
void Reset(const FlowKey &k)
Definition: flow_entry.cc:505
const VrfEntry * GetDestinationVrf() const
Definition: flow_entry.cc:2688
void RpfInit(const AgentRoute *rt, const IpAddress &sip)
Definition: flow_entry.cc:1249
std::string peer_vrouter_
Definition: flow_entry.h:830
void GetSgList(const Interface *intf)
Definition: flow_entry.cc:1836
void GetDestRouteInfo(const AgentRoute *rt)
Definition: flow_entry.cc:1558
VmInterfaceKey reverse_flow_vmi() const
Definition: flow_entry.cc:1024
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:685
void GetPolicyInfo()
Definition: flow_entry.cc:1721
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:1357
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:1421
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:1077
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:1489
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:611
@ 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:112
PortTableManager * port_table_manager()
Definition: flow_proto.h:126
bool FindFlowExportInfo(const FlowEntry *fe, FlowEntryTree::iterator &it)
uint32_t hash_id() const
Agent * agent() const
Definition: flow_table.h:197
static void GetFlowSandeshActionParams(const FlowAction &action_info, std::string &action_str)
Definition: flow_table.cc:952
void DelLinkLocalFlowInfo(int fd)
Definition: flow_table.cc:774
uint16_t table_index() const
Definition: flow_table.h:198
FlowEntryFreeList * free_list()
Definition: flow_table.h:239
int flow_task_id() const
Definition: flow_table.h:252
boost::uuids::uuid rand_gen()
Definition: flow_table.cc:514
FlowEntryMap flow_entry_map_
Definition: flow_table.h:297
void AddLinkLocalFlowInfo(int fd, uint32_t index, const FlowKey &key, const uint64_t timestamp)
Definition: flow_table.cc:761
bool ConcurrencyCheck(int task_id, bool check_task_instance)
Definition: flow_table.cc:95
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:323
@ VM_INTERFACE
Definition: interface.h:35
@ PHYSICAL
Definition: interface.h:29
const NextHop * flow_key_nh() const
Definition: interface.h:137
const std::string & name() const
Definition: interface.h:114
const AgentQosConfig * qos_config() const
Definition: interface.h:140
static const uint32_t kInvalidIndex
Definition: interface.h:70
const boost::uuids::uuid & GetUuid() const
Definition: interface.h:113
Type type() const
Definition: interface.h:112
const uint32_t id() const
Definition: interface.h:123
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::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
tbb::recursive_mutex mutex_
Definition: flow_entry.h:1099
void UpdatePortConfig(const PortConfig *port_config)
Definition: flow_entry.cc:4101
tbb::recursive_mutex & mutex()
Definition: flow_entry.h:1043
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
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:178
int GetTaskId(const std::string &name)
Definition: task.cc:856
static TaskScheduler * GetInstance()
Definition: task.cc:547
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:222
bool Cancel()
Definition: timer.cc:150
bool Start(int time, Handler handler, ErrorHandler error_handler=NULL)
Definition: timer.cc:108
Definition: trace.h:286
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:32
void update_flow_count(int val) const
Definition: vm.cc:69
const string & GetCfgName() const
Definition: vm.h:43
void operator=(const VmFlowRef &rhs)
Definition: flow_entry.cc:140
bool AllocateFd(Agent *agent, uint8_t l3_proto)
Definition: flow_entry.cc:218
void SetVm(const VmEntry *vm)
Definition: flow_entry.cc:200
void Reset(bool reset_flow)
Definition: flow_entry.cc:167
void FreeFd()
Definition: flow_entry.cc:185
VmEntryConstRef vm_
Definition: flow_entry.h:119
void FreeRef()
Definition: flow_entry.cc:175
uint16_t port_
Definition: flow_entry.h:121
void Init(FlowEntry *flow)
Definition: flow_entry.cc:136
void Move(VmFlowRef *rhs)
Definition: flow_entry.cc:152
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:86
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:88
const uint32_t vrf_id() const
Definition: vrf.h:99
AgentRouteTable * GetEvpnRouteTable() const
Definition: vrf.cc:330
const VrfEntry * GetVrf() const
Definition: nexthop.h:1444
Definition: vrf.h:268
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:570
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:593
static std::size_t HashIp(std::size_t hash, const IpAddress &ip)
Definition: flow_entry.cc:598
void intrusive_ptr_add_ref(FlowEntry *fe)
Definition: flow_entry.cc:566
static std::vector< std::string > MakeList(const VnListType &ilist)
Definition: flow_entry.cc:330
static void SetRpfFieldsInternal(FlowEntry *flow, const AgentRoute *rt)
Definition: flow_entry.cc:1186
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:33
map< int, int > FlowRouteRefMap
Definition: pkt_flow_info.h:16
#define BGP_SERVICE_TTL_REV_FLOW
Definition: pkt_handler.h:46
#define BGP_SERVICE_TTL_FWD_FLOW
Definition: pkt_handler.h:47
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:183
uint32_t ifindex
Definition: pkt_handler.h:180
uint8_t cmd_param_5
Definition: pkt_handler.h:188
@ ADD_DEL_CHANGE
Definition: agent_db.h:98
Definition: acl.h:35
VrfTranslateActionSpec vrf_translate_action_
Definition: acl.h:48
void Clear()
Definition: acl.h:40
std::vector< MirrorActionSpec > mirror_l
Definition: acl.h:47
uint32_t action
Definition: acl.h:44
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:347
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:278
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:351
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:339
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:343
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:30
std::string uuid
Definition: acl.h:25
bool other
Definition: acl.h:28
bool terminal
Definition: acl.h:27
std::string src_match_vn
Definition: acl.h:29
bool drop
Definition: acl.h:26
std::string acl_name
Definition: acl.h:31
AclDBEntryConstRef acl
Definition: acl.h:54
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:365
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:393
uint32_t vrf
Definition: pkt_handler.h:391
IpAddress ip_daddr
Definition: pkt_handler.h:395
IpAddress ip_saddr
Definition: pkt_handler.h:394
TunnelInfo tunnel
Definition: pkt_handler.h:407
MacAddress smac
Definition: pkt_handler.h:392
const AgentHdr & GetAgentHdr() const
AgentHdr agent_hdr
Definition: pkt_handler.h:388
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:409
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:404
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:417
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:200
Definition: vrf.h:22
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