Coverage Report

Created: 2026-08-15 06:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openvswitch/lib/odp-execute.c
Line
Count
Source
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 <sys/types.h>
21
#include <netinet/in.h>
22
#include <arpa/inet.h>
23
#include <netinet/icmp6.h>
24
#include <netinet/ip6.h>
25
#include <stdlib.h>
26
#include <string.h>
27
28
#include "coverage.h"
29
#include "dp-packet.h"
30
#include "dpif.h"
31
#include "netlink.h"
32
#include "odp-netlink.h"
33
#include "odp-util.h"
34
#include "packets.h"
35
#include "flow.h"
36
#include "unaligned.h"
37
#include "util.h"
38
#include "csum.h"
39
#include "conntrack.h"
40
#include "openvswitch/vlog.h"
41
#include "unixctl.h"
42
43
VLOG_DEFINE_THIS_MODULE(odp_execute);
44
COVERAGE_DEFINE(datapath_drop_sample_error);
45
COVERAGE_DEFINE(datapath_drop_nsh_decap_error);
46
COVERAGE_DEFINE(drop_action_of_pipeline);
47
COVERAGE_DEFINE(drop_action_bridge_not_found);
48
COVERAGE_DEFINE(drop_action_recursion_too_deep);
49
COVERAGE_DEFINE(drop_action_too_many_resubmit);
50
COVERAGE_DEFINE(drop_action_stack_too_deep);
51
COVERAGE_DEFINE(drop_action_no_recirculation_context);
52
COVERAGE_DEFINE(drop_action_recirculation_conflict);
53
COVERAGE_DEFINE(drop_action_too_many_mpls_labels);
54
COVERAGE_DEFINE(drop_action_invalid_tunnel_metadata);
55
COVERAGE_DEFINE(drop_action_unsupported_packet_type);
56
COVERAGE_DEFINE(drop_action_congestion);
57
COVERAGE_DEFINE(drop_action_forwarding_disabled);
58
COVERAGE_DEFINE(drop_action_tunnel_routing_failed);
59
COVERAGE_DEFINE(drop_action_tunnel_output_no_ethernet);
60
COVERAGE_DEFINE(drop_action_tunnel_neigh_cache_miss);
61
COVERAGE_DEFINE(drop_action_tunnel_header_build_failed);
62
63
static void
64
dp_update_drop_action_counter(enum xlate_error drop_reason,
65
                              int delta)
66
0
{
67
0
   static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
68
69
0
   switch (drop_reason) {
70
0
   case XLATE_OK:
71
0
        COVERAGE_ADD(drop_action_of_pipeline, delta);
72
0
        break;
73
0
   case XLATE_BRIDGE_NOT_FOUND:
74
0
        COVERAGE_ADD(drop_action_bridge_not_found, delta);
75
0
        break;
76
0
   case XLATE_RECURSION_TOO_DEEP:
77
0
        COVERAGE_ADD(drop_action_recursion_too_deep, delta);
78
0
        break;
79
0
   case XLATE_TOO_MANY_RESUBMITS:
80
0
        COVERAGE_ADD(drop_action_too_many_resubmit, delta);
81
0
        break;
82
0
   case XLATE_STACK_TOO_DEEP:
83
0
        COVERAGE_ADD(drop_action_stack_too_deep, delta);
84
0
        break;
85
0
   case XLATE_NO_RECIRCULATION_CONTEXT:
86
0
        COVERAGE_ADD(drop_action_no_recirculation_context, delta);
87
0
        break;
88
0
   case XLATE_RECIRCULATION_CONFLICT:
89
0
        COVERAGE_ADD(drop_action_recirculation_conflict, delta);
90
0
        break;
91
0
   case XLATE_TOO_MANY_MPLS_LABELS:
92
0
        COVERAGE_ADD(drop_action_too_many_mpls_labels, delta);
93
0
        break;
94
0
   case XLATE_INVALID_TUNNEL_METADATA:
95
0
        COVERAGE_ADD(drop_action_invalid_tunnel_metadata, delta);
96
0
        break;
97
0
   case XLATE_UNSUPPORTED_PACKET_TYPE:
98
0
        COVERAGE_ADD(drop_action_unsupported_packet_type, delta);
99
0
        break;
100
0
   case XLATE_CONGESTION_DROP:
101
0
        COVERAGE_ADD(drop_action_congestion, delta);
102
0
        break;
103
0
   case XLATE_FORWARDING_DISABLED:
104
0
        COVERAGE_ADD(drop_action_forwarding_disabled, delta);
105
0
        break;
106
0
   case XLATE_TUNNEL_ROUTING_FAILED:
107
0
        COVERAGE_ADD(drop_action_tunnel_routing_failed, delta);
108
0
        break;
109
0
   case XLATE_TUNNEL_OUTPUT_NO_ETHERNET:
110
0
        COVERAGE_ADD(drop_action_tunnel_output_no_ethernet, delta);
111
0
        break;
112
0
   case XLATE_TUNNEL_NEIGH_CACHE_MISS:
113
0
        COVERAGE_ADD(drop_action_tunnel_neigh_cache_miss, delta);
114
0
        break;
115
0
   case XLATE_TUNNEL_HEADER_BUILD_FAILED:
116
0
        COVERAGE_ADD(drop_action_tunnel_header_build_failed, delta);
117
0
        break;
118
0
   case XLATE_MAX:
119
0
   default:
120
0
        VLOG_ERR_RL(&rl, "Invalid Drop reason type: %d", drop_reason);
121
0
   }
122
0
}
123
124
/* Masked copy of an ethernet address. 'src' is already properly masked. */
125
static void
126
ether_addr_copy_masked(struct eth_addr *dst, const struct eth_addr src,
127
                       const struct eth_addr mask)
128
0
{
129
0
    int i;
130
131
0
    for (i = 0; i < ARRAY_SIZE(dst->be16); i++) {
132
0
        dst->be16[i] = src.be16[i] | (dst->be16[i] & ~mask.be16[i]);
133
0
    }
134
0
}
135
136
static void
137
odp_eth_set_addrs(struct dp_packet *packet, const struct ovs_key_ethernet *key,
138
                  const struct ovs_key_ethernet *mask)
139
0
{
140
0
    struct eth_header *eh = dp_packet_eth(packet);
141
142
0
    if (eh) {
143
0
        if (!mask) {
144
0
            eh->eth_src = key->eth_src;
145
0
            eh->eth_dst = key->eth_dst;
146
0
        } else {
147
0
            ether_addr_copy_masked(&eh->eth_src, key->eth_src, mask->eth_src);
148
0
            ether_addr_copy_masked(&eh->eth_dst, key->eth_dst, mask->eth_dst);
149
0
        }
150
0
    }
151
0
}
152
153
static void
154
odp_set_ipv4(struct dp_packet *packet, const struct ovs_key_ipv4 *key,
155
             const struct ovs_key_ipv4 *mask)
