udp: add udp decapsulation
[vpp.git] / src / vnet / udp / udp_decap.c
1 /*
2  * Copyright (c) 2021 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 <vnet/udp/udp.h>
17
18 uword
19 unformat_next_node (unformat_input_t *input, va_list *args)
20 {
21   vlib_main_t *vm = va_arg (*args, vlib_main_t *);
22   u32 *node_index = va_arg (*args, u32 *);
23   if (unformat (input, "mpls"))
24     *node_index = vlib_get_node_by_name (vm, (u8 *) "mpls-input")->index;
25   else if (unformat (input, "ip4"))
26     *node_index = vlib_get_node_by_name (vm, (u8 *) "ip4-input")->index;
27   else if (unformat (input, "ip6"))
28     *node_index = vlib_get_node_by_name (vm, (u8 *) "ip6-input")->index;
29   else
30     return 0;
31   return 1;
32 }
33
34 static clib_error_t *
35 udp_decap_cli (vlib_main_t *vm, unformat_input_t *input,
36                vlib_cli_command_t *cmd_arg)
37 {
38   unformat_input_t _line_input, *line_input = &_line_input;
39   clib_error_t *error = NULL;
40   u8 is_add = 1, is_ip4 = 1;
41   int i = 0;
42   u16 port = 0;
43   u32 node_index = ~0;
44
45   if (!unformat_user (input, unformat_line_input, line_input))
46     return 0;
47
48   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
49     {
50       if (unformat (line_input, "add"))
51         is_add = 1;
52       else if (unformat (line_input, "del"))
53         is_add = 0;
54       else if (unformat (line_input, "ipv4"))
55         is_ip4 = 1;
56       else if (unformat (line_input, "ipv6"))
57         is_ip4 = 0;
58       else if (unformat (line_input, "%d", &i))
59         port = i;
60       else if (unformat (line_input, "next-proto %U", unformat_next_node, vm,
61                          &node_index))
62         ;
63       else
64         {
65           error = clib_error_return (0, "parse error: '%U'",
66                                      format_unformat_error, line_input);
67           goto done;
68         }
69     }
70   if (port == 0)
71     {
72       error = clib_error_return (0, "missing port");
73       goto done;
74     }
75   if (is_add && node_index == ~0)
76     {
77       error = clib_error_return (0, "missing protocol");
78       goto done;
79     }
80   if (is_add)
81     udp_register_dst_port (vm, port, node_index, is_ip4);
82   else
83     udp_unregister_dst_port (vm, port, is_ip4);
84
85 done:
86   unformat_free (line_input);
87   return error;
88 }
89
90 /*?
91  * Register a port to decapsulate incoming UDP encapsulated packets.
92  *
93  * @cliexpar
94  * @clistart
95  * udp decap add ipv4 1234 next-proto mpls
96  * @cliend
97  * @cliexcmd{udp decap [add|del] [ipv4|ipv6] <dst-port> next-proto
98 <inner-protocol>}
99 ?*/
100
101 VLIB_CLI_COMMAND (udp_decap_add_command, static) = {
102   .path = "udp decap",
103   .short_help =
104     "udp decap [add|del] [ipv4|ipv6] <dst-port> next-proto <inner-protocol>",
105   .function = udp_decap_cli,
106 };