FD.io VPP  v17.04-9-g99c0734
Vector Packet Processing
l2sess.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16  *------------------------------------------------------------------
17  * l2sess.c - simple MAC-swap API / debug CLI handling
18  *------------------------------------------------------------------
19  */
20 
21 #include <vnet/vnet.h>
22 #include <vnet/plugin/plugin.h>
23 #include <acl/l2sess.h>
24 
25 #include <vlibapi/api.h>
26 #include <vlibmemory/api.h>
27 #include <vlibsocket/api.h>
28 #include <vppinfra/timing_wheel.h>
29 
30 #include <vnet/l2/l2_output.h>
31 #include <vnet/l2/l2_input.h>
32 
33 void
35 {
36 #define _(node_name, node_var, is_out, is_ip6, is_track) \
37  if (is_out) \
38  feat_bitmap_init_next_nodes(vm, node_var.index, L2OUTPUT_N_FEAT, \
39  l2output_get_feat_names (), \
40  sm->node_var ## _feat_next_node_index); \
41  else \
42  feat_bitmap_init_next_nodes(vm, node_var.index, L2INPUT_N_FEAT, \
43  l2input_get_feat_names (), \
44  sm->node_var ## _feat_next_node_index);
45 
47 #undef _
48 }
49 
50 void
52  u8 * prev_node_name, int add_output_nodes)
53 {
54  vlib_node_t *n;
55  n = vlib_get_node_by_name (vm, prev_node_name);
56 #define _(node_name, node_var, is_out, is_ip6, is_track) \
57  if (is_out == add_output_nodes) { \
58  u32 idx = vlib_node_add_next_with_slot(vm, n->index, node_var.index, ~0); \
59  if (is_track) { \
60  sm->next_slot_track_node_by_is_ip6_is_out[is_ip6][is_out] = idx; \
61  } \
62  }
64 #undef _
65 }
66 
67 void
69 {
72 
74 
75  l2sess_add_our_next_nodes (vm, sm, (u8 *) "l2-input-classify", 0);
76  l2sess_add_our_next_nodes (vm, sm, (u8 *) "l2-output-classify", 1);
77 
78 }
79 
80 static char *
81 get_l4_proto_str (int is_ip6, uint8_t l4_proto)
82 {
83  switch (l4_proto)
84  {
85  case 6:
86  return "tcp";
87  case 17:
88  return "udp";
89  case 1:
90  return "icmp";
91  case 58:
92  return "icmp6";
93  default:
94  return "<?l4-unknown?>";
95  }
96 }
97 
98 static clib_error_t *
100  unformat_input_t * input, vlib_cli_command_t * cmd)
101 {
102  l2sess_main_t *sm = &l2sess_main;
103  clib_time_t *ct = &vm->clib_time;
104  l2s_session_t *s;
105  u64 now = clib_cpu_time_now ();
106 
107  vlib_cli_output (vm, "Timing wheel info: \n%U", format_timing_wheel,
108  &sm->timing_wheel, 255);
109 
110  pool_foreach (s, sm->sessions, (
111  {
112  f64 ctime =
113  (now -
114  s->create_time) * ct->seconds_per_clock;
115  f64 atime0 =
116  (now -
117  s->side[0].active_time) *
118  ct->seconds_per_clock;
119  f64 atime1 =
120  (now -
121  s->side[1].active_time) *
122  ct->seconds_per_clock;
123 /*
124  f64 ctime = (s->create_time - vm->cpu_time_main_loop_start) * ct->seconds_per_clock;
125  f64 atime0 = (s->side[0].active_time - vm->cpu_time_main_loop_start) * ct->seconds_per_clock;
126  f64 atime1 = (s->side[1].active_time - vm->cpu_time_main_loop_start) * ct->seconds_per_clock;
127 */
128  u8 * out0 =
129  format (0,
130  "%5d: create time: %U pkts/bytes/active time: [ %ld %ld %U : %ld %ld %U ]\n",
131  (s - sm->sessions),
132  format_time_interval, "h:m:s:u",
133  ctime, s->side[0].n_packets,
134  s->side[0].n_bytes,
135  format_time_interval, "h:m:s:u",
136  atime0, s->side[1].n_packets,
137  s->side[1].n_bytes,
138  format_time_interval, "h:m:s:u",
139  atime1); u8 * out1 = 0;
140  if (s->is_ip6)
141  {
142  out1 =
143  format (0, "%s %U :%u <-> %U :%u",
144  get_l4_proto_str (s->is_ip6,
145  s->l4_proto),
146  format_ip6_address,
147  &s->side[0].addr.ip6,
148  s->side[0].port,
149  format_ip6_address,
150  &s->side[1].addr.ip6,
151  s->side[1].port);}
152  else
153  {
154  out1 =
155  format (0, "%s %U :%u <-> %U :%u",
156  get_l4_proto_str (s->is_ip6,
157  s->l4_proto),
158  format_ip4_address,
159  &s->side[0].addr.ip4,
160  s->side[0].port,
161  format_ip4_address,
162  &s->side[1].addr.ip4,
163  s->side[1].port);}
164  vlib_cli_output (vm, "%s %s", out0,
165  out1); vec_free (out0);
166  vec_free (out1);}
167  ));
168  return 0;
169 }
170 
171 static clib_error_t *
173  unformat_input_t * input,
174  vlib_cli_command_t * cmd)
175 {
176  l2sess_main_t *sm = &l2sess_main;
177 
178  vlib_cli_output (vm, "Timing wheel info: \n%U", format_timing_wheel,
179  &sm->timing_wheel, 255);
180  vlib_cli_output (vm, "session pool len: %d, pool elts: %d",
181  pool_len (sm->sessions), pool_elts (sm->sessions));
182  vlib_cli_output (vm,
183  "attempted to delete sessions which were already free: %d",
185  return 0;
186 }
187 
188 
189 /* *INDENT-OFF* */
190 VLIB_CLI_COMMAND (l2sess_show_command, static) = {
191  .path = "show l2sess",
192  .short_help = "show l2sess",
193  .function = l2sess_show_command_fn,
194 };
195 
196 VLIB_CLI_COMMAND (l2sess_show_count_command, static) = {
197  .path = "show l2sess count",
198  .short_help = "show l2sess count",
199  .function = l2sess_show_count_command_fn,
200 };
201 /* *INDENT-OFF* */
202 
203 static inline u64
205 {
206  return (u64)(((f64)sec)/ct->seconds_per_clock);
207 }
208 
210 {
211  l2sess_main_t * sm = &l2sess_main;
212  clib_error_t * error = 0;
213  u64 cpu_time_now = clib_cpu_time_now();
214 
215 
216  clib_time_t *ct = &vm->clib_time;
220 
221  /* The min sched time of 10e-1 causes erroneous behavior... */
222  sm->timing_wheel.min_sched_time = 10e-2;
223  sm->timing_wheel.max_sched_time = 3600.0*48.0;
224  timing_wheel_init (&sm->timing_wheel, cpu_time_now, vm->clib_time.clocks_per_second);
227  /* Pre-allocate expired nodes. */
229 
232 
233  return error;
234 }
235 
237 
238 
void timing_wheel_init(timing_wheel_t *w, u64 current_cpu_time, f64 cpu_clocks_per_second)
Definition: timing_wheel.c:21
static clib_error_t * l2sess_show_count_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: l2sess.c:172
f64 clocks_per_second
Definition: time.h:53
static u64 clib_cpu_time_now(void)
Definition: time.h:73
clib_time_t clib_time
Definition: main.h:62
#define vec_alloc(V, N)
Allocate space for N more elements (no header, unspecified alignment)
Definition: vec.h:279
#define pool_len(p)
Number of elements in pool vector.
Definition: pool.h:121
static char * get_l4_proto_str(int is_ip6, uint8_t l4_proto)
Definition: l2sess.c:81
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:376
void l2sess_init_next_features(vlib_main_t *vm, l2sess_main_t *sm)
Definition: l2sess.c:34
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
format_function_t format_timing_wheel
Definition: timing_wheel.h:142
unsigned long u64
Definition: types.h:89
timing_wheel_t timing_wheel
Definition: l2sess.h:126
struct _unformat_input_t unformat_input_t
l2s_session_t * sessions
Definition: l2sess.h:118
f64 seconds_per_clock
Definition: time.h:57
#define foreach_l2sess_node
Definition: l2sess.h:32
static clib_error_t * l2sess_init(vlib_main_t *vm)
Definition: l2sess.c:209
vlib_main_t * vm
Definition: buffer.c:276
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:340
foreach_l2sess_node l2_output_next_nodes_st output_next_nodes
Definition: l2sess.h:101
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
static u64 time_sec_to_clock(clib_time_t *ct, f64 sec)
Definition: l2sess.c:204
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
u64 timer_wheel_next_expiring_time
Definition: l2sess.h:128
u64 timer_wheel_tick
Definition: l2sess.h:129
u32 * data_from_advancing_timing_wheel
Definition: l2sess.h:127
l2sess_main_t l2sess_main
Definition: l2sess.h:139
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
#define UDP_SESSION_IDLE_TIMEOUT_SEC
Definition: l2sess.h:82
#define TCP_SESSION_IDLE_TIMEOUT_SEC
Definition: l2sess.h:83
double f64
Definition: types.h:142
static clib_error_t * l2sess_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: l2sess.c:99
unsigned char u8
Definition: types.h:56
void l2sess_setup_nodes(void)
Definition: l2sess.c:68
u64 udp_session_idle_timeout
Definition: l2sess.h:123
u64 counter_attempted_delete_free_session
Definition: l2sess.h:136
void l2sess_add_our_next_nodes(vlib_main_t *vm, l2sess_main_t *sm, u8 *prev_node_name, int add_output_nodes)
Definition: l2sess.c:51
u64 tcp_session_transient_timeout
Definition: l2sess.h:121
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:577
static void l2output_init_output_node_vec(u32 **output_node_index_vec)
Definition: l2_output.h:168
u64 tcp_session_idle_timeout
Definition: l2sess.h:122
#define TCP_SESSION_TRANSIENT_TIMEOUT_SEC
Definition: l2sess.h:84
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109