FD.io VPP  v16.06
Vector Packet Processing
l2t.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 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 #include <vnet/vnet.h>
16 #include <vnet/ip/ip.h>
17 #include <vnet/ethernet/ethernet.h>
18 
19 #if DPDK == 0
20 #include <vnet/devices/pci/ixge.h>
21 #else
22 #include <vnet/devices/dpdk/dpdk.h>
23 #endif
24 
25 #include <vppinfra/error.h>
26 #include <vppinfra/hash.h>
27 #include <app/l2t.h>
28 
30 
31 /* $$$$ unused?
32  * get_interface_ethernet_address
33  * paints the ethernet address for a given interface
34  * into the supplied destination
35  */
37  u8 *dst, u32 sw_if_index)
38 {
42 
43  hi = vnet_get_sup_hw_interface (lm->vnet_main, sw_if_index);
45  clib_memcpy (dst, ei->address, sizeof (ei->address));
46 }
47 
48 /* packet trace format function */
49 u8 * format_l2t_trace (u8 * s, va_list * args)
50 {
51  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
52  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
53  l2t_trace_t * t = va_arg (*args, l2t_trace_t *);
54 
55  if (t->is_user_to_network)
56  s = format (s, "L2T: %U (client) -> %U (our) session %d",
59  t->session_index);
60  else
61  s = format (s, "L2T: %U (our) -> %U (client) session %d)",
64  t->session_index);
65  return s;
66 }
67 
68 u8 * format_l2t_session (u8 * s, va_list * args)
69 {
70  l2t_session_t * session = va_arg (*args, l2t_session_t *);
71  l2t_main_t * lm = &l2t_main;
74 
75  s = format (s, "[%d] %U (our) %U (client) vlan-id %d rx_sw_if_index %d\n",
76  session - lm->sessions,
79  clib_net_to_host_u16(session->vlan_id), session->sw_if_index);
80 
81  s = format (s, " local cookie %llx remote cookie %llx\n",
82  clib_net_to_host_u64 (session->local_cookie),
83  clib_net_to_host_u64 (session->remote_cookie));
84 
85  if (session->cookie_flags & L2TP_COOKIE_ROLLOVER_LOCAL) {
86  s = format (s, " local rollover cookie %llx\n",
87  clib_net_to_host_u64 (session->lcl_ro_cookie));
88  }
89 
90  s = format (s, " local session-id %d remote session-id %d\n",
91  clib_net_to_host_u32 (session->local_session_id),
92  clib_net_to_host_u32 (session->remote_session_id));
93 
94  s = format (s, " l2 specific sublayer %s\n",
95  session->l2_sublayer_present ? "preset" : "absent");
96 
97  counter_index =
100 
101  vlib_get_combined_counter (&lm->counter_main, counter_index, &v);
102  if (v.packets != 0)
103  s = format (s, " user-to-net: %llu pkts %llu bytes\n",
104  v.packets, v.bytes);
105 
106  vlib_get_combined_counter (&lm->counter_main, counter_index+1, &v);
107 
108  if (v.packets != 0)
109  s = format (s, " net-to-user: %llu pkts %llu bytes\n",
110  v.packets, v.bytes);
111  return s;
112 }
113 
114 static clib_error_t *
116  unformat_input_t * input,
117  vlib_cli_command_t * cmd)
118 {
119  l2t_main_t *lm = &l2t_main;
120 
121  vlib_cli_output (vm, "%d active sessions\n", pool_elts (lm->sessions));
122 
123  return 0;
124 }
125 
126 static VLIB_CLI_COMMAND (show_session_summary_command) = {
127  .path = "show session",
128  .short_help = "show session summary",
130 };
131 
132 static clib_error_t *
134  unformat_input_t * input,
135  vlib_cli_command_t * cmd)
136 {
137  l2t_session_t *session;
138  l2t_main_t *lm = &l2t_main;
139 
140  pool_foreach (session, lm->sessions,
141  ({
142  vlib_cli_output (vm, "%U", format_l2t_session, session);
143  }));
144 
145  return 0;
146 }
147 
148 static VLIB_CLI_COMMAND (show_session_detail_command) = {
149  .path = "show session detail",
150  .short_help = "show session table detail",
151  .function = show_session_detail_command_fn,
152 };
153 
154 static clib_error_t *
156  unformat_input_t * input,
157  vlib_cli_command_t * cmd)
158 {
159  l2t_session_t *session;
160  l2t_main_t *lm = &l2t_main;
161  u32 session_index;
163  u32 nincr=0;
164 
165  pool_foreach (session, lm->sessions,
166  ({
167  session_index = session - lm->sessions;
168  counter_index =
169  session_index_to_counter_index (session_index,
170  SESSION_COUNTER_USER_TO_NETWORK);
171  vlib_increment_combined_counter (&lm->counter_main,
172  counter_index,
173  1/*pkt*/, 1111 /*bytes*/);
174  vlib_increment_combined_counter (&lm->counter_main,
175  counter_index+1,
176  1/*pkt*/, 2222 /*bytes*/);
177  nincr++;
178 
179  }));
180  vlib_cli_output (vm, "Incremented %d active counters\n", nincr);
181 
182  return 0;
183 }
184 
185 static VLIB_CLI_COMMAND (test_counters_command) = {
186  .path = "test counters",
187  .short_help = "increment all active counters",
188  .function = test_counters_command_fn,
189 };
190 
191 static clib_error_t *
193  unformat_input_t * input,
194  vlib_cli_command_t * cmd)
195 {
196  l2t_session_t *session;
197  l2t_main_t *lm = &l2t_main;
198  u32 session_index;
200  u32 nincr=0;
201 
202  pool_foreach (session, lm->sessions,
203  ({
204  session_index = session - lm->sessions;
205  counter_index =
206  session_index_to_counter_index (session_index,
207  SESSION_COUNTER_USER_TO_NETWORK);
208  vlib_zero_combined_counter (&lm->counter_main, counter_index);
209  vlib_zero_combined_counter (&lm->counter_main, counter_index+1);
210  nincr++;
211 
212  }));
213  vlib_cli_output (vm, "Cleared %d active counters\n", nincr);
214 
215  return 0;
216 }
217 
218 static VLIB_CLI_COMMAND (clear_counters_command) = {
219  .path = "clear counters",
220  .short_help = "clear all active counters",
221  .function = clear_counters_command_fn,
222 };
223 
224 static clib_error_t *
226  unformat_input_t * input,
227  vlib_cli_command_t * cmd)
228 {
229  ip6_address_t client_address, our_address;
230  ip6_address_t * dst_address_copy, * src_address_copy;
231  unformat_input_t _line_input, * line_input = &_line_input;
232  u32 vlan_id;
233  u32 sw_if_index = (u32)~0;
234  l2t_main_t *lm = &l2t_main;
235  l2t_session_t *s;
236  uword *p;
238  vnet_sw_interface_t * si;
239  u32 next_index;
240  uword vlan_and_sw_if_index_key;
242  u64 local_cookie = (u64)~0, remote_cookie = (u64)~0;
243  u32 local_session_id = 1, remote_session_id = 1;
244  int our_address_set = 0, client_address_set = 0;
245  int l2_sublayer_present = 0;
246 
247  /* Get a line of input. */
248  if (! unformat_user (input, unformat_line_input, line_input))
249  return 0;
250 
251  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
252  if (unformat (line_input, "client %U",
253  unformat_ip6_address, &client_address))
254  client_address_set = 1;
255  else if (unformat (line_input, "our %U",
256  unformat_ip6_address, &our_address))
257  our_address_set = 1;
258  else if (unformat (line_input, "vlan %d", &vlan_id))
259  ;
260  else if (unformat (line_input, "l2-interface %U",
262  vnet_get_main(), &sw_if_index))
263  ;
264  else if (unformat (line_input, "interface %U",
266  vnet_get_main(), &sw_if_index))
267  ;
268  else if (unformat (line_input, "local-cookie %llx", &local_cookie))
269  ;
270  else if (unformat (line_input, "remote-cookie %llx", &remote_cookie))
271  ;
272  else if (unformat (line_input, "local-session-id %d",
273  &local_session_id))
274  ;
275  else if (unformat (line_input, "remote-session-id %d",
276  &remote_session_id))
277  ;
278  else if (unformat (line_input, "l2-sublayer-present"))
279  l2_sublayer_present = 1;
280  else
281  return clib_error_return (0, "parse error: '%U'",
282  format_unformat_error, line_input);
283  }
284 
285  unformat_free (line_input);
286 
287  if (sw_if_index == (u32)~0)
288  return clib_error_return (0, "l2-interface not specified");
289  if (our_address_set == 0)
290  return clib_error_return (0, "our address not specified");
291  if (client_address_set == 0)
292  return clib_error_return (0, "client address not specified");
293 
294  remote_session_id = clib_host_to_net_u32 (remote_session_id);
295  local_session_id = clib_host_to_net_u32 (local_session_id);
296 
297  switch (lm->lookup_type) {
299  p = hash_get_mem (lm->session_by_src_address, &client_address);
300  if (p)
301  return clib_error_return
302  (0, "Session w/ client address %U already exists",
303  format_ip6_address, &client_address);
304  break;
305 
307  p = hash_get_mem (lm->session_by_dst_address, &our_address);
308  if (p)
309  return clib_error_return
310  (0, "Session w/ our address %U already exists",
311  format_ip6_address, &our_address);
312  break;
313 
315  p = hash_get (lm->session_by_session_id, local_session_id);
316  if (p)
317  return clib_error_return
318  (0,
319  "Session w/ local session id %d already exists",
320  clib_net_to_host_u32 (local_session_id));
321  break;
322 
323  default:
324  ASSERT(0);
325  }
326 
327  pool_get (lm->sessions, s);
328  memset (s, 0, sizeof (*s));
329  clib_memcpy (&s->our_address, &our_address, sizeof (s->our_address));
330  clib_memcpy (&s->client_address, &client_address, sizeof (s->client_address));
331  s->sw_if_index = sw_if_index;
332  s->vlan_id = clib_host_to_net_u16 (vlan_id);
333  s->local_cookie = clib_host_to_net_u64 (local_cookie);
334  l2tp_session_set_remote_cookie (s, remote_cookie);
335  s->local_session_id = local_session_id;
336  s->remote_session_id = remote_session_id;
337  s->l2_sublayer_present = l2_sublayer_present;
338 
339  hi = vnet_get_sup_hw_interface (lm->vnet_main, sw_if_index);
340  si = vnet_get_sup_sw_interface (lm->vnet_main, sw_if_index);
341 
342  next_index = vlib_node_add_next (vm, l2t_ip6_node.index,
343  hi->output_node_index);
344  s->l2_output_next_index = next_index;
345  s->l2_output_sw_if_index = si->sw_if_index;
346 
347  /* Setup hash table entries */
348  switch (lm->lookup_type) {
350  src_address_copy = clib_mem_alloc (sizeof (*src_address_copy));
351  clib_memcpy (src_address_copy, &client_address, sizeof (*src_address_copy));
352  hash_set_mem (lm->session_by_src_address, src_address_copy,
353  s - lm->sessions);
354  break;
356  dst_address_copy = clib_mem_alloc (sizeof (*dst_address_copy));
357  clib_memcpy (dst_address_copy, &our_address, sizeof (*dst_address_copy));
358  hash_set_mem (lm->session_by_dst_address, dst_address_copy,
359  s - lm->sessions);
360  break;
362  hash_set (lm->session_by_session_id, local_session_id,
363  s - lm->sessions);
364  break;
365 
366  default:
367  ASSERT(0);
368  }
369 
370  vlan_and_sw_if_index_key = ((uword)(s->vlan_id)<<32) | sw_if_index;
371  hash_set (lm->session_by_vlan_and_rx_sw_if_index,
372  vlan_and_sw_if_index_key, s - lm->sessions);
373 
374  /* validate counters */
375  counter_index =
378  vlib_validate_counter (&lm->counter_main, counter_index);
379  vlib_validate_counter (&lm->counter_main, counter_index+1);
380 
381  /* Set promiscuous mode on the l2 interface */
385  l2t_l2_node.index);
386  return 0;
387 }
388 
389 static VLIB_CLI_COMMAND (l2tp_session_add_command) = {
390  .path = "l2tp session add",
391  .short_help =
392  "l2tp session add client <ip6> our <ip6> vlan <id> local-cookie <hex> remote-cookie <hex> local-session <dec> remote-session <dec> l2-interface <int>",
393  .function = l2tp_session_add_command_fn,
394 };
395 
396 static clib_error_t *
398  unformat_input_t * input,
399  vlib_cli_command_t * cmd)
400 {
401  l2t_main_t *lm = &l2t_main;
402  u32 session_index;
403  l2t_session_t *s;
404  hash_pair_t * hp;
405  void *key;
406  uword vlan_and_sw_if_index_key;
407 
408  if (!unformat (input, "%d", &session_index))
409  return clib_error_return (0, "missing session index: '%U'",
410  format_unformat_error, input);
411 
412  if (pool_is_free_index (lm->sessions, session_index))
413  return clib_error_return (0, "session %d not in use", session_index);
414 
415  s = pool_elt_at_index (lm->sessions, session_index);
416 
417  switch (lm->lookup_type) {
420  if (hp) {
421  key = (void *)(hp->key);
423  clib_mem_free (key);
424  } else
425  clib_warning ("session %d src address key %U AWOL",
426  s - lm->sessions,
428  break;
429 
432  if (hp) {
433  key = (void *)(hp->key);
435  clib_mem_free (key);
436  } else
437  clib_warning ("session %d dst address key %U AWOL",
438  s - lm->sessions,
440  break;
441 
444  break;
445 
446  default:
447  ASSERT(0);
448  }
449 
450  vlan_and_sw_if_index_key = ((uword)(s->vlan_id)<<32) | s->sw_if_index;
451 
452  hash_unset (lm->session_by_vlan_and_rx_sw_if_index, vlan_and_sw_if_index_key);
453 
454  pool_put (lm->sessions, s);
455  return 0;
456 }
457 
458 static VLIB_CLI_COMMAND (l2tp_session_del_command) = {
459  .path = "l2tp session delete",
460  .short_help =
461  "l2tp session delete <session-id>",
462  .function = l2tp_session_del_command_fn,
463 };
464 
465 static clib_error_t *
467  unformat_input_t * input,
468  vlib_cli_command_t * cmd)
469 {
470  l2t_main_t *lm = &l2t_main;
471  u32 session_index;
472  l2t_session_t *s;
473  u64 lcl_ro_cookie = (u64)~0, rem_ro_cookie = (u64)~0;
474  u8 cookie_flags = 0;
475 
476  if (!unformat (input, "%d", &session_index))
477  return clib_error_return (0, "missing session index: '%U'",
478  format_unformat_error, input);
479 
480  if (pool_is_free_index (lm->sessions, session_index))
481  return clib_error_return (0, "session %d not in use", session_index);
482 
483  s = pool_elt_at_index (lm->sessions, session_index);
484 
485  if (unformat (input, "commit")) {
486  if (!s->cookie_flags) {
487  return clib_error_return (0,
488  "no rollover cookie ready to commit");
489  } else {
490  l2tp_session_cookie_commit (s);
491  return 0;
492  }
493  }
494  if (!unformat (input, "rollover"))
495  return clib_error_return (0, "missing 'commit|rollover': '%U'",
496  format_unformat_error, input);
497  if (unformat (input, "local %llx", &lcl_ro_cookie)) {
498  cookie_flags |= L2TP_COOKIE_ROLLOVER_LOCAL;
499  l2tp_session_set_local_rollover_cookie (s, lcl_ro_cookie);
500  }
501  if (unformat (input, "remote %llx", &rem_ro_cookie)) {
502  cookie_flags |= L2TP_COOKIE_ROLLOVER_REMOTE;
503  l2tp_session_set_remote_cookie (s, rem_ro_cookie);
504  }
505  if (!cookie_flags)
506  return clib_error_return (0, "no rollover cookie specified");
507 
508  return 0;
509 }
510 
511 static VLIB_CLI_COMMAND (l2tp_session_cookie_command) = {
512  .path = "l2tp session cookie",
513  .short_help =
514  "l2tp session cookie <session id> commit|rollover [local <hex>] [remote <hex>]",
515  .function = l2tp_session_cookie_command_fn,
516 };
int is_user_to_network
Definition: l2tp.h:81
u8 cookie_flags
Definition: l2tp.h:44
u64 local_cookie[2]
Definition: l2tp.h:33
vmrglw vmrglh hi
#define hash_set(h, key, value)
Definition: hash.h:237
ip6_address_t client_address
Definition: l2tp.h:84
#define CLIB_UNUSED(x)
Definition: clib.h:79
static clib_error_t * clear_counters_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: l2t.c:192
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:942
#define hash_unset(h, key)
Definition: hash.h:243
format_function_t format_ip6_address
Definition: format.h:87
vlib_node_registration_t l2t_ip6_node
Definition: l2t_ip6.c:66
ethernet_main_t * ethernet_get_main(vlib_main_t *vm)
Definition: init.c:95
always_inline void clib_mem_free(void *p)
Definition: mem.h:149
int vnet_hw_interface_rx_redirect_to_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Definition: interface.c:901
uword * session_by_session_id
Definition: l2tp.h:60
always_inline void unformat_free(unformat_input_t *i)
Definition: format.h:160
#define UNFORMAT_END_OF_INPUT
Definition: format.h:142
static clib_error_t * l2tp_session_add_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: l2t.c:225
ip6_address_t our_address
Definition: l2tp.h:27
static clib_error_t * l2tp_session_cookie_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: l2t.c:466
static clib_error_t * show_session_summary_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: l2t.c:115
#define hash_set_mem(h, key, value)
Definition: hash.h:257
#define hash_get_pair_mem(h, key)
Definition: hash.h:254
unformat_function_t unformat_vnet_sw_interface
#define pool_get(P, E)
Definition: pool.h:186
u64 remote_cookie
Definition: l2tp.h:34
static u32 session_index_to_counter_index(u32 session_index, u32 counter_id)
Definition: l2tp.h:96
ip6_address_t client_address
Definition: l2tp.h:28
always_inline uword unformat_check_input(unformat_input_t *i)
Definition: format.h:168
vnet_main_t * vnet_get_main(void)
Definition: misc.c:45
#define pool_foreach(VAR, POOL, BODY)
Definition: pool.h:328
static clib_error_t * show_session_detail_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: l2t.c:133
always_inline uword pool_elts(void *v)
Definition: pool.h:97
#define clib_warning(format, args...)
Definition: error.h:59
unsigned long u64
Definition: types.h:89
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:953
vlib_node_registration_t l2t_l2_node
(constructor) VLIB_REGISTER_NODE (l2t_l2_node)
Definition: l2t_l2.c:60
void get_interface_ethernet_address(l2t_main_t *lm, u8 *dst, u32 sw_if_index)
Definition: l2t.c:36
#define hash_get(h, key)
Definition: hash.h:231
#define pool_elt_at_index(p, i)
Definition: pool.h:346
#define hash_unset_mem(h, key)
Definition: hash.h:263
static clib_error_t * l2tp_session_del_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: l2t.c:397
u32 local_session_id
Definition: l2tp.h:35
#define pool_put(P, E)
Definition: pool.h:200
static void vlib_get_combined_counter(vlib_combined_counter_main_t *cm, u32 index, vlib_counter_t *result)
Definition: counter.h:248
u8 * format_l2t_session(u8 *s, va_list *args)
Definition: l2t.c:68
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:538
ip6_to_l2_lookup_t lookup_type
Definition: l2tp.h:62
unformat_function_t unformat_ip6_address
Definition: format.h:86
ip6_address_t our_address
Definition: l2tp.h:83
always_inline void * clib_mem_alloc(uword size)
Definition: mem.h:109
u8 * format_l2t_trace(u8 *s, va_list *args)
Definition: l2t.c:49
#define clib_memcpy(a, b, c)
Definition: string.h:63
always_inline vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
#define ETHERNET_INTERFACE_FLAG_ACCEPT_ALL
Definition: ethernet.h:81
#define pool_is_free_index(P, I)
Definition: pool.h:197
always_inline vnet_sw_interface_t * vnet_get_sup_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:150
#define ASSERT(truth)
vlib_main_t * vlib_main
Definition: l2tp.h:74
u32 remote_session_id
Definition: l2tp.h:36
unsigned int u32
Definition: types.h:88
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:87
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
vnet_main_t * vnet_main
Definition: l2tp.h:75
uword * session_by_dst_address
Definition: l2tp.h:59
always_inline uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:919
vlib_combined_counter_main_t counter_main
Definition: l2tp.h:65
u64 uword
Definition: types.h:112
unsigned char u8
Definition: types.h:56
l2t_session_t * sessions
Definition: l2tp.h:55
#define hash_get_mem(h, key)
Definition: hash.h:251
#define clib_error_return(e, args...)
Definition: error.h:112
struct _unformat_input_t unformat_input_t
uword * session_by_src_address
Definition: l2tp.h:58
u8 l2_sublayer_present
Definition: l2tp.h:43
static clib_error_t * test_counters_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: l2t.c:155
l2t_main_t l2t_main
Definition: l2t.c:29
ethernet_interface_t * interfaces
Definition: ethernet.h:201
u32 sw_if_index
Definition: l2tp.h:40
unformat_function_t unformat_line_input
Definition: format.h:279
uword key
Definition: hash.h:148
always_inline u32 counter_index(vlib_main_t *vm, vlib_error_t e)
u32 session_index
Definition: l2tp.h:82
u32 ethernet_set_flags(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: interface.c:243