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