OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
flow_kstate.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <base/task.h>
6 #include <base/address_util.h>
7 
8 #include <cmn/agent_cmn.h>
9 #include <kstate/kstate.h>
10 #include <kstate/flow_kstate.h>
11 
12 #include <vr_flow.h>
13 #include <vr_mirror.h>
14 
15 #include <pkt/flow_table.h>
16 
19 
20 using namespace std;
21 
22 FlowKState::FlowKState(Agent *agent, const string &resp_ctx, int idx) :
23  Task((TaskScheduler::GetInstance()->GetTaskId("Agent::FlowResponder")),
24  0), response_context_(resp_ctx), flow_idx_(idx), evicted_(0),
25  flow_iteration_key_(0), agent_(agent) {
26 }
27 
28 FlowKState::FlowKState(Agent *agent, const string &resp_ctx,
29  const string &iter_idx) :
30  Task((TaskScheduler::GetInstance()->GetTaskId("Agent::FlowResponder")),
31  0), response_context_(resp_ctx), flow_idx_(-1), evicted_(0),
32  flow_iteration_key_(0), agent_(agent) {
33  stringToInteger(iter_idx, flow_iteration_key_);
34 }
35 
36 void FlowKState::SendResponse(KFlowResp *resp) const {
37  resp->set_context(response_context_);
38  resp->Response();
39 }
40 
41 const string FlowKState::FlagToStr(unsigned int flag) const {
42  switch(flag) {
43  case VR_FLOW_FLAG_ACTIVE:
44  return " ACTIVE ";
45  case VR_FLOW_FLAG_MIRROR:
46  return " MIRROR ";
47  case VR_FLOW_FLAG_VRFT:
48  return " VRFT ";
49  case VR_FLOW_FLAG_SNAT:
50  return " SNAT ";
51  case VR_FLOW_FLAG_SPAT:
52  return " SPAT ";
53  case VR_FLOW_FLAG_DNAT:
54  return " DNAT ";
55  case VR_FLOW_FLAG_DPAT:
56  return " DPAT ";
57  case VR_FLOW_FLAG_LINK_LOCAL:
58  return " LINK_LOCAL ";
59  case VR_FLOW_FLAG_EVICTED:
60  return " EVICTED ";
61  case VR_FLOW_FLAG_EVICT_CANDIDATE:
62  return " EVICT_CANDIDATE ";
63  case VR_FLOW_FLAG_NEW_FLOW:
64  return " NEW_FLOW ";
65  case VR_FLOW_FLAG_MODIFIED:
66  return " MODIFIED ";
67  case VR_RFLOW_VALID:
68  return " RFLOW_VALID ";
69  default:
70  return " INVALID ";
71  }
72 }
73 
74 const string FlowKState::TcpFlagToStr(unsigned int flag) const {
75  switch(flag) {
76  case VR_FLOW_TCP_SYN:
77  return " SYN ";
78  case VR_FLOW_TCP_SYN_R:
79  return " SYN_R ";
80  case VR_FLOW_TCP_ESTABLISHED:
81  return " ESTB ";
82  case VR_FLOW_TCP_ESTABLISHED_R:
83  return " ESTB_R ";
84  case VR_FLOW_TCP_FIN:
85  return " FIN ";
86  case VR_FLOW_TCP_FIN_R:
87  return " FIN_R ";
88  case VR_FLOW_TCP_RST:
89  return " RST ";
90  case VR_FLOW_TCP_HALF_CLOSE:
91  return " HALF_CLOSE ";
92  case VR_FLOW_TCP_DEAD:
93  return " DEAD ";
94  default:
95  return " INVALID ";
96  }
97 }
98 
99 void FlowKState::UpdateFlagStr(string &str, bool &set, bool tcp, unsigned sflag,
100  unsigned cflag) const {
101  string flag_str;
102  if (sflag & cflag) {
103  if (tcp) {
104  flag_str.assign(TcpFlagToStr(cflag));
105  } else {
106  flag_str.assign(FlagToStr(cflag));
107  }
108  if (set) {
109  str.append("|" + flag_str);
110  } else {
111  str.assign(flag_str);
112  set = true;
113  }
114  }
115 }
116 
117 const std::string FlowKState::DropCodeToStr(uint8_t drop_code) const {
118  switch (drop_code) {
119  case VR_FLOW_DR_UNKNOWN:
120  return "Unknown";
121  case VR_FLOW_DR_UNAVIALABLE_INTF:
122  return "IntfErr";
123  case VR_FLOW_DR_IPv4_FWD_DIS:
124  return "Ipv4Dis";
125  case VR_FLOW_DR_UNAVAILABLE_VRF:
126  return "VrfErr";
127  case VR_FLOW_DR_NO_SRC_ROUTE:
128  return "NoSrcRt";
129  case VR_FLOW_DR_NO_DST_ROUTE:
130  return "NoDstRt";
131  case VR_FLOW_DR_AUDIT_ENTRY:
132  return "Audit";
133  case VR_FLOW_DR_VRF_CHANGE:
134  return "VrfChange";
135  case VR_FLOW_DR_NO_REVERSE_FLOW:
136  return "NoRevFlow";
137  case VR_FLOW_DR_REVERSE_FLOW_CHANGE:
138  return "RevFlowChng";
139  case VR_FLOW_DR_NAT_CHANGE:
140  return "NatChng";
141  case VR_FLOW_DR_FLOW_LIMIT:
142  return "FlowLim";
143  case VR_FLOW_DR_LINKLOCAL_SRC_NAT:
144  return "LinkSrcNatErr";
145  case VR_FLOW_DR_POLICY:
146  return "Policy";
147  case VR_FLOW_DR_OUT_POLICY:
148  return "OutPolicy";
149  case VR_FLOW_DR_SG:
150  return "SG";
151  case VR_FLOW_DR_OUT_SG:
152  return "OutSG";
153  case VR_FLOW_DR_REVERSE_SG:
154  return "RevSG";
155  case VR_FLOW_DR_REVERSE_OUT_SG:
156  return "RevOutSG";
157  case VR_FLOW_DR_FW_POLICY:
158  return "FwPolicy";
159  case VR_FLOW_DR_OUT_FW_POLICY:
160  return "OutFwPolicy";
161  case VR_FLOW_DR_REVERSE_FW_POLICY:
162  return "RevFwPolicy";
163  case VR_FLOW_DR_REVERSE_OUT_FW_POLICY:
164  return "RevOutFwPolicy";
165  case VR_FLOW_DR_SAME_FLOW_RFLOW_KEY:
166  return "SameFlowRflowKey";
167  default:
168  return "Unknown";
169  }
170 }
171 
172 void FlowKState::SetFlowHandle(KFlowResp *resp, const uint32_t idx) const {
173  if (evicted_) {
174  resp->set_flow_handle(integerToString(idx) + " evicted_set");
175  } else {
176  resp->set_flow_handle(integerToString(idx));
177  }
178 }
179 
180 void FlowKState::SetFlowData(vector<KFlowInfo> &list,
181  const vr_flow_entry *k_flow,
182  const int index) const {
183  KFlowInfo data;
184  bool action_drop = false;
185  KSyncFlowMemory *flow_mem = agent_->ksync()->ksync_flow_memory();
186  IpAddress sip, dip;
187  flow_mem->VrFlowToIp(k_flow, &sip, &dip);
188  string action_str;
189  string flag_str, tcp_flags;
190  data.set_index((unsigned int)index);
191  data.set_sport((unsigned)ntohs(k_flow->fe_key.flow4_sport));
192  data.set_dport((unsigned)ntohs(k_flow->fe_key.flow4_dport));
193  data.set_sip(sip.to_string());
194  data.set_dip(dip.to_string());
195  data.set_vrf_id(k_flow->fe_vrf);
196  data.set_proto(k_flow->fe_key.flow4_proto);
197  data.set_nhid(k_flow->fe_key.flow_nh_id);
198  switch (k_flow->fe_action) {
199  case VR_FLOW_ACTION_FORWARD:
200  action_str.assign("FORWARD");
201  break;
202  case VR_FLOW_ACTION_DROP:
203  action_str.assign("DROP");
204  action_drop = true;
205  break;
206  case VR_FLOW_ACTION_NAT:
207  action_str.assign("NAT");
208  break;
209  case VR_FLOW_ACTION_HOLD:
210  action_str.assign("HOLD");
211  break;
212  default:
213  action_str.assign("INVALID");
214  }
215  data.set_action(action_str);
216  bool assigned = false;
217  UpdateFlagStr(flag_str, assigned, false, k_flow->fe_flags,
218  VR_FLOW_FLAG_ACTIVE);
219  UpdateFlagStr(flag_str, assigned, false, k_flow->fe_flags,
220  VR_FLOW_FLAG_MIRROR);
221  UpdateFlagStr(flag_str, assigned, false, k_flow->fe_flags,
222  VR_FLOW_FLAG_VRFT);
223  UpdateFlagStr(flag_str, assigned, false, k_flow->fe_flags,
224  VR_FLOW_FLAG_SNAT);
225  UpdateFlagStr(flag_str, assigned, false, k_flow->fe_flags,
226  VR_FLOW_FLAG_SPAT);
227  UpdateFlagStr(flag_str, assigned, false, k_flow->fe_flags,
228  VR_FLOW_FLAG_DNAT);
229  UpdateFlagStr(flag_str, assigned, false, k_flow->fe_flags,
230  VR_FLOW_FLAG_SPAT);
231  UpdateFlagStr(flag_str, assigned, false, k_flow->fe_flags,
232  VR_FLOW_FLAG_LINK_LOCAL);
233  UpdateFlagStr(flag_str, assigned, false, k_flow->fe_flags,
234  VR_FLOW_FLAG_EVICTED);
235  UpdateFlagStr(flag_str, assigned, false, k_flow->fe_flags,
236  VR_FLOW_FLAG_EVICT_CANDIDATE);
237  UpdateFlagStr(flag_str, assigned, false, k_flow->fe_flags,
238  VR_FLOW_FLAG_NEW_FLOW);
239  UpdateFlagStr(flag_str, assigned, false, k_flow->fe_flags,
240  VR_FLOW_FLAG_MODIFIED);
241  UpdateFlagStr(flag_str, assigned, false, k_flow->fe_flags, VR_RFLOW_VALID);
242  data.set_flags(flag_str);
243 
244  if (k_flow->fe_key.flow4_proto == IPPROTO_TCP) {
245  assigned = false;
246  UpdateFlagStr(tcp_flags, assigned, true, k_flow->fe_tcp_flags,
247  VR_FLOW_TCP_SYN);
248  UpdateFlagStr(tcp_flags, assigned, true, k_flow->fe_tcp_flags,
249  VR_FLOW_TCP_SYN_R);
250  UpdateFlagStr(tcp_flags, assigned, true, k_flow->fe_tcp_flags,
251  VR_FLOW_TCP_ESTABLISHED);
252  UpdateFlagStr(tcp_flags, assigned, true, k_flow->fe_tcp_flags,
253  VR_FLOW_TCP_ESTABLISHED_R);
254  UpdateFlagStr(tcp_flags, assigned, true, k_flow->fe_tcp_flags,
255  VR_FLOW_TCP_FIN);
256  UpdateFlagStr(tcp_flags, assigned, true, k_flow->fe_tcp_flags,
257  VR_FLOW_TCP_FIN_R);
258  UpdateFlagStr(tcp_flags, assigned, true, k_flow->fe_tcp_flags,
259  VR_FLOW_TCP_RST);
260  UpdateFlagStr(tcp_flags, assigned, true, k_flow->fe_tcp_flags,
261  VR_FLOW_TCP_HALF_CLOSE);
262  UpdateFlagStr(tcp_flags, assigned, true, k_flow->fe_tcp_flags,
263  VR_FLOW_TCP_DEAD);
264  data.set_tcp_flags(tcp_flags);
265  }
266  if (action_drop) {
267  data.set_drop_reason(DropCodeToStr(k_flow->fe_drop_reason));
268  }
269  data.set_underlay_udp_sport(k_flow->fe_udp_src_port);
270  data.set_rflow(k_flow->fe_rflow);
271  data.set_d_vrf_id(k_flow->fe_dvrf);
272  data.set_bytes(k_flow->fe_stats.flow_bytes);
273  data.set_pkts(k_flow->fe_stats.flow_packets);
274  if (k_flow->fe_mirror_id != VR_MAX_MIRROR_INDICES) {
275  data.set_mirror_id(k_flow->fe_mirror_id);
276  }
277  if (k_flow->fe_sec_mirror_id != VR_MAX_MIRROR_INDICES) {
278  data.set_sec_mirror_id(k_flow->fe_sec_mirror_id);
279  }
280  if (k_flow->fe_ecmp_nh_index != -1) {
281  data.set_ecmp_index(k_flow->fe_ecmp_nh_index);
282  }
283  data.set_ttl(k_flow->fe_ttl);
284  data.set_qos_id(k_flow->fe_qos_id);
285  data.set_gen_id(k_flow->fe_gen_id);
286  data.set_tcp_seq(k_flow->fe_tcp_seq);
287  data.set_oflow_bytes(k_flow->fe_stats.flow_bytes_oflow);
288  data.set_oflow_packets(k_flow->fe_stats.flow_packets_oflow);
289  data.set_underlay_gw_index(k_flow->fe_underlay_ecmp_index);
290  list.push_back(data);
291 }
292 
294  int count = 0;
295  const vr_flow_entry *k_flow;
296  KFlowResp *resp;
297 
298  KSyncFlowMemory *ksync_obj = agent_->ksync()->ksync_flow_memory();
299 
300  if (flow_idx_ != -1) {
301  k_flow = ksync_obj->GetKernelFlowEntry(flow_idx_, false);
302  if (k_flow) {
303  resp = new KFlowResp();
304  vector<KFlowInfo> &list = const_cast<std::vector<KFlowInfo>&>
305  (resp->get_flow_list());
306  SetFlowData(list, k_flow, flow_idx_);
307  SendResponse(resp);
308  } else {
309  ErrResp *resp = new ErrResp();
310  resp->set_context(response_context_);
311  resp->Response();
312  }
313  return true;
314  }
315  uint32_t idx = flow_iteration_key_;
316  uint32_t max_flows = ksync_obj->table_entries_count();
317 
318  resp = new KFlowResp();
319  vector<KFlowInfo> &list = const_cast<std::vector<KFlowInfo>&>
320  (resp->get_flow_list());
321  while(idx < max_flows) {
322  k_flow = ksync_obj->GetKernelFlowEntry(idx, false);
323  idx++;
324  if (k_flow) {
325  if((k_flow->fe_flags & VR_FLOW_FLAG_EVICTED) && (!evicted_)) {
326  continue;
327  }
328  count++;
329  SetFlowData(list, k_flow, (idx-1));
330  }
331  if (count == KState::kMaxEntriesPerResponse) {
332  if (idx != max_flows) {
333  SetFlowHandle(resp, idx);
334  } else {
335  SetFlowHandle(resp, 0);
336  }
337  SendResponse(resp);
338  return true;
339  }
340  }
341  SetFlowHandle(resp, 0);
342  SendResponse(resp);
343 
344  return true;
345 }
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h:178
void SetFlowHandle(KFlowResp *resp, const uint32_t idx) const
Definition: flow_kstate.cc:172
uint32_t flow_iteration_key_
Definition: flow_kstate.h:24
boost::asio::ip::address IpAddress
Definition: address.h:13
bool stringToInteger(const std::string &str, NumberType &num)
Definition: string_util.h:71
std::string response_context_
Definition: flow_kstate.h:21
void SetFlowData(std::vector< KFlowInfo > &list, const vr_flow_entry *k_flow, int index) const
Definition: flow_kstate.cc:180
const std::string FlagToStr(unsigned int flag) const
Definition: flow_kstate.cc:41
static void VrFlowToIp(const vr_flow_entry *kflow, IpAddress *sip, IpAddress *dip)
const std::string TcpFlagToStr(unsigned int flag) const
Definition: flow_kstate.cc:74
int flow_idx_
Definition: flow_kstate.h:22
static const std::string integerToString(const NumberType &num)
Definition: string_util.h:19
Definition: agent.h:358
KSync * ksync() const
Definition: agent.cc:901
virtual bool Run()
Code to execute. Returns true if task is completed. Return false to reschedule the task...
Definition: flow_kstate.cc:293
uint32_t table_entries_count()
Definition: ksync_memory.h:57
const vr_flow_entry * GetKernelFlowEntry(uint32_t idx, bool ignore_active_status) const
static const int kMaxEntriesPerResponse
Definition: kstate.h:26
Agent * agent_
Definition: flow_kstate.h:26
FlowKState(Agent *agent, const std::string &resp_ctx, int idx)
const std::string DropCodeToStr(uint8_t drop_code) const
Definition: flow_kstate.cc:117
KSyncFlowMemory * ksync_flow_memory() const
Definition: ksync_init.h:58
Task is a wrapper over tbb::task to support policies.
Definition: task.h:86
virtual void SendResponse(KFlowResp *resp) const
Definition: flow_kstate.cc:36
void UpdateFlagStr(std::string &str, bool &set, bool tcp, unsigned sflag, unsigned cflag) const
Definition: flow_kstate.cc:99
bool evicted_
Definition: flow_kstate.h:23