]> git.proxmox.com Git - mirror_ovs.git/blob - lib/netdev-offload-dpdk.c
netdev-offload-dpdk: Support offload of clone tnl_push/output actions.
[mirror_ovs.git] / lib / netdev-offload-dpdk.c
1 /*
2 * Copyright (c) 2014, 2015, 2016, 2017 Nicira, Inc.
3 * Copyright (c) 2019 Mellanox Technologies, Ltd.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 #include <config.h>
18
19 #include <sys/types.h>
20 #include <netinet/ip6.h>
21 #include <rte_flow.h>
22
23 #include "cmap.h"
24 #include "dpif-netdev.h"
25 #include "netdev-offload-provider.h"
26 #include "netdev-provider.h"
27 #include "openvswitch/match.h"
28 #include "openvswitch/vlog.h"
29 #include "packets.h"
30 #include "uuid.h"
31
32 VLOG_DEFINE_THIS_MODULE(netdev_offload_dpdk);
33 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(100, 5);
34
35 /* Thread-safety
36 * =============
37 *
38 * Below API is NOT thread safe in following terms:
39 *
40 * - The caller must be sure that none of these functions will be called
41 * simultaneously. Even for different 'netdev's.
42 *
43 * - The caller must be sure that 'netdev' will not be destructed/deallocated.
44 *
45 * - The caller must be sure that 'netdev' configuration will not be changed.
46 * For example, simultaneous call of 'netdev_reconfigure()' for the same
47 * 'netdev' is forbidden.
48 *
49 * For current implementation all above restrictions could be fulfilled by
50 * taking the datapath 'port_mutex' in lib/dpif-netdev.c. */
51
52 /*
53 * A mapping from ufid to dpdk rte_flow.
54 */
55 static struct cmap ufid_to_rte_flow = CMAP_INITIALIZER;
56
57 struct ufid_to_rte_flow_data {
58 struct cmap_node node;
59 ovs_u128 ufid;
60 struct rte_flow *rte_flow;
61 bool actions_offloaded;
62 struct dpif_flow_stats stats;
63 };
64
65 /* Find rte_flow with @ufid. */
66 static struct ufid_to_rte_flow_data *
67 ufid_to_rte_flow_data_find(const ovs_u128 *ufid)
68 {
69 size_t hash = hash_bytes(ufid, sizeof *ufid, 0);
70 struct ufid_to_rte_flow_data *data;
71
72 CMAP_FOR_EACH_WITH_HASH (data, node, hash, &ufid_to_rte_flow) {
73 if (ovs_u128_equals(*ufid, data->ufid)) {
74 return data;
75 }
76 }
77
78 return NULL;
79 }
80
81 static inline void
82 ufid_to_rte_flow_associate(const ovs_u128 *ufid,
83 struct rte_flow *rte_flow, bool actions_offloaded)
84 {
85 size_t hash = hash_bytes(ufid, sizeof *ufid, 0);
86 struct ufid_to_rte_flow_data *data = xzalloc(sizeof *data);
87 struct ufid_to_rte_flow_data *data_prev;
88
89 /*
90 * We should not simply overwrite an existing rte flow.
91 * We should have deleted it first before re-adding it.
92 * Thus, if following assert triggers, something is wrong:
93 * the rte_flow is not destroyed.
94 */
95 data_prev = ufid_to_rte_flow_data_find(ufid);
96 if (data_prev) {
97 ovs_assert(data_prev->rte_flow == NULL);
98 }
99
100 data->ufid = *ufid;
101 data->rte_flow = rte_flow;
102 data->actions_offloaded = actions_offloaded;
103
104 cmap_insert(&ufid_to_rte_flow,
105 CONST_CAST(struct cmap_node *, &data->node), hash);
106 }
107
108 static inline void
109 ufid_to_rte_flow_disassociate(const ovs_u128 *ufid)
110 {
111 size_t hash = hash_bytes(ufid, sizeof *ufid, 0);
112 struct ufid_to_rte_flow_data *data;
113
114 CMAP_FOR_EACH_WITH_HASH (data, node, hash, &ufid_to_rte_flow) {
115 if (ovs_u128_equals(*ufid, data->ufid)) {
116 cmap_remove(&ufid_to_rte_flow,
117 CONST_CAST(struct cmap_node *, &data->node), hash);
118 ovsrcu_postpone(free, data);
119 return;
120 }
121 }
122
123 VLOG_WARN("ufid "UUID_FMT" is not associated with an rte flow",
124 UUID_ARGS((struct uuid *) ufid));
125 }
126
127 /*
128 * To avoid individual xrealloc calls for each new element, a 'curent_max'
129 * is used to keep track of current allocated number of elements. Starts
130 * by 8 and doubles on each xrealloc call.
131 */
132 struct flow_patterns {
133 struct rte_flow_item *items;
134 int cnt;
135 int current_max;
136 };
137
138 struct flow_actions {
139 struct rte_flow_action *actions;
140 int cnt;
141 int current_max;
142 };
143
144 static void
145 dump_flow_attr(struct ds *s, const struct rte_flow_attr *attr)
146 {
147 ds_put_format(s, "%s%spriority %"PRIu32" group %"PRIu32" %s",
148 attr->ingress ? "ingress " : "",
149 attr->egress ? "egress " : "", attr->priority, attr->group,
150 attr->transfer ? "transfer " : "");
151 }
152
153 /* Adds one pattern item 'field' with the 'mask' to dynamic string 's' using
154 * 'testpmd command'-like format. */
155 #define DUMP_PATTERN_ITEM(mask, field, fmt, spec_pri, mask_pri) \
156 if (is_all_ones(&mask, sizeof mask)) { \
157 ds_put_format(s, field " is " fmt " ", spec_pri); \
158 } else if (!is_all_zeros(&mask, sizeof mask)) { \
159 ds_put_format(s, field " spec " fmt " " field " mask " fmt " ", \
160 spec_pri, mask_pri); \
161 }
162
163 static void
164 dump_flow_pattern(struct ds *s, const struct rte_flow_item *item)
165 {
166 if (item->type == RTE_FLOW_ITEM_TYPE_ETH) {
167 const struct rte_flow_item_eth *eth_spec = item->spec;
168 const struct rte_flow_item_eth *eth_mask = item->mask;
169
170 ds_put_cstr(s, "eth ");
171 if (eth_spec) {
172 if (!eth_mask) {
173 eth_mask = &rte_flow_item_eth_mask;
174 }
175 DUMP_PATTERN_ITEM(eth_mask->src, "src", ETH_ADDR_FMT,
176 ETH_ADDR_BYTES_ARGS(eth_spec->src.addr_bytes),
177 ETH_ADDR_BYTES_ARGS(eth_mask->src.addr_bytes));
178 DUMP_PATTERN_ITEM(eth_mask->dst, "dst", ETH_ADDR_FMT,
179 ETH_ADDR_BYTES_ARGS(eth_spec->dst.addr_bytes),
180 ETH_ADDR_BYTES_ARGS(eth_mask->dst.addr_bytes));
181 DUMP_PATTERN_ITEM(eth_mask->type, "type", "0x%04"PRIx16,
182 ntohs(eth_spec->type),
183 ntohs(eth_mask->type));
184 }
185 ds_put_cstr(s, "/ ");
186 } else if (item->type == RTE_FLOW_ITEM_TYPE_VLAN) {
187 const struct rte_flow_item_vlan *vlan_spec = item->spec;
188 const struct rte_flow_item_vlan *vlan_mask = item->mask;
189
190 ds_put_cstr(s, "vlan ");
191 if (vlan_spec) {
192 if (!vlan_mask) {
193 vlan_mask = &rte_flow_item_vlan_mask;
194 }
195 DUMP_PATTERN_ITEM(vlan_mask->inner_type, "inner_type", "0x%"PRIx16,
196 ntohs(vlan_spec->inner_type),
197 ntohs(vlan_mask->inner_type));
198 DUMP_PATTERN_ITEM(vlan_mask->tci, "tci", "0x%"PRIx16,
199 ntohs(vlan_spec->tci), ntohs(vlan_mask->tci));
200 }
201 ds_put_cstr(s, "/ ");
202 } else if (item->type == RTE_FLOW_ITEM_TYPE_IPV4) {
203 const struct rte_flow_item_ipv4 *ipv4_spec = item->spec;
204 const struct rte_flow_item_ipv4 *ipv4_mask = item->mask;
205
206 ds_put_cstr(s, "ipv4 ");
207 if (ipv4_spec) {
208 if (!ipv4_mask) {
209 ipv4_mask = &rte_flow_item_ipv4_mask;
210 }
211 DUMP_PATTERN_ITEM(ipv4_mask->hdr.src_addr, "src", IP_FMT,
212 IP_ARGS(ipv4_spec->hdr.src_addr),
213 IP_ARGS(ipv4_mask->hdr.src_addr));
214 DUMP_PATTERN_ITEM(ipv4_mask->hdr.dst_addr, "dst", IP_FMT,
215 IP_ARGS(ipv4_spec->hdr.dst_addr),
216 IP_ARGS(ipv4_mask->hdr.dst_addr));
217 DUMP_PATTERN_ITEM(ipv4_mask->hdr.next_proto_id, "proto",
218 "0x%"PRIx8, ipv4_spec->hdr.next_proto_id,
219 ipv4_mask->hdr.next_proto_id);
220 DUMP_PATTERN_ITEM(ipv4_mask->hdr.type_of_service, "tos",
221 "0x%"PRIx8, ipv4_spec->hdr.type_of_service,
222 ipv4_mask->hdr.type_of_service);
223 DUMP_PATTERN_ITEM(ipv4_mask->hdr.time_to_live, "ttl",
224 "0x%"PRIx8, ipv4_spec->hdr.time_to_live,
225 ipv4_mask->hdr.time_to_live);
226 }
227 ds_put_cstr(s, "/ ");
228 } else if (item->type == RTE_FLOW_ITEM_TYPE_UDP) {
229 const struct rte_flow_item_udp *udp_spec = item->spec;
230 const struct rte_flow_item_udp *udp_mask = item->mask;
231
232 ds_put_cstr(s, "udp ");
233 if (udp_spec) {
234 if (!udp_mask) {
235 udp_mask = &rte_flow_item_udp_mask;
236 }
237 DUMP_PATTERN_ITEM(udp_mask->hdr.src_port, "src", "%"PRIu16,
238 ntohs(udp_spec->hdr.src_port),
239 ntohs(udp_mask->hdr.src_port));
240 DUMP_PATTERN_ITEM(udp_mask->hdr.dst_port, "dst", "%"PRIu16,
241 ntohs(udp_spec->hdr.dst_port),
242 ntohs(udp_mask->hdr.dst_port));
243 }
244 ds_put_cstr(s, "/ ");
245 } else if (item->type == RTE_FLOW_ITEM_TYPE_SCTP) {
246 const struct rte_flow_item_sctp *sctp_spec = item->spec;
247 const struct rte_flow_item_sctp *sctp_mask = item->mask;
248
249 ds_put_cstr(s, "sctp ");
250 if (sctp_spec) {
251 if (!sctp_mask) {
252 sctp_mask = &rte_flow_item_sctp_mask;
253 }
254 DUMP_PATTERN_ITEM(sctp_mask->hdr.src_port, "src", "%"PRIu16,
255 ntohs(sctp_spec->hdr.src_port),
256 ntohs(sctp_mask->hdr.src_port));
257 DUMP_PATTERN_ITEM(sctp_mask->hdr.dst_port, "dst", "%"PRIu16,
258 ntohs(sctp_spec->hdr.dst_port),
259 ntohs(sctp_mask->hdr.dst_port));
260 }
261 ds_put_cstr(s, "/ ");
262 } else if (item->type == RTE_FLOW_ITEM_TYPE_ICMP) {
263 const struct rte_flow_item_icmp *icmp_spec = item->spec;
264 const struct rte_flow_item_icmp *icmp_mask = item->mask;
265
266 ds_put_cstr(s, "icmp ");
267 if (icmp_spec) {
268 if (!icmp_mask) {
269 icmp_mask = &rte_flow_item_icmp_mask;
270 }
271 DUMP_PATTERN_ITEM(icmp_mask->hdr.icmp_type, "icmp_type", "%"PRIu8,
272 icmp_spec->hdr.icmp_type,
273 icmp_mask->hdr.icmp_type);
274 DUMP_PATTERN_ITEM(icmp_mask->hdr.icmp_code, "icmp_code", "%"PRIu8,
275 icmp_spec->hdr.icmp_code,
276 icmp_mask->hdr.icmp_code);
277 }
278 ds_put_cstr(s, "/ ");
279 } else if (item->type == RTE_FLOW_ITEM_TYPE_TCP) {
280 const struct rte_flow_item_tcp *tcp_spec = item->spec;
281 const struct rte_flow_item_tcp *tcp_mask = item->mask;
282
283 ds_put_cstr(s, "tcp ");
284 if (tcp_spec) {
285 if (!tcp_mask) {
286 tcp_mask = &rte_flow_item_tcp_mask;
287 }
288 DUMP_PATTERN_ITEM(tcp_mask->hdr.src_port, "src", "%"PRIu16,
289 ntohs(tcp_spec->hdr.src_port),
290 ntohs(tcp_mask->hdr.src_port));
291 DUMP_PATTERN_ITEM(tcp_mask->hdr.dst_port, "dst", "%"PRIu16,
292 ntohs(tcp_spec->hdr.dst_port),
293 ntohs(tcp_mask->hdr.dst_port));
294 DUMP_PATTERN_ITEM(tcp_mask->hdr.tcp_flags, "flags", "0x%"PRIx8,
295 tcp_spec->hdr.tcp_flags,
296 tcp_mask->hdr.tcp_flags);
297 }
298 ds_put_cstr(s, "/ ");
299 } else if (item->type == RTE_FLOW_ITEM_TYPE_IPV6) {
300 const struct rte_flow_item_ipv6 *ipv6_spec = item->spec;
301 const struct rte_flow_item_ipv6 *ipv6_mask = item->mask;
302
303 char addr_str[INET6_ADDRSTRLEN];
304 char mask_str[INET6_ADDRSTRLEN];
305 struct in6_addr addr, mask;
306
307 ds_put_cstr(s, "ipv6 ");
308 if (ipv6_spec) {
309 if (!ipv6_mask) {
310 ipv6_mask = &rte_flow_item_ipv6_mask;
311 }
312 memcpy(&addr, ipv6_spec->hdr.src_addr, sizeof addr);
313 memcpy(&mask, ipv6_mask->hdr.src_addr, sizeof mask);
314 ipv6_string_mapped(addr_str, &addr);
315 ipv6_string_mapped(mask_str, &mask);
316 DUMP_PATTERN_ITEM(mask, "src", "%s", addr_str, mask_str);
317
318 memcpy(&addr, ipv6_spec->hdr.dst_addr, sizeof addr);
319 memcpy(&mask, ipv6_mask->hdr.dst_addr, sizeof mask);
320 ipv6_string_mapped(addr_str, &addr);
321 ipv6_string_mapped(mask_str, &mask);
322 DUMP_PATTERN_ITEM(mask, "dst", "%s", addr_str, mask_str);
323
324 DUMP_PATTERN_ITEM(ipv6_mask->hdr.proto, "proto", "%"PRIu8,
325 ipv6_spec->hdr.proto, ipv6_mask->hdr.proto);
326 DUMP_PATTERN_ITEM(ipv6_mask->hdr.vtc_flow, "tc", "0x%"PRIx32,
327 ntohl(ipv6_spec->hdr.vtc_flow),
328 ntohl(ipv6_mask->hdr.vtc_flow));
329 DUMP_PATTERN_ITEM(ipv6_mask->hdr.hop_limits, "hop", "%"PRIu8,
330 ipv6_spec->hdr.hop_limits,
331 ipv6_mask->hdr.hop_limits);
332 }
333 ds_put_cstr(s, "/ ");
334 } else {
335 ds_put_format(s, "unknown rte flow pattern (%d)\n", item->type);
336 }
337 }
338
339 static void
340 dump_flow_action(struct ds *s, struct ds *s_extra,
341 const struct rte_flow_action *actions)
342 {
343 if (actions->type == RTE_FLOW_ACTION_TYPE_MARK) {
344 const struct rte_flow_action_mark *mark = actions->conf;
345
346 ds_put_cstr(s, "mark ");
347 if (mark) {
348 ds_put_format(s, "id %d ", mark->id);
349 }
350 ds_put_cstr(s, "/ ");
351 } else if (actions->type == RTE_FLOW_ACTION_TYPE_RSS) {
352 ds_put_cstr(s, "rss / ");
353 } else if (actions->type == RTE_FLOW_ACTION_TYPE_COUNT) {
354 ds_put_cstr(s, "count / ");
355 } else if (actions->type == RTE_FLOW_ACTION_TYPE_PORT_ID) {
356 const struct rte_flow_action_port_id *port_id = actions->conf;
357
358 ds_put_cstr(s, "port_id ");
359 if (port_id) {
360 ds_put_format(s, "original %d id %d ",
361 port_id->original, port_id->id);
362 }
363 ds_put_cstr(s, "/ ");
364 } else if (actions->type == RTE_FLOW_ACTION_TYPE_DROP) {
365 ds_put_cstr(s, "drop / ");
366 } else if (actions->type == RTE_FLOW_ACTION_TYPE_SET_MAC_SRC ||
367 actions->type == RTE_FLOW_ACTION_TYPE_SET_MAC_DST) {
368 const struct rte_flow_action_set_mac *set_mac = actions->conf;
369
370 char *dirstr = actions->type == RTE_FLOW_ACTION_TYPE_SET_MAC_DST
371 ? "dst" : "src";
372
373 ds_put_format(s, "set_mac_%s ", dirstr);
374 if (set_mac) {
375 ds_put_format(s, "mac_addr "ETH_ADDR_FMT" ",
376 ETH_ADDR_BYTES_ARGS(set_mac->mac_addr));
377 }
378 ds_put_cstr(s, "/ ");
379 } else if (actions->type == RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC ||
380 actions->type == RTE_FLOW_ACTION_TYPE_SET_IPV4_DST) {
381 const struct rte_flow_action_set_ipv4 *set_ipv4 = actions->conf;
382 char *dirstr = actions->type == RTE_FLOW_ACTION_TYPE_SET_IPV4_DST
383 ? "dst" : "src";
384
385 ds_put_format(s, "set_ipv4_%s ", dirstr);
386 if (set_ipv4) {
387 ds_put_format(s, "ipv4_addr "IP_FMT" ",
388 IP_ARGS(set_ipv4->ipv4_addr));
389 }
390 ds_put_cstr(s, "/ ");
391 } else if (actions->type == RTE_FLOW_ACTION_TYPE_SET_TTL) {
392 const struct rte_flow_action_set_ttl *set_ttl = actions->conf;
393
394 ds_put_cstr(s, "set_ttl ");
395 if (set_ttl) {
396 ds_put_format(s, "ttl_value %d ", set_ttl->ttl_value);
397 }
398 ds_put_cstr(s, "/ ");
399 } else if (actions->type == RTE_FLOW_ACTION_TYPE_SET_TP_SRC ||
400 actions->type == RTE_FLOW_ACTION_TYPE_SET_TP_DST) {
401 const struct rte_flow_action_set_tp *set_tp = actions->conf;
402 char *dirstr = actions->type == RTE_FLOW_ACTION_TYPE_SET_TP_DST
403 ? "dst" : "src";
404
405 ds_put_format(s, "set_tp_%s ", dirstr);
406 if (set_tp) {
407 ds_put_format(s, "port %"PRIu16" ", ntohs(set_tp->port));
408 }
409 ds_put_cstr(s, "/ ");
410 } else if (actions->type == RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN) {
411 const struct rte_flow_action_of_push_vlan *of_push_vlan =
412 actions->conf;
413
414 ds_put_cstr(s, "of_push_vlan ");
415 if (of_push_vlan) {
416 ds_put_format(s, "ethertype 0x%"PRIx16" ",
417 ntohs(of_push_vlan->ethertype));
418 }
419 ds_put_cstr(s, "/ ");
420 } else if (actions->type == RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP) {
421 const struct rte_flow_action_of_set_vlan_pcp *of_set_vlan_pcp =
422 actions->conf;
423
424 ds_put_cstr(s, "of_set_vlan_pcp ");
425 if (of_set_vlan_pcp) {
426 ds_put_format(s, "vlan_pcp %"PRIu8" ", of_set_vlan_pcp->vlan_pcp);
427 }
428 ds_put_cstr(s, "/ ");
429 } else if (actions->type == RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID) {
430 const struct rte_flow_action_of_set_vlan_vid *of_set_vlan_vid =
431 actions->conf;
432
433 ds_put_cstr(s, "of_set_vlan_vid ");
434 if (of_set_vlan_vid) {
435 ds_put_format(s, "vlan_vid %"PRIu16" ",
436 ntohs(of_set_vlan_vid->vlan_vid));
437 }
438 ds_put_cstr(s, "/ ");
439 } else if (actions->type == RTE_FLOW_ACTION_TYPE_OF_POP_VLAN) {
440 ds_put_cstr(s, "of_pop_vlan / ");
441 } else if (actions->type == RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC ||
442 actions->type == RTE_FLOW_ACTION_TYPE_SET_IPV6_DST) {
443 const struct rte_flow_action_set_ipv6 *set_ipv6 = actions->conf;
444
445 char *dirstr = actions->type == RTE_FLOW_ACTION_TYPE_SET_IPV6_DST
446 ? "dst" : "src";
447
448 ds_put_format(s, "set_ipv6_%s ", dirstr);
449 if (set_ipv6) {
450 ds_put_cstr(s, "ipv6_addr ");
451 ipv6_format_addr((struct in6_addr *) &set_ipv6->ipv6_addr, s);
452 ds_put_cstr(s, " ");
453 }
454 ds_put_cstr(s, "/ ");
455 } else if (actions->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
456 const struct rte_flow_action_raw_encap *raw_encap = actions->conf;
457
458 ds_put_cstr(s, "raw_encap index 0 / ");
459 if (raw_encap) {
460 ds_put_format(s_extra, "Raw-encap size=%ld set raw_encap 0 raw "
461 "pattern is ", raw_encap->size);
462 for (int i = 0; i < raw_encap->size; i++) {
463 ds_put_format(s_extra, "%02x", raw_encap->data[i]);
464 }
465 ds_put_cstr(s_extra, " / end_set;");
466 }
467 } else {
468 ds_put_format(s, "unknown rte flow action (%d)\n", actions->type);
469 }
470 }
471
472 static struct ds *
473 dump_flow(struct ds *s, struct ds *s_extra,
474 const struct rte_flow_attr *attr,
475 const struct rte_flow_item *items,
476 const struct rte_flow_action *actions)
477 {
478 if (attr) {
479 dump_flow_attr(s, attr);
480 }
481 ds_put_cstr(s, "pattern ");
482 while (items && items->type != RTE_FLOW_ITEM_TYPE_END) {
483 dump_flow_pattern(s, items++);
484 }
485 ds_put_cstr(s, "end actions ");
486 while (actions && actions->type != RTE_FLOW_ACTION_TYPE_END) {
487 dump_flow_action(s, s_extra, actions++);
488 }
489 ds_put_cstr(s, "end");
490 return s;
491 }
492
493 static struct rte_flow *
494 netdev_offload_dpdk_flow_create(struct netdev *netdev,
495 const struct rte_flow_attr *attr,
496 const struct rte_flow_item *items,
497 const struct rte_flow_action *actions,
498 struct rte_flow_error *error)
499 {
500 struct ds s_extra = DS_EMPTY_INITIALIZER;
501 struct ds s = DS_EMPTY_INITIALIZER;
502 struct rte_flow *flow;
503 char *extra_str;
504
505 flow = netdev_dpdk_rte_flow_create(netdev, attr, items, actions, error);
506 if (flow) {
507 if (!VLOG_DROP_DBG(&rl)) {
508 dump_flow(&s, &s_extra, attr, items, actions);
509 extra_str = ds_cstr(&s_extra);
510 VLOG_DBG_RL(&rl, "%s: rte_flow 0x%"PRIxPTR" %s flow create %d %s",
511 netdev_get_name(netdev), (intptr_t) flow, extra_str,
512 netdev_dpdk_get_port_id(netdev), ds_cstr(&s));
513 }
514 } else {
515 enum vlog_level level = VLL_WARN;
516
517 if (error->type == RTE_FLOW_ERROR_TYPE_ACTION) {
518 level = VLL_DBG;
519 }
520 VLOG_RL(&rl, level, "%s: rte_flow creation failed: %d (%s).",
521 netdev_get_name(netdev), error->type, error->message);
522 if (!vlog_should_drop(&this_module, level, &rl)) {
523 dump_flow(&s, &s_extra, attr, items, actions);
524 extra_str = ds_cstr(&s_extra);
525 VLOG_RL(&rl, level, "%s: Failed flow: %s flow create %d %s",
526 netdev_get_name(netdev), extra_str,
527 netdev_dpdk_get_port_id(netdev), ds_cstr(&s));
528 }
529 }
530 ds_destroy(&s);
531 ds_destroy(&s_extra);
532 return flow;
533 }
534
535 static void
536 add_flow_pattern(struct flow_patterns *patterns, enum rte_flow_item_type type,
537 const void *spec, const void *mask)
538 {
539 int cnt = patterns->cnt;
540
541 if (cnt == 0) {
542 patterns->current_max = 8;
543 patterns->items = xcalloc(patterns->current_max,
544 sizeof *patterns->items);
545 } else if (cnt == patterns->current_max) {
546 patterns->current_max *= 2;
547 patterns->items = xrealloc(patterns->items, patterns->current_max *
548 sizeof *patterns->items);
549 }
550
551 patterns->items[cnt].type = type;
552 patterns->items[cnt].spec = spec;
553 patterns->items[cnt].mask = mask;
554 patterns->items[cnt].last = NULL;
555 patterns->cnt++;
556 }
557
558 static void
559 add_flow_action(struct flow_actions *actions, enum rte_flow_action_type type,
560 const void *conf)
561 {
562 int cnt = actions->cnt;
563
564 if (cnt == 0) {
565 actions->current_max = 8;
566 actions->actions = xcalloc(actions->current_max,
567 sizeof *actions->actions);
568 } else if (cnt == actions->current_max) {
569 actions->current_max *= 2;
570 actions->actions = xrealloc(actions->actions, actions->current_max *
571 sizeof *actions->actions);
572 }
573
574 actions->actions[cnt].type = type;
575 actions->actions[cnt].conf = conf;
576 actions->cnt++;
577 }
578
579 static void
580 free_flow_patterns(struct flow_patterns *patterns)
581 {
582 int i;
583
584 for (i = 0; i < patterns->cnt; i++) {
585 if (patterns->items[i].spec) {
586 free(CONST_CAST(void *, patterns->items[i].spec));
587 }
588 if (patterns->items[i].mask) {
589 free(CONST_CAST(void *, patterns->items[i].mask));
590 }
591 }
592 free(patterns->items);
593 patterns->items = NULL;
594 patterns->cnt = 0;
595 }
596
597 static void
598 free_flow_actions(struct flow_actions *actions)
599 {
600 int i;
601
602 for (i = 0; i < actions->cnt; i++) {
603 if (actions->actions[i].conf) {
604 free(CONST_CAST(void *, actions->actions[i].conf));
605 }
606 }
607 free(actions->actions);
608 actions->actions = NULL;
609 actions->cnt = 0;
610 }
611
612 static int
613 parse_flow_match(struct flow_patterns *patterns,
614 struct match *match)
615 {
616 uint8_t *next_proto_mask = NULL;
617 struct flow *consumed_masks;
618 uint8_t proto = 0;
619
620 consumed_masks = &match->wc.masks;
621
622 memset(&consumed_masks->in_port, 0, sizeof consumed_masks->in_port);
623 /* recirc id must be zero. */
624 if (match->wc.masks.recirc_id & match->flow.recirc_id) {
625 return -1;
626 }
627 consumed_masks->recirc_id = 0;
628 consumed_masks->packet_type = 0;
629
630 /* Eth */
631 if (match->wc.masks.dl_type ||
632 !eth_addr_is_zero(match->wc.masks.dl_src) ||
633 !eth_addr_is_zero(match->wc.masks.dl_dst)) {
634 struct rte_flow_item_eth *spec, *mask;
635
636 spec = xzalloc(sizeof *spec);
637 mask = xzalloc(sizeof *mask);
638
639 memcpy(&spec->dst, &match->flow.dl_dst, sizeof spec->dst);
640 memcpy(&spec->src, &match->flow.dl_src, sizeof spec->src);
641 spec->type = match->flow.dl_type;
642
643 memcpy(&mask->dst, &match->wc.masks.dl_dst, sizeof mask->dst);
644 memcpy(&mask->src, &match->wc.masks.dl_src, sizeof mask->src);
645 mask->type = match->wc.masks.dl_type;
646
647 memset(&consumed_masks->dl_dst, 0, sizeof consumed_masks->dl_dst);
648 memset(&consumed_masks->dl_src, 0, sizeof consumed_masks->dl_src);
649 consumed_masks->dl_type = 0;
650
651 add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_ETH, spec, mask);
652 }
653
654 /* VLAN */
655 if (match->wc.masks.vlans[0].tci && match->flow.vlans[0].tci) {
656 struct rte_flow_item_vlan *spec, *mask;
657
658 spec = xzalloc(sizeof *spec);
659 mask = xzalloc(sizeof *mask);
660
661 spec->tci = match->flow.vlans[0].tci & ~htons(VLAN_CFI);
662 mask->tci = match->wc.masks.vlans[0].tci & ~htons(VLAN_CFI);
663
664 /* Match any protocols. */
665 mask->inner_type = 0;
666
667 add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_VLAN, spec, mask);
668 }
669 /* For untagged matching match->wc.masks.vlans[0].tci is 0xFFFF and
670 * match->flow.vlans[0].tci is 0. Consuming is needed outside of the if
671 * scope to handle that.
672 */
673 memset(&consumed_masks->vlans[0], 0, sizeof consumed_masks->vlans[0]);
674
675 /* IP v4 */
676 if (match->flow.dl_type == htons(ETH_TYPE_IP)) {
677 struct rte_flow_item_ipv4 *spec, *mask;
678
679 spec = xzalloc(sizeof *spec);
680 mask = xzalloc(sizeof *mask);
681
682 spec->hdr.type_of_service = match->flow.nw_tos;
683 spec->hdr.time_to_live = match->flow.nw_ttl;
684 spec->hdr.next_proto_id = match->flow.nw_proto;
685 spec->hdr.src_addr = match->flow.nw_src;
686 spec->hdr.dst_addr = match->flow.nw_dst;
687
688 mask->hdr.type_of_service = match->wc.masks.nw_tos;
689 mask->hdr.time_to_live = match->wc.masks.nw_ttl;
690 mask->hdr.next_proto_id = match->wc.masks.nw_proto;
691 mask->hdr.src_addr = match->wc.masks.nw_src;
692 mask->hdr.dst_addr = match->wc.masks.nw_dst;
693
694 consumed_masks->nw_tos = 0;
695 consumed_masks->nw_ttl = 0;
696 consumed_masks->nw_proto = 0;
697 consumed_masks->nw_src = 0;
698 consumed_masks->nw_dst = 0;
699
700 add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_IPV4, spec, mask);
701
702 /* Save proto for L4 protocol setup. */
703 proto = spec->hdr.next_proto_id &
704 mask->hdr.next_proto_id;
705 next_proto_mask = &mask->hdr.next_proto_id;
706 }
707 /* If fragmented, then don't HW accelerate - for now. */
708 if (match->wc.masks.nw_frag & match->flow.nw_frag) {
709 return -1;
710 }
711 consumed_masks->nw_frag = 0;
712
713 /* IP v6 */
714 if (match->flow.dl_type == htons(ETH_TYPE_IPV6)) {
715 struct rte_flow_item_ipv6 *spec, *mask;
716
717 spec = xzalloc(sizeof *spec);
718 mask = xzalloc(sizeof *mask);
719
720 spec->hdr.proto = match->flow.nw_proto;
721 spec->hdr.hop_limits = match->flow.nw_ttl;
722 spec->hdr.vtc_flow =
723 htonl((uint32_t) match->flow.nw_tos << RTE_IPV6_HDR_TC_SHIFT);
724 memcpy(spec->hdr.src_addr, &match->flow.ipv6_src,
725 sizeof spec->hdr.src_addr);
726 memcpy(spec->hdr.dst_addr, &match->flow.ipv6_dst,
727 sizeof spec->hdr.dst_addr);
728
729 mask->hdr.proto = match->wc.masks.nw_proto;
730 mask->hdr.hop_limits = match->wc.masks.nw_ttl;
731 mask->hdr.vtc_flow =
732 htonl((uint32_t) match->wc.masks.nw_tos << RTE_IPV6_HDR_TC_SHIFT);
733 memcpy(mask->hdr.src_addr, &match->wc.masks.ipv6_src,
734 sizeof mask->hdr.src_addr);
735 memcpy(mask->hdr.dst_addr, &match->wc.masks.ipv6_dst,
736 sizeof mask->hdr.dst_addr);
737
738 consumed_masks->nw_proto = 0;
739 consumed_masks->nw_ttl = 0;
740 consumed_masks->nw_tos = 0;
741 memset(&consumed_masks->ipv6_src, 0, sizeof consumed_masks->ipv6_src);
742 memset(&consumed_masks->ipv6_dst, 0, sizeof consumed_masks->ipv6_dst);
743
744 add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_IPV6, spec, mask);
745
746 /* Save proto for L4 protocol setup. */
747 proto = spec->hdr.proto & mask->hdr.proto;
748 next_proto_mask = &mask->hdr.proto;
749 }
750
751 if (proto != IPPROTO_ICMP && proto != IPPROTO_UDP &&
752 proto != IPPROTO_SCTP && proto != IPPROTO_TCP &&
753 (match->wc.masks.tp_src ||
754 match->wc.masks.tp_dst ||
755 match->wc.masks.tcp_flags)) {
756 VLOG_DBG("L4 Protocol (%u) not supported", proto);
757 return -1;
758 }
759
760 if (proto == IPPROTO_TCP) {
761 struct rte_flow_item_tcp *spec, *mask;
762
763 spec = xzalloc(sizeof *spec);
764 mask = xzalloc(sizeof *mask);
765
766 spec->hdr.src_port = match->flow.tp_src;
767 spec->hdr.dst_port = match->flow.tp_dst;
768 spec->hdr.data_off = ntohs(match->flow.tcp_flags) >> 8;
769 spec->hdr.tcp_flags = ntohs(match->flow.tcp_flags) & 0xff;
770
771 mask->hdr.src_port = match->wc.masks.tp_src;
772 mask->hdr.dst_port = match->wc.masks.tp_dst;
773 mask->hdr.data_off = ntohs(match->wc.masks.tcp_flags) >> 8;
774 mask->hdr.tcp_flags = ntohs(match->wc.masks.tcp_flags) & 0xff;
775
776 consumed_masks->tp_src = 0;
777 consumed_masks->tp_dst = 0;
778 consumed_masks->tcp_flags = 0;
779
780 add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_TCP, spec, mask);
781
782 /* proto == TCP and ITEM_TYPE_TCP, thus no need for proto match. */
783 if (next_proto_mask) {
784 *next_proto_mask = 0;
785 }
786 } else if (proto == IPPROTO_UDP) {
787 struct rte_flow_item_udp *spec, *mask;
788
789 spec = xzalloc(sizeof *spec);
790 mask = xzalloc(sizeof *mask);
791
792 spec->hdr.src_port = match->flow.tp_src;
793 spec->hdr.dst_port = match->flow.tp_dst;
794
795 mask->hdr.src_port = match->wc.masks.tp_src;
796 mask->hdr.dst_port = match->wc.masks.tp_dst;
797
798 consumed_masks->tp_src = 0;
799 consumed_masks->tp_dst = 0;
800
801 add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_UDP, spec, mask);
802
803 /* proto == UDP and ITEM_TYPE_UDP, thus no need for proto match. */
804 if (next_proto_mask) {
805 *next_proto_mask = 0;
806 }
807 } else if (proto == IPPROTO_SCTP) {
808 struct rte_flow_item_sctp *spec, *mask;
809
810 spec = xzalloc(sizeof *spec);
811 mask = xzalloc(sizeof *mask);
812
813 spec->hdr.src_port = match->flow.tp_src;
814 spec->hdr.dst_port = match->flow.tp_dst;
815
816 mask->hdr.src_port = match->wc.masks.tp_src;
817 mask->hdr.dst_port = match->wc.masks.tp_dst;
818
819 consumed_masks->tp_src = 0;
820 consumed_masks->tp_dst = 0;
821
822 add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_SCTP, spec, mask);
823
824 /* proto == SCTP and ITEM_TYPE_SCTP, thus no need for proto match. */
825 if (next_proto_mask) {
826 *next_proto_mask = 0;
827 }
828 } else if (proto == IPPROTO_ICMP) {
829 struct rte_flow_item_icmp *spec, *mask;
830
831 spec = xzalloc(sizeof *spec);
832 mask = xzalloc(sizeof *mask);
833
834 spec->hdr.icmp_type = (uint8_t) ntohs(match->flow.tp_src);
835 spec->hdr.icmp_code = (uint8_t) ntohs(match->flow.tp_dst);
836
837 mask->hdr.icmp_type = (uint8_t) ntohs(match->wc.masks.tp_src);
838 mask->hdr.icmp_code = (uint8_t) ntohs(match->wc.masks.tp_dst);
839
840 consumed_masks->tp_src = 0;
841 consumed_masks->tp_dst = 0;
842
843 add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_ICMP, spec, mask);
844
845 /* proto == ICMP and ITEM_TYPE_ICMP, thus no need for proto match. */
846 if (next_proto_mask) {
847 *next_proto_mask = 0;
848 }
849 }
850
851 add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_END, NULL, NULL);
852
853 if (!is_all_zeros(consumed_masks, sizeof *consumed_masks)) {
854 return -1;
855 }
856 return 0;
857 }
858
859 static void
860 add_flow_mark_rss_actions(struct flow_actions *actions,
861 uint32_t flow_mark,
862 const struct netdev *netdev)
863 {
864 struct rte_flow_action_mark *mark;
865 struct action_rss_data {
866 struct rte_flow_action_rss conf;
867 uint16_t queue[0];
868 } *rss_data;
869 BUILD_ASSERT_DECL(offsetof(struct action_rss_data, conf) == 0);
870 int i;
871
872 mark = xzalloc(sizeof *mark);
873
874 mark->id = flow_mark;
875 add_flow_action(actions, RTE_FLOW_ACTION_TYPE_MARK, mark);
876
877 rss_data = xmalloc(sizeof *rss_data +
878 netdev_n_rxq(netdev) * sizeof rss_data->queue[0]);
879 *rss_data = (struct action_rss_data) {
880 .conf = (struct rte_flow_action_rss) {
881 .func = RTE_ETH_HASH_FUNCTION_DEFAULT,
882 .level = 0,
883 .types = 0,
884 .queue_num = netdev_n_rxq(netdev),
885 .queue = rss_data->queue,
886 .key_len = 0,
887 .key = NULL
888 },
889 };
890
891 /* Override queue array with default. */
892 for (i = 0; i < netdev_n_rxq(netdev); i++) {
893 rss_data->queue[i] = i;
894 }
895
896 add_flow_action(actions, RTE_FLOW_ACTION_TYPE_RSS, &rss_data->conf);
897 add_flow_action(actions, RTE_FLOW_ACTION_TYPE_END, NULL);
898 }
899
900 static struct rte_flow *
901 netdev_offload_dpdk_mark_rss(struct flow_patterns *patterns,
902 struct netdev *netdev,
903 uint32_t flow_mark)
904 {
905 struct flow_actions actions = { .actions = NULL, .cnt = 0 };
906 const struct rte_flow_attr flow_attr = {
907 .group = 0,
908 .priority = 0,
909 .ingress = 1,
910 .egress = 0
911 };
912 struct rte_flow_error error;
913 struct rte_flow *flow;
914
915 add_flow_mark_rss_actions(&actions, flow_mark, netdev);
916
917 flow = netdev_offload_dpdk_flow_create(netdev, &flow_attr, patterns->items,
918 actions.actions, &error);
919
920 free_flow_actions(&actions);
921 return flow;
922 }
923
924 static void
925 add_count_action(struct flow_actions *actions)
926 {
927 struct rte_flow_action_count *count = xzalloc(sizeof *count);
928
929 add_flow_action(actions, RTE_FLOW_ACTION_TYPE_COUNT, count);
930 }
931
932 static int
933 add_port_id_action(struct flow_actions *actions,
934 struct netdev *outdev)
935 {
936 struct rte_flow_action_port_id *port_id;
937 int outdev_id;
938
939 outdev_id = netdev_dpdk_get_port_id(outdev);
940 if (outdev_id < 0) {
941 return -1;
942 }
943 port_id = xzalloc(sizeof *port_id);
944 port_id->id = outdev_id;
945 add_flow_action(actions, RTE_FLOW_ACTION_TYPE_PORT_ID, port_id);
946 return 0;
947 }
948
949 static int
950 add_output_action(struct netdev *netdev,
951 struct flow_actions *actions,
952 const struct nlattr *nla)
953 {
954 struct netdev *outdev;
955 odp_port_t port;
956 int ret = 0;
957
958 port = nl_attr_get_odp_port(nla);
959 outdev = netdev_ports_get(port, netdev->dpif_type);
960 if (outdev == NULL) {
961 VLOG_DBG_RL(&rl, "Cannot find netdev for odp port %"PRIu32, port);
962 return -1;
963 }
964 if (!netdev_flow_api_equals(netdev, outdev) ||
965 add_port_id_action(actions, outdev)) {
966 VLOG_DBG_RL(&rl, "%s: Output to port \'%s\' cannot be offloaded.",
967 netdev_get_name(netdev), netdev_get_name(outdev));
968 ret = -1;
969 }
970 netdev_close(outdev);
971 return ret;
972 }
973
974 static int
975 add_set_flow_action__(struct flow_actions *actions,
976 const void *value, void *mask,
977 const size_t size, const int attr)
978 {
979 void *spec;
980
981 if (mask) {
982 /* DPDK does not support partially masked set actions. In such
983 * case, fail the offload.
984 */
985 if (is_all_zeros(mask, size)) {
986 return 0;
987 }
988 if (!is_all_ones(mask, size)) {
989 VLOG_DBG_RL(&rl, "Partial mask is not supported");
990 return -1;
991 }
992 }
993
994 spec = xzalloc(size);
995 memcpy(spec, value, size);
996 add_flow_action(actions, attr, spec);
997
998 /* Clear used mask for later checking. */
999 if (mask) {
1000 memset(mask, 0, size);
1001 }
1002 return 0;
1003 }
1004
1005 BUILD_ASSERT_DECL(sizeof(struct rte_flow_action_set_mac) ==
1006 MEMBER_SIZEOF(struct ovs_key_ethernet, eth_src));
1007 BUILD_ASSERT_DECL(sizeof(struct rte_flow_action_set_mac) ==
1008 MEMBER_SIZEOF(struct ovs_key_ethernet, eth_dst));
1009 BUILD_ASSERT_DECL(sizeof(struct rte_flow_action_set_ipv4) ==
1010 MEMBER_SIZEOF(struct ovs_key_ipv4, ipv4_src));
1011 BUILD_ASSERT_DECL(sizeof(struct rte_flow_action_set_ipv4) ==
1012 MEMBER_SIZEOF(struct ovs_key_ipv4, ipv4_dst));
1013 BUILD_ASSERT_DECL(sizeof(struct rte_flow_action_set_ttl) ==
1014 MEMBER_SIZEOF(struct ovs_key_ipv4, ipv4_ttl));
1015 BUILD_ASSERT_DECL(sizeof(struct rte_flow_action_set_ipv6) ==
1016 MEMBER_SIZEOF(struct ovs_key_ipv6, ipv6_src));
1017 BUILD_ASSERT_DECL(sizeof(struct rte_flow_action_set_ipv6) ==
1018 MEMBER_SIZEOF(struct ovs_key_ipv6, ipv6_dst));
1019 BUILD_ASSERT_DECL(sizeof(struct rte_flow_action_set_ttl) ==
1020 MEMBER_SIZEOF(struct ovs_key_ipv6, ipv6_hlimit));
1021 BUILD_ASSERT_DECL(sizeof(struct rte_flow_action_set_tp) ==
1022 MEMBER_SIZEOF(struct ovs_key_tcp, tcp_src));
1023 BUILD_ASSERT_DECL(sizeof(struct rte_flow_action_set_tp) ==
1024 MEMBER_SIZEOF(struct ovs_key_tcp, tcp_dst));
1025 BUILD_ASSERT_DECL(sizeof(struct rte_flow_action_set_tp) ==
1026 MEMBER_SIZEOF(struct ovs_key_udp, udp_src));
1027 BUILD_ASSERT_DECL(sizeof(struct rte_flow_action_set_tp) ==
1028 MEMBER_SIZEOF(struct ovs_key_udp, udp_dst));
1029
1030 static int
1031 parse_set_actions(struct flow_actions *actions,
1032 const struct nlattr *set_actions,
1033 const size_t set_actions_len,
1034 bool masked)
1035 {
1036 const struct nlattr *sa;
1037 unsigned int sleft;
1038
1039 #define add_set_flow_action(field, type) \
1040 if (add_set_flow_action__(actions, &key->field, \
1041 mask ? CONST_CAST(void *, &mask->field) : NULL, \
1042 sizeof key->field, type)) { \
1043 return -1; \
1044 }
1045
1046 NL_ATTR_FOR_EACH_UNSAFE (sa, sleft, set_actions, set_actions_len) {
1047 if (nl_attr_type(sa) == OVS_KEY_ATTR_ETHERNET) {
1048 const struct ovs_key_ethernet *key = nl_attr_get(sa);
1049 const struct ovs_key_ethernet *mask = masked ? key + 1 : NULL;
1050
1051 add_set_flow_action(eth_src, RTE_FLOW_ACTION_TYPE_SET_MAC_SRC);
1052 add_set_flow_action(eth_dst, RTE_FLOW_ACTION_TYPE_SET_MAC_DST);
1053
1054 if (mask && !is_all_zeros(mask, sizeof *mask)) {
1055 VLOG_DBG_RL(&rl, "Unsupported ETHERNET set action");
1056 return -1;
1057 }
1058 } else if (nl_attr_type(sa) == OVS_KEY_ATTR_IPV4) {
1059 const struct ovs_key_ipv4 *key = nl_attr_get(sa);
1060 const struct ovs_key_ipv4 *mask = masked ? key + 1 : NULL;
1061
1062 add_set_flow_action(ipv4_src, RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC);
1063 add_set_flow_action(ipv4_dst, RTE_FLOW_ACTION_TYPE_SET_IPV4_DST);
1064 add_set_flow_action(ipv4_ttl, RTE_FLOW_ACTION_TYPE_SET_TTL);
1065
1066 if (mask && !is_all_zeros(mask, sizeof *mask)) {
1067 VLOG_DBG_RL(&rl, "Unsupported IPv4 set action");
1068 return -1;
1069 }
1070 } else if (nl_attr_type(sa) == OVS_KEY_ATTR_IPV6) {
1071 const struct ovs_key_ipv6 *key = nl_attr_get(sa);
1072 const struct ovs_key_ipv6 *mask = masked ? key + 1 : NULL;
1073
1074 add_set_flow_action(ipv6_src, RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC);
1075 add_set_flow_action(ipv6_dst, RTE_FLOW_ACTION_TYPE_SET_IPV6_DST);
1076 add_set_flow_action(ipv6_hlimit, RTE_FLOW_ACTION_TYPE_SET_TTL);
1077
1078 if (mask && !is_all_zeros(mask, sizeof *mask)) {
1079 VLOG_DBG_RL(&rl, "Unsupported IPv6 set action");
1080 return -1;
1081 }
1082 } else if (nl_attr_type(sa) == OVS_KEY_ATTR_TCP) {
1083 const struct ovs_key_tcp *key = nl_attr_get(sa);
1084 const struct ovs_key_tcp *mask = masked ? key + 1 : NULL;
1085
1086 add_set_flow_action(tcp_src, RTE_FLOW_ACTION_TYPE_SET_TP_SRC);
1087 add_set_flow_action(tcp_dst, RTE_FLOW_ACTION_TYPE_SET_TP_DST);
1088
1089 if (mask && !is_all_zeros(mask, sizeof *mask)) {
1090 VLOG_DBG_RL(&rl, "Unsupported TCP set action");
1091 return -1;
1092 }
1093 } else if (nl_attr_type(sa) == OVS_KEY_ATTR_UDP) {
1094 const struct ovs_key_udp *key = nl_attr_get(sa);
1095 const struct ovs_key_udp *mask = masked ? key + 1 : NULL;
1096
1097 add_set_flow_action(udp_src, RTE_FLOW_ACTION_TYPE_SET_TP_SRC);
1098 add_set_flow_action(udp_dst, RTE_FLOW_ACTION_TYPE_SET_TP_DST);
1099
1100 if (mask && !is_all_zeros(mask, sizeof *mask)) {
1101 VLOG_DBG_RL(&rl, "Unsupported UDP set action");
1102 return -1;
1103 }
1104 } else {
1105 VLOG_DBG_RL(&rl,
1106 "Unsupported set action type %d", nl_attr_type(sa));
1107 return -1;
1108 }
1109 }
1110
1111 return 0;
1112 }
1113
1114 static int
1115 parse_vlan_push_action(struct flow_actions *actions,
1116 const struct ovs_action_push_vlan *vlan_push)
1117 {
1118 struct rte_flow_action_of_push_vlan *rte_push_vlan;
1119 struct rte_flow_action_of_set_vlan_pcp *rte_vlan_pcp;
1120 struct rte_flow_action_of_set_vlan_vid *rte_vlan_vid;
1121
1122 rte_push_vlan = xzalloc(sizeof *rte_push_vlan);
1123 rte_push_vlan->ethertype = vlan_push->vlan_tpid;
1124 add_flow_action(actions, RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN, rte_push_vlan);
1125
1126 rte_vlan_pcp = xzalloc(sizeof *rte_vlan_pcp);
1127 rte_vlan_pcp->vlan_pcp = vlan_tci_to_pcp(vlan_push->vlan_tci);
1128 add_flow_action(actions, RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP,
1129 rte_vlan_pcp);
1130
1131 rte_vlan_vid = xzalloc(sizeof *rte_vlan_vid);
1132 rte_vlan_vid->vlan_vid = htons(vlan_tci_to_vid(vlan_push->vlan_tci));
1133 add_flow_action(actions, RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID,
1134 rte_vlan_vid);
1135 return 0;
1136 }
1137
1138 static int
1139 parse_clone_actions(struct netdev *netdev,
1140 struct flow_actions *actions,
1141 const struct nlattr *clone_actions,
1142 const size_t clone_actions_len)
1143 {
1144 const struct nlattr *ca;
1145 unsigned int cleft;
1146
1147 NL_ATTR_FOR_EACH_UNSAFE (ca, cleft, clone_actions, clone_actions_len) {
1148 int clone_type = nl_attr_type(ca);
1149
1150 if (clone_type == OVS_ACTION_ATTR_TUNNEL_PUSH) {
1151 const struct ovs_action_push_tnl *tnl_push = nl_attr_get(ca);
1152 struct rte_flow_action_raw_encap *raw_encap =
1153 xzalloc(sizeof *raw_encap);
1154
1155 raw_encap->data = (uint8_t *) tnl_push->header;
1156 raw_encap->preserve = NULL;
1157 raw_encap->size = tnl_push->header_len;
1158
1159 add_flow_action(actions, RTE_FLOW_ACTION_TYPE_RAW_ENCAP,
1160 raw_encap);
1161 } else if (clone_type == OVS_ACTION_ATTR_OUTPUT) {
1162 if (add_output_action(netdev, actions, ca)) {
1163 return -1;
1164 }
1165 } else {
1166 VLOG_DBG_RL(&rl,
1167 "Unsupported nested action inside clone(), "
1168 "action type: %d", clone_type);
1169 return -1;
1170 }
1171 }
1172 return 0;
1173 }
1174
1175 static int
1176 parse_flow_actions(struct netdev *netdev,
1177 struct flow_actions *actions,
1178 struct nlattr *nl_actions,
1179 size_t nl_actions_len)
1180 {
1181 struct nlattr *nla;
1182 size_t left;
1183
1184 add_count_action(actions);
1185 NL_ATTR_FOR_EACH_UNSAFE (nla, left, nl_actions, nl_actions_len) {
1186 if (nl_attr_type(nla) == OVS_ACTION_ATTR_OUTPUT) {
1187 if (add_output_action(netdev, actions, nla)) {
1188 return -1;
1189 }
1190 } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_DROP) {
1191 add_flow_action(actions, RTE_FLOW_ACTION_TYPE_DROP, NULL);
1192 } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_SET ||
1193 nl_attr_type(nla) == OVS_ACTION_ATTR_SET_MASKED) {
1194 const struct nlattr *set_actions = nl_attr_get(nla);
1195 const size_t set_actions_len = nl_attr_get_size(nla);
1196 bool masked = nl_attr_type(nla) == OVS_ACTION_ATTR_SET_MASKED;
1197
1198 if (parse_set_actions(actions, set_actions, set_actions_len,
1199 masked)) {
1200 return -1;
1201 }
1202 } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_PUSH_VLAN) {
1203 const struct ovs_action_push_vlan *vlan = nl_attr_get(nla);
1204
1205 if (parse_vlan_push_action(actions, vlan)) {
1206 return -1;
1207 }
1208 } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_POP_VLAN) {
1209 add_flow_action(actions, RTE_FLOW_ACTION_TYPE_OF_POP_VLAN, NULL);
1210 } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_CLONE &&
1211 left <= NLA_ALIGN(nla->nla_len)) {
1212 const struct nlattr *clone_actions = nl_attr_get(nla);
1213 size_t clone_actions_len = nl_attr_get_size(nla);
1214
1215 if (parse_clone_actions(netdev, actions, clone_actions,
1216 clone_actions_len)) {
1217 return -1;
1218 }
1219 } else {
1220 VLOG_DBG_RL(&rl, "Unsupported action type %d", nl_attr_type(nla));
1221 return -1;
1222 }
1223 }
1224
1225 if (nl_actions_len == 0) {
1226 VLOG_DBG_RL(&rl, "No actions provided");
1227 return -1;
1228 }
1229
1230 add_flow_action(actions, RTE_FLOW_ACTION_TYPE_END, NULL);
1231 return 0;
1232 }
1233
1234 static struct rte_flow *
1235 netdev_offload_dpdk_actions(struct netdev *netdev,
1236 struct flow_patterns *patterns,
1237 struct nlattr *nl_actions,
1238 size_t actions_len)
1239 {
1240 const struct rte_flow_attr flow_attr = { .ingress = 1, .transfer = 1 };
1241 struct flow_actions actions = { .actions = NULL, .cnt = 0 };
1242 struct rte_flow *flow = NULL;
1243 struct rte_flow_error error;
1244 int ret;
1245
1246 ret = parse_flow_actions(netdev, &actions, nl_actions, actions_len);
1247 if (ret) {
1248 goto out;
1249 }
1250 flow = netdev_offload_dpdk_flow_create(netdev, &flow_attr, patterns->items,
1251 actions.actions, &error);
1252 out:
1253 free_flow_actions(&actions);
1254 return flow;
1255 }
1256
1257 static int
1258 netdev_offload_dpdk_add_flow(struct netdev *netdev,
1259 struct match *match,
1260 struct nlattr *nl_actions,
1261 size_t actions_len,
1262 const ovs_u128 *ufid,
1263 struct offload_info *info)
1264 {
1265 struct flow_patterns patterns = { .items = NULL, .cnt = 0 };
1266 bool actions_offloaded = true;
1267 struct rte_flow *flow;
1268 int ret = 0;
1269
1270 ret = parse_flow_match(&patterns, match);
1271 if (ret) {
1272 VLOG_DBG_RL(&rl, "%s: matches of ufid "UUID_FMT" are not supported",
1273 netdev_get_name(netdev), UUID_ARGS((struct uuid *) ufid));
1274 goto out;
1275 }
1276
1277 flow = netdev_offload_dpdk_actions(netdev, &patterns, nl_actions,
1278 actions_len);
1279 if (!flow) {
1280 /* If we failed to offload the rule actions fallback to MARK+RSS
1281 * actions.
1282 */
1283 flow = netdev_offload_dpdk_mark_rss(&patterns, netdev,
1284 info->flow_mark);
1285 actions_offloaded = false;
1286 }
1287
1288 if (!flow) {
1289 ret = -1;
1290 goto out;
1291 }
1292 ufid_to_rte_flow_associate(ufid, flow, actions_offloaded);
1293 VLOG_DBG("%s: installed flow %p by ufid "UUID_FMT,
1294 netdev_get_name(netdev), flow, UUID_ARGS((struct uuid *)ufid));
1295
1296 out:
1297 free_flow_patterns(&patterns);
1298 return ret;
1299 }
1300
1301 static int
1302 netdev_offload_dpdk_destroy_flow(struct netdev *netdev,
1303 const ovs_u128 *ufid,
1304 struct rte_flow *rte_flow)
1305 {
1306 struct rte_flow_error error;
1307 int ret = netdev_dpdk_rte_flow_destroy(netdev, rte_flow, &error);
1308
1309 if (ret == 0) {
1310 ufid_to_rte_flow_disassociate(ufid);
1311 VLOG_DBG_RL(&rl, "%s: rte_flow 0x%"PRIxPTR
1312 " flow destroy %d ufid " UUID_FMT,
1313 netdev_get_name(netdev), (intptr_t) rte_flow,
1314 netdev_dpdk_get_port_id(netdev),
1315 UUID_ARGS((struct uuid *) ufid));
1316 } else {
1317 VLOG_ERR("Failed flow: %s: flow destroy %d ufid " UUID_FMT,
1318 netdev_get_name(netdev), netdev_dpdk_get_port_id(netdev),
1319 UUID_ARGS((struct uuid *) ufid));
1320 }
1321
1322 return ret;
1323 }
1324
1325 static int
1326 netdev_offload_dpdk_flow_put(struct netdev *netdev, struct match *match,
1327 struct nlattr *actions, size_t actions_len,
1328 const ovs_u128 *ufid, struct offload_info *info,
1329 struct dpif_flow_stats *stats)
1330 {
1331 struct ufid_to_rte_flow_data *rte_flow_data;
1332 int ret;
1333
1334 /*
1335 * If an old rte_flow exists, it means it's a flow modification.
1336 * Here destroy the old rte flow first before adding a new one.
1337 */
1338 rte_flow_data = ufid_to_rte_flow_data_find(ufid);
1339 if (rte_flow_data && rte_flow_data->rte_flow) {
1340 ret = netdev_offload_dpdk_destroy_flow(netdev, ufid,
1341 rte_flow_data->rte_flow);
1342 if (ret < 0) {
1343 return ret;
1344 }
1345 }
1346
1347 if (stats) {
1348 memset(stats, 0, sizeof *stats);
1349 }
1350 return netdev_offload_dpdk_add_flow(netdev, match, actions,
1351 actions_len, ufid, info);
1352 }
1353
1354 static int
1355 netdev_offload_dpdk_flow_del(struct netdev *netdev, const ovs_u128 *ufid,
1356 struct dpif_flow_stats *stats)
1357 {
1358 struct ufid_to_rte_flow_data *rte_flow_data;
1359
1360 rte_flow_data = ufid_to_rte_flow_data_find(ufid);
1361 if (!rte_flow_data || !rte_flow_data->rte_flow) {
1362 return -1;
1363 }
1364
1365 if (stats) {
1366 memset(stats, 0, sizeof *stats);
1367 }
1368 return netdev_offload_dpdk_destroy_flow(netdev, ufid,
1369 rte_flow_data->rte_flow);
1370 }
1371
1372 static int
1373 netdev_offload_dpdk_init_flow_api(struct netdev *netdev)
1374 {
1375 return netdev_dpdk_flow_api_supported(netdev) ? 0 : EOPNOTSUPP;
1376 }
1377
1378 static int
1379 netdev_offload_dpdk_flow_get(struct netdev *netdev,
1380 struct match *match OVS_UNUSED,
1381 struct nlattr **actions OVS_UNUSED,
1382 const ovs_u128 *ufid,
1383 struct dpif_flow_stats *stats,
1384 struct dpif_flow_attrs *attrs,
1385 struct ofpbuf *buf OVS_UNUSED)
1386 {
1387 struct rte_flow_query_count query = { .reset = 1 };
1388 struct ufid_to_rte_flow_data *rte_flow_data;
1389 struct rte_flow_error error;
1390 int ret = 0;
1391
1392 rte_flow_data = ufid_to_rte_flow_data_find(ufid);
1393 if (!rte_flow_data || !rte_flow_data->rte_flow) {
1394 ret = -1;
1395 goto out;
1396 }
1397
1398 attrs->offloaded = true;
1399 if (!rte_flow_data->actions_offloaded) {
1400 attrs->dp_layer = "ovs";
1401 memset(stats, 0, sizeof *stats);
1402 goto out;
1403 }
1404 attrs->dp_layer = "dpdk";
1405 ret = netdev_dpdk_rte_flow_query_count(netdev, rte_flow_data->rte_flow,
1406 &query, &error);
1407 if (ret) {
1408 VLOG_DBG_RL(&rl, "%s: Failed to query ufid "UUID_FMT" flow: %p",
1409 netdev_get_name(netdev), UUID_ARGS((struct uuid *) ufid),
1410 rte_flow_data->rte_flow);
1411 goto out;
1412 }
1413 rte_flow_data->stats.n_packets += (query.hits_set) ? query.hits : 0;
1414 rte_flow_data->stats.n_bytes += (query.bytes_set) ? query.bytes : 0;
1415 if (query.hits_set && query.hits) {
1416 rte_flow_data->stats.used = time_msec();
1417 }
1418 memcpy(stats, &rte_flow_data->stats, sizeof *stats);
1419 out:
1420 attrs->dp_extra_info = NULL;
1421 return ret;
1422 }
1423
1424 const struct netdev_flow_api netdev_offload_dpdk = {
1425 .type = "dpdk_flow_api",
1426 .flow_put = netdev_offload_dpdk_flow_put,
1427 .flow_del = netdev_offload_dpdk_flow_del,
1428 .init_flow_api = netdev_offload_dpdk_init_flow_api,
1429 .flow_get = netdev_offload_dpdk_flow_get,
1430 };