FD.io VPP  v20.09-64-g4f7b92f0a
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 
22  unformat_input_t *input,
23  vlib_cli_command_t *cmd) {
24  unformat_input_t _line_input, *line_input = &_line_input;
26  u32 instance = ~0;
27  u32 fib_index = 0;
28  u32 table_id = 0;
29  int rv;
30  u32 num_m_args = 0;
32  clib_error_t *error = NULL;
33  bool ip4_set = false, ip6_set = false;
34  tunnel_mode_t mode = TUNNEL_MODE_P2P;
35 
36  /* Get a line of input. */
37  if (!unformat_user(input, unformat_line_input, line_input))
38  return 0;
39 
40  while (unformat_check_input(line_input) != UNFORMAT_END_OF_INPUT) {
41  if (unformat(line_input, "instance %d", &instance))
42  ;
43  else if (unformat(line_input, "src %U", unformat_ip4_address, &src.ip4)) {
44  num_m_args++;
45  ip4_set = true;
46  } else if (unformat(line_input, "dst %U", unformat_ip4_address, &dst.ip4)) {
47  num_m_args++;
48  ip4_set = true;
49  } else if (unformat(line_input, "src %U", unformat_ip6_address, &src.ip6)) {
50  num_m_args++;
51  ip6_set = true;
52  } else if (unformat(line_input, "dst %U", unformat_ip6_address, &dst.ip6)) {
53  num_m_args++;
54  ip6_set = true;
55  } else if (unformat(line_input, "%U", unformat_tunnel_mode, &mode)) {
56  num_m_args++;
57  } else if (unformat(line_input, "outer-table-id %d", &table_id))
58  ;
59  else {
60  error = clib_error_return(0, "unknown input `%U'", format_unformat_error,
61  line_input);
62  goto done;
63  }
64  }
65 
66  if (num_m_args < 2) {
67  error = clib_error_return(0, "mandatory argument(s) missing");
68  goto done;
69  }
70  if (ip4_set && ip6_set) {
71  error = clib_error_return(0, "source and destination must be of same address family");
72  goto done;
73  }
74 
75  fib_index = fib_table_find(fib_ip_proto(ip6_set), table_id);
76 
77  if (~0 == fib_index)
78  {
79  rv = VNET_API_ERROR_NO_SUCH_FIB;
80  }
81  else
82  {
84  instance,
85  &src,
86  &dst,
87  fib_index,
88  TUNNEL_ENCAP_DECAP_FLAG_NONE,
89  IP_DSCP_CS0,
90  mode,
91  &sw_if_index);
92  }
93 
94  switch (rv) {
95  case 0:
97  sw_if_index);
98  break;
99  case VNET_API_ERROR_IF_ALREADY_EXISTS:
100  error = clib_error_return(0, "IPIP tunnel already exists...");
101  goto done;
102  case VNET_API_ERROR_NO_SUCH_FIB:
103  error = clib_error_return(0, "outer fib ID %d doesn't exist\n", fib_index);
104  goto done;
105  case VNET_API_ERROR_NO_SUCH_ENTRY:
106  error = clib_error_return(0, "IPIP tunnel doesn't exist");
107  goto done;
108  case VNET_API_ERROR_INSTANCE_IN_USE:
109  error = clib_error_return(0, "Instance is in use");
110  goto done;
111  case VNET_API_ERROR_INVALID_DST_ADDRESS:
112  error = clib_error_return(0, "destination IP address when mode is multi-point");
113  goto done;
114  default:
115  error = clib_error_return(0, "vnet_ipip_add_del_tunnel returned %d", rv);
116  goto done;
117  }
118 
119 done:
120  unformat_free(line_input);
121 
122  return error;
123 }
124 
126  unformat_input_t *input,
127  vlib_cli_command_t *cmd) {
128  unformat_input_t _line_input, *line_input = &_line_input;
129  int rv;
130  u32 num_m_args = 0;
131  u32 sw_if_index = ~0;
132  clib_error_t *error = NULL;
133 
134  /* Get a line of input. */
135  if (!unformat_user(input, unformat_line_input, line_input))
136  return 0;
137 
138  while (unformat_check_input(line_input) != UNFORMAT_END_OF_INPUT) {
139  if (unformat(line_input, "sw_if_index %d", &sw_if_index))
140  num_m_args++;
141  else {
142  error = clib_error_return(0, "unknown input `%U'", format_unformat_error,
143  line_input);
144  goto done;
145  }
146  }
147 
148  if (num_m_args < 1) {
149  error = clib_error_return(0, "mandatory argument(s) missing");
150  goto done;
151  }
152 
153  rv = ipip_del_tunnel(sw_if_index);
154  printf("RV %d\n", rv);
155 
156 done:
157  unformat_free(line_input);
158 
159  return error;
160 }
161 
162 /* *INDENT-OFF* */
163 VLIB_CLI_COMMAND(create_ipip_tunnel_command, static) = {
164  .path = "create ipip tunnel",
165  .short_help = "create ipip tunnel src <addr> dst <addr> [instance <n>] "
166  "[outer-table-id <ID>]",
167  .function = create_ipip_tunnel_command_fn,
168 };
169 VLIB_CLI_COMMAND(delete_ipip_tunnel_command, static) = {
170  .path = "delete ipip tunnel",
171  .short_help = "delete ipip tunnel sw_if_index <sw_if_index>",
172  .function = delete_ipip_tunnel_command_fn,
173 };
174 /* *INDENT-ON* */
175 
176 static u8 *format_ipip_tunnel(u8 *s, va_list *args) {
177  ipip_tunnel_t *t = va_arg(*args, ipip_tunnel_t *);
178 
180  u32 table_id;
181 
182  table_id = fib_table_get_table_id(t->fib_index,
183  fib_proto_from_ip46(type));
184  switch (t->mode) {
185  case IPIP_MODE_6RD:
186  s = format(s, "[%d] 6rd src %U ip6-pfx %U/%d ",
187  t->dev_instance,
188  format_ip46_address, &t->tunnel_src, type,
190  break;
191  case IPIP_MODE_P2P:
192  s = format(s, "[%d] instance %d src %U dst %U ",
194  format_ip46_address, &t->tunnel_src, type,
195  format_ip46_address, &t->tunnel_dst, type);
196  break;
197  case IPIP_MODE_P2MP:
198  s = format(s, "[%d] instance %d p2mp src %U ",
200  format_ip46_address, &t->tunnel_src, type);
201  break;
202  }
203 
204  s = format(s, "table-ID %d sw-if-idx %d flags [%U] dscp %U",
205  table_id, t->sw_if_index,
207  format_ip_dscp, t->dscp);
208 
209  return s;
210 }
211 
213  unformat_input_t *input,
214  vlib_cli_command_t *cmd) {
216  ipip_tunnel_t *t;
217  u32 ti = ~0;
218 
219  if (pool_elts(gm->tunnels) == 0)
220  vlib_cli_output(vm, "No IPIP tunnels configured...");
221 
222  while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT) {
223  if (unformat(input, "%d", &ti))
224  ;
225  else
226  break;
227  }
228 
229  if (ti == ~0) {
230  /* *INDENT-OFF* */
231  pool_foreach(t, gm->tunnels,
232  ({vlib_cli_output(vm, "%U", format_ipip_tunnel, t); }));
233  /* *INDENT-ON* */
234  } else {
235  t = pool_elt_at_index(gm->tunnels, ti);
236  if (t)
237  vlib_cli_output(vm, "%U", format_ipip_tunnel, t);
238  }
239  return 0;
240 }
241 
242 /* *INDENT-OFF* */
243 VLIB_CLI_COMMAND(show_ipip_tunnel_command, static) = {
244  .path = "show ipip tunnel",
245  .function = show_ipip_tunnel_command_fn,
246 };
247 /* *INDENT-ON* */
248 
249 static u8 *
250 format_ipip_tunnel_key (u8 *s, va_list *args)
251 {
252  ipip_tunnel_key_t *t = va_arg(*args, ipip_tunnel_key_t *);
253 
254  s = format (s, "src:%U dst:%U fib:%d transport:%d mode:%d",
257  t->fib_index, t->transport, t->mode);
258 
259  return (s);
260 }
261 
262 static clib_error_t *
264  unformat_input_t * input,
265  vlib_cli_command_t * cmd)
266 {
267  ipip_main_t *im = &ipip_main;
268  ipip_tunnel_key_t *key;
269  u32 index;
270 
271  /* *INDENT-OFF* */
272  hash_foreach(key, index, im->tunnel_by_key,
273  ({
274  vlib_cli_output (vm, " %U -> %d", format_ipip_tunnel_key, key, index);
275  }));
276  /* *INDENT-ON* */
277 
278  return NULL;
279 }
280 
281 /**
282  * show IPSEC tunnel protection hash tables
283  */
284 /* *INDENT-OFF* */
285 VLIB_CLI_COMMAND (ipip_tunnel_hash_show_node, static) =
286 {
287  .path = "show ipip tunnel-hash",
288  .function = ipip_tunnel_hash_show,
289  .short_help = "show ipip tunnel-hash",
290 };
291 /* *INDENT-ON* */
292 
294  unformat_input_t *input,
295  vlib_cli_command_t *cmd) {
296  unformat_input_t _line_input, *line_input = &_line_input;
298  ip6_address_t ip6_prefix;
299  ip4_address_t ip4_src;
300  u32 ip6_prefix_len = 0, ip4_prefix_len = 0, sixrd_tunnel_index;
301  u32 num_m_args = 0;
302  /* Optional arguments */
303  u32 ip4_table_id = 0, ip4_fib_index;
304  u32 ip6_table_id = 0, ip6_fib_index;
305  clib_error_t *error = 0;
306  bool security_check = false;
307  int rv;
308 
309  /* Get a line of input. */
310  if (!unformat_user(input, unformat_line_input, line_input))
311  return 0;
312  while (unformat_check_input(line_input) != UNFORMAT_END_OF_INPUT) {
313  if (unformat(line_input, "security-check"))
314  security_check = true;
315  else if (unformat(line_input, "ip6-pfx %U/%d", unformat_ip6_address,
316  &ip6_prefix, &ip6_prefix_len))
317  num_m_args++;
318  else if (unformat(line_input, "ip4-pfx %U/%d", unformat_ip4_address,
319  &ip4_prefix, &ip4_prefix_len))
320  num_m_args++;
321  else if (unformat(line_input, "ip4-src %U", unformat_ip4_address, &ip4_src))
322  num_m_args++;
323  else if (unformat(line_input, "ip4-table-id %d", &ip4_table_id))
324  ;
325  else if (unformat(line_input, "ip6-table-id %d", &ip6_table_id))
326  ;
327  else {
328  error = clib_error_return(0, "unknown input `%U'", format_unformat_error,
329  line_input);
330  goto done;
331  }
332  }
333 
334  if (num_m_args < 3) {
335  error = clib_error_return(0, "mandatory argument(s) missing");
336  goto done;
337  }
338  ip4_fib_index = fib_table_find(FIB_PROTOCOL_IP4, ip4_table_id);
339  ip6_fib_index = fib_table_find(FIB_PROTOCOL_IP6, ip6_table_id);
340 
341  if (~0 == ip4_fib_index)
342  {
343  error = clib_error_return(0, "No such IP4 table %d", ip4_table_id);
344  rv = VNET_API_ERROR_NO_SUCH_FIB;
345  }
346  else if (~0 == ip6_fib_index)
347  {
348  error = clib_error_return(0, "No such IP6 table %d", ip6_table_id);
349  rv = VNET_API_ERROR_NO_SUCH_FIB;
350  }
351  else
352  {
353  rv = sixrd_add_tunnel(&ip6_prefix, ip6_prefix_len, &ip4_prefix,
354  ip4_prefix_len, &ip4_src, security_check,
355  ip4_fib_index, ip6_fib_index,
356  &sixrd_tunnel_index);
357 
358  if (rv)
359  error = clib_error_return(0, "adding tunnel failed %d", rv);
360  }
361 
362 done:
363  unformat_free(line_input);
364 
365  return error;
366 }
367 
369  unformat_input_t *input,
370  vlib_cli_command_t *cmd) {
371  unformat_input_t _line_input, *line_input = &_line_input;
372  u32 num_m_args = 0;
373  /* Optional arguments */
374  clib_error_t *error = 0;
375  u32 sw_if_index = ~0;
376 
377  /* Get a line of input. */
378  if (!unformat_user(input, unformat_line_input, line_input))
379  return 0;
380  while (unformat_check_input(line_input) != UNFORMAT_END_OF_INPUT) {
381  if (unformat(line_input, "sw_if_index %d", &sw_if_index))
382  num_m_args++;
383  else {
384  error = clib_error_return(0, "unknown input `%U'", format_unformat_error,
385  line_input);
386  goto done;
387  }
388  }
389 
390  if (num_m_args < 1) {
391  error = clib_error_return(0, "mandatory argument(s) missing");
392  goto done;
393  }
394  int rv = sixrd_del_tunnel(sw_if_index);
395  printf("RV %d\n", rv);
396 
397 done:
398  unformat_free(line_input);
399 
400  return error;
401 }
402 
403 /* *INDENT-OFF* */
404 VLIB_CLI_COMMAND(create_sixrd_tunnel_command, static) = {
405  .path = "create 6rd tunnel",
406  .short_help = "create 6rd tunnel ip6-pfx <ip6-pfx> ip4-pfx <ip4-pfx> "
407  "ip4-src <ip4-addr> ip4-table-id <ID> ip6-table-id <ID> "
408  "[security-check]",
409  .function = create_sixrd_tunnel_command_fn,
410 };
411 VLIB_CLI_COMMAND(delete_sixrd_tunnel_command, static) = {
412  .path = "delete 6rd tunnel",
413  .short_help = "delete 6rd tunnel sw_if_index <sw_if_index>",
414  .function = delete_sixrd_tunnel_command_fn,
415 };
416 /* *INDENT-ON* */
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:21
u32 ip6_table_id
Definition: gbp.api:75
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:212
A representation of a IPIP tunnel.
Definition: ipip.h:75
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
ip46_address_t tunnel_src
Definition: ipip.h:82
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:125
manual_print typedef ip4_prefix
Definition: ip_types.api:119
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:1582
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
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:653
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
struct ipip_tunnel_t::@408 sixrd
static u8 * format_ipip_tunnel_key(u8 *s, va_list *args)
Definition: ipip_cli.c:250
manual_print typedef ip6_prefix
Definition: ip_types.api:114
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:513
unformat_function_t unformat_ip4_address
Definition: format.h:68
u32 user_instance
Definition: ipip.h:88
#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:293
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:1097
u8 * format_ip_dscp(u8 *s, va_list *va)
Definition: ip.c:142
unformat_function_t unformat_line_input
Definition: format.h:283
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:390
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:534
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:176
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
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:368
ipip_main_t ipip_main
Definition: ipip.c:31
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
format_function_t format_ip6_address
Definition: format.h:91
u32 ip4_table_id
Definition: gbp.api:74
#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:263
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:1086
uword * tunnel_by_key
Definition: ipip.h:107
u32 sw_if_index
Definition: ipip.h:86
typedef key
Definition: ipsec_types.api:85
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:80
ipip_mode_t mode
Definition: ipip.h:80
static void unformat_free(unformat_input_t *i)
Definition: format.h:163
u32 table_id
Definition: wireguard.api:100
u32 index
Definition: flow_types.api:221
int ipip_del_tunnel(u32 sw_if_index)
Definition: ipip.c:761
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:33
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:171
ip46_type_t
Definition: ip46_address.h:22
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128