flow: add vnet/flow formal API
[vpp.git] / src / vnet / flow / flow_api.c
1 /*
2  *------------------------------------------------------------------
3  * flow_api.c - flow api
4  *
5  * Copyright (c) 2020 Intel and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19
20 #include <stddef.h>
21
22 #include <vnet/vnet.h>
23 #include <vlibmemory/api.h>
24 #include <vnet/interface.h>
25 #include <vnet/api_errno.h>
26 #include <vnet/flow/flow.h>
27 #include <vnet/fib/fib_table.h>
28 #include <vnet/tunnel/tunnel_types_api.h>
29 #include <vnet/ip/ip_types_api.h>
30 #include <vnet/vnet_msg_enum.h>
31
32 #define vl_typedefs             /* define message structures */
33 #include <vnet/vnet_all_api_h.h>
34 #undef vl_typedefs
35
36 #define vl_endianfun            /* define message structures */
37 #include <vnet/vnet_all_api_h.h>
38 #undef vl_endianfun
39
40 /* instantiate all the print functions we know about */
41 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
42 #define vl_printfun
43 #include <vnet/vnet_all_api_h.h>
44 #undef vl_printfun
45
46 #include <vlibapi/api_helper_macros.h>
47
48 #define foreach_vpe_api_msg         \
49 _(FLOW_ADD, flow_add)               \
50 _(FLOW_DEL, flow_del)               \
51 _(FLOW_ENABLE, flow_enable)         \
52 _(FLOW_DISABLE, flow_disable)
53
54 static inline void
55 ipv4_addr_and_mask_convert (vl_api_ip4_address_and_mask_t * vl_api_addr,
56                             ip4_address_and_mask_t * vnet_addr)
57 {
58   clib_memcpy (vnet_addr, vl_api_addr, sizeof (*vnet_addr));
59 }
60
61 static inline void
62 ipv6_addr_and_mask_convert (vl_api_ip6_address_and_mask_t * vl_api_addr,
63                             ip6_address_and_mask_t * vnet_addr)
64 {
65   clib_memcpy (vnet_addr, vl_api_addr, sizeof (*vnet_addr));
66 }
67
68 static inline void
69 port_and_mask_convert (vl_api_ip_port_and_mask_t * vl_api_port,
70                        ip_port_and_mask_t * vnet_port)
71 {
72   vnet_port->port = ntohs (vl_api_port->port);
73   vnet_port->mask = ntohs (vl_api_port->mask);
74 }
75
76 static inline void
77 ipv4_n_tuple_flow_convert (vl_api_flow_ip4_n_tuple_t * vl_api_flow,
78                            vnet_flow_ip4_n_tuple_t * f)
79 {
80   ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
81   ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
82
83   port_and_mask_convert (&vl_api_flow->src_port, &f->src_port);
84   port_and_mask_convert (&vl_api_flow->dst_port, &f->dst_port);
85
86   f->protocol = (ip_protocol_t) vl_api_flow->protocol;
87 }
88
89 static void
90 ipv6_n_tuple_flow_convert (vl_api_flow_ip6_n_tuple_t * vl_api_flow,
91                            vnet_flow_ip6_n_tuple_t * f)
92 {
93   ipv6_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
94   ipv6_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
95
96   port_and_mask_convert (&vl_api_flow->src_port, &f->src_port);
97   port_and_mask_convert (&vl_api_flow->dst_port, &f->dst_port);
98
99   f->protocol = (ip_protocol_t) vl_api_flow->protocol;
100 }
101
102 static inline void
103 ipv4_n_tuple_tagged_flow_convert (vl_api_flow_ip4_n_tuple_tagged_t *
104                                   vl_api_flow,
105                                   vnet_flow_ip4_n_tuple_tagged_t * f)
106 {
107   return ipv4_n_tuple_flow_convert ((vl_api_flow_ip4_n_tuple_t *) vl_api_flow,
108                                     (vnet_flow_ip4_n_tuple_t *) f);
109 }
110
111 static inline void
112 ipv6_n_tuple_tagged_flow_convert (vl_api_flow_ip6_n_tuple_tagged_t *
113                                   vl_api_flow,
114                                   vnet_flow_ip6_n_tuple_tagged_t * f)
115 {
116   return ipv6_n_tuple_flow_convert ((vl_api_flow_ip6_n_tuple_t *) vl_api_flow,
117                                     (vnet_flow_ip6_n_tuple_t *) f);
118 }
119
120 static inline void
121 ipv4_l2tpv3oip_flow_convert (vl_api_flow_ip4_l2tpv3oip_t * vl_api_flow,
122                              vnet_flow_ip4_l2tpv3oip_t * f)
123 {
124   ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
125   ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
126
127   f->protocol = (ip_protocol_t) vl_api_flow->protocol;
128   f->session_id = ntohl (vl_api_flow->session_id);
129 }
130
131 static inline void
132 ipv4_ipsec_esp_flow_convert (vl_api_flow_ip4_ipsec_esp_t * vl_api_flow,
133                              vnet_flow_ip4_ipsec_esp_t * f)
134 {
135   ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
136   ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
137
138   f->protocol = (ip_protocol_t) vl_api_flow->protocol;
139   f->spi = ntohl (vl_api_flow->spi);
140 }
141
142 static inline void
143 ipv4_ipsec_ah_flow_convert (vl_api_flow_ip4_ipsec_ah_t * vl_api_flow,
144                             vnet_flow_ip4_ipsec_ah_t * f)
145 {
146   ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
147   ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
148
149   f->protocol = (ip_protocol_t) vl_api_flow->protocol;
150   f->spi = ntohl (vl_api_flow->spi);
151 }
152
153 static inline void
154 ipv4_gtpu_flow_convert (vl_api_flow_ip4_gtpu_t * vl_api_flow,
155                         vnet_flow_ip4_gtpu_t * f)
156 {
157   ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
158   ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
159
160   port_and_mask_convert (&vl_api_flow->src_port, &f->src_port);
161   port_and_mask_convert (&vl_api_flow->dst_port, &f->dst_port);
162
163   f->protocol = (ip_protocol_t) vl_api_flow->protocol;
164   f->teid = ntohl (vl_api_flow->teid);
165 }
166
167 static inline void
168 ipv4_gtpc_flow_convert (vl_api_flow_ip4_gtpc_t * vl_api_flow,
169                         vnet_flow_ip4_gtpc_t * f)
170 {
171   ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
172   ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
173
174   port_and_mask_convert (&vl_api_flow->src_port, &f->src_port);
175   port_and_mask_convert (&vl_api_flow->dst_port, &f->dst_port);
176
177   f->protocol = (ip_protocol_t) vl_api_flow->protocol;
178   f->teid = ntohl (vl_api_flow->teid);
179 }
180
181 static void
182 vl_api_flow_add_t_handler (vl_api_flow_add_t * mp)
183 {
184   vl_api_flow_add_reply_t *rmp;
185   int rv = 0;
186   vnet_flow_t flow;
187   u32 flow_index = ~0;
188   vl_api_flow_rule_t *f = &mp->flow;
189
190   vnet_main_t *vnm = vnet_get_main ();
191
192   flow.type = ntohl (f->type);
193   flow.actions = ntohl (f->actions);
194   flow.mark_flow_id = ntohl (f->mark_flow_id);
195   flow.redirect_node_index = ntohl (f->redirect_node_index);
196   flow.redirect_device_input_next_index =
197     ntohl (f->redirect_device_input_next_index);
198   flow.redirect_queue = ntohl (f->redirect_queue);
199   flow.buffer_advance = ntohl (f->buffer_advance);
200
201   switch (flow.type)
202     {
203     case VNET_FLOW_TYPE_IP4_N_TUPLE:
204       ipv4_n_tuple_flow_convert (&f->flow.ip4_n_tuple, &flow.ip4_n_tuple);
205       break;
206     case VNET_FLOW_TYPE_IP6_N_TUPLE:
207       ipv6_n_tuple_flow_convert (&f->flow.ip6_n_tuple, &flow.ip6_n_tuple);
208       break;
209     case VNET_FLOW_TYPE_IP4_N_TUPLE_TAGGED:
210       ipv4_n_tuple_tagged_flow_convert (&f->flow.ip4_n_tuple_tagged,
211                                         &flow.ip4_n_tuple_tagged);
212       break;
213     case VNET_FLOW_TYPE_IP6_N_TUPLE_TAGGED:
214       ipv6_n_tuple_tagged_flow_convert (&f->flow.ip6_n_tuple_tagged,
215                                         &flow.ip6_n_tuple_tagged);
216       break;
217     case VNET_FLOW_TYPE_IP4_L2TPV3OIP:
218       ipv4_l2tpv3oip_flow_convert (&f->flow.ip4_l2tpv3oip,
219                                    &flow.ip4_l2tpv3oip);
220       break;
221     case VNET_FLOW_TYPE_IP4_IPSEC_ESP:
222       ipv4_ipsec_esp_flow_convert (&f->flow.ip4_ipsec_esp,
223                                    &flow.ip4_ipsec_esp);
224       break;
225     case VNET_FLOW_TYPE_IP4_IPSEC_AH:
226       ipv4_ipsec_ah_flow_convert (&f->flow.ip4_ipsec_ah, &flow.ip4_ipsec_ah);
227       break;
228     case VNET_FLOW_TYPE_IP4_GTPU:
229       ipv4_gtpu_flow_convert (&f->flow.ip4_gtpu, &flow.ip4_gtpu);
230       break;
231     case VNET_FLOW_TYPE_IP4_GTPC:
232       ipv4_gtpc_flow_convert (&f->flow.ip4_gtpc, &flow.ip4_gtpc);
233       break;
234     default:
235       rv = VNET_FLOW_ERROR_NOT_SUPPORTED;
236       goto out;
237       break;
238
239     }
240
241   rv = vnet_flow_add (vnm, &flow, &flow_index);
242
243   goto out;
244 out:
245   /* *INDENT-OFF* */
246   REPLY_MACRO2(VL_API_FLOW_ADD_REPLY,
247   ({
248     rmp->flow_index = ntohl (flow_index);
249   }));
250 }
251
252 static void
253 vl_api_flow_del_t_handler (vl_api_flow_del_t * mp)
254 {
255   vl_api_flow_add_reply_t *rmp;
256   int rv = 0;
257
258   vnet_main_t *vnm = vnet_get_main();
259   rv = vnet_flow_del(vnm, ntohl(mp->flow_index));
260
261   REPLY_MACRO (VL_API_FLOW_DEL_REPLY);
262 }
263
264 static void
265 vl_api_flow_enable_t_handler (vl_api_flow_enable_t * mp)
266 {
267   vl_api_flow_add_reply_t *rmp;
268   int rv = 0;
269
270   vnet_main_t *vnm = vnet_get_main();
271   rv = vnet_flow_enable(vnm, ntohl(mp->flow_index), ntohl(mp->hw_if_index));
272
273   REPLY_MACRO (VL_API_FLOW_ENABLE_REPLY);
274 }
275
276 static void
277 vl_api_flow_disable_t_handler (vl_api_flow_disable_t * mp)
278 {
279   vl_api_flow_add_reply_t *rmp;
280   int rv = 0;
281
282   vnet_main_t *vnm = vnet_get_main();
283   rv = vnet_flow_disable(vnm, ntohl(mp->flow_index), ntohl(mp->hw_if_index));
284
285   REPLY_MACRO (VL_API_FLOW_DISABLE_REPLY);
286 }
287
288 #define vl_msg_name_crc_list
289 #include <vnet/flow/flow.api.h>
290 #undef vl_msg_name_crc_list
291
292 /*
293  * flow_api_hookup
294  * Add vpe's API message handlers to the table.
295  * vlib has already mapped shared memory and
296  * added the client registration handlers.
297  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
298  */
299
300
301 static void
302 setup_message_id_table (api_main_t * am)
303 {
304 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
305   foreach_vl_msg_name_crc_flow;
306 #undef _
307 }
308
309 static clib_error_t *
310 hw_flow_api_hookup (vlib_main_t * vm)
311 {
312   api_main_t *am = vlibapi_get_main ();
313
314 #define _(N,n)                                                  \
315     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
316                            vl_api_##n##_t_handler,              \
317                            vl_noop_handler,                     \
318                            vl_api_##n##_t_endian,               \
319                            vl_api_##n##_t_print,                \
320                            sizeof(vl_api_##n##_t), 1);
321   foreach_vpe_api_msg;
322 #undef _
323
324   /*
325    * Set up the (msg_name, crc, message-id) table
326    */
327   setup_message_id_table (am);
328
329   return 0;
330 }
331
332 VLIB_API_INIT_FUNCTION (hw_flow_api_hookup);
333
334 /*
335  * fd.io coding-style-patch-verification: ON
336  *
337  * Local Variables:
338  * eval: (c-set-style "gnu")
339  * End:
340  */