Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
3 : : * Copyright (c) 2013 Simon Horman
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 : :
18 : : #include <config.h>
19 : : #include "odp-execute.h"
20 : : #include <arpa/inet.h>
21 : : #include <netinet/in.h>
22 : : #include <netinet/icmp6.h>
23 : : #include <netinet/ip6.h>
24 : : #include <stdlib.h>
25 : : #include <string.h>
26 : :
27 : : #include "dp-packet.h"
28 : : #include "dpif.h"
29 : : #include "netlink.h"
30 : : #include "odp-netlink.h"
31 : : #include "odp-util.h"
32 : : #include "packets.h"
33 : : #include "flow.h"
34 : : #include "unaligned.h"
35 : : #include "util.h"
36 : :
37 : : /* Masked copy of an ethernet address. 'src' is already properly masked. */
38 : : static void
39 : 2723 : ether_addr_copy_masked(struct eth_addr *dst, const struct eth_addr src,
40 : : const struct eth_addr mask)
41 : : {
42 : : int i;
43 : :
44 [ + + ]: 10892 : for (i = 0; i < ARRAY_SIZE(dst->be16); i++) {
45 : 8169 : dst->be16[i] = src.be16[i] | (dst->be16[i] & ~mask.be16[i]);
46 : : }
47 : 2723 : }
48 : :
49 : : static void
50 : 2284 : odp_eth_set_addrs(struct dp_packet *packet, const struct ovs_key_ethernet *key,
51 : : const struct ovs_key_ethernet *mask)
52 : : {
53 : 2284 : struct eth_header *eh = dp_packet_l2(packet);
54 : :
55 [ + - ]: 2284 : if (eh) {
56 [ + + ]: 2284 : if (!mask) {
57 : 1477 : eh->eth_src = key->eth_src;
58 : 1477 : eh->eth_dst = key->eth_dst;
59 : : } else {
60 : 807 : ether_addr_copy_masked(&eh->eth_src, key->eth_src, mask->eth_src);
61 : 807 : ether_addr_copy_masked(&eh->eth_dst, key->eth_dst, mask->eth_dst);
62 : : }
63 : : }
64 : 2284 : }
65 : :
66 : : static void
67 : 1269 : odp_set_ipv4(struct dp_packet *packet, const struct ovs_key_ipv4 *key,
68 : : const struct ovs_key_ipv4 *mask)
69 : : {
70 : 1269 : struct ip_header *nh = dp_packet_l3(packet);
71 : :
72 : 1269 : packet_set_ipv4(
73 : : packet,
74 : 1269 : key->ipv4_src | (get_16aligned_be32(&nh->ip_src) & ~mask->ipv4_src),
75 : 1269 : key->ipv4_dst | (get_16aligned_be32(&nh->ip_dst) & ~mask->ipv4_dst),
76 : 3807 : key->ipv4_tos | (nh->ip_tos & ~mask->ipv4_tos),
77 : 3807 : key->ipv4_ttl | (nh->ip_ttl & ~mask->ipv4_ttl));
78 : 1269 : }
79 : :
80 : : static const ovs_be32 *
81 : 5 : mask_ipv6_addr(const ovs_16aligned_be32 *old, const ovs_be32 *addr,
82 : : const ovs_be32 *mask, ovs_be32 *masked)
83 : : {
84 [ + + ]: 25 : for (int i = 0; i < 4; i++) {
85 : 20 : masked[i] = addr[i] | (get_16aligned_be32(&old[i]) & ~mask[i]);
86 : : }
87 : :
88 : 5 : return masked;
89 : : }
90 : :
91 : : static void
92 : 1 : odp_set_ipv6(struct dp_packet *packet, const struct ovs_key_ipv6 *key,
93 : : const struct ovs_key_ipv6 *mask)
94 : : {
95 : 1 : struct ovs_16aligned_ip6_hdr *nh = dp_packet_l3(packet);
96 : : ovs_be32 sbuf[4], dbuf[4];
97 : 1 : uint8_t old_tc = ntohl(get_16aligned_be32(&nh->ip6_flow)) >> 20;
98 : 1 : ovs_be32 old_fl = get_16aligned_be32(&nh->ip6_flow) & htonl(0xfffff);
99 : :
100 : 1 : packet_set_ipv6(
101 : : packet,
102 : 1 : mask_ipv6_addr(nh->ip6_src.be32, key->ipv6_src, mask->ipv6_src, sbuf),
103 : 1 : mask_ipv6_addr(nh->ip6_dst.be32, key->ipv6_dst, mask->ipv6_dst, dbuf),
104 : 2 : key->ipv6_tclass | (old_tc & ~mask->ipv6_tclass),
105 : 1 : key->ipv6_label | (old_fl & ~mask->ipv6_label),
106 : 3 : key->ipv6_hlimit | (nh->ip6_hlim & ~mask->ipv6_hlimit));
107 : 1 : }
108 : :
109 : : static void
110 : 15 : odp_set_tcp(struct dp_packet *packet, const struct ovs_key_tcp *key,
111 : : const struct ovs_key_tcp *mask)
112 : : {
113 : 15 : struct tcp_header *th = dp_packet_l4(packet);
114 : :
115 [ + - ][ + + ]: 15 : if (OVS_LIKELY(th && dp_packet_get_tcp_payload(packet))) {
116 : 11 : packet_set_tcp_port(packet,
117 : 33 : key->tcp_src | (th->tcp_src & ~mask->tcp_src),
118 : 33 : key->tcp_dst | (th->tcp_dst & ~mask->tcp_dst));
119 : : }
120 : 15 : }
121 : :
122 : : static void
123 : 4 : odp_set_udp(struct dp_packet *packet, const struct ovs_key_udp *key,
124 : : const struct ovs_key_udp *mask)
125 : : {
126 : 4 : struct udp_header *uh = dp_packet_l4(packet);
127 : :
128 [ + - ][ + - ]: 4 : if (OVS_LIKELY(uh && dp_packet_get_udp_payload(packet))) {
129 : 4 : packet_set_udp_port(packet,
130 : 12 : key->udp_src | (uh->udp_src & ~mask->udp_src),
131 : 12 : key->udp_dst | (uh->udp_dst & ~mask->udp_dst));
132 : : }
133 : 4 : }
134 : :
135 : : static void
136 : 4 : odp_set_sctp(struct dp_packet *packet, const struct ovs_key_sctp *key,
137 : : const struct ovs_key_sctp *mask)
138 : : {
139 : 4 : struct sctp_header *sh = dp_packet_l4(packet);
140 : :
141 [ + - ][ + - ]: 4 : if (OVS_LIKELY(sh && dp_packet_get_sctp_payload(packet))) {
142 : 4 : packet_set_sctp_port(packet,
143 : 12 : key->sctp_src | (sh->sctp_src & ~mask->sctp_src),
144 : 12 : key->sctp_dst | (sh->sctp_dst & ~mask->sctp_dst));
145 : : }
146 : 4 : }
147 : :
148 : : static void
149 : 2 : odp_set_tunnel_action(const struct nlattr *a, struct flow_tnl *tun_key)
150 : : {
151 : : enum odp_key_fitness fitness;
152 : :
153 : 2 : fitness = odp_tun_key_from_attr(a, true, tun_key);
154 [ - + ]: 2 : ovs_assert(fitness != ODP_FIT_ERROR);
155 : 2 : }
156 : :
157 : : static void
158 : 553 : set_arp(struct dp_packet *packet, const struct ovs_key_arp *key,
159 : : const struct ovs_key_arp *mask)
160 : : {
161 : 553 : struct arp_eth_header *arp = dp_packet_l3(packet);
162 : :
163 [ - + ]: 553 : if (!mask) {
164 : 0 : arp->ar_op = key->arp_op;
165 : 0 : arp->ar_sha = key->arp_sha;
166 : 0 : put_16aligned_be32(&arp->ar_spa, key->arp_sip);
167 : 0 : arp->ar_tha = key->arp_tha;
168 : 0 : put_16aligned_be32(&arp->ar_tpa, key->arp_tip);
169 : : } else {
170 : 553 : ovs_be32 ar_spa = get_16aligned_be32(&arp->ar_spa);
171 : 553 : ovs_be32 ar_tpa = get_16aligned_be32(&arp->ar_tpa);
172 : :
173 : 553 : arp->ar_op = key->arp_op | (arp->ar_op & ~mask->arp_op);
174 : 553 : ether_addr_copy_masked(&arp->ar_sha, key->arp_sha, mask->arp_sha);
175 : 553 : put_16aligned_be32(&arp->ar_spa,
176 : 553 : key->arp_sip | (ar_spa & ~mask->arp_sip));
177 : 553 : ether_addr_copy_masked(&arp->ar_tha, key->arp_tha, mask->arp_tha);
178 : 553 : put_16aligned_be32(&arp->ar_tpa,
179 : 553 : key->arp_tip | (ar_tpa & ~mask->arp_tip));
180 : : }
181 : 553 : }
182 : :
183 : : static void
184 : 3 : odp_set_nd(struct dp_packet *packet, const struct ovs_key_nd *key,
185 : : const struct ovs_key_nd *mask)
186 : : {
187 : 3 : const struct ovs_nd_msg *ns = dp_packet_l4(packet);
188 : 3 : const struct ovs_nd_opt *nd_opt = dp_packet_get_nd_payload(packet);
189 : :
190 [ + - ][ + - ]: 3 : if (OVS_LIKELY(ns && nd_opt)) {
191 : 3 : int bytes_remain = dp_packet_l4_size(packet) - sizeof(*ns);
192 : : ovs_be32 tgt_buf[4];
193 : 3 : struct eth_addr sll_buf = eth_addr_zero;
194 : 3 : struct eth_addr tll_buf = eth_addr_zero;
195 : :
196 [ + - ][ + - ]: 3 : while (bytes_remain >= ND_OPT_LEN && nd_opt->nd_opt_len != 0) {
197 [ + + ]: 3 : if (nd_opt->nd_opt_type == ND_OPT_SOURCE_LINKADDR
198 [ + - ]: 2 : && nd_opt->nd_opt_len == 1) {
199 : 2 : sll_buf = nd_opt->nd_opt_mac;
200 : 2 : ether_addr_copy_masked(&sll_buf, key->nd_sll, mask->nd_sll);
201 : :
202 : : /* A packet can only contain one SLL or TLL option */
203 : 2 : break;
204 [ + - ]: 1 : } else if (nd_opt->nd_opt_type == ND_OPT_TARGET_LINKADDR
205 [ + - ]: 1 : && nd_opt->nd_opt_len == 1) {
206 : 1 : tll_buf = nd_opt->nd_opt_mac;
207 : 1 : ether_addr_copy_masked(&tll_buf, key->nd_tll, mask->nd_tll);
208 : :
209 : : /* A packet can only contain one SLL or TLL option */
210 : 1 : break;
211 : : }
212 : :
213 : 0 : nd_opt += nd_opt->nd_opt_len;
214 : 0 : bytes_remain -= nd_opt->nd_opt_len * ND_OPT_LEN;
215 : : }
216 : :
217 : 3 : packet_set_nd(packet,
218 : 3 : mask_ipv6_addr(ns->target.be32,
219 : 3 : key->nd_target, mask->nd_target, tgt_buf),
220 : : sll_buf,
221 : : tll_buf);
222 : : }
223 : 3 : }
224 : :
225 : : static void
226 : 1541 : odp_execute_set_action(struct dp_packet *packet, const struct nlattr *a)
227 : : {
228 : 1541 : enum ovs_key_attr type = nl_attr_type(a);
229 : : const struct ovs_key_ipv4 *ipv4_key;
230 : : const struct ovs_key_ipv6 *ipv6_key;
231 : 1541 : struct pkt_metadata *md = &packet->md;
232 : :
233 [ - + + + : 1541 : switch (type) {
- - + + +
+ - + - -
- - ]
234 : : case OVS_KEY_ATTR_PRIORITY:
235 : 0 : md->skb_priority = nl_attr_get_u32(a);
236 : 0 : break;
237 : :
238 : : case OVS_KEY_ATTR_TUNNEL:
239 : 2 : odp_set_tunnel_action(a, &md->tunnel);
240 : 2 : break;
241 : :
242 : : case OVS_KEY_ATTR_SKB_MARK:
243 : 4 : md->pkt_mark = nl_attr_get_u32(a);
244 : 4 : break;
245 : :
246 : : case OVS_KEY_ATTR_ETHERNET:
247 : 1477 : odp_eth_set_addrs(packet, nl_attr_get(a), NULL);
248 : 1477 : break;
249 : :
250 : : case OVS_KEY_ATTR_IPV4:
251 : 0 : ipv4_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_ipv4));
252 : 0 : packet_set_ipv4(packet, ipv4_key->ipv4_src,
253 : 0 : ipv4_key->ipv4_dst, ipv4_key->ipv4_tos,
254 : 0 : ipv4_key->ipv4_ttl);
255 : 0 : break;
256 : :
257 : : case OVS_KEY_ATTR_IPV6:
258 : 0 : ipv6_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_ipv6));
259 : 0 : packet_set_ipv6(packet, ipv6_key->ipv6_src, ipv6_key->ipv6_dst,
260 : 0 : ipv6_key->ipv6_tclass, ipv6_key->ipv6_label,
261 : 0 : ipv6_key->ipv6_hlimit);
262 : 0 : break;
263 : :
264 : : case OVS_KEY_ATTR_TCP:
265 [ + - ]: 3 : if (OVS_LIKELY(dp_packet_get_tcp_payload(packet))) {
266 : 3 : const struct ovs_key_tcp *tcp_key
267 : : = nl_attr_get_unspec(a, sizeof(struct ovs_key_tcp));
268 : :
269 : 3 : packet_set_tcp_port(packet, tcp_key->tcp_src,
270 : 3 : tcp_key->tcp_dst);
271 : : }
272 : 3 : break;
273 : :
274 : : case OVS_KEY_ATTR_UDP:
275 [ + - ]: 6 : if (OVS_LIKELY(dp_packet_get_udp_payload(packet))) {
276 : 6 : const struct ovs_key_udp *udp_key
277 : : = nl_attr_get_unspec(a, sizeof(struct ovs_key_udp));
278 : :
279 : 6 : packet_set_udp_port(packet, udp_key->udp_src,
280 : 6 : udp_key->udp_dst);
281 : : }
282 : 6 : break;
283 : :
284 : : case OVS_KEY_ATTR_SCTP:
285 [ + - ]: 3 : if (OVS_LIKELY(dp_packet_get_sctp_payload(packet))) {
286 : 3 : const struct ovs_key_sctp *sctp_key
287 : : = nl_attr_get_unspec(a, sizeof(struct ovs_key_sctp));
288 : :
289 : 3 : packet_set_sctp_port(packet, sctp_key->sctp_src,
290 : 3 : sctp_key->sctp_dst);
291 : : }
292 : 3 : break;
293 : :
294 : : case OVS_KEY_ATTR_MPLS:
295 : 42 : set_mpls_lse(packet, nl_attr_get_be32(a));
296 : 42 : break;
297 : :
298 : : case OVS_KEY_ATTR_ARP:
299 : 0 : set_arp(packet, nl_attr_get(a), NULL);
300 : 0 : break;
301 : :
302 : : case OVS_KEY_ATTR_ICMP:
303 : : case OVS_KEY_ATTR_ICMPV6:
304 [ + - ]: 4 : if (OVS_LIKELY(dp_packet_get_icmp_payload(packet))) {
305 : 4 : const struct ovs_key_icmp *icmp_key
306 : : = nl_attr_get_unspec(a, sizeof(struct ovs_key_icmp));
307 : :
308 : 4 : packet_set_icmp(packet, icmp_key->icmp_type, icmp_key->icmp_code);
309 : : }
310 : 4 : break;
311 : :
312 : : case OVS_KEY_ATTR_ND:
313 [ # # ]: 0 : if (OVS_LIKELY(dp_packet_get_nd_payload(packet))) {
314 : 0 : const struct ovs_key_nd *nd_key
315 : : = nl_attr_get_unspec(a, sizeof(struct ovs_key_nd));
316 : 0 : packet_set_nd(packet, nd_key->nd_target, nd_key->nd_sll,
317 : : nd_key->nd_tll);
318 : : }
319 : 0 : break;
320 : :
321 : : case OVS_KEY_ATTR_DP_HASH:
322 : 0 : md->dp_hash = nl_attr_get_u32(a);
323 : 0 : break;
324 : :
325 : : case OVS_KEY_ATTR_RECIRC_ID:
326 : 0 : md->recirc_id = nl_attr_get_u32(a);
327 : 0 : break;
328 : :
329 : : case OVS_KEY_ATTR_UNSPEC:
330 : : case OVS_KEY_ATTR_ENCAP:
331 : : case OVS_KEY_ATTR_ETHERTYPE:
332 : : case OVS_KEY_ATTR_IN_PORT:
333 : : case OVS_KEY_ATTR_VLAN:
334 : : case OVS_KEY_ATTR_TCP_FLAGS:
335 : : case OVS_KEY_ATTR_CT_STATE:
336 : : case OVS_KEY_ATTR_CT_ZONE:
337 : : case OVS_KEY_ATTR_CT_MARK:
338 : : case OVS_KEY_ATTR_CT_LABELS:
339 : : case __OVS_KEY_ATTR_MAX:
340 : : default:
341 : 0 : OVS_NOT_REACHED();
342 : : }
343 : 1541 : }
344 : :
345 : : #define get_mask(a, type) ((const type *)(const void *)(a + 1) + 1)
346 : :
347 : : static void
348 : 2656 : odp_execute_masked_set_action(struct dp_packet *packet,
349 : : const struct nlattr *a)
350 : : {
351 : 2656 : struct pkt_metadata *md = &packet->md;
352 : 2656 : enum ovs_key_attr type = nl_attr_type(a);
353 : : struct mpls_hdr *mh;
354 : :
355 [ - - + + : 2656 : switch (type) {
+ + + + -
+ + - -
- ]
356 : : case OVS_KEY_ATTR_PRIORITY:
357 : 0 : md->skb_priority = nl_attr_get_u32(a)
358 : 0 : | (md->skb_priority & ~*get_mask(a, uint32_t));
359 : 0 : break;
360 : :
361 : : case OVS_KEY_ATTR_SKB_MARK:
362 : 0 : md->pkt_mark = nl_attr_get_u32(a)
363 : 0 : | (md->pkt_mark & ~*get_mask(a, uint32_t));
364 : 0 : break;
365 : :
366 : : case OVS_KEY_ATTR_ETHERNET:
367 : 807 : odp_eth_set_addrs(packet, nl_attr_get(a),
368 : : get_mask(a, struct ovs_key_ethernet));
369 : 807 : break;
370 : :
371 : : case OVS_KEY_ATTR_IPV4:
372 : 1269 : odp_set_ipv4(packet, nl_attr_get(a),
373 : : get_mask(a, struct ovs_key_ipv4));
374 : 1269 : break;
375 : :
376 : : case OVS_KEY_ATTR_IPV6:
377 : 1 : odp_set_ipv6(packet, nl_attr_get(a),
378 : : get_mask(a, struct ovs_key_ipv6));
379 : 1 : break;
380 : :
381 : : case OVS_KEY_ATTR_TCP:
382 : 15 : odp_set_tcp(packet, nl_attr_get(a),
383 : : get_mask(a, struct ovs_key_tcp));
384 : 15 : break;
385 : :
386 : : case OVS_KEY_ATTR_UDP:
387 : 4 : odp_set_udp(packet, nl_attr_get(a),
388 : : get_mask(a, struct ovs_key_udp));
389 : 4 : break;
390 : :
391 : : case OVS_KEY_ATTR_SCTP:
392 : 4 : odp_set_sctp(packet, nl_attr_get(a),
393 : : get_mask(a, struct ovs_key_sctp));
394 : 4 : break;
395 : :
396 : : case OVS_KEY_ATTR_MPLS:
397 : 0 : mh = dp_packet_l2_5(packet);
398 [ # # ]: 0 : if (mh) {
399 : 0 : put_16aligned_be32(&mh->mpls_lse, nl_attr_get_be32(a)
400 : 0 : | (get_16aligned_be32(&mh->mpls_lse)
401 : 0 : & ~*get_mask(a, ovs_be32)));
402 : : }
403 : 0 : break;
404 : :
405 : : case OVS_KEY_ATTR_ARP:
406 : 553 : set_arp(packet, nl_attr_get(a),
407 : : get_mask(a, struct ovs_key_arp));
408 : 553 : break;
409 : :
410 : : case OVS_KEY_ATTR_ND:
411 : 3 : odp_set_nd(packet, nl_attr_get(a),
412 : : get_mask(a, struct ovs_key_nd));
413 : 3 : break;
414 : :
415 : : case OVS_KEY_ATTR_DP_HASH:
416 : 0 : md->dp_hash = nl_attr_get_u32(a)
417 : 0 : | (md->dp_hash & ~*get_mask(a, uint32_t));
418 : 0 : break;
419 : :
420 : : case OVS_KEY_ATTR_RECIRC_ID:
421 : 0 : md->recirc_id = nl_attr_get_u32(a)
422 : 0 : | (md->recirc_id & ~*get_mask(a, uint32_t));
423 : 0 : break;
424 : :
425 : : case OVS_KEY_ATTR_TUNNEL: /* Masked data not supported for tunnel. */
426 : : case OVS_KEY_ATTR_UNSPEC:
427 : : case OVS_KEY_ATTR_CT_STATE:
428 : : case OVS_KEY_ATTR_CT_ZONE:
429 : : case OVS_KEY_ATTR_CT_MARK:
430 : : case OVS_KEY_ATTR_CT_LABELS:
431 : : case OVS_KEY_ATTR_ENCAP:
432 : : case OVS_KEY_ATTR_ETHERTYPE:
433 : : case OVS_KEY_ATTR_IN_PORT:
434 : : case OVS_KEY_ATTR_VLAN:
435 : : case OVS_KEY_ATTR_ICMP:
436 : : case OVS_KEY_ATTR_ICMPV6:
437 : : case OVS_KEY_ATTR_TCP_FLAGS:
438 : : case __OVS_KEY_ATTR_MAX:
439 : : default:
440 : 0 : OVS_NOT_REACHED();
441 : : }
442 : 2656 : }
443 : :
444 : : static void
445 : 60 : odp_execute_sample(void *dp, struct dp_packet *packet, bool steal,
446 : : const struct nlattr *action,
447 : : odp_execute_cb dp_execute_action)
448 : : {
449 : 60 : const struct nlattr *subactions = NULL;
450 : : const struct nlattr *a;
451 : : struct dp_packet_batch pb;
452 : : size_t left;
453 : :
454 [ + + ]: 180 : NL_NESTED_FOR_EACH_UNSAFE (a, left, action) {
455 : 120 : int type = nl_attr_type(a);
456 : :
457 [ + + - ]: 120 : switch ((enum ovs_sample_attr) type) {
458 : : case OVS_SAMPLE_ATTR_PROBABILITY:
459 [ - + ]: 60 : if (random_uint32() >= nl_attr_get_u32(a)) {
460 [ # # ]: 0 : if (steal) {
461 : 0 : dp_packet_delete(packet);
462 : : }
463 : 0 : return;
464 : : }
465 : 60 : break;
466 : :
467 : : case OVS_SAMPLE_ATTR_ACTIONS:
468 : 60 : subactions = a;
469 : 60 : break;
470 : :
471 : : case OVS_SAMPLE_ATTR_UNSPEC:
472 : : case __OVS_SAMPLE_ATTR_MAX:
473 : : default:
474 : 0 : OVS_NOT_REACHED();
475 : : }
476 : : }
477 : :
478 : 60 : packet_batch_init_packet(&pb, packet);
479 : 60 : odp_execute_actions(dp, &pb, steal, nl_attr_get(subactions),
480 : : nl_attr_get_size(subactions), dp_execute_action);
481 : : }
482 : :
483 : : static bool
484 : 28058 : requires_datapath_assistance(const struct nlattr *a)
485 : : {
486 : 28058 : enum ovs_action_attr type = nl_attr_type(a);
487 : :
488 [ + + - - ]: 28058 : switch (type) {
489 : : /* These only make sense in the context of a datapath. */
490 : : case OVS_ACTION_ATTR_OUTPUT:
491 : : case OVS_ACTION_ATTR_TUNNEL_PUSH:
492 : : case OVS_ACTION_ATTR_TUNNEL_POP:
493 : : case OVS_ACTION_ATTR_USERSPACE:
494 : : case OVS_ACTION_ATTR_RECIRC:
495 : : case OVS_ACTION_ATTR_CT:
496 : 22492 : return true;
497 : :
498 : : case OVS_ACTION_ATTR_SET:
499 : : case OVS_ACTION_ATTR_SET_MASKED:
500 : : case OVS_ACTION_ATTR_PUSH_VLAN:
501 : : case OVS_ACTION_ATTR_POP_VLAN:
502 : : case OVS_ACTION_ATTR_SAMPLE:
503 : : case OVS_ACTION_ATTR_HASH:
504 : : case OVS_ACTION_ATTR_PUSH_MPLS:
505 : : case OVS_ACTION_ATTR_POP_MPLS:
506 : : case OVS_ACTION_ATTR_TRUNC:
507 : 5566 : return false;
508 : :
509 : : case OVS_ACTION_ATTR_UNSPEC:
510 : : case __OVS_ACTION_ATTR_MAX:
511 : 0 : OVS_NOT_REACHED();
512 : : }
513 : :
514 : 0 : return false;
515 : : }
516 : :
517 : : void
518 : 19610 : odp_execute_actions(void *dp, struct dp_packet_batch *batch, bool steal,
519 : : const struct nlattr *actions, size_t actions_len,
520 : : odp_execute_cb dp_execute_action)
521 : : {
522 : 19610 : struct dp_packet **packets = batch->packets;
523 : 19610 : int cnt = batch->count;
524 : : const struct nlattr *a;
525 : : unsigned int left;
526 : : int i;
527 : :
528 [ + + ]: 31429 : NL_ATTR_FOR_EACH_UNSAFE (a, left, actions, actions_len) {
529 : 28058 : int type = nl_attr_type(a);
530 : 28058 : bool last_action = (left <= NLA_ALIGN(a->nla_len));
531 : :
532 [ + + ]: 28058 : if (requires_datapath_assistance(a)) {
533 [ + + ]: 22492 : if (dp_execute_action) {
534 : : /* Allow 'dp_execute_action' to steal the packet data if we do
535 : : * not need it any more. */
536 [ + + ][ + + ]: 22479 : bool may_steal = steal && last_action;
537 : :
538 : 22479 : dp_execute_action(dp, batch, a, may_steal);
539 : :
540 [ + + ]: 22479 : if (last_action) {
541 : : /* We do not need to free the packets. dp_execute_actions()
542 : : * has stolen them */
543 : 16216 : return;
544 : : }
545 : : }
546 : 6276 : continue;
547 : : }
548 : :
549 [ + + + + : 5566 : switch ((enum ovs_action_attr) type) {
+ + + + +
- - ]
550 : : case OVS_ACTION_ATTR_HASH: {
551 : 277 : const struct ovs_action_hash *hash_act = nl_attr_get(a);
552 : :
553 : : /* Calculate a hash value directly. This might not match the
554 : : * value computed by the datapath, but it is much less expensive,
555 : : * and the current use case (bonding) does not require a strict
556 : : * match to work properly. */
557 [ + - ]: 277 : if (hash_act->hash_alg == OVS_HASH_ALG_L4) {
558 : : struct flow flow;
559 : : uint32_t hash;
560 : :
561 [ + + ]: 554 : for (i = 0; i < cnt; i++) {
562 : 277 : flow_extract(packets[i], &flow);
563 : 277 : hash = flow_hash_5tuple(&flow, hash_act->hash_basis);
564 : :
565 : 277 : packets[i]->md.dp_hash = hash;
566 : : }
567 : : } else {
568 : : /* Assert on unknown hash algorithm. */
569 : 0 : OVS_NOT_REACHED();
570 : : }
571 : 277 : break;
572 : : }
573 : :
574 : : case OVS_ACTION_ATTR_PUSH_VLAN: {
575 : 112 : const struct ovs_action_push_vlan *vlan = nl_attr_get(a);
576 : :
577 [ + + ]: 224 : for (i = 0; i < cnt; i++) {
578 : 112 : eth_push_vlan(packets[i], vlan->vlan_tpid, vlan->vlan_tci);
579 : : }
580 : 112 : break;
581 : : }
582 : :
583 : : case OVS_ACTION_ATTR_POP_VLAN:
584 [ + + ]: 76 : for (i = 0; i < cnt; i++) {
585 : 38 : eth_pop_vlan(packets[i]);
586 : : }
587 : 38 : break;
588 : :
589 : : case OVS_ACTION_ATTR_PUSH_MPLS: {
590 : 157 : const struct ovs_action_push_mpls *mpls = nl_attr_get(a);
591 : :
592 [ + + ]: 314 : for (i = 0; i < cnt; i++) {
593 : 157 : push_mpls(packets[i], mpls->mpls_ethertype, mpls->mpls_lse);
594 : : }
595 : 157 : break;
596 : : }
597 : :
598 : : case OVS_ACTION_ATTR_POP_MPLS:
599 [ + + ]: 274 : for (i = 0; i < cnt; i++) {
600 : 137 : pop_mpls(packets[i], nl_attr_get_be16(a));
601 : : }
602 : 137 : break;
603 : :
604 : : case OVS_ACTION_ATTR_SET:
605 [ + + ]: 3082 : for (i = 0; i < cnt; i++) {
606 : 1541 : odp_execute_set_action(packets[i], nl_attr_get(a));
607 : : }
608 : 1541 : break;
609 : :
610 : : case OVS_ACTION_ATTR_SET_MASKED:
611 [ + + ]: 5312 : for (i = 0; i < cnt; i++) {
612 : 2656 : odp_execute_masked_set_action(packets[i], nl_attr_get(a));
613 : : }
614 : 2656 : break;
615 : :
616 : : case OVS_ACTION_ATTR_SAMPLE:
617 [ + + ]: 120 : for (i = 0; i < cnt; i++) {
618 [ + - ][ + + ]: 60 : odp_execute_sample(dp, packets[i], steal && last_action, a,
619 : : dp_execute_action);
620 : : }
621 : :
622 [ + + ]: 60 : if (last_action) {
623 : : /* We do not need to free the packets. odp_execute_sample() has
624 : : * stolen them*/
625 : 23 : return;
626 : : }
627 : 37 : break;
628 : :
629 : : case OVS_ACTION_ATTR_TRUNC: {
630 : 588 : const struct ovs_action_trunc *trunc =
631 : : nl_attr_get_unspec(a, sizeof *trunc);
632 : :
633 : 588 : batch->trunc = true;
634 [ + + ]: 1176 : for (i = 0; i < cnt; i++) {
635 : 588 : dp_packet_set_cutlen(packets[i], trunc->max_len);
636 : : }
637 : 588 : break;
638 : : }
639 : :
640 : : case OVS_ACTION_ATTR_OUTPUT:
641 : : case OVS_ACTION_ATTR_TUNNEL_PUSH:
642 : : case OVS_ACTION_ATTR_TUNNEL_POP:
643 : : case OVS_ACTION_ATTR_USERSPACE:
644 : : case OVS_ACTION_ATTR_RECIRC:
645 : : case OVS_ACTION_ATTR_CT:
646 : : case OVS_ACTION_ATTR_UNSPEC:
647 : : case __OVS_ACTION_ATTR_MAX:
648 : 0 : OVS_NOT_REACHED();
649 : : }
650 : : }
651 : :
652 [ + + ]: 3371 : if (steal) {
653 [ + + ]: 3922 : for (i = 0; i < cnt; i++) {
654 : 1961 : dp_packet_delete(packets[i]);
655 : : }
656 : : }
657 : : }
|