blob: b24c8510be5ea378a64c23d681c534d3067746a0 [file] [log] [blame]
Chenmin Sund0236f72020-07-27 17:54:40 +08001/*
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>
Florin Corasb040f982020-10-20 14:59:43 -070028#include <vnet/udp/udp_local.h>
Chenmin Sund0236f72020-07-27 17:54:40 +080029#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
55static inline void
56ipv4_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
62static inline void
63ipv6_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
69static inline void
Chenmin Sun34bfa502020-07-27 17:40:17 +080070protocol_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
77static inline void
Chenmin Sund0236f72020-07-27 17:54:40 +080078port_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
85static inline void
86ipv4_n_tuple_flow_convert (vl_api_flow_ip4_n_tuple_t * vl_api_flow,
87 vnet_flow_ip4_n_tuple_t * f)
88{
89 ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
90 ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
Chenmin Sun34bfa502020-07-27 17:40:17 +080091 protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
Chenmin Sund0236f72020-07-27 17:54:40 +080092
93 port_and_mask_convert (&vl_api_flow->src_port, &f->src_port);
94 port_and_mask_convert (&vl_api_flow->dst_port, &f->dst_port);
Chenmin Sund0236f72020-07-27 17:54:40 +080095}
96
97static void
98ipv6_n_tuple_flow_convert (vl_api_flow_ip6_n_tuple_t * vl_api_flow,
99 vnet_flow_ip6_n_tuple_t * f)
100{
101 ipv6_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
102 ipv6_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
Chenmin Sun34bfa502020-07-27 17:40:17 +0800103 protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
Chenmin Sund0236f72020-07-27 17:54:40 +0800104
105 port_and_mask_convert (&vl_api_flow->src_port, &f->src_port);
106 port_and_mask_convert (&vl_api_flow->dst_port, &f->dst_port);
Chenmin Sund0236f72020-07-27 17:54:40 +0800107}
108
109static inline void
110ipv4_n_tuple_tagged_flow_convert (vl_api_flow_ip4_n_tuple_tagged_t *
111 vl_api_flow,
112 vnet_flow_ip4_n_tuple_tagged_t * f)
113{
114 return ipv4_n_tuple_flow_convert ((vl_api_flow_ip4_n_tuple_t *) vl_api_flow,
115 (vnet_flow_ip4_n_tuple_t *) f);
116}
117
118static inline void
119ipv6_n_tuple_tagged_flow_convert (vl_api_flow_ip6_n_tuple_tagged_t *
120 vl_api_flow,
121 vnet_flow_ip6_n_tuple_tagged_t * f)
122{
123 return ipv6_n_tuple_flow_convert ((vl_api_flow_ip6_n_tuple_t *) vl_api_flow,
124 (vnet_flow_ip6_n_tuple_t *) f);
125}
126
127static inline void
128ipv4_l2tpv3oip_flow_convert (vl_api_flow_ip4_l2tpv3oip_t * vl_api_flow,
129 vnet_flow_ip4_l2tpv3oip_t * f)
130{
131 ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
132 ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
133
Chenmin Sun34bfa502020-07-27 17:40:17 +0800134 protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
Chenmin Sund0236f72020-07-27 17:54:40 +0800135 f->session_id = ntohl (vl_api_flow->session_id);
136}
137
138static inline void
139ipv4_ipsec_esp_flow_convert (vl_api_flow_ip4_ipsec_esp_t * vl_api_flow,
140 vnet_flow_ip4_ipsec_esp_t * f)
141{
142 ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
143 ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
144
Chenmin Sun34bfa502020-07-27 17:40:17 +0800145 protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
Chenmin Sund0236f72020-07-27 17:54:40 +0800146 f->spi = ntohl (vl_api_flow->spi);
147}
148
149static inline void
150ipv4_ipsec_ah_flow_convert (vl_api_flow_ip4_ipsec_ah_t * vl_api_flow,
151 vnet_flow_ip4_ipsec_ah_t * f)
152{
153 ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
154 ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
155
Chenmin Sun34bfa502020-07-27 17:40:17 +0800156 protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
Chenmin Sund0236f72020-07-27 17:54:40 +0800157 f->spi = ntohl (vl_api_flow->spi);
158}
159
160static inline void
161ipv4_gtpu_flow_convert (vl_api_flow_ip4_gtpu_t * vl_api_flow,
162 vnet_flow_ip4_gtpu_t * f)
163{
164 ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
165 ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
166
167 port_and_mask_convert (&vl_api_flow->src_port, &f->src_port);
168 port_and_mask_convert (&vl_api_flow->dst_port, &f->dst_port);
169
Chenmin Sun34bfa502020-07-27 17:40:17 +0800170 protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
Chenmin Sund0236f72020-07-27 17:54:40 +0800171 f->teid = ntohl (vl_api_flow->teid);
172}
173
174static inline void
175ipv4_gtpc_flow_convert (vl_api_flow_ip4_gtpc_t * vl_api_flow,
176 vnet_flow_ip4_gtpc_t * f)
177{
178 ipv4_addr_and_mask_convert (&vl_api_flow->src_addr, &f->src_addr);
179 ipv4_addr_and_mask_convert (&vl_api_flow->dst_addr, &f->dst_addr);
180
181 port_and_mask_convert (&vl_api_flow->src_port, &f->src_port);
182 port_and_mask_convert (&vl_api_flow->dst_port, &f->dst_port);
183
Chenmin Sun34bfa502020-07-27 17:40:17 +0800184 protocol_and_mask_convert (&vl_api_flow->protocol, &f->protocol);
Chenmin Sund0236f72020-07-27 17:54:40 +0800185 f->teid = ntohl (vl_api_flow->teid);
186}
187
188static void
189vl_api_flow_add_t_handler (vl_api_flow_add_t * mp)
190{
191 vl_api_flow_add_reply_t *rmp;
192 int rv = 0;
193 vnet_flow_t flow;
194 u32 flow_index = ~0;
195 vl_api_flow_rule_t *f = &mp->flow;
196
197 vnet_main_t *vnm = vnet_get_main ();
198
199 flow.type = ntohl (f->type);
200 flow.actions = ntohl (f->actions);
201 flow.mark_flow_id = ntohl (f->mark_flow_id);
202 flow.redirect_node_index = ntohl (f->redirect_node_index);
203 flow.redirect_device_input_next_index =
204 ntohl (f->redirect_device_input_next_index);
205 flow.redirect_queue = ntohl (f->redirect_queue);
206 flow.buffer_advance = ntohl (f->buffer_advance);
207
208 switch (flow.type)
209 {
210 case VNET_FLOW_TYPE_IP4_N_TUPLE:
211 ipv4_n_tuple_flow_convert (&f->flow.ip4_n_tuple, &flow.ip4_n_tuple);
212 break;
213 case VNET_FLOW_TYPE_IP6_N_TUPLE:
214 ipv6_n_tuple_flow_convert (&f->flow.ip6_n_tuple, &flow.ip6_n_tuple);
215 break;
216 case VNET_FLOW_TYPE_IP4_N_TUPLE_TAGGED:
217 ipv4_n_tuple_tagged_flow_convert (&f->flow.ip4_n_tuple_tagged,
218 &flow.ip4_n_tuple_tagged);
219 break;
220 case VNET_FLOW_TYPE_IP6_N_TUPLE_TAGGED:
221 ipv6_n_tuple_tagged_flow_convert (&f->flow.ip6_n_tuple_tagged,
222 &flow.ip6_n_tuple_tagged);
223 break;
224 case VNET_FLOW_TYPE_IP4_L2TPV3OIP:
225 ipv4_l2tpv3oip_flow_convert (&f->flow.ip4_l2tpv3oip,
226 &flow.ip4_l2tpv3oip);
227 break;
228 case VNET_FLOW_TYPE_IP4_IPSEC_ESP:
229 ipv4_ipsec_esp_flow_convert (&f->flow.ip4_ipsec_esp,
230 &flow.ip4_ipsec_esp);
231 break;
232 case VNET_FLOW_TYPE_IP4_IPSEC_AH:
233 ipv4_ipsec_ah_flow_convert (&f->flow.ip4_ipsec_ah, &flow.ip4_ipsec_ah);
234 break;
235 case VNET_FLOW_TYPE_IP4_GTPU:
236 ipv4_gtpu_flow_convert (&f->flow.ip4_gtpu, &flow.ip4_gtpu);
237 break;
238 case VNET_FLOW_TYPE_IP4_GTPC:
239 ipv4_gtpc_flow_convert (&f->flow.ip4_gtpc, &flow.ip4_gtpc);
240 break;
241 default:
242 rv = VNET_FLOW_ERROR_NOT_SUPPORTED;
243 goto out;
244 break;
Chenmin Sund0236f72020-07-27 17:54:40 +0800245 }
246
247 rv = vnet_flow_add (vnm, &flow, &flow_index);
248
Chenmin Sund0236f72020-07-27 17:54:40 +0800249out:
250 /* *INDENT-OFF* */
251 REPLY_MACRO2(VL_API_FLOW_ADD_REPLY,
252 ({
253 rmp->flow_index = ntohl (flow_index);
254 }));
Florin Corasb040f982020-10-20 14:59:43 -0700255 /* *INDENT-ON* */
Chenmin Sund0236f72020-07-27 17:54:40 +0800256}
257
258static void
259vl_api_flow_del_t_handler (vl_api_flow_del_t * mp)
260{
261 vl_api_flow_add_reply_t *rmp;
262 int rv = 0;
263
Florin Corasb040f982020-10-20 14:59:43 -0700264 vnet_main_t *vnm = vnet_get_main ();
265 rv = vnet_flow_del (vnm, ntohl (mp->flow_index));
Chenmin Sund0236f72020-07-27 17:54:40 +0800266
267 REPLY_MACRO (VL_API_FLOW_DEL_REPLY);
268}
269
270static void
271vl_api_flow_enable_t_handler (vl_api_flow_enable_t * mp)
272{
273 vl_api_flow_add_reply_t *rmp;
274 int rv = 0;
275
Florin Corasb040f982020-10-20 14:59:43 -0700276 vnet_main_t *vnm = vnet_get_main ();
277 rv =
278 vnet_flow_enable (vnm, ntohl (mp->flow_index), ntohl (mp->hw_if_index));
Chenmin Sund0236f72020-07-27 17:54:40 +0800279
280 REPLY_MACRO (VL_API_FLOW_ENABLE_REPLY);
281}
282
283static void
284vl_api_flow_disable_t_handler (vl_api_flow_disable_t * mp)
285{
286 vl_api_flow_add_reply_t *rmp;
287 int rv = 0;
288
Florin Corasb040f982020-10-20 14:59:43 -0700289 vnet_main_t *vnm = vnet_get_main ();
290 rv =
291 vnet_flow_disable (vnm, ntohl (mp->flow_index), ntohl (mp->hw_if_index));
Chenmin Sund0236f72020-07-27 17:54:40 +0800292
293 REPLY_MACRO (VL_API_FLOW_DISABLE_REPLY);
294}
295
296#define vl_msg_name_crc_list
297#include <vnet/flow/flow.api.h>
298#undef vl_msg_name_crc_list
299
300/*
301 * flow_api_hookup
302 * Add vpe's API message handlers to the table.
303 * vlib has already mapped shared memory and
304 * added the client registration handlers.
305 * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
306 */
307
308
309static void
310setup_message_id_table (api_main_t * am)
311{
312#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
313 foreach_vl_msg_name_crc_flow;
314#undef _
315}
316
317static clib_error_t *
318hw_flow_api_hookup (vlib_main_t * vm)
319{
320 api_main_t *am = vlibapi_get_main ();
321
322#define _(N,n) \
323 vl_msg_api_set_handlers(VL_API_##N, #n, \
324 vl_api_##n##_t_handler, \
325 vl_noop_handler, \
326 vl_api_##n##_t_endian, \
327 vl_api_##n##_t_print, \
328 sizeof(vl_api_##n##_t), 1);
329 foreach_vpe_api_msg;
330#undef _
331
332 /*
333 * Set up the (msg_name, crc, message-id) table
334 */
335 setup_message_id_table (am);
336
337 return 0;
338}
339
340VLIB_API_INIT_FUNCTION (hw_flow_api_hookup);
341
342/*
343 * fd.io coding-style-patch-verification: ON
344 *
345 * Local Variables:
346 * eval: (c-set-style "gnu")
347 * End:
348 */