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  const VmInterface *vm_port = NULL;
1904  if (intf != NULL) {
1905  if (intf->type() == Interface::VM_INTERFACE) {
1906  vm_port = static_cast<const VmInterface *>(intf);
1907  }
1908  }
1909 
1910  if (vm_port != NULL) {
1911  MatchAclParams acl;
1912  FirewallPolicyList::const_iterator it =
1913  vm_port->fw_policy_list().begin();
1914  for(; it != vm_port->fw_policy_list().end(); it++) {
1915  acl.acl = *it;
1916  data_.match_p.aps_policy.m_acl_l.push_back(acl);
1920  }
1921 
1922  // Get the ACL for FWAAS
1923  it = vm_port->fwaas_fw_policy_list().begin();
1924  for(; it != vm_port->fwaas_fw_policy_list().end(); it++) {
1925  acl.acl = *it;
1926  data_.match_p.fwaas_policy.m_acl_l.push_back(acl);
1930  }
1931  }
1932 
1933  // For local flows, we have to apply NW Policy from out-vn also
1934  if (!is_flags_set(FlowEntry::LocalFlow) || rflow == NULL) {
1935  // Not local flow
1936  return;
1937  }
1938 
1939  const Interface *r_intf = rflow->data_.intf_entry.get();
1940  if (r_intf == NULL) {
1941  return;
1942  }
1943 
1944  vm_port = dynamic_cast<const VmInterface *>(r_intf);
1945  if (vm_port != NULL) {
1946  MatchAclParams acl;
1947  FirewallPolicyList::const_iterator it =
1948  vm_port->fw_policy_list().begin();
1949  for(; it != vm_port->fw_policy_list().end(); it++) {
1950  acl.acl = *it;
1951  data_.match_p.aps_policy.m_out_acl_l.push_back(acl);
1953  data_.match_p.aps_policy.m_reverse_acl_l.push_back(acl);
1955  }
1956 
1957  // Get the ACL for FWAAS
1958  it = vm_port->fwaas_fw_policy_list().begin();
1959  for(; it != vm_port->fwaas_fw_policy_list().end(); it++) {
1960  acl.acl = *it;
1961  data_.match_p.fwaas_policy.m_out_acl_l.push_back(acl);
1963  data_.match_p.fwaas_policy.m_reverse_acl_l.push_back(acl);
1965  }
1966  }
1967 }
1968 
1969 // Ingress-ACL/Egress-ACL in interface with VM as reference point.
1970 // Ingress : Packet to VM
1971 // Egress : Packet from VM
1972 // The direction stored in flow is defined with vrouter as reference point
1973 // Ingress : Packet to Vrouter from VM
1974 // Egress : Packet from Vrouter to VM
1975 //
1976 // Function takes care of copying right rules
1977 static bool CopySgEntries(const VmInterface *vm_port, bool ingress_acl,
1978  std::list<MatchAclParams> &list) {
1979  /* If policy is NOT enabled on VMI, do not copy SG rules */
1980  if (!vm_port->policy_enabled()) {
1981  return false;
1982  }
1983  bool ret = false;
1984  for (VmInterface::SecurityGroupEntrySet::const_iterator it =
1985  vm_port->sg_list().list_.begin();
1986  it != vm_port->sg_list().list_.end(); ++it) {
1987  if (it->sg_ == NULL)
1988  continue;
1989 
1990  if (it->sg_->IsAclSet()) {
1991  ret = true;
1992  }
1993  MatchAclParams acl;
1994  // As per definition above,
1995  // get EgressACL if flow direction is Ingress
1996  // get IngressACL if flow direction is Egress
1997  if (ingress_acl) {
1998  acl.acl = it->sg_->GetEgressAcl();
1999  } else {
2000  acl.acl = it->sg_->GetIngressAcl();
2001  }
2002  if (acl.acl)
2003  list.push_back(acl);
2004  }
2005 
2006  return ret;
2007 }
2008 
2010  const VmInterface *reverse_vm_port) {
2011  // Get SG-Rule for the forward flow
2012  if (vm_port) {
2014  CopySgEntries(vm_port, true, data_.match_p.sg_policy.m_acl_l);
2015  }
2016  // For local flow, we need to simulate SG lookup at both ends.
2017  // Assume packet is from VM-A to VM-B.
2018  // If we apply Ingress-ACL from VM-A, then apply Egress-ACL from VM-B
2019  // If we apply Egress-ACL from VM-A, then apply Ingress-ACL from VM-B
2020  if (reverse_vm_port) {
2022  CopySgEntries(reverse_vm_port, false, data_.match_p.sg_policy.m_out_acl_l);
2023  }
2025  return;
2026  }
2027  // TCP ACK workaround:
2028  // Ideally TCP State machine should be run to age TCP flows
2029  // Temporary workaound in place of state machine. For TCP ACK packets allow
2030  // the flow if either forward or reverse flow is allowed
2031 
2032  // Copy the SG rules to be applied for reverse flow
2033  if (vm_port) {
2035  CopySgEntries(vm_port, false,
2037  }
2038 
2039  if (reverse_vm_port) {
2041  CopySgEntries(reverse_vm_port, true,
2043  }
2044 }
2045 
2047  // Get SG-Rule for the forward flow
2048  bool ingress = is_flags_set(FlowEntry::IngressDir);
2049  if (vm_port) {
2051  CopySgEntries(vm_port, ingress,
2053  }
2054 
2056 
2058  return;
2059  }
2060 
2061  // TCP ACK workaround:
2062  // Ideally TCP State machine should be run to age TCP flows
2063  // Temporary workaound in place of state machine. For TCP ACK packets allow
2064  // the flow if either forward or reverse flow is allowed
2065 
2066  // Copy the SG rules to be applied for reverse flow
2067  if (vm_port) {
2069  CopySgEntries(vm_port, !ingress,
2071  }
2073 }
2074 
2075 // For an L2-Flow, refresh the vn-list and sg-list from the route used for
2076 // flow
2078  // Skip L3-Flows
2079  if (l3_flow())
2080  return;
2081 
2082  Agent *agent = flow_table()->agent();
2083  // Get VRF for the flow. L2 flow have same in and out-vrf. So, use same
2084  // vrf for both smac and dmac lookup
2085  uint32_t vrf_id = data().flow_source_vrf;
2086  const VrfEntry *vrf = agent->vrf_table()->FindVrfFromId(vrf_id);
2087  if (vrf == NULL || vrf->IsDeleted()) {
2088  return;
2089  }
2090  BridgeAgentRouteTable *table =
2091  static_cast<BridgeAgentRouteTable *>(vrf->GetBridgeRouteTable());
2092 
2093  // Get route-info for smac
2095  // Get route-info for dmac
2096  GetDestRouteInfo(table->FindRoute(data().dmac));
2097 }
2098 
2100 // Flow policy processing routines
2102 
2103 // Set HBS information
2104 // |-------------------------------------------------------------------------|
2105 // | Source | Destination: VMI | Destination: Fabric|
2106 // |--------------------------------------------------------------------------
2107 // | VMI | L (src vif index < dst vif index) | L |
2108 // | | else R | |
2109 // |--------------------------------------------------------------------------
2110 // | Fabric | R | - |
2111 // |-------------------------------------------------------------------------|
2112 //
2114 
2118  return;
2119  }
2120 
2121  const VmInterface *src_intf =
2122  dynamic_cast<const VmInterface *>(intf_entry());
2123  FlowEntry *rev_flow = reverse_flow_entry();
2124  const VmInterface *dst_intf =
2125  dynamic_cast<const VmInterface *>(rev_flow->intf_entry());
2126 
2127  if ( src_intf == NULL || dst_intf == NULL ) {
2130  return;
2131  }
2132 
2133  //Enable HBF flow flag
2134  set_flags(HbfFlow);
2135  if (is_flags_set(LocalFlow)) {
2136  /* Handle Service Chain Traffic for local flow VM <--> SI*/
2137  /* Case 1: Reset the HBS Action if flow source is service interface */
2138  if (!src_intf->service_intf_type().empty()) {
2141  return;
2142  }
2143  /* Case 2: Set appropriate interface left/right based on service interface type */
2144  if (!dst_intf->service_intf_type().empty()) {
2145  if (dst_intf->service_intf_type() == "left") {
2147  } else if (dst_intf->service_intf_type() == "right") {
2149  }
2150  return;
2151  }
2152  // VM <--> VM on same compute
2153  (src_intf->id() < dst_intf->id()) ?
2156  } else {
2157  /* Handle Service chain traffic entering the compute */
2158  if ((!src_intf->service_intf_type().empty() ||
2159  !dst_intf->service_intf_type().empty())) {
2160  if (is_flags_set(IngressDir) == 0) {
2161  if (dst_intf->service_intf_type() == "left") {
2163  } else if (dst_intf->service_intf_type() == "right") {
2165  }
2166  } else {
2169  }
2170  } else {
2171  // VM <--> VM on different compute
2175  }
2176  }
2177 }
2178 
2181  (1 << TrafficAction::VRF_TRANSLATE))) {
2182  //If VRF assign was evaluated and the vrf translate
2183  //action is not present in latest evaluation mark the
2184  //flow as short flow
2187  != Agent::NullString()) {
2189  }
2190  data_.vrf_assign_evaluated = true;
2192  return;
2193  }
2194 
2195  std::string vrf_assigned_name =
2197  std::list<MatchAclParams>::const_iterator acl_it;
2198  for (acl_it = match_p().m_vrf_assign_acl_l.begin();
2199  acl_it != match_p().m_vrf_assign_acl_l.end();
2200  ++acl_it) {
2201  std::string vrf = acl_it->action_info.vrf_translate_action_.vrf_name();
2203  //Check if VRF assign acl says, network ACL and SG action
2204  //to be ignored
2205  bool ignore_acl =
2206  acl_it->action_info.vrf_translate_action_.ignore_acl();
2208  (ignore_acl);
2209  }
2210  if (data_.vrf_assign_evaluated && vrf_assigned_name !=
2213  }
2214 
2218  }
2219  data_.vrf_assign_evaluated = true;
2220 }
2221 
2222 uint32_t FlowEntry::MatchAcl(const PacketHeader &hdr,
2223  std::list<MatchAclParams> &acl,
2224  bool add_implicit_deny, bool add_implicit_allow,
2225  FlowPolicyInfo *info) {
2226  PktHandler *pkt_handler = Agent::GetInstance()->pkt()->pkt_handler();
2227 
2228  // If there are no ACL to match, make it pass
2229  if (acl.size() == 0 && add_implicit_allow) {
2230  if (info) {
2231  /* We are setting UUIDs for linklocal and multicast flows here,
2232  * because even if we move this to the place where acl association
2233  * is being skipped, we still need checks for linklocal and
2234  * multicast flows here to avoid its value being overwritten with
2235  * IMPLICIT_ALLOW
2236  */
2239  } else if (is_flags_set(FlowEntry::Multicast)) {
2243  } else {
2244  /* We need to make sure that info is not already populated
2245  * before setting it to IMPLICIT_ALLOW. This is required
2246  * because info could earlier be set by previous call to
2247  * MatchAcl. We should note here that same 'info' var is passed
2248  * for MatchAcl calls with in_acl and out_acl
2249  */
2250  if (!info->terminal && !info->other) {
2252  }
2253  }
2254  }
2255  return (1 << TrafficAction::PASS);
2256  }
2257 
2258  // PASS default GW traffic, if it is ICMP or DNS
2259  if ((hdr.protocol == IPPROTO_ICMP ||
2260  (hdr.protocol == IPPROTO_UDP &&
2261  (hdr.src_port == DNS_SERVER_PORT ||
2262  hdr.dst_port == DNS_SERVER_PORT))) &&
2263  (pkt_handler->IsGwPacket(data_.intf_entry.get(), hdr.dst_ip) ||
2264  pkt_handler->IsGwPacket(data_.intf_entry.get(), hdr.src_ip))) {
2265  if (info) {
2267  }
2268  return (1 << TrafficAction::PASS);
2269  }
2270 
2271  uint32_t action = 0;
2272  for (std::list<MatchAclParams>::iterator it = acl.begin();
2273  it != acl.end(); ++it) {
2274  if (it->acl.get() == NULL) {
2275  continue;
2276  }
2277 
2278  if (it->acl->PacketMatch(hdr, *it, info)) {
2279  action |= it->action_info.action;
2280  if (it->action_info.action & (1 << TrafficAction::MIRROR)) {
2283  it->action_info.mirror_l.begin(),
2284  it->action_info.mirror_l.end());
2285  }
2286 
2287  if (it->terminal_rule) {
2288  break;
2289  }
2290  }
2291  }
2292 
2293  // If no acl matched, make it imlicit deny
2294  if (action == 0 && add_implicit_deny) {
2295  action = (1 << TrafficAction::DENY) |
2297  if (info) {
2299  info->drop = true;
2300  }
2301  }
2302 
2303  return action;
2304 }
2305 
2307  hdr->vrf = data_.vrf;
2308  hdr->src_ip = key_.src_addr;
2309  hdr->dst_ip = key_.dst_addr;
2310  hdr->protocol = key_.protocol;
2311  if (hdr->protocol == IPPROTO_UDP || hdr->protocol == IPPROTO_TCP) {
2312  hdr->src_port = key_.src_port;
2313  hdr->dst_port = key_.dst_port;
2314  } else {
2315  hdr->src_port = 0;
2316  hdr->dst_port = 0;
2317  }
2319  hdr->dst_policy_id = &(data_.dest_vn_list);
2320  hdr->src_sg_id_l = &(data_.source_sg_id_l);
2321  hdr->dst_sg_id_l = &(data_.dest_sg_id_l);
2323  hdr->dst_tags_ = data_.dest_tag_id_l;
2324  hdr->family = key_.family;
2325 }
2326 
2327 // In case of NAT flows, the key fields can change.
2329  FlowEntry *rflow = reverse_flow_entry();
2330  if (rflow == NULL)
2331  return;
2332 
2333  hdr->vrf = rflow->data().vrf;
2334  hdr->src_ip = rflow->key().dst_addr;
2335  hdr->dst_ip = rflow->key().src_addr;
2336  hdr->protocol = rflow->key().protocol;
2337  if (hdr->protocol == IPPROTO_UDP || hdr->protocol == IPPROTO_TCP) {
2338  hdr->src_port = rflow->key().dst_port;
2339  hdr->dst_port = rflow->key().src_port;
2340  } else {
2341  hdr->src_port = 0;
2342  hdr->dst_port = 0;
2343  }
2344  hdr->src_policy_id = &(rflow->data().dest_vn_list);
2345  hdr->dst_policy_id = &(rflow->data().source_vn_list);
2346  hdr->src_sg_id_l = &(rflow->data().dest_sg_id_l);
2347  hdr->dst_sg_id_l = &(rflow->data().source_sg_id_l);
2348  hdr->src_tags_ = rflow->data_.dest_tag_id_l;
2349  hdr->dst_tags_ = rflow->data_.source_tag_id_l;
2350  hdr->family = key_.family;
2351 }
2352 
2354  const FlowPolicyInfo &fwd_flow_info,
2355  const FlowPolicyInfo &rev_flow_info,
2356  bool tcp_rev, bool is_sg) {
2357 
2358  FlowEntry *rflow = reverse_flow_entry();
2359  if (rflow == NULL) {
2360  return;
2361  }
2362 
2363  sp->rule_uuid_ = fwd_flow_info.uuid;
2364  sp->acl_name_ = fwd_flow_info.acl_name;
2365 
2366  rsp->rule_uuid_ = rev_flow_info.uuid;
2367  rsp->acl_name_ = rev_flow_info.acl_name;
2368 
2369  //If Forward flow SG rule says drop, copy corresponding
2370  //ACE id to both forward and reverse flow
2371  if (fwd_flow_info.drop) {
2372  rsp->rule_uuid_ = fwd_flow_info.uuid;
2373  rsp->acl_name_ = fwd_flow_info.acl_name;
2374  return;
2375  }
2376 
2377  //If reverse flow SG rule says drop, copy corresponding
2378  //ACE id to both forward and reverse flow
2379  if (rev_flow_info.drop) {
2380  sp->rule_uuid_ = rev_flow_info.uuid;
2381  sp->acl_name_ = rev_flow_info.acl_name;
2382  return;
2383  }
2384 
2385  if (tcp_rev == false) {
2386  if (is_sg) {
2387  if (data_.match_p.sg_policy.rule_present == false) {
2388  sp->rule_uuid_ = rev_flow_info.uuid;
2389  sp->acl_name_ = rev_flow_info.acl_name;
2390  }
2391 
2392  if (data_.match_p.sg_policy.out_rule_present == false) {
2393  rsp->rule_uuid_ = fwd_flow_info.uuid;
2394  rsp->acl_name_ = fwd_flow_info.acl_name;
2395  }
2396  } else {
2397  if (data_.match_p.aps_policy.rule_present == false) {
2398  sp->rule_uuid_ = rev_flow_info.uuid;
2399  sp->acl_name_ = rev_flow_info.acl_name;
2400  }
2401 
2402  if (data_.match_p.aps_policy.out_rule_present == false) {
2403  rsp->rule_uuid_ = fwd_flow_info.uuid;
2404  rsp->acl_name_ = fwd_flow_info.acl_name;
2405  }
2406  }
2407  }
2408 
2409  if (tcp_rev == true) {
2410  if (sp->reverse_rule_present == false) {
2411  rsp->rule_uuid_ = fwd_flow_info.uuid;
2412  rsp->acl_name_ = fwd_flow_info.acl_name;
2413  }
2414 
2415  if (sp->reverse_out_rule_present == false) {
2416  sp->rule_uuid_ = rev_flow_info.uuid;
2417  sp->acl_name_ = rev_flow_info.acl_name;
2418  }
2419  }
2420 }
2421 
2423  bool is_sg) {
2424 
2425  FlowEntry *rflow = reverse_flow_entry();
2426  const string value = FlowPolicyStateStr.at(NOT_EVALUATED);
2427  FlowPolicyInfo acl_info(value);
2428  FlowPolicyInfo out_acl_info(value);
2429  FlowPolicyInfo rev_acl_info(value);
2430  FlowPolicyInfo rev_out_acl_info(value);
2431 
2433  sp->acl_name_ = "";
2434 
2435  if (rsp) {
2436  rsp->rule_uuid_ =
2438  rsp->acl_name_ = "";
2439  }
2440 
2441  PacketHeader hdr;
2442  SetPacketHeader(&hdr);
2443 
2444  //Apply ACL configured on ingress interface
2445  sp->action = MatchAcl(hdr, sp->m_acl_l, true, !sp->rule_present, &acl_info);
2446 
2447  //Apply ACL configured on egress interface
2448  PacketHeader out_hdr;
2449  if (ShouldDrop(sp->action) == false && rflow) {
2450  // Key fields for lookup in out-acl can potentially change in case
2451  // of NAT. Form ACL lookup based on post-NAT fields
2452  SetOutPacketHeader(&out_hdr);
2453  sp->out_action = MatchAcl(out_hdr, sp->m_out_acl_l, true,
2454  !sp->out_rule_present, &out_acl_info);
2455  }
2456 
2457  // For TCP-ACK packet, we allow packet if either forward or reverse
2458  // flow says allow. So, continue matching reverse flow even if forward
2459  // flow says drop
2460  if (is_flags_set(FlowEntry::TcpAckFlow) && rflow) {
2461  rflow->SetPacketHeader(&hdr);
2462  sp->reverse_action = MatchAcl(hdr, sp->m_reverse_acl_l, true,
2463  !sp->reverse_rule_present, &rev_acl_info);
2464 
2465  if (ShouldDrop(sp->reverse_action) == false) {
2466  // Key fields for lookup in out-acl can potentially change in
2467  // case of NAT. Form ACL lookup based on post-NAT fields
2468  rflow->SetOutPacketHeader(&out_hdr);
2469  sp->reverse_out_action = MatchAcl(out_hdr, sp->m_reverse_out_acl_l,
2470  true, !sp->reverse_out_rule_present,
2471  &rev_out_acl_info);
2472  }
2473  }
2474 
2475  // Compute summary SG action.
2476  // For Non-TCP-ACK Flows
2477  // DROP if any of policy.action, out_action, policy.reverse_action or
2478  // policy.reverse_out_action says DROP
2479  // Only acl_info which is derived from sp->m_acl_l
2480  // and sp->m_out_acl_l will be populated. Pick the
2481  // UUID specified by acl_info for flow's SG rule UUID
2482  // For TCP-ACK flows
2483  // ALLOW if either ((policy.action && out_action) ||
2484  // (policy.reverse_action & policy.reverse_out_action))
2485  // ALLOW
2486  // For flow's SG rule UUID use the following rules
2487  // --If both acl_info and rev_acl_info has drop set, pick the
2488  // UUID from acl_info.
2489  // --If either of acl_info or rev_acl_info does not have drop
2490  // set, pick the UUID from the one which does not have drop set.
2491  // --If both of them does not have drop set, pick it up from
2492  // acl_info
2493  //
2495  sp->action_summary =
2496  sp->action | sp->out_action | sp->reverse_action | sp->reverse_out_action;
2497  SetAclInfo(sp, rsp, acl_info, out_acl_info, false, is_sg);
2498  } else if (ShouldDrop(sp->action | sp->out_action) &&
2500  //If both ingress ACL and egress ACL of VMI denies the
2501  //packet, then pick ingress ACE uuid to send to UVE
2502  sp->action_summary = (1 << TrafficAction::DENY);
2503  SetAclInfo(sp, rsp, acl_info, out_acl_info, false, is_sg);
2504  } else {
2505  sp->action_summary = (1 << TrafficAction::PASS);
2506  if (sp->action & (1 << TrafficAction::HBS) ||
2507  sp->out_action & (1 << TrafficAction::HBS) ||
2508  sp->reverse_action & (1 << TrafficAction::HBS) ||
2509  sp->reverse_out_action & (1 << TrafficAction::HBS)) {
2510  sp->action_summary|=(1 << TrafficAction::HBS);
2511  }
2512  if (!ShouldDrop(sp->action | sp->out_action)) {
2513  SetAclInfo(sp, rsp, acl_info, out_acl_info, false, is_sg);
2514  } else if (!ShouldDrop(sp->reverse_action | sp->reverse_out_action)) {
2515  SetAclInfo(sp, rsp, rev_out_acl_info, rev_acl_info, true, is_sg);
2516  }
2517  }
2518 }
2519 
2520 // Apply Policy and SG rules for a flow.
2521 //
2522 // Special case of local flows:
2523 // For local-flows, both VM are on same compute and we need to apply SG from
2524 // both the ports. sg_policy.m_acl_l will contain ACL for port in forward flow and
2525 // sg_policy.m_out_acl_l will have ACL from other port
2526 //
2527 // If forward flow goes thru NAT, the key for matching ACL in
2528 // sg_policy.m_out_acl_l can potentially change. The routine SetOutPacketHeader
2529 // takes care of forming header after NAT
2530 //
2531 // Rules applied are based on flow type
2532 // Non-Local Forward Flow
2533 // Network Policy.
2534 // Out-Network Policy will be empty
2535 // SG
2536 // Out-SG will be empty
2537 // Non-Local Reverse Flow
2538 // Network Policy.
2539 // Out-Network Policy will be empty
2540 // SG and out-SG from forward flow
2541 // Local Forward Flow
2542 // Network Policy.
2543 // Out-Network Policy
2544 // SG
2545 // Out-SG
2546 // Local Reverse Flow
2547 // Network Policy.
2548 // Out-Network Policy
2549 // SG and out-SG from forward flow
2552  return true;
2553  }
2559 
2563 
2564  const string value = FlowPolicyStateStr.at(NOT_EVALUATED);
2565  FlowPolicyInfo nw_acl_info(value);
2566 
2567  FlowEntry *rflow = reverse_flow_entry();
2568  PacketHeader hdr;
2569  SetPacketHeader(&hdr);
2570 
2571  //Calculate VRF assign entry, and ignore acl is set
2572  //skip network and SG acl action is set
2574  {
2576  }
2577  else
2578  {
2582  }
2583 
2584  // Mirror is valid even if packet is to be dropped. So, apply it first
2586  false, true, NULL);
2587 
2588  // Apply out-policy. Valid only for local-flow
2590  data_.match_p.m_out_mirror_acl_l, false, true, NULL);
2591 
2592  // Apply network policy
2595  true, &nw_acl_info);
2597  goto done;
2599  true, true, &nw_acl_info);
2601  goto done;
2602  }
2603  else {
2604  if (rflow) {
2605  uint32_t r_policy_action = MatchAcl(hdr,
2606  rflow->data_.match_p.m_acl_l, true, true, &nw_acl_info);
2607  if (ShouldDrop(r_policy_action)) {
2609  goto done;
2610  }
2611  uint32_t r_out_policy_action = MatchAcl(hdr,
2612  rflow->data_.match_p.m_out_acl_l, true, true, &nw_acl_info);
2613  if (ShouldDrop(r_out_policy_action)) {
2615  goto done;
2616  }
2617  }
2618  }
2619 
2620  // Apply sg policy
2622  SessionPolicy *r_sg_policy = NULL;
2623  SessionPolicy *r_aps_policy = NULL;
2624  SessionPolicy *r_fwaas_policy = NULL;
2625 
2626  if (rflow) {
2627  r_sg_policy = &(rflow->data_.match_p.sg_policy);
2628  r_aps_policy = &(rflow->data_.match_p.aps_policy);
2629  r_fwaas_policy = &(rflow->data_.match_p.fwaas_policy);
2630  }
2631 
2632  SessionMatch(&data_.match_p.sg_policy, r_sg_policy, true);
2634  goto done;
2635  }
2636 
2637  SessionMatch(&data_.match_p.fwaas_policy, r_fwaas_policy, false);
2639  goto done;
2640  }
2641 
2642  SessionMatch(&data_.match_p.aps_policy, r_aps_policy, false);
2643  } else {
2644  // SG is reflexive ACL. For reverse-flow, copy SG action from
2645  // forward flow
2647  }
2648 
2649 done:
2650  nw_ace_uuid_ = nw_acl_info.uuid;
2651  if (!nw_acl_info.src_match_vn.empty())
2652  data_.source_vn_match = nw_acl_info.src_match_vn;
2653  if (!nw_acl_info.dst_match_vn.empty())
2654  data_.dest_vn_match = nw_acl_info.dst_match_vn;
2655  // Set mirror vrf after evaluation of actions
2657  //Set VRF assign action
2659  //Set HBS information
2661  // Summarize the actions based on lookups above
2662  ActionRecompute();
2663  return true;
2664 }
2665 
2667 // Flow policy action compute routines
2670  DoPolicy();
2671 
2672  // If this is forward flow, update the SG action for reflexive entry
2673  FlowEntry *rflow = (is_flags_set(FlowEntry::ReverseFlow) == false) ?
2674  reverse_flow_entry() : NULL;
2675  // Dont update reflexive entry for TcpAck Flows. Since it can flip
2676  // Deny state for the reflexive entry.
2677  if (!(is_flags_set(FlowEntry::TcpAckFlow)) && rflow) {
2678  // Update action for reverse flow
2679  rflow->UpdateReflexiveAction();
2680  //Set HBS information
2681  rflow->SetHbsInfofromAction();
2682  rflow->ActionRecompute();
2683  }
2684 }
2685 
2686 const VrfEntry*
2688  const VrfEntry *vrf = NULL;
2689  VrfTable *vrf_table = flow_table()->agent()->vrf_table();
2690 
2692  match_p().action_info.action & (1 << TrafficAction::VRF_TRANSLATE)) {
2693  vrf = vrf_table->FindVrfFromId(data().dest_vrf);
2694  } else {
2695  vrf = vrf_table->FindVrfFromId(data().vrf);
2696  }
2697  return vrf;
2698 }
2699 
2702  MatchAclParamsList::const_iterator it;
2703 
2704  // For reverse flows, first check if we have our own QoS config
2705  // (from interface), and only fall back to forward flow if not
2707  // First, check if reverse flow has its own QoS config from interface
2708  const VmInterface *intf =
2709  dynamic_cast<const VmInterface*>(data_.intf_entry.get());
2710  if (intf && intf->qos_config()) {
2711  i = intf->qos_config()->id();
2712  }
2713 
2714  // If still no QoS config, copy from forward flow
2716  FlowEntry *fwd_flow = reverse_flow_entry();
2717  if (fwd_flow) {
2718  i = fwd_flow->data().qos_config_idx;
2719  }
2720  }
2721 
2722  // If we got a valid QoS config, use it and return early
2724  if (i != data_.qos_config_idx) {
2725  data_.qos_config_idx = i;
2726  return true;
2727  }
2728  return false;
2729  }
2730  // If no QoS config found yet, continue with normal processing
2731  }
2732 
2733  // Priority of QOS config for forward flows (and reverse flows that didn't find config above)
2734  // 1> SG
2735  // 2> Interface
2736  // 3> ACL
2737  // 4> VN (handled through ACLs)
2739  for (it = data_.match_p.sg_policy.m_acl_l.begin();
2740  it != data_.match_p.sg_policy.m_acl_l.end(); it++) {
2741  if (it->action_info.action & 1 << TrafficAction::APPLY_QOS &&
2742  it->action_info.qos_config_action_.id()
2744  i = it->action_info.qos_config_action_.id();
2745  break;
2746  }
2747  }
2749  for (it = data_.match_p.sg_policy.m_out_acl_l.begin();
2750  it != data_.match_p.sg_policy.m_out_acl_l.end(); it++) {
2751  if (it->action_info.action & 1 << TrafficAction::APPLY_QOS &&
2752  it->action_info.qos_config_action_.id() !=
2754  i = it->action_info.qos_config_action_.id();
2755  break;
2756  }
2757  }
2759  for (it = data_.match_p.m_acl_l.begin();
2760  it != data_.match_p.m_acl_l.end(); it++) {
2761  if (it->action_info.action & 1 << TrafficAction::APPLY_QOS &&
2762  it->action_info.qos_config_action_.id() !=
2764  i = it->action_info.qos_config_action_.id();
2765  break;
2766  }
2767  }
2769  for (it = data_.match_p.m_out_acl_l.begin();
2770  it != data_.match_p.m_out_acl_l.end(); it++) {
2771  if (it->action_info.action & 1 << TrafficAction::APPLY_QOS &&
2772  it->action_info.qos_config_action_.id() !=
2774  i = it->action_info.qos_config_action_.id();
2775  break;
2776  }
2777  }
2778  }
2779 
2780  const VmInterface *intf =
2781  dynamic_cast<const VmInterface*>(data_.intf_entry.get());
2782  if (intf && intf->qos_config()) {
2783  if (intf->is_vn_qos_config() == false ||
2785  i = intf->qos_config()->id();
2786  }
2787  }
2788 
2789  if (i != data_.qos_config_idx) {
2790  data_.qos_config_idx = i;
2791  return true;
2792  }
2793 
2794  return false;
2795 }
2796 
2797 // Recompute FlowEntry action based on ACLs already set in the flow
2799  uint32_t action = 0;
2800  uint16_t drop_reason = DROP_UNKNOWN;
2801  bool ret = false;
2802 
2808 
2809  //Only VRF assign acl, can specify action to
2810  //translate VRF. VRF translate action specified
2811  //by egress VN ACL or ingress VN ACL should be ignored
2812  action &= ~(1 << TrafficAction::VRF_TRANSLATE);
2814 
2815  if (action & (1 << TrafficAction::VRF_TRANSLATE) &&
2817  //In case of multi inline service chain, match condition generated on
2818  //each of service instance interface takes higher priority than
2819  //network ACL. Match condition on the interface would have ignore acl
2820  //flag set to avoid applying two ACL for vrf translation
2824 
2825  //Pick mirror action from network ACL
2828  action |= (1 << TrafficAction::MIRROR);
2829  }
2830  }
2831 
2832  action &= ~(1 << TrafficAction::HBS);
2834  action |= (1 << TrafficAction::HBS);
2835  }
2836 
2837  if (SetQosConfigIndex()) {
2838  ret = true;
2839  }
2840 
2841  // check for conflicting actions and remove allowed action
2842  if (ShouldDrop(action)) {
2843  action = (action & ~TrafficAction::DROP_FLAGS &
2844  ~TrafficAction::PASS_FLAGS);
2845  action |= (1 << TrafficAction::DENY);
2847  drop_reason = short_flow_reason_;
2848  } else if (ShouldDrop(data_.match_p.policy_action)) {
2849  drop_reason = DROP_POLICY;
2850  } else if (ShouldDrop(data_.match_p.out_policy_action)) {
2851  drop_reason = DROP_OUT_POLICY;
2852  } else if (ShouldDrop(data_.match_p.sg_policy.action)) {
2853  drop_reason = DROP_SG;
2855  drop_reason = DROP_OUT_SG;
2857  drop_reason = DROP_REVERSE_SG;
2859  drop_reason = DROP_REVERSE_OUT_SG;
2860  } else if (ShouldDrop(data_.match_p.aps_policy.action)) {
2861  drop_reason = DROP_FIREWALL_POLICY;
2863  drop_reason = DROP_OUT_FIREWALL_POLICY;
2865  drop_reason = DROP_REVERSE_FIREWALL_POLICY;
2867  drop_reason = DROP_REVERSE_OUT_FIREWALL_POLICY;
2868  } else if (ShouldDrop(data_.match_p.fwaas_policy.action)) {
2869  drop_reason = DROP_FWAAS_POLICY;
2871  drop_reason = DROP_FWAAS_OUT_POLICY;
2873  drop_reason = DROP_FWAAS_REVERSE_POLICY;
2875  drop_reason = DROP_FWAAS_REVERSE_OUT_POLICY;
2876  } else {
2877  drop_reason = DROP_UNKNOWN;
2878  }
2879  }
2880 
2881  if (action & (1 << TrafficAction::TRAP)) {
2882  action = (1 << TrafficAction::TRAP);
2883  }
2884 
2885  if (action != data_.match_p.action_info.action) {
2886  data_.match_p.action_info.action = action;
2887  ret = true;
2888  }
2889  if (drop_reason != data_.drop_reason) {
2890  data_.drop_reason = drop_reason;
2891  ret = true;
2892  }
2893  return ret;
2894 }
2895 
2896 // SetMirrorVrfFromAction
2897 // For this flow check for mirror action from dynamic ACLs or policy mirroring
2898 // assign the vrf from its Virtual Nework that ACL is used
2899 // If it is a local flow and out mirror action or policy is set
2900 // assign the vrf of the reverse flow, since ACL came from the reverse flow
2904  const VnEntry *vn = vn_entry();
2905  if (vn && vn->GetVrf()) {
2906  SetMirrorVrf(vn->GetVrf()->vrf_id());
2907  }
2908  }
2911  FlowEntry *rflow = reverse_flow_entry_.get();
2912  if (rflow) {
2913  const VnEntry *rvn = rflow->vn_entry();
2914  if (rvn && rvn->GetVrf()) {
2915  SetMirrorVrf(rvn->GetVrf()->vrf_id());
2916  }
2917  }
2918  }
2919 }
2920 
2924  short_flow_reason_ = reason;
2925  }
2926  if (reverse_flow_entry_ &&
2927  !reverse_flow_entry_->is_flags_set(FlowEntry::ShortFlow)) {
2929  reverse_flow_entry_->short_flow_reason_ = reason;
2930  }
2931 }
2932 
2934  FlowEntry *rflow = reverse_flow_entry_.get();
2935  SessionPolicy *r_sg_policy = NULL;
2936  SessionPolicy *r_aps_policy = NULL;
2937  SessionPolicy *r_fwaas_policy = NULL;
2938 
2939  if (rflow) {
2940  r_sg_policy = &(rflow->data_.match_p.sg_policy);
2941  r_aps_policy = &(rflow->data_.match_p.aps_policy);
2942  r_fwaas_policy = &(rflow->data_.match_p.fwaas_policy);
2943  }
2944 
2947  UpdateReflexiveAction(&data_.match_p.fwaas_policy, r_fwaas_policy);
2948 }
2949 
2951  sp->action = (1 << TrafficAction::PASS);
2952  sp->out_action = (1 << TrafficAction::PASS);
2953  sp->reverse_action = (1 << TrafficAction::PASS);;
2955  sp->action_summary = rsp->action_summary;
2956 
2957  if (ShouldDrop(sp->action_summary) == false) {
2958  return;
2959  }
2960 
2962  sp->action |= (1 << TrafficAction::TRAP);
2963 }
2964 
2966 // Routines to manage pending actions on a flow. The pending actions are used
2967 // to state-compress actions trigged due to update of,
2968 // - DBEntries like interface, ACL etc..
2969 // - Routes
2972  Reset();
2973 }
2974 
2976 }
2977 
2979  delete_ = false;
2980  recompute_ = false;
2981  recompute_dbentry_ = false;
2982  revaluate_ = false;
2983 }
2984 
2986  if (delete_)
2987  return false;
2988 
2989  delete_ = true;
2990  return true;
2991 }
2992 
2994  delete_ = false;
2995  recompute_ = false;
2996  recompute_dbentry_ = false;
2997  revaluate_ = false;
2998 }
2999 
3001  return delete_;
3002 }
3003 
3005  if (delete_ || recompute_)
3006  return false;
3007 
3008  recompute_ = true;
3009  return true;
3010 }
3011 
3013  recompute_ = false;
3014  recompute_dbentry_ = false;
3015  revaluate_ = false;
3016 }
3017 
3019  if (delete_)
3020  return false;
3021 
3022  return recompute_;
3023 }
3024 
3027  return false;
3028 
3029  recompute_dbentry_ = true;
3030  return true;
3031 }
3032 
3034  recompute_dbentry_ = false;
3035  revaluate_ = false;
3036 }
3037 
3039  if (delete_ || recompute_)
3040  return false;
3041 
3042  return recompute_dbentry_;
3043 }
3044 
3047  return false;
3048 
3049  revaluate_ = true;
3050  return true;
3051 }
3052 
3054  revaluate_ = false;
3055 }
3056 
3059  return false;
3060 
3061  return revaluate_;
3062 }
3063 
3065 // Introspect routines
3067 void SetActionStr(const FlowAction &action_info,
3068  std::vector<ActionStr> &action_str_l) {
3069  std::bitset<32> bs(action_info.action);
3070  for (unsigned int i = 0; i < bs.size(); i++) {
3071  if (bs[i]) {
3072  ActionStr astr;
3073  astr.action =
3075  action_str_l.push_back(astr);
3077  std::vector<MirrorActionSpec>::const_iterator m_it;
3078  for (m_it = action_info.mirror_l.begin();
3079  m_it != action_info.mirror_l.end();
3080  ++m_it) {
3081  ActionStr mstr;
3082  mstr.action += (*m_it).ip.to_string();
3083  mstr.action += " ";
3084  mstr.action += integerToString((*m_it).port);
3085  mstr.action += " ";
3086  mstr.action += (*m_it).vrf_name;
3087  mstr.action += " ";
3088  mstr.action += (*m_it).encap;
3089  action_str_l.push_back(mstr);
3090  }
3091  }
3093  ActionStr vrf_action_str;
3094  vrf_action_str.action +=
3095  action_info.vrf_translate_action_.vrf_name();
3096  action_str_l.push_back(vrf_action_str);
3097  }
3099  ActionStr hbf_action_str;
3100  hbf_action_str.action += "hbs";
3101  action_str_l.push_back(hbf_action_str);
3102  }
3103  }
3104  }
3105 }
3106 
3107 static void SetAclListAclAction(const std::list<MatchAclParams> &acl_l,
3108  std::vector<AclAction> &acl_action_l,
3109  std::string &acl_type) {
3110  std::list<MatchAclParams>::const_iterator it;
3111  for(it = acl_l.begin(); it != acl_l.end(); ++it) {
3112  AclAction acl_action;
3113  acl_action.set_acl_id(UuidToString((*it).acl->GetUuid()));
3114  acl_action.set_acl_type(acl_type);
3115  std::vector<ActionStr> action_str_l;
3116  SetActionStr((*it).action_info, action_str_l);
3117  acl_action.set_action_l(action_str_l);
3118  acl_action_l.push_back(acl_action);
3119  }
3120 }
3121 
3122 void FlowEntry::SetAclAction(std::vector<AclAction> &acl_action_l) const {
3123  const std::list<MatchAclParams> &acl_l = data_.match_p.m_acl_l;
3124  std::string acl_type("nw policy");
3125  SetAclListAclAction(acl_l, acl_action_l, acl_type);
3126 
3127  const std::list<MatchAclParams> &sg_acl_l = data_.match_p.sg_policy.m_acl_l;
3128  acl_type = "sg";
3129  SetAclListAclAction(sg_acl_l, acl_action_l, acl_type);
3130 
3131  const std::list<MatchAclParams> &m_acl_l = data_.match_p.m_mirror_acl_l;
3132  acl_type = "dynamic";
3133  SetAclListAclAction(m_acl_l, acl_action_l, acl_type);
3134 
3135  const std::list<MatchAclParams> &out_acl_l = data_.match_p.m_out_acl_l;
3136  acl_type = "o nw policy";
3137  SetAclListAclAction(out_acl_l, acl_action_l, acl_type);
3138 
3139  const std::list<MatchAclParams> &out_sg_acl_l =
3141  acl_type = "o sg";
3142  SetAclListAclAction(out_sg_acl_l, acl_action_l, acl_type);
3143 
3144  const std::list<MatchAclParams> &out_m_acl_l =
3146  acl_type = "o dynamic";
3147  SetAclListAclAction(out_m_acl_l, acl_action_l, acl_type);
3148 
3149  const std::list<MatchAclParams> &r_sg_l = data_.match_p.sg_policy.m_reverse_acl_l;
3150  acl_type = "r sg";
3151  SetAclListAclAction(r_sg_l, acl_action_l, acl_type);
3152 
3153  const std::list<MatchAclParams> &r_out_sg_l =
3155  acl_type = "r o sg";
3156  SetAclListAclAction(r_out_sg_l, acl_action_l, acl_type);
3157 
3158  const std::list<MatchAclParams> &vrf_assign_acl_l =
3160  acl_type = "vrf assign";
3161  SetAclListAclAction(vrf_assign_acl_l, acl_action_l, acl_type);
3162 
3163  const std::list<MatchAclParams> &aps_l =
3165  acl_type = "fw acl";
3166  SetAclListAclAction(aps_l, acl_action_l, acl_type);
3167 
3168  const std::list<MatchAclParams> &out_aps_l =
3170  acl_type = "reverse fw acl";
3171  SetAclListAclAction(out_aps_l,
3172  acl_action_l, acl_type);
3173 
3174  const std::list<MatchAclParams> &fwaas_l =
3176  acl_type = "fwaas acl";
3177  SetAclListAclAction(fwaas_l, acl_action_l, acl_type);
3178 
3179  const std::list<MatchAclParams> &out_fwaas_l =
3181  acl_type = "reverse fwaas acl";
3182  SetAclListAclAction(out_fwaas_l,
3183  acl_action_l, acl_type);
3184 }
3185 
3186 void FlowEntry::FillFlowInfo(FlowInfo &info) const {
3187  info.set_gen_id(gen_id_);
3188  info.set_flow_index(flow_handle_);
3189  if (key_.family == Address::INET) {
3190  info.set_source_ip(key_.src_addr.to_v4().to_ulong());
3191  info.set_destination_ip(key_.dst_addr.to_v4().to_ulong());
3192  } else {
3193  uint64_t sip[2], dip[2];
3194  Ip6AddressToU64Array(key_.src_addr.to_v6(), sip, 2);
3195  Ip6AddressToU64Array(key_.dst_addr.to_v6(), dip, 2);
3196  info.set_sip_upper(sip[0]);
3197  info.set_sip_lower(sip[1]);
3198  info.set_dip_upper(dip[0]);
3199  info.set_dip_lower(dip[1]);
3200  info.set_source_ip(0);
3201  info.set_destination_ip(0);
3202  }
3203  info.set_source_port(key_.src_port);
3204  info.set_destination_port(key_.dst_port);
3205  info.set_protocol(key_.protocol);
3206  info.set_hbs_intf_dir(hbs_intf_);
3207  info.set_nh_id(key_.nh);
3208  info.set_vrf(data_.vrf);
3209  info.set_source_vn_list(data_.SourceVnList());
3210  info.set_dest_vn_list(data_.DestinationVnList());
3211  info.set_source_vn_match(data_.source_vn_match);
3212  info.set_dest_vn_match(data_.dest_vn_match);
3213  std::vector<uint32_t> v;
3214  SecurityGroupList::const_iterator it;
3215  for (it = data_.source_sg_id_l.begin();
3216  it != data_.source_sg_id_l.end(); it++) {
3217  v.push_back(*it);
3218  }
3219  info.set_source_sg_id_l(v);
3220  v.clear();
3221  for (it = data_.dest_sg_id_l.begin(); it != data_.dest_sg_id_l.end();
3222  it++) {
3223  v.push_back(*it);
3224  }
3225  info.set_dest_sg_id_l(v);
3226 
3227  uint32_t fe_action = data_.match_p.action_info.action;
3228  if (fe_action & (1 << TrafficAction::DENY)) {
3229  info.set_deny(true);
3230  } else if (fe_action & (1 << TrafficAction::PASS)) {
3231  info.set_allow(true);
3232  }
3233 
3234  if (reverse_flow_entry_.get()) {
3235  info.set_reverse_index(reverse_flow_entry_->flow_handle());
3236  }
3237 
3239  info.set_nat(true);
3240  FlowEntry *nat_flow = reverse_flow_entry_.get();
3241  // TODO : IPv6
3242  if (nat_flow) {
3243  if (key_.src_addr != nat_flow->key().dst_addr) {
3244  if (key_.family == Address::INET) {
3245  info.set_nat_source_ip
3246  (nat_flow->key().dst_addr.to_v4().to_ulong());
3247  } else {
3248  info.set_nat_source_ip(0);
3249  }
3250  }
3251 
3252  if (key_.dst_addr != nat_flow->key().src_addr) {
3253  if (key_.family == Address::INET) {
3254  info.set_nat_destination_ip
3255  (nat_flow->key().src_addr.to_v4().to_ulong());
3256  } else {
3257  info.set_nat_destination_ip(0);
3258  }
3259  }
3260 
3261  if (key_.src_port != nat_flow->key().dst_port) {
3262  info.set_nat_source_port(nat_flow->key().dst_port);
3263  }
3264 
3265  if (key_.dst_port != nat_flow->key().src_port) {
3266  info.set_nat_destination_port(nat_flow->key().src_port);
3267  }
3268  info.set_nat_protocol(nat_flow->key().protocol);
3269  info.set_nat_vrf(data_.dest_vrf);
3270  info.set_nat_mirror_vrf(nat_flow->data().mirror_vrf);
3271  }
3272  }
3273 
3275  info.set_mirror(true);
3276  std::vector<MirrorActionSpec>::const_iterator it;
3277  std::vector<MirrorInfo> mirror_l;
3278  for (it = data_.match_p.action_info.mirror_l.begin();
3279  it != data_.match_p.action_info.mirror_l.end();
3280  ++it) {
3281  MirrorInfo mirror_info;
3282  mirror_info.set_mirror_destination((*it).ip.to_string());
3283  mirror_info.set_mirror_port((*it).port);
3284  mirror_info.set_mirror_vrf((*it).vrf_name);
3285  mirror_info.set_analyzer((*it).analyzer_name);
3286  mirror_l.push_back(mirror_info);
3287  }
3288  info.set_mirror_l(mirror_l);
3289  }
3290  info.set_mirror_vrf(data_.mirror_vrf);
3291  info.set_implicit_deny(ImplicitDenyFlow());
3292  info.set_short_flow(is_flags_set(FlowEntry::ShortFlow));
3295  info.set_ecmp_index(data_.component_nh_idx);
3296  }
3298  info.set_trap(true);
3299  }
3300  info.set_vrf_assign(acl_assigned_vrf());
3301  info.set_l3_flow(l3_flow_);
3302  info.set_smac(data_.smac.ToString());
3303  info.set_dmac(data_.dmac.ToString());
3304  info.set_short_flow_reason(FlowEntry::DropReasonStr(short_flow_reason_));
3305  info.set_drop_reason(FlowEntry::DropReasonStr(data_.drop_reason));
3306  if (flow_table_) {
3307  info.set_table_id(flow_table_->table_index());
3308  }
3309 
3310  if (rpf_nh()) {
3311  info.set_rpf_nh(rpf_nh()->id());
3312  } else {
3313  info.set_rpf_nh(0xFFFFFFFF);
3314  }
3315  if (src_ip_nh()) {
3316  info.set_src_ip_nh(src_ip_nh()->id());
3317  } else {
3318  info.set_src_ip_nh(0xFFFFFFFF);
3319  }
3320 }
3321 
3322 static void SetAclListAceId(const AclDBEntry *acl,
3323  const MatchAclParamsList &acl_l,
3324  std::vector<AceId> &ace_l) {
3325  std::list<MatchAclParams>::const_iterator ma_it;
3326  for (ma_it = acl_l.begin();
3327  ma_it != acl_l.end();
3328  ++ma_it) {
3329  if ((*ma_it).acl != acl) {
3330  continue;
3331  }
3332  AclEntryIDList::const_iterator ait;
3333  for (ait = (*ma_it).ace_id_list.begin();
3334  ait != (*ma_it).ace_id_list.end(); ++ ait) {
3335  AceId ace_id;
3336  ace_id.id = ait->id_;
3337  ace_l.push_back(ace_id);
3338  }
3339  }
3340 }
3341 
3343  FlowSandeshData &fe_sandesh_data, Agent *agent) const {
3344  fe_sandesh_data.set_vrf(integerToString(data_.vrf));
3345  fe_sandesh_data.set_src(key_.src_addr.to_string());
3346  fe_sandesh_data.set_dst(key_.dst_addr.to_string());
3347  fe_sandesh_data.set_src_port(key_.src_port);
3348  fe_sandesh_data.set_dst_port(key_.dst_port);
3349  fe_sandesh_data.set_protocol(key_.protocol);
3350  fe_sandesh_data.set_ingress(is_flags_set(FlowEntry::IngressDir));
3351  std::vector<ActionStr> action_str_l;
3352  SetActionStr(data_.match_p.action_info, action_str_l);
3353  fe_sandesh_data.set_action_l(action_str_l);
3354 
3355  std::vector<AclAction> acl_action_l;
3356  SetAclAction(acl_action_l);
3357  fe_sandesh_data.set_acl_action_l(acl_action_l);
3358 
3359  fe_sandesh_data.set_flow_handle(integerToString(flow_handle_));
3360  if (!data_.origin_vn_src.empty()) {
3361  fe_sandesh_data.set_source_vn(data_.origin_vn_src);
3362  } else {
3363  fe_sandesh_data.set_source_vn(data_.source_vn_match);
3364  }
3365  if (!data_.origin_vn_dst.empty()) {
3366  fe_sandesh_data.set_dest_vn(data_.origin_vn_dst);
3367  } else {
3368  fe_sandesh_data.set_dest_vn(data_.dest_vn_match);
3369  }
3370  if (!data_.OriginVnSrcList().empty()) {
3371  fe_sandesh_data.set_source_vn_list(data_.OriginVnSrcList());
3372  } else {
3373  fe_sandesh_data.set_source_vn_list(data_.SourceVnList());
3374  }
3375  if (!data_.OriginVnDstList().empty()) {
3376  fe_sandesh_data.set_dest_vn_list(data_.OriginVnDstList());
3377  } else {
3378  fe_sandesh_data.set_dest_vn_list(data_.DestinationVnList());
3379  }
3380  std::vector<uint32_t> v;
3381  SecurityGroupList::const_iterator it;
3382  for (it = data_.source_sg_id_l.begin();
3383  it != data_.source_sg_id_l.end(); it++) {
3384  v.push_back(*it);
3385  }
3386  fe_sandesh_data.set_source_sg_id_l(v);
3387  v.clear();
3388  for (it = data_.dest_sg_id_l.begin(); it != data_.dest_sg_id_l.end();
3389  it++) {
3390  v.push_back(*it);
3391  }
3392  fe_sandesh_data.set_dest_sg_id_l(v);
3393  fe_sandesh_data.set_flow_uuid(UuidToString(uuid()));
3394  if (fsc_) {
3395  const FlowExportInfo *info = fsc_->FindFlowExportInfo(this);
3396  if (info) {
3397  fe_sandesh_data.set_bytes(integerToString(info->bytes()));
3398  fe_sandesh_data.set_packets(integerToString(info->packets()));
3399  if (info->teardown_time()) {
3400  fe_sandesh_data.set_teardown_time(
3402  } else {
3403  fe_sandesh_data.set_teardown_time("");
3404  }
3405  }
3406  }
3407  fe_sandesh_data.set_current_time(integerToString(
3409 
3410  SetAclListAceId(acl, data_.match_p.m_acl_l, fe_sandesh_data.ace_l);
3411  SetAclListAceId(acl, data_.match_p.sg_policy.m_acl_l, fe_sandesh_data.ace_l);
3412  SetAclListAceId(acl, data_.match_p.m_mirror_acl_l, fe_sandesh_data.ace_l);
3413  SetAclListAceId(acl, data_.match_p.m_out_acl_l, fe_sandesh_data.ace_l);
3415  fe_sandesh_data.ace_l);
3417  fe_sandesh_data.ace_l);
3418  SetAclListAceId(acl, data_.match_p.sg_policy.m_out_acl_l, fe_sandesh_data.ace_l);
3420  fe_sandesh_data.ace_l);
3422  fe_sandesh_data.ace_l);
3424  fe_sandesh_data.ace_l);
3426  fe_sandesh_data.ace_l);
3428  fe_sandesh_data.ace_l);
3430  fe_sandesh_data.ace_l);
3431 
3432  fe_sandesh_data.set_reverse_flow(is_flags_set(FlowEntry::ReverseFlow) ?
3433  "yes" : "no");
3434  fe_sandesh_data.set_nat(is_flags_set(FlowEntry::NatFlow) ? "yes" : "no");
3435  fe_sandesh_data.set_implicit_deny(ImplicitDenyFlow() ? "yes" : "no");
3436  fe_sandesh_data.set_short_flow(is_flags_set(FlowEntry::ShortFlow) ?
3437  "yes" : "no");
3438  fe_sandesh_data.set_l3_flow(l3_flow_);
3439  fe_sandesh_data.set_smac(data_.smac.ToString());
3440  fe_sandesh_data.set_dmac(data_.dmac.ToString());
3441 }
3442 
3443 string FlowEntry::KeyString() const {
3444  std::ostringstream str;
3446  str << " Idx : " << idx
3447  << " Key : "
3448  << key_.nh << " "
3449  << key_.src_addr.to_string() << ":"
3450  << key_.src_port << " "
3451  << key_.dst_addr.to_string() << ":"
3452  << key_.dst_port << " "
3453  << (uint16_t)key_.protocol;
3454  return str.str();
3455 }
3456 
3457 static std::string EventToString(FlowEventLog::Event event,
3458  std::string &event_str) {
3459  switch (event) {
3461  event_str = "FlowAdd";
3462  break;
3464  event_str = "FlowUpdate";
3465  break;
3467  event_str = "FlowDelete";
3468  break;
3470  event_str = "FlowEvict";
3471  break;
3473  event_str = "FlowHandleAssign";
3474  break;
3476  event_str = "FlowMessageSkippedEvictedFlow";
3477  break;
3478  default:
3479  event_str = "Unknown";
3480  break;
3481  }
3482  return event_str;
3483 }
3484 
3485 void FlowEntry::SetEventSandeshData(SandeshFlowIndexInfo *info) {
3486  KSyncFlowIndexManager *mgr =
3488  info->set_trace_index(event_log_index_);
3489  if (mgr->sm_log_count() == 0) {
3490  return;
3491  }
3492  int start = 0;
3493  int count = event_log_index_;
3494  if (event_log_index_ >= mgr->sm_log_count()) {
3495  start = event_log_index_ % mgr->sm_log_count();
3496  count = mgr->sm_log_count();
3497  }
3498  std::vector<SandeshFlowIndexTrace> trace_list;
3499  for (int i = 0; i < count; i++) {
3500  SandeshFlowIndexTrace trace;
3501  FlowEventLog *log = &event_logs_[((start + i) % mgr->sm_log_count())];
3502  trace.set_timestamp(log->time_);
3503  trace.set_flow_handle(log->flow_handle_);
3504  trace.set_flow_gen_id(log->flow_gen_id_);
3505  string event_str;
3506  trace.set_event(EventToString(log->event_, event_str));
3507  trace.set_ksync_hash_id(log->hash_id_);
3508  trace.set_ksync_gen_id(log->gen_id_);
3509  trace.set_vrouter_flow_handle(log->vrouter_flow_handle_);
3510  trace.set_vrouter_gen_id(log->vrouter_gen_id_);
3511  trace_list.push_back(trace);
3512  }
3513  info->set_flow_index_trace(trace_list);
3514 }
3515 
3517  uint32_t flow_handle, uint8_t gen_id) {
3518  KSyncFlowIndexManager *mgr =
3520  string event_str;
3521  LOG(DEBUG, "Flow event = " << EventToString(event, event_str)
3522  << " flow = " << (void *)this
3523  << " flow->flow_handle = " << flow_handle_
3524  << " flow->gen_id = " << (int)gen_id_
3525  << " ksync = " << (void *)ksync
3526  << " Ksync->hash_id = " << ((ksync != NULL) ? ksync->hash_id() : -1)
3527  << " Ksync->gen_id = " << ((ksync != NULL) ? (int)ksync->gen_id() : 0)
3528  << " new_flow_handle = " << flow_handle
3529  << " new_gen_id = " << (int)gen_id);
3530 
3531  if (mgr->sm_log_count() == 0) {
3532  return;
3533  }
3534 
3535  if (event_logs_ == NULL) {
3536  event_log_index_ = 0;
3537  event_logs_.reset(new FlowEventLog[mgr->sm_log_count()]);
3538  }
3539 
3541  event_log_index_++;
3542 
3543  log->time_ = ClockMonotonicUsec();
3544  log->event_ = event;
3545  log->flow_handle_ = flow_handle_;
3546  log->flow_gen_id_ = gen_id_;
3547  log->ksync_entry_ = ksync;
3548  log->hash_id_ = (ksync != NULL) ? ksync->hash_id() : -1;
3549  log->gen_id_ = (ksync != NULL) ? ksync->gen_id() : 0;
3551  log->vrouter_gen_id_ = gen_id;
3552 }
3553 
3556  return data_.source_tag_id_l;
3557  }
3558  return data_.dest_tag_id_l;
3559 }
3560 
3563  return data_.dest_tag_id_l;
3564  }
3565  return data_.source_tag_id_l;
3566 }
3567 
3568 const std::string FlowEntry::BuildRemotePrefix(const FlowRouteRefMap &rt_list,
3569  uint32_t vrf,
3570  const IpAddress &ip) const {
3571  int plen = -1;
3572  FlowRouteRefMap::const_iterator it;
3573  for (it = rt_list.begin(); it != rt_list.end(); it++) {
3574  if (it->first == static_cast<int>(vrf)) {
3575  plen = it->second;
3576  break;
3577  }
3578  }
3579  if (plen != -1) {
3580  return ip.to_string() + "/" + integerToString(plen);
3581  }
3582  return "";
3583 }
3584 
3585 /* Remote prefix is required only wnen remote_tagset is absent. Returns empty
3586  * string as remote-prefix when remote-tagset is present */
3587 const std::string FlowEntry::RemotePrefix() const {
3588  if (remote_tagset().size() > 0) {
3589  return "";
3590  }
3594  }
3596  key_.src_addr);
3597 }
3598 
3600  const VnEntry *vn = vn_entry();
3601  info->vn_ = vn? vn->GetName() : "";
3602  info->nw_ace_uuid_ = nw_ace_uuid();
3603  if (!info->vn_.empty() && !info->nw_ace_uuid_.empty()) {
3604  info->is_valid_ = true;
3605  }
3606 }
3607 
3609  bool added) const {
3610  info->initiator_ = false;
3612  info->remote_vn_ = data_.dest_vn_match;
3613  info->local_tagset_ = local_tagset();
3614  info->remote_tagset_ = remote_tagset();
3615  info->fw_policy_ = fw_policy_name_uuid();
3616  info->remote_prefix_ = RemotePrefix();
3617  info->added_ = added;
3619  info->short_flow_ = true;
3620  } else {
3621  info->short_flow_ = false;
3622  }
3624  info->action_);
3625  info->is_valid_ = true;
3626 }
3627 
3629  bool added) const {
3631  info->initiator_ = true;
3633  info->remote_vn_ = data_.dest_vn_match;
3634  } else {
3635  info->initiator_ = false;
3636  info->local_vn_ = data_.dest_vn_match;
3638  }
3639  info->local_tagset_ = local_tagset();
3640  info->remote_tagset_ = remote_tagset();
3641  info->fw_policy_ = fw_policy_name_uuid();
3642  info->remote_prefix_ = RemotePrefix();
3643  info->added_ = added;
3645  info->short_flow_ = true;
3646  } else {
3647  info->short_flow_ = false;
3648  }
3650  info->action_);
3651  info->is_valid_ = true;
3652 }
3653 
3655  bool added) const {
3656  /* Endpoint statistics update is not required in the following
3657  * cases
3658  * 1. When flow has empty policy_set_acl_name. One example of this
3659  * case is when matching rule for flow is IMPLICIT_ALLOW
3660  * 2. Link local flows
3661  * 3. Reverse flows. We need session_count and not flow_count. So we
3662  * consider only forward flows.
3663  *
3664  * Also count is updated only for forward-flow as the count
3665  * indicates session_count and NOT flow-count
3666  */
3669  return;
3670  }
3673  FillUveLocalRevFlowStatsInfo(info, added);
3674  } else {
3675  FillUveFwdFlowStatsInfo(info, added);
3676  }
3677  } else {
3678  FillUveFwdFlowStatsInfo(info, added);
3679  }
3680 }
3681 
3682 const std::string FlowEntry::fw_policy_uuid() const {
3684 }
3685 
3686 const std::string FlowEntry::fw_policy_name_uuid() const {
3687  /* If policy-name is empty return only policy UUID. Policy-name will be
3688  * empty when one of the implicit rules match */
3689  if (data_.match_p.aps_policy.acl_name_.empty()) {
3690  return fw_policy_uuid();
3691  }
3692  return data_.match_p.aps_policy.acl_name_ + ":" +
3693  fw_policy_uuid();
3694 }
3695 
3697  flow_mgmt_info_.reset(info);
3698 }
3699 
3700 uint8_t FlowEntry::GetUnderlayGwIndex(uint32_t intf_in, const IpAddress &sip,
3701  const IpAddress &dip, uint8_t proto, uint16_t sport,
3702  uint16_t dport) const {
3703  if ((!flow_table()->agent()->is_l3mh()) || (is_flags_set(FlowEntry::LocalFlow))) {
3704  return -1;
3705  }
3706 
3707  uint8_t underlay_gw_index = -1;
3709  FlowEntry *rflow = reverse_flow_entry_.get();
3710  if (rflow != NULL) {
3711  underlay_gw_index = rflow->data().underlay_gw_index_;
3712  }
3713  return underlay_gw_index;
3714  }
3715 
3716  InetUnicastRouteEntry *rt = static_cast<InetUnicastRouteEntry *>
3718  const TunnelNH *tunnel_nh = rt != nullptr ?
3719  dynamic_cast<const TunnelNH *>(rt->GetActiveNextHop()) : nullptr;
3720 
3721  if (!tunnel_nh && is_flags_set(FlowEntry::EcmpFlow) &&
3723  // For composite nh set underlay gw index to component_nh_idx (same hash is used)
3725  }
3726 
3727  Interface *intf = flow_table()->agent()->interface_table()->
3728  FindInterface(intf_in);
3729  if (intf && intf->type() == Interface::PHYSICAL) {
3730  underlay_gw_index = intf->id();
3731  return underlay_gw_index;
3732  } else {
3733  std::size_t hash = 0;
3734  hash = HashIp(hash, sip);
3735  hash = HashIp(hash, dip);
3736 
3737  hash = HashCombine(hash, sport);
3738  hash = HashCombine(hash, dport);
3739  hash = HashCombine(hash, proto);
3740  underlay_gw_index = hash % (flow_table()->agent()->fabric_interface_name_list().size());
3741  }
3742 
3743  if (rt == nullptr) {
3744  return -1;
3745  }
3746  if ( !(tunnel_nh && (tunnel_nh->IsValid()))) {
3747  return -1;
3748  }
3749  uint8_t index = 0;
3750  TunnelNH::EncapDataList encap_list = tunnel_nh->GetEncapDataList();
3751  while (index < encap_list.size()) {
3752  if (encap_list[index].get()->interface_.get() &&
3753  underlay_gw_index == (encap_list[index].get()->interface_).get()->id()) {
3754  underlay_gw_index = index;
3755  break;
3756  }
3757  index++;
3758  }
3759 
3760  if (tunnel_nh->IsEncapValid(underlay_gw_index)) {
3761  return underlay_gw_index;
3762  } else if ( ((underlay_gw_index +1) < (uint8_t)tunnel_nh->GetEncapDataList().size()) &&
3763  tunnel_nh->IsEncapValid(underlay_gw_index +1)) {
3764  return underlay_gw_index +1;
3765  } else if (((underlay_gw_index +1) >= (uint8_t)tunnel_nh->GetEncapDataList().size()) &&
3766  tunnel_nh->IsEncapValid(underlay_gw_index + 1 - tunnel_nh->GetEncapDataList().size())) {
3767  return (underlay_gw_index + 1 - tunnel_nh->GetEncapDataList().size());
3768  }
3769  return -1;
3770 }
3771 
3773  socket_.close();
3774 }
3775 
3776 uint16_t TcpPort::Bind() {
3777  boost::system::error_code ec;
3778  socket_.open(tcp::v4());
3779  socket_.bind(tcp::endpoint(tcp::v4(), port_), ec);
3780  if (ec.failed()) {
3781  return 0;
3782  }
3783  port_ = socket_.local_endpoint(ec).port();
3784  return port_;
3785 }
3786 
3788  socket_.close();
3789 }
3790 
3791 uint16_t UdpPort::Bind() {
3792  boost::system::error_code ec;
3793  socket_.open(udp::v4());
3794  socket_.bind(udp::endpoint(udp::v4(), port_), ec);
3795  if (ec.failed()) {
3796  return 0;
3797  }
3798  port_ = socket_.local_endpoint(ec).port();
3799  return port_;
3800 }
3801 
3803  return key_.IsLess(rhs.key_);
3804 }
3805 
3807  stale_ = true;
3809 }
3810 
3811 bool PortCacheEntry::CanBeAged(uint64_t current_time, uint64_t timeout) const {
3812  if (stale_ &&
3813  current_time - delete_time_ >= timeout) {
3814  return true;
3815  }
3816 
3817  return false;
3818 }
3819 
3821  port_table_(table),
3822  timer_(TimerManager::CreateTimer(
3823  *(table->agent()->event_manager())->io_service(),
3824  "FlowPortBindTimer",
3825  TaskScheduler::GetInstance()->GetTaskId(kTaskFlowMgmt), -1)),
3826  hash_(0), timeout_(PortCacheTable::kAgingTimeout) {
3828  boost::bind(&PortCacheTable::Age, this));
3829 }
3830 
3832  timer_->Cancel();
3834 }
3835 
3837  if (tree_.size() == 0) {
3838  return false;
3839  }
3840 
3841  tbb::recursive_mutex::scoped_lock lock(port_table_->mutex());
3842  uint16_t no_of_entries = tree_.size() / kCacheAging;
3843  uint16_t entries_processed = 0;
3844  uint64_t current_time = UTCTimestampUsec();
3845 
3846  PortCacheTree::iterator it = tree_.lower_bound(hash_);
3847  while (it != tree_.end() && entries_processed <= no_of_entries) {
3848  //Go thru each entry in particular hash bucket and identify
3849  //if any of them can be released
3850  PortCacheEntryList::iterator pcit = it->second.begin();
3851  while (pcit != it->second.end() && entries_processed <= no_of_entries) {
3852  PortCacheEntryList::iterator saved_pcit = pcit;
3853  pcit++;
3854  if (saved_pcit->CanBeAged(current_time, timeout_)) {
3855  //Release reference to port
3856  //check if port is empty, delete the port
3857  port_table_->Free(saved_pcit->key(), saved_pcit->port(), true);
3858  }
3859  entries_processed++;
3860  }
3861  it++;
3862  }
3863 
3864  if (it == tree_.end()) {
3865  hash_ = 0;
3866  } else {
3867  hash_ = it->first;
3868  hash_++;
3869  }
3870 
3871  return true;
3872 }
3873 
3876  boost::bind(&PortCacheTable::Age, this));
3877 }
3878 
3880  timer_->Cancel();
3881 }
3882 
3883 void PortCacheTable::Add(const PortCacheEntry &cache_entry) {
3884  uint16_t hash = port_table_->HashFlowKey(cache_entry.key());
3885  tree_[hash].insert(cache_entry);
3886 
3887  if (tree_.size() == 1) {
3888  StartTimer();
3889  }
3890 }
3891 
3892 void PortCacheTable::Delete(const PortCacheEntry &cache_entry) {
3893  uint16_t hash = port_table_->HashFlowKey(cache_entry.key());
3894  tree_[hash].erase(cache_entry);
3895  if (tree_[hash].size() == 0) {
3896  tree_.erase(hash);
3897  }
3898 
3899  if (tree_.size() == 0) {
3900  StopTimer();
3901  }
3902 }
3903 
3904 void PortCacheTable::MarkDelete(const PortCacheEntry &cache_entry) {
3905  uint16_t hash = port_table_->HashFlowKey(cache_entry.key());
3906 
3907  PortCacheEntryList::iterator it = tree_[hash].find(cache_entry);
3908  if (it != tree_[hash].end()) {
3909  it->MarkDelete();
3910  }
3911 }
3912 
3913 const PortCacheEntry*
3914 PortCacheTable::Find(const FlowKey &key) const {
3915  PortCacheEntry cache_entry(key, 0);
3916  uint16_t hash = port_table_->HashFlowKey(cache_entry.key());
3917 
3918  PortCacheTree::const_iterator pct_it = tree_.find(hash);
3919  if (pct_it == tree_.end()) {
3920  return NULL;
3921  }
3922 
3923  PortCacheEntryList::const_iterator it = pct_it->second.find(cache_entry);
3924  if (it != pct_it->second.end()) {
3925  return &(*it);
3926  }
3927 
3928  return NULL;
3929 }
3930 
3931 uint16_t PortTable::HashFlowKey(const FlowKey &key) {
3932  std::size_t hash = 0;
3933  boost::hash_combine(hash, key.dst_addr.to_v4().to_ulong());
3934  boost::hash_combine(hash, key.dst_port);
3935 
3936  return (hash % hash_table_size_);
3937 }
3938 
3939 PortTable::PortTable(Agent *agent, uint32_t hash_table_size, uint8_t protocol):
3940  agent_(agent), protocol_(protocol), cache_(this),
3941  hash_table_size_(hash_table_size) {
3942  for (uint32_t i = 0; i < hash_table_size; i++) {
3943  hash_table_.push_back(PortBitMapPtr(new PortBitMap()));
3944  }
3945 }
3946 
3948  if (task_trigger_.get()) {
3949  task_trigger_->Reset();
3950  }
3951 }
3952 
3953 uint16_t PortTable::Allocate(const FlowKey &key) {
3954  if (key.protocol != IPPROTO_TCP && key.protocol != IPPROTO_UDP) {
3955  return key.src_port;
3956  }
3957 
3958  tbb::recursive_mutex::scoped_lock lock(mutex_);
3959  //Check if the entry is present in flow cache tree
3960  const PortCacheEntry *entry = cache_.Find(key);
3961  if (entry) {
3962  entry->set_stale(false);
3963  return entry->port();
3964  }
3965 
3966  uint16_t port_hash = HashFlowKey(key);
3967  uint16_t port = kInvalidPort;
3968 
3969  PortBitMapPtr bit_map = hash_table_[port_hash];
3970 
3971  //Mark the port as used in bit map of hash
3972  uint16_t index = bit_map->Insert(key);
3973  if (index >= port_to_bit_index_.size()) {
3974  bit_map->Remove(index);
3975  return port;
3976  }
3977  //Using the index above get the actual port to be used
3978  port = port_list_.At(index)->port();
3979  PortCacheEntry cache_entry(key, port);
3980  //Add to cache tree
3981  cache_.Add(cache_entry);
3982 
3983  return port;
3984 }
3985 
3987 PortTable::CreatePortEntry(uint16_t port_no) {
3988  switch(protocol_) {
3989  case IPPROTO_TCP:
3990  return PortPtr(new TcpPort(*(agent_->event_manager()->io_service()),
3991  port_no));
3992 
3993  case IPPROTO_UDP:
3994  return PortPtr(new UdpPort(*(agent_->event_manager()->io_service()),
3995  port_no));
3996  }
3997 
3998  return PortPtr();
3999 }
4000 
4001 void PortTable::Free(const FlowKey &key, uint16_t port, bool release) {
4002  tbb::recursive_mutex::scoped_lock lock(mutex_);
4003  PortCacheEntry cache_entry(key, kInvalidPort);
4004  if (release) {
4005  //Delete from cache entry
4006  PortCacheEntry cache_entry(key, kInvalidPort);
4007  cache_.Delete(cache_entry);
4008 
4009  uint16_t port_hash = HashFlowKey(key);
4010  PortBitMapPtr bit_map = hash_table_[port_hash];
4011  if (port_to_bit_index_.find(port) != port_to_bit_index_.end()) {
4012  //Upon config change all the entries in bit map
4013  //are implicitly deleted, hence a duplicate
4014  //delete from flow table needs to be handled
4015  //after cross check if key matches
4016  FlowKey existing_key = bit_map->At(port_to_bit_index_[port]);
4017  if (existing_key.IsEqual(key)) {
4018  bit_map->Remove(port_to_bit_index_[port]);
4019  }
4020  }
4021  } else {
4022  //Mark cache entry for deletion
4023  //after aging timeout
4024  cache_.MarkDelete(cache_entry);
4025  }
4026 }
4027 
4028 void PortTable::Relocate(uint16_t port_no) {
4029  PortToBitIndexMap::iterator it = port_to_bit_index_.find(port_no);
4030  assert(it != port_to_bit_index_.end());
4031 
4032  PortPtr port_ptr = port_list_.At(it->second);
4033  DeleteAllFlow(port_no, it->second);
4034  port_list_.Remove(it->second);
4035  it->second = port_list_.Insert(port_ptr);
4036 }
4037 
4038 void PortTable::AddPort(uint16_t port_no) {
4039  PortToBitIndexMap::iterator it = port_to_bit_index_.find(port_no);
4040  //Port number already present
4041  if (port_no != kInvalidPort && it != port_to_bit_index_.end()) {
4042  if (it->second >= port_config_.port_count) {
4043  Relocate(port_no);
4044  }
4045  return;
4046  }
4047 
4048  PortPtr port_ptr = CreatePortEntry(port_no);
4049  if (port_ptr->Bind() || agent_->test_mode()) {
4050  size_t index = port_list_.Insert(port_ptr);
4051  port_to_bit_index_.insert((PortToBitIndexPair(port_ptr->port(),
4052  (uint16_t)index)));
4053  }
4054 }
4055 
4056 void PortTable::DeleteAllFlow(uint16_t port_no, uint16_t index) {
4057  for (uint16_t i = 0; i < hash_table_size_; i++) {
4058  FlowKey key = hash_table_[i]->At((size_t)index);
4059  if (key.family == Address::UNSPEC) {
4060  continue;
4061  }
4062  hash_table_[i]->Remove(index);
4063  Free(key, port_no, true);
4064  //Enqueue delete of flow
4066  }
4067 }
4068 
4069 void PortTable::DeletePort(uint16_t port_no) {
4070  assert(port_no != kInvalidPort);
4071 
4072  PortToBitIndexMap::const_iterator it = port_to_bit_index_.find(port_no);
4073  assert(it != port_to_bit_index_.end());
4074  uint16_t index = it->second;
4075 
4076  //Delete all the flow using this port
4077  DeleteAllFlow(port_no, index);
4078 
4079  port_list_.Remove(index);
4080  port_to_bit_index_.erase(port_no);
4081 }
4082 
4083 bool PortTable::IsValidPort(uint16_t port, uint16_t count) {
4084  if (port_config_.port_range.size() != 0) {
4085  std::vector<PortConfig::PortRange>::const_iterator it =
4086  port_config_.port_range.begin();
4087  //Go thru each range
4088  for(; it != port_config_.port_range.end(); it++) {
4089  if (port >= it->port_start && port <= it->port_end) {
4090  return true;
4091  }
4092  }
4093  } else {
4094  return (count < port_config_.port_count);
4095  }
4096 
4097  return false;
4098 }
4099 
4101  if (task_trigger_.get()) {
4102  task_trigger_->Reset();
4103  }
4104 
4105  PortConfig new_pc = *pc;
4106 
4108  task_trigger_.reset
4109  (new TaskTrigger(boost::bind(&PortTable::HandlePortConfig, this,
4110  new_pc), task_id, 0));
4111  task_trigger_->Set();
4112 }
4113 
4115  tbb::recursive_mutex::scoped_lock lock(mutex_);
4116  uint16_t old_port_count = port_to_bit_index_.size();
4117  port_config_ = pc;
4118 
4119  uint16_t count = 0;
4120 
4121  for (uint16_t index = 0; index < old_port_count; index++) {
4122  PortPtr port = port_list_.At(index);
4123  if (port.get() && IsValidPort(port->port(), count) == false) {
4124  DeletePort(port->port());
4125  } else {
4126  count++;
4127  //For relocating the port of index is higher than
4128  //port count
4129  AddPort(port->port());
4130  }
4131  }
4132 
4133  if (port_config_.port_range.size()) {
4134  std::vector<PortConfig::PortRange>::const_iterator it =
4135  port_config_.port_range.begin();
4136  //Go thru each range
4137  for(; it != port_config_.port_range.end(); it++) {
4138  //Handle range of port
4139  for (uint16_t port = it->port_start;
4140  it->port_end && port <= it->port_end;
4141  port++) {
4142  AddPort(port);
4143  }
4144  }
4145  } else {
4146  //Handle port count, port_count_ would be set only if range is
4147  //not valid
4148  for (uint16_t port = count; port < port_config_.port_count; port++) {
4149  AddPort(0);
4150  }
4151  }
4152  return true;
4153 }
4154 
4155 uint16_t PortTable::GetPortIndex(uint16_t port) const {
4156  PortToBitIndexMap::const_iterator it = port_to_bit_index_.find(port);
4157  assert(it != port_to_bit_index_.end());
4158  return it->second;
4159 }
4160 
4161 void PortTable::GetFlowKeyList(uint16_t port,
4162  std::vector<FlowKey> &list) const {
4163  tbb::recursive_mutex::scoped_lock lock(mutex_);
4164  if (port_to_bit_index_.find(port) == port_to_bit_index_.end()) {
4165  return;
4166  }
4167 
4168  for (uint16_t hash = 0; hash < hash_table_size_; hash++) {
4169  const PortBitMapPtr bit_map = hash_table_[hash];
4170  FlowKey existing_key = bit_map->At(GetPortIndex(port));
4171  if (existing_key.family != Address::UNSPEC) {
4172  list.push_back(existing_key);
4173  }
4174  }
4175 }
4176 
4177 PortTableManager::PortTableManager(Agent *agent, uint16_t hash_table_size):
4178  agent_(agent) {
4179  port_table_list_[IPPROTO_TCP] =
4180  PortTablePtr(new PortTable(agent, hash_table_size, IPPROTO_TCP));
4181  port_table_list_[IPPROTO_UDP] =
4182  PortTablePtr(new PortTable(agent, hash_table_size, IPPROTO_UDP));
4184 }
4185 
4187  for (uint16_t proto = 0; proto < IPPROTO_MAX; proto++) {
4188  port_table_list_[proto].reset();
4189  }
4190 }
4191 uint16_t PortTableManager::Allocate(const FlowKey &key) {
4192  if (key.protocol != IPPROTO_TCP && key.protocol != IPPROTO_UDP) {
4193  return key.src_port;
4194  }
4195 
4196  return port_table_list_[key.protocol]->Allocate(key);
4197 }
4198 
4199 void PortTableManager::Free(const FlowKey &key, uint16_t port, bool evict) {
4200  if (key.protocol != IPPROTO_TCP && key.protocol != IPPROTO_UDP) {
4201  return;
4202  }
4203 
4204  return port_table_list_[key.protocol]->Free(key, port, evict);
4205 }
4206 
4207 void PortTableManager::UpdatePortConfig(uint8_t protocol, const PortConfig *pc) {
4208  if (port_table_list_[protocol].get() == NULL) {
4209  return;
4210  }
4211 
4212  port_table_list_[protocol]->UpdatePortConfig(pc);
4213 }
4214 
4215 void PortTableManager::PortConfigHandler(Agent *agent, uint8_t protocol,
4216  const PortConfig *pc) {
4217  agent->pkt()->get_flow_proto()->port_table_manager()->
4218  UpdatePortConfig(protocol, pc);
4219 }
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:2046
void SetVrfAssignEntry()
Definition: flow_entry.cc:2179
const FlowKey & key() const
Definition: flow_entry.h:594
void SetMirrorVrfFromAction()
Definition: flow_entry.cc:2901
bool ImplicitDenyFlow() const
Definition: flow_entry.h:676
void SetAclAction(std::vector< AclAction > &acl_action_l) const
Definition: flow_entry.cc:3122
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:3682
void SetAclFlowSandeshData(const AclDBEntry *acl, FlowSandeshData &fe_sandesh_data, Agent *agent) const
Definition: flow_entry.cc:3342
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:2798
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:2328
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:3516
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:3561
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:3696
uint32_t MatchAcl(const PacketHeader &hdr, MatchAclParamsList &acl, bool add_implicit_deny, bool add_implicit_allow, FlowPolicyInfo *info)
Definition: flow_entry.cc:2222
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:3587
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:3628
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:3686
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:2700
void GetVrfAssignAcl()
Definition: flow_entry.cc:1793
void SetEventSandeshData(SandeshFlowIndexInfo *info)
Definition: flow_entry.cc:3485
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:3608
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:2933
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:3443
const std::string BuildRemotePrefix(const FlowRouteRefMap &rt_list, uint32_t vr, const IpAddress &ip) const
Definition: flow_entry.cc:3568
void SetHbsInfofromAction()
Definition: flow_entry.cc:2113
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:2009
@ 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:3599
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:2687
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:2921
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:2353
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:3554
const VnEntry * vn_entry() const
Definition: flow_entry.h:653
void FillUveFwStatsInfo(FlowUveFwPolicyInfo *info, bool added) const
Definition: flow_entry.cc:3654
void SessionMatch(SessionPolicy *sp, SessionPolicy *rsp, bool is_sg)
Definition: flow_entry.cc:2422
uint8_t gen_id_
Definition: flow_entry.h:817
void FillFlowInfo(FlowInfo &info) const
Definition: flow_entry.cc:3186
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:2550
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:3700
bool l3_flow() const
Definition: flow_entry.h:598
void SetPacketHeader(PacketHeader *hdr)
Definition: flow_entry.cc:2306
void UpdateL2RouteInfo()
Definition: flow_entry.cc:2077
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:2669
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:3025
bool CanRecomputeDBEntry()
Definition: flow_entry.cc:3038
void ResetRecomputeDBEntry()
Definition: flow_entry.cc:3033
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:3811
void MarkDelete() const
Definition: flow_entry.cc:3806
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:3802
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:3914
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:3820
void MarkDelete(const PortCacheEntry &cache_entry)
Definition: flow_entry.cc:3904
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:3883
PortCacheTree tree_
Definition: flow_entry.h:1002
void Delete(const PortCacheEntry &cache_entry)
Definition: flow_entry.cc:3892
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:4215
void Free(const FlowKey &key, uint16_t port, bool release)
Definition: flow_entry.cc:4199
boost::shared_ptr< PortTable > PortTablePtr
Definition: flow_entry.h:1105
void UpdatePortConfig(uint8_t protocol, const PortConfig *config)
Definition: flow_entry.cc:4207
uint16_t Allocate(const FlowKey &key)
Definition: flow_entry.cc:4191
PortTableManager(Agent *agent, uint16_t hash_table_size)
Definition: flow_entry.cc:4177
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:4161
uint16_t HashFlowKey(const FlowKey &key)
Definition: flow_entry.cc:3931
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:4100
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:4155
uint16_t Allocate(const FlowKey &key)
Definition: flow_entry.cc:3953
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:4069
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:4114
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:4001
bool IsValidPort(uint16_t port, uint16_t count)
Definition: flow_entry.cc:4083
void DeleteAllFlow(uint16_t port, uint16_t index)
Definition: flow_entry.cc:4056
void Relocate(uint16_t port_no)
Definition: flow_entry.cc:4028
void AddPort(uint16_t port_no)
Definition: flow_entry.cc:4038
PortPtr CreatePortEntry(uint16_t port_no)
Definition: flow_entry.cc:3987
PortTable(Agent *agent, uint32_t bucket_size, uint8_t protocol)
Definition: flow_entry.cc:3939
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:3776
boost::asio::ip::tcp::socket socket_
Definition: flow_entry.h:928
virtual ~TcpPort()
Definition: flow_entry.cc:3772
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:3791
boost::asio::ip::udp::socket socket_
Definition: flow_entry.h:939
virtual ~UdpPort()
Definition: flow_entry.cc:3787
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:3322
void SetActionStr(const FlowAction &action_info, std::vector< ActionStr > &action_str_l)
Definition: flow_entry.cc:3067
static bool CopySgEntries(const VmInterface *vm_port, bool ingress_acl, std::list< MatchAclParams > &list)
Definition: flow_entry.cc:1977
static void SetAclListAclAction(const std::list< MatchAclParams > &acl_l, std::vector< AclAction > &acl_action_l, std::string &acl_type)
Definition: flow_entry.cc:3107
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:3457
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