156
0
{
157
0
    struct ip_header *nh = dp_packet_l3(packet);
158
0
    ovs_be32 ip_src_nh;
159
0
    ovs_be32 ip_dst_nh;
160
0
    ovs_be32 new_ip_src;
161
0
    ovs_be32 new_ip_dst;
162
0
    uint8_t new_tos;
163
0
    uint8_t new_ttl;
164
165
0
    ovs_assert(nh);
166
167
0
    if (mask->ipv4_src) {
168
0
        ip_src_nh = get_16aligned_be32(&nh->ip_src);
169
0
        new_ip_src = key->ipv4_src | (ip_src_nh & ~mask->ipv4_src);
170
171
0
        if (ip_src_nh != new_ip_src) {
172
0
            packet_set_ipv4_addr(packet, &nh->ip_src, new_ip_src);
173
0
        }
174
0
    }
175
176
0
    if (mask->ipv4_dst) {
177
0
        ip_dst_nh = get_16aligned_be32(&nh->ip_dst);
178
0
        new_ip_dst = key->ipv4_dst | (ip_dst_nh & ~mask->ipv4_dst);
179
180
0
        if (ip_dst_nh != new_ip_dst) {
181
0
            packet_set_ipv4_addr(packet, &nh->ip_dst, new_ip_dst);
182
0
        }
183
0
    }
184
185
0
    if (mask->ipv4_tos) {
186
0
        new_tos = key->ipv4_tos | (nh->ip_tos & ~mask->ipv4_tos);
187
188
0
        if (nh->ip_tos != new_tos) {
189
0
            if (dp_packet_ip_checksum_valid(packet)) {
190
0
                dp_packet_ip_checksum_set_partial(packet);
191
0
            } else {
192
0
                nh->ip_csum = recalc_csum16(nh->ip_csum,
193
0
                                            htons((uint16_t) nh->ip_tos),
194
0
                                            htons((uint16_t) new_tos));
195
0
            }
196
197
0
            nh->ip_tos = new_tos;
198
0
        }
199
0
    }
200
201
0
    if (OVS_LIKELY(mask->ipv4_ttl)) {
202
0
        new_ttl = key->ipv4_ttl | (nh->ip_ttl & ~mask->ipv4_ttl);
203
204
0
        if (OVS_LIKELY(nh->ip_ttl != new_ttl)) {
205
0
            if (dp_packet_ip_checksum_valid(packet)) {
206
0
                dp_packet_ip_checksum_set_partial(packet);
207
0
            } else {
208
0
                nh->ip_csum = recalc_csum16(nh->ip_csum,
209
0
                                            htons(nh->ip_ttl << 8),
210
0
                                            htons(new_ttl << 8));
211
0
            }
212
213
0
            nh->ip_ttl = new_ttl;
214
0
        }
215
0
    }
216
0
}
217
218
static struct in6_addr *
219
mask_ipv6_addr(const ovs_16aligned_be32 *old, const struct in6_addr *addr,
220
               const struct in6_addr *mask, struct in6_addr *masked)
221
0
{
222
0
#ifdef s6_addr32
223
0
    for (int i = 0; i < 4; i++) {
224
0
        masked->s6_addr32[i] = addr->s6_addr32[i]
225
0
            | (get_16aligned_be32(&old[i]) & ~mask->s6_addr32[i]);
226
0
    }
227
#else
228
    const uint8_t *old8 = (const uint8_t *)old;
229
    for (int i = 0; i < 16; i++) {
230
        masked->s6_addr[i] = addr->s6_addr[i] | (old8[i] & ~mask->s6_addr[i]);
231
    }
232
#endif
233
0
    return masked;
234
0
}
235
236
static void
237
odp_set_ipv6(struct dp_packet *packet, const struct ovs_key_ipv6 *key,
238
             const struct ovs_key_ipv6 *mask)
239
0
{
240
0
    struct ovs_16aligned_ip6_hdr *nh = dp_packet_l3(packet);
241
0
    struct in6_addr sbuf, dbuf;
242
0
    uint8_t old_tc = ntohl(get_16aligned_be32(&nh->ip6_flow)) >> 20;
243
0
    ovs_be32 old_fl = get_16aligned_be32(&nh->ip6_flow) & htonl(0xfffff);
244
245
0
    packet_set_ipv6(
246
0
        packet,
247
0
        mask_ipv6_addr(nh->ip6_src.be32, &key->ipv6_src, &mask->ipv6_src,
248
0
                       &sbuf),
249
0
        mask_ipv6_addr(nh->ip6_dst.be32, &key->ipv6_dst, &mask->ipv6_dst,
250
0
                       &dbuf),
251
0
        key->ipv6_tclass | (old_tc & ~mask->ipv6_tclass),
252
0
        key->ipv6_label | (old_fl & ~mask->ipv6_label),
253
0
        key->ipv6_hlimit | (nh->ip6_hlim & ~mask->ipv6_hlimit));
254
0
}
255
256
static void
257
odp_set_tcp(struct dp_packet *packet, const struct ovs_key_tcp *key,
258
             const struct ovs_key_tcp *mask)
259
0
{
260
0
    struct tcp_header *th = dp_packet_l4(packet);
261
262
0
    if (OVS_LIKELY(th && dp_packet_get_tcp_payload(packet))) {
263
0
        packet_set_tcp_port(packet,
264
0
                            key->tcp_src | (th->tcp_src & ~mask->tcp_src),
265
0
                            key->tcp_dst | (th->tcp_dst & ~mask->tcp_dst));
266
0
    }
267
0
}
268
269
static void
270
odp_set_udp(struct dp_packet *packet, const struct ovs_key_udp *key,
271
             const struct ovs_key_udp *mask)
272
0
{
273
0
    struct udp_header *uh = dp_packet_l4(packet);
274
275
0
    if (OVS_LIKELY(uh && dp_packet_get_udp_payload(packet))) {
276
0
        packet_set_udp_port(packet,
277
0
                            key->udp_src | (uh->udp_src & ~mask->udp_src),
278
0
                            key->udp_dst | (uh->udp_dst & ~mask->udp_dst));
279
0
    }
280
0
}
281
282
static void
283
odp_set_sctp(struct dp_packet *packet, const struct ovs_key_sctp *key,
284
             const struct ovs_key_sctp *mask)
285
0
{
286
0
    struct sctp_header *sh = dp_packet_l4(packet);
287
288
0
    if (OVS_LIKELY(sh && dp_packet_get_sctp_payload(packet))) {
289
0
        packet_set_sctp_port(packet,
290
0
                             key->sctp_src | (sh->sctp_src & ~mask->sctp_src),
291
0
                             key->sctp_dst | (sh->sctp_dst & ~mask->sctp_dst));
292
0
    }
293
0
}
294
295
static void
296
odp_set_tunnel_action(const struct nlattr *a, struct flow_tnl *tun_key)
297
0
{
298
0
    ovs_assert(odp_tun_key_from_attr(a, tun_key, NULL) != ODP_FIT_ERROR);
299
0
}
300
301
static void
302
set_arp(struct dp_packet *packet, const struct ovs_key_arp *key,
303
        const struct ovs_key_arp *mask)
