blob: 1a8e8896965669bd4a48f56f39d4027d1e993f42 [file] [log] [blame]
Ole Troan298c6952018-03-08 12:30:43 +01001/*
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>
Neale Ranns61502112018-08-22 00:21:14 -070019#include <vnet/fib/fib_table.h>
Ole Troan298c6952018-03-08 12:30:43 +010020
Mohammed Hawari8b552612020-12-01 11:20:31 +010021static clib_error_t *
22create_ipip_tunnel_command_fn (vlib_main_t * vm,
23 unformat_input_t * input,
24 vlib_cli_command_t * cmd)
25{
Ole Troan298c6952018-03-08 12:30:43 +010026 unformat_input_t _line_input, *line_input = &_line_input;
Mohammed Hawari8b552612020-12-01 11:20:31 +010027 ip46_address_t src = ip46_address_initializer, dst =
28 ip46_address_initializer;
Ole Troan298c6952018-03-08 12:30:43 +010029 u32 instance = ~0;
30 u32 fib_index = 0;
Neale Ranns61502112018-08-22 00:21:14 -070031 u32 table_id = 0;
Ole Troan298c6952018-03-08 12:30:43 +010032 int rv;
33 u32 num_m_args = 0;
34 u32 sw_if_index;
35 clib_error_t *error = NULL;
36 bool ip4_set = false, ip6_set = false;
Neale Ranns14053c92019-12-29 23:55:18 +000037 tunnel_mode_t mode = TUNNEL_MODE_P2P;
Mohammed Hawari59b792f2020-12-01 11:30:57 +010038 tunnel_encap_decap_flags_t flags = TUNNEL_ENCAP_DECAP_FLAG_NONE;
Ole Troan298c6952018-03-08 12:30:43 +010039
40 /* Get a line of input. */
Mohammed Hawari8b552612020-12-01 11:20:31 +010041 if (!unformat_user (input, unformat_line_input, line_input))
Ole Troan298c6952018-03-08 12:30:43 +010042 return 0;
43
Mohammed Hawari8b552612020-12-01 11:20:31 +010044 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
Mohammed Hawari59b792f2020-12-01 11:30:57 +010079 if (unformat
80 (line_input, "flags %U", unformat_tunnel_encap_decap_flags,
81 &flags))
82 ;
83 else
Mohammed Hawari8b552612020-12-01 11:20:31 +010084 {
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");
Ole Troan298c6952018-03-08 12:30:43 +010095 goto done;
96 }
Mohammed Hawari8b552612020-12-01 11:20:31 +010097 if (ip4_set && ip6_set)
98 {
99 error =
100 clib_error_return (0,
101 "source and destination must be of same address family");
102 goto done;
Neale Ranns61502112018-08-22 00:21:14 -0700103 }
104
Mohammed Hawari8b552612020-12-01 11:20:31 +0100105 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 {
113 rv = ipip_add_tunnel (ip6_set ? IPIP_TRANSPORT_IP6 : IPIP_TRANSPORT_IP4,
114 instance,
115 &src,
116 &dst,
117 fib_index,
Mohammed Hawari59b792f2020-12-01 11:30:57 +0100118 flags, IP_DSCP_CS0, mode, &sw_if_index);
Mohammed Hawari8b552612020-12-01 11:20:31 +0100119 }
120
121 switch (rv)
122 {
123 case 0:
124 vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name,
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 =
142 clib_error_return (0,
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 }
Ole Troan298c6952018-03-08 12:30:43 +0100150
151done:
Mohammed Hawari8b552612020-12-01 11:20:31 +0100152 unformat_free (line_input);
Ole Troan298c6952018-03-08 12:30:43 +0100153
154 return error;
155}
156
Mohammed Hawari8b552612020-12-01 11:20:31 +0100157static clib_error_t *
158delete_ipip_tunnel_command_fn (vlib_main_t * vm,
159 unformat_input_t * input,
160 vlib_cli_command_t * cmd)
161{
Ole Troan298c6952018-03-08 12:30:43 +0100162 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. */
Mohammed Hawari8b552612020-12-01 11:20:31 +0100169 if (!unformat_user (input, unformat_line_input, line_input))
Ole Troan298c6952018-03-08 12:30:43 +0100170 return 0;
171
Mohammed Hawari8b552612020-12-01 11:20:31 +0100172 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");
Ole Troan298c6952018-03-08 12:30:43 +0100188 goto done;
189 }
Ole Troan298c6952018-03-08 12:30:43 +0100190
Mohammed Hawari8b552612020-12-01 11:20:31 +0100191 rv = ipip_del_tunnel (sw_if_index);
192 printf ("RV %d\n", rv);
Ole Troan298c6952018-03-08 12:30:43 +0100193
194done:
Mohammed Hawari8b552612020-12-01 11:20:31 +0100195 unformat_free (line_input);
Ole Troan298c6952018-03-08 12:30:43 +0100196
197 return error;
198}
199
200/* *INDENT-OFF* */
201VLIB_CLI_COMMAND(create_ipip_tunnel_command, static) = {
202 .path = "create ipip tunnel",
203 .short_help = "create ipip tunnel src <addr> dst <addr> [instance <n>] "
Neale Rannsae0d46e2020-09-22 13:20:27 +0000204 "[outer-table-id <ID>] [p2mp]",
Ole Troan298c6952018-03-08 12:30:43 +0100205 .function = create_ipip_tunnel_command_fn,
206};
207VLIB_CLI_COMMAND(delete_ipip_tunnel_command, static) = {
208 .path = "delete ipip tunnel",
Ignas Bacius3d93ad92019-10-10 16:14:47 +0300209 .short_help = "delete ipip tunnel sw_if_index <sw_if_index>",
Ole Troan298c6952018-03-08 12:30:43 +0100210 .function = delete_ipip_tunnel_command_fn,
211};
212/* *INDENT-ON* */
213
Mohammed Hawari8b552612020-12-01 11:20:31 +0100214static u8 *
215format_ipip_tunnel (u8 * s, va_list * args)
216{
217 ipip_tunnel_t *t = va_arg (*args, ipip_tunnel_t *);
Ole Troan298c6952018-03-08 12:30:43 +0100218
Mohammed Hawari8b552612020-12-01 11:20:31 +0100219 ip46_type_t type =
220 (t->transport == IPIP_TRANSPORT_IP4) ? IP46_TYPE_IP4 : IP46_TYPE_IP6;
Neale Ranns61502112018-08-22 00:21:14 -0700221 u32 table_id;
222
Mohammed Hawari8b552612020-12-01 11:20:31 +0100223 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,
231 format_ip6_address, &t->sixrd.ip6_prefix,
232 t->sixrd.ip6_prefix_len);
233 break;
234 case IPIP_MODE_P2P:
235 s = format (s, "[%d] instance %d src %U dst %U ",
236 t->dev_instance, t->user_instance,
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 ",
242 t->dev_instance, t->user_instance,
243 format_ip46_address, &t->tunnel_src, type);
244 break;
245 }
Ole Troan298c6952018-03-08 12:30:43 +0100246
Mohammed Hawari8b552612020-12-01 11:20:31 +0100247 s = format (s, "table-ID %d sw-if-idx %d flags [%U] dscp %U",
248 table_id, t->sw_if_index,
249 format_tunnel_encap_decap_flags, t->flags,
250 format_ip_dscp, t->dscp);
Neale Ranns95346962019-11-25 13:04:44 +0000251
Ole Troan298c6952018-03-08 12:30:43 +0100252 return s;
253}
254
Mohammed Hawari8b552612020-12-01 11:20:31 +0100255static clib_error_t *
256show_ipip_tunnel_command_fn (vlib_main_t * vm,
257 unformat_input_t * input,
258 vlib_cli_command_t * cmd)
259{
Ole Troan298c6952018-03-08 12:30:43 +0100260 ipip_main_t *gm = &ipip_main;
261 ipip_tunnel_t *t;
262 u32 ti = ~0;
263
Mohammed Hawari8b552612020-12-01 11:20:31 +0100264 if (pool_elts (gm->tunnels) == 0)
265 vlib_cli_output (vm, "No IPIP tunnels configured...");
Ole Troan298c6952018-03-08 12:30:43 +0100266
Mohammed Hawari8b552612020-12-01 11:20:31 +0100267 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
268 {
269 if (unformat (input, "%d", &ti))
270 ;
271 else
272 break;
273 }
Ole Troan298c6952018-03-08 12:30:43 +0100274
Mohammed Hawari8b552612020-12-01 11:20:31 +0100275 if (ti == ~0)
276 {
Ole Troan298c6952018-03-08 12:30:43 +0100277 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +0100278 pool_foreach (t, gm->tunnels)
279 {vlib_cli_output(vm, "%U", format_ipip_tunnel, t); }
Ole Troan298c6952018-03-08 12:30:43 +0100280 /* *INDENT-ON* */
Mohammed Hawari8b552612020-12-01 11:20:31 +0100281 }
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 }
Ole Troan298c6952018-03-08 12:30:43 +0100290 return 0;
291}
292
293/* *INDENT-OFF* */
294VLIB_CLI_COMMAND(show_ipip_tunnel_command, static) = {
295 .path = "show ipip tunnel",
296 .function = show_ipip_tunnel_command_fn,
297};
298/* *INDENT-ON* */
299
Neale Ranns14053c92019-12-29 23:55:18 +0000300static u8 *
Mohammed Hawari8b552612020-12-01 11:20:31 +0100301format_ipip_tunnel_key (u8 * s, va_list * args)
Neale Ranns14053c92019-12-29 23:55:18 +0000302{
Mohammed Hawari8b552612020-12-01 11:20:31 +0100303 ipip_tunnel_key_t *t = va_arg (*args, ipip_tunnel_key_t *);
Neale Ranns14053c92019-12-29 23:55:18 +0000304
305 s = format (s, "src:%U dst:%U fib:%d transport:%d mode:%d",
Mohammed Hawari8b552612020-12-01 11:20:31 +0100306 format_ip46_address, &t->src, IP46_TYPE_ANY,
307 format_ip46_address, &t->dst, IP46_TYPE_ANY,
308 t->fib_index, t->transport, t->mode);
Neale Ranns14053c92019-12-29 23:55:18 +0000309
310 return (s);
311}
312
313static clib_error_t *
314ipip_tunnel_hash_show (vlib_main_t * vm,
Mohammed Hawari8b552612020-12-01 11:20:31 +0100315 unformat_input_t * input, vlib_cli_command_t * cmd)
Neale Ranns14053c92019-12-29 23:55:18 +0000316{
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* */
335VLIB_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
Mohammed Hawari8b552612020-12-01 11:20:31 +0100343static clib_error_t *
344create_sixrd_tunnel_command_fn (vlib_main_t * vm,
345 unformat_input_t * input,
346 vlib_cli_command_t * cmd)
347{
Ole Troan298c6952018-03-08 12:30:43 +0100348 unformat_input_t _line_input, *line_input = &_line_input;
349 ip4_address_t ip4_prefix;
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 */
Neale Ranns61502112018-08-22 00:21:14 -0700355 u32 ip4_table_id = 0, ip4_fib_index;
356 u32 ip6_table_id = 0, ip6_fib_index;
Ole Troan298c6952018-03-08 12:30:43 +0100357 clib_error_t *error = 0;
358 bool security_check = false;
Neale Ranns61502112018-08-22 00:21:14 -0700359 int rv;
Ole Troan298c6952018-03-08 12:30:43 +0100360
361 /* Get a line of input. */
Mohammed Hawari8b552612020-12-01 11:20:31 +0100362 if (!unformat_user (input, unformat_line_input, line_input))
Ole Troan298c6952018-03-08 12:30:43 +0100363 return 0;
Mohammed Hawari8b552612020-12-01 11:20:31 +0100364 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");
Ole Troan298c6952018-03-08 12:30:43 +0100394 goto done;
395 }
Mohammed Hawari8b552612020-12-01 11:20:31 +0100396 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);
Ole Troan298c6952018-03-08 12:30:43 +0100398
Neale Ranns61502112018-08-22 00:21:14 -0700399 if (~0 == ip4_fib_index)
Mohammed Hawari8b552612020-12-01 11:20:31 +0100400 {
401 error = clib_error_return (0, "No such IP4 table %d", ip4_table_id);
Neale Ranns61502112018-08-22 00:21:14 -0700402 rv = VNET_API_ERROR_NO_SUCH_FIB;
Mohammed Hawari8b552612020-12-01 11:20:31 +0100403 }
Neale Ranns61502112018-08-22 00:21:14 -0700404 else if (~0 == ip6_fib_index)
Mohammed Hawari8b552612020-12-01 11:20:31 +0100405 {
406 error = clib_error_return (0, "No such IP6 table %d", ip6_table_id);
Neale Ranns61502112018-08-22 00:21:14 -0700407 rv = VNET_API_ERROR_NO_SUCH_FIB;
Mohammed Hawari8b552612020-12-01 11:20:31 +0100408 }
Neale Ranns61502112018-08-22 00:21:14 -0700409 else
Mohammed Hawari8b552612020-12-01 11:20:31 +0100410 {
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);
Neale Ranns61502112018-08-22 00:21:14 -0700415
416 if (rv)
Mohammed Hawari8b552612020-12-01 11:20:31 +0100417 error = clib_error_return (0, "adding tunnel failed %d", rv);
418 }
Neale Ranns61502112018-08-22 00:21:14 -0700419
420done:
Mohammed Hawari8b552612020-12-01 11:20:31 +0100421 unformat_free (line_input);
Ole Troan298c6952018-03-08 12:30:43 +0100422
423 return error;
424}
425
Mohammed Hawari8b552612020-12-01 11:20:31 +0100426static clib_error_t *
427delete_sixrd_tunnel_command_fn (vlib_main_t * vm,
428 unformat_input_t * input,
429 vlib_cli_command_t * cmd)
430{
Ole Troan298c6952018-03-08 12:30:43 +0100431 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. */
Mohammed Hawari8b552612020-12-01 11:20:31 +0100438 if (!unformat_user (input, unformat_line_input, line_input))
Ole Troan298c6952018-03-08 12:30:43 +0100439 return 0;
Mohammed Hawari8b552612020-12-01 11:20:31 +0100440 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");
Ole Troan298c6952018-03-08 12:30:43 +0100456 goto done;
457 }
Mohammed Hawari8b552612020-12-01 11:20:31 +0100458 int rv = sixrd_del_tunnel (sw_if_index);
459 printf ("RV %d\n", rv);
Ole Troan298c6952018-03-08 12:30:43 +0100460
461done:
Mohammed Hawari8b552612020-12-01 11:20:31 +0100462 unformat_free (line_input);
Ole Troan298c6952018-03-08 12:30:43 +0100463
464 return error;
465}
466
467/* *INDENT-OFF* */
468VLIB_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> "
Ignas Bacius3d93ad92019-10-10 16:14:47 +0300471 "ip4-src <ip4-addr> ip4-table-id <ID> ip6-table-id <ID> "
BenoƮt Ganne1b52ca92019-04-19 10:12:42 +0200472 "[security-check]",
Ole Troan298c6952018-03-08 12:30:43 +0100473 .function = create_sixrd_tunnel_command_fn,
474};
475VLIB_CLI_COMMAND(delete_sixrd_tunnel_command, static) = {
476 .path = "delete 6rd tunnel",
Ignas Bacius3d93ad92019-10-10 16:14:47 +0300477 .short_help = "delete 6rd tunnel sw_if_index <sw_if_index>",
Ole Troan298c6952018-03-08 12:30:43 +0100478 .function = delete_sixrd_tunnel_command_fn,
479};
480/* *INDENT-ON* */
Mohammed Hawari8b552612020-12-01 11:20:31 +0100481
482/*
483 * fd.io coding-style-patch-verification: ON
484 *
485 * Local Variables:
486 * eval: (c-set-style "gnu")
487 * End:
488 */