Line data Source code
1 : /*
2 : * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #ifndef __AGENT_PKT_FLOW_ENTRY_H__
7 : #define __AGENT_PKT_FLOW_ENTRY_H__
8 :
9 : #include <mutex>
10 : #include <atomic>
11 :
12 : #include <boost/uuid/uuid_io.hpp>
13 : #include <boost/intrusive_ptr.hpp>
14 : #include <boost/intrusive/list.hpp>
15 : #include <base/util.h>
16 : #include <base/address.h>
17 : #include <db/db_table_walker.h>
18 : #include <cmn/agent_cmn.h>
19 : #include <oper/mirror_table.h>
20 : #include <filter/traffic_action.h>
21 : #include <filter/acl_entry.h>
22 : #include <filter/acl.h>
23 : #include <pkt/pkt_types.h>
24 : #include <pkt/pkt_handler.h>
25 : #include <pkt/pkt_init.h>
26 : #include <pkt/pkt_flow_info.h>
27 : #include <pkt/flow_token.h>
28 : #include <sandesh/sandesh_trace.h>
29 : #include <oper/global_vrouter.h>
30 : #include <oper/vn.h>
31 : #include <oper/vm.h>
32 : #include <oper/interface_common.h>
33 : #include <oper/nexthop.h>
34 : #include <oper/route_common.h>
35 : #include <oper/sg.h>
36 : #include <oper/vrf.h>
37 : #include <filter/acl.h>
38 : #include <sandesh/common/flow_types.h>
39 :
40 : class FlowTableKSyncEntry;
41 : class FlowEntry;
42 : class FlowExportInfo;
43 : class FlowStatsCollector;
44 : class Token;
45 : class FlowMgmtRequest;
46 : class FlowEntryInfo;
47 : struct FlowUveFwPolicyInfo;
48 : struct FlowUveVnAcePolicyInfo;
49 : typedef std::unique_ptr<FlowEntryInfo> FlowMgmtEntryInfoPtr;
50 :
51 : ////////////////////////////////////////////////////////////////////////////
52 : // This is helper struct to carry parameters of reverse-flow. When flow is
53 : // being deleted, the relationship between forward and reverse flows are
54 : // broken. However, some info of reverse flow is needed during export of flows
55 : // for FlowStatsCollector. This information of reverse flow is carried in the
56 : // following struct.
57 : ////////////////////////////////////////////////////////////////////////////
58 : struct RevFlowDepParams {
59 : boost::uuids::uuid rev_uuid_;
60 : boost::uuids::uuid rev_egress_uuid_;
61 : IpAddress sip_;
62 : std::string vmi_uuid_;
63 : std::string sg_uuid_;
64 : std::string vm_cfg_name_;
65 : uint16_t drop_reason_;
66 : std::string nw_ace_uuid_;
67 : FlowAction action_info_;
68 :
69 10163 : RevFlowDepParams() : rev_uuid_(), rev_egress_uuid_(), sip_(), vmi_uuid_(),
70 10163 : sg_uuid_(), vm_cfg_name_(), drop_reason_(),
71 10163 : nw_ace_uuid_(), action_info_() {
72 10163 : }
73 :
74 : RevFlowDepParams(const boost::uuids::uuid &rev_uuid,
75 : const boost::uuids::uuid &rev_egress_uuid,
76 : IpAddress sip,
77 : const std::string &vmi_uuid,
78 : const std::string &sg_uuid,
79 : const std::string &vm_cfg_name,
80 : uint16_t &drop_reason,
81 : std::string &nw_ace_uuid,
82 : FlowAction &action_info) : rev_uuid_(rev_uuid),
83 : rev_egress_uuid_(rev_egress_uuid), sip_(sip), vmi_uuid_(vmi_uuid),
84 : sg_uuid_(sg_uuid), vm_cfg_name_(vm_cfg_name),
85 : drop_reason_(drop_reason), nw_ace_uuid_(nw_ace_uuid),
86 : action_info_(action_info) {
87 : }
88 : };
89 :
90 : ////////////////////////////////////////////////////////////////////////////
91 : // Helper class to manage following,
92 : // 1. VM referred by the flow
93 : // 2. Per VM flow counters to apply per-vm flow limits
94 : // - Number of flows for a VM
95 : // - Number of linklocal flows for a VM
96 : // 3. socket opened for linklocal flows
97 : ////////////////////////////////////////////////////////////////////////////
98 : class VmFlowRef {
99 : public:
100 : static const int kInvalidFd=-1;
101 : VmFlowRef();
102 : VmFlowRef(const VmFlowRef &rhs);
103 : ~VmFlowRef();
104 :
105 : void Init(FlowEntry *flow);
106 : void operator=(const VmFlowRef &rhs);
107 : void Reset(bool reset_flow);
108 : void FreeRef();
109 : void FreeFd();
110 : void SetVm(const VmEntry *vm);
111 : bool AllocateFd(Agent *agent, uint8_t l3_proto);
112 : void Move(VmFlowRef *rhs);
113 :
114 112 : int fd() const { return fd_; }
115 0 : uint16_t port() const { return port_; }
116 : const VmEntry *vm() const { return vm_.get(); }
117 : private:
118 : // IMPORTANT: Keep this structure assignable. Assignment operator is used in
119 : // FlowEntry::Copy() on this structure
120 : VmEntryConstRef vm_;
121 : int fd_;
122 : uint16_t port_;
123 : FlowEntry *flow_;
124 : };
125 :
126 : typedef boost::intrusive_ptr<FlowEntry> FlowEntryPtr;
127 :
128 : struct FlowKey {
129 15793 : FlowKey() :
130 15793 : family(Address::UNSPEC), nh(0), src_addr(Ip4Address(0)),
131 15794 : dst_addr(Ip4Address(0)), protocol(0),
132 15794 : src_port(0), dst_port(0){
133 15794 : }
134 :
135 222 : FlowKey(uint32_t nh_p, const Ip4Address &sip_p, const Ip4Address &dip_p,
136 : uint8_t proto_p, uint16_t sport_p, uint16_t dport_p)
137 222 : : family(Address::INET), nh(nh_p), src_addr(sip_p), dst_addr(dip_p),
138 222 : protocol(proto_p), src_port(sport_p), dst_port(dport_p) {
139 222 : }
140 :
141 224 : FlowKey(uint32_t nh_p, const IpAddress &sip_p, const IpAddress &dip_p,
142 : uint8_t proto_p, uint16_t sport_p, uint16_t dport_p)
143 224 : : family(sip_p.is_v4() ? Address::INET : Address::INET6), nh(nh_p),
144 224 : src_addr(sip_p), dst_addr(dip_p), protocol(proto_p), src_port(sport_p),
145 224 : dst_port(dport_p) {
146 224 : }
147 :
148 304 : FlowKey(const FlowKey &key) :
149 304 : family(key.family), nh(key.nh), src_addr(key.src_addr),
150 304 : dst_addr(key.dst_addr), protocol(key.protocol), src_port(key.src_port),
151 304 : dst_port(key.dst_port) {
152 304 : }
153 :
154 : // Comparator for the flow-entry
155 6542 : bool IsLess(const FlowKey &key) const {
156 6542 : if (family != key.family)
157 0 : return family < key.family;
158 :
159 6542 : if (nh != key.nh)
160 5102 : return nh < key.nh;
161 :
162 1440 : if (src_addr != key.src_addr)
163 322 : return src_addr < key.src_addr;
164 :
165 1118 : if (dst_addr != key.dst_addr)
166 26 : return dst_addr < key.dst_addr;
167 :
168 1092 : if (protocol != key.protocol)
169 0 : return protocol < key.protocol;
170 :
171 1092 : if (src_port != key.src_port)
172 254 : return src_port < key.src_port;
173 :
174 838 : return dst_port < key.dst_port;
175 : }
176 :
177 3 : bool IsEqual(const FlowKey &key) const {
178 3 : if (family != key.family)
179 0 : return false;
180 :
181 3 : if (nh != key.nh)
182 0 : return false;
183 :
184 3 : if (src_addr != key.src_addr)
185 0 : return false;
186 :
187 3 : if (dst_addr != key.dst_addr)
188 0 : return false;
189 :
190 3 : if (protocol != key.protocol)
191 0 : return false;
192 :
193 3 : if (src_port != key.src_port)
194 0 : return false;
195 :
196 3 : if (dst_port != key.dst_port)
197 0 : return false;
198 :
199 3 : return true;
200 : }
201 :
202 : void Reset() {
203 : family = Address::UNSPEC;
204 : nh = -1;
205 : src_addr = Ip4Address(0);
206 : dst_addr = Ip4Address(0);
207 : protocol = -1;
208 : src_port = -1;
209 : dst_port = -1;
210 : }
211 :
212 : Address::Family family;
213 : uint32_t nh;
214 : IpAddress src_addr;
215 : IpAddress dst_addr;
216 : uint8_t protocol;
217 : uint16_t src_port;
218 : uint16_t dst_port;
219 : };
220 :
221 : typedef std::list<MatchAclParams> MatchAclParamsList;
222 :
223 : struct SessionPolicy {
224 : void Reset();
225 : void ResetAction();
226 : void ResetPolicy();
227 : void ResetRuleMatchInfo();
228 :
229 : MatchAclParamsList m_acl_l;
230 : bool rule_present;
231 : uint32_t action;
232 :
233 : MatchAclParamsList m_out_acl_l;
234 : bool out_rule_present;
235 : uint32_t out_action;
236 :
237 : MatchAclParamsList m_reverse_acl_l;
238 : bool reverse_rule_present;
239 : uint32_t reverse_action;
240 :
241 : MatchAclParamsList m_reverse_out_acl_l;
242 : bool reverse_out_rule_present;
243 : uint32_t reverse_out_action;
244 :
245 : std::string rule_uuid_;
246 : std::string acl_name_;
247 : uint32_t action_summary;
248 : };
249 :
250 : // IMPORTANT: Keep this structure assignable. Assignment operator is used in
251 : // FlowEntry::Copy() on this structure
252 : struct MatchPolicy {
253 : MatchPolicy();
254 : ~MatchPolicy();
255 :
256 : void Reset();
257 :
258 : // IMPORTANT: Keep this structure assignable.
259 : MatchAclParamsList m_acl_l;
260 : uint32_t policy_action;
261 :
262 : MatchAclParamsList m_out_acl_l;
263 : uint32_t out_policy_action;
264 :
265 : SessionPolicy sg_policy;
266 : SessionPolicy aps_policy;
267 : SessionPolicy fwaas_policy;
268 :
269 : MatchAclParamsList m_mirror_acl_l;
270 : uint32_t mirror_action;
271 :
272 : MatchAclParamsList m_out_mirror_acl_l;
273 : uint32_t out_mirror_action;
274 :
275 : MatchAclParamsList m_vrf_assign_acl_l;
276 : uint32_t vrf_assign_acl_action;
277 :
278 : FlowAction action_info;
279 : };
280 :
281 : // IMPORTANT: Keep this structure assignable. Assignment operator is used in
282 : // FlowEntry::Copy() on this structure
283 : struct FlowData {
284 : FlowData();
285 : ~FlowData();
286 :
287 : void Reset();
288 : std::vector<std::string> SourceVnList() const;
289 : std::vector<std::string> DestinationVnList() const;
290 : std::vector<std::string> OriginVnSrcList() const;
291 : std::vector<std::string> OriginVnDstList() const;
292 :
293 : MacAddress smac;
294 : MacAddress dmac;
295 : std::string source_vn_match;
296 : std::string dest_vn_match;
297 : std::string origin_vn_src;
298 : std::string origin_vn_dst;
299 : VnListType source_vn_list;
300 : VnListType dest_vn_list;
301 : VnListType origin_vn_src_list;
302 : VnListType origin_vn_dst_list;
303 : SecurityGroupList source_sg_id_l;
304 : SecurityGroupList dest_sg_id_l;
305 : TagList source_tag_id_l;
306 : TagList dest_tag_id_l;
307 : uint32_t flow_source_vrf;
308 : uint32_t flow_dest_vrf;
309 :
310 : MatchPolicy match_p;
311 : VnEntryConstRef vn_entry;
312 : InterfaceConstRef intf_entry;
313 : VmFlowRef in_vm_entry;
314 : VmFlowRef out_vm_entry;
315 : NextHopConstRef src_ip_nh;
316 : uint32_t vrf;
317 : uint32_t mirror_vrf;
318 : uint32_t dest_vrf;
319 : uint32_t component_nh_idx;
320 : uint32_t bgp_as_a_service_sport;
321 : uint32_t bgp_as_a_service_dport;
322 : boost::uuids::uuid bgp_health_check_uuid;
323 : uint32_t ttl;
324 : // In case of policy on fabric, the forwarding happens in
325 : // agent_->fabric_vrf(), but policy processing must happen in
326 : // agent_->fabric_policy_vrf(). Storing the route infor for
327 : // fabric_policy_vrf() for tracking purpose
328 : uint32_t src_policy_vrf;
329 : uint32_t src_policy_plen;
330 : uint32_t dst_policy_vrf;
331 : uint32_t dst_policy_plen;
332 :
333 : // Stats
334 : uint8_t source_plen;
335 : uint8_t dest_plen;
336 : uint16_t drop_reason;
337 : bool vrf_assign_evaluated;
338 : uint32_t if_index_info;
339 : TunnelInfo tunnel_info;
340 : // map for references to the routes which were ignored due to more specific
341 : // route this will be used to trigger flow re-compute to use more specific
342 : // on route add. key for the map is vrf and data is prefix length
343 : FlowRouteRefMap flow_source_plen_map;
344 : FlowRouteRefMap flow_dest_plen_map;
345 :
346 : // RPF related
347 : bool enable_rpf;
348 : // RPF NH for the flow
349 : NextHopConstRef rpf_nh;
350 : // When RPF is derived from a INET route, flow-management uses VRF and plen
351 : // below to track the route for any NH change
352 : // rpf_vrf will be VrfEntry::kInvalidIndex if flow uses l2-route for RPF
353 : uint32_t rpf_vrf;
354 : uint8_t rpf_plen;
355 :
356 : bool disable_validation; // ignore RPF on specific flows (like BFD health check)
357 :
358 : std::string vm_cfg_name;
359 : uint32_t acl_assigned_vrf_index_;
360 : uint32_t qos_config_idx;
361 : uint16_t allocated_port_;
362 : uint8_t underlay_gw_index_;
363 : // IMPORTANT: Keep this structure assignable. Assignment operator is used in
364 : // FlowEntry::Copy() on this structure
365 : };
366 :
367 : struct FlowEventLog {
368 : enum Event {
369 : FLOW_ADD,
370 : FLOW_UPDATE,
371 : FLOW_DELETE,
372 : FLOW_EVICT,
373 : FLOW_HANDLE_ASSIGN,
374 : FLOW_MSG_SKIP_EVICTED,
375 : EVENT_MAXIMUM
376 : };
377 :
378 : FlowEventLog();
379 : ~FlowEventLog();
380 :
381 : uint64_t time_;
382 : Event event_;
383 : uint32_t flow_handle_;
384 : uint8_t flow_gen_id_;
385 : FlowTableKSyncEntry *ksync_entry_;
386 : uint32_t hash_id_;
387 : uint8_t gen_id_;
388 : uint32_t vrouter_flow_handle_;
389 : uint8_t vrouter_gen_id_;
390 : };
391 :
392 : // There are 4 actions supported,
393 : // Flow recomputation goes thru 2 stages of processing,
394 : //
395 : // - recompute_dbentry_ : In this stage, flow is enqueued to flow-update-queue
396 : // as a result of db-entry add/delete/change.
397 : // - recompute_ : In this stage, flow is enqueued to flow-event-queue
398 : // for recomputation of flow
399 : // - delete_ : Specifies that delete action is pending on flow.
400 : // - recompute_ : Specifies that flow is enqueued into flow-event-queue
401 : // for recomputation.
402 : //
403 : // The actions have a priority, the higher priorty action overrides lower
404 : // priority actions. The priority in decreasing order is,
405 : // - delete_
406 : // - recompute_
407 : // - recompute_dbentry_
408 : // - revaluate_
409 : //
410 : // The flags are also used for state-compression of objects. The state
411 : // compression is acheived with,
412 : //
413 : // - Before Event Enqueue :
414 : // Before enqueuing an event, the FlowEvent module checks if the
415 : // corresponding action or higher priority action is pending. If so, the
416 : // event is ignored.
417 : // Note, if the lower priority event is pending, the higher priority event
418 : // is still enqueued. The lower priority event is ignored later as given below
419 : //
420 : // - On Event dequeue :
421 : // After dequeuing an event, FlowEvent module checks if a higher priority
422 : // event is pending. If so, the current event is ignored.
423 : //
424 : // - Post Event processing:
425 : // Once the event is processed, the corresponding action is cleared for both
426 : // forward and reverse flows. Clearing an action also clears lower priority
427 : // actions
428 : class FlowPendingAction {
429 : public:
430 : FlowPendingAction();
431 : ~FlowPendingAction();
432 :
433 : void Reset();
434 :
435 : bool CanDelete();
436 : bool SetDelete();
437 : void ResetDelete();
438 :
439 : bool CanRecompute();
440 : bool SetRecompute();
441 : void ResetRecompute();
442 :
443 : bool CanRecomputeDBEntry();
444 : bool SetRecomputeDBEntry();
445 : void ResetRecomputeDBEntry();
446 :
447 : bool CanRevaluate();
448 : bool SetRevaluate();
449 : void ResetRevaluate();
450 : private:
451 : // delete pending
452 : bool delete_;
453 : // Flow pending complete recompute
454 : bool recompute_;
455 : // Flow pending recompute-dbentry
456 : bool recompute_dbentry_;
457 : // Flow pending revaluation due to change in interface, vn, acl and nh
458 : bool revaluate_;
459 : };
460 :
461 : class FlowEntry {
462 : public:
463 : enum FlowShortReason {
464 : /* Please update FlowEntry::FlowDropReasonStr whenever entries are added
465 : * to the below enum */
466 : SHORT_UNKNOWN = 0,
467 : SHORT_UNAVIALABLE_INTERFACE,
468 : SHORT_IPV4_FWD_DIS,
469 : SHORT_UNAVIALABLE_VRF,
470 : SHORT_NO_SRC_ROUTE,
471 : SHORT_NO_DST_ROUTE,
472 : SHORT_AUDIT_ENTRY,
473 : SHORT_VRF_CHANGE,
474 : SHORT_NO_REVERSE_FLOW,
475 : SHORT_REVERSE_FLOW_CHANGE,
476 : SHORT_NAT_CHANGE,
477 : SHORT_FLOW_LIMIT,
478 : SHORT_LINKLOCAL_SRC_NAT,
479 : SHORT_FAILED_VROUTER_INSTALL,
480 : SHORT_INVALID_L2_FLOW,
481 : SHORT_FLOW_ON_TSN,
482 : SHORT_NO_MIRROR_ENTRY,
483 : SHORT_SAME_FLOW_RFLOW_KEY,
484 : SHORT_PORT_MAP_DROP,
485 : SHORT_NO_SRC_ROUTE_L2RPF,
486 : SHORT_FAT_FLOW_NAT_CONFLICT,
487 : SHORT_L3MH_PHY_INTF_DOWN,
488 : SHORT_MAX
489 : };
490 :
491 : enum FlowDropReason {
492 : /* Please update FlowEntry::FlowDropReasonStr whenever entries are added
493 : * to the below enum */
494 : DROP_UNKNOWN = 0,
495 : DROP_POLICY = SHORT_MAX,
496 : DROP_OUT_POLICY,
497 : DROP_SG,
498 : DROP_OUT_SG,
499 : DROP_REVERSE_SG,
500 : DROP_REVERSE_OUT_SG,
501 : DROP_FIREWALL_POLICY,
502 : DROP_OUT_FIREWALL_POLICY,
503 : DROP_REVERSE_FIREWALL_POLICY,
504 : DROP_REVERSE_OUT_FIREWALL_POLICY,
505 : DROP_FWAAS_POLICY,
506 : DROP_FWAAS_OUT_POLICY,
507 : DROP_FWAAS_REVERSE_POLICY,
508 : DROP_FWAAS_REVERSE_OUT_POLICY,
509 : };
510 :
511 : enum FlowPolicyState {
512 : NOT_EVALUATED,
513 : IMPLICIT_ALLOW, /* Due to No Acl rules */
514 : IMPLICIT_DENY,
515 : DEFAULT_GW_ICMP_OR_DNS, /* DNS/ICMP pkt to/from default gateway */
516 : LINKLOCAL_FLOW, /* No policy applied for linklocal flow */
517 : MULTICAST_FLOW, /* No policy applied for multicast flow */
518 : BGPROUTERSERVICE_FLOW, /* No policy applied for bgp router service flow */
519 : NON_IP_FLOW, /* Flow due to bridging */
520 : };
521 :
522 : static const uint32_t kInvalidFlowHandle=0xFFFFFFFF;
523 : static const uint8_t kMaxMirrorsPerFlow=0x2;
524 : static const std::map<FlowPolicyState, const char*> FlowPolicyStateStr;
525 : static const std::map<uint16_t, const char*> FlowDropReasonStr;
526 : static const uint32_t kFlowRetryAttempts = 5;
527 : // Don't go beyond PCAP_END, pcap type is one byte
528 : enum PcapType {
529 : PCAP_CAPTURE_HOST = 1,
530 : PCAP_FLAGS = 2,
531 : PCAP_SOURCE_VN = 3,
532 : PCAP_DEST_VN = 4,
533 : PCAP_TLV_END = 255
534 : };
535 :
536 : enum FlowEntryFlags {
537 : NatFlow = 1 << 0,
538 : LocalFlow = 1 << 1,
539 : ShortFlow = 1 << 2,
540 : LinkLocalFlow = 1 << 3,
541 : ReverseFlow = 1 << 4,
542 : EcmpFlow = 1 << 5,
543 : IngressDir = 1 << 6,
544 : Trap = 1 << 7,
545 : Multicast = 1 << 8,
546 : // a local port bind is done (used as as src port for linklocal nat)
547 : LinkLocalBindLocalSrcPort = 1 << 9,
548 : TcpAckFlow = 1 << 10,
549 : UnknownUnicastFlood = 1 << 11,
550 : BgpRouterService = 1 << 12,
551 : AliasIpFlow = 1 << 13,
552 : FabricControlFlow = 1 << 14,
553 : FabricFlow = 1 << 15,
554 : HbfFlow = 1 << 16
555 : };
556 :
557 : enum HbsInterface {
558 : HBS_INTERFACE_INVALID = 0,
559 : HBS_INTERFACE_LEFT = 1,
560 : HBS_INTERFACE_RIGHT = 2
561 : };
562 :
563 : FlowEntry(FlowTable *flow_table);
564 : virtual ~FlowEntry();
565 :
566 : void Reset(const FlowKey &k);
567 : void Reset();
568 :
569 : // Copy data fields from rhs
570 : void Copy(FlowEntry *rhs, bool update);
571 :
572 : void InitFwdFlow(const PktFlowInfo *info, const PktInfo *pkt,
573 : const PktControlInfo *ctrl,
574 : const PktControlInfo *rev_ctrl, FlowEntry *rflow,
575 : Agent *agent);
576 : void InitRevFlow(const PktFlowInfo *info, const PktInfo *pkt,
577 : const PktControlInfo *ctrl,
578 : const PktControlInfo *rev_ctrl, FlowEntry *rflow,
579 : Agent *agent);
580 : void InitAuditFlow(uint32_t flow_idx, uint8_t gen_id);
581 : static void Init();
582 :
583 : static AgentRoute *GetL2Route(const VrfEntry *entry, const MacAddress &mac);
584 : static AgentRoute *GetUcRoute(const VrfEntry *entry, const IpAddress &addr);
585 : static AgentRoute *GetEvpnRoute(const VrfEntry *entry, const MacAddress &mac,
586 : const IpAddress &addr, uint32_t ethernet_tag);
587 32 : static const SecurityGroupList &default_sg_list() {
588 32 : return default_sg_list_;
589 : }
590 : static FlowEntry *Allocate(const FlowKey &key, FlowTable *flow_table);
591 : static bool ShouldDrop(uint32_t action);
592 :
593 : // Flow accessor routines
594 0 : int GetRefCount() { return refcount_; }
595 7779 : const FlowKey &key() const { return key_;}
596 12603 : FlowData &data() { return data_;}
597 209 : const FlowData &data() const { return data_;}
598 10872 : FlowTable *flow_table() const { return flow_table_; }
599 2640 : bool l3_flow() const { return l3_flow_; }
600 2511 : uint8_t gen_id() const { return gen_id_; }
601 4892 : uint32_t flow_handle() const { return flow_handle_; }
602 : void set_flow_handle(uint32_t flow_handle, uint8_t gen_id);
603 6415 : FlowEntry *reverse_flow_entry() { return reverse_flow_entry_.get(); }
604 : uint32_t flags() const { return flags_; }
605 197 : const FlowEntry *reverse_flow_entry() const {
606 197 : return reverse_flow_entry_.get();
607 : }
608 743 : void set_reverse_flow_entry(FlowEntry *reverse_flow_entry) {
609 743 : reverse_flow_entry_ = reverse_flow_entry;
610 743 : }
611 41335 : bool is_flags_set(const FlowEntryFlags &flags) const {
612 41335 : return (flags_ & flags);
613 : }
614 556 : void set_flags(const FlowEntryFlags &flags) { flags_ |= flags; }
615 3132 : void reset_flags(const FlowEntryFlags &flags) { flags_ &= ~flags; }
616 : void set_source_sg_id_l(const SecurityGroupList &sg_l) {
617 : data_.source_sg_id_l = sg_l;
618 : }
619 : void set_dest_sg_id_l(const SecurityGroupList &sg_l) {
620 : data_.dest_sg_id_l = sg_l;
621 : }
622 59 : int linklocal_src_port() const { return data_.in_vm_entry.port(); }
623 : int linklocal_src_port_fd() const { return data_.in_vm_entry.fd(); }
624 : const std::string& acl_assigned_vrf() const;
625 : void set_acl_assigned_vrf_index();
626 : uint32_t acl_assigned_vrf_index() const;
627 88 : uint32_t fip() const { return fip_; }
628 44 : VmInterfaceKey fip_vmi() const { return fip_vmi_; }
629 : uint32_t reverse_flow_fip() const;
630 : VmInterfaceKey reverse_flow_vmi() const;
631 : void UpdateFipStatsInfo(uint32_t fip, uint32_t id, Agent *agent);
632 2462 : const boost::uuids::uuid &uuid() const { return uuid_; }
633 189 : const boost::uuids::uuid &egress_uuid() const { return egress_uuid_;}
634 555 : const std::string &sg_rule_uuid() const {
635 555 : return data_.match_p.sg_policy.rule_uuid_;
636 : }
637 555 : const std::string &nw_ace_uuid() const { return nw_ace_uuid_; }
638 : const std::string fw_policy_name_uuid() const;
639 : const std::string fw_policy_uuid() const;
640 : const std::string RemotePrefix() const;
641 : const TagList &remote_tagset() const;
642 : const TagList &local_tagset() const;
643 76 : const std::string &peer_vrouter() const { return peer_vrouter_; }
644 96 : TunnelType tunnel_type() const { return tunnel_type_; }
645 :
646 0 : uint16_t short_flow_reason() const { return short_flow_reason_; }
647 : const MacAddress &smac() const { return data_.smac; }
648 : const MacAddress &dmac() const { return data_.dmac; }
649 367 : bool on_tree() const { return on_tree_; }
650 144 : void set_on_tree() { on_tree_ = true; }
651 3958 : std::mutex &mutex() { return mutex_; }
652 :
653 2118 : const Interface *intf_entry() const { return data_.intf_entry.get(); }
654 952 : const VnEntry *vn_entry() const { return data_.vn_entry.get(); }
655 112 : VmFlowRef *in_vm_flow_ref() { return &(data_.in_vm_entry); }
656 : const VmEntry *in_vm_entry() const { return data_.in_vm_entry.vm(); }
657 : const VmEntry *out_vm_entry() const { return data_.out_vm_entry.vm(); }
658 490 : const NextHop *src_ip_nh() const { return data_.src_ip_nh.get(); }
659 948 : const NextHop *rpf_nh() const { return data_.rpf_nh.get(); }
660 74 : uint32_t GetEcmpIndex() const { return data_.component_nh_idx; }
661 0 : const uint32_t bgp_as_a_service_sport() const {
662 0 : if (is_flags_set(FlowEntry::BgpRouterService))
663 0 : return data_.bgp_as_a_service_sport;
664 0 : return 0;
665 : }
666 10 : const uint32_t bgp_as_a_service_dport() const {
667 10 : if (is_flags_set(FlowEntry::BgpRouterService))
668 10 : return data_.bgp_as_a_service_dport;
669 0 : return 0;
670 : }
671 4331 : const MatchPolicy &match_p() const { return data_.match_p; }
672 :
673 11 : bool ActionSet(TrafficAction::Action action) const {
674 11 : return ((data_.match_p.action_info.action &
675 11 : (1 << action)) ? true : false);
676 : }
677 251 : bool ImplicitDenyFlow() const {
678 251 : return ((data_.match_p.action_info.action &
679 251 : (1 << TrafficAction::IMPLICIT_DENY)) ? true : false);
680 : }
681 1853 : bool deleted() { return deleted_; }
682 :
683 291 : bool IsShortFlow() const { return is_flags_set(FlowEntry::ShortFlow); }
684 15 : bool IsEcmpFlow() const { return is_flags_set(FlowEntry::EcmpFlow); }
685 0 : bool IsNatFlow() const { return is_flags_set(FlowEntry::NatFlow); }
686 104 : bool IsIngressFlow() const { return is_flags_set(FlowEntry::IngressDir); }
687 : // Flow action routines
688 : void ResyncFlow();
689 : void RpfUpdate();
690 : bool ActionRecompute();
691 : bool DoPolicy();
692 : void MakeShortFlow(FlowShortReason reason);
693 : void SetMirrorVrfFromAction();
694 : void SetHbsInfofromAction();
695 : void SetVrfAssignEntry();
696 : void ComputeReflexiveAction();
697 : uint32_t MatchAcl(const PacketHeader &hdr,
698 : MatchAclParamsList &acl, bool add_implicit_deny,
699 : bool add_implicit_allow, FlowPolicyInfo *info);
700 : void ResetPolicy();
701 :
702 : void FillFlowInfo(FlowInfo &info) const;
703 : void GetPolicyInfo(const VnEntry *vn, const FlowEntry *rflow);
704 : void GetPolicyInfo(const FlowEntry *rflow);
705 : void GetPolicyInfo(const VnEntry *vn);
706 : void GetPolicyInfo();
707 : void UpdateL2RouteInfo();
708 : void GetVrfAssignAcl();
709 0 : void SetMirrorVrf(const uint32_t id) {data_.mirror_vrf = id;}
710 :
711 : void GetPolicy(const VnEntry *vn, const FlowEntry *rflow);
712 : void GetNonLocalFlowSgList(const VmInterface *vm_port);
713 : void GetLocalFlowSgList(const VmInterface *vm_port,
714 : const VmInterface *reverse_vm_port);
715 : void GetSgList(const Interface *intf);
716 : void GetApplicationPolicySet(const Interface *intf,
717 : const FlowEntry *rflow);
718 : void SetPacketHeader(PacketHeader *hdr);
719 : void SetOutPacketHeader(PacketHeader *hdr);
720 224 : void set_deleted(bool deleted) { deleted_ = deleted; }
721 : void SetAclAction(std::vector<AclAction> &acl_action_l) const;
722 : void UpdateReflexiveAction();
723 : bool IsFabricControlFlow() const;
724 : void SetAclFlowSandeshData(const AclDBEntry *acl,
725 : FlowSandeshData &fe_sandesh_data,
726 : Agent *agent) const;
727 : uint32_t InterfaceKeyToId(Agent *agent, const VmInterfaceKey &key);
728 0 : FlowTableKSyncEntry *ksync_entry() { return ksync_entry_; }
729 677 : FlowStatsCollector* fsc() const {
730 677 : return fsc_;
731 : }
732 :
733 288 : void set_fsc(FlowStatsCollector *fsc) {
734 288 : fsc_ = fsc;
735 288 : }
736 : static std::string DropReasonStr(uint16_t reason);
737 : std::string KeyString() const;
738 : void SetEventSandeshData(SandeshFlowIndexInfo *info);
739 : void LogFlow(FlowEventLog::Event event, FlowTableKSyncEntry* ksync,
740 : uint32_t flow_handle, uint8_t gen_id);
741 : void RevFlowDepInfo(RevFlowDepParams *params);
742 455 : uint32_t last_event() const { return last_event_; }
743 1078 : void set_last_event(uint32_t event) {
744 1078 : last_event_ = event;
745 1078 : e_history_.UpdateEvtHistory(event);
746 1078 : }
747 0 : uint8_t GetMaxRetryAttempts() { return flow_retry_attempts_; }
748 0 : void IncrementRetrycount() { flow_retry_attempts_++;}
749 0 : void ResetRetryCount(){ flow_retry_attempts_ = 0; }
750 6 : bool IsOnUnresolvedList(){ return is_flow_on_unresolved_list;}
751 0 : void SetUnResolvedList(bool added){ is_flow_on_unresolved_list = added;}
752 644 : FlowPendingAction *GetPendingAction() { return &pending_actions_; }
753 598 : bool trace() const { return trace_; }
754 224 : void set_trace(bool val) { trace_ = val; }
755 :
756 454 : FlowMgmtRequest *flow_mgmt_request() const { return flow_mgmt_request_; }
757 747 : void set_flow_mgmt_request(FlowMgmtRequest *req) {
758 747 : flow_mgmt_request_ = req;
759 747 : }
760 :
761 742 : FlowEntryInfo *flow_mgmt_info() const { return flow_mgmt_info_.get(); }
762 : void set_flow_mgmt_info(FlowEntryInfo *info);
763 : void FillUveFwStatsInfo(FlowUveFwPolicyInfo *info, bool added) const;
764 : void FillUveVnAceInfo(FlowUveVnAcePolicyInfo *info) const;
765 : bool IsClientFlow();
766 : bool IsServerFlow();
767 230 : uint16_t allocated_port() {
768 230 : return data_.allocated_port_;
769 : }
770 80 : void IncrementTransactionId() { transaction_id_++;}
771 1057 : uint32_t GetTransactionId() {return transaction_id_;}
772 313 : void SetHbsInterface (HbsInterface intf) { hbs_intf_ = intf; }
773 22 : HbsInterface GetHbsInterface() { return hbs_intf_; }
774 : private:
775 : friend class FlowTable;
776 : friend class FlowEntryFreeList;
777 : friend class FlowStatsCollector;
778 : friend class KSyncFlowIndexManager;
779 :
780 : friend void intrusive_ptr_add_ref(FlowEntry *fe);
781 : friend void intrusive_ptr_release(FlowEntry *fe);
782 :
783 : void FillUveLocalRevFlowStatsInfo(FlowUveFwPolicyInfo *info, bool added)
784 : const;
785 : void FillUveFwdFlowStatsInfo(FlowUveFwPolicyInfo *info, bool added) const;
786 : void RpfInit(const AgentRoute *rt, const IpAddress &sip);
787 : void RpfSetRpfNhFields(const NextHop *rpf_nh);
788 : void RpfSetRpfNhFields(const AgentRoute *rt, const NextHop *rpf_nh);
789 : void RpfSetSrcIpNhFields(const AgentRoute *rt, const NextHop *src_ip_nh);
790 : bool RpfFromSrcIpNh() const;
791 : void RpfComputeEgress();
792 : void RpfComputeIngress();
793 :
794 : bool InitFlowCmn(const PktFlowInfo *info, const PktControlInfo *ctrl,
795 : const PktControlInfo *rev_ctrl, FlowEntry *rflow);
796 : VmInterfaceKey InterfaceIdToKey(Agent *agent, uint32_t id);
797 : void GetSourceRouteInfo(const AgentRoute *rt);
798 : void GetDestRouteInfo(const AgentRoute *rt);
799 : const std::string InterfaceIdToVmCfgName(Agent *agent, uint32_t id);
800 : const VrfEntry *GetDestinationVrf() const;
801 : bool SetQosConfigIndex();
802 : void SetAclInfo(SessionPolicy *sp, SessionPolicy *rsp,
803 : const FlowPolicyInfo &fwd_flow_info,
804 : const FlowPolicyInfo &rev_flow_info, bool tcp_rev,
805 : bool is_sg);
806 : void SessionMatch(SessionPolicy *sp, SessionPolicy *rsp, bool is_sg);
807 : void UpdateReflexiveAction(SessionPolicy *sp, SessionPolicy *rsp);
808 : const std::string BuildRemotePrefix(const FlowRouteRefMap &rt_list,
809 : uint32_t vr, const IpAddress &ip) const;
810 : uint8_t GetUnderlayGwIndex(uint32_t intf_in, const IpAddress &sip,
811 : const IpAddress &dip, uint8_t proto, uint16_t sport,
812 : uint16_t dport) const;
813 :
814 : FlowKey key_;
815 : FlowTable *flow_table_;
816 : FlowData data_;
817 : bool l3_flow_;
818 : uint8_t gen_id_;
819 : uint32_t flow_handle_;
820 : FlowEntryPtr reverse_flow_entry_;
821 : static std::atomic<int> alloc_count_;
822 : bool deleted_;
823 : uint32_t flags_;
824 : uint16_t short_flow_reason_;
825 : boost::uuids::uuid uuid_;
826 : boost::uuids::uuid egress_uuid_;
827 : std::string sg_rule_uuid_;
828 : std::string nw_ace_uuid_;
829 : //IP address of the src vrouter for egress flows and dst vrouter for
830 : //ingress flows. Used only during flow-export
831 : std::string peer_vrouter_;
832 : //Underlay IP protocol type. Used only during flow-export
833 : TunnelType tunnel_type_;
834 : // Is flow-entry on the tree
835 : bool on_tree_;
836 : // Following fields are required for FIP stats accounting
837 : uint32_t fip_;
838 : VmInterfaceKey fip_vmi_;
839 : // Ksync entry for the flow
840 : FlowTableKSyncEntry *ksync_entry_;
841 : // atomic refcount
842 : std::atomic<int> refcount_;
843 : std::mutex mutex_;
844 : boost::intrusive::list_member_hook<> free_list_node_;
845 : FlowStatsCollector *fsc_;
846 : uint32_t last_event_;
847 : bool trace_;
848 : boost::scoped_array<FlowEventLog> event_logs_;
849 : uint16_t event_log_index_;
850 : FlowPendingAction pending_actions_;
851 : static SecurityGroupList default_sg_list_;
852 : uint8_t flow_retry_attempts_;
853 : bool is_flow_on_unresolved_list;
854 : // flow_mgmt_request used for compressing events to flow-mgmt queue.
855 : // flow_mgmt_request_ is set when flow is enqueued to flow-mgmt queue. No
856 : // subsequent enqueues are done till this field is set. The request can be
857 : // updated with new values to reflect latest state
858 : FlowMgmtRequest *flow_mgmt_request_;
859 :
860 : // Field used by flow-mgmt module. Its stored here to optimize flow-mgmt
861 : // and avoid lookups
862 : FlowMgmtEntryInfoPtr flow_mgmt_info_;
863 : const std::string fw_policy_;
864 : // Transaction id is used to detect old/stale vrouter add-ack response for
865 : // reverse flow handle allocation requests. It can happen if flow are
866 : // evicted from vrouter just after add-ack response sent to agent
867 : // and same flows are created before add-ack response gets processed
868 : // in agent.
869 : // transaction id should not be copied, it is incremented when flow entry
870 : // is reused.
871 : uint32_t transaction_id_;
872 : class FlowEntryEventHistory {
873 : public:
874 10000 : FlowEntryEventHistory() {
875 10000 : idx_ = 0;
876 60000 : for (uint32_t i = 0; i < size_; i++) {
877 50000 : last_events_[i] = 0;
878 : }
879 10000 : }
880 :
881 1078 : void UpdateEvtHistory( uint32_t event ) {
882 1078 : last_events_[idx_] = event;
883 1078 : idx_ = (idx_+1) % size_;
884 1078 : }
885 :
886 : private:
887 : static const uint32_t size_ = 5;
888 : uint32_t last_events_[size_];
889 : uint32_t idx_;
890 : };
891 : // Not modifying on Reset and Copy to retain the history
892 : FlowEntryEventHistory e_history_;
893 : HbsInterface hbs_intf_;
894 : // IMPORTANT: Remember to update Reset() routine if new fields are added
895 : // IMPORTANT: Remember to update Copy() routine if new fields are added
896 : };
897 :
898 : void intrusive_ptr_add_ref(FlowEntry *fe);
899 : void intrusive_ptr_release(FlowEntry *fe);
900 :
901 : //A bound source port could be reused across different
902 : //destination IP address, Port class holds a list of
903 : //destination IP which have used this particular source
904 : //port
905 : class Port {
906 : public:
907 : Port() :
908 : port_(0) {}
909 0 : Port(uint16_t port) : port_(port) {}
910 0 : ~Port() {}
911 :
912 0 : uint16_t port() const {
913 0 : return port_;
914 : }
915 :
916 : virtual uint16_t Bind() = 0;
917 : protected:
918 : uint16_t port_;
919 : };
920 :
921 : class TcpPort : public Port {
922 : public:
923 0 : TcpPort(boost::asio::io_context &io, uint16_t port):
924 0 : Port(port), socket_(io) {}
925 : virtual ~TcpPort();
926 :
927 : virtual uint16_t Bind();
928 : private:
929 : boost::asio::ip::tcp::socket socket_;
930 : };
931 :
932 : class UdpPort : public Port {
933 : public:
934 0 : UdpPort(boost::asio::io_context &io, uint16_t port):
935 0 : Port(port), socket_(io) {}
936 : virtual ~UdpPort();
937 :
938 : virtual uint16_t Bind();
939 : private:
940 : boost::asio::ip::udp::socket socket_;
941 : };
942 :
943 : //Given a flow key gives the port used
944 : //This would fail on first attempt or if the
945 : //flow has been idle for long time
946 : class PortCacheEntry {
947 : public:
948 0 : PortCacheEntry(const FlowKey &key,
949 0 : const uint16_t port):
950 0 : key_(key), port_(port), stale_(false) {}
951 :
952 0 : const FlowKey& key() const {
953 0 : return key_;
954 : }
955 :
956 0 : uint16_t port() const {
957 0 : return port_;
958 : }
959 :
960 0 : void set_stale(bool stale) const {
961 0 : stale_ = stale;
962 0 : }
963 :
964 : void MarkDelete() const;
965 : bool operator<(const PortCacheEntry &rhs) const;
966 : bool CanBeAged(uint64_t current_time, uint64_t timeout) const;
967 : private:
968 : FlowKey key_;
969 : uint16_t port_;
970 : mutable bool stale_;
971 : mutable uint64_t delete_time_;
972 : };
973 :
974 : class PortTable;
975 :
976 : //Maintain a cache table which would be used to check
977 : //if a flow prexisted and reuse the port if yes
978 : class PortCacheTable {
979 : public:
980 : static const uint64_t kCacheAging = 1000;
981 : static const uint64_t kAgingTimeout = 1000 * 1000 * 600; //10 minutes
982 :
983 : typedef std::set<PortCacheEntry> PortCacheEntryList;
984 : typedef std::map<uint16_t , PortCacheEntryList> PortCacheTree;
985 :
986 : PortCacheTable(PortTable *table);
987 : ~PortCacheTable();
988 :
989 : void Add(const PortCacheEntry &cache_entry);
990 : void Delete(const PortCacheEntry &cache_entry);
991 : const PortCacheEntry* Find(const FlowKey &key) const;
992 : void MarkDelete(const PortCacheEntry &cache_entry);
993 :
994 2 : void set_timeout(uint64_t timeout) {
995 2 : timeout_ = timeout;
996 2 : }
997 :
998 : private:
999 : void StartTimer();
1000 : void StopTimer();
1001 : bool Age();
1002 :
1003 : PortCacheTree tree_;
1004 : PortTable *port_table_;
1005 : Timer* timer_;
1006 : uint16_t hash_;
1007 : uint64_t timeout_;
1008 : };
1009 :
1010 : //Per protocol table to manage port allocation
1011 : class PortTable {
1012 : public:
1013 : const static uint8_t kInvalidPort = 0;
1014 :
1015 : typedef boost::shared_ptr<Port> PortPtr;
1016 : typedef IndexVector<PortPtr> PortList;
1017 :
1018 : typedef std::map<uint16_t, uint16_t> PortToBitIndexMap;
1019 : typedef std::pair<uint16_t, uint16_t> PortToBitIndexPair;
1020 :
1021 : typedef IndexVector<FlowKey> PortBitMap;
1022 : typedef boost::shared_ptr<PortBitMap> PortBitMapPtr;
1023 : typedef std::vector<PortBitMapPtr> PortHashTable;
1024 :
1025 : PortTable(Agent *agent, uint32_t bucket_size, uint8_t protocol);
1026 : ~PortTable();
1027 :
1028 : uint16_t Allocate(const FlowKey &key);
1029 : void Free(const FlowKey &key, uint16_t port, bool release);
1030 : uint16_t HashFlowKey(const FlowKey &key);
1031 :
1032 4 : Agent *agent() {
1033 4 : return agent_;
1034 : }
1035 :
1036 : uint16_t port_count() const {
1037 : return port_config_.port_count;
1038 : }
1039 :
1040 2 : void set_timeout(uint64_t timeout) {
1041 2 : cache_.set_timeout(timeout);
1042 2 : }
1043 :
1044 0 : std::recursive_mutex& mutex() {
1045 0 : return mutex_;
1046 : }
1047 :
1048 : void UpdatePortConfig(const PortConfig *port_config);
1049 :
1050 : uint16_t GetPortIndex(uint16_t port) const;
1051 0 : const PortConfig* port_config() const {
1052 0 : return &port_config_;
1053 : }
1054 :
1055 0 : std::vector<uint16_t> GetPortList() const {
1056 0 : std::lock_guard<std::recursive_mutex> lock(mutex_);
1057 0 : std::vector<uint16_t> port_list;
1058 0 : PortToBitIndexMap::const_iterator it = port_to_bit_index_.begin();
1059 0 : for(; it != port_to_bit_index_.end(); it++) {
1060 0 : port_list.push_back(it->first);
1061 : }
1062 0 : return port_list;
1063 0 : }
1064 :
1065 : void GetFlowKeyList(uint16_t port, std::vector<FlowKey> &key) const;
1066 : private:
1067 : Agent *agent_;
1068 : PortPtr CreatePortEntry(uint16_t port_no);
1069 : //Create a port with given port_no
1070 : void AddPort(uint16_t port_no);
1071 : void DeletePort(uint16_t port_no);
1072 : void Relocate(uint16_t port_no);
1073 : bool IsValidPort(uint16_t port, uint16_t count);
1074 : void DeleteAllFlow(uint16_t port, uint16_t index);
1075 : bool HandlePortConfig(const PortConfig &pc);
1076 :
1077 : uint8_t protocol_;
1078 : //Holds freed bit entry in table for while so that
1079 : //flow could be re-established after aging
1080 : PortCacheTable cache_;
1081 :
1082 : //Max no of hash entries, higher the number
1083 : //lesser the chance of clash. Hash would be derived based on
1084 : //destination IP and port
1085 : uint16_t hash_table_size_;
1086 :
1087 : //A Given a hash holds a list of used port numbers
1088 : //Free Bit index is to be used in Port tree to get actual port value
1089 : PortHashTable hash_table_;
1090 :
1091 : //Mapping from bit vector offset to actual port number
1092 : PortList port_list_;
1093 :
1094 : //Mapping from port to bit index for easier auditing on config
1095 : //change
1096 : PortToBitIndexMap port_to_bit_index_;
1097 :
1098 : //Number of port that agent can bind on
1099 : PortConfig port_config_;
1100 : mutable std::recursive_mutex mutex_;
1101 : std::unique_ptr<TaskTrigger> task_trigger_;
1102 : };
1103 :
1104 : class PortTableManager {
1105 : public:
1106 : typedef boost::shared_ptr<PortTable> PortTablePtr;
1107 : PortTableManager(Agent *agent, uint16_t hash_table_size);
1108 : ~PortTableManager();
1109 :
1110 : uint16_t Allocate(const FlowKey &key);
1111 : void Free(const FlowKey &key, uint16_t port, bool release);
1112 :
1113 : void UpdatePortConfig(uint8_t protocol, const PortConfig *config);
1114 : static void PortConfigHandler(Agent *agent, uint8_t protocol,
1115 : const PortConfig *pc);
1116 0 : const PortTable* GetPortTable(uint8_t proto) {
1117 0 : return port_table_list_[proto].get();
1118 : }
1119 : private:
1120 : Agent *agent_;
1121 : PortTablePtr port_table_list_[IPPROTO_MAX];
1122 : };
1123 : #endif // __AGENT_PKT_FLOW_ENTRY_H__
|