304
0
{
305
0
    struct arp_eth_header *arp = dp_packet_l3(packet);
306
307
0
    ovs_assert(arp);
308
309
0
    if (!mask) {
310
0
        arp->ar_op = key->arp_op;
311
0
        arp->ar_sha = key->arp_sha;
312
0
        put_16aligned_be32(&arp->ar_spa, key->arp_sip);
313
0
        arp->ar_tha = key->arp_tha;
314
0
        put_16aligned_be32(&arp->ar_tpa, key->arp_tip);
315
0
    } else {
316
0
        ovs_be32 ar_spa = get_16aligned_be32(&arp->ar_spa);
317
0
        ovs_be32 ar_tpa = get_16aligned_be32(&arp->ar_tpa);
318
319
0
        arp->ar_op = key->arp_op | (arp->ar_op & ~mask->arp_op);
320
0
        ether_addr_copy_masked(&arp->ar_sha, key->arp_sha, mask->arp_sha);
321
0
        put_16aligned_be32(&arp->ar_spa,
322
0
                           key->arp_sip | (ar_spa & ~mask->arp_sip));
323
0
        ether_addr_copy_masked(&arp->ar_tha, key->arp_tha, mask->arp_tha);
324
0
        put_16aligned_be32(&arp->ar_tpa,
325
0
                           key->arp_tip | (ar_tpa & ~mask->arp_tip));
326
0
    }
327
0
}
328
329
static void
330
odp_set_nd_ext(struct dp_packet *packet, const struct ovs_key_nd_extensions
331
        *key, const struct ovs_key_nd_extensions *mask)
332
0
{
333
0
    const struct ovs_nd_msg *ns = dp_packet_l4(packet);
334
0
    ovs_16aligned_be32 reserved = ns->rso_flags;
335
0
    uint8_t opt_type = ns->options[0].type;
336
337
0
    if (mask->nd_reserved) {
338
0
        put_16aligned_be32(&reserved, key->nd_reserved);
339
0
    }
340
0
    if (mask->nd_options_type) {
341
0
        opt_type = key->nd_options_type;
342
0
    }
343
0
    packet_set_nd_ext(packet, reserved, opt_type);
344
0
}
345
346
static void
347
odp_set_nd(struct dp_packet *packet, const struct ovs_key_nd *key,
348
           const struct ovs_key_nd *mask)
349
0
{
350
0
    const struct ovs_nd_msg *ns = dp_packet_l4(packet);
351
0
    const struct ovs_nd_lla_opt *lla_opt = dp_packet_get_nd_payload(packet);
352
353
0
    if (OVS_LIKELY(ns && lla_opt)) {
354
0
        int bytes_remain = dp_packet_l4_size(packet) - sizeof(*ns);
355
0
        struct in6_addr tgt_buf;
356
0
        struct eth_addr sll_buf = eth_addr_zero;
357
0
        struct eth_addr tll_buf = eth_addr_zero;
358
359
0
        while (bytes_remain >= ND_LLA_OPT_LEN && lla_opt->len != 0
360
0
               && bytes_remain >= (lla_opt->len * ND_LLA_OPT_LEN)) {
361
0
            if (lla_opt->type == ND_OPT_SOURCE_LINKADDR
362
0
                && lla_opt->len == 1) {
363
0
                sll_buf = lla_opt->mac;
364
0
                ether_addr_copy_masked(&sll_buf, key->nd_sll, mask->nd_sll);
365
366
                /* A packet can only contain one SLL or TLL option */
367
0
                break;
368
0
            } else if (lla_opt->type == ND_OPT_TARGET_LINKADDR
369
0
                       && lla_opt->len == 1) {
370
0
                tll_buf = lla_opt->mac;
371
0
                ether_addr_copy_masked(&tll_buf, key->nd_tll, mask->nd_tll);
372
373
                /* A packet can only contain one SLL or TLL option */
374
0
                break;
375
0
            }
376
377
0
            lla_opt += lla_opt->len;
378
0
            bytes_remain -= lla_opt->len * ND_LLA_OPT_LEN;
379
0
        }
380
381
0
        packet_set_nd(packet,
382
0
                      mask_ipv6_addr(ns->target.be32, &key->nd_target,
383
0
                                     &mask->nd_target, &tgt_buf),
384
0
                      sll_buf,
385
0
                      tll_buf);
386
0
    }
387
0
}
388
389
/* Set the NSH header. Assumes the NSH header is present and matches the
390
 * MD format of the key. The slow path must take case of that. */
