LCOV - code coverage report
Current view: top level - lib - odp-execute.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 219 276 79.3 %
Date: 2016-09-14 01:02:56 Functions: 16 16 100.0 %
Branches: 101 148 68.2 %

           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                 :            : }

Generated by: LCOV version 1.12