FD.io VPP  v21.01.1
Vector Packet Processing
ipip_cli.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 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 #include "ipip.h"
17 #include <vppinfra/error.h>
18 #include <vnet/vnet.h>
19 #include <vnet/fib/fib_table.h>
20 
21 static clib_error_t *
23  unformat_input_t * input,
24  vlib_cli_command_t * cmd)
25 {
26  unformat_input_t _line_input, *line_input = &_line_input;
27  ip46_address_t src = ip46_address_initializer, dst =
29  u32 instance = ~0;
30  u32 fib_index = 0;
31  u32 table_id = 0;
32  int rv;
33  u32 num_m_args = 0;
35  clib_error_t *error = NULL;
36  bool ip4_set = false, ip6_set = false;
37  tunnel_mode_t mode = TUNNEL_MODE_P2P;
38  tunnel_encap_decap_flags_t flags = TUNNEL_ENCAP_DECAP_FLAG_NONE;
39 
40  /* Get a line of input. */
41  if (!unformat_user (input, unformat_line_input, line_input))
42  return 0;
43 
44  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
45  {
46  if (unformat (line_input, "instance %d", &instance))
47  ;
48  else
49  if (unformat (line_input, "src %U", unformat_ip4_address, &src.ip4))
50  {
51  num_m_args++;
52  ip4_set = true;
53  }
54  else
55  if (unformat (line_input, "dst %U", unformat_ip4_address, &dst.ip4))
56  {
57  num_m_args++;
58  ip4_set = true;
59  }
60  else
61  if (unformat (line_input, "src %U", unformat_ip6_address, &src.ip6))
62  {
63  num_m_args++;
64  ip6_set = true;
65  }
66  else
67  if (unformat (line_input, "dst %U", unformat_ip6_address, &dst.ip6))
68  {
69  num_m_args++;
70  ip6_set = true;
71  }
72  else if (unformat (line_input, "%U", unformat_tunnel_mode, &mode))
73  {
74  num_m_args++;
75  }
76  else if (unformat (line_input, "outer-table-id %d", &table_id))
77  ;
78  else
79  if (unformat
80  (line_input, "flags %U", unformat_tunnel_encap_decap_flags,
81  &flags))
82  ;
83  else
84  {
85  error =
86  clib_error_return (0, "unknown input `%U'", format_unformat_error,
87  line_input);
88  goto done;
89  }
90  }
91 
92  if (num_m_args < 2)
93  {
94  error = clib_error_return (0, "mandatory argument(s) missing");
95  goto done;
96  }
97  if (ip4_set && ip6_set)
98  {
99  error =
101  "source and destination must be of same address family");
102  goto done;
103  }
104 
105  fib_index = fib_table_find (fib_ip_proto (ip6_set), table_id);
106 
107  if (~0 == fib_index)
108  {
109  rv = VNET_API_ERROR_NO_SUCH_FIB;
110  }
111  else
112  {
114  instance,
115  &src,
116  &dst,
117  fib_index,
118  flags, IP_DSCP_CS0, mode, &sw_if_index);
119  }
120 
121  switch (rv)
122  {
123  case 0:
125  vnet_get_main (), sw_if_index);
126  break;
127  case VNET_API_ERROR_IF_ALREADY_EXISTS:
128  error = clib_error_return (0, "IPIP tunnel already exists...");
129  goto done;
130  case VNET_API_ERROR_NO_SUCH_FIB:
131  error =
132  clib_error_return (0, "outer fib ID %d doesn't exist\n", fib_index);
133  goto done;
134  case VNET_API_ERROR_NO_SUCH_ENTRY:
135  error = clib_error_return (0, "IPIP tunnel doesn't exist");
136  goto done;
137  case VNET_API_ERROR_INSTANCE_IN_USE:
138  error = clib_error_return (0, "Instance is in use");
139  goto done;
140  case VNET_API_ERROR_INVALID_DST_ADDRESS:
141  error =
143  "destination IP address when mode is multi-point");
144  goto done;
145  default:
146  error =
147  clib_error_return (0, "vnet_ipip_add_del_tunnel returned %d", rv);
148  goto done;
149  }
150 
151 done:
152  unformat_free (line_input);
153 
154  return error;
155 }
156 
157 static clib_error_t *
159  unformat_input_t * input,
160  vlib_cli_command_t * cmd)
161 {
162  unformat_input_t _line_input, *line_input = &_line_input;
163  int rv;
164  u32 num_m_args = 0;
165  u32 sw_if_index = ~0;
166  clib_error_t *error = NULL;
167 
168  /* Get a line of input. */
169  if (!unformat_user (input, unformat_line_input, line_input))
170  return 0;
171 
172  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
173  {
174  if (unformat (line_input, "sw_if_index %d", &sw_if_index))
175  num_m_args++;
176  else
177  {
178  error =
179  clib_error_return (0, "unknown input `%U'", format_unformat_error,
180  line_input);
181  goto done;
182  }
183  }
184 
185  if (num_m_args < 1)
186  {
187  error = clib_error_return (0, "mandatory argument(s) missing");
188  goto done;
189  }
190 
191  rv = ipip_del_tunnel (sw_if_index);
192  printf ("RV %d\n", rv);
193 
194 done:
195  unformat_free (line_input);
196 
197  return error;
198 }
199 
200 /* *INDENT-OFF* */
201 VLIB_CLI_COMMAND(create_ipip_tunnel_command, static) = {
202  .path = "create ipip tunnel",
203  .short_help = "create ipip tunnel src <addr> dst <addr> [instance <n>] "
204  "[outer-table-id <ID>] [p2mp]",
205  .function = create_ipip_tunnel_command_fn,
206 };
207 VLIB_CLI_COMMAND(delete_ipip_tunnel_command, static) = {
208  .path = "delete ipip tunnel",
209  .short_help = "delete ipip tunnel sw_if_index <sw_if_index>",
210  .function = delete_ipip_tunnel_command_fn,
211 };
212 /* *INDENT-ON* */
213 
214 static u8 *
215 format_ipip_tunnel (u8 * s, va_list * args)
216 {
217  ipip_tunnel_t *t = va_arg (*args, ipip_tunnel_t *);
218 
219  ip46_type_t type =
221  u32 table_id;
222 
223  table_id = fib_table_get_table_id (t->fib_index,
224  fib_proto_from_ip46 (type));
225  switch (t->mode)
226  {
227  case IPIP_MODE_6RD:
228  s = format (s, "[%d] 6rd src %U ip6-pfx %U/%d ",
229  t->dev_instance,
230  format_ip46_address, &t->tunnel_src, type,
232  t->sixrd.ip6_prefix_len);
233  break;
234  case IPIP_MODE_P2P:
235  s = format (s, "[%d] instance %d src %U dst %U ",
237  format_ip46_address, &t->tunnel_src, type,
238  format_ip46_address, &t->tunnel_dst, type);
239  break;
240  case IPIP_MODE_P2MP:
241  s = format (s, "[%d] instance %d p2mp src %U ",
243  format_ip46_address, &t->tunnel_src, type);
244  break;
245  }
246 
247  s = format (s, "table-ID %d sw-if-idx %d flags [%U] dscp %U",
248  table_id, t->sw_if_index,
250  format_ip_dscp, t->dscp);
251 
252  return s;
253 }
254 
255 static clib_error_t *
257  unformat_input_t * input,
258  vlib_cli_command_t * cmd)
259 {
261  ipip_tunnel_t *t;
262  u32 ti = ~0;
263 
264  if (pool_elts (gm->tunnels) == 0)
265  vlib_cli_output (vm, "No IPIP tunnels configured...");
266 
268  {
269  if (unformat (input, "%d", &ti))
270  ;
271  else
272  break;
273  }
274 
275  if (ti == ~0)
276  {
277  /* *INDENT-OFF* */
278  pool_foreach (t, gm->tunnels)
279  {vlib_cli_output(vm, "%U", format_ipip_tunnel, t); }
280  /* *INDENT-ON* */
281  }
282  else
283  {
284  if (pool_is_free_index (gm->tunnels, ti))
285  return clib_error_return (0, "unknown index:%d", ti);
286  t = pool_elt_at_index (gm->tunnels, ti);
287  if (t)
288  vlib_cli_output (vm, "%U", format_ipip_tunnel, t);
289  }
290  return 0;
291 }
292 
293 /* *INDENT-OFF* */
294 VLIB_CLI_COMMAND(show_ipip_tunnel_command, static) = {
295  .path = "show ipip tunnel",
296  .function = show_ipip_tunnel_command_fn,
297 };
298 /* *INDENT-ON* */
299 
300 static u8 *
301 format_ipip_tunnel_key (u8 * s, va_list * args)
302 {
303  ipip_tunnel_key_t *t = va_arg (*args, ipip_tunnel_key_t *);
304 
305  s = format (s, "src:%U dst:%U fib:%d transport:%d mode:%d",
308  t->fib_index, t->transport, t->mode);
309 
310  return (s);
311 }
312 
313 static clib_error_t *
315  unformat_input_t * input, vlib_cli_command_t * cmd)
316 {
317  ipip_main_t *im = &ipip_main;
318  ipip_tunnel_key_t *key;
319  u32 index;
320 
321  /* *INDENT-OFF* */
322  hash_foreach(key, index, im->tunnel_by_key,
323  ({
324  vlib_cli_output (vm, " %U -> %d", format_ipip_tunnel_key, key, index);
325  }));
326  /* *INDENT-ON* */
327 
328  return NULL;
329 }
330 
331 /**
332  * show IPSEC tunnel protection hash tables
333  */
334 /* *INDENT-OFF* */
335 VLIB_CLI_COMMAND (ipip_tunnel_hash_show_node, static) =
336 {
337  .path = "show ipip tunnel-hash",
338  .function = ipip_tunnel_hash_show,
339  .short_help = "show ipip tunnel-hash",
340 };
341 /* *INDENT-ON* */
342 
343 static clib_error_t *
345  unformat_input_t * input,
346  vlib_cli_command_t * cmd)
347 {
348  unformat_input_t _line_input, *line_input = &_line_input;
350  ip6_address_t ip6_prefix;
351  ip4_address_t ip4_src;
352  u32 ip6_prefix_len = 0, ip4_prefix_len = 0, sixrd_tunnel_index;
353  u32 num_m_args = 0;
354  /* Optional arguments */
355  u32 ip4_table_id = 0, ip4_fib_index;
356  u32 ip6_table_id = 0, ip6_fib_index;
357  clib_error_t *error = 0;
358  bool security_check = false;
359  int rv;
360 
361  /* Get a line of input. */
362  if (!unformat_user (input, unformat_line_input, line_input))
363  return 0;
364  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
365  {
366  if (unformat (line_input, "security-check"))
367  security_check = true;
368  else if (unformat (line_input, "ip6-pfx %U/%d", unformat_ip6_address,
369  &ip6_prefix, &ip6_prefix_len))
370  num_m_args++;
371  else if (unformat (line_input, "ip4-pfx %U/%d", unformat_ip4_address,
372  &ip4_prefix, &ip4_prefix_len))
373  num_m_args++;
374  else
375  if (unformat
376  (line_input, "ip4-src %U", unformat_ip4_address, &ip4_src))
377  num_m_args++;
378  else if (unformat (line_input, "ip4-table-id %d", &ip4_table_id))
379  ;
380  else if (unformat (line_input, "ip6-table-id %d", &ip6_table_id))
381  ;
382  else
383  {
384  error =
385  clib_error_return (0, "unknown input `%U'", format_unformat_error,
386  line_input);
387  goto done;
388  }
389  }
390 
391  if (num_m_args < 3)
392  {
393  error = clib_error_return (0, "mandatory argument(s) missing");
394  goto done;
395  }
396  ip4_fib_index = fib_table_find (FIB_PROTOCOL_IP4, ip4_table_id);
397  ip6_fib_index = fib_table_find (FIB_PROTOCOL_IP6, ip6_table_id);
398 
399  if (~0 == ip4_fib_index)
400  {
401  error = clib_error_return (0, "No such IP4 table %d", ip4_table_id);
402  rv = VNET_API_ERROR_NO_SUCH_FIB;
403  }
404  else if (~0 == ip6_fib_index)
405  {
406  error = clib_error_return (0, "No such IP6 table %d", ip6_table_id);
407  rv = VNET_API_ERROR_NO_SUCH_FIB;
408  }
409  else
410  {
411  rv = sixrd_add_tunnel (&ip6_prefix, ip6_prefix_len, &ip4_prefix,
412  ip4_prefix_len, &ip4_src, security_check,
413  ip4_fib_index, ip6_fib_index,
414  &sixrd_tunnel_index);
415 
416  if (rv)
417  error = clib_error_return (0, "adding tunnel failed %d", rv);
418  }
419 
420 done:
421  unformat_free (line_input);
422 
423  return error;
424 }
425 
426 static clib_error_t *
428  unformat_input_t * input,
429  vlib_cli_command_t * cmd)
430 {
431  unformat_input_t _line_input, *line_input = &_line_input;
432  u32 num_m_args = 0;
433  /* Optional arguments */
434  clib_error_t *error = 0;
435  u32 sw_if_index = ~0;
436 
437  /* Get a line of input. */
438  if (!unformat_user (input, unformat_line_input, line_input))
439  return 0;
440  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
441  {
442  if (unformat (line_input, "sw_if_index %d", &sw_if_index))
443  num_m_args++;
444  else
445  {
446  error =
447  clib_error_return (0, "unknown input `%U'", format_unformat_error,
448  line_input);
449  goto done;
450  }
451  }
452 
453  if (num_m_args < 1)
454  {
455  error = clib_error_return (0, "mandatory argument(s) missing");
456  goto done;
457  }
458  int rv = sixrd_del_tunnel (sw_if_index);
459  printf ("RV %d\n", rv);
460 
461 done:
462  unformat_free (line_input);
463 
464  return error;
465 }
466 
467 /* *INDENT-OFF* */
468 VLIB_CLI_COMMAND(create_sixrd_tunnel_command, static) = {
469  .path = "create 6rd tunnel",
470  .short_help = "create 6rd tunnel ip6-pfx <ip6-pfx> ip4-pfx <ip4-pfx> "
471  "ip4-src <ip4-addr> ip4-table-id <ID> ip6-table-id <ID> "
472  "[security-check]",
473  .function = create_sixrd_tunnel_command_fn,
474 };
475 VLIB_CLI_COMMAND(delete_sixrd_tunnel_command, static) = {
476  .path = "delete 6rd tunnel",
477  .short_help = "delete 6rd tunnel sw_if_index <sw_if_index>",
478  .function = delete_sixrd_tunnel_command_fn,
479 };
480 /* *INDENT-ON* */
481 
482 /*
483  * fd.io coding-style-patch-verification: ON
484  *
485  * Local Variables:
486  * eval: (c-set-style "gnu")
487  * End:
488  */
int sixrd_add_tunnel(ip6_address_t *ip6_prefix, u8 ip6_prefix_len, ip4_address_t *ip4_prefix, u8 ip4_prefix_len, ip4_address_t *ip4_src, bool security_check, u32 ip4_fib_index, u32 ip6_fib_index, u32 *sw_if_index)
Definition: sixrd.c:271
static clib_error_t * create_ipip_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipip_cli.c:22
u32 ip6_table_id
Definition: gbp.api:75
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
static clib_error_t * show_ipip_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipip_cli.c:256
A representation of a IPIP tunnel.
Definition: ipip.h:75
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:527
ip46_address_t tunnel_src
Definition: ipip.h:82
uword unformat_tunnel_encap_decap_flags(unformat_input_t *input, va_list *args)
Definition: tunnel.c:66
struct ipip_tunnel_t::@428 sixrd
static clib_error_t * delete_ipip_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipip_cli.c:158
manual_print typedef ip4_prefix
Definition: ip_types.api:130
uword unformat_tunnel_mode(unformat_input_t *input, va_list *args)
Definition: tunnel.c:38
vl_api_address_t src
Definition: gre.api:54
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
vlib_main_t * vm
Definition: in2out_ed.c:1580
int ipip_add_tunnel(ipip_transport_t transport, u32 instance, ip46_address_t *src, ip46_address_t *dst, u32 fib_index, tunnel_encap_decap_flags_t flags, ip_dscp_t dscp, tunnel_mode_t tmode, u32 *sw_if_indexp)
Definition: ipip.c:664
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
static u8 * format_ipip_tunnel_key(u8 *s, va_list *args)
Definition: ipip_cli.c:301
manual_print typedef ip6_prefix
Definition: ip_types.api:125
unformat_function_t unformat_ip4_address
Definition: format.h:68
u32 user_instance
Definition: ipip.h:88
description fragment has unexpected format
Definition: map.api:433
#define hash_foreach(key_var, value_var, h, body)
Definition: hash.h:442
#define clib_error_return(e, args...)
Definition: error.h:99
static clib_error_t * create_sixrd_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipip_cli.c:344
unsigned int u32
Definition: types.h:88
u32 fib_table_find(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1106
u8 * format_ip_dscp(u8 *s, va_list *va)
Definition: ip.c:262
unformat_function_t unformat_line_input
Definition: format.h:282
vl_api_fib_path_type_t type
Definition: fib_types.api:123
fib_protocol_t fib_proto_from_ip46(ip46_type_t iproto)
Convert from ip46_type to fib_protocol.
Definition: fib_types.c:409
Definition: cJSON.c:84
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:546
tunnel_encap_decap_flags_t flags
Definition: ipip.h:89
#define gm
Definition: dlmalloc.c:1219
ip6_address_t ip6_prefix
Definition: ipip.h:94
struct _unformat_input_t unformat_input_t
static u8 * format_ipip_tunnel(u8 *s, va_list *args)
Definition: ipip_cli.c:215
ipip_tunnel_t * tunnels
Definition: ipip.h:106
int sixrd_del_tunnel(u32 sw_if_index)
Definition: sixrd.c:374
vl_api_address_t dst
Definition: gre.api:55
enum tunnel_encap_decap_flags_t_ tunnel_encap_decap_flags_t
vl_api_tunnel_mode_t mode
Definition: gre.api:48
format_function_t format_ip46_address
Definition: ip46_address.h:50
ip_dscp_t dscp
Definition: ipip.h:90
unformat_function_t unformat_ip6_address
Definition: format.h:89
static clib_error_t * delete_sixrd_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipip_cli.c:427
ipip_main_t ipip_main
Definition: ipip.c:31
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
format_function_t format_ip6_address
Definition: format.h:91
u32 ip4_table_id
Definition: gbp.api:74
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:298
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
static clib_error_t * ipip_tunnel_hash_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipip_cli.c:314
u32 fib_index
Definition: ipip.h:84
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:696
u8 ip6_prefix_len
Definition: ipip.h:96
ipip_transport_t transport
Definition: ipip.h:81
u32 fib_table_get_table_id(u32 fib_index, fib_protocol_t proto)
Get the Table-ID of the FIB from protocol and index.
Definition: fib_table.c:1095
uword * tunnel_by_key
Definition: ipip.h:107
u32 sw_if_index
Definition: ipip.h:86
typedef key
Definition: ipsec_types.api:86
u32 instance
Definition: gre.api:51
static fib_protocol_t fib_ip_proto(bool is_ip6)
Convert from boolean is_ip6 to FIB protocol.
Definition: fib_types.h:79
ipip_mode_t mode
Definition: ipip.h:80
static void unformat_free(unformat_input_t *i)
Definition: format.h:162
u32 table_id
Definition: wireguard.api:102
u32 index
Definition: flow_types.api:221
int ipip_del_tunnel(u32 sw_if_index)
Definition: ipip.c:772
u32 dev_instance
Definition: ipip.h:87
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
u8 * format_tunnel_encap_decap_flags(u8 *s, va_list *args)
Definition: tunnel.c:52
ip46_address_t tunnel_dst
Definition: ipip.h:83
enum tunnel_mode_t_ tunnel_mode_t
#define ip46_address_initializer
Definition: ip46_address.h:52
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
ip46_type_t
Definition: ip46_address.h:22
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:127