391
static void
392
odp_set_nsh(struct dp_packet *packet, const struct nlattr *a, bool has_mask)
393
0
{
394
0
    struct ovs_key_nsh key, mask;
395
0
    struct nsh_hdr *nsh = dp_packet_l3(packet);
396
0
    uint8_t mdtype = nsh_md_type(nsh);
397
0
    ovs_be32 path_hdr;
398
399
0
    if (has_mask) {
400
0
        odp_nsh_key_from_attr(a, &key, &mask, NULL);
401
0
    } else {
402
0
        odp_nsh_key_from_attr(a, &key, NULL, NULL);
403
0
    }
404
405
0
    if (!has_mask) {
406
0
        nsh_set_flags_and_ttl(nsh, key.flags, key.ttl);
407
0
        put_16aligned_be32(&nsh->path_hdr, key.path_hdr);
408
0
        switch (mdtype) {
409
0
            case NSH_M_TYPE1:
410
0
                for (int i = 0; i < 4; i++) {
411
0
                    put_16aligned_be32(&nsh->md1.context[i], key.context[i]);
412
0
                }
413
0
                break;
414
0
            case NSH_M_TYPE2:
415
0
            default:
416
                /* No support for setting any other metadata format yet. */
417
0
                break;
418
0
        }
419
0
    } else {
420
0
        uint8_t flags = nsh_get_flags(nsh);
421
0
        uint8_t ttl = nsh_get_ttl(nsh);
422
423
0
        flags = key.flags | (flags & ~mask.flags);
424
0
        ttl = key.ttl | (ttl & ~mask.ttl);
425
0
        nsh_set_flags_and_ttl(nsh, flags, ttl);
426
427
0
        uint32_t spi = ntohl(nsh_get_spi(nsh));
428
0
        uint8_t si = nsh_get_si(nsh);
429
0
        uint32_t spi_mask = nsh_path_hdr_to_spi_uint32(mask.path_hdr);
430
0
        uint8_t si_mask = nsh_path_hdr_to_si(mask.path_hdr);
431
0
        if (spi_mask == 0x00ffffff) {
432
0
            spi_mask = UINT32_MAX;
433
0
        }
434
0
        spi = nsh_path_hdr_to_spi_uint32(key.path_hdr) | (spi & ~spi_mask);
435
0
        si = nsh_path_hdr_to_si(key.path_hdr) | (si & ~si_mask);
436
0
        path_hdr = nsh_get_path_hdr(nsh);
437
0
        nsh_path_hdr_set_spi(&path_hdr, htonl(spi));
438
0
        nsh_path_hdr_set_si(&path_hdr, si);
439
0
        put_16aligned_be32(&nsh->path_hdr, path_hdr);
440
0
        switch (mdtype) {
441
0
            case NSH_M_TYPE1:
442
0
                for (int i = 0; i < 4; i++) {
443
0
                    ovs_be32 p = get_16aligned_be32(&nsh->md1.context[i]);
444
0
                    ovs_be32 k = key.context[i];
445
0
                    ovs_be32 m = mask.context[i];
446
0
                    put_16aligned_be32(&nsh->md1.context[i], k | (p & ~m));
447
0
                }
448
0
                break;
449
0
            case NSH_M_TYPE2:
450
0
            default:
451
                /* No support for setting any other metadata format yet. */
452
0
                break;
453
0
        }
454
0
    }
455
0
}
456
457
static void
458
odp_execute_set_action(struct dp_packet *packet, const struct nlattr *a)
459
0
{
460
0
    enum ovs_key_attr type = nl_attr_type(a);
461
0
    const struct ovs_key_ipv4 *ipv4_key;
462
0
    const struct ovs_key_ipv6 *ipv6_key;
463
0
    struct pkt_metadata *md = &packet->md;
464
465
0
    switch (type) {
466
0
    case OVS_KEY_ATTR_PRIORITY:
467
0
        md->skb_priority = nl_attr_get_u32(a);
468
0
        break;
469
470
0
    case OVS_KEY_ATTR_TUNNEL:
471
0
        odp_set_tunnel_action(a, &md->tunnel);
472
0
        break;
473
474
0
    case OVS_KEY_ATTR_SKB_MARK:
475
0
        md->pkt_mark = nl_attr_get_u32(a);
476
0
        break;
477
478
0
    case OVS_KEY_ATTR_ETHERNET:
479
0
        odp_eth_set_addrs(packet, nl_attr_get(a), NULL);
480
0
        break;
481
482
0
    case OVS_KEY_ATTR_NSH: {
483
0
        odp_set_nsh(packet, a, false);
484
0
        break;
485
0
    }
486
487
0
    case OVS_KEY_ATTR_IPV4:
488
0
        ipv4_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_ipv4));
489
0
        packet_set_ipv4(packet, ipv4_key->ipv4_src,
490
0
                        ipv4_key->ipv4_dst, ipv4_key->ipv4_tos,
491
0
                        ipv4_key->ipv4_ttl);
492
0
        break;
493
494
0
    case OVS_KEY_ATTR_IPV6:
495
0
        ipv6_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_ipv6));
496
0
        packet_set_ipv6(packet, &ipv6_key->ipv6_src, &ipv6_key->ipv6_dst,
497
0
                        ipv6_key->ipv6_tclass, ipv6_key->ipv6_label,
498
0
                        ipv6_key->ipv6_hlimit);
499
0
        break;
500
501
0
    case OVS_KEY_ATTR_TCP:
502
0
        if (OVS_LIKELY(dp_packet_get_tcp_payload(packet))) {
503
0
            const struct ovs_key_tcp *tcp_key
504
0
                = nl_attr_get_unspec(a, sizeof(struct ovs_key_tcp));
505
506
0
            packet_set_tcp_port(packet, tcp_key->tcp_src,
507
0
                                tcp_key->tcp_dst);
508
0
        }
509
0
        break;
510
511
0
    case OVS_KEY_ATTR_UDP:
512
0
        if (OVS_LIKELY(dp_packet_get_udp_payload(packet))) {
513
0
            const struct ovs_key_udp *udp_key
514
0
                = nl_attr_get_unspec(a, sizeof(struct ovs_key_udp));
515
516
0
            packet_set_udp_port(packet, udp_key->udp_src,
517
0
                                udp_key->udp_dst);
518
0
        }
519
0
        break;
520
521
0
    case OVS_KEY_ATTR_SCTP:
522
0
        if (OVS_LIKELY(dp_packet_get_sctp_payload(packet))) {
523
0
            const struct ovs_key_sctp *sctp_key
524
0
                = nl_attr_get_unspec(a, sizeof(struct ovs_key_sctp));
525
526
0
            packet_set_sctp_port(packet, sctp_key->sctp_src,
527
0
                                 sctp_key->sctp_dst);
528
0
        }
529
0
        break;
530
531
0
    case OVS_KEY_ATTR_MPLS:
532
0
        set_mpls_lse(packet, nl_attr_get_be32(a));
533
0
        break;
534
535
0
    case OVS_KEY_ATTR_ARP:
536
0
        set_arp(packet, nl_attr_get(a), NULL);
537
0
        break;
538
539
0
    case OVS_KEY_ATTR_ICMP:
540
0
    case OVS_KEY_ATTR_ICMPV6:
541
0
        if (OVS_LIKELY(dp_packet_get_icmp_payload(packet))) {
542
0
            const struct ovs_key_icmp *icmp_key
543
0
                = nl_attr_get_unspec(a, sizeof(struct ovs_key_icmp));
544
545
0
            packet_set_icmp(packet, icmp_key->icmp_type, icmp_key->icmp_code);
546
0
        }
547
0
        break;
548
549
0
    case OVS_KEY_ATTR_ND:
550
0
        if (OVS_LIKELY(dp_packet_get_nd_payload(packet))) {
551
0
            const struct ovs_key_nd *nd_key
552
0
                   = nl_attr_get_unspec(a, sizeof(struct ovs_key_nd));
553
0
            packet_set_nd(packet, &nd_key->nd_target, nd_key->nd_sll,
554
0
                          nd_key->nd_tll);
555
0
        }
556
0
        break;
557
558
0
    case OVS_KEY_ATTR_ND_EXTENSIONS:
559
0
        if (OVS_LIKELY(dp_packet_get_nd_payload(packet))) {
560
0
            const struct ovs_key_nd_extensions *nd_ext_key
561
0
                 = nl_attr_get_unspec(a, sizeof(struct ovs_key_nd_extensions));
562
0
            ovs_16aligned_be32 rso_flags;
563
0
            put_16aligned_be32(&rso_flags, nd_ext_key->nd_reserved);
564
0
            packet_set_nd_ext(packet, rso_flags, nd_ext_key->nd_options_type);
565
0
        }
566
0
        break;
567
568
0
    case OVS_KEY_ATTR_DP_HASH:
569
0
        md->dp_hash = nl_attr_get_u32(a);
570
0
        break;
571
572
0
    case OVS_KEY_ATTR_RECIRC_ID:
573
0
        md->recirc_id = nl_attr_get_u32(a);
574
0
        break;
575
576
0
    case OVS_KEY_ATTR_UNSPEC:
577
0
    case OVS_KEY_ATTR_PACKET_TYPE:
