4fcff896f47a74f8960c3d21ad66614ca5413166
[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 #include <vnet/format_fns.h>
34 #include <vnet/flow/flow.api_enum.h>
35 #include <vnet/flow/flow.api_types.h>
36
37 #define REPLY_MSG_ID_BASE flow_main.msg_id_base
38 #include <vlibapi/api_helper_macros.h>
39
40 static inline void
41 ipv4_addr_and_mask_convert (vl_api_ip4_address_and_mask_t * vl_api_addr,
42                             ip4_address_and_mask_t * vnet_addr)
43 {
44   clib_memcpy (vnet_addr, vl_api_addr, sizeof (*vnet_addr));
45 }
46
47 static inline void
48 ipv6_addr_and_mask_convert (vl_api_ip6_address_and_mask_t * vl_api_addr,
49                             ip6_address_and_mask_t * vnet_addr)
50 {
51   clib_memcpy (vnet_addr, vl_api_addr, sizeof (*vnet_addr));
52 }
53
54 static inline void
55 protocol_and_mask_convert (vl_api_ip_prot_and_mask_t * vl_api_protocol,
56                            ip_prot_and_mask_t * vnet_protocol)
57 {
58   vnet_protocol->prot = (ip_protocol_t) vl_api_protocol->prot;
59   vnet_protocol->mask = vl_api_protocol->mask;
60 }
61
62 static inline void
63 port_and_mask_convert (vl_api_ip_port_and_mask_t * vl_api_port,
64                        ip_port_and_mask_t * vnet_port)
65 {
66   vnet_port->port = ntohs (vl_api_port->port);
67   vnet_port->mask = ntohs (vl_api_port->mask);
68 }
69
70 static inline void
71 ipv4_flow_convert (vl_api_flow_ip4_t *vl_api_flow, vnet_flow_ip4_t *f)
72 {
73   ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
74   ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
75
76   protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
77 }
78
79 static void
80 ipv6_flow_convert (vl_api_flow_ip6_t *vl_api_flow, vnet_flow_ip6_t *f)
81 {
82   ipv6_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
83   ipv6_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
84
85   protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
86 }
87
88 static inline void
89 ipv4_n_tuple_flow_convert (vl_api_flow_ip4_n_tuple_t * vl_api_flow,
90                            vnet_flow_ip4_n_tuple_t * f)
91 {
92   ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
93   ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
94   protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
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
100 static void
101 ipv6_n_tuple_flow_convert (vl_api_flow_ip6_n_tuple_t * vl_api_flow,
102                            vnet_flow_ip6_n_tuple_t * f)
103 {
104   ipv6_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
105   ipv6_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
106   protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
107
108   port_and_mask_convert (&vl_api_flow->src_port, &f->src_port);
109   port_and_mask_convert (&vl_api_flow->dst_port, &f->dst_port);
110 }
111
112 static inline void
113 ipv4_n_tuple_tagged_flow_convert (vl_api_flow_ip4_n_tuple_tagged_t *
114                                   vl_api_flow,
115                                   vnet_flow_ip4_n_tuple_tagged_t * f)
116 {
117   return ipv4_n_tuple_flow_convert ((vl_api_flow_ip4_n_tuple_t *) vl_api_flow,
118                                     (vnet_flow_ip4_n_tuple_t *) f);
119 }
120
121 static inline void
122 ipv6_n_tuple_tagged_flow_convert (vl_api_flow_ip6_n_tuple_tagged_t *
123                                   vl_api_flow,
124                                   vnet_flow_ip6_n_tuple_tagged_t * f)
125 {
126   return ipv6_n_tuple_flow_convert ((vl_api_flow_ip6_n_tuple_t *) vl_api_flow,
127                                     (vnet_flow_ip6_n_tuple_t *) f);
128 }
129
130 static inline void
131 ipv4_l2tpv3oip_flow_convert (vl_api_flow_ip4_l2tpv3oip_t * vl_api_flow,
132                              vnet_flow_ip4_l2tpv3oip_t * f)
133 {
134   ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
135   ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
136
137   protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
138   f->session_id = ntohl (vl_api_flow->session_id);
139 }
140
141 static inline void
142 ipv4_ipsec_esp_flow_convert (vl_api_flow_ip4_ipsec_esp_t * vl_api_flow,
143                              vnet_flow_ip4_ipsec_esp_t * f)
144 {
145   ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
146   ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
147
148   protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
149   f->spi = ntohl (vl_api_flow->spi);
150 }
151
152 static inline void
153 ipv4_ipsec_ah_flow_convert (vl_api_flow_ip4_ipsec_ah_t * vl_api_flow,
154                             vnet_flow_ip4_ipsec_ah_t * f)
155 {
156   ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
157   ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
158
159   protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
160   f->spi = ntohl (vl_api_flow->spi);
161 }
162
163 static inline void
164 ipv4_vxlan_flow_convert (vl_api_flow_ip4_vxlan_t *vl_api_flow,
165                          vnet_flow_ip4_vxlan_t *f)
166 {
167   ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
168   ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
169   protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
170
171   port_and_mask_convert (&vl_api_flow->src_port, &f->src_port);
172   port_and_mask_convert (&vl_api_flow->dst_port, &f->dst_port);
173
174   f->vni = ntohl (vl_api_flow->vni);
175 }
176
177 static inline void
178 ipv6_vxlan_flow_convert (vl_api_flow_ip6_vxlan_t *vl_api_flow,
179                          vnet_flow_ip6_vxlan_t *f)
180 {
181   ipv6_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
182   ipv6_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
183   protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
184
185   port_and_mask_convert (&vl_api_flow->src_port, &f->src_port);
186   port_and_mask_convert (&vl_api_flow->dst_port, &f->dst_port);
187
188   f->vni = ntohl (vl_api_flow->vni);
189 }
190
191 static inline void
192 ipv4_gtpu_flow_convert (vl_api_flow_ip4_gtpu_t * vl_api_flow,
193                         vnet_flow_ip4_gtpu_t * f)
194 {
195   ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
196   ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
197
198   port_and_mask_convert (&vl_api_flow->src_port, &f->src_port);
199   port_and_mask_convert (&vl_api_flow->dst_port, &f->dst_port);
200
201   protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
202   f->teid = ntohl (vl_api_flow->teid);
203 }
204
205 static inline void
206 ipv4_gtpc_flow_convert (vl_api_flow_ip4_gtpc_t * vl_api_flow,
207                         vnet_flow_ip4_gtpc_t * f)
208 {
209   ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
210   ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
211
212   port_and_mask_convert (&vl_api_flow->src_port, &f->src_port);
213   port_and_mask_convert (&vl_api_flow->dst_port, &f->dst_port);
214
215   protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
216   f->teid = ntohl (vl_api_flow->teid);
217 }
218
219 static void
220 vl_api_flow_add_t_handler (vl_api_flow_add_t * mp)
221 {
222   vl_api_flow_add_reply_t *rmp;
223   int rv = 0;
224   vnet_flow_t flow;
225   u32 flow_index = ~0;
226   vl_api_flow_rule_t *f = &mp->flow;
227
228   vnet_main_t *vnm = vnet_get_main ();
229
230   flow.type = ntohl (f->type);
231   flow.actions = ntohl (f->actions);
232   flow.mark_flow_id = ntohl (f->mark_flow_id);
233   flow.redirect_node_index = ntohl (f->redirect_node_index);
234   flow.redirect_device_input_next_index =
235     ntohl (f->redirect_device_input_next_index);
236   flow.redirect_queue = ntohl (f->redirect_queue);
237   flow.buffer_advance = ntohl (f->buffer_advance);
238
239   switch (flow.type)
240     {
241     case VNET_FLOW_TYPE_IP4:
242       ipv4_flow_convert (&f->flow.ip4, &flow.ip4);
243       break;
244     case VNET_FLOW_TYPE_IP6:
245       ipv6_flow_convert (&f->flow.ip6, &flow.ip6);
246       break;
247     case VNET_FLOW_TYPE_IP4_N_TUPLE:
248       ipv4_n_tuple_flow_convert (&f->flow.ip4_n_tuple, &flow.ip4_n_tuple);
249       break;
250     case VNET_FLOW_TYPE_IP6_N_TUPLE:
251       ipv6_n_tuple_flow_convert (&f->flow.ip6_n_tuple, &flow.ip6_n_tuple);
252       break;
253     case VNET_FLOW_TYPE_IP4_N_TUPLE_TAGGED:
254       ipv4_n_tuple_tagged_flow_convert (&f->flow.ip4_n_tuple_tagged,
255                                         &flow.ip4_n_tuple_tagged);
256       break;
257     case VNET_FLOW_TYPE_IP6_N_TUPLE_TAGGED:
258       ipv6_n_tuple_tagged_flow_convert (&f->flow.ip6_n_tuple_tagged,
259                                         &flow.ip6_n_tuple_tagged);
260       break;
261     case VNET_FLOW_TYPE_IP4_L2TPV3OIP:
262       ipv4_l2tpv3oip_flow_convert (&f->flow.ip4_l2tpv3oip,
263                                    &flow.ip4_l2tpv3oip);
264       break;
265     case VNET_FLOW_TYPE_IP4_IPSEC_ESP:
266       ipv4_ipsec_esp_flow_convert (&f->flow.ip4_ipsec_esp,
267                                    &flow.ip4_ipsec_esp);
268       break;
269     case VNET_FLOW_TYPE_IP4_IPSEC_AH:
270       ipv4_ipsec_ah_flow_convert (&f->flow.ip4_ipsec_ah, &flow.ip4_ipsec_ah);
271       break;
272     case VNET_FLOW_TYPE_IP4_VXLAN:
273       ipv4_vxlan_flow_convert (&f->flow.ip4_vxlan, &flow.ip4_vxlan);
274       break;
275     case VNET_FLOW_TYPE_IP6_VXLAN:
276       ipv6_vxlan_flow_convert (&f->flow.ip6_vxlan, &flow.ip6_vxlan);
277       break;
278     case VNET_FLOW_TYPE_IP4_GTPU:
279       ipv4_gtpu_flow_convert (&f->flow.ip4_gtpu, &flow.ip4_gtpu);
280       break;
281     case VNET_FLOW_TYPE_IP4_GTPC:
282       ipv4_gtpc_flow_convert (&f->flow.ip4_gtpc, &flow.ip4_gtpc);
283       break;
284     default:
285       rv = VNET_FLOW_ERROR_NOT_SUPPORTED;
286       goto out;
287       break;
288     }
289
290   rv = vnet_flow_add (vnm, &flow, &flow_index);
291
292 out:
293   /* *INDENT-OFF* */
294   REPLY_MACRO2(VL_API_FLOW_ADD_REPLY,
295   ({
296     rmp->flow_index = ntohl (flow_index);
297   }));
298   /* *INDENT-ON* */
299 }
300
301 static void
302 vl_api_flow_del_t_handler (vl_api_flow_del_t * mp)
303 {
304   vl_api_flow_add_reply_t *rmp;
305   int rv = 0;
306
307   vnet_main_t *vnm = vnet_get_main ();
308   rv = vnet_flow_del (vnm, ntohl (mp->flow_index));
309
310   REPLY_MACRO (VL_API_FLOW_DEL_REPLY);
311 }
312
313 static void
314 vl_api_flow_enable_t_handler (vl_api_flow_enable_t * mp)
315 {
316   vl_api_flow_add_reply_t *rmp;
317   int rv = 0;
318
319   vnet_main_t *vnm = vnet_get_main ();
320   rv =
321     vnet_flow_enable (vnm, ntohl (mp->flow_index), ntohl (mp->hw_if_index));
322
323   REPLY_MACRO (VL_API_FLOW_ENABLE_REPLY);
324 }
325
326 static void
327 vl_api_flow_disable_t_handler (vl_api_flow_disable_t * mp)
328 {
329   vl_api_flow_add_reply_t *rmp;
330   int rv = 0;
331
332   vnet_main_t *vnm = vnet_get_main ();
333   rv =
334     vnet_flow_disable (vnm, ntohl (mp->flow_index), ntohl (mp->hw_if_index));
335
336   REPLY_MACRO (VL_API_FLOW_DISABLE_REPLY);
337 }
338
339 #include <vnet/flow/flow.api.c>
340 static clib_error_t *
341 hw_flow_api_hookup (vlib_main_t * vm)
342 {
343   flow_main.msg_id_base = setup_message_id_table ();
344
345   return 0;
346 }
347
348 VLIB_API_INIT_FUNCTION (hw_flow_api_hookup);
349
350 /*
351  * fd.io coding-style-patch-verification: ON
352  *
353  * Local Variables:
354  * eval: (c-set-style "gnu")
355  * End:
356  */