linux-cp: Linux Interface Mirroring for Control Plane Integration
[vpp.git] / src / plugins / linux-cp / lcp_cli.c
1 /* Hey Emacs use -*- mode: C -*- */
2 /*
3  * Copyright 2020 Rubicon Communications, LLC.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <sys/socket.h>
19 #include <linux/if.h>
20
21 #include <vnet/vnet.h>
22 #include <vnet/plugin/plugin.h>
23
24 #include <vlibapi/api.h>
25 #include <vlibmemory/api.h>
26 #include <vpp/app/version.h>
27 #include <vnet/format_fns.h>
28
29 #include <plugins/linux-cp/lcp_interface.h>
30
31 static clib_error_t *
32 lcp_itf_pair_create_command_fn (vlib_main_t *vm, unformat_input_t *input,
33                                 vlib_cli_command_t *cmd)
34 {
35   unformat_input_t _line_input, *line_input = &_line_input;
36   vnet_main_t *vnm = vnet_get_main ();
37   u32 sw_if_index;
38   u8 *host_if_name;
39   lip_host_type_t host_if_type;
40   u8 *ns;
41   int r;
42
43   if (!unformat_user (input, unformat_line_input, line_input))
44     return 0;
45
46   sw_if_index = ~0;
47   host_if_name = ns = NULL;
48   host_if_type = LCP_ITF_HOST_TAP;
49
50   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
51     {
52       if (unformat (line_input, "%d", &sw_if_index))
53         ;
54       else if (unformat (line_input, "%U", unformat_vnet_sw_interface, vnm,
55                          &sw_if_index))
56         ;
57       else if (unformat (line_input, "host-if %s", &host_if_name))
58         ;
59       else if (unformat (line_input, "netns %s", &ns))
60         ;
61       else if (unformat (line_input, "tun"))
62         host_if_type = LCP_ITF_HOST_TUN;
63       else
64         {
65           unformat_free (line_input);
66           vec_free (host_if_name);
67           vec_free (ns);
68           return clib_error_return (0, "unknown input `%U'",
69                                     format_unformat_error, input);
70         }
71     }
72
73   unformat_free (line_input);
74
75   if (sw_if_index == ~0)
76     {
77       vec_free (host_if_name);
78       vec_free (ns);
79       return clib_error_return (0, "interface name or sw_if_index required");
80     }
81
82   if (vec_len (ns) >= LCP_NS_LEN)
83     {
84       vec_free (host_if_name);
85       vec_free (ns);
86       return clib_error_return (
87         0, "Namespace name should be fewer than %d characters", LCP_NS_LEN);
88     }
89
90   r = lcp_itf_pair_create (sw_if_index, host_if_name, host_if_type, ns);
91
92   vec_free (host_if_name);
93   vec_free (ns);
94
95   if (r)
96     return clib_error_return (0, "linux-cp pair creation failed (%d)", r);
97
98   return 0;
99 }
100
101 VLIB_CLI_COMMAND (lcp_itf_pair_create_command, static) = {
102   .path = "lcp create",
103   .short_help = "lcp create <sw_if_index>|<if-name> host-if <host-if-name> "
104                 "netns <namespace> [tun]",
105   .function = lcp_itf_pair_create_command_fn,
106 };
107
108 static clib_error_t *
109 lcp_default_netns_command_fn (vlib_main_t *vm, unformat_input_t *input,
110                               vlib_cli_command_t *cmd)
111 {
112   unformat_input_t _line_input, *line_input = &_line_input;
113   u8 *ns;
114   int r;
115
116   if (!unformat_user (input, unformat_line_input, line_input))
117     return 0;
118
119   ns = 0;
120
121   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
122     {
123       if (unformat (line_input, "netns %s", &ns))
124         ;
125       else if (unformat (line_input, "clear netns"))
126         ;
127     }
128
129   unformat_free (line_input);
130
131   vlib_cli_output (vm, "lcp set default netns '%s'\n", (char *) ns);
132
133   r = lcp_set_default_ns (ns);
134
135   if (r)
136     return clib_error_return (0, "linux-cp set default netns failed (%d)", r);
137
138   return 0;
139 }
140
141 VLIB_CLI_COMMAND (lcp_default_netns_command, static) = {
142   .path = "lcp default",
143   .short_help = "lcp default netns [<namespace>]",
144   .function = lcp_default_netns_command_fn,
145 };
146
147 static clib_error_t *
148 lcp_itf_pair_delete_command_fn (vlib_main_t *vm, unformat_input_t *input,
149                                 vlib_cli_command_t *cmd)
150 {
151   vnet_main_t *vnm = vnet_get_main ();
152   unformat_input_t _line_input, *line_input = &_line_input;
153   u32 sw_if_index;
154   int r;
155
156   if (!unformat_user (input, unformat_line_input, line_input))
157     return 0;
158
159   sw_if_index = ~0;
160
161   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
162     {
163       if (unformat (line_input, "%d", &sw_if_index))
164         ;
165       else if (unformat (line_input, "%U", unformat_vnet_sw_interface, vnm,
166                          &sw_if_index))
167         ;
168       else
169         return clib_error_return (0, "unknown input `%U'",
170                                   format_unformat_error, input);
171     }
172
173   unformat_free (line_input);
174
175   if (sw_if_index == ~0)
176     return clib_error_return (0, "interface name or sw_if_index required");
177
178   r = lcp_itf_pair_delete (sw_if_index);
179
180   if (r)
181     return clib_error_return (0, "linux-cp pair deletion failed (%d)", r);
182   return 0;
183 }
184
185 VLIB_CLI_COMMAND (lcp_itf_pair_delete_command, static) = {
186   .path = "lcp delete",
187   .short_help = "lcp delete <sw_if_index>|<if-name>",
188   .function = lcp_itf_pair_delete_command_fn,
189 };
190
191 static clib_error_t *
192 lcp_itf_pair_show_cmd (vlib_main_t *vm, unformat_input_t *input,
193                        vlib_cli_command_t *cmd)
194 {
195   vnet_main_t *vnm = vnet_get_main ();
196   u32 phy_sw_if_index;
197
198   phy_sw_if_index = ~0;
199
200   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
201     {
202       if (unformat (input, "phy %U", unformat_vnet_sw_interface, vnm,
203                     &phy_sw_if_index))
204         ;
205       else
206         return clib_error_return (0, "unknown input '%U'",
207                                   format_unformat_error, input);
208     }
209
210   lcp_itf_pair_show (phy_sw_if_index);
211
212   return 0;
213 }
214
215 VLIB_CLI_COMMAND (lcp_itf_pair_show_cmd_node, static) = {
216   .path = "show lcp",
217   .function = lcp_itf_pair_show_cmd,
218   .short_help = "show lcp [phy <interface>]",
219   .is_mp_safe = 1,
220 };
221
222 clib_error_t *
223 lcp_cli_init (vlib_main_t *vm)
224 {
225   return 0;
226 }
227
228 VLIB_INIT_FUNCTION (lcp_cli_init);
229
230 /*
231  * fd.io coding-style-patch-verification: ON
232  *
233  * Local Variables:
234  * eval: (c-set-style "gnu")
235  * End:
236  */