578
0
    case OVS_KEY_ATTR_ENCAP:
579
0
    case OVS_KEY_ATTR_ETHERTYPE:
580
0
    case OVS_KEY_ATTR_IN_PORT:
581
0
    case OVS_KEY_ATTR_VLAN:
582
0
    case OVS_KEY_ATTR_TCP_FLAGS:
583
0
    case OVS_KEY_ATTR_CT_STATE:
584
0
    case OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4:
585
0
    case OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6:
586
0
    case OVS_KEY_ATTR_CT_ZONE:
587
0
    case OVS_KEY_ATTR_CT_MARK:
588
0
    case OVS_KEY_ATTR_CT_LABELS:
589
0
    case OVS_KEY_ATTR_TUNNEL_INFO:
590
0
    case __OVS_KEY_ATTR_MAX:
591
0
    default:
592
0
        OVS_NOT_REACHED();
593
0
    }
594
0
}
595
596
static void
597
odp_execute_masked_set_action(struct dp_packet *packet,
598
                              const struct nlattr *a)
599
0
{
600
0
    struct pkt_metadata *md = &packet->md;
601
0
    enum ovs_key_attr type = nl_attr_type(a);
602
0
    struct mpls_hdr *mh;
603
604
0
    switch (type) {
605
0
    case OVS_KEY_ATTR_PRIORITY:
606
0
        md->skb_priority = nl_attr_get_u32(a)
607
0
            | (md->skb_priority & ~*odp_get_key_mask(a, uint32_t));
608
0
        break;
609
610
0
    case OVS_KEY_ATTR_SKB_MARK:
611
0
        md->pkt_mark = nl_attr_get_u32(a)
612
0
            | (md->pkt_mark & ~*odp_get_key_mask(a, uint32_t));
613
0
        break;
614
615
0
    case OVS_KEY_ATTR_ETHERNET:
616
0
        odp_eth_set_addrs(packet, nl_attr_get(a),
617
0
                          odp_get_key_mask(a, struct ovs_key_ethernet));
618
0
        break;
619
620
0
    case OVS_KEY_ATTR_NSH: {
621
0
        odp_set_nsh(packet, a, true);
622
0
        break;
623
0
    }
624
625
0
    case OVS_KEY_ATTR_IPV4:
626
0
        odp_set_ipv4(packet, nl_attr_get(a),
627
0
                     odp_get_key_mask(a, struct ovs_key_ipv4));
628
0
        break;
629
630
0
    case OVS_KEY_ATTR_IPV6:
631
0
        odp_set_ipv6(packet, nl_attr_get(a),
632
0
                     odp_get_key_mask(a, struct ovs_key_ipv6));
633
0
        break;
634
635
0
    case OVS_KEY_ATTR_TCP:
636
0
        odp_set_tcp(packet, nl_attr_get(a),
637
0
                    odp_get_key_mask(a, struct ovs_key_tcp));
638
0
        break;
639
640
0
    case OVS_KEY_ATTR_UDP:
641
0
        odp_set_udp(packet, nl_attr_get(a),
642
0
                    odp_get_key_mask(a, struct ovs_key_udp));
643
0
        break;
644
645
0
    case OVS_KEY_ATTR_SCTP:
646
0
        odp_set_sctp(packet, nl_attr_get(a),
647
0
                     odp_get_key_mask(a, struct ovs_key_sctp));
648
0
        break;
649
650
0
    case OVS_KEY_ATTR_MPLS:
651
0
        mh = dp_packet_l2_5(packet);
652
0
        if (mh) {
653
0
            put_16aligned_be32(&mh->mpls_lse, nl_attr_get_be32(a)
654
0
                               | (get_16aligned_be32(&mh->mpls_lse)
655
0
                                  & ~*odp_get_key_mask(a, ovs_be32)));
656
0
        }
657
0
        break;
658
659
0
    case OVS_KEY_ATTR_ARP:
660
0
        set_arp(packet, nl_attr_get(a),
661
0
                odp_get_key_mask(a, struct ovs_key_arp));
662
0
        break;
663
664
0
    case OVS_KEY_ATTR_ND:
665
0
        odp_set_nd(packet, nl_attr_get(a),
666
0
                   odp_get_key_mask(a, struct ovs_key_nd));
667
0
        break;
668
669
0
    case OVS_KEY_ATTR_ND_EXTENSIONS:
670
0
        odp_set_nd_ext(packet, nl_attr_get(a),
671
0
                       odp_get_key_mask(a, struct ovs_key_nd_extensions));
672
0
        break;
673
674
0
    case OVS_KEY_ATTR_DP_HASH:
675
0
        md->dp_hash = nl_attr_get_u32(a)
676
0
            | (md->dp_hash & ~*odp_get_key_mask(a, uint32_t));
677
0
        break;
678
679
0
    case OVS_KEY_ATTR_RECIRC_ID:
680
0
        md->recirc_id = nl_attr_get_u32(a)
681
0
            | (md->recirc_id & ~*odp_get_key_mask(a, uint32_t));
682
0
        break;
683
684
0
    case OVS_KEY_ATTR_TUNNEL:    /* Masked data not supported for tunnel. */
685
0
    case OVS_KEY_ATTR_PACKET_TYPE:
686
0
    case OVS_KEY_ATTR_UNSPEC:
687
0
    case OVS_KEY_ATTR_CT_STATE:
688
0
    case OVS_KEY_ATTR_CT_ZONE:
689
0
    case OVS_KEY_ATTR_CT_MARK:
690
0
    case OVS_KEY_ATTR_CT_LABELS:
691
0
    case OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4:
692
0
    case OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6:
693
0
    case OVS_KEY_ATTR_ENCAP:
694
0
    case OVS_KEY_ATTR_ETHERTYPE:
695
0
    case OVS_KEY_ATTR_IN_PORT:
696
0
    case OVS_KEY_ATTR_VLAN:
697
0
    case OVS_KEY_ATTR_ICMP:
698
0
    case OVS_KEY_ATTR_ICMPV6:
699
0
    case OVS_KEY_ATTR_TCP_FLAGS:
700
0
    case OVS_KEY_ATTR_TUNNEL_INFO:
701
0
    case __OVS_KEY_ATTR_MAX:
702
0
    default:
703
0
        OVS_NOT_REACHED();
704
0
    }
705
0
}
706
707
static void
708
odp_execute_sample(void *dp, struct dp_packet *packet, bool steal,
709
                   const struct nlattr *action,
710
                   odp_execute_cb dp_execute_action)
711
0
{
712
0
    const struct nlattr *subactions = NULL;
713
0
    const struct nlattr *a;
714
0
    struct dp_packet_batch pb;
715
0
    size_t left;
716
717
0
    NL_NESTED_FOR_EACH_UNSAFE (a, left, action) {
718
0
        int type = nl_attr_type(a);
719
720
0
        switch ((enum ovs_sample_attr) type) {
721
0
        case OVS_SAMPLE_ATTR_PROBABILITY:
722
0
            if (random_uint32() >= nl_attr_get_u32(a)) {
723
0
                if (steal) {
724
0
                    COVERAGE_INC(datapath_drop_sample_error);
725
0
                    dp_packet_delete(packet);
726
0
                }
727
0
                return;
728
0
            }
729
0
            break;
730
731
0
        case OVS_SAMPLE_ATTR_ACTIONS:
732
0
            subactions = a;
733
0
            break;
734
735
0
        case OVS_SAMPLE_ATTR_UNSPEC:
736
0
        case __OVS_SAMPLE_ATTR_MAX:
737
0
        default:
738
0
            OVS_NOT_REACHED();
739
0
        }
740
0
    }
741
742
0
    if (!subactions) {
743
0
        if (steal) {
744
0
            COVERAGE_INC(datapath_drop_sample_error);
745
0
            dp_packet_delete(packet);
746
0
        }
747
0
        return;
748
0
    }
749
750
0
    if (!steal) {
751
        /* The 'subactions' may modify the packet, but the modification
752
         * should not propagate beyond this sample action. Make a copy
753
         * the packet in case we don't own the packet, so that the
754
         * 'subactions' are only applid to the clone.  'odp_execute_actions'
755
         * will free the clone.  */
756
0
        packet = dp_packet_clone(packet);
757
0
    }
758
0
    dp_packet_batch_init_packet(&pb, packet);
759
0
    odp_execute_actions(dp, &pb, true, nl_attr_get(subactions),
760
0
                        nl_attr_get_size(subactions), dp_execute_action);
761
0
    dp_packet_batch_destroy(&pb);
762
0
}
763
764
static void
765
odp_execute_clone(void *dp, struct dp_packet_batch *batch, bool steal,
766
                   const struct nlattr *actions,
767
                   odp_execute_cb dp_execute_action)
768
0
{
769
0
    if (!steal) {
770
        /* The 'actions' may modify the packet, but the modification
771
         * should not propagate beyond this clone action. Make a copy
772
         * the packet in case we don't own the packet, so that the
773
         * 'actions' are only applied to the clone.  'odp_execute_actions'
774
         * will free the clone.  */
775
0
        struct dp_packet_batch clone_pkt_batch;
776
0
        dp_packet_batch_clone(&clone_pkt_batch, batch);
777
0
        dp_packet_batch_reset_cutlen(batch);
778
0
        odp_execute_actions(dp, &clone_pkt_batch, true, nl_attr_get(actions),
779
0
                        nl_attr_get_size(actions), dp_execute_action);
780
0
        dp_packet_batch_destroy(&clone_pkt_batch);
781
0
    }
782
0
    else {
783
0
        odp_execute_actions(dp, batch, true, nl_attr_get(actions),
784
0
                            nl_attr_get_size(actions), dp_execute_action);
785
0
    }
786
0
}
787
788
static void
789
odp_execute_check_pkt_len(void *dp, struct dp_packet *packet, bool steal,
790
                          const struct nlattr *action,
791
                          odp_execute_cb dp_execute_action)
792
0
{
793
0
    static const struct nl_policy ovs_cpl_policy[] = {
794
0
        [OVS_CHECK_PKT_LEN_ATTR_PKT_LEN] = { .type = NL_A_U16 },
795
0
        [OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER] = { .type = NL_A_NESTED },
796
0
        [OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL]
797
0
            = { .type = NL_A_NESTED },
798
0
    };
799
0
    struct nlattr *attrs[ARRAY_SIZE(ovs_cpl_policy)];
800
801
0
    if (!nl_parse_nested(action, ovs_cpl_policy, attrs, ARRAY_SIZE(attrs))) {
802
0
        OVS_NOT_REACHED();
803
0
    }
804
805
0
    const struct nlattr *a;
806
0
    struct dp_packet_batch pb;
807
0
    uint32_t size = dp_packet_get_send_len(packet)
808
0
                    - dp_packet_l2_pad_size(packet);
809
810
0
    if (dp_packet_get_tso_segsz(packet)) {
811
0
        const void *payload;
812
0
        uint32_t segsize;
813
814
0
        if (dp_packet_tunnel(packet)) {
815
0
            payload = dp_packet_get_inner_tcp_payload(packet);
816
0
        } else {
817
0
            payload = dp_packet_get_tcp_payload(packet);
818
0
        }
819
0
        if (payload) {
820
            /* Evaluate a segment maximum length for this TSO packet. */
821
0
            segsize = (char *) payload - (char *) dp_packet_data(packet)
822
0
                      + dp_packet_get_tso_segsz(packet);
823
0
            if (segsize < size) {
824
0
                size = segsize;
825
0
            }
826
0
        }
827
0
    }
828
829
0
    a = attrs[OVS_CHECK_PKT_LEN_ATTR_PKT_LEN];
830
0
    if (size > nl_attr_get_u16(a)) {
831
0
        a = attrs[OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER];
832
0
    } else {
833
0
        a = attrs[OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL];
834
0
    }
835
836
0
    if (!steal) {
837
        /* The 'subactions' may modify the packet, but the modification
838
         * should not propagate beyond this action. Make a copy
839
         * the packet in case we don't own the packet, so that the
840
         * 'subactions' are only applid to check_pkt_len. 'odp_execute_actions'
841
         * will free the clone.  */
842
0
        packet = dp_packet_clone(packet);
843
0
    }
844
    /* If nl_attr_get(a) is NULL, the packet will be freed by
845
     * odp_execute_actions. */
846
0
    dp_packet_batch_init_packet(&pb, packet);
847
0
    odp_execute_actions(dp, &pb, true, nl_attr_get(a), nl_attr_get_size(a),
848
0
                        dp_execute_action);
849
0
    dp_packet_batch_destroy(&pb);
850
0
}
851
852
static bool
853
requires_datapath_assistance(const struct nlattr *a)
854
0
{
855
0
    enum ovs_action_attr type = nl_attr_type(a);
856
857
0
    switch (type) {
858
        /* These only make sense in the context of a datapath. */
859
0
    case OVS_ACTION_ATTR_OUTPUT:
860
0
    case OVS_ACTION_ATTR_LB_OUTPUT:
861
0
    case OVS_ACTION_ATTR_TUNNEL_PUSH:
862
0
    case OVS_ACTION_ATTR_TUNNEL_POP:
863
0
    case OVS_ACTION_ATTR_USERSPACE:
864
0
    case OVS_ACTION_ATTR_RECIRC:
865
0
    case OVS_ACTION_ATTR_CT:
866
0
    case OVS_ACTION_ATTR_METER:
867
0
    case OVS_ACTION_ATTR_PSAMPLE:
868
0
        return true;
869
870
0
    case OVS_ACTION_ATTR_SET:
871
0
    case OVS_ACTION_ATTR_SET_MASKED:
872
0
    case OVS_ACTION_ATTR_PUSH_VLAN:
873
0
    case OVS_ACTION_ATTR_POP_VLAN:
874
0
    case OVS_ACTION_ATTR_HASH:
875
0
    case OVS_ACTION_ATTR_PUSH_MPLS:
876
0
    case OVS_ACTION_ATTR_POP_MPLS:
877
0
    case OVS_ACTION_ATTR_TRUNC:
878
0
    case OVS_ACTION_ATTR_PUSH_ETH:
879
0
    case OVS_ACTION_ATTR_POP_ETH:
880
0
    case OVS_ACTION_ATTR_CLONE:
881
0
    case OVS_ACTION_ATTR_PUSH_NSH:
882
0
    case OVS_ACTION_ATTR_POP_NSH:
883
0
    case OVS_ACTION_ATTR_CT_CLEAR:
884
0
    case OVS_ACTION_ATTR_CHECK_PKT_LEN:
885
0
    case OVS_ACTION_ATTR_ADD_MPLS:
886
0
    case OVS_ACTION_ATTR_DEC_TTL:
887
0
    case OVS_ACTION_ATTR_DROP:
888
0
        return false;
889
890
0
    case OVS_ACTION_ATTR_SAMPLE: {
891
        /* Nested "psample" actions rely on the datapath executing the
892
         * parent "sample", storing the probability and making it available
893
         * when the nested "psample" is run. */
894
0
        const struct nlattr *attr;
895
0
        unsigned int left;
896
897
0
        NL_NESTED_FOR_EACH (attr, left, a) {
898
0
            if (nl_attr_type(attr) == OVS_SAMPLE_ATTR_ACTIONS) {
899
0
                const struct nlattr *act;
900
0
                unsigned int act_left;
901
902
0
                NL_NESTED_FOR_EACH (act, act_left, attr) {
903
0
                    if (nl_attr_type(act) == OVS_ACTION_ATTR_PSAMPLE) {
904
0
                        return true;
905
0
                    }
906
0
                }
907
0
            }
908
0
        }
909
0
        return false;
910
0
    }
911
912
0
    case OVS_ACTION_ATTR_UNSPEC:
913
0
    case __OVS_ACTION_ATTR_MAX:
914
0
        OVS_NOT_REACHED();
915
0
    }
916
917
0
    return false;
918
0
}
919
920
/* Executes all of the 'actions_len' bytes of datapath actions in 'actions' on
921
 * the packets in 'batch'.  If 'steal' is true, possibly modifies and
922
 * definitely free the packets in 'batch', otherwise leaves 'batch' unchanged.
923
 *
924
 * Some actions (e.g. output actions) can only be executed by a datapath.  This
925
 * function implements those actions by passing the action and the packets to
926
 * 'dp_execute_action' (along with 'dp').  If 'dp_execute_action' is passed a
927
 * true 'steal' parameter then it must definitely free the packets passed into
928
 * it.  The packet can be modified whether 'steal' is false or true.  If a
929
 * packet is removed from the batch, then the fate of the packet is determined
930
 * by the code that does this removal, irrespective of the value of 'steal'.
931
 * Otherwise, if the packet is not removed from the batch and 'steal' is false
932
 * then the packet could either be cloned or not. */
933
void
934
odp_execute_actions(void *dp, struct dp_packet_batch *batch, bool steal,
935
                    const struct nlattr *actions, size_t actions_len,
936
                    odp_execute_cb dp_execute_action)
937
0
{
938
0
    struct dp_packet *packet;
939
0
    const struct nlattr *a;
940
0
    unsigned int left;
941
942
0
    NL_ATTR_FOR_EACH_UNSAFE (a, left, actions, actions_len) {
943
0
        int type = nl_attr_type(a);
944
0
        enum ovs_action_attr attr_type = (enum ovs_action_attr) type;
945
0
        bool last_action = (left <= NLA_ALIGN(a->nla_len));
946
947
0
        if (requires_datapath_assistance(a)) {
948
0
            if (dp_execute_action) {
949
                /* Allow 'dp_execute_action' to steal the packet data if we do
950
                 * not need it any more. */
951
0
                bool should_steal = steal && last_action;
952
953
0
                dp_execute_action(dp, batch, a, should_steal);
954
955
0
                if (last_action || dp_packet_batch_is_empty(batch)) {
956
                    /* We do not need to free the packets.
957
                     * Either dp_execute_actions() has stolen them
958
                     * or the batch is freed due to errors. In either
959
                     * case we do not need to execute further actions.
960
                     */
961
0
                    return;
962
0
                }
963
0
            }
964
0
            continue;
965
0
        }
966
967
0
        switch (attr_type) {
968
0
        case OVS_ACTION_ATTR_POP_VLAN:
969
0
            DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
970
0
                eth_pop_vlan(packet);
971
0
            }
972
0
            break;
973
974
0
        case OVS_ACTION_ATTR_PUSH_VLAN: {
975
0
            const struct ovs_action_push_vlan *vlan = nl_attr_get(a);
976
977
0
            DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
978
0
                eth_push_vlan(packet, vlan->vlan_tpid, vlan->vlan_tci);
979
0
            }
980
0
            break;
981
0
        }
982
983
0
        case OVS_ACTION_ATTR_HASH: {
984
0
            const struct ovs_action_hash *hash_act = nl_attr_get(a);
985
986
            /* Calculate a hash value directly. This might not match the
987
             * value computed by the datapath, but it is much less expensive,
988
             * and the current use case (bonding) does not require a strict
989
             * match to work properly. */
990
0
            switch (hash_act->hash_alg) {
991
0
            case OVS_HASH_ALG_L4: {
992
0
                struct flow flow;
993
0
                uint32_t hash;
994
995
0
                DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
996
                    /* RSS hash can be used here instead of 5tuple for
997
                     * performance reasons. */
998
0
                    if (dp_packet_rss_valid(packet)) {
999
0
                        hash = dp_packet_get_rss_hash(packet);
1000
0
                        hash = hash_int(hash, hash_act->hash_basis);
1001
0
                    } else {
1002
0
                        flow_extract(packet, &flow);
1003
0
                        hash = flow_hash_5tuple(&flow, hash_act->hash_basis);
1004
0
                    }
1005
0
                    packet->md.dp_hash = hash;
1006
0
                }
1007
0
                break;
1008
0
            }
1009
0
            case OVS_HASH_ALG_SYM_L4: {
1010
0
                struct flow flow;
1011
0
                uint32_t hash;
1012
1013
0
                DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
1014
0
                    flow_extract(packet, &flow);
1015
0
                    hash = flow_hash_symmetric_l3l4(&flow,
1016
0
                                                    hash_act->hash_basis,
1017
0
                                                    false);
1018
0
                    packet->md.dp_hash = hash;
1019
0
                }
1020
0
                break;
1021
0
            }
1022
0
            default:
1023
                /* Assert on unknown hash algorithm.  */
1024
0
                OVS_NOT_REACHED();
1025
0
            }
1026
0
            break;
1027
0
        }
1028
1029
0
        case OVS_ACTION_ATTR_PUSH_MPLS: {
1030
0
            const struct ovs_action_push_mpls *mpls = nl_attr_get(a);
1031
1032
0
            DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
1033
0
                push_mpls(packet, mpls->mpls_ethertype, mpls->mpls_lse);
1034
0
            }
1035
0
            break;
1036
0
         }
1037
1038
0
        case OVS_ACTION_ATTR_POP_MPLS:
1039
0
            DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
1040
0
                pop_mpls(packet, nl_attr_get_be16(a));
1041
0
            }
1042
0
            break;
1043
1044
0
        case OVS_ACTION_ATTR_SET:
1045
0
            DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
1046
0
                odp_execute_set_action(packet, nl_attr_get(a));
1047
0
            }
1048
0
            break;
1049
1050
0
        case OVS_ACTION_ATTR_SET_MASKED:
1051
0
            DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
1052
0
                odp_execute_masked_set_action(packet, nl_attr_get(a));
1053
0
            }
1054
0
            break;
1055
1056
0
        case OVS_ACTION_ATTR_SAMPLE:
1057
0
            DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
1058
0
                odp_execute_sample(dp, packet, steal && last_action, a,
1059
0
                                   dp_execute_action);
1060
0
            }
1061
1062
0
            if (last_action) {
1063
                /* We do not need to free the packets. odp_execute_sample() has
1064
                 * stolen them*/
1065
0
                return;
1066
0
            }
1067
0
            break;
1068
1069
0
        case OVS_ACTION_ATTR_TRUNC: {
1070
0
            const struct ovs_action_trunc *trunc =
1071
0
                        nl_attr_get_unspec(a, sizeof *trunc);
1072
1073
0
            batch->trunc = true;
1074
0
            DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
1075
0
                dp_packet_set_cutlen(packet, trunc->max_len);
1076
0
            }
1077
0
            break;
1078
0
        }
1079
1080
0
        case OVS_ACTION_ATTR_CLONE:
1081
0
            odp_execute_clone(dp, batch, steal && last_action, a,
1082
0
                                                dp_execute_action);
1083
0
            if (last_action) {
1084
                /* We do not need to free the packets. odp_execute_clone() has
1085
                 * stolen them.  */
1086
0
                return;
1087
0
            }
1088
0
            break;
1089
0
        case OVS_ACTION_ATTR_METER:
1090
            /* Not implemented yet. */
1091
0
            break;
1092
0
        case OVS_ACTION_ATTR_PUSH_ETH: {
1093
0
            const struct ovs_action_push_eth *eth = nl_attr_get(a);
1094
1095
0
            DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
1096
0
                push_eth(packet, &eth->addresses.eth_dst,
1097
0
                         &eth->addresses.eth_src);
1098
0
            }
1099
0
            break;
1100
0
        }
1101
1102
0
        case OVS_ACTION_ATTR_POP_ETH:
1103
0
            DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
1104
0
                pop_eth(packet);
1105
0
            }
1106
0
            break;
1107
1108
0
        case OVS_ACTION_ATTR_PUSH_NSH: {
1109
0
            uint32_t buffer[NSH_HDR_MAX_LEN / 4];
1110
0
            struct nsh_hdr *nsh_hdr = ALIGNED_CAST(struct nsh_hdr *, buffer);
1111
0
            nsh_reset_ver_flags_ttl_len(nsh_hdr);
1112
0
            odp_nsh_hdr_from_attr(nl_attr_get(a), nsh_hdr, NSH_HDR_MAX_LEN);
1113
0
            DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
1114
0
                push_nsh(packet, nsh_hdr);
1115
0
            }
1116
0
            break;
1117
0
        }
1118
0
        case OVS_ACTION_ATTR_POP_NSH: {
1119
0
            size_t i;
1120
0
            const size_t num = dp_packet_batch_size(batch);
1121
1122
0
            DP_PACKET_BATCH_REFILL_FOR_EACH (i, num, packet, batch) {
1123
0
                if (pop_nsh(packet)) {
1124
0
                    dp_packet_batch_add(batch, packet);
1125
0
                } else {
1126
0
                    COVERAGE_INC(datapath_drop_nsh_decap_error);
1127
0
                    dp_packet_delete(packet);
1128
0
                }
1129
0
            }
1130
0
            break;
1131
0
        }
1132
0
        case OVS_ACTION_ATTR_CT_CLEAR:
1133
0
            DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
1134
0
                conntrack_clear(packet);
1135
0
            }
1136
0
            break;
1137
1138
0
        case OVS_ACTION_ATTR_CHECK_PKT_LEN:
1139
0
            DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
1140
0
                odp_execute_check_pkt_len(dp, packet, steal && last_action, a,
1141
0
                                          dp_execute_action);
1142
0
            }
1143
1144
0
            if (last_action) {
1145
                /* We do not need to free the packets.
1146
                 * odp_execute_check_pkt_len() has stolen them. */
1147
0
                return;
1148
0
            }
1149
0
            break;
1150
1151
0
        case OVS_ACTION_ATTR_ADD_MPLS: {
1152
0
            const struct ovs_action_add_mpls *mpls = nl_attr_get(a);
1153
0
            bool l3_flag =  mpls->tun_flags & OVS_MPLS_L3_TUNNEL_FLAG_MASK;
1154
1155
0
            DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
1156
0
                add_mpls(packet, mpls->mpls_ethertype, mpls->mpls_lse,
1157
0
                         l3_flag);
1158
0
            }
1159
0
            break;
1160
0
        }
1161
1162
0
        case OVS_ACTION_ATTR_DROP:{
1163
0
            const enum xlate_error *drop_reason = nl_attr_get(a);
1164
1165
0
            dp_update_drop_action_counter(*drop_reason,
1166
0
                                          dp_packet_batch_size(batch));
1167
0
            dp_packet_delete_batch(batch, steal);
1168
0
            return;
1169
0
        }
1170
0
        case OVS_ACTION_ATTR_OUTPUT:
1171
0
        case OVS_ACTION_ATTR_LB_OUTPUT:
1172
0
        case OVS_ACTION_ATTR_TUNNEL_PUSH:
1173
0
        case OVS_ACTION_ATTR_TUNNEL_POP:
1174
0
        case OVS_ACTION_ATTR_USERSPACE:
1175
0
        case OVS_ACTION_ATTR_RECIRC:
1176
0
        case OVS_ACTION_ATTR_CT:
1177
0
        case OVS_ACTION_ATTR_UNSPEC:
1178
0
        case OVS_ACTION_ATTR_DEC_TTL:
1179
0
        case OVS_ACTION_ATTR_PSAMPLE:
1180
0
        case __OVS_ACTION_ATTR_MAX:
1181
0
            OVS_NOT_REACHED();
1182
0
        }
1183
0
    }
1184
1185
0
    dp_packet_delete_batch(batch, steal);
1186
0
}