flow: Add API implementation of IP4/IP6, IP4_VXLAN/IP6_VXLAN
[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/udp/udp_local.h>
29 #include <vnet/tunnel/tunnel_types_api.h>
30 #include <vnet/ip/ip_types_api.h>
31 #include <vnet/vnet_msg_enum.h>
32
33 #define vl_typedefs             /* define message structures */
34 #include <vnet/vnet_all_api_h.h>
35 #undef vl_typedefs
36
37 #define vl_endianfun            /* define message structures */
38 #include <vnet/vnet_all_api_h.h>
39 #undef vl_endianfun
40
41 /* instantiate all the print functions we know about */
42 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
43 #define vl_printfun
44 #include <vnet/vnet_all_api_h.h>
45 #undef vl_printfun
46
47 #include <vlibapi/api_helper_macros.h>
48
49 #define foreach_vpe_api_msg         \
50 _(FLOW_ADD, flow_add)               \
51 _(FLOW_DEL, flow_del)               \
52 _(FLOW_ENABLE, flow_enable)         \
53 _(FLOW_DISABLE, flow_disable)
54
55 static inline void
56 ipv4_addr_and_mask_convert (vl_api_ip4_address_and_mask_t * vl_api_addr,
57                             ip4_address_and_mask_t * vnet_addr)
58 {
59   clib_memcpy (vnet_addr, vl_api_addr, sizeof (*vnet_addr));
60 }
61
62 static inline void
63 ipv6_addr_and_mask_convert (vl_api_ip6_address_and_mask_t * vl_api_addr,
64                             ip6_address_and_mask_t * vnet_addr)
65 {
66   clib_memcpy (vnet_addr, vl_api_addr, sizeof (*vnet_addr));
67 }
68
69 static inline void
70 protocol_and_mask_convert (vl_api_ip_prot_and_mask_t * vl_api_protocol,
71                            ip_prot_and_mask_t * vnet_protocol)
72 {
73   vnet_protocol->prot = (ip_protocol_t) vl_api_protocol->prot;
74   vnet_protocol->mask = vl_api_protocol->mask;
75 }
76
77 static inline void
78 port_and_mask_convert (vl_api_ip_port_and_mask_t * vl_api_port,
79                        ip_port_and_mask_t * vnet_port)
80 {
81   vnet_port->port = ntohs (vl_api_port->port);
82   vnet_port->mask = ntohs (vl_api_port->mask);
83 }
84
85 static inline void
86 ipv4_flow_convert (vl_api_flow_ip4_t *vl_api_flow, vnet_flow_ip4_t *f)
87 {
88   ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
89   ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
90
91   protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
92 }
93
94 static void
95 ipv6_flow_convert (vl_api_flow_ip6_t *vl_api_flow, vnet_flow_ip6_t *f)
96 {
97   ipv6_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
98   ipv6_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
99
100   protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
101 }
102
103 static inline void
104 ipv4_n_tuple_flow_convert (vl_api_flow_ip4_n_tuple_t * vl_api_flow,
105                            vnet_flow_ip4_n_tuple_t * f)
106 {
107   ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
108   ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
109   protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
110
111   port_and_mask_convert (&vl_api_flow->src_port, &f->src_port);
112   port_and_mask_convert (&vl_api_flow->dst_port, &f->dst_port);
113 }
114
115 static void
116 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   ipv6_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
120   ipv6_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
121   protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
122
123   port_and_mask_convert (&vl_api_flow->src_port, &f->src_port);
124   port_and_mask_convert (&vl_api_flow->dst_port, &f->dst_port);
125 }
126
127 static inline void
128 ipv4_n_tuple_tagged_flow_convert (vl_api_flow_ip4_n_tuple_tagged_t *
129                                   vl_api_flow,
130                                   vnet_flow_ip4_n_tuple_tagged_t * f)
131 {
132   return ipv4_n_tuple_flow_convert ((vl_api_flow_ip4_n_tuple_t *) vl_api_flow,
133                                     (vnet_flow_ip4_n_tuple_t *) f);
134 }
135
136 static inline void
137 ipv6_n_tuple_tagged_flow_convert (vl_api_flow_ip6_n_tuple_tagged_t *
138                                   vl_api_flow,
139                                   vnet_flow_ip6_n_tuple_tagged_t * f)
140 {
141   return ipv6_n_tuple_flow_convert ((vl_api_flow_ip6_n_tuple_t *) vl_api_flow,
142                                     (vnet_flow_ip6_n_tuple_t *) f);
143 }
144
145 static inline void
146 ipv4_l2tpv3oip_flow_convert (vl_api_flow_ip4_l2tpv3oip_t * vl_api_flow,
147                              vnet_flow_ip4_l2tpv3oip_t * f)
148 {
149   ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
150   ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
151
152   protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
153   f->session_id = ntohl (vl_api_flow->session_id);
154 }
155
156 static inline void
157 ipv4_ipsec_esp_flow_convert (vl_api_flow_ip4_ipsec_esp_t * vl_api_flow,
158                              vnet_flow_ip4_ipsec_esp_t * f)
159 {
160   ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
161   ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
162
163   protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
164   f->spi = ntohl (vl_api_flow->spi);
165 }
166
167 static inline void
168 ipv4_ipsec_ah_flow_convert (vl_api_flow_ip4_ipsec_ah_t * vl_api_flow,
169                             vnet_flow_ip4_ipsec_ah_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   protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
175   f->spi = ntohl (vl_api_flow->spi);
176 }
177
178 static inline void
179 ipv4_vxlan_flow_convert (vl_api_flow_ip4_vxlan_t *vl_api_flow,
180                          vnet_flow_ip4_vxlan_t *f)
181 {
182   ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
183   ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
184   protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
185
186   port_and_mask_convert (&vl_api_flow->src_port, &f->src_port);
187   port_and_mask_convert (&vl_api_flow->dst_port, &f->dst_port);
188
189   f->vni = ntohs (vl_api_flow->vni);
190 }
191
192 static inline void
193 ipv6_vxlan_flow_convert (vl_api_flow_ip6_vxlan_t *vl_api_flow,
194                          vnet_flow_ip6_vxlan_t *f)
195 {
196   ipv6_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
197   ipv6_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
198   protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
199
200   port_and_mask_convert (&vl_api_flow->src_port, &f->src_port);
201   port_and_mask_convert (&vl_api_flow->dst_port, &f->dst_port);
202
203   f->vni = ntohs (vl_api_flow->vni);
204 }
205
206 static inline void
207 ipv4_gtpu_flow_convert (vl_api_flow_ip4_gtpu_t * vl_api_flow,
208                         vnet_flow_ip4_gtpu_t * f)
209 {
210   ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
211   ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
212
213   port_and_mask_convert (&vl_api_flow->src_port, &f->src_port);
214   port_and_mask_convert (&vl_api_flow->dst_port, &f->dst_port);
215
216   protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
217   f->teid = ntohl (vl_api_flow->teid);
218 }
219
220 static inline void
221 ipv4_gtpc_flow_convert (vl_api_flow_ip4_gtpc_t * vl_api_flow,
222                         vnet_flow_ip4_gtpc_t * f)
223 {
224   ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
225   ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
226
227   port_and_mask_convert (&vl_api_flow->src_port, &f->src_port);
228   port_and_mask_convert (&vl_api_flow->dst_port, &f->dst_port);
229
230   protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
231   f->teid = ntohl (vl_api_flow->teid);
232 }
233
234 static void
235 vl_api_flow_add_t_handler (vl_api_flow_add_t * mp)
236 {
237   vl_api_flow_add_reply_t *rmp;
238   int rv = 0;
239   vnet_flow_t flow;
240   u32 flow_index = ~0;
241   vl_api_flow_rule_t *f = &mp->flow;
242
243   vnet_main_t *vnm = vnet_get_main ();
244
245   flow.type = ntohl (f->type);
246   flow.actions = ntohl (f->actions);
247   flow.mark_flow_id = ntohl (f->mark_flow_id);
248   flow.redirect_node_index = ntohl (f->redirect_node_index);
249   flow.redirect_device_input_next_index =
250     ntohl (f->redirect_device_input_next_index);
251   flow.redirect_queue = ntohl (f->redirect_queue);
252   flow.buffer_advance = ntohl (f->buffer_advance);
253
254   switch (flow.type)
255     {
256     case VNET_FLOW_TYPE_IP4:
257       ipv4_flow_convert (&f->flow.ip4, &flow.ip4);
258       break;
259     case VNET_FLOW_TYPE_IP6:
260       ipv6_flow_convert (&f->flow.ip6, &flow.ip6);
261       break;
262     case VNET_FLOW_TYPE_IP4_N_TUPLE:
263       ipv4_n_tuple_flow_convert (&f->flow.ip4_n_tuple, &flow.ip4_n_tuple);
264       break;
265     case VNET_FLOW_TYPE_IP6_N_TUPLE:
266       ipv6_n_tuple_flow_convert (&f->flow.ip6_n_tuple, &flow.ip6_n_tuple);
267       break;
268     case VNET_FLOW_TYPE_IP4_N_TUPLE_TAGGED:
269       ipv4_n_tuple_tagged_flow_convert (&f->flow.ip4_n_tuple_tagged,
270                                         &flow.ip4_n_tuple_tagged);
271       break;
272     case VNET_FLOW_TYPE_IP6_N_TUPLE_TAGGED:
273       ipv6_n_tuple_tagged_flow_convert (&f->flow.ip6_n_tuple_tagged,
274                                         &flow.ip6_n_tuple_tagged);
275       break;
276     case VNET_FLOW_TYPE_IP4_L2TPV3OIP:
277       ipv4_l2tpv3oip_flow_convert (&f->flow.ip4_l2tpv3oip,
278                                    &flow.ip4_l2tpv3oip);
279       break;
280     case VNET_FLOW_TYPE_IP4_IPSEC_ESP:
281       ipv4_ipsec_esp_flow_convert (&f->flow.ip4_ipsec_esp,
282                                    &flow.ip4_ipsec_esp);
283       break;
284     case VNET_FLOW_TYPE_IP4_IPSEC_AH:
285       ipv4_ipsec_ah_flow_convert (&f->flow.ip4_ipsec_ah, &flow.ip4_ipsec_ah);
286       break;
287     case VNET_FLOW_TYPE_IP4_VXLAN:
288       ipv4_vxlan_flow_convert (&f->flow.ip4_vxlan, &flow.ip4_vxlan);
289       break;
290     case VNET_FLOW_TYPE_IP6_VXLAN:
291       ipv6_vxlan_flow_convert (&f->flow.ip6_vxlan, &flow.ip6_vxlan);
292       break;
293     case VNET_FLOW_TYPE_IP4_GTPU:
294       ipv4_gtpu_flow_convert (&f->flow.ip4_gtpu, &flow.ip4_gtpu);
295       break;
296     case VNET_FLOW_TYPE_IP4_GTPC:
297       ipv4_gtpc_flow_convert (&f->flow.ip4_gtpc, &flow.ip4_gtpc);
298       break;
299     default:
300       rv = VNET_FLOW_ERROR_NOT_SUPPORTED;
301       goto out;
302       break;
303     }
304
305   rv = vnet_flow_add (vnm, &flow, &flow_index);
306
307 out:
308   /* *INDENT-OFF* */
309   REPLY_MACRO2(VL_API_FLOW_ADD_REPLY,
310   ({
311     rmp->flow_index = ntohl (flow_index);
312   }));
313   /* *INDENT-ON* */
314 }
315
316 static void
317 vl_api_flow_del_t_handler (vl_api_flow_del_t * mp)
318 {
319   vl_api_flow_add_reply_t *rmp;
320   int rv = 0;
321
322   vnet_main_t *vnm = vnet_get_main ();
323   rv = vnet_flow_del (vnm, ntohl (mp->flow_index));
324
325   REPLY_MACRO (VL_API_FLOW_DEL_REPLY);
326 }
327
328 static void
329 vl_api_flow_enable_t_handler (vl_api_flow_enable_t * mp)
330 {
331   vl_api_flow_add_reply_t *rmp;
332   int rv = 0;
333
334   vnet_main_t *vnm = vnet_get_main ();
335   rv =
336     vnet_flow_enable (vnm, ntohl (mp->flow_index), ntohl (mp->hw_if_index));
337
338   REPLY_MACRO (VL_API_FLOW_ENABLE_REPLY);
339 }
340
341 static void
342 vl_api_flow_disable_t_handler (vl_api_flow_disable_t * mp)
343 {
344   vl_api_flow_add_reply_t *rmp;
345   int rv = 0;
346
347   vnet_main_t *vnm = vnet_get_main ();
348   rv =
349     vnet_flow_disable (vnm, ntohl (mp->flow_index), ntohl (mp->hw_if_index));
350
351   REPLY_MACRO (VL_API_FLOW_DISABLE_REPLY);
352 }
353
354 #define vl_msg_name_crc_list
355 #include <vnet/flow/flow.api.h>
356 #undef vl_msg_name_crc_list
357
358 /*
359  * flow_api_hookup
360  * Add vpe's API message handlers to the table.
361  * vlib has already mapped shared memory and
362  * added the client registration handlers.
363  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
364  */
365
366
367 static void
368 setup_message_id_table (api_main_t * am)
369 {
370 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
371   foreach_vl_msg_name_crc_flow;
372 #undef _
373 }
374
375 static clib_error_t *
376 hw_flow_api_hookup (vlib_main_t * vm)
377 {
378   api_main_t *am = vlibapi_get_main ();
379
380 #define _(N,n)                                                  \
381     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
382                            vl_api_##n##_t_handler,              \
383                            vl_noop_handler,                     \
384                            vl_api_##n##_t_endian,               \
385                            vl_api_##n##_t_print,                \
386                            sizeof(vl_api_##n##_t), 1);
387   foreach_vpe_api_msg;
388 #undef _
389
390   /*
391    * Set up the (msg_name, crc, message-id) table
392    */
393   setup_message_id_table (am);
394
395   return 0;
396 }
397
398 VLIB_API_INIT_FUNCTION (hw_flow_api_hookup);
399
400 /*
401  * fd.io coding-style-patch-verification: ON
402  *
403  * Local Variables:
404  * eval: (c-set-style "gnu")
405  * End:
406  */