LCOV - code coverage report
Current view: top level - lib - odp-util.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2504 2804 89.3 %
Date: 2016-09-14 01:02:56 Functions: 155 161 96.3 %
Branches: 2045 2699 75.8 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
       3                 :            :  *
       4                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
       5                 :            :  * you may not use this file except in compliance with the License.
       6                 :            :  * You may obtain a copy of the License at:
       7                 :            :  *
       8                 :            :  *     http://www.apache.org/licenses/LICENSE-2.0
       9                 :            :  *
      10                 :            :  * Unless required by applicable law or agreed to in writing, software
      11                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      12                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13                 :            :  * See the License for the specific language governing permissions and
      14                 :            :  * limitations under the License.
      15                 :            :  */
      16                 :            : 
      17                 :            : #include <config.h>
      18                 :            : #include <arpa/inet.h>
      19                 :            : #include "odp-util.h"
      20                 :            : #include <errno.h>
      21                 :            : #include <inttypes.h>
      22                 :            : #include <math.h>
      23                 :            : #include <netinet/in.h>
      24                 :            : #include <netinet/icmp6.h>
      25                 :            : #include <netinet/ip6.h>
      26                 :            : #include <stdlib.h>
      27                 :            : #include <string.h>
      28                 :            : 
      29                 :            : #include "byte-order.h"
      30                 :            : #include "coverage.h"
      31                 :            : #include "dpif.h"
      32                 :            : #include "openvswitch/dynamic-string.h"
      33                 :            : #include "flow.h"
      34                 :            : #include "netlink.h"
      35                 :            : #include "openvswitch/ofpbuf.h"
      36                 :            : #include "packets.h"
      37                 :            : #include "simap.h"
      38                 :            : #include "timeval.h"
      39                 :            : #include "tun-metadata.h"
      40                 :            : #include "unaligned.h"
      41                 :            : #include "util.h"
      42                 :            : #include "uuid.h"
      43                 :            : #include "openvswitch/vlog.h"
      44                 :            : 
      45                 :      20190 : VLOG_DEFINE_THIS_MODULE(odp_util);
      46                 :            : 
      47                 :            : /* The interface between userspace and kernel uses an "OVS_*" prefix.
      48                 :            :  * Since this is fairly non-specific for the OVS userspace components,
      49                 :            :  * "ODP_*" (Open vSwitch Datapath) is used as the prefix for
      50                 :            :  * interactions with the datapath.
      51                 :            :  */
      52                 :            : 
      53                 :            : /* The set of characters that may separate one action or one key attribute
      54                 :            :  * from another. */
      55                 :            : static const char *delimiters = ", \t\r\n";
      56                 :            : static const char *delimiters_end = ", \t\r\n)";
      57                 :            : 
      58                 :            : struct attr_len_tbl {
      59                 :            :     int len;
      60                 :            :     const struct attr_len_tbl *next;
      61                 :            :     int next_max;
      62                 :            : };
      63                 :            : #define ATTR_LEN_INVALID  -1
      64                 :            : #define ATTR_LEN_VARIABLE -2
      65                 :            : #define ATTR_LEN_NESTED   -3
      66                 :            : 
      67                 :            : static int parse_odp_key_mask_attr(const char *, const struct simap *port_names,
      68                 :            :                               struct ofpbuf *, struct ofpbuf *);
      69                 :            : static void format_odp_key_attr(const struct nlattr *a,
      70                 :            :                                 const struct nlattr *ma,
      71                 :            :                                 const struct hmap *portno_names, struct ds *ds,
      72                 :            :                                 bool verbose);
      73                 :            : 
      74                 :            : struct geneve_scan {
      75                 :            :     struct geneve_opt d[63];
      76                 :            :     int len;
      77                 :            : };
      78                 :            : 
      79                 :            : static int scan_geneve(const char *s, struct geneve_scan *key,
      80                 :            :                        struct geneve_scan *mask);
      81                 :            : static void format_geneve_opts(const struct geneve_opt *opt,
      82                 :            :                                const struct geneve_opt *mask, int opts_len,
      83                 :            :                                struct ds *, bool verbose);
      84                 :            : 
      85                 :            : static struct nlattr *generate_all_wildcard_mask(const struct attr_len_tbl tbl[],
      86                 :            :                                                  int max, struct ofpbuf *,
      87                 :            :                                                  const struct nlattr *key);
      88                 :            : static void format_u128(struct ds *ds, const ovs_u128 *value,
      89                 :            :                         const ovs_u128 *mask, bool verbose);
      90                 :            : static int scan_u128(const char *s, ovs_u128 *value, ovs_u128 *mask);
      91                 :            : 
      92                 :            : /* Returns one the following for the action with the given OVS_ACTION_ATTR_*
      93                 :            :  * 'type':
      94                 :            :  *
      95                 :            :  *   - For an action whose argument has a fixed length, returned that
      96                 :            :  *     nonnegative length in bytes.
      97                 :            :  *
      98                 :            :  *   - For an action with a variable-length argument, returns ATTR_LEN_VARIABLE.
      99                 :            :  *
     100                 :            :  *   - For an invalid 'type', returns ATTR_LEN_INVALID. */
     101                 :            : static int
     102                 :   15594900 : odp_action_len(uint16_t type)
     103                 :            : {
     104         [ -  + ]:   15594900 :     if (type > OVS_ACTION_ATTR_MAX) {
     105                 :          0 :         return -1;
     106                 :            :     }
     107                 :            : 
     108   [ +  +  +  +  :   15594900 :     switch ((enum ovs_action_attr) type) {
          +  +  +  +  +  
          +  +  +  +  +  
                +  -  - ]
     109                 :   15593689 :     case OVS_ACTION_ATTR_OUTPUT: return sizeof(uint32_t);
     110                 :         32 :     case OVS_ACTION_ATTR_TRUNC: return sizeof(struct ovs_action_trunc);
     111                 :         25 :     case OVS_ACTION_ATTR_TUNNEL_PUSH: return ATTR_LEN_VARIABLE;
     112                 :          7 :     case OVS_ACTION_ATTR_TUNNEL_POP: return sizeof(uint32_t);
     113                 :         63 :     case OVS_ACTION_ATTR_USERSPACE: return ATTR_LEN_VARIABLE;
     114                 :        110 :     case OVS_ACTION_ATTR_PUSH_VLAN: return sizeof(struct ovs_action_push_vlan);
     115                 :        109 :     case OVS_ACTION_ATTR_POP_VLAN: return 0;
     116                 :          6 :     case OVS_ACTION_ATTR_PUSH_MPLS: return sizeof(struct ovs_action_push_mpls);
     117                 :          9 :     case OVS_ACTION_ATTR_POP_MPLS: return sizeof(ovs_be16);
     118                 :        319 :     case OVS_ACTION_ATTR_RECIRC: return sizeof(uint32_t);
     119                 :        256 :     case OVS_ACTION_ATTR_HASH: return sizeof(struct ovs_action_hash);
     120                 :         83 :     case OVS_ACTION_ATTR_SET: return ATTR_LEN_VARIABLE;
     121                 :        104 :     case OVS_ACTION_ATTR_SET_MASKED: return ATTR_LEN_VARIABLE;
     122                 :         10 :     case OVS_ACTION_ATTR_SAMPLE: return ATTR_LEN_VARIABLE;
     123                 :         78 :     case OVS_ACTION_ATTR_CT: return ATTR_LEN_VARIABLE;
     124                 :            : 
     125                 :            :     case OVS_ACTION_ATTR_UNSPEC:
     126                 :            :     case __OVS_ACTION_ATTR_MAX:
     127                 :          0 :         return ATTR_LEN_INVALID;
     128                 :            :     }
     129                 :            : 
     130                 :          0 :     return ATTR_LEN_INVALID;
     131                 :            : }
     132                 :            : 
     133                 :            : /* Returns a string form of 'attr'.  The return value is either a statically
     134                 :            :  * allocated constant string or the 'bufsize'-byte buffer 'namebuf'.  'bufsize'
     135                 :            :  * should be at least OVS_KEY_ATTR_BUFSIZE. */
     136                 :            : enum { OVS_KEY_ATTR_BUFSIZE = 3 + INT_STRLEN(unsigned int) + 1 };
     137                 :            : static const char *
     138                 :      23501 : ovs_key_attr_to_string(enum ovs_key_attr attr, char *namebuf, size_t bufsize)
     139                 :            : {
     140   [ -  +  +  +  :      23501 :     switch (attr) {
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
                +  +  - ]
     141                 :          0 :     case OVS_KEY_ATTR_UNSPEC: return "unspec";
     142                 :        265 :     case OVS_KEY_ATTR_ENCAP: return "encap";
     143                 :       1435 :     case OVS_KEY_ATTR_PRIORITY: return "skb_priority";
     144                 :       1412 :     case OVS_KEY_ATTR_SKB_MARK: return "skb_mark";
     145                 :       1439 :     case OVS_KEY_ATTR_CT_STATE: return "ct_state";
     146                 :       1410 :     case OVS_KEY_ATTR_CT_ZONE: return "ct_zone";
     147                 :       1412 :     case OVS_KEY_ATTR_CT_MARK: return "ct_mark";
     148                 :       1411 :     case OVS_KEY_ATTR_CT_LABELS: return "ct_label";
     149                 :        202 :     case OVS_KEY_ATTR_TUNNEL: return "tunnel";
     150                 :       2207 :     case OVS_KEY_ATTR_IN_PORT: return "in_port";
     151                 :       2048 :     case OVS_KEY_ATTR_ETHERNET: return "eth";
     152                 :        265 :     case OVS_KEY_ATTR_VLAN: return "vlan";
     153                 :       2456 :     case OVS_KEY_ATTR_ETHERTYPE: return "eth_type";
     154                 :       1667 :     case OVS_KEY_ATTR_IPV4: return "ipv4";
     155                 :        212 :     case OVS_KEY_ATTR_IPV6: return "ipv6";
     156                 :        958 :     case OVS_KEY_ATTR_TCP: return "tcp";
     157                 :        788 :     case OVS_KEY_ATTR_TCP_FLAGS: return "tcp_flags";
     158                 :        111 :     case OVS_KEY_ATTR_UDP: return "udp";
     159                 :          4 :     case OVS_KEY_ATTR_SCTP: return "sctp";
     160                 :        293 :     case OVS_KEY_ATTR_ICMP: return "icmp";
     161                 :         91 :     case OVS_KEY_ATTR_ICMPV6: return "icmpv6";
     162                 :         89 :     case OVS_KEY_ATTR_ARP: return "arp";
     163                 :         68 :     case OVS_KEY_ATTR_ND: return "nd";
     164                 :         57 :     case OVS_KEY_ATTR_MPLS: return "mpls";
     165                 :       1394 :     case OVS_KEY_ATTR_DP_HASH: return "dp_hash";
     166                 :       1807 :     case OVS_KEY_ATTR_RECIRC_ID: return "recirc_id";
     167                 :            : 
     168                 :            :     case __OVS_KEY_ATTR_MAX:
     169                 :            :     default:
     170                 :          0 :         snprintf(namebuf, bufsize, "key%u", (unsigned int) attr);
     171                 :          0 :         return namebuf;
     172                 :            :     }
     173                 :            : }
     174                 :            : 
     175                 :            : static void
     176                 :          0 : format_generic_odp_action(struct ds *ds, const struct nlattr *a)
     177                 :            : {
     178                 :          0 :     size_t len = nl_attr_get_size(a);
     179                 :            : 
     180                 :          0 :     ds_put_format(ds, "action%"PRId16, nl_attr_type(a));
     181         [ #  # ]:          0 :     if (len) {
     182                 :            :         const uint8_t *unspec;
     183                 :            :         unsigned int i;
     184                 :            : 
     185                 :          0 :         unspec = nl_attr_get(a);
     186         [ #  # ]:          0 :         for (i = 0; i < len; i++) {
     187         [ #  # ]:          0 :             ds_put_char(ds, i ? ' ': '(');
     188                 :          0 :             ds_put_format(ds, "%02x", unspec[i]);
     189                 :            :         }
     190                 :          0 :         ds_put_char(ds, ')');
     191                 :            :     }
     192                 :          0 : }
     193                 :            : 
     194                 :            : static void
     195                 :         10 : format_odp_sample_action(struct ds *ds, const struct nlattr *attr)
     196                 :            : {
     197                 :            :     static const struct nl_policy ovs_sample_policy[] = {
     198                 :            :         [OVS_SAMPLE_ATTR_PROBABILITY] = { .type = NL_A_U32 },
     199                 :            :         [OVS_SAMPLE_ATTR_ACTIONS] = { .type = NL_A_NESTED }
     200                 :            :     };
     201                 :            :     struct nlattr *a[ARRAY_SIZE(ovs_sample_policy)];
     202                 :            :     double percentage;
     203                 :            :     const struct nlattr *nla_acts;
     204                 :            :     int len;
     205                 :            : 
     206                 :         10 :     ds_put_cstr(ds, "sample");
     207                 :            : 
     208         [ -  + ]:         10 :     if (!nl_parse_nested(attr, ovs_sample_policy, a, ARRAY_SIZE(a))) {
     209                 :          0 :         ds_put_cstr(ds, "(error)");
     210                 :          0 :         return;
     211                 :            :     }
     212                 :            : 
     213                 :         10 :     percentage = (100.0 * nl_attr_get_u32(a[OVS_SAMPLE_ATTR_PROBABILITY])) /
     214                 :            :                         UINT32_MAX;
     215                 :            : 
     216                 :         10 :     ds_put_format(ds, "(sample=%.1f%%,", percentage);
     217                 :            : 
     218                 :         10 :     ds_put_cstr(ds, "actions(");
     219                 :         10 :     nla_acts = nl_attr_get(a[OVS_SAMPLE_ATTR_ACTIONS]);
     220                 :         10 :     len = nl_attr_get_size(a[OVS_SAMPLE_ATTR_ACTIONS]);
     221                 :         10 :     format_odp_actions(ds, nla_acts, len);
     222                 :         10 :     ds_put_format(ds, "))");
     223                 :            : }
     224                 :            : 
     225                 :            : static const char *
     226                 :         44 : slow_path_reason_to_string(uint32_t reason)
     227                 :            : {
     228   [ +  -  -  -  :         44 :     switch ((enum slow_path_reason) reason) {
             -  +  +  - ]
     229                 :            : #define SPR(ENUM, STRING, EXPLANATION) case ENUM: return STRING;
     230                 :         44 :         SLOW_PATH_REASONS
     231                 :            : #undef SPR
     232                 :            :     }
     233                 :            : 
     234                 :          0 :     return NULL;
     235                 :            : }
     236                 :            : 
     237                 :            : const char *
     238                 :          8 : slow_path_reason_to_explanation(enum slow_path_reason reason)
     239                 :            : {
     240   [ -  +  -  -  :          8 :     switch (reason) {
             -  +  +  - ]
     241                 :            : #define SPR(ENUM, STRING, EXPLANATION) case ENUM: return EXPLANATION;
     242                 :          8 :         SLOW_PATH_REASONS
     243                 :            : #undef SPR
     244                 :            :     }
     245                 :            : 
     246                 :          0 :     return "<unknown>";
     247                 :            : }
     248                 :            : 
     249                 :            : static int
     250                 :        500 : parse_odp_flags(const char *s, const char *(*bit_to_string)(uint32_t),
     251                 :            :                 uint32_t *res_flags, uint32_t allowed, uint32_t *res_mask)
     252                 :            : {
     253                 :        500 :     return parse_flags(s, bit_to_string, ')', NULL, NULL,
     254                 :            :                        res_flags, allowed, res_mask);
     255                 :            : }
     256                 :            : 
     257                 :            : static void
     258                 :         63 : format_odp_userspace_action(struct ds *ds, const struct nlattr *attr)
     259                 :            : {
     260                 :            :     static const struct nl_policy ovs_userspace_policy[] = {
     261                 :            :         [OVS_USERSPACE_ATTR_PID] = { .type = NL_A_U32 },
     262                 :            :         [OVS_USERSPACE_ATTR_USERDATA] = { .type = NL_A_UNSPEC,
     263                 :            :                                           .optional = true },
     264                 :            :         [OVS_USERSPACE_ATTR_EGRESS_TUN_PORT] = { .type = NL_A_U32,
     265                 :            :                                                  .optional = true },
     266                 :            :         [OVS_USERSPACE_ATTR_ACTIONS] = { .type = NL_A_UNSPEC,
     267                 :            :                                                  .optional = true },
     268                 :            :     };
     269                 :            :     struct nlattr *a[ARRAY_SIZE(ovs_userspace_policy)];
     270                 :            :     const struct nlattr *userdata_attr;
     271                 :            :     const struct nlattr *tunnel_out_port_attr;
     272                 :            : 
     273         [ -  + ]:         63 :     if (!nl_parse_nested(attr, ovs_userspace_policy, a, ARRAY_SIZE(a))) {
     274                 :          0 :         ds_put_cstr(ds, "userspace(error)");
     275                 :          0 :         return;
     276                 :            :     }
     277                 :            : 
     278                 :         63 :     ds_put_format(ds, "userspace(pid=%"PRIu32,
     279                 :         63 :                   nl_attr_get_u32(a[OVS_USERSPACE_ATTR_PID]));
     280                 :            : 
     281                 :         63 :     userdata_attr = a[OVS_USERSPACE_ATTR_USERDATA];
     282                 :            : 
     283         [ +  + ]:         63 :     if (userdata_attr) {
     284                 :         61 :         const uint8_t *userdata = nl_attr_get(userdata_attr);
     285                 :         61 :         size_t userdata_len = nl_attr_get_size(userdata_attr);
     286                 :         61 :         bool userdata_unspec = true;
     287                 :            :         union user_action_cookie cookie;
     288                 :            : 
     289         [ +  - ]:         61 :         if (userdata_len >= sizeof cookie.type
     290         [ +  - ]:         61 :             && userdata_len <= sizeof cookie) {
     291                 :            : 
     292                 :         61 :             memset(&cookie, 0, sizeof cookie);
     293                 :         61 :             memcpy(&cookie, userdata, userdata_len);
     294                 :            : 
     295                 :         61 :             userdata_unspec = false;
     296                 :            : 
     297         [ +  + ]:         61 :             if (userdata_len == sizeof cookie.sflow
     298         [ +  + ]:         52 :                 && cookie.type == USER_ACTION_COOKIE_SFLOW) {
     299                 :         10 :                 ds_put_format(ds, ",sFlow("
     300                 :            :                               "vid=%"PRIu16",pcp=%"PRIu8",output=%"PRIu32")",
     301                 :          5 :                               vlan_tci_to_vid(cookie.sflow.vlan_tci),
     302                 :          5 :                               vlan_tci_to_pcp(cookie.sflow.vlan_tci),
     303                 :            :                               cookie.sflow.output);
     304         [ +  + ]:         56 :             } else if (userdata_len == sizeof cookie.slow_path
     305         [ +  + ]:         47 :                        && cookie.type == USER_ACTION_COOKIE_SLOW_PATH) {
     306                 :         44 :                 ds_put_cstr(ds, ",slow_path(");
     307                 :         44 :                 format_flags(ds, slow_path_reason_to_string,
     308                 :            :                              cookie.slow_path.reason, ',');
     309                 :         44 :                 ds_put_format(ds, ")");
     310         [ +  + ]:         12 :             } else if (userdata_len == sizeof cookie.flow_sample
     311         [ +  - ]:          7 :                        && cookie.type == USER_ACTION_COOKIE_FLOW_SAMPLE) {
     312                 :          7 :                 ds_put_format(ds, ",flow_sample(probability=%"PRIu16
     313                 :            :                               ",collector_set_id=%"PRIu32
     314                 :            :                               ",obs_domain_id=%"PRIu32
     315                 :            :                               ",obs_point_id=%"PRIu32
     316                 :            :                               ",output_port=%"PRIu32")",
     317                 :          7 :                               cookie.flow_sample.probability,
     318                 :            :                               cookie.flow_sample.collector_set_id,
     319                 :            :                               cookie.flow_sample.obs_domain_id,
     320                 :            :                               cookie.flow_sample.obs_point_id,
     321                 :            :                               cookie.flow_sample.output_odp_port);
     322         [ +  - ]:          5 :             } else if (userdata_len >= sizeof cookie.ipfix
     323         [ +  + ]:          5 :                        && cookie.type == USER_ACTION_COOKIE_IPFIX) {
     324                 :          3 :                 ds_put_format(ds, ",ipfix(output_port=%"PRIu32")",
     325                 :            :                               cookie.ipfix.output_odp_port);
     326                 :            :             } else {
     327                 :          2 :                 userdata_unspec = true;
     328                 :            :             }
     329                 :            :         }
     330                 :            : 
     331         [ +  + ]:         61 :         if (userdata_unspec) {
     332                 :            :             size_t i;
     333                 :          2 :             ds_put_format(ds, ",userdata(");
     334         [ +  + ]:         32 :             for (i = 0; i < userdata_len; i++) {
     335                 :         30 :                 ds_put_format(ds, "%02x", userdata[i]);
     336                 :            :             }
     337                 :         61 :             ds_put_char(ds, ')');
     338                 :            :         }
     339                 :            :     }
     340                 :            : 
     341         [ +  + ]:         63 :     if (a[OVS_USERSPACE_ATTR_ACTIONS]) {
     342                 :          6 :         ds_put_cstr(ds, ",actions");
     343                 :            :     }
     344                 :            : 
     345                 :         63 :     tunnel_out_port_attr = a[OVS_USERSPACE_ATTR_EGRESS_TUN_PORT];
     346         [ +  + ]:         63 :     if (tunnel_out_port_attr) {
     347                 :         10 :         ds_put_format(ds, ",tunnel_out_port=%"PRIu32,
     348                 :            :                       nl_attr_get_u32(tunnel_out_port_attr));
     349                 :            :     }
     350                 :            : 
     351                 :         63 :     ds_put_char(ds, ')');
     352                 :            : }
     353                 :            : 
     354                 :            : static void
     355                 :        375 : format_vlan_tci(struct ds *ds, ovs_be16 tci, ovs_be16 mask, bool verbose)
     356                 :            : {
     357 [ +  + ][ +  + ]:        375 :     if (verbose || vlan_tci_to_vid(tci) || vlan_tci_to_vid(mask)) {
                 [ +  - ]
     358                 :        375 :         ds_put_format(ds, "vid=%"PRIu16, vlan_tci_to_vid(tci));
     359         [ -  + ]:        375 :         if (vlan_tci_to_vid(mask) != VLAN_VID_MASK) { /* Partially masked. */
     360                 :          0 :             ds_put_format(ds, "/0x%"PRIx16, vlan_tci_to_vid(mask));
     361                 :            :         };
     362                 :        375 :         ds_put_char(ds, ',');
     363                 :            :     }
     364 [ +  + ][ +  + ]:        375 :     if (verbose || vlan_tci_to_pcp(tci) || vlan_tci_to_pcp(mask)) {
                 [ +  + ]
     365                 :        374 :         ds_put_format(ds, "pcp=%d", vlan_tci_to_pcp(tci));
     366         [ +  + ]:        374 :         if (vlan_tci_to_pcp(mask) != (VLAN_PCP_MASK >> VLAN_PCP_SHIFT)) {
     367                 :          4 :             ds_put_format(ds, "/0x%x", vlan_tci_to_pcp(mask));
     368                 :            :         }
     369                 :        374 :         ds_put_char(ds, ',');
     370                 :            :     }
     371         [ +  + ]:        375 :     if (!(tci & htons(VLAN_CFI))) {
     372                 :          2 :         ds_put_cstr(ds, "cfi=0");
     373                 :          2 :         ds_put_char(ds, ',');
     374                 :            :     }
     375                 :        375 :     ds_chomp(ds, ',');
     376                 :        375 : }
     377                 :            : 
     378                 :            : static void
     379                 :         70 : format_mpls_lse(struct ds *ds, ovs_be32 mpls_lse)
     380                 :            : {
     381                 :         70 :     ds_put_format(ds, "label=%"PRIu32",tc=%d,ttl=%d,bos=%d",
     382                 :            :                   mpls_lse_to_label(mpls_lse),
     383                 :         70 :                   mpls_lse_to_tc(mpls_lse),
     384                 :         70 :                   mpls_lse_to_ttl(mpls_lse),
     385                 :         70 :                   mpls_lse_to_bos(mpls_lse));
     386                 :         70 : }
     387                 :            : 
     388                 :            : static void
     389                 :         57 : format_mpls(struct ds *ds, const struct ovs_key_mpls *mpls_key,
     390                 :            :             const struct ovs_key_mpls *mpls_mask, int n)
     391                 :            : {
     392         [ +  + ]:        126 :     for (int i = 0; i < n; i++) {
     393                 :         69 :         ovs_be32 key = mpls_key[i].mpls_lse;
     394                 :            : 
     395         [ +  + ]:         69 :         if (mpls_mask == NULL) {
     396                 :         64 :             format_mpls_lse(ds, key);
     397                 :            :         } else {
     398                 :          5 :             ovs_be32 mask = mpls_mask[i].mpls_lse;
     399                 :            : 
     400                 :          5 :             ds_put_format(ds, "label=%"PRIu32"/0x%x,tc=%d/%x,ttl=%d/0x%x,bos=%d/%x",
     401                 :            :                           mpls_lse_to_label(key), mpls_lse_to_label(mask),
     402                 :          5 :                           mpls_lse_to_tc(key), mpls_lse_to_tc(mask),
     403                 :          5 :                           mpls_lse_to_ttl(key), mpls_lse_to_ttl(mask),
     404                 :          5 :                           mpls_lse_to_bos(key), mpls_lse_to_bos(mask));
     405                 :            :         }
     406                 :         69 :         ds_put_char(ds, ',');
     407                 :            :     }
     408                 :         57 :     ds_chomp(ds, ',');
     409                 :         57 : }
     410                 :            : 
     411                 :            : static void
     412                 :        319 : format_odp_recirc_action(struct ds *ds, uint32_t recirc_id)
     413                 :            : {
     414                 :        319 :     ds_put_format(ds, "recirc(%#"PRIx32")", recirc_id);
     415                 :        319 : }
     416                 :            : 
     417                 :            : static void
     418                 :        256 : format_odp_hash_action(struct ds *ds, const struct ovs_action_hash *hash_act)
     419                 :            : {
     420                 :        256 :     ds_put_format(ds, "hash(");
     421                 :            : 
     422         [ +  - ]:        256 :     if (hash_act->hash_alg == OVS_HASH_ALG_L4) {
     423                 :        256 :         ds_put_format(ds, "hash_l4(%"PRIu32")", hash_act->hash_basis);
     424                 :            :     } else {
     425                 :          0 :         ds_put_format(ds, "Unknown hash algorithm(%"PRIu32")",
     426                 :            :                       hash_act->hash_alg);
     427                 :            :     }
     428                 :        256 :     ds_put_format(ds, ")");
     429                 :        256 : }
     430                 :            : 
     431                 :            : static const void *
     432                 :         18 : format_udp_tnl_push_header(struct ds *ds, const struct udp_header *udp)
     433                 :            : {
     434                 :         18 :     ds_put_format(ds, "udp(src=%"PRIu16",dst=%"PRIu16",csum=0x%"PRIx16"),",
     435                 :         18 :                   ntohs(udp->udp_src), ntohs(udp->udp_dst),
     436                 :         18 :                   ntohs(udp->udp_csum));
     437                 :            : 
     438                 :         18 :     return udp + 1;
     439                 :            : }
     440                 :            : 
     441                 :            : static void
     442                 :         25 : format_odp_tnl_push_header(struct ds *ds, struct ovs_action_push_tnl *data)
     443                 :            : {
     444                 :            :     const struct eth_header *eth;
     445                 :            :     const void *l3;
     446                 :            :     const void *l4;
     447                 :            :     const struct udp_header *udp;
     448                 :            : 
     449                 :         25 :     eth = (const struct eth_header *)data->header;
     450                 :            : 
     451                 :         25 :     l3 = eth + 1;
     452                 :            : 
     453                 :            :     /* Ethernet */
     454                 :         25 :     ds_put_format(ds, "header(size=%"PRIu8",type=%"PRIu8",eth(dst=",
     455                 :            :                   data->header_len, data->tnl_type);
     456                 :         25 :     ds_put_format(ds, ETH_ADDR_FMT, ETH_ADDR_ARGS(eth->eth_dst));
     457                 :         25 :     ds_put_format(ds, ",src=");
     458                 :         25 :     ds_put_format(ds, ETH_ADDR_FMT, ETH_ADDR_ARGS(eth->eth_src));
     459                 :         25 :     ds_put_format(ds, ",dl_type=0x%04"PRIx16"),", ntohs(eth->eth_type));
     460                 :            : 
     461         [ +  + ]:         25 :     if (eth->eth_type == htons(ETH_TYPE_IP)) {
     462                 :            :         /* IPv4 */
     463                 :            :         const struct ip_header *ip;
     464                 :         14 :         ip = (const struct ip_header *) l3;
     465                 :         14 :         ds_put_format(ds, "ipv4(src="IP_FMT",dst="IP_FMT",proto=%"PRIu8
     466                 :            :                       ",tos=%#"PRIx8",ttl=%"PRIu8",frag=0x%"PRIx16"),",
     467                 :         14 :                       IP_ARGS(get_16aligned_be32(&ip->ip_src)),
     468                 :         14 :                       IP_ARGS(get_16aligned_be32(&ip->ip_dst)),
     469                 :         28 :                       ip->ip_proto, ip->ip_tos,
     470                 :         14 :                       ip->ip_ttl,
     471                 :         14 :                       ntohs(ip->ip_frag_off));
     472                 :         14 :         l4 = (ip + 1);
     473                 :            :     } else {
     474                 :            :         const struct ip6_hdr *ip6;
     475                 :         11 :         ip6 = (const struct ip6_hdr *) l3;
     476                 :         11 :         ds_put_format(ds, "ipv6(src=");
     477                 :         11 :         ipv6_format_addr(&ip6->ip6_src, ds);
     478                 :         11 :         ds_put_format(ds, ",dst=");
     479                 :         11 :         ipv6_format_addr(&ip6->ip6_dst, ds);
     480                 :         11 :         ds_put_format(ds, ",label=%i,proto=%"PRIu8",tclass=0x%"PRIx8
     481                 :            :                           ",hlimit=%"PRIu8"),",
     482                 :         11 :                       ntohl(ip6->ip6_flow) & IPV6_LABEL_MASK, ip6->ip6_nxt,
     483                 :         11 :                       (ntohl(ip6->ip6_flow) >> 20) & 0xff, ip6->ip6_hlim);
     484                 :         11 :         l4 = (ip6 + 1);
     485                 :            :     }
     486                 :            : 
     487                 :         25 :     udp = (const struct udp_header *) l4;
     488                 :            : 
     489         [ +  + ]:         25 :     if (data->tnl_type == OVS_VPORT_TYPE_VXLAN) {
     490                 :            :         const struct vxlanhdr *vxh;
     491                 :            : 
     492                 :          6 :         vxh = format_udp_tnl_push_header(ds, udp);
     493                 :            : 
     494                 :          6 :         ds_put_format(ds, "vxlan(flags=0x%"PRIx32",vni=0x%"PRIx32")",
     495                 :            :                       ntohl(get_16aligned_be32(&vxh->vx_flags)),
     496                 :          6 :                       ntohl(get_16aligned_be32(&vxh->vx_vni)) >> 8);
     497         [ +  + ]:         19 :     } else if (data->tnl_type == OVS_VPORT_TYPE_GENEVE) {
     498                 :            :         const struct genevehdr *gnh;
     499                 :            : 
     500                 :         12 :         gnh = format_udp_tnl_push_header(ds, udp);
     501                 :            : 
     502 [ +  + ][ +  + ]:         12 :         ds_put_format(ds, "geneve(%s%svni=0x%"PRIx32,
     503                 :         12 :                       gnh->oam ? "oam," : "",
     504                 :         12 :                       gnh->critical ? "crit," : "",
     505                 :         12 :                       ntohl(get_16aligned_be32(&gnh->vni)) >> 8);
     506                 :            :  
     507         [ +  + ]:         12 :         if (gnh->opt_len) {
     508                 :          5 :             ds_put_cstr(ds, ",options(");
     509                 :          5 :             format_geneve_opts(gnh->options, NULL, gnh->opt_len * 4,
     510                 :            :                                ds, false);
     511                 :          5 :             ds_put_char(ds, ')');
     512                 :            :         }
     513                 :            : 
     514                 :         12 :         ds_put_char(ds, ')');
     515         [ +  - ]:          7 :     } else if (data->tnl_type == OVS_VPORT_TYPE_GRE) {
     516                 :            :         const struct gre_base_hdr *greh;
     517                 :            :         ovs_16aligned_be32 *options;
     518                 :            : 
     519                 :          7 :         greh = (const struct gre_base_hdr *) l4;
     520                 :            : 
     521                 :          7 :         ds_put_format(ds, "gre((flags=0x%"PRIx16",proto=0x%"PRIx16")",
     522                 :          7 :                            ntohs(greh->flags), ntohs(greh->protocol));
     523                 :          7 :         options = (ovs_16aligned_be32 *)(greh + 1);
     524         [ +  + ]:          7 :         if (greh->flags & htons(GRE_CSUM)) {
     525                 :          2 :             ds_put_format(ds, ",csum=0x%"PRIx16, ntohs(*((ovs_be16 *)options)));
     526                 :          2 :             options++;
     527                 :            :         }
     528         [ +  - ]:          7 :         if (greh->flags & htons(GRE_KEY)) {
     529                 :          7 :             ds_put_format(ds, ",key=0x%"PRIx32, ntohl(get_16aligned_be32(options)));
     530                 :          7 :             options++;
     531                 :            :         }
     532         [ -  + ]:          7 :         if (greh->flags & htons(GRE_SEQ)) {
     533                 :          0 :             ds_put_format(ds, ",seq=0x%"PRIx32, ntohl(get_16aligned_be32(options)));
     534                 :          0 :             options++;
     535                 :            :         }
     536                 :          7 :         ds_put_format(ds, ")");
     537                 :            :     }
     538                 :         25 :     ds_put_format(ds, ")");
     539                 :         25 : }
     540                 :            : 
     541                 :            : static void
     542                 :         25 : format_odp_tnl_push_action(struct ds *ds, const struct nlattr *attr)
     543                 :            : {
     544                 :            :     struct ovs_action_push_tnl *data;
     545                 :            : 
     546                 :         25 :     data = (struct ovs_action_push_tnl *) nl_attr_get(attr);
     547                 :            : 
     548                 :         25 :     ds_put_format(ds, "tnl_push(tnl_port(%"PRIu32"),", data->tnl_port);
     549                 :         25 :     format_odp_tnl_push_header(ds, data);
     550                 :         25 :     ds_put_format(ds, ",out_port(%"PRIu32"))", data->out_port);
     551                 :         25 : }
     552                 :            : 
     553                 :            : static const struct nl_policy ovs_nat_policy[] = {
     554                 :            :     [OVS_NAT_ATTR_SRC] = { .type = NL_A_FLAG, .optional = true, },
     555                 :            :     [OVS_NAT_ATTR_DST] = { .type = NL_A_FLAG, .optional = true, },
     556                 :            :     [OVS_NAT_ATTR_IP_MIN] = { .type = NL_A_UNSPEC, .optional = true,
     557                 :            :                               .min_len = sizeof(struct in_addr),
     558                 :            :                               .max_len = sizeof(struct in6_addr)},
     559                 :            :     [OVS_NAT_ATTR_IP_MAX] = { .type = NL_A_UNSPEC, .optional = true,
     560                 :            :                               .min_len = sizeof(struct in_addr),
     561                 :            :                               .max_len = sizeof(struct in6_addr)},
     562                 :            :     [OVS_NAT_ATTR_PROTO_MIN] = { .type = NL_A_U16, .optional = true, },
     563                 :            :     [OVS_NAT_ATTR_PROTO_MAX] = { .type = NL_A_U16, .optional = true, },
     564                 :            :     [OVS_NAT_ATTR_PERSISTENT] = { .type = NL_A_FLAG, .optional = true, },
     565                 :            :     [OVS_NAT_ATTR_PROTO_HASH] = { .type = NL_A_FLAG, .optional = true, },
     566                 :            :     [OVS_NAT_ATTR_PROTO_RANDOM] = { .type = NL_A_FLAG, .optional = true, },
     567                 :            : };
     568                 :            : 
     569                 :            : static void
     570                 :         48 : format_odp_ct_nat(struct ds *ds, const struct nlattr *attr)
     571                 :            : {
     572                 :            :     struct nlattr *a[ARRAY_SIZE(ovs_nat_policy)];
     573                 :            :     size_t addr_len;
     574                 :            :     ovs_be32 ip_min, ip_max;
     575                 :            :     struct in6_addr ip6_min, ip6_max;
     576                 :            :     uint16_t proto_min, proto_max;
     577                 :            : 
     578         [ -  + ]:         48 :     if (!nl_parse_nested(attr, ovs_nat_policy, a, ARRAY_SIZE(a))) {
     579                 :          0 :         ds_put_cstr(ds, "nat(error: nl_parse_nested() failed.)");
     580                 :          0 :         return;
     581                 :            :     }
     582                 :            :     /* If no type, then nothing else either. */
     583 [ +  + ][ +  + ]:         48 :     if (!(a[OVS_NAT_ATTR_SRC] || a[OVS_NAT_ATTR_DST])
     584 [ +  - ][ +  - ]:          7 :         && (a[OVS_NAT_ATTR_IP_MIN] || a[OVS_NAT_ATTR_IP_MAX]
     585 [ +  - ][ +  - ]:          7 :             || a[OVS_NAT_ATTR_PROTO_MIN] || a[OVS_NAT_ATTR_PROTO_MAX]
     586 [ +  - ][ +  - ]:          7 :             || a[OVS_NAT_ATTR_PERSISTENT] || a[OVS_NAT_ATTR_PROTO_HASH]
     587         [ -  + ]:          7 :             || a[OVS_NAT_ATTR_PROTO_RANDOM])) {
     588                 :          0 :         ds_put_cstr(ds, "nat(error: options allowed only with \"src\" or \"dst\")");
     589                 :          0 :         return;
     590                 :            :     }
     591                 :            :     /* Both SNAT & DNAT may not be specified. */
     592 [ +  + ][ -  + ]:         48 :     if (a[OVS_NAT_ATTR_SRC] && a[OVS_NAT_ATTR_DST]) {
     593                 :          0 :         ds_put_cstr(ds, "nat(error: Only one of \"src\" or \"dst\" may be present.)");
     594                 :          0 :         return;
     595                 :            :     }
     596                 :            :     /* proto may not appear without ip. */
     597 [ +  + ][ -  + ]:         48 :     if (!a[OVS_NAT_ATTR_IP_MIN] && a[OVS_NAT_ATTR_PROTO_MIN]) {
     598                 :          0 :         ds_put_cstr(ds, "nat(error: proto but no IP.)");
     599                 :          0 :         return;
     600                 :            :     }
     601                 :            :     /* MAX may not appear without MIN. */
     602 [ +  + ][ +  - ]:         48 :     if ((!a[OVS_NAT_ATTR_IP_MIN] && a[OVS_NAT_ATTR_IP_MAX])
     603 [ +  + ][ -  + ]:         48 :         || (!a[OVS_NAT_ATTR_PROTO_MIN] && a[OVS_NAT_ATTR_PROTO_MAX])) {
     604                 :          0 :         ds_put_cstr(ds, "nat(error: range max without min.)");
     605                 :          0 :         return;
     606                 :            :     }
     607                 :            :     /* Address sizes must match. */
     608         [ +  + ]:         48 :     if ((a[OVS_NAT_ATTR_IP_MIN]
     609   [ +  +  +  - ]:         42 :          && (nl_attr_get_size(a[OVS_NAT_ATTR_IP_MIN]) != sizeof(ovs_be32) &&
     610                 :          3 :              nl_attr_get_size(a[OVS_NAT_ATTR_IP_MIN]) != sizeof(struct in6_addr)))
     611 [ +  + ][ +  + ]:         48 :         || (a[OVS_NAT_ATTR_IP_MIN] && a[OVS_NAT_ATTR_IP_MAX]
     612         [ -  + ]:         10 :             && (nl_attr_get_size(a[OVS_NAT_ATTR_IP_MIN])
     613                 :          5 :                 != nl_attr_get_size(a[OVS_NAT_ATTR_IP_MAX])))) {
     614                 :          0 :         ds_put_cstr(ds, "nat(error: IP address sizes do not match)");
     615                 :          0 :         return;
     616                 :            :     }
     617                 :            : 
     618                 :         96 :     addr_len = a[OVS_NAT_ATTR_IP_MIN]
     619         [ +  + ]:         48 :         ? nl_attr_get_size(a[OVS_NAT_ATTR_IP_MIN]) : 0;
     620         [ +  - ]:         36 :     ip_min = addr_len == sizeof(ovs_be32) && a[OVS_NAT_ATTR_IP_MIN]
     621         [ +  + ]:         84 :         ? nl_attr_get_be32(a[OVS_NAT_ATTR_IP_MIN]) : 0;
     622         [ +  + ]:         36 :     ip_max = addr_len == sizeof(ovs_be32) && a[OVS_NAT_ATTR_IP_MAX]
     623         [ +  + ]:         84 :         ? nl_attr_get_be32(a[OVS_NAT_ATTR_IP_MAX]) : 0;
     624         [ +  + ]:         48 :     if (addr_len == sizeof ip6_min) {
     625         [ +  - ]:          6 :         ip6_min = a[OVS_NAT_ATTR_IP_MIN]
     626                 :          3 :             ? *(struct in6_addr *)nl_attr_get(a[OVS_NAT_ATTR_IP_MIN])
     627                 :            :             : in6addr_any;
     628         [ +  + ]:          5 :         ip6_max = a[OVS_NAT_ATTR_IP_MAX]
     629                 :          2 :             ? *(struct in6_addr *)nl_attr_get(a[OVS_NAT_ATTR_IP_MAX])
     630                 :            :             : in6addr_any;
     631                 :            :     }
     632         [ +  + ]:         48 :     proto_min = a[OVS_NAT_ATTR_PROTO_MIN]
     633                 :          3 :         ? nl_attr_get_u16(a[OVS_NAT_ATTR_PROTO_MIN]) : 0;
     634         [ +  + ]:         48 :     proto_max = a[OVS_NAT_ATTR_PROTO_MAX]
     635                 :          3 :         ? nl_attr_get_u16(a[OVS_NAT_ATTR_PROTO_MAX]) : 0;
     636                 :            : 
     637         [ +  + ]:         48 :     if ((addr_len == sizeof(ovs_be32)
     638 [ +  + ][ +  - ]:         36 :          && ip_max && ntohl(ip_min) > ntohl(ip_max))
     639         [ +  + ]:         48 :         || (addr_len == sizeof(struct in6_addr)
     640         [ +  + ]:          3 :             && !ipv6_mask_is_any(&ip6_max)
     641         [ +  - ]:          2 :             && memcmp(&ip6_min, &ip6_max, sizeof ip6_min) > 0)
     642 [ +  + ][ -  + ]:         48 :         || (proto_max && proto_min > proto_max)) {
     643                 :          0 :         ds_put_cstr(ds, "nat(range error)");
     644                 :          0 :         return;
     645                 :            :     }
     646                 :            : 
     647                 :         48 :     ds_put_cstr(ds, "nat");
     648 [ +  + ][ +  + ]:         48 :     if (a[OVS_NAT_ATTR_SRC] || a[OVS_NAT_ATTR_DST]) {
     649                 :         41 :         ds_put_char(ds, '(');
     650         [ +  + ]:         41 :         if (a[OVS_NAT_ATTR_SRC]) {
     651                 :          8 :             ds_put_cstr(ds, "src");
     652         [ +  - ]:         33 :         } else if (a[OVS_NAT_ATTR_DST]) {
     653                 :         33 :             ds_put_cstr(ds, "dst");
     654                 :            :         }
     655                 :            : 
     656         [ +  + ]:         41 :         if (addr_len > 0) {
     657                 :         39 :             ds_put_cstr(ds, "=");
     658                 :            : 
     659         [ +  + ]:         39 :             if (addr_len == sizeof ip_min) {
     660                 :         36 :                 ds_put_format(ds, IP_FMT, IP_ARGS(ip_min));
     661                 :            : 
     662 [ +  + ][ +  - ]:         36 :                 if (ip_max && ip_max != ip_min) {
     663                 :         36 :                     ds_put_format(ds, "-"IP_FMT, IP_ARGS(ip_max));
     664                 :            :                 }
     665         [ +  - ]:          3 :             } else if (addr_len == sizeof ip6_min) {
     666                 :          3 :                 ipv6_format_addr_bracket(&ip6_min, ds, proto_min);
     667                 :            : 
     668 [ +  + ][ +  - ]:          3 :                 if (!ipv6_mask_is_any(&ip6_max) &&
     669                 :          2 :                     memcmp(&ip6_max, &ip6_min, sizeof ip6_max) != 0) {
     670                 :          2 :                     ds_put_char(ds, '-');
     671                 :          2 :                     ipv6_format_addr_bracket(&ip6_max, ds, proto_min);
     672                 :            :                 }
     673                 :            :             }
     674         [ +  + ]:         39 :             if (proto_min) {
     675                 :          3 :                 ds_put_format(ds, ":%"PRIu16, proto_min);
     676                 :            : 
     677 [ +  - ][ +  - ]:          3 :                 if (proto_max && proto_max != proto_min) {
     678                 :          3 :                     ds_put_format(ds, "-%"PRIu16, proto_max);
     679                 :            :                 }
     680                 :            :             }
     681                 :            :         }
     682                 :         41 :         ds_put_char(ds, ',');
     683         [ +  + ]:         41 :         if (a[OVS_NAT_ATTR_PERSISTENT]) {
     684                 :          1 :             ds_put_cstr(ds, "persistent,");
     685                 :            :         }
     686         [ +  + ]:         41 :         if (a[OVS_NAT_ATTR_PROTO_HASH]) {
     687                 :          1 :             ds_put_cstr(ds, "hash,");
     688                 :            :         }
     689         [ +  + ]:         41 :         if (a[OVS_NAT_ATTR_PROTO_RANDOM]) {
     690                 :          5 :             ds_put_cstr(ds, "random,");
     691                 :            :         }
     692                 :         41 :         ds_chomp(ds, ',');
     693                 :         48 :         ds_put_char(ds, ')');
     694                 :            :     }
     695                 :            : }
     696                 :            : 
     697                 :            : static const struct nl_policy ovs_conntrack_policy[] = {
     698                 :            :     [OVS_CT_ATTR_COMMIT] = { .type = NL_A_FLAG, .optional = true, },
     699                 :            :     [OVS_CT_ATTR_ZONE] = { .type = NL_A_U16, .optional = true, },
     700                 :            :     [OVS_CT_ATTR_MARK] = { .type = NL_A_UNSPEC, .optional = true,
     701                 :            :                            .min_len = sizeof(uint32_t) * 2 },
     702                 :            :     [OVS_CT_ATTR_LABELS] = { .type = NL_A_UNSPEC, .optional = true,
     703                 :            :                              .min_len = sizeof(struct ovs_key_ct_labels) * 2 },
     704                 :            :     [OVS_CT_ATTR_HELPER] = { .type = NL_A_STRING, .optional = true,
     705                 :            :                              .min_len = 1, .max_len = 16 },
     706                 :            :     [OVS_CT_ATTR_NAT] = { .type = NL_A_UNSPEC, .optional = true },
     707                 :            : };
     708                 :            : 
     709                 :            : static void
     710                 :         78 : format_odp_conntrack_action(struct ds *ds, const struct nlattr *attr)
     711                 :            : {
     712                 :            :     struct nlattr *a[ARRAY_SIZE(ovs_conntrack_policy)];
     713                 :            :     const ovs_u128 *label;
     714                 :            :     const uint32_t *mark;
     715                 :            :     const char *helper;
     716                 :            :     uint16_t zone;
     717                 :            :     bool commit;
     718                 :            :     const struct nlattr *nat;
     719                 :            : 
     720         [ -  + ]:         78 :     if (!nl_parse_nested(attr, ovs_conntrack_policy, a, ARRAY_SIZE(a))) {
     721                 :          0 :         ds_put_cstr(ds, "ct(error)");
     722                 :          0 :         return;
     723                 :            :     }
     724                 :            : 
     725                 :         78 :     commit = a[OVS_CT_ATTR_COMMIT] ? true : false;
     726         [ +  + ]:         78 :     zone = a[OVS_CT_ATTR_ZONE] ? nl_attr_get_u16(a[OVS_CT_ATTR_ZONE]) : 0;
     727         [ +  + ]:         78 :     mark = a[OVS_CT_ATTR_MARK] ? nl_attr_get(a[OVS_CT_ATTR_MARK]) : NULL;
     728         [ +  + ]:         78 :     label = a[OVS_CT_ATTR_LABELS] ? nl_attr_get(a[OVS_CT_ATTR_LABELS]): NULL;
     729         [ +  + ]:         78 :     helper = a[OVS_CT_ATTR_HELPER] ? nl_attr_get(a[OVS_CT_ATTR_HELPER]) : NULL;
     730                 :         78 :     nat = a[OVS_CT_ATTR_NAT];
     731                 :            : 
     732                 :         78 :     ds_put_format(ds, "ct");
     733 [ +  + ][ +  + ]:         78 :     if (commit || zone || mark || label || helper || nat) {
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
     734                 :         63 :         ds_put_cstr(ds, "(");
     735         [ +  + ]:         63 :         if (commit) {
     736                 :         55 :             ds_put_format(ds, "commit,");
     737                 :            :         }
     738         [ +  + ]:         63 :         if (zone) {
     739                 :          2 :             ds_put_format(ds, "zone=%"PRIu16",", zone);
     740                 :            :         }
     741         [ +  + ]:         63 :         if (mark) {
     742                 :          1 :             ds_put_format(ds, "mark=%#"PRIx32"/%#"PRIx32",", *mark,
     743                 :          1 :                           *(mark + 1));
     744                 :            :         }
     745         [ +  + ]:         63 :         if (label) {
     746                 :          4 :             ds_put_format(ds, "label=");
     747                 :          4 :             format_u128(ds, label, label + 1, true);
     748                 :          4 :             ds_put_char(ds, ',');
     749                 :            :         }
     750         [ +  + ]:         63 :         if (helper) {
     751                 :          2 :             ds_put_format(ds, "helper=%s,", helper);
     752                 :            :         }
     753         [ +  + ]:         63 :         if (nat) {
     754                 :         48 :             format_odp_ct_nat(ds, nat);
     755                 :            :         }
     756                 :         63 :         ds_chomp(ds, ',');
     757                 :         78 :         ds_put_cstr(ds, ")");
     758                 :            :     }
     759                 :            : }
     760                 :            : 
     761                 :            : static void
     762                 :   15594900 : format_odp_action(struct ds *ds, const struct nlattr *a)
     763                 :            : {
     764                 :            :     int expected_len;
     765                 :   15594900 :     enum ovs_action_attr type = nl_attr_type(a);
     766                 :            :     size_t size;
     767                 :            : 
     768                 :   15594900 :     expected_len = odp_action_len(nl_attr_type(a));
     769   [ +  +  -  + ]:   31189437 :     if (expected_len != ATTR_LEN_VARIABLE &&
     770                 :   15594537 :         nl_attr_get_size(a) != expected_len) {
     771                 :          0 :         ds_put_format(ds, "bad length %"PRIuSIZE", expected %d for: ",
     772                 :            :                       nl_attr_get_size(a), expected_len);
     773                 :          0 :         format_generic_odp_action(ds, a);
     774                 :          0 :         return;
     775                 :            :     }
     776                 :            : 
     777   [ +  +  +  +  :   15594900 :     switch (type) {
          +  +  +  +  +  
          +  +  +  +  +  
                   +  - ]
     778                 :            :     case OVS_ACTION_ATTR_OUTPUT:
     779                 :   15593689 :         ds_put_format(ds, "%"PRIu32, nl_attr_get_u32(a));
     780                 :   15593689 :         break;
     781                 :            :     case OVS_ACTION_ATTR_TRUNC: {
     782                 :         32 :         const struct ovs_action_trunc *trunc =
     783                 :            :                        nl_attr_get_unspec(a, sizeof *trunc);
     784                 :            : 
     785                 :         32 :         ds_put_format(ds, "trunc(%"PRIu32")", trunc->max_len);
     786                 :         32 :         break;
     787                 :            :     }
     788                 :            :     break;
     789                 :            :     case OVS_ACTION_ATTR_TUNNEL_POP:
     790                 :          7 :         ds_put_format(ds, "tnl_pop(%"PRIu32")", nl_attr_get_u32(a));
     791                 :          7 :         break;
     792                 :            :     case OVS_ACTION_ATTR_TUNNEL_PUSH:
     793                 :         25 :         format_odp_tnl_push_action(ds, a);
     794                 :         25 :         break;
     795                 :            :     case OVS_ACTION_ATTR_USERSPACE:
     796                 :         63 :         format_odp_userspace_action(ds, a);
     797                 :         63 :         break;
     798                 :            :     case OVS_ACTION_ATTR_RECIRC:
     799                 :        319 :         format_odp_recirc_action(ds, nl_attr_get_u32(a));
     800                 :        319 :         break;
     801                 :            :     case OVS_ACTION_ATTR_HASH:
     802                 :        256 :         format_odp_hash_action(ds, nl_attr_get(a));
     803                 :        256 :         break;
     804                 :            :     case OVS_ACTION_ATTR_SET_MASKED:
     805                 :        104 :         a = nl_attr_get(a);
     806                 :        104 :         size = nl_attr_get_size(a) / 2;
     807                 :        104 :         ds_put_cstr(ds, "set(");
     808                 :            : 
     809                 :            :         /* Masked set action not supported for tunnel key, which is bigger. */
     810         [ +  - ]:        104 :         if (size <= sizeof(struct ovs_key_ipv6)) {
     811                 :            :             struct nlattr attr[1 + DIV_ROUND_UP(sizeof(struct ovs_key_ipv6),
     812                 :            :                                                 sizeof(struct nlattr))];
     813                 :            :             struct nlattr mask[1 + DIV_ROUND_UP(sizeof(struct ovs_key_ipv6),
     814                 :            :                                                 sizeof(struct nlattr))];
     815                 :            : 
     816                 :        104 :             mask->nla_type = attr->nla_type = nl_attr_type(a);
     817                 :        104 :             mask->nla_len = attr->nla_len = NLA_HDRLEN + size;
     818                 :        104 :             memcpy(attr + 1, (char *)(a + 1), size);
     819                 :        104 :             memcpy(mask + 1, (char *)(a + 1) + size, size);
     820                 :        104 :             format_odp_key_attr(attr, mask, NULL, ds, false);
     821                 :            :         } else {
     822                 :          0 :             format_odp_key_attr(a, NULL, NULL, ds, false);
     823                 :            :         }
     824                 :        104 :         ds_put_cstr(ds, ")");
     825                 :        104 :         break;
     826                 :            :     case OVS_ACTION_ATTR_SET:
     827                 :         83 :         ds_put_cstr(ds, "set(");
     828                 :         83 :         format_odp_key_attr(nl_attr_get(a), NULL, NULL, ds, true);
     829                 :         83 :         ds_put_cstr(ds, ")");
     830                 :         83 :         break;
     831                 :            :     case OVS_ACTION_ATTR_PUSH_VLAN: {
     832                 :        110 :         const struct ovs_action_push_vlan *vlan = nl_attr_get(a);
     833                 :        110 :         ds_put_cstr(ds, "push_vlan(");
     834         [ +  + ]:        110 :         if (vlan->vlan_tpid != htons(ETH_TYPE_VLAN)) {
     835                 :          2 :             ds_put_format(ds, "tpid=0x%04"PRIx16",", ntohs(vlan->vlan_tpid));
     836                 :            :         }
     837                 :        110 :         format_vlan_tci(ds, vlan->vlan_tci, OVS_BE16_MAX, false);
     838                 :        110 :         ds_put_char(ds, ')');
     839                 :        110 :         break;
     840                 :            :     }
     841                 :            :     case OVS_ACTION_ATTR_POP_VLAN:
     842                 :        109 :         ds_put_cstr(ds, "pop_vlan");
     843                 :        109 :         break;
     844                 :            :     case OVS_ACTION_ATTR_PUSH_MPLS: {
     845                 :          6 :         const struct ovs_action_push_mpls *mpls = nl_attr_get(a);
     846                 :          6 :         ds_put_cstr(ds, "push_mpls(");
     847                 :          6 :         format_mpls_lse(ds, mpls->mpls_lse);
     848                 :          6 :         ds_put_format(ds, ",eth_type=0x%"PRIx16")", ntohs(mpls->mpls_ethertype));
     849                 :          6 :         break;
     850                 :            :     }
     851                 :            :     case OVS_ACTION_ATTR_POP_MPLS: {
     852                 :          9 :         ovs_be16 ethertype = nl_attr_get_be16(a);
     853                 :          9 :         ds_put_format(ds, "pop_mpls(eth_type=0x%"PRIx16")", ntohs(ethertype));
     854                 :          9 :         break;
     855                 :            :     }
     856                 :            :     case OVS_ACTION_ATTR_SAMPLE:
     857                 :         10 :         format_odp_sample_action(ds, a);
     858                 :         10 :         break;
     859                 :            :     case OVS_ACTION_ATTR_CT:
     860                 :         78 :         format_odp_conntrack_action(ds, a);
     861                 :         78 :         break;
     862                 :            :     case OVS_ACTION_ATTR_UNSPEC:
     863                 :            :     case __OVS_ACTION_ATTR_MAX:
     864                 :            :     default:
     865                 :          0 :         format_generic_odp_action(ds, a);
     866                 :          0 :         break;
     867                 :            :     }
     868                 :            : }
     869                 :            : 
     870                 :            : void
     871                 :       9127 : format_odp_actions(struct ds *ds, const struct nlattr *actions,
     872                 :            :                    size_t actions_len)
     873                 :            : {
     874         [ +  + ]:       9127 :     if (actions_len) {
     875                 :            :         const struct nlattr *a;
     876                 :            :         unsigned int left;
     877                 :            : 
     878         [ +  + ]:   15603360 :         NL_ATTR_FOR_EACH (a, left, actions, actions_len) {
     879         [ +  + ]:   15594900 :             if (a != actions) {
     880                 :   15586440 :                 ds_put_char(ds, ',');
     881                 :            :             }
     882                 :   15594900 :             format_odp_action(ds, a);
     883                 :            :         }
     884         [ -  + ]:       8460 :         if (left) {
     885                 :            :             int i;
     886                 :            : 
     887         [ #  # ]:          0 :             if (left == actions_len) {
     888                 :          0 :                 ds_put_cstr(ds, "<empty>");
     889                 :            :             }
     890                 :          0 :             ds_put_format(ds, ",***%u leftover bytes*** (", left);
     891         [ #  # ]:          0 :             for (i = 0; i < left; i++) {
     892                 :          0 :                 ds_put_format(ds, "%02x", ((const uint8_t *) a)[i]);
     893                 :            :             }
     894                 :       8460 :             ds_put_char(ds, ')');
     895                 :            :         }
     896                 :            :     } else {
     897                 :        667 :         ds_put_cstr(ds, "drop");
     898                 :            :     }
     899                 :       9127 : }
     900                 :            : 
     901                 :            : /* Separate out parse_odp_userspace_action() function. */
     902                 :            : static int
     903                 :         14 : parse_odp_userspace_action(const char *s, struct ofpbuf *actions)
     904                 :            : {
     905                 :            :     uint32_t pid;
     906                 :            :     union user_action_cookie cookie;
     907                 :            :     struct ofpbuf buf;
     908                 :            :     odp_port_t tunnel_out_port;
     909                 :         14 :     int n = -1;
     910                 :         14 :     void *user_data = NULL;
     911                 :         14 :     size_t user_data_size = 0;
     912                 :         14 :     bool include_actions = false;
     913                 :            :     int res;
     914                 :            : 
     915         [ -  + ]:         14 :     if (!ovs_scan(s, "userspace(pid=%"SCNi32"%n", &pid, &n)) {
     916                 :          0 :         return -EINVAL;
     917                 :            :     }
     918                 :            : 
     919                 :         14 :     ofpbuf_init(&buf, 16);
     920                 :            : 
     921                 :            :     {
     922                 :            :         uint32_t output;
     923                 :            :         uint32_t probability;
     924                 :            :         uint32_t collector_set_id;
     925                 :            :         uint32_t obs_domain_id;
     926                 :            :         uint32_t obs_point_id;
     927                 :            :         int vid, pcp;
     928                 :         14 :         int n1 = -1;
     929         [ +  + ]:         14 :         if (ovs_scan(&s[n], ",sFlow(vid=%i,"
     930                 :            :                      "pcp=%i,output=%"SCNi32")%n",
     931                 :            :                      &vid, &pcp, &output, &n1)) {
     932                 :            :             uint16_t tci;
     933                 :            : 
     934                 :          2 :             n += n1;
     935                 :          2 :             tci = vid | (pcp << VLAN_PCP_SHIFT);
     936         [ +  - ]:          2 :             if (tci) {
     937                 :          2 :                 tci |= VLAN_CFI;
     938                 :            :             }
     939                 :            : 
     940                 :          2 :             cookie.type = USER_ACTION_COOKIE_SFLOW;
     941                 :          2 :             cookie.sflow.vlan_tci = htons(tci);
     942                 :          2 :             cookie.sflow.output = output;
     943                 :          2 :             user_data = &cookie;
     944                 :          2 :             user_data_size = sizeof cookie.sflow;
     945         [ +  + ]:         12 :         } else if (ovs_scan(&s[n], ",slow_path(%n",
     946                 :            :                             &n1)) {
     947                 :          4 :             n += n1;
     948                 :          4 :             cookie.type = USER_ACTION_COOKIE_SLOW_PATH;
     949                 :          4 :             cookie.slow_path.unused = 0;
     950                 :          4 :             cookie.slow_path.reason = 0;
     951                 :            : 
     952                 :          4 :             res = parse_odp_flags(&s[n], slow_path_reason_to_string,
     953                 :            :                                   &cookie.slow_path.reason,
     954                 :            :                                   SLOW_PATH_REASON_MASK, NULL);
     955 [ +  - ][ +  - ]:          4 :             if (res < 0 || s[n + res] != ')') {
     956                 :            :                 goto out;
     957                 :            :             }
     958                 :          4 :             n += res + 1;
     959                 :            : 
     960                 :          4 :             user_data = &cookie;
     961                 :          4 :             user_data_size = sizeof cookie.slow_path;
     962         [ +  + ]:          8 :         } else if (ovs_scan(&s[n], ",flow_sample(probability=%"SCNi32","
     963                 :            :                             "collector_set_id=%"SCNi32","
     964                 :            :                             "obs_domain_id=%"SCNi32","
     965                 :            :                             "obs_point_id=%"SCNi32","
     966                 :            :                             "output_port=%"SCNi32")%n",
     967                 :            :                             &probability, &collector_set_id,
     968                 :            :                             &obs_domain_id, &obs_point_id,
     969                 :            :                             &output, &n1)) {
     970                 :          2 :             n += n1;
     971                 :            : 
     972                 :          2 :             cookie.type = USER_ACTION_COOKIE_FLOW_SAMPLE;
     973                 :          2 :             cookie.flow_sample.probability = probability;
     974                 :          2 :             cookie.flow_sample.collector_set_id = collector_set_id;
     975                 :          2 :             cookie.flow_sample.obs_domain_id = obs_domain_id;
     976                 :          2 :             cookie.flow_sample.obs_point_id = obs_point_id;
     977                 :          2 :             cookie.flow_sample.output_odp_port = u32_to_odp(output);
     978                 :          2 :             user_data = &cookie;
     979                 :          2 :             user_data_size = sizeof cookie.flow_sample;
     980         [ +  + ]:          6 :         } else if (ovs_scan(&s[n], ",ipfix(output_port=%"SCNi32")%n",
     981                 :            :                             &output, &n1) ) {
     982                 :          2 :             n += n1;
     983                 :          2 :             cookie.type = USER_ACTION_COOKIE_IPFIX;
     984                 :          2 :             cookie.ipfix.output_odp_port = u32_to_odp(output);
     985                 :          2 :             user_data = &cookie;
     986                 :          2 :             user_data_size = sizeof cookie.ipfix;
     987         [ +  + ]:          4 :         } else if (ovs_scan(&s[n], ",userdata(%n",
     988                 :            :                             &n1)) {
     989                 :            :             char *end;
     990                 :            : 
     991                 :          2 :             n += n1;
     992                 :          2 :             end = ofpbuf_put_hex(&buf, &s[n], NULL);
     993         [ -  + ]:          2 :             if (end[0] != ')') {
     994                 :          0 :                 res = -EINVAL;
     995                 :          0 :                 goto out;
     996                 :            :             }
     997                 :          2 :             user_data = buf.data;
     998                 :          2 :             user_data_size = buf.size;
     999                 :          2 :             n = (end + 1) - s;
    1000                 :            :         }
    1001                 :            :     }
    1002                 :            : 
    1003                 :            :     {
    1004                 :         14 :         int n1 = -1;
    1005         [ +  + ]:         14 :         if (ovs_scan(&s[n], ",actions%n", &n1)) {
    1006                 :          3 :             n += n1;
    1007                 :          3 :             include_actions = true;
    1008                 :            :         }
    1009                 :            :     }
    1010                 :            : 
    1011                 :            :     {
    1012                 :         14 :         int n1 = -1;
    1013         [ +  + ]:         14 :         if (ovs_scan(&s[n], ",tunnel_out_port=%"SCNi32")%n",
    1014                 :            :                      &tunnel_out_port, &n1)) {
    1015                 :          7 :             odp_put_userspace_action(pid, user_data, user_data_size,
    1016                 :            :                                      tunnel_out_port, include_actions, actions);
    1017                 :          7 :             res = n + n1;
    1018         [ +  - ]:          7 :         } else if (s[n] == ')') {
    1019                 :          7 :             odp_put_userspace_action(pid, user_data, user_data_size,
    1020                 :            :                                      ODPP_NONE, include_actions, actions);
    1021                 :          7 :             res = n + 1;
    1022                 :            :         } else {
    1023                 :         14 :             res = -EINVAL;
    1024                 :            :         }
    1025                 :            :     }
    1026                 :            : out:
    1027                 :         14 :     ofpbuf_uninit(&buf);
    1028                 :         14 :     return res;
    1029                 :            : }
    1030                 :            : 
    1031                 :            : static int
    1032                 :         12 : ovs_parse_tnl_push(const char *s, struct ovs_action_push_tnl *data)
    1033                 :            : {
    1034                 :            :     struct eth_header *eth;
    1035                 :            :     struct ip_header *ip;
    1036                 :            :     struct ovs_16aligned_ip6_hdr *ip6;
    1037                 :            :     struct udp_header *udp;
    1038                 :            :     struct gre_base_hdr *greh;
    1039                 :            :     uint16_t gre_proto, gre_flags, dl_type, udp_src, udp_dst, csum;
    1040                 :            :     ovs_be32 sip, dip;
    1041                 :         12 :     uint32_t tnl_type = 0, header_len = 0, ip_len = 0;
    1042                 :            :     void *l3, *l4;
    1043                 :         12 :     int n = 0;
    1044                 :            : 
    1045         [ -  + ]:         12 :     if (!ovs_scan_len(s, &n, "tnl_push(tnl_port(%"SCNi32"),", &data->tnl_port)) {
    1046                 :          0 :         return -EINVAL;
    1047                 :            :     }
    1048                 :         12 :     eth = (struct eth_header *) data->header;
    1049                 :         12 :     l3 = (data->header + sizeof *eth);
    1050                 :         12 :     ip = (struct ip_header *) l3;
    1051                 :         12 :     ip6 = (struct ovs_16aligned_ip6_hdr *) l3;
    1052         [ -  + ]:         12 :     if (!ovs_scan_len(s, &n, "header(size=%"SCNi32",type=%"SCNi32","
    1053                 :            :                       "eth(dst="ETH_ADDR_SCAN_FMT",",
    1054                 :            :                       &data->header_len,
    1055                 :            :                       &data->tnl_type,
    1056                 :            :                       ETH_ADDR_SCAN_ARGS(eth->eth_dst))) {
    1057                 :          0 :         return -EINVAL;
    1058                 :            :     }
    1059                 :            : 
    1060         [ -  + ]:         12 :     if (!ovs_scan_len(s, &n, "src="ETH_ADDR_SCAN_FMT",",
    1061                 :            :                       ETH_ADDR_SCAN_ARGS(eth->eth_src))) {
    1062                 :          0 :         return -EINVAL;
    1063                 :            :     }
    1064         [ -  + ]:         12 :     if (!ovs_scan_len(s, &n, "dl_type=0x%"SCNx16"),", &dl_type)) {
    1065                 :          0 :         return -EINVAL;
    1066                 :            :     }
    1067                 :         12 :     eth->eth_type = htons(dl_type);
    1068                 :            : 
    1069         [ +  + ]:         12 :     if (eth->eth_type == htons(ETH_TYPE_IP)) {
    1070                 :            :         /* IPv4 */
    1071                 :            :         uint16_t ip_frag_off;
    1072         [ -  + ]:          6 :         if (!ovs_scan_len(s, &n, "ipv4(src="IP_SCAN_FMT",dst="IP_SCAN_FMT",proto=%"SCNi8
    1073                 :            :                           ",tos=%"SCNi8",ttl=%"SCNi8",frag=0x%"SCNx16"),",
    1074                 :            :                           IP_SCAN_ARGS(&sip),
    1075                 :            :                           IP_SCAN_ARGS(&dip),
    1076                 :            :                           &ip->ip_proto, &ip->ip_tos,
    1077                 :            :                           &ip->ip_ttl, &ip_frag_off)) {
    1078                 :          0 :             return -EINVAL;
    1079                 :            :         }
    1080                 :          6 :         put_16aligned_be32(&ip->ip_src, sip);
    1081                 :          6 :         put_16aligned_be32(&ip->ip_dst, dip);
    1082                 :          6 :         ip->ip_frag_off = htons(ip_frag_off);
    1083                 :          6 :         ip_len = sizeof *ip;
    1084                 :            :     } else {
    1085                 :            :         char sip6_s[IPV6_SCAN_LEN + 1];
    1086                 :            :         char dip6_s[IPV6_SCAN_LEN + 1];
    1087                 :            :         struct in6_addr sip6, dip6;
    1088                 :            :         uint8_t tclass;
    1089                 :            :         uint32_t label;
    1090         [ +  - ]:          6 :         if (!ovs_scan_len(s, &n, "ipv6(src="IPV6_SCAN_FMT",dst="IPV6_SCAN_FMT
    1091                 :            :                              ",label=%i,proto=%"SCNi8",tclass=0x%"SCNx8
    1092                 :            :                              ",hlimit=%"SCNi8"),",
    1093                 :            :                              sip6_s, dip6_s, &label, &ip6->ip6_nxt,
    1094                 :            :                              &tclass, &ip6->ip6_hlim)
    1095         [ +  - ]:          6 :             || (label & ~IPV6_LABEL_MASK) != 0
    1096         [ +  - ]:          6 :             || inet_pton(AF_INET6, sip6_s, &sip6) != 1
    1097         [ -  + ]:          6 :             || inet_pton(AF_INET6, dip6_s, &dip6) != 1) {
    1098                 :          0 :             return -EINVAL;
    1099                 :            :         }
    1100                 :         12 :         put_16aligned_be32(&ip6->ip6_flow, htonl(6 << 28) |
    1101                 :          6 :                            htonl(tclass << 20) | htonl(label));
    1102                 :          6 :         memcpy(&ip6->ip6_src, &sip6, sizeof(ip6->ip6_src));
    1103                 :          6 :         memcpy(&ip6->ip6_dst, &dip6, sizeof(ip6->ip6_dst));
    1104                 :          6 :         ip_len = sizeof *ip6;
    1105                 :            :     }
    1106                 :            : 
    1107                 :            :     /* Tunnel header */
    1108                 :         12 :     l4 = ((uint8_t *) l3 + ip_len);
    1109                 :         12 :     udp = (struct udp_header *) l4;
    1110                 :         12 :     greh = (struct gre_base_hdr *) l4;
    1111         [ +  + ]:         12 :     if (ovs_scan_len(s, &n, "udp(src=%"SCNi16",dst=%"SCNi16",csum=0x%"SCNx16"),",
    1112                 :            :                      &udp_src, &udp_dst, &csum)) {
    1113                 :            :         uint32_t vx_flags, vni;
    1114                 :            : 
    1115                 :          8 :         udp->udp_src = htons(udp_src);
    1116                 :          8 :         udp->udp_dst = htons(udp_dst);
    1117                 :          8 :         udp->udp_len = 0;
    1118                 :          8 :         udp->udp_csum = htons(csum);
    1119                 :            : 
    1120         [ +  + ]:          8 :         if (ovs_scan_len(s, &n, "vxlan(flags=0x%"SCNx32",vni=0x%"SCNx32"))",
    1121                 :            :                          &vx_flags, &vni)) {
    1122                 :          2 :             struct vxlanhdr *vxh = (struct vxlanhdr *) (udp + 1);
    1123                 :            : 
    1124                 :          2 :             put_16aligned_be32(&vxh->vx_flags, htonl(vx_flags));
    1125                 :          2 :             put_16aligned_be32(&vxh->vx_vni, htonl(vni << 8));
    1126                 :          2 :             tnl_type = OVS_VPORT_TYPE_VXLAN;
    1127                 :          2 :             header_len = sizeof *eth + ip_len +
    1128                 :            :                          sizeof *udp + sizeof *vxh;
    1129         [ +  - ]:          6 :         } else if (ovs_scan_len(s, &n, "geneve(")) {
    1130                 :          6 :             struct genevehdr *gnh = (struct genevehdr *) (udp + 1);
    1131                 :            : 
    1132                 :          6 :             memset(gnh, 0, sizeof *gnh);
    1133                 :          6 :             header_len = sizeof *eth + ip_len +
    1134                 :            :                          sizeof *udp + sizeof *gnh;
    1135                 :            : 
    1136         [ +  + ]:          6 :             if (ovs_scan_len(s, &n, "oam,")) {
    1137                 :          2 :                 gnh->oam = 1;
    1138                 :            :             }
    1139         [ +  + ]:          6 :             if (ovs_scan_len(s, &n, "crit,")) {
    1140                 :          2 :                 gnh->critical = 1;
    1141                 :            :             }
    1142         [ -  + ]:          6 :             if (!ovs_scan_len(s, &n, "vni=%"SCNi32, &vni)) {
    1143                 :          0 :                 return -EINVAL;
    1144                 :            :             }
    1145         [ +  + ]:          6 :             if (ovs_scan_len(s, &n, ",options(")) {
    1146                 :            :                 struct geneve_scan options;
    1147                 :            :                 int len;
    1148                 :            : 
    1149                 :          2 :                 memset(&options, 0, sizeof options);
    1150                 :          2 :                 len = scan_geneve(s + n, &options, NULL);
    1151         [ -  + ]:          2 :                 if (!len) {
    1152                 :          0 :                     return -EINVAL;
    1153                 :            :                 }
    1154                 :            : 
    1155                 :          2 :                 memcpy(gnh->options, options.d, options.len);
    1156                 :          2 :                 gnh->opt_len = options.len / 4;
    1157                 :          2 :                 header_len += options.len;
    1158                 :            : 
    1159                 :          2 :                 n += len;
    1160                 :            :             }
    1161         [ -  + ]:          6 :             if (!ovs_scan_len(s, &n, "))")) {
    1162                 :          0 :                 return -EINVAL;
    1163                 :            :             }
    1164                 :            : 
    1165                 :          6 :             gnh->proto_type = htons(ETH_TYPE_TEB);
    1166                 :          6 :             put_16aligned_be32(&gnh->vni, htonl(vni << 8));
    1167                 :          6 :             tnl_type = OVS_VPORT_TYPE_GENEVE;
    1168                 :            :         } else {
    1169                 :          8 :             return -EINVAL;
    1170                 :            :         }
    1171         [ +  - ]:          4 :     } else if (ovs_scan_len(s, &n, "gre((flags=0x%"SCNx16",proto=0x%"SCNx16")",
    1172                 :            :                             &gre_flags, &gre_proto)){
    1173                 :            : 
    1174                 :          4 :         tnl_type = OVS_VPORT_TYPE_GRE;
    1175                 :          4 :         greh->flags = htons(gre_flags);
    1176                 :          4 :         greh->protocol = htons(gre_proto);
    1177                 :          4 :         ovs_16aligned_be32 *options = (ovs_16aligned_be32 *) (greh + 1);
    1178                 :            : 
    1179         [ +  + ]:          4 :         if (greh->flags & htons(GRE_CSUM)) {
    1180         [ -  + ]:          2 :             if (!ovs_scan_len(s, &n, ",csum=0x%"SCNx16, &csum)) {
    1181                 :          0 :                 return -EINVAL;
    1182                 :            :             }
    1183                 :            : 
    1184                 :          2 :             memset(options, 0, sizeof *options);
    1185                 :          2 :             *((ovs_be16 *)options) = htons(csum);
    1186                 :          2 :             options++;
    1187                 :            :         }
    1188         [ +  - ]:          4 :         if (greh->flags & htons(GRE_KEY)) {
    1189                 :            :             uint32_t key;
    1190                 :            : 
    1191         [ -  + ]:          4 :             if (!ovs_scan_len(s, &n, ",key=0x%"SCNx32, &key)) {
    1192                 :          0 :                 return -EINVAL;
    1193                 :            :             }
    1194                 :            : 
    1195                 :          4 :             put_16aligned_be32(options, htonl(key));
    1196                 :          4 :             options++;
    1197                 :            :         }
    1198         [ -  + ]:          4 :         if (greh->flags & htons(GRE_SEQ)) {
    1199                 :            :             uint32_t seq;
    1200                 :            : 
    1201         [ #  # ]:          0 :             if (!ovs_scan_len(s, &n, ",seq=0x%"SCNx32, &seq)) {
    1202                 :          0 :                 return -EINVAL;
    1203                 :            :             }
    1204                 :          0 :             put_16aligned_be32(options, htonl(seq));
    1205                 :          0 :             options++;
    1206                 :            :         }
    1207                 :            : 
    1208         [ -  + ]:          4 :         if (!ovs_scan_len(s, &n, "))")) {
    1209                 :          0 :             return -EINVAL;
    1210                 :            :         }
    1211                 :            : 
    1212                 :          4 :         header_len = sizeof *eth + ip_len +
    1213                 :          4 :                      ((uint8_t *) options - (uint8_t *) greh);
    1214                 :            :     } else {
    1215                 :          0 :         return -EINVAL;
    1216                 :            :     }
    1217                 :            : 
    1218                 :            :     /* check tunnel meta data. */
    1219         [ -  + ]:         12 :     if (data->tnl_type != tnl_type) {
    1220                 :          0 :         return -EINVAL;
    1221                 :            :     }
    1222         [ -  + ]:         12 :     if (data->header_len != header_len) {
    1223                 :          0 :         return -EINVAL;
    1224                 :            :     }
    1225                 :            : 
    1226                 :            :     /* Out port */
    1227         [ -  + ]:         12 :     if (!ovs_scan_len(s, &n, ",out_port(%"SCNi32"))", &data->out_port)) {
    1228                 :          0 :         return -EINVAL;
    1229                 :            :     }
    1230                 :            : 
    1231                 :         12 :     return n;
    1232                 :            : }
    1233                 :            : 
    1234                 :            : struct ct_nat_params {
    1235                 :            :     bool snat;
    1236                 :            :     bool dnat;
    1237                 :            :     size_t addr_len;
    1238                 :            :     union {
    1239                 :            :         ovs_be32 ip;
    1240                 :            :         struct in6_addr ip6;
    1241                 :            :     } addr_min;
    1242                 :            :     union {
    1243                 :            :         ovs_be32 ip;
    1244                 :            :         struct in6_addr ip6;
    1245                 :            :     } addr_max;
    1246                 :            :     uint16_t proto_min;
    1247                 :            :     uint16_t proto_max;
    1248                 :            :     bool persistent;
    1249                 :            :     bool proto_hash;
    1250                 :            :     bool proto_random;
    1251                 :            : };
    1252                 :            : 
    1253                 :            : static int
    1254                 :         10 : scan_ct_nat_range(const char *s, int *n, struct ct_nat_params *p)
    1255                 :            : {
    1256         [ +  + ]:         10 :     if (ovs_scan_len(s, n, "=")) {
    1257                 :            :         char ipv6_s[IPV6_SCAN_LEN + 1];
    1258                 :            :         struct in6_addr ipv6;
    1259                 :            : 
    1260         [ +  + ]:          8 :         if (ovs_scan_len(s, n, IP_SCAN_FMT, IP_SCAN_ARGS(&p->addr_min.ip))) {
    1261                 :          5 :             p->addr_len = sizeof p->addr_min.ip;
    1262         [ +  + ]:          5 :             if (ovs_scan_len(s, n, "-")) {
    1263         [ -  + ]:          3 :                 if (!ovs_scan_len(s, n, IP_SCAN_FMT,
    1264                 :         12 :                                   IP_SCAN_ARGS(&p->addr_max.ip))) {
    1265                 :          0 :                     return -EINVAL;
    1266                 :            :                 }
    1267                 :            :             }
    1268         [ +  + ]:          3 :         } else if ((ovs_scan_len(s, n, IPV6_SCAN_FMT, ipv6_s)
    1269         [ +  - ]:          1 :                     || ovs_scan_len(s, n, "["IPV6_SCAN_FMT"]", ipv6_s))
    1270         [ +  - ]:          3 :                    && inet_pton(AF_INET6, ipv6_s, &ipv6) == 1) {
    1271                 :          3 :             p->addr_len = sizeof p->addr_min.ip6;
    1272                 :          3 :             p->addr_min.ip6 = ipv6;
    1273         [ +  + ]:          5 :             if (ovs_scan_len(s, n, "-")) {
    1274         [ +  + ]:          2 :                 if ((ovs_scan_len(s, n, IPV6_SCAN_FMT, ipv6_s)
    1275         [ +  - ]:          1 :                      || ovs_scan_len(s, n, "["IPV6_SCAN_FMT"]", ipv6_s))
    1276         [ +  - ]:          2 :                     && inet_pton(AF_INET6, ipv6_s, &ipv6) == 1) {
    1277                 :          2 :                     p->addr_max.ip6 = ipv6;
    1278                 :            :                 } else {
    1279                 :          0 :                     return -EINVAL;
    1280                 :            :                 }
    1281                 :            :             }
    1282                 :            :         } else {
    1283                 :          0 :             return -EINVAL;
    1284                 :            :         }
    1285         [ +  + ]:          8 :         if (ovs_scan_len(s, n, ":%"SCNu16, &p->proto_min)) {
    1286         [ +  - ]:          3 :             if (ovs_scan_len(s, n, "-")) {
    1287         [ -  + ]:          3 :                 if (!ovs_scan_len(s, n, "%"SCNu16, &p->proto_max)) {
    1288                 :          8 :                     return -EINVAL;
    1289                 :            :                 }
    1290                 :            :             }
    1291                 :            :         }
    1292                 :            :     }
    1293                 :         10 :     return 0;
    1294                 :            : }
    1295                 :            : 
    1296                 :            : static int
    1297                 :         11 : scan_ct_nat(const char *s, struct ct_nat_params *p)
    1298                 :            : {
    1299                 :         11 :     int n = 0;
    1300                 :            : 
    1301         [ +  - ]:         11 :     if (ovs_scan_len(s, &n, "nat")) {
    1302                 :         11 :         memset(p, 0, sizeof *p);
    1303                 :            : 
    1304         [ +  + ]:         11 :         if (ovs_scan_len(s, &n, "(")) {
    1305                 :            :             char *end;
    1306                 :            :             int end_n;
    1307                 :            : 
    1308                 :         10 :             end = strchr(s + n, ')');
    1309         [ -  + ]:         10 :             if (!end) {
    1310                 :          0 :                 return -EINVAL;
    1311                 :            :             }
    1312                 :         10 :             end_n = end - s;
    1313                 :            : 
    1314         [ +  + ]:         27 :             while (n < end_n) {
    1315                 :         17 :                 n += strspn(s + n, delimiters);
    1316         [ +  + ]:         17 :                 if (ovs_scan_len(s, &n, "src")) {
    1317                 :          8 :                     int err = scan_ct_nat_range(s, &n, p);
    1318         [ -  + ]:          8 :                     if (err) {
    1319                 :          0 :                         return err;
    1320                 :            :                     }
    1321                 :          8 :                     p->snat = true;
    1322                 :          8 :                     continue;
    1323                 :            :                 }
    1324         [ +  + ]:          9 :                 if (ovs_scan_len(s, &n, "dst")) {
    1325                 :          2 :                     int err = scan_ct_nat_range(s, &n, p);
    1326         [ -  + ]:          2 :                     if (err) {
    1327                 :          0 :                         return err;
    1328                 :            :                     }
    1329                 :          2 :                     p->dnat = true;
    1330                 :          2 :                     continue;
    1331                 :            :                 }
    1332         [ +  + ]:          7 :                 if (ovs_scan_len(s, &n, "persistent")) {
    1333                 :          1 :                     p->persistent = true;
    1334                 :          1 :                     continue;
    1335                 :            :                 }
    1336         [ +  + ]:          6 :                 if (ovs_scan_len(s, &n, "hash")) {
    1337                 :          1 :                     p->proto_hash = true;
    1338                 :          1 :                     continue;
    1339                 :            :                 }
    1340         [ +  - ]:          5 :                 if (ovs_scan_len(s, &n, "random")) {
    1341                 :          5 :                     p->proto_random = true;
    1342                 :          5 :                     continue;
    1343                 :            :                 }
    1344                 :          0 :                 return -EINVAL;
    1345                 :            :             }
    1346                 :            : 
    1347 [ +  + ][ -  + ]:         10 :             if (p->snat && p->dnat) {
    1348                 :          0 :                 return -EINVAL;
    1349                 :            :             }
    1350 [ +  + ][ +  + ]:         10 :             if ((p->addr_len != 0 &&
    1351         [ +  - ]:          5 :                  memcmp(&p->addr_max, &in6addr_any, p->addr_len) &&
    1352         [ +  + ]:         10 :                  memcmp(&p->addr_max, &p->addr_min, p->addr_len) < 0) ||
    1353         [ -  + ]:          3 :                 (p->proto_max && p->proto_max < p->proto_min)) {
    1354                 :          0 :                 return -EINVAL;
    1355                 :            :             }
    1356 [ +  + ][ -  + ]:         10 :             if (p->proto_hash && p->proto_random) {
    1357                 :          0 :                 return -EINVAL;
    1358                 :            :             }
    1359                 :         10 :             n++;
    1360                 :            :         }
    1361                 :            :     }
    1362                 :         11 :     return n;
    1363                 :            : }
    1364                 :            : 
    1365                 :            : static void
    1366                 :         11 : nl_msg_put_ct_nat(struct ct_nat_params *p, struct ofpbuf *actions)
    1367                 :            : {
    1368                 :         11 :     size_t start = nl_msg_start_nested(actions, OVS_CT_ATTR_NAT);
    1369                 :            : 
    1370         [ +  + ]:         11 :     if (p->snat) {
    1371                 :          8 :         nl_msg_put_flag(actions, OVS_NAT_ATTR_SRC);
    1372         [ +  + ]:          3 :     } else if (p->dnat) {
    1373                 :          2 :         nl_msg_put_flag(actions, OVS_NAT_ATTR_DST);
    1374                 :            :     } else {
    1375                 :          1 :         goto out;
    1376                 :            :     }
    1377         [ +  + ]:         10 :     if (p->addr_len != 0) {
    1378                 :          8 :         nl_msg_put_unspec(actions, OVS_NAT_ATTR_IP_MIN, &p->addr_min,
    1379                 :            :                           p->addr_len);
    1380         [ +  + ]:          8 :         if (memcmp(&p->addr_max, &p->addr_min, p->addr_len) > 0) {
    1381                 :          5 :             nl_msg_put_unspec(actions, OVS_NAT_ATTR_IP_MAX, &p->addr_max,
    1382                 :            :                               p->addr_len);
    1383                 :            :         }
    1384         [ +  + ]:          8 :         if (p->proto_min) {
    1385                 :          3 :             nl_msg_put_u16(actions, OVS_NAT_ATTR_PROTO_MIN, p->proto_min);
    1386 [ +  - ][ +  - ]:          3 :             if (p->proto_max && p->proto_max > p->proto_min) {
    1387                 :          3 :                 nl_msg_put_u16(actions, OVS_NAT_ATTR_PROTO_MAX, p->proto_max);
    1388                 :            :             }
    1389                 :            :         }
    1390         [ +  + ]:          8 :         if (p->persistent) {
    1391                 :          1 :             nl_msg_put_flag(actions, OVS_NAT_ATTR_PERSISTENT);
    1392                 :            :         }
    1393         [ +  + ]:          8 :         if (p->proto_hash) {
    1394                 :          1 :             nl_msg_put_flag(actions, OVS_NAT_ATTR_PROTO_HASH);
    1395                 :            :         }
    1396         [ +  + ]:          8 :         if (p->proto_random) {
    1397                 :          5 :             nl_msg_put_flag(actions, OVS_NAT_ATTR_PROTO_RANDOM);
    1398                 :            :         }
    1399                 :            :     }
    1400                 :            : out:
    1401                 :         11 :     nl_msg_end_nested(actions, start);
    1402                 :         11 : }
    1403                 :            : 
    1404                 :            : static int
    1405                 :         29 : parse_conntrack_action(const char *s_, struct ofpbuf *actions)
    1406                 :            : {
    1407                 :         29 :     const char *s = s_;
    1408                 :            : 
    1409         [ +  + ]:         29 :     if (ovs_scan(s, "ct")) {
    1410                 :         17 :         const char *helper = NULL;
    1411                 :         17 :         size_t helper_len = 0;
    1412                 :         17 :         bool commit = false;
    1413                 :         17 :         uint16_t zone = 0;
    1414                 :            :         struct {
    1415                 :            :             uint32_t value;
    1416                 :            :             uint32_t mask;
    1417                 :         17 :         } ct_mark = { 0, 0 };
    1418                 :            :         struct {
    1419                 :            :             ovs_u128 value;
    1420                 :            :             ovs_u128 mask;
    1421                 :            :         } ct_label;
    1422                 :            :         struct ct_nat_params nat_params;
    1423                 :         17 :         bool have_nat = false;
    1424                 :            :         size_t start;
    1425                 :            :         char *end;
    1426                 :            : 
    1427                 :         17 :         memset(&ct_label, 0, sizeof(ct_label));
    1428                 :            : 
    1429                 :         17 :         s += 2;
    1430         [ +  + ]:         17 :         if (ovs_scan(s, "(")) {
    1431                 :         16 :             s++;
    1432                 :            : find_end:
    1433                 :         27 :             end = strchr(s, ')');
    1434         [ -  + ]:         27 :             if (!end) {
    1435                 :          0 :                 return -EINVAL;
    1436                 :            :             }
    1437                 :            : 
    1438         [ +  + ]:         47 :             while (s != end) {
    1439                 :            :                 int n;
    1440                 :            : 
    1441                 :         31 :                 s += strspn(s, delimiters);
    1442         [ +  + ]:         31 :                 if (ovs_scan(s, "commit%n", &n)) {
    1443                 :         15 :                     commit = true;
    1444                 :         15 :                     s += n;
    1445                 :         20 :                     continue;
    1446                 :            :                 }
    1447         [ +  + ]:         16 :                 if (ovs_scan(s, "zone=%"SCNu16"%n", &zone, &n)) {
    1448                 :          1 :                     s += n;
    1449                 :          1 :                     continue;
    1450                 :            :                 }
    1451         [ +  + ]:         15 :                 if (ovs_scan(s, "mark=%"SCNx32"%n", &ct_mark.value, &n)) {
    1452                 :          1 :                     s += n;
    1453                 :          1 :                     n = -1;
    1454         [ +  - ]:          1 :                     if (ovs_scan(s, "/%"SCNx32"%n", &ct_mark.mask, &n)) {
    1455                 :          1 :                         s += n;
    1456                 :            :                     } else {
    1457                 :          0 :                         ct_mark.mask = UINT32_MAX;
    1458                 :            :                     }
    1459                 :          1 :                     continue;
    1460                 :            :                 }
    1461         [ +  + ]:         14 :                 if (ovs_scan(s, "label=%n", &n)) {
    1462                 :            :                     int retval;
    1463                 :            : 
    1464                 :          1 :                     s += n;
    1465                 :          1 :                     retval = scan_u128(s, &ct_label.value, &ct_label.mask);
    1466         [ -  + ]:          1 :                     if (retval < 0) {
    1467                 :          0 :                         return retval;
    1468                 :            :                     }
    1469                 :          1 :                     s += retval;
    1470                 :          1 :                     continue;
    1471                 :            :                 }
    1472         [ +  + ]:         13 :                 if (ovs_scan(s, "helper=%n", &n)) {
    1473                 :          2 :                     s += n;
    1474                 :          2 :                     helper_len = strcspn(s, delimiters_end);
    1475 [ +  - ][ -  + ]:          2 :                     if (!helper_len || helper_len > 15) {
    1476                 :          0 :                         return -EINVAL;
    1477                 :            :                     }
    1478                 :          2 :                     helper = s;
    1479                 :          2 :                     s += helper_len;
    1480                 :          2 :                     continue;
    1481                 :            :                 }
    1482                 :            : 
    1483                 :         11 :                 n = scan_ct_nat(s, &nat_params);
    1484         [ +  - ]:         11 :                 if (n > 0) {
    1485                 :         11 :                     s += n;
    1486                 :         11 :                     have_nat = true;
    1487                 :            : 
    1488                 :            :                     /* end points to the end of the nested, nat action.
    1489                 :            :                      * find the real end. */
    1490                 :         11 :                     goto find_end;
    1491                 :            :                 }
    1492                 :            :                 /* Nothing matched. */
    1493                 :          0 :                 return -EINVAL;
    1494                 :            :             }
    1495                 :         16 :             s++;
    1496                 :            :         }
    1497                 :            : 
    1498                 :         17 :         start = nl_msg_start_nested(actions, OVS_ACTION_ATTR_CT);
    1499         [ +  + ]:         17 :         if (commit) {
    1500                 :         15 :             nl_msg_put_flag(actions, OVS_CT_ATTR_COMMIT);
    1501                 :            :         }
    1502         [ +  + ]:         17 :         if (zone) {
    1503                 :          1 :             nl_msg_put_u16(actions, OVS_CT_ATTR_ZONE, zone);
    1504                 :            :         }
    1505         [ +  + ]:         17 :         if (ct_mark.mask) {
    1506                 :          1 :             nl_msg_put_unspec(actions, OVS_CT_ATTR_MARK, &ct_mark,
    1507                 :            :                               sizeof(ct_mark));
    1508                 :            :         }
    1509         [ +  + ]:         17 :         if (!ovs_u128_is_zero(ct_label.mask)) {
    1510                 :          1 :             nl_msg_put_unspec(actions, OVS_CT_ATTR_LABELS, &ct_label,
    1511                 :            :                               sizeof ct_label);
    1512                 :            :         }
    1513         [ +  + ]:         17 :         if (helper) {
    1514                 :          2 :             nl_msg_put_string__(actions, OVS_CT_ATTR_HELPER, helper,
    1515                 :            :                                 helper_len);
    1516                 :            :         }
    1517         [ +  + ]:         17 :         if (have_nat) {
    1518                 :         11 :             nl_msg_put_ct_nat(&nat_params, actions);
    1519                 :            :         }
    1520                 :         17 :         nl_msg_end_nested(actions, start);
    1521                 :            :     }
    1522                 :            : 
    1523                 :         29 :     return s - s_;
    1524                 :            : }
    1525                 :            : 
    1526                 :            : static int
    1527                 :       1106 : parse_odp_action(const char *s, const struct simap *port_names,
    1528                 :            :                  struct ofpbuf *actions)
    1529                 :            : {
    1530                 :            :     {
    1531                 :            :         uint32_t port;
    1532                 :            :         int n;
    1533                 :            : 
    1534         [ +  + ]:       1106 :         if (ovs_scan(s, "%"SCNi32"%n", &port, &n)) {
    1535                 :        752 :             nl_msg_put_u32(actions, OVS_ACTION_ATTR_OUTPUT, port);
    1536                 :        752 :             return n;
    1537                 :            :         }
    1538                 :            :     }
    1539                 :            : 
    1540                 :            :     {
    1541                 :            :         uint32_t max_len;
    1542                 :            :         int n;
    1543                 :            : 
    1544         [ +  + ]:        354 :         if (ovs_scan(s, "trunc(%"SCNi32")%n", &max_len, &n)) {
    1545                 :            :             struct ovs_action_trunc *trunc;
    1546                 :            : 
    1547                 :          1 :             trunc = nl_msg_put_unspec_uninit(actions,
    1548                 :            :                      OVS_ACTION_ATTR_TRUNC, sizeof *trunc);
    1549                 :          1 :             trunc->max_len = max_len;
    1550                 :          1 :             return n;
    1551                 :            :         }
    1552                 :            :     }
    1553                 :            : 
    1554         [ +  + ]:        353 :     if (port_names) {
    1555                 :        268 :         int len = strcspn(s, delimiters);
    1556                 :            :         struct simap_node *node;
    1557                 :            : 
    1558                 :        268 :         node = simap_find_len(port_names, s, len);
    1559         [ -  + ]:        268 :         if (node) {
    1560                 :          0 :             nl_msg_put_u32(actions, OVS_ACTION_ATTR_OUTPUT, node->data);
    1561                 :          0 :             return len;
    1562                 :            :         }
    1563                 :            :     }
    1564                 :            : 
    1565                 :            :     {
    1566                 :            :         uint32_t recirc_id;
    1567                 :        353 :         int n = -1;
    1568                 :            : 
    1569         [ -  + ]:        353 :         if (ovs_scan(s, "recirc(%"PRIu32")%n", &recirc_id, &n)) {
    1570                 :          0 :             nl_msg_put_u32(actions, OVS_ACTION_ATTR_RECIRC, recirc_id);
    1571                 :          0 :             return n;
    1572                 :            :         }
    1573                 :            :     }
    1574                 :            : 
    1575         [ +  + ]:        353 :     if (!strncmp(s, "userspace(", 10)) {
    1576                 :         14 :         return parse_odp_userspace_action(s, actions);
    1577                 :            :     }
    1578                 :            : 
    1579         [ +  + ]:        339 :     if (!strncmp(s, "set(", 4)) {
    1580                 :            :         size_t start_ofs;
    1581                 :            :         int retval;
    1582                 :            :         struct nlattr mask[128 / sizeof(struct nlattr)];
    1583                 :            :         struct ofpbuf maskbuf;
    1584                 :            :         struct nlattr *nested, *key;
    1585                 :            :         size_t size;
    1586                 :            : 
    1587                 :            :         /* 'mask' is big enough to hold any key. */
    1588                 :         34 :         ofpbuf_use_stack(&maskbuf, mask, sizeof mask);
    1589                 :            : 
    1590                 :         34 :         start_ofs = nl_msg_start_nested(actions, OVS_ACTION_ATTR_SET);
    1591                 :         34 :         retval = parse_odp_key_mask_attr(s + 4, port_names, actions, &maskbuf);
    1592         [ -  + ]:         34 :         if (retval < 0) {
    1593                 :          0 :             return retval;
    1594                 :            :         }
    1595         [ -  + ]:         34 :         if (s[retval + 4] != ')') {
    1596                 :          0 :             return -EINVAL;
    1597                 :            :         }
    1598                 :            : 
    1599                 :         34 :         nested = ofpbuf_at_assert(actions, start_ofs, sizeof *nested);
    1600                 :         34 :         key = nested + 1;
    1601                 :            : 
    1602                 :         34 :         size = nl_attr_get_size(mask);
    1603         [ +  + ]:         34 :         if (size == nl_attr_get_size(key)) {
    1604                 :            :             /* Change to masked set action if not fully masked. */
    1605         [ +  + ]:         32 :             if (!is_all_ones(mask + 1, size)) {
    1606                 :         23 :                 key->nla_len += size;
    1607                 :         23 :                 ofpbuf_put(actions, mask + 1, size);
    1608                 :            :                 /* 'actions' may have been reallocated by ofpbuf_put(). */
    1609                 :         23 :                 nested = ofpbuf_at_assert(actions, start_ofs, sizeof *nested);
    1610                 :         23 :                 nested->nla_type = OVS_ACTION_ATTR_SET_MASKED;
    1611                 :            :             }
    1612                 :            :         }
    1613                 :            : 
    1614                 :         34 :         nl_msg_end_nested(actions, start_ofs);
    1615                 :         34 :         return retval + 5;
    1616                 :            :     }
    1617                 :            : 
    1618                 :            :     {
    1619                 :            :         struct ovs_action_push_vlan push;
    1620                 :        305 :         int tpid = ETH_TYPE_VLAN;
    1621                 :            :         int vid, pcp;
    1622                 :        305 :         int cfi = 1;
    1623                 :        305 :         int n = -1;
    1624                 :            : 
    1625         [ +  + ]:        305 :         if (ovs_scan(s, "push_vlan(vid=%i,pcp=%i)%n", &vid, &pcp, &n)
    1626         [ +  + ]:        180 :             || ovs_scan(s, "push_vlan(vid=%i,pcp=%i,cfi=%i)%n",
    1627                 :            :                         &vid, &pcp, &cfi, &n)
    1628         [ +  + ]:        179 :             || ovs_scan(s, "push_vlan(tpid=%i,vid=%i,pcp=%i)%n",
    1629                 :            :                         &tpid, &vid, &pcp, &n)
    1630         [ +  + ]:        178 :             || ovs_scan(s, "push_vlan(tpid=%i,vid=%i,pcp=%i,cfi=%i)%n",
    1631                 :            :                         &tpid, &vid, &pcp, &cfi, &n)) {
    1632                 :        128 :             push.vlan_tpid = htons(tpid);
    1633         [ +  + ]:        128 :             push.vlan_tci = htons((vid << VLAN_VID_SHIFT)
    1634                 :        128 :                                   | (pcp << VLAN_PCP_SHIFT)
    1635                 :        128 :                                   | (cfi ? VLAN_CFI : 0));
    1636                 :        128 :             nl_msg_put_unspec(actions, OVS_ACTION_ATTR_PUSH_VLAN,
    1637                 :            :                               &push, sizeof push);
    1638                 :            : 
    1639                 :        128 :             return n;
    1640                 :            :         }
    1641                 :            :     }
    1642                 :            : 
    1643         [ +  + ]:        177 :     if (!strncmp(s, "pop_vlan", 8)) {
    1644                 :        146 :         nl_msg_put_flag(actions, OVS_ACTION_ATTR_POP_VLAN);
    1645                 :        146 :         return 8;
    1646                 :            :     }
    1647                 :            : 
    1648                 :            :     {
    1649                 :            :         double percentage;
    1650                 :         31 :         int n = -1;
    1651                 :            : 
    1652         [ +  + ]:         31 :         if (ovs_scan(s, "sample(sample=%lf%%,actions(%n", &percentage, &n)
    1653 [ +  - ][ +  - ]:          1 :             && percentage >= 0. && percentage <= 100.0) {
    1654                 :            :             size_t sample_ofs, actions_ofs;
    1655                 :            :             double probability;
    1656                 :            : 
    1657                 :          1 :             probability = floor(UINT32_MAX * (percentage / 100.0) + .5);
    1658                 :          1 :             sample_ofs = nl_msg_start_nested(actions, OVS_ACTION_ATTR_SAMPLE);
    1659 [ -  + ][ -  + ]:          1 :             nl_msg_put_u32(actions, OVS_SAMPLE_ATTR_PROBABILITY,
    1660                 :            :                            (probability <= 0 ? 0
    1661                 :            :                             : probability >= UINT32_MAX ? UINT32_MAX
    1662                 :            :                             : probability));
    1663                 :            : 
    1664                 :          1 :             actions_ofs = nl_msg_start_nested(actions,
    1665                 :            :                                               OVS_SAMPLE_ATTR_ACTIONS);
    1666                 :            :             for (;;) {
    1667                 :            :                 int retval;
    1668                 :            : 
    1669                 :          5 :                 n += strspn(s + n, delimiters);
    1670         [ +  + ]:          5 :                 if (s[n] == ')') {
    1671                 :          1 :                     break;
    1672                 :            :                 }
    1673                 :            : 
    1674                 :          4 :                 retval = parse_odp_action(s + n, port_names, actions);
    1675         [ -  + ]:          4 :                 if (retval < 0) {
    1676                 :          1 :                     return retval;
    1677                 :            :                 }
    1678                 :          4 :                 n += retval;
    1679                 :          4 :             }
    1680                 :          1 :             nl_msg_end_nested(actions, actions_ofs);
    1681                 :          1 :             nl_msg_end_nested(actions, sample_ofs);
    1682                 :            : 
    1683         [ +  - ]:          1 :             return s[n + 1] == ')' ? n + 2 : -EINVAL;
    1684                 :            :         }
    1685                 :            :     }
    1686                 :            : 
    1687                 :            :     {
    1688                 :            :         uint32_t port;
    1689                 :            :         int n;
    1690                 :            : 
    1691         [ +  + ]:         30 :         if (ovs_scan(s, "tnl_pop(%"SCNi32")%n", &port, &n)) {
    1692                 :          1 :             nl_msg_put_u32(actions, OVS_ACTION_ATTR_TUNNEL_POP, port);
    1693                 :          1 :             return n;
    1694                 :            :         }
    1695                 :            :     }
    1696                 :            : 
    1697                 :            :     {
    1698                 :            :         int retval;
    1699                 :            : 
    1700                 :         29 :         retval = parse_conntrack_action(s, actions);
    1701         [ +  + ]:         29 :         if (retval) {
    1702                 :         17 :             return retval;
    1703                 :            :         }
    1704                 :            :     }
    1705                 :            : 
    1706                 :            :     {
    1707                 :            :         struct ovs_action_push_tnl data;
    1708                 :            :         int n;
    1709                 :            : 
    1710                 :         12 :         n = ovs_parse_tnl_push(s, &data);
    1711         [ +  - ]:         12 :         if (n > 0) {
    1712                 :         12 :             odp_put_tnl_push_action(actions, &data);
    1713                 :         12 :             return n;
    1714         [ #  # ]:          0 :         } else if (n < 0) {
    1715                 :          0 :             return n;
    1716                 :            :         }
    1717                 :            :     }
    1718                 :          0 :     return -EINVAL;
    1719                 :            : }
    1720                 :            : 
    1721                 :            : /* Parses the string representation of datapath actions, in the format output
    1722                 :            :  * by format_odp_action().  Returns 0 if successful, otherwise a positive errno
    1723                 :            :  * value.  On success, the ODP actions are appended to 'actions' as a series of
    1724                 :            :  * Netlink attributes.  On failure, no data is appended to 'actions'.  Either
    1725                 :            :  * way, 'actions''s data might be reallocated. */
    1726                 :            : int
    1727                 :        294 : odp_actions_from_string(const char *s, const struct simap *port_names,
    1728                 :            :                         struct ofpbuf *actions)
    1729                 :            : {
    1730                 :            :     size_t old_size;
    1731                 :            : 
    1732         [ +  + ]:        294 :     if (!strcasecmp(s, "drop")) {
    1733                 :         60 :         return 0;
    1734                 :            :     }
    1735                 :            : 
    1736                 :        234 :     old_size = actions->size;
    1737                 :            :     for (;;) {
    1738                 :            :         int retval;
    1739                 :            : 
    1740                 :       1336 :         s += strspn(s, delimiters);
    1741         [ +  + ]:       1336 :         if (!*s) {
    1742                 :        234 :             return 0;
    1743                 :            :         }
    1744                 :            : 
    1745                 :       1102 :         retval = parse_odp_action(s, port_names, actions);
    1746 [ +  - ][ -  + ]:       1102 :         if (retval < 0 || !strchr(delimiters, s[retval])) {
    1747                 :          0 :             actions->size = old_size;
    1748                 :          0 :             return -retval;
    1749                 :            :         }
    1750                 :       1102 :         s += retval;
    1751                 :       1102 :     }
    1752                 :            : 
    1753                 :            :     return 0;
    1754                 :            : }
    1755                 :            : 
    1756                 :            : static const struct attr_len_tbl ovs_vxlan_ext_attr_lens[OVS_VXLAN_EXT_MAX + 1] = {
    1757                 :            :     [OVS_VXLAN_EXT_GBP]                 = { .len = 4 },
    1758                 :            : };
    1759                 :            : 
    1760                 :            : static const struct attr_len_tbl ovs_tun_key_attr_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] = {
    1761                 :            :     [OVS_TUNNEL_KEY_ATTR_ID]            = { .len = 8 },
    1762                 :            :     [OVS_TUNNEL_KEY_ATTR_IPV4_SRC]      = { .len = 4 },
    1763                 :            :     [OVS_TUNNEL_KEY_ATTR_IPV4_DST]      = { .len = 4 },
    1764                 :            :     [OVS_TUNNEL_KEY_ATTR_TOS]           = { .len = 1 },
    1765                 :            :     [OVS_TUNNEL_KEY_ATTR_TTL]           = { .len = 1 },
    1766                 :            :     [OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = { .len = 0 },
    1767                 :            :     [OVS_TUNNEL_KEY_ATTR_CSUM]          = { .len = 0 },
    1768                 :            :     [OVS_TUNNEL_KEY_ATTR_TP_SRC]        = { .len = 2 },
    1769                 :            :     [OVS_TUNNEL_KEY_ATTR_TP_DST]        = { .len = 2 },
    1770                 :            :     [OVS_TUNNEL_KEY_ATTR_OAM]           = { .len = 0 },
    1771                 :            :     [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS]   = { .len = ATTR_LEN_VARIABLE },
    1772                 :            :     [OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS]    = { .len = ATTR_LEN_NESTED,
    1773                 :            :                                             .next = ovs_vxlan_ext_attr_lens ,
    1774                 :            :                                             .next_max = OVS_VXLAN_EXT_MAX},
    1775                 :            :     [OVS_TUNNEL_KEY_ATTR_IPV6_SRC]      = { .len = 16 },
    1776                 :            :     [OVS_TUNNEL_KEY_ATTR_IPV6_DST]      = { .len = 16 },
    1777                 :            : };
    1778                 :            : 
    1779                 :            : static const struct attr_len_tbl ovs_flow_key_attr_lens[OVS_KEY_ATTR_MAX + 1] = {
    1780                 :            :     [OVS_KEY_ATTR_ENCAP]     = { .len = ATTR_LEN_NESTED },
    1781                 :            :     [OVS_KEY_ATTR_PRIORITY]  = { .len = 4 },
    1782                 :            :     [OVS_KEY_ATTR_SKB_MARK]  = { .len = 4 },
    1783                 :            :     [OVS_KEY_ATTR_DP_HASH]   = { .len = 4 },
    1784                 :            :     [OVS_KEY_ATTR_RECIRC_ID] = { .len = 4 },
    1785                 :            :     [OVS_KEY_ATTR_TUNNEL]    = { .len = ATTR_LEN_NESTED,
    1786                 :            :                                  .next = ovs_tun_key_attr_lens,
    1787                 :            :                                  .next_max = OVS_TUNNEL_KEY_ATTR_MAX },
    1788                 :            :     [OVS_KEY_ATTR_IN_PORT]   = { .len = 4  },
    1789                 :            :     [OVS_KEY_ATTR_ETHERNET]  = { .len = sizeof(struct ovs_key_ethernet) },
    1790                 :            :     [OVS_KEY_ATTR_VLAN]      = { .len = 2 },
    1791                 :            :     [OVS_KEY_ATTR_ETHERTYPE] = { .len = 2 },
    1792                 :            :     [OVS_KEY_ATTR_MPLS]      = { .len = ATTR_LEN_VARIABLE },
    1793                 :            :     [OVS_KEY_ATTR_IPV4]      = { .len = sizeof(struct ovs_key_ipv4) },
    1794                 :            :     [OVS_KEY_ATTR_IPV6]      = { .len = sizeof(struct ovs_key_ipv6) },
    1795                 :            :     [OVS_KEY_ATTR_TCP]       = { .len = sizeof(struct ovs_key_tcp) },
    1796                 :            :     [OVS_KEY_ATTR_TCP_FLAGS] = { .len = 2 },
    1797                 :            :     [OVS_KEY_ATTR_UDP]       = { .len = sizeof(struct ovs_key_udp) },
    1798                 :            :     [OVS_KEY_ATTR_SCTP]      = { .len = sizeof(struct ovs_key_sctp) },
    1799                 :            :     [OVS_KEY_ATTR_ICMP]      = { .len = sizeof(struct ovs_key_icmp) },
    1800                 :            :     [OVS_KEY_ATTR_ICMPV6]    = { .len = sizeof(struct ovs_key_icmpv6) },
    1801                 :            :     [OVS_KEY_ATTR_ARP]       = { .len = sizeof(struct ovs_key_arp) },
    1802                 :            :     [OVS_KEY_ATTR_ND]        = { .len = sizeof(struct ovs_key_nd) },
    1803                 :            :     [OVS_KEY_ATTR_CT_STATE]  = { .len = 4 },
    1804                 :            :     [OVS_KEY_ATTR_CT_ZONE]   = { .len = 2 },
    1805                 :            :     [OVS_KEY_ATTR_CT_MARK]   = { .len = 4 },
    1806                 :            :     [OVS_KEY_ATTR_CT_LABELS] = { .len = sizeof(struct ovs_key_ct_labels) },
    1807                 :            : };
    1808                 :            : 
    1809                 :            : /* Returns the correct length of the payload for a flow key attribute of the
    1810                 :            :  * specified 'type', ATTR_LEN_INVALID if 'type' is unknown, ATTR_LEN_VARIABLE
    1811                 :            :  * if the attribute's payload is variable length, or ATTR_LEN_NESTED if the
    1812                 :            :  * payload is a nested type. */
    1813                 :            : static int
    1814                 :    2185451 : odp_key_attr_len(const struct attr_len_tbl tbl[], int max_len, uint16_t type)
    1815                 :            : {
    1816         [ +  + ]:    2185451 :     if (type > max_len) {
    1817                 :     142210 :         return ATTR_LEN_INVALID;
    1818                 :            :     }
    1819                 :            : 
    1820                 :    2043241 :     return tbl[type].len;
    1821                 :            : }
    1822                 :            : 
    1823                 :            : static void
    1824                 :          0 : format_generic_odp_key(const struct nlattr *a, struct ds *ds)
    1825                 :            : {
    1826                 :          0 :     size_t len = nl_attr_get_size(a);
    1827         [ #  # ]:          0 :     if (len) {
    1828                 :            :         const uint8_t *unspec;
    1829                 :            :         unsigned int i;
    1830                 :            : 
    1831                 :          0 :         unspec = nl_attr_get(a);
    1832         [ #  # ]:          0 :         for (i = 0; i < len; i++) {
    1833         [ #  # ]:          0 :             if (i) {
    1834                 :          0 :                 ds_put_char(ds, ' ');
    1835                 :            :             }
    1836                 :          0 :             ds_put_format(ds, "%02x", unspec[i]);
    1837                 :            :         }
    1838                 :            :     }
    1839                 :          0 : }
    1840                 :            : 
    1841                 :            : static const char *
    1842                 :       1839 : ovs_frag_type_to_string(enum ovs_frag_type type)
    1843                 :            : {
    1844   [ +  +  +  - ]:       1839 :     switch (type) {
    1845                 :            :     case OVS_FRAG_TYPE_NONE:
    1846                 :       1711 :         return "no";
    1847                 :            :     case OVS_FRAG_TYPE_FIRST:
    1848                 :         64 :         return "first";
    1849                 :            :     case OVS_FRAG_TYPE_LATER:
    1850                 :         64 :         return "later";
    1851                 :            :     case __OVS_FRAG_TYPE_MAX:
    1852                 :            :     default:
    1853                 :          0 :         return "<error>";
    1854                 :            :     }
    1855                 :            : }
    1856                 :            : 
    1857                 :            : static enum odp_key_fitness
    1858                 :      76711 : odp_tun_key_from_attr__(const struct nlattr *attr,
    1859                 :            :                         const struct nlattr *flow_attrs, size_t flow_attr_len,
    1860                 :            :                         const struct flow_tnl *src_tun, struct flow_tnl *tun,
    1861                 :            :                         bool udpif)
    1862                 :            : {
    1863                 :            :     unsigned int left;
    1864                 :            :     const struct nlattr *a;
    1865                 :      76711 :     bool ttl = false;
    1866                 :      76711 :     bool unknown = false;
    1867                 :            : 
    1868         [ +  + ]:     270562 :     NL_NESTED_FOR_EACH(a, left, attr) {
    1869                 :     193851 :         uint16_t type = nl_attr_type(a);
    1870                 :     193851 :         size_t len = nl_attr_get_size(a);
    1871                 :     193851 :         int expected_len = odp_key_attr_len(ovs_tun_key_attr_lens,
    1872                 :            :                                             OVS_TUNNEL_ATTR_MAX, type);
    1873                 :            : 
    1874 [ +  + ][ -  + ]:     193851 :         if (len != expected_len && expected_len >= 0) {
    1875                 :          0 :             return ODP_FIT_ERROR;
    1876                 :            :         }
    1877                 :            : 
    1878   [ +  +  +  +  :     193851 :         switch (type) {
          +  +  +  +  +  
          +  +  -  -  +  
                      - ]
    1879                 :            :         case OVS_TUNNEL_KEY_ATTR_ID:
    1880                 :      18202 :             tun->tun_id = nl_attr_get_be64(a);
    1881                 :      18202 :             tun->flags |= FLOW_TNL_F_KEY;
    1882                 :      18202 :             break;
    1883                 :            :         case OVS_TUNNEL_KEY_ATTR_IPV4_SRC:
    1884                 :      16718 :             tun->ip_src = nl_attr_get_be32(a);
    1885                 :      16718 :             break;
    1886                 :            :         case OVS_TUNNEL_KEY_ATTR_IPV4_DST:
    1887                 :      16721 :             tun->ip_dst = nl_attr_get_be32(a);
    1888                 :      16721 :             break;
    1889                 :            :         case OVS_TUNNEL_KEY_ATTR_IPV6_SRC:
    1890                 :          4 :             tun->ipv6_src = nl_attr_get_in6_addr(a);
    1891                 :          4 :             break;
    1892                 :            :         case OVS_TUNNEL_KEY_ATTR_IPV6_DST:
    1893                 :          4 :             tun->ipv6_dst = nl_attr_get_in6_addr(a);
    1894                 :          4 :             break;
    1895                 :            :         case OVS_TUNNEL_KEY_ATTR_TOS:
    1896                 :       8169 :             tun->ip_tos = nl_attr_get_u8(a);
    1897                 :       8169 :             break;
    1898                 :            :         case OVS_TUNNEL_KEY_ATTR_TTL:
    1899                 :      76711 :             tun->ip_ttl = nl_attr_get_u8(a);
    1900                 :      76711 :             ttl = true;
    1901                 :      76711 :             break;
    1902                 :            :         case OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT:
    1903                 :       8120 :             tun->flags |= FLOW_TNL_F_DONT_FRAGMENT;
    1904                 :       8120 :             break;
    1905                 :            :         case OVS_TUNNEL_KEY_ATTR_CSUM:
    1906                 :      16353 :             tun->flags |= FLOW_TNL_F_CSUM;
    1907                 :      16353 :             break;
    1908                 :            :         case OVS_TUNNEL_KEY_ATTR_TP_SRC:
    1909                 :       8358 :             tun->tp_src = nl_attr_get_be16(a);
    1910                 :       8358 :             break;
    1911                 :            :         case OVS_TUNNEL_KEY_ATTR_TP_DST:
    1912                 :       8358 :             tun->tp_dst = nl_attr_get_be16(a);
    1913                 :       8358 :             break;
    1914                 :            :         case OVS_TUNNEL_KEY_ATTR_OAM:
    1915                 :          0 :             tun->flags |= FLOW_TNL_F_OAM;
    1916                 :          0 :             break;
    1917                 :            :         case OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS: {
    1918                 :            :             static const struct nl_policy vxlan_opts_policy[] = {
    1919                 :            :                 [OVS_VXLAN_EXT_GBP] = { .type = NL_A_U32 },
    1920                 :            :             };
    1921                 :            :             struct nlattr *ext[ARRAY_SIZE(vxlan_opts_policy)];
    1922                 :            : 
    1923         [ #  # ]:          0 :             if (!nl_parse_nested(a, vxlan_opts_policy, ext, ARRAY_SIZE(ext))) {
    1924                 :          0 :                 return ODP_FIT_ERROR;
    1925                 :            :             }
    1926                 :            : 
    1927         [ #  # ]:          0 :             if (ext[OVS_VXLAN_EXT_GBP]) {
    1928                 :          0 :                 uint32_t gbp = nl_attr_get_u32(ext[OVS_VXLAN_EXT_GBP]);
    1929                 :            : 
    1930                 :          0 :                 tun->gbp_id = htons(gbp & 0xFFFF);
    1931                 :          0 :                 tun->gbp_flags = (gbp >> 16) & 0xFF;
    1932                 :            :             }
    1933                 :            : 
    1934                 :          0 :             break;
    1935                 :            :         }
    1936                 :            :         case OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS:
    1937         [ -  + ]:      16133 :             if (tun_metadata_from_geneve_nlattr(a, flow_attrs, flow_attr_len,
    1938                 :            :                                                 src_tun, udpif, tun)) {
    1939                 :          0 :                 return ODP_FIT_ERROR;
    1940                 :            :             }
    1941                 :      16133 :             break;
    1942                 :            : 
    1943                 :            :         default:
    1944                 :            :             /* Allow this to show up as unexpected, if there are unknown
    1945                 :            :              * tunnel attribute, eventually resulting in ODP_FIT_TOO_MUCH. */
    1946                 :          0 :             unknown = true;
    1947                 :          0 :             break;
    1948                 :            :         }
    1949                 :            :     }
    1950                 :            : 
    1951         [ -  + ]:      76711 :     if (!ttl) {
    1952                 :          0 :         return ODP_FIT_ERROR;
    1953                 :            :     }
    1954         [ -  + ]:      76711 :     if (unknown) {
    1955                 :          0 :         return ODP_FIT_TOO_MUCH;
    1956                 :            :     }
    1957                 :      76711 :     return ODP_FIT_PERFECT;
    1958                 :            : }
    1959                 :            : 
    1960                 :            : enum odp_key_fitness
    1961                 :         36 : odp_tun_key_from_attr(const struct nlattr *attr, bool udpif,
    1962                 :            :                       struct flow_tnl *tun)
    1963                 :            : {
    1964                 :         36 :     memset(tun, 0, sizeof *tun);
    1965                 :         36 :     return odp_tun_key_from_attr__(attr, NULL, 0, NULL, tun, udpif);
    1966                 :            : }
    1967                 :            : 
    1968                 :            : static void
    1969                 :      14173 : tun_key_to_attr(struct ofpbuf *a, const struct flow_tnl *tun_key,
    1970                 :            :                 const struct flow_tnl *tun_flow_key,
    1971                 :            :                 const struct ofpbuf *key_buf)
    1972                 :            : {
    1973                 :            :     size_t tun_key_ofs;
    1974                 :            : 
    1975                 :      14173 :     tun_key_ofs = nl_msg_start_nested(a, OVS_KEY_ATTR_TUNNEL);
    1976                 :            : 
    1977                 :            :     /* tun_id != 0 without FLOW_TNL_F_KEY is valid if tun_key is a mask. */
    1978 [ +  + ][ +  + ]:      14173 :     if (tun_key->tun_id || tun_key->flags & FLOW_TNL_F_KEY) {
    1979                 :       2873 :         nl_msg_put_be64(a, OVS_TUNNEL_KEY_ATTR_ID, tun_key->tun_id);
    1980                 :            :     }
    1981         [ +  + ]:      14173 :     if (tun_key->ip_src) {
    1982                 :       1829 :         nl_msg_put_be32(a, OVS_TUNNEL_KEY_ATTR_IPV4_SRC, tun_key->ip_src);
    1983                 :            :     }
    1984         [ +  + ]:      14173 :     if (tun_key->ip_dst) {
    1985                 :       1925 :         nl_msg_put_be32(a, OVS_TUNNEL_KEY_ATTR_IPV4_DST, tun_key->ip_dst);
    1986                 :            :     }
    1987         [ +  + ]:      14173 :     if (ipv6_addr_is_set(&tun_key->ipv6_src)) {
    1988                 :          6 :         nl_msg_put_in6_addr(a, OVS_TUNNEL_KEY_ATTR_IPV6_SRC, &tun_key->ipv6_src);
    1989                 :            :     }
    1990         [ +  + ]:      14173 :     if (ipv6_addr_is_set(&tun_key->ipv6_dst)) {
    1991                 :          7 :         nl_msg_put_in6_addr(a, OVS_TUNNEL_KEY_ATTR_IPV6_DST, &tun_key->ipv6_dst);
    1992                 :            :     }
    1993         [ +  + ]:      14173 :     if (tun_key->ip_tos) {
    1994                 :        924 :         nl_msg_put_u8(a, OVS_TUNNEL_KEY_ATTR_TOS, tun_key->ip_tos);
    1995                 :            :     }
    1996                 :      14173 :     nl_msg_put_u8(a, OVS_TUNNEL_KEY_ATTR_TTL, tun_key->ip_ttl);
    1997         [ +  + ]:      14173 :     if (tun_key->flags & FLOW_TNL_F_DONT_FRAGMENT) {
    1998                 :        980 :         nl_msg_put_flag(a, OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT);
    1999                 :            :     }
    2000         [ +  + ]:      14173 :     if (tun_key->flags & FLOW_TNL_F_CSUM) {
    2001                 :       1689 :         nl_msg_put_flag(a, OVS_TUNNEL_KEY_ATTR_CSUM);
    2002                 :            :     }
    2003         [ +  + ]:      14173 :     if (tun_key->tp_src) {
    2004                 :        840 :         nl_msg_put_be16(a, OVS_TUNNEL_KEY_ATTR_TP_SRC, tun_key->tp_src);
    2005                 :            :     }
    2006         [ +  + ]:      14173 :     if (tun_key->tp_dst) {
    2007                 :        840 :         nl_msg_put_be16(a, OVS_TUNNEL_KEY_ATTR_TP_DST, tun_key->tp_dst);
    2008                 :            :     }
    2009         [ -  + ]:      14173 :     if (tun_key->flags & FLOW_TNL_F_OAM) {
    2010                 :          0 :         nl_msg_put_flag(a, OVS_TUNNEL_KEY_ATTR_OAM);
    2011                 :            :     }
    2012 [ +  - ][ -  + ]:      14173 :     if (tun_key->gbp_flags || tun_key->gbp_id) {
    2013                 :            :         size_t vxlan_opts_ofs;
    2014                 :            : 
    2015                 :          0 :         vxlan_opts_ofs = nl_msg_start_nested(a, OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS);
    2016                 :          0 :         nl_msg_put_u32(a, OVS_VXLAN_EXT_GBP,
    2017                 :          0 :                        (tun_key->gbp_flags << 16) | ntohs(tun_key->gbp_id));
    2018                 :          0 :         nl_msg_end_nested(a, vxlan_opts_ofs);
    2019                 :            :     }
    2020                 :      14173 :     tun_metadata_to_geneve_nlattr(tun_key, tun_flow_key, key_buf, a);
    2021                 :            : 
    2022                 :      14173 :     nl_msg_end_nested(a, tun_key_ofs);
    2023                 :      14173 : }
    2024                 :            : 
    2025                 :            : static bool
    2026                 :      18592 : odp_mask_attr_is_wildcard(const struct nlattr *ma)
    2027                 :            : {
    2028                 :      18592 :     return is_all_zeros(nl_attr_get(ma), nl_attr_get_size(ma));
    2029                 :            : }
    2030                 :            : 
    2031                 :            : static bool
    2032                 :      25328 : odp_mask_is_exact(enum ovs_key_attr attr, const void *mask, size_t size)
    2033                 :            : {
    2034         [ +  + ]:      25328 :     if (attr == OVS_KEY_ATTR_TCP_FLAGS) {
    2035                 :        770 :         return TCP_FLAGS(*(ovs_be16 *)mask) == TCP_FLAGS(OVS_BE16_MAX);
    2036                 :            :     }
    2037         [ +  + ]:      24558 :     if (attr == OVS_KEY_ATTR_IPV6) {
    2038                 :        128 :         const struct ovs_key_ipv6 *ipv6_mask = mask;
    2039                 :            : 
    2040                 :            :         return
    2041                 :        256 :             ((ipv6_mask->ipv6_label & htonl(IPV6_LABEL_MASK))
    2042                 :        128 :              == htonl(IPV6_LABEL_MASK))
    2043         [ +  + ]:         93 :             && ipv6_mask->ipv6_proto == UINT8_MAX
    2044         [ +  + ]:         92 :             && ipv6_mask->ipv6_tclass == UINT8_MAX
    2045         [ +  - ]:         91 :             && ipv6_mask->ipv6_hlimit == UINT8_MAX
    2046         [ +  - ]:         91 :             && ipv6_mask->ipv6_frag == UINT8_MAX
    2047         [ +  + ]:         91 :             && ipv6_mask_is_exact((const struct in6_addr *)ipv6_mask->ipv6_src)
    2048 [ +  + ][ +  - ]:        221 :             && ipv6_mask_is_exact((const struct in6_addr *)ipv6_mask->ipv6_dst);
    2049                 :            :     }
    2050         [ -  + ]:      24430 :     if (attr == OVS_KEY_ATTR_TUNNEL) {
    2051                 :          0 :         return false;
    2052                 :            :     }
    2053                 :            : 
    2054         [ +  + ]:      24430 :     if (attr == OVS_KEY_ATTR_ARP) {
    2055                 :            :         /* ARP key has padding, ignore it. */
    2056                 :            :         BUILD_ASSERT_DECL(sizeof(struct ovs_key_arp) == 24);
    2057                 :            :         BUILD_ASSERT_DECL(offsetof(struct ovs_key_arp, arp_tha) == 10 + 6);
    2058                 :       2052 :         size = offsetof(struct ovs_key_arp, arp_tha) + ETH_ADDR_LEN;
    2059         [ -  + ]:       2052 :         ovs_assert(((uint16_t *)mask)[size/2] == 0);
    2060                 :            :     }
    2061                 :            : 
    2062                 :      24430 :     return is_all_ones(mask, size);
    2063                 :            : }
    2064                 :            : 
    2065                 :            : static bool
    2066                 :      15384 : odp_mask_attr_is_exact(const struct nlattr *ma)
    2067                 :            : {
    2068                 :      15384 :     enum ovs_key_attr attr = nl_attr_type(ma);
    2069                 :            :     const void *mask;
    2070                 :            :     size_t size;
    2071                 :            : 
    2072         [ +  + ]:      15384 :     if (attr == OVS_KEY_ATTR_TUNNEL) {
    2073                 :         75 :         return false;
    2074                 :            :     } else {
    2075                 :      15309 :         mask = nl_attr_get(ma);
    2076                 :      15309 :         size = nl_attr_get_size(ma);
    2077                 :            :     }
    2078                 :            : 
    2079                 :      15309 :     return odp_mask_is_exact(attr, mask, size);
    2080                 :            : }
    2081                 :            : 
    2082                 :            : void
    2083                 :        201 : odp_portno_names_set(struct hmap *portno_names, odp_port_t port_no,
    2084                 :            :                      char *port_name)
    2085                 :            : {
    2086                 :            :     struct odp_portno_names *odp_portno_names;
    2087                 :            : 
    2088                 :        201 :     odp_portno_names = xmalloc(sizeof *odp_portno_names);
    2089                 :        201 :     odp_portno_names->port_no = port_no;
    2090                 :        201 :     odp_portno_names->name = xstrdup(port_name);
    2091                 :        201 :     hmap_insert(portno_names, &odp_portno_names->hmap_node,
    2092                 :            :                 hash_odp_port(port_no));
    2093                 :        201 : }
    2094                 :            : 
    2095                 :            : static char *
    2096                 :          7 : odp_portno_names_get(const struct hmap *portno_names, odp_port_t port_no)
    2097                 :            : {
    2098                 :            :     struct odp_portno_names *odp_portno_names;
    2099                 :            : 
    2100 [ +  - ][ #  # ]:         11 :     HMAP_FOR_EACH_IN_BUCKET (odp_portno_names, hmap_node,
    2101                 :            :                              hash_odp_port(port_no), portno_names) {
    2102         [ +  + ]:         11 :         if (odp_portno_names->port_no == port_no) {
    2103                 :          7 :             return odp_portno_names->name;
    2104                 :            :         }
    2105                 :            :     }
    2106                 :          0 :     return NULL;
    2107                 :            : }
    2108                 :            : 
    2109                 :            : void
    2110                 :         34 : odp_portno_names_destroy(struct hmap *portno_names)
    2111                 :            : {
    2112                 :            :     struct odp_portno_names *odp_portno_names;
    2113                 :            : 
    2114 [ +  + ][ -  + ]:        235 :     HMAP_FOR_EACH_POP (odp_portno_names, hmap_node, portno_names) {
                 [ +  + ]
    2115                 :        201 :         free(odp_portno_names->name);
    2116                 :        201 :         free(odp_portno_names);
    2117                 :            :     }
    2118                 :         34 : }
    2119                 :            : 
    2120                 :            : /* Format helpers. */
    2121                 :            : 
    2122                 :            : static void
    2123                 :       4410 : format_eth(struct ds *ds, const char *name, const struct eth_addr key,
    2124                 :            :            const struct eth_addr *mask, bool verbose)
    2125                 :            : {
    2126 [ +  + ][ +  + ]:       4410 :     bool mask_empty = mask && eth_addr_is_zero(*mask);
    2127                 :            : 
    2128 [ +  + ][ +  + ]:       4410 :     if (verbose || !mask_empty) {
    2129 [ +  + ][ +  + ]:       4282 :         bool mask_full = !mask || eth_mask_is_exact(*mask);
    2130                 :            : 
    2131         [ +  + ]:       4282 :         if (mask_full) {
    2132                 :       4091 :             ds_put_format(ds, "%s="ETH_ADDR_FMT",", name, ETH_ADDR_ARGS(key));
    2133                 :            :         } else {
    2134                 :        191 :             ds_put_format(ds, "%s=", name);
    2135                 :        191 :             eth_format_masked(key, mask, ds);
    2136                 :        191 :             ds_put_char(ds, ',');
    2137                 :            :         }
    2138                 :            :     }
    2139                 :       4410 : }
    2140                 :            : 
    2141                 :            : static void
    2142                 :        194 : format_be64(struct ds *ds, const char *name, ovs_be64 key,
    2143                 :            :             const ovs_be64 *mask, bool verbose)
    2144                 :            : {
    2145 [ +  + ][ -  + ]:        194 :     bool mask_empty = mask && !*mask;
    2146                 :            : 
    2147 [ +  + ][ +  - ]:        194 :     if (verbose || !mask_empty) {
    2148 [ +  + ][ +  + ]:        194 :         bool mask_full = !mask || *mask == OVS_BE64_MAX;
    2149                 :            : 
    2150                 :        194 :         ds_put_format(ds, "%s=0x%"PRIx64, name, ntohll(key));
    2151         [ +  + ]:        194 :         if (!mask_full) { /* Partially masked. */
    2152                 :         51 :             ds_put_format(ds, "/%#"PRIx64, ntohll(*mask));
    2153                 :            :         }
    2154                 :        194 :         ds_put_char(ds, ',');
    2155                 :            :     }
    2156                 :        194 : }
    2157                 :            : 
    2158                 :            : static void
    2159                 :       3878 : format_ipv4(struct ds *ds, const char *name, ovs_be32 key,
    2160                 :            :             const ovs_be32 *mask, bool verbose)
    2161                 :            : {
    2162 [ +  + ][ +  + ]:       3878 :     bool mask_empty = mask && !*mask;
    2163                 :            : 
    2164 [ +  + ][ +  + ]:       3878 :     if (verbose || !mask_empty) {
    2165 [ +  + ][ +  + ]:       3211 :         bool mask_full = !mask || *mask == OVS_BE32_MAX;
    2166                 :            : 
    2167                 :       3211 :         ds_put_format(ds, "%s="IP_FMT, name, IP_ARGS(key));
    2168         [ +  + ]:       3211 :         if (!mask_full) { /* Partially masked. */
    2169                 :        279 :             ds_put_format(ds, "/"IP_FMT, IP_ARGS(*mask));
    2170                 :            :         }
    2171                 :       3211 :         ds_put_char(ds, ',');
    2172                 :            :     }
    2173                 :       3878 : }
    2174                 :            : 
    2175                 :            : static void
    2176                 :        495 : format_in6_addr(struct ds *ds, const char *name,
    2177                 :            :                 const struct in6_addr *key,
    2178                 :            :                 const struct in6_addr *mask,
    2179                 :            :                 bool verbose)
    2180                 :            : {
    2181                 :            :     char buf[INET6_ADDRSTRLEN];
    2182 [ +  + ][ +  + ]:        495 :     bool mask_empty = mask && ipv6_mask_is_any(mask);
    2183                 :            : 
    2184 [ +  + ][ +  + ]:        495 :     if (verbose || !mask_empty) {
    2185 [ +  + ][ +  + ]:        449 :         bool mask_full = !mask || ipv6_mask_is_exact(mask);
    2186                 :            : 
    2187                 :        449 :         inet_ntop(AF_INET6, key, buf, sizeof buf);
    2188                 :        449 :         ds_put_format(ds, "%s=%s", name, buf);
    2189         [ +  + ]:        449 :         if (!mask_full) { /* Partially masked. */
    2190                 :         61 :             inet_ntop(AF_INET6, mask, buf, sizeof buf);
    2191                 :         61 :             ds_put_format(ds, "/%s", buf);
    2192                 :            :         }
    2193                 :        449 :         ds_put_char(ds, ',');
    2194                 :            :     }
    2195                 :        495 : }
    2196                 :            : 
    2197                 :            : static void
    2198                 :        492 : format_ipv6(struct ds *ds, const char *name, const ovs_be32 key_[4],
    2199                 :            :             const ovs_be32 (*mask_)[4], bool verbose)
    2200                 :            : {
    2201                 :        492 :     format_in6_addr(ds, name,
    2202                 :            :                     (const struct in6_addr *)key_,
    2203                 :            :                     mask_ ? (const struct in6_addr *)*mask_ : NULL,
    2204                 :            :                     verbose);
    2205                 :        492 : }
    2206                 :            : 
    2207                 :            : static void
    2208                 :        212 : format_ipv6_label(struct ds *ds, const char *name, ovs_be32 key,
    2209                 :            :                   const ovs_be32 *mask, bool verbose)
    2210                 :            : {
    2211 [ +  + ][ +  + ]:        212 :     bool mask_empty = mask && !*mask;
    2212                 :            : 
    2213 [ +  + ][ +  + ]:        212 :     if (verbose || !mask_empty) {
    2214                 :        191 :         bool mask_full = !mask
    2215 [ +  + ][ +  + ]:        191 :             || (*mask & htonl(IPV6_LABEL_MASK)) == htonl(IPV6_LABEL_MASK);
    2216                 :            : 
    2217                 :        191 :         ds_put_format(ds, "%s=%#"PRIx32, name, ntohl(key));
    2218         [ +  + ]:        191 :         if (!mask_full) { /* Partially masked. */
    2219                 :         11 :             ds_put_format(ds, "/%#"PRIx32, ntohl(*mask));
    2220                 :            :         }
    2221                 :        191 :         ds_put_char(ds, ',');
    2222                 :            :     }
    2223                 :        212 : }
    2224                 :            : 
    2225                 :            : static void
    2226                 :       2019 : format_u8x(struct ds *ds, const char *name, uint8_t key,
    2227                 :            :            const uint8_t *mask, bool verbose)
    2228                 :            : {
    2229 [ +  + ][ +  + ]:       2019 :     bool mask_empty = mask && !*mask;
    2230                 :            : 
    2231 [ +  + ][ +  + ]:       2019 :     if (verbose || !mask_empty) {
    2232 [ +  + ][ +  + ]:       1630 :         bool mask_full = !mask || *mask == UINT8_MAX;
    2233                 :            : 
    2234                 :       1630 :         ds_put_format(ds, "%s=%#"PRIx8, name, key);
    2235         [ +  + ]:       1630 :         if (!mask_full) { /* Partially masked. */
    2236                 :        101 :             ds_put_format(ds, "/%#"PRIx8, *mask);
    2237                 :            :         }
    2238                 :       1630 :         ds_put_char(ds, ',');
    2239                 :            :     }
    2240                 :       2019 : }
    2241                 :            : 
    2242                 :            : static void
    2243                 :       4779 : format_u8u(struct ds *ds, const char *name, uint8_t key,
    2244                 :            :            const uint8_t *mask, bool verbose)
    2245                 :            : {
    2246 [ +  + ][ +  + ]:       4779 :     bool mask_empty = mask && !*mask;
    2247                 :            : 
    2248 [ +  + ][ +  + ]:       4779 :     if (verbose || !mask_empty) {
    2249 [ +  + ][ +  + ]:       4085 :         bool mask_full = !mask || *mask == UINT8_MAX;
    2250                 :            : 
    2251                 :       4085 :         ds_put_format(ds, "%s=%"PRIu8, name, key);
    2252         [ +  + ]:       4085 :         if (!mask_full) { /* Partially masked. */
    2253                 :        245 :             ds_put_format(ds, "/%#"PRIx8, *mask);
    2254                 :            :         }
    2255                 :       4085 :         ds_put_char(ds, ',');
    2256                 :            :     }
    2257                 :       4779 : }
    2258                 :            : 
    2259                 :            : static void
    2260                 :       2266 : format_be16(struct ds *ds, const char *name, ovs_be16 key,
    2261                 :            :             const ovs_be16 *mask, bool verbose)
    2262                 :            : {
    2263 [ +  + ][ +  + ]:       2266 :     bool mask_empty = mask && !*mask;
    2264                 :            : 
    2265 [ +  + ][ +  + ]:       2266 :     if (verbose || !mask_empty) {
    2266 [ +  + ][ +  + ]:       2194 :         bool mask_full = !mask || *mask == OVS_BE16_MAX;
    2267                 :            : 
    2268                 :       2194 :         ds_put_format(ds, "%s=%"PRIu16, name, ntohs(key));
    2269         [ +  + ]:       2194 :         if (!mask_full) { /* Partially masked. */
    2270                 :        234 :             ds_put_format(ds, "/%#"PRIx16, ntohs(*mask));
    2271                 :            :         }
    2272                 :       2194 :         ds_put_char(ds, ',');
    2273                 :            :     }
    2274                 :       2266 : }
    2275                 :            : 
    2276                 :            : static void
    2277                 :         51 : format_be16x(struct ds *ds, const char *name, ovs_be16 key,
    2278                 :            :              const ovs_be16 *mask, bool verbose)
    2279                 :            : {
    2280 [ +  + ][ -  + ]:         51 :     bool mask_empty = mask && !*mask;
    2281                 :            : 
    2282 [ +  + ][ +  - ]:         51 :     if (verbose || !mask_empty) {
    2283 [ +  + ][ +  - ]:         51 :         bool mask_full = !mask || *mask == OVS_BE16_MAX;
    2284                 :            : 
    2285                 :         51 :         ds_put_format(ds, "%s=%#"PRIx16, name, ntohs(key));
    2286         [ -  + ]:         51 :         if (!mask_full) { /* Partially masked. */
    2287                 :          0 :             ds_put_format(ds, "/%#"PRIx16, ntohs(*mask));
    2288                 :            :         }
    2289                 :         51 :         ds_put_char(ds, ',');
    2290                 :            :     }
    2291                 :         51 : }
    2292                 :            : 
    2293                 :            : static void
    2294                 :        202 : format_tun_flags(struct ds *ds, const char *name, uint16_t key,
    2295                 :            :                  const uint16_t *mask, bool verbose)
    2296                 :            : {
    2297 [ +  + ][ -  + ]:        202 :     bool mask_empty = mask && !*mask;
    2298                 :            : 
    2299 [ +  + ][ +  - ]:        202 :     if (verbose || !mask_empty) {
    2300                 :        202 :         ds_put_cstr(ds, name);
    2301                 :        202 :         ds_put_char(ds, '(');
    2302         [ +  + ]:        202 :         if (mask) {
    2303                 :         75 :             format_flags_masked(ds, NULL, flow_tun_flag_to_string, key,
    2304                 :         75 :                                 *mask & FLOW_TNL_F_MASK, FLOW_TNL_F_MASK);
    2305                 :            :         } else { /* Fully masked. */
    2306                 :        127 :             format_flags(ds, flow_tun_flag_to_string, key, '|');
    2307                 :            :         }
    2308                 :        202 :         ds_put_cstr(ds, "),");
    2309                 :            :     }
    2310                 :        202 : }
    2311                 :            : 
    2312                 :            : static bool
    2313                 :      24564 : check_attr_len(struct ds *ds, const struct nlattr *a, const struct nlattr *ma,
    2314                 :            :                const struct attr_len_tbl tbl[], int max_len, bool need_key)
    2315                 :            : {
    2316                 :            :     int expected_len;
    2317                 :            : 
    2318                 :      24564 :     expected_len = odp_key_attr_len(tbl, max_len, nl_attr_type(a));
    2319 [ +  + ][ +  + ]:      24564 :     if (expected_len != ATTR_LEN_VARIABLE &&
    2320                 :            :         expected_len != ATTR_LEN_NESTED) {
    2321                 :            : 
    2322                 :      23997 :         bool bad_key_len = nl_attr_get_size(a) != expected_len;
    2323 [ +  + ][ -  + ]:      23997 :         bool bad_mask_len = ma && nl_attr_get_size(ma) != expected_len;
    2324                 :            : 
    2325 [ +  - ][ -  + ]:      23997 :         if (bad_key_len || bad_mask_len) {
    2326         [ #  # ]:          0 :             if (need_key) {
    2327                 :          0 :                 ds_put_format(ds, "key%u", nl_attr_type(a));
    2328                 :            :             }
    2329         [ #  # ]:          0 :             if (bad_key_len) {
    2330                 :          0 :                 ds_put_format(ds, "(bad key length %"PRIuSIZE", expected %d)(",
    2331                 :            :                               nl_attr_get_size(a), expected_len);
    2332                 :            :             }
    2333                 :          0 :             format_generic_odp_key(a, ds);
    2334         [ #  # ]:          0 :             if (ma) {
    2335                 :          0 :                 ds_put_char(ds, '/');
    2336         [ #  # ]:          0 :                 if (bad_mask_len) {
    2337                 :          0 :                     ds_put_format(ds, "(bad mask length %"PRIuSIZE", expected %d)(",
    2338                 :            :                                   nl_attr_get_size(ma), expected_len);
    2339                 :            :                 }
    2340                 :          0 :                 format_generic_odp_key(ma, ds);
    2341                 :            :             }
    2342                 :          0 :             ds_put_char(ds, ')');
    2343                 :          0 :             return false;
    2344                 :            :         }
    2345                 :            :     }
    2346                 :            : 
    2347                 :      24564 :     return true;
    2348                 :            : }
    2349                 :            : 
    2350                 :            : static void
    2351                 :          0 : format_unknown_key(struct ds *ds, const struct nlattr *a,
    2352                 :            :                    const struct nlattr *ma)
    2353                 :            : {
    2354                 :          0 :     ds_put_format(ds, "key%u(", nl_attr_type(a));
    2355                 :          0 :     format_generic_odp_key(a, ds);
    2356 [ #  # ][ #  # ]:          0 :     if (ma && !odp_mask_attr_is_exact(ma)) {
    2357                 :          0 :         ds_put_char(ds, '/');
    2358                 :          0 :         format_generic_odp_key(ma, ds);
    2359                 :            :     }
    2360                 :          0 :     ds_put_cstr(ds, "),");
    2361                 :          0 : }
    2362                 :            : 
    2363                 :            : static void
    2364                 :         17 : format_odp_tun_vxlan_opt(const struct nlattr *attr,
    2365                 :            :                          const struct nlattr *mask_attr, struct ds *ds,
    2366                 :            :                          bool verbose)
    2367                 :            : {
    2368                 :            :     unsigned int left;
    2369                 :            :     const struct nlattr *a;
    2370                 :            :     struct ofpbuf ofp;
    2371                 :            : 
    2372                 :         17 :     ofpbuf_init(&ofp, 100);
    2373         [ +  + ]:         34 :     NL_NESTED_FOR_EACH(a, left, attr) {
    2374                 :         17 :         uint16_t type = nl_attr_type(a);
    2375                 :         17 :         const struct nlattr *ma = NULL;
    2376                 :            : 
    2377         [ +  - ]:         17 :         if (mask_attr) {
    2378                 :         17 :             ma = nl_attr_find__(nl_attr_get(mask_attr),
    2379                 :            :                                 nl_attr_get_size(mask_attr), type);
    2380         [ -  + ]:         17 :             if (!ma) {
    2381                 :          0 :                 ma = generate_all_wildcard_mask(ovs_vxlan_ext_attr_lens,
    2382                 :            :                                                 OVS_VXLAN_EXT_MAX,
    2383                 :            :                                                 &ofp, a);
    2384                 :            :             }
    2385                 :            :         }
    2386                 :            : 
    2387         [ -  + ]:         17 :         if (!check_attr_len(ds, a, ma, ovs_vxlan_ext_attr_lens,
    2388                 :            :                             OVS_VXLAN_EXT_MAX, true)) {
    2389                 :          0 :             continue;
    2390                 :            :         }
    2391                 :            : 
    2392         [ +  - ]:         17 :         switch (type) {
    2393                 :            :         case OVS_VXLAN_EXT_GBP: {
    2394                 :         17 :             uint32_t key = nl_attr_get_u32(a);
    2395                 :            :             ovs_be16 id, id_mask;
    2396                 :         17 :             uint8_t flags, flags_mask = 0;
    2397                 :            : 
    2398                 :         17 :             id = htons(key & 0xFFFF);
    2399                 :         17 :             flags = (key >> 16) & 0xFF;
    2400         [ +  - ]:         17 :             if (ma) {
    2401                 :         17 :                 uint32_t mask = nl_attr_get_u32(ma);
    2402                 :         17 :                 id_mask = htons(mask & 0xFFFF);
    2403                 :         17 :                 flags_mask = (mask >> 16) & 0xFF;
    2404                 :            :             }
    2405                 :            : 
    2406                 :         17 :             ds_put_cstr(ds, "gbp(");
    2407         [ +  - ]:         17 :             format_be16(ds, "id", id, ma ? &id_mask : NULL, verbose);
    2408         [ +  - ]:         17 :             format_u8x(ds, "flags", flags, ma ? &flags_mask : NULL, verbose);
    2409                 :         17 :             ds_chomp(ds, ',');
    2410                 :         17 :             ds_put_cstr(ds, "),");
    2411                 :         17 :             break;
    2412                 :            :         }
    2413                 :            : 
    2414                 :            :         default:
    2415                 :          0 :             format_unknown_key(ds, a, ma);
    2416                 :            :         }
    2417                 :         17 :         ofpbuf_clear(&ofp);
    2418                 :            :     }
    2419                 :            : 
    2420                 :         17 :     ds_chomp(ds, ',');
    2421                 :         17 :     ofpbuf_uninit(&ofp);
    2422                 :         17 : }
    2423                 :            : 
    2424                 :            : #define MASK(PTR, FIELD) PTR ? &PTR->FIELD : NULL
    2425                 :            : 
    2426                 :            : static void
    2427                 :         31 : format_geneve_opts(const struct geneve_opt *opt,
    2428                 :            :                    const struct geneve_opt *mask, int opts_len,
    2429                 :            :                    struct ds *ds, bool verbose)
    2430                 :            : {
    2431         [ +  + ]:         82 :     while (opts_len > 0) {
    2432                 :            :         unsigned int len;
    2433                 :            :         uint8_t data_len, data_len_mask;
    2434                 :            : 
    2435         [ -  + ]:         51 :         if (opts_len < sizeof *opt) {
    2436                 :          0 :             ds_put_format(ds, "opt len %u less than minimum %"PRIuSIZE,
    2437                 :            :                           opts_len, sizeof *opt);
    2438                 :          0 :             return;
    2439                 :            :         }
    2440                 :            : 
    2441                 :         51 :         data_len = opt->length * 4;
    2442         [ +  + ]:         51 :         if (mask) {
    2443         [ +  - ]:         43 :             if (mask->length == 0x1f) {
    2444                 :         43 :                 data_len_mask = UINT8_MAX;
    2445                 :            :             } else {
    2446                 :          0 :                 data_len_mask = mask->length;
    2447                 :            :             }
    2448                 :            :         }
    2449                 :         51 :         len = sizeof *opt + data_len;
    2450         [ -  + ]:         51 :         if (len > opts_len) {
    2451                 :          0 :             ds_put_format(ds, "opt len %u greater than remaining %u",
    2452                 :            :                           len, opts_len);
    2453                 :          0 :             return;
    2454                 :            :         }
    2455                 :            : 
    2456                 :         51 :         ds_put_char(ds, '{');
    2457         [ +  + ]:         51 :         format_be16x(ds, "class", opt->opt_class, MASK(mask, opt_class),
    2458                 :            :                     verbose);
    2459         [ +  + ]:         51 :         format_u8x(ds, "type", opt->type, MASK(mask, type), verbose);
    2460         [ +  + ]:         51 :         format_u8u(ds, "len", data_len, mask ? &data_len_mask : NULL, verbose);
    2461 [ +  + ][ +  + ]:         51 :         if (data_len &&
    2462 [ +  + ][ +  + ]:         43 :             (verbose || !mask || !is_all_zeros(mask + 1, data_len))) {
    2463                 :         48 :             ds_put_hex(ds, opt + 1, data_len);
    2464 [ +  + ][ +  + ]:         72 :             if (mask && !is_all_ones(mask + 1, data_len)) {
    2465                 :         24 :                 ds_put_char(ds, '/');
    2466                 :         24 :                 ds_put_hex(ds, mask + 1, data_len);
    2467                 :            :             }
    2468                 :            :         } else {
    2469                 :          3 :             ds_chomp(ds, ',');
    2470                 :            :         }
    2471                 :         51 :         ds_put_char(ds, '}');
    2472                 :            : 
    2473                 :         51 :         opt += len / sizeof(*opt);
    2474         [ +  + ]:         51 :         if (mask) {
    2475                 :         43 :             mask += len / sizeof(*opt);
    2476                 :            :         }
    2477                 :         51 :         opts_len -= len;
    2478                 :            :     };
    2479                 :            : }
    2480                 :            : 
    2481                 :            : static void
    2482                 :         26 : format_odp_tun_geneve(const struct nlattr *attr,
    2483                 :            :                       const struct nlattr *mask_attr, struct ds *ds,
    2484                 :            :                       bool verbose)
    2485                 :            : {
    2486                 :         26 :     int opts_len = nl_attr_get_size(attr);
    2487                 :         26 :     const struct geneve_opt *opt = nl_attr_get(attr);
    2488                 :         26 :     const struct geneve_opt *mask = mask_attr ?
    2489         [ +  + ]:         26 :                                     nl_attr_get(mask_attr) : NULL;
    2490                 :            : 
    2491 [ +  + ][ -  + ]:         26 :     if (mask && nl_attr_get_size(attr) != nl_attr_get_size(mask_attr)) {
    2492                 :          0 :         ds_put_format(ds, "value len %"PRIuSIZE" different from mask len %"PRIuSIZE,
    2493                 :            :                       nl_attr_get_size(attr), nl_attr_get_size(mask_attr));
    2494                 :          0 :         return;
    2495                 :            :     }
    2496                 :            : 
    2497                 :         26 :     format_geneve_opts(opt, mask, opts_len, ds, verbose);
    2498                 :            : }
    2499                 :            : 
    2500                 :            : static void
    2501                 :        202 : format_odp_tun_attr(const struct nlattr *attr, const struct nlattr *mask_attr,
    2502                 :            :                     struct ds *ds, bool verbose)
    2503                 :            : {
    2504                 :            :     unsigned int left;
    2505                 :            :     const struct nlattr *a;
    2506                 :        202 :     uint16_t flags = 0;
    2507                 :        202 :     uint16_t mask_flags = 0;
    2508                 :            :     struct ofpbuf ofp;
    2509                 :            : 
    2510                 :        202 :     ofpbuf_init(&ofp, 100);
    2511         [ +  + ]:       1248 :     NL_NESTED_FOR_EACH(a, left, attr) {
    2512                 :       1046 :         enum ovs_tunnel_key_attr type = nl_attr_type(a);
    2513                 :       1046 :         const struct nlattr *ma = NULL;
    2514                 :            : 
    2515         [ +  + ]:       1046 :         if (mask_attr) {
    2516                 :        445 :             ma = nl_attr_find__(nl_attr_get(mask_attr),
    2517                 :            :                                 nl_attr_get_size(mask_attr), type);
    2518         [ +  + ]:        445 :             if (!ma) {
    2519                 :         14 :                 ma = generate_all_wildcard_mask(ovs_tun_key_attr_lens,
    2520                 :            :                                                 OVS_TUNNEL_KEY_ATTR_MAX,
    2521                 :            :                                                 &ofp, a);
    2522                 :            :             }
    2523                 :            :         }
    2524                 :            : 
    2525         [ -  + ]:       1046 :         if (!check_attr_len(ds, a, ma, ovs_tun_key_attr_lens,
    2526                 :            :                             OVS_TUNNEL_KEY_ATTR_MAX, true)) {
    2527                 :          0 :             continue;
    2528                 :            :         }
    2529                 :            : 
    2530   [ +  +  +  +  :       1046 :         switch (type) {
          +  +  +  +  +  
          +  +  +  +  +  
                   -  - ]
    2531                 :            :         case OVS_TUNNEL_KEY_ATTR_ID:
    2532         [ +  + ]:        194 :             format_be64(ds, "tun_id", nl_attr_get_be64(a),
    2533                 :            :                         ma ? nl_attr_get(ma) : NULL, verbose);
    2534                 :        194 :         flags |= FLOW_TNL_F_KEY;
    2535         [ +  + ]:        194 :             if (ma) {
    2536                 :         75 :                 mask_flags |= FLOW_TNL_F_KEY;
    2537                 :            :             }
    2538                 :        194 :             break;
    2539                 :            :         case OVS_TUNNEL_KEY_ATTR_IPV4_SRC:
    2540         [ +  + ]:        166 :             format_ipv4(ds, "src", nl_attr_get_be32(a),
    2541                 :            :                         ma ? nl_attr_get(ma) : NULL, verbose);
    2542                 :        166 :             break;
    2543                 :            :         case OVS_TUNNEL_KEY_ATTR_IPV4_DST:
    2544         [ +  + ]:        200 :             format_ipv4(ds, "dst", nl_attr_get_be32(a),
    2545                 :            :                         ma ? nl_attr_get(ma) : NULL, verbose);
    2546                 :        200 :             break;
    2547                 :            :         case OVS_TUNNEL_KEY_ATTR_IPV6_SRC: {
    2548                 :            :             struct in6_addr ipv6_src;
    2549                 :          1 :             ipv6_src = nl_attr_get_in6_addr(a);
    2550         [ +  - ]:          1 :             format_in6_addr(ds, "ipv6_src", &ipv6_src,
    2551                 :            :                             ma ? nl_attr_get(ma) : NULL, verbose);
    2552                 :          1 :             break;
    2553                 :            :         }
    2554                 :            :         case OVS_TUNNEL_KEY_ATTR_IPV6_DST: {
    2555                 :            :             struct in6_addr ipv6_dst;
    2556                 :          2 :             ipv6_dst = nl_attr_get_in6_addr(a);
    2557         [ +  + ]:          2 :             format_in6_addr(ds, "ipv6_dst", &ipv6_dst,
    2558                 :            :                             ma ? nl_attr_get(ma) : NULL, verbose);
    2559                 :          2 :             break;
    2560                 :            :         }
    2561                 :            :         case OVS_TUNNEL_KEY_ATTR_TOS:
    2562         [ +  + ]:         72 :             format_u8x(ds, "tos", nl_attr_get_u8(a),
    2563                 :            :                        ma ? nl_attr_get(ma) : NULL, verbose);
    2564                 :         72 :             break;
    2565                 :            :         case OVS_TUNNEL_KEY_ATTR_TTL:
    2566         [ +  + ]:        202 :             format_u8u(ds, "ttl", nl_attr_get_u8(a),
    2567                 :            :                        ma ? nl_attr_get(ma) : NULL, verbose);
    2568                 :        202 :             break;
    2569                 :            :         case OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT:
    2570                 :         53 :         flags |= FLOW_TNL_F_DONT_FRAGMENT;
    2571                 :         53 :             break;
    2572                 :            :         case OVS_TUNNEL_KEY_ATTR_CSUM:
    2573                 :         82 :         flags |= FLOW_TNL_F_CSUM;
    2574                 :         82 :             break;
    2575                 :            :         case OVS_TUNNEL_KEY_ATTR_TP_SRC:
    2576         [ +  - ]:          7 :             format_be16(ds, "tp_src", nl_attr_get_be16(a),
    2577                 :            :                         ma ? nl_attr_get(ma) : NULL, verbose);
    2578                 :          7 :             break;
    2579                 :            :         case OVS_TUNNEL_KEY_ATTR_TP_DST:
    2580         [ +  - ]:          7 :             format_be16(ds, "tp_dst", nl_attr_get_be16(a),
    2581                 :            :                         ma ? nl_attr_get(ma) : NULL, verbose);
    2582                 :          7 :             break;
    2583                 :            :         case OVS_TUNNEL_KEY_ATTR_OAM:
    2584                 :         17 :         flags |= FLOW_TNL_F_OAM;
    2585                 :         17 :             break;
    2586                 :            :         case OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS:
    2587                 :         17 :             ds_put_cstr(ds, "vxlan(");
    2588                 :         17 :             format_odp_tun_vxlan_opt(a, ma, ds, verbose);
    2589                 :         17 :             ds_put_cstr(ds, "),");
    2590                 :         17 :             break;
    2591                 :            :         case OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS:
    2592                 :         26 :             ds_put_cstr(ds, "geneve(");
    2593                 :         26 :             format_odp_tun_geneve(a, ma, ds, verbose);
    2594                 :         26 :             ds_put_cstr(ds, "),");
    2595                 :         26 :             break;
    2596                 :            :         case OVS_TUNNEL_KEY_ATTR_PAD:
    2597                 :          0 :             break;
    2598                 :            :         case __OVS_TUNNEL_KEY_ATTR_MAX:
    2599                 :            :         default:
    2600                 :          0 :             format_unknown_key(ds, a, ma);
    2601                 :            :         }
    2602                 :       1046 :         ofpbuf_clear(&ofp);
    2603                 :            :     }
    2604                 :            : 
    2605                 :            :     /* Flags can have a valid mask even if the attribute is not set, so
    2606                 :            :      * we need to collect these separately. */
    2607         [ +  + ]:        202 :     if (mask_attr) {
    2608         [ +  + ]:        641 :         NL_NESTED_FOR_EACH(a, left, mask_attr) {
    2609   [ +  +  +  + ]:        566 :             switch (nl_attr_type(a)) {
    2610                 :            :             case OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT:
    2611                 :         75 :                 mask_flags |= FLOW_TNL_F_DONT_FRAGMENT;
    2612                 :         75 :                 break;
    2613                 :            :             case OVS_TUNNEL_KEY_ATTR_CSUM:
    2614                 :         75 :                 mask_flags |= FLOW_TNL_F_CSUM;
    2615                 :         75 :                 break;
    2616                 :            :             case OVS_TUNNEL_KEY_ATTR_OAM:
    2617                 :         51 :                 mask_flags |= FLOW_TNL_F_OAM;
    2618                 :         51 :                 break;
    2619                 :            :             }
    2620                 :            :         }
    2621                 :            :     }
    2622                 :            : 
    2623         [ +  + ]:        202 :     format_tun_flags(ds, "flags", flags, mask_attr ? &mask_flags : NULL,
    2624                 :            :                      verbose);
    2625                 :        202 :     ds_chomp(ds, ',');
    2626                 :        202 :     ofpbuf_uninit(&ofp);
    2627                 :        202 : }
    2628                 :            : 
    2629                 :            : static const char *
    2630                 :       6404 : odp_ct_state_to_string(uint32_t flag)
    2631                 :            : {
    2632   [ +  +  +  +  :       6404 :     switch (flag) {
             +  +  +  +  
                      - ]
    2633                 :            :     case OVS_CS_F_REPLY_DIR:
    2634                 :        802 :         return "rpl";
    2635                 :            :     case OVS_CS_F_TRACKED:
    2636                 :        837 :         return "trk";
    2637                 :            :     case OVS_CS_F_NEW:
    2638                 :        813 :         return "new";
    2639                 :            :     case OVS_CS_F_ESTABLISHED:
    2640                 :        808 :         return "est";
    2641                 :            :     case OVS_CS_F_RELATED:
    2642                 :        792 :         return "rel";
    2643                 :            :     case OVS_CS_F_INVALID:
    2644                 :        800 :         return "inv";
    2645                 :            :     case OVS_CS_F_SRC_NAT:
    2646                 :        776 :         return "snat";
    2647                 :            :     case OVS_CS_F_DST_NAT:
    2648                 :        776 :         return "dnat";
    2649                 :            :     default:
    2650                 :          0 :         return NULL;
    2651                 :            :     }
    2652                 :            : }
    2653                 :            : 
    2654                 :            : static void
    2655                 :       1879 : format_frag(struct ds *ds, const char *name, uint8_t key,
    2656                 :            :             const uint8_t *mask, bool verbose)
    2657                 :            : {
    2658 [ +  + ][ +  + ]:       1879 :     bool mask_empty = mask && !*mask;
    2659                 :            : 
    2660                 :            :     /* ODP frag is an enumeration field; partial masks are not meaningful. */
    2661 [ +  + ][ +  + ]:       1879 :     if (verbose || !mask_empty) {
    2662 [ +  + ][ +  - ]:       1839 :         bool mask_full = !mask || *mask == UINT8_MAX;
    2663                 :            : 
    2664         [ -  + ]:       1839 :         if (!mask_full) { /* Partially masked. */
    2665                 :          0 :             ds_put_format(ds, "error: partial mask not supported for frag (%#"
    2666                 :          0 :                           PRIx8"),", *mask);
    2667                 :            :         } else {
    2668                 :       1839 :             ds_put_format(ds, "%s=%s,", name, ovs_frag_type_to_string(key));
    2669                 :            :         }
    2670                 :            :     }
    2671                 :       1879 : }
    2672                 :            : 
    2673                 :            : static bool
    2674                 :       2503 : mask_empty(const struct nlattr *ma)
    2675                 :            : {
    2676                 :            :     const void *mask;
    2677                 :            :     size_t n;
    2678                 :            : 
    2679         [ -  + ]:       2503 :     if (!ma) {
    2680                 :          0 :         return true;
    2681                 :            :     }
    2682                 :       2503 :     mask = nl_attr_get(ma);
    2683                 :       2503 :     n = nl_attr_get_size(ma);
    2684                 :            : 
    2685                 :       2503 :     return is_all_zeros(mask, n);
    2686                 :            : }
    2687                 :            : 
    2688                 :            : static void
    2689                 :      23501 : format_odp_key_attr(const struct nlattr *a, const struct nlattr *ma,
    2690                 :            :                     const struct hmap *portno_names, struct ds *ds,
    2691                 :            :                     bool verbose)
    2692                 :            : {
    2693                 :      23501 :     enum ovs_key_attr attr = nl_attr_type(a);
    2694                 :            :     char namebuf[OVS_KEY_ATTR_BUFSIZE];
    2695                 :            :     bool is_exact;
    2696                 :            : 
    2697 [ +  + ][ +  + ]:      23501 :     is_exact = ma ? odp_mask_attr_is_exact(ma) : true;
    2698                 :            : 
    2699                 :      23501 :     ds_put_cstr(ds, ovs_key_attr_to_string(attr, namebuf, sizeof namebuf));
    2700                 :            : 
    2701         [ -  + ]:      23501 :     if (!check_attr_len(ds, a, ma, ovs_flow_key_attr_lens,
    2702                 :            :                         OVS_KEY_ATTR_MAX, false)) {
    2703                 :          0 :         return;
    2704                 :            :     }
    2705                 :            : 
    2706                 :      23501 :     ds_put_char(ds, '(');
    2707   [ +  +  +  +  :      23501 :     switch (attr) {
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
                   +  - ]
    2708                 :            :     case OVS_KEY_ATTR_ENCAP:
    2709 [ +  + ][ +  + ]:        265 :         if (ma && nl_attr_get_size(ma) && nl_attr_get_size(a)) {
                 [ +  - ]
    2710                 :         82 :             odp_flow_format(nl_attr_get(a), nl_attr_get_size(a),
    2711                 :         41 :                             nl_attr_get(ma), nl_attr_get_size(ma), NULL, ds,
    2712                 :            :                             verbose);
    2713         [ +  + ]:        224 :         } else if (nl_attr_get_size(a)) {
    2714                 :        219 :             odp_flow_format(nl_attr_get(a), nl_attr_get_size(a), NULL, 0, NULL,
    2715                 :            :                             ds, verbose);
    2716                 :            :         }
    2717                 :        265 :         break;
    2718                 :            : 
    2719                 :            :     case OVS_KEY_ATTR_PRIORITY:
    2720                 :            :     case OVS_KEY_ATTR_SKB_MARK:
    2721                 :            :     case OVS_KEY_ATTR_DP_HASH:
    2722                 :            :     case OVS_KEY_ATTR_RECIRC_ID:
    2723                 :       6048 :         ds_put_format(ds, "%#"PRIx32, nl_attr_get_u32(a));
    2724         [ +  + ]:       6048 :         if (!is_exact) {
    2725                 :        231 :             ds_put_format(ds, "/%#"PRIx32, nl_attr_get_u32(ma));
    2726                 :            :         }
    2727                 :       6048 :         break;
    2728                 :            : 
    2729                 :            :     case OVS_KEY_ATTR_CT_MARK:
    2730 [ +  + ][ +  - ]:       1412 :         if (verbose || !mask_empty(ma)) {
    2731                 :       1412 :             ds_put_format(ds, "%#"PRIx32, nl_attr_get_u32(a));
    2732         [ +  + ]:       1412 :             if (!is_exact) {
    2733                 :         87 :                 ds_put_format(ds, "/%#"PRIx32, nl_attr_get_u32(ma));
    2734                 :            :             }
    2735                 :            :         }
    2736                 :       1412 :         break;
    2737                 :            : 
    2738                 :            :     case OVS_KEY_ATTR_CT_STATE:
    2739         [ +  + ]:       1439 :         if (verbose) {
    2740                 :        618 :                 ds_put_format(ds, "%#"PRIx32, nl_attr_get_u32(a));
    2741         [ +  + ]:        618 :                 if (!is_exact) {
    2742         [ +  + ]:        618 :                     ds_put_format(ds, "/%#"PRIx32,
    2743                 :         96 :                                   mask_empty(ma) ? 0 : nl_attr_get_u32(ma));
    2744                 :            :                 }
    2745         [ +  - ]:        821 :         } else if (!is_exact) {
    2746         [ -  + ]:        821 :             format_flags_masked(ds, NULL, odp_ct_state_to_string,
    2747                 :            :                                 nl_attr_get_u32(a),
    2748                 :        821 :                                 mask_empty(ma) ? 0 : nl_attr_get_u32(ma),
    2749                 :            :                                 UINT32_MAX);
    2750                 :            :         } else {
    2751                 :          0 :             format_flags(ds, odp_ct_state_to_string, nl_attr_get_u32(a), '|');
    2752                 :            :         }
    2753                 :       1439 :         break;
    2754                 :            : 
    2755                 :            :     case OVS_KEY_ATTR_CT_ZONE:
    2756 [ +  + ][ +  - ]:       1410 :         if (verbose || !mask_empty(ma)) {
    2757                 :       1410 :             ds_put_format(ds, "%#"PRIx16, nl_attr_get_u16(a));
    2758         [ +  + ]:       1410 :             if (!is_exact) {
    2759                 :         85 :                 ds_put_format(ds, "/%#"PRIx16, nl_attr_get_u16(ma));
    2760                 :            :             }
    2761                 :            :         }
    2762                 :       1410 :         break;
    2763                 :            : 
    2764                 :            :     case OVS_KEY_ATTR_CT_LABELS: {
    2765                 :       1411 :         const ovs_u128 *value = nl_attr_get(a);
    2766         [ +  + ]:       1411 :         const ovs_u128 *mask = ma ? nl_attr_get(ma) : NULL;
    2767                 :            : 
    2768                 :       1411 :         format_u128(ds, value, mask, verbose);
    2769                 :       1411 :         break;
    2770                 :            :     }
    2771                 :            : 
    2772                 :            :     case OVS_KEY_ATTR_TUNNEL:
    2773                 :        202 :         format_odp_tun_attr(a, ma, ds, verbose);
    2774                 :        202 :         break;
    2775                 :            : 
    2776                 :            :     case OVS_KEY_ATTR_IN_PORT:
    2777 [ +  + ][ +  + ]:       2214 :         if (portno_names && verbose && is_exact) {
                 [ +  - ]
    2778                 :          7 :             char *name = odp_portno_names_get(portno_names,
    2779                 :            :                             u32_to_odp(nl_attr_get_u32(a)));
    2780         [ +  - ]:          7 :             if (name) {
    2781                 :          7 :                 ds_put_format(ds, "%s", name);
    2782                 :            :             } else {
    2783                 :          0 :                 ds_put_format(ds, "%"PRIu32, nl_attr_get_u32(a));
    2784                 :            :             }
    2785                 :            :         } else {
    2786                 :       2200 :             ds_put_format(ds, "%"PRIu32, nl_attr_get_u32(a));
    2787         [ +  + ]:       2200 :             if (!is_exact) {
    2788                 :          9 :                 ds_put_format(ds, "/%#"PRIx32, nl_attr_get_u32(ma));
    2789                 :            :             }
    2790                 :            :         }
    2791                 :       2207 :         break;
    2792                 :            : 
    2793                 :            :     case OVS_KEY_ATTR_ETHERNET: {
    2794         [ +  + ]:       2048 :         const struct ovs_key_ethernet *mask = ma ? nl_attr_get(ma) : NULL;
    2795                 :       2048 :         const struct ovs_key_ethernet *key = nl_attr_get(a);
    2796                 :            : 
    2797         [ +  + ]:       2048 :         format_eth(ds, "src", key->eth_src, MASK(mask, eth_src), verbose);
    2798         [ +  + ]:       2048 :         format_eth(ds, "dst", key->eth_dst, MASK(mask, eth_dst), verbose);
    2799                 :       2048 :         ds_chomp(ds, ',');
    2800                 :       2048 :         break;
    2801                 :            :     }
    2802                 :            :     case OVS_KEY_ATTR_VLAN:
    2803         [ +  + ]:        308 :         format_vlan_tci(ds, nl_attr_get_be16(a),
    2804                 :         43 :                         ma ? nl_attr_get_be16(ma) : OVS_BE16_MAX, verbose);
    2805                 :        265 :         break;
    2806                 :            : 
    2807                 :            :     case OVS_KEY_ATTR_MPLS: {
    2808                 :         57 :         const struct ovs_key_mpls *mpls_key = nl_attr_get(a);
    2809                 :         57 :         const struct ovs_key_mpls *mpls_mask = NULL;
    2810                 :         57 :         size_t size = nl_attr_get_size(a);
    2811                 :            : 
    2812 [ +  - ][ -  + ]:         57 :         if (!size || size % sizeof *mpls_key) {
    2813                 :          0 :             ds_put_format(ds, "(bad key length %"PRIuSIZE")", size);
    2814                 :          0 :             return;
    2815                 :            :         }
    2816         [ +  + ]:         57 :         if (!is_exact) {
    2817                 :          3 :             mpls_mask = nl_attr_get(ma);
    2818         [ -  + ]:          3 :             if (size != nl_attr_get_size(ma)) {
    2819                 :          0 :                 ds_put_format(ds, "(key length %"PRIuSIZE" != "
    2820                 :            :                               "mask length %"PRIuSIZE")",
    2821                 :            :                               size, nl_attr_get_size(ma));
    2822                 :          0 :                 return;
    2823                 :            :             }
    2824                 :            :         }
    2825                 :         57 :         format_mpls(ds, mpls_key, mpls_mask, size / sizeof *mpls_key);
    2826                 :         57 :         break;
    2827                 :            :     }
    2828                 :            :     case OVS_KEY_ATTR_ETHERTYPE:
    2829                 :       2456 :         ds_put_format(ds, "0x%04"PRIx16, ntohs(nl_attr_get_be16(a)));
    2830         [ +  + ]:       2456 :         if (!is_exact) {
    2831                 :         10 :             ds_put_format(ds, "/0x%04"PRIx16, ntohs(nl_attr_get_be16(ma)));
    2832                 :            :         }
    2833                 :       2456 :         break;
    2834                 :            : 
    2835                 :            :     case OVS_KEY_ATTR_IPV4: {
    2836                 :       1667 :         const struct ovs_key_ipv4 *key = nl_attr_get(a);
    2837         [ +  + ]:       1667 :         const struct ovs_key_ipv4 *mask = ma ? nl_attr_get(ma) : NULL;
    2838                 :            : 
    2839         [ +  + ]:       1667 :         format_ipv4(ds, "src", key->ipv4_src, MASK(mask, ipv4_src), verbose);
    2840         [ +  + ]:       1667 :         format_ipv4(ds, "dst", key->ipv4_dst, MASK(mask, ipv4_dst), verbose);
    2841         [ +  + ]:       1667 :         format_u8u(ds, "proto", key->ipv4_proto, MASK(mask, ipv4_proto),
    2842                 :            :                       verbose);
    2843         [ +  + ]:       1667 :         format_u8x(ds, "tos", key->ipv4_tos, MASK(mask, ipv4_tos), verbose);
    2844         [ +  + ]:       1667 :         format_u8u(ds, "ttl", key->ipv4_ttl, MASK(mask, ipv4_ttl), verbose);
    2845         [ +  + ]:       1667 :         format_frag(ds, "frag", key->ipv4_frag, MASK(mask, ipv4_frag),
    2846                 :            :                     verbose);
    2847                 :       1667 :         ds_chomp(ds, ',');
    2848                 :       1667 :         break;
    2849                 :            :     }
    2850                 :            :     case OVS_KEY_ATTR_IPV6: {
    2851                 :        212 :         const struct ovs_key_ipv6 *key = nl_attr_get(a);
    2852         [ +  + ]:        212 :         const struct ovs_key_ipv6 *mask = ma ? nl_attr_get(ma) : NULL;
    2853                 :            : 
    2854         [ +  + ]:        212 :         format_ipv6(ds, "src", key->ipv6_src, MASK(mask, ipv6_src), verbose);
    2855         [ +  + ]:        212 :         format_ipv6(ds, "dst", key->ipv6_dst, MASK(mask, ipv6_dst), verbose);
    2856         [ +  + ]:        212 :         format_ipv6_label(ds, "label", key->ipv6_label, MASK(mask, ipv6_label),
    2857                 :            :                           verbose);
    2858         [ +  + ]:        212 :         format_u8u(ds, "proto", key->ipv6_proto, MASK(mask, ipv6_proto),
    2859                 :            :                       verbose);
    2860         [ +  + ]:        212 :         format_u8x(ds, "tclass", key->ipv6_tclass, MASK(mask, ipv6_tclass),
    2861                 :            :                       verbose);
    2862         [ +  + ]:        212 :         format_u8u(ds, "hlimit", key->ipv6_hlimit, MASK(mask, ipv6_hlimit),
    2863                 :            :                       verbose);
    2864         [ +  + ]:        212 :         format_frag(ds, "frag", key->ipv6_frag, MASK(mask, ipv6_frag),
    2865                 :            :                     verbose);
    2866                 :        212 :         ds_chomp(ds, ',');
    2867                 :        212 :         break;
    2868                 :            :     }
    2869                 :            :         /* These have the same structure and format. */
    2870                 :            :     case OVS_KEY_ATTR_TCP:
    2871                 :            :     case OVS_KEY_ATTR_UDP:
    2872                 :            :     case OVS_KEY_ATTR_SCTP: {
    2873                 :       1073 :         const struct ovs_key_tcp *key = nl_attr_get(a);
    2874         [ +  + ]:       1073 :         const struct ovs_key_tcp *mask = ma ? nl_attr_get(ma) : NULL;
    2875                 :            : 
    2876         [ +  + ]:       1073 :         format_be16(ds, "src", key->tcp_src, MASK(mask, tcp_src), verbose);
    2877         [ +  + ]:       1073 :         format_be16(ds, "dst", key->tcp_dst, MASK(mask, tcp_dst), verbose);
    2878                 :       1073 :         ds_chomp(ds, ',');
    2879                 :       1073 :         break;
    2880                 :            :     }
    2881                 :            :     case OVS_KEY_ATTR_TCP_FLAGS:
    2882         [ +  + ]:        788 :         if (!is_exact) {
    2883                 :          2 :             format_flags_masked(ds, NULL, packet_tcp_flag_to_string,
    2884                 :          2 :                                 ntohs(nl_attr_get_be16(a)),
    2885                 :          2 :                                 TCP_FLAGS(nl_attr_get_be16(ma)),
    2886                 :          2 :                                 TCP_FLAGS(OVS_BE16_MAX));
    2887                 :            :         } else {
    2888                 :        786 :             format_flags(ds, packet_tcp_flag_to_string,
    2889                 :        786 :                          ntohs(nl_attr_get_be16(a)), '|');
    2890                 :            :         }
    2891                 :        788 :         break;
    2892                 :            : 
    2893                 :            :     case OVS_KEY_ATTR_ICMP: {
    2894                 :        293 :         const struct ovs_key_icmp *key = nl_attr_get(a);
    2895         [ +  + ]:        293 :         const struct ovs_key_icmp *mask = ma ? nl_attr_get(ma) : NULL;
    2896                 :            : 
    2897         [ +  + ]:        293 :         format_u8u(ds, "type", key->icmp_type, MASK(mask, icmp_type), verbose);
    2898         [ +  + ]:        293 :         format_u8u(ds, "code", key->icmp_code, MASK(mask, icmp_code), verbose);
    2899                 :        293 :         ds_chomp(ds, ',');
    2900                 :        293 :         break;
    2901                 :            :     }
    2902                 :            :     case OVS_KEY_ATTR_ICMPV6: {
    2903                 :         91 :         const struct ovs_key_icmpv6 *key = nl_attr_get(a);
    2904         [ +  + ]:         91 :         const struct ovs_key_icmpv6 *mask = ma ? nl_attr_get(ma) : NULL;
    2905                 :            : 
    2906         [ +  + ]:         91 :         format_u8u(ds, "type", key->icmpv6_type, MASK(mask, icmpv6_type),
    2907                 :            :                    verbose);
    2908         [ +  + ]:         91 :         format_u8u(ds, "code", key->icmpv6_code, MASK(mask, icmpv6_code),
    2909                 :            :                    verbose);
    2910                 :         91 :         ds_chomp(ds, ',');
    2911                 :         91 :         break;
    2912                 :            :     }
    2913                 :            :     case OVS_KEY_ATTR_ARP: {
    2914         [ +  + ]:         89 :         const struct ovs_key_arp *mask = ma ? nl_attr_get(ma) : NULL;
    2915                 :         89 :         const struct ovs_key_arp *key = nl_attr_get(a);
    2916                 :            : 
    2917         [ +  + ]:         89 :         format_ipv4(ds, "sip", key->arp_sip, MASK(mask, arp_sip), verbose);
    2918         [ +  + ]:         89 :         format_ipv4(ds, "tip", key->arp_tip, MASK(mask, arp_tip), verbose);
    2919         [ +  + ]:         89 :         format_be16(ds, "op", key->arp_op, MASK(mask, arp_op), verbose);
    2920         [ +  + ]:         89 :         format_eth(ds, "sha", key->arp_sha, MASK(mask, arp_sha), verbose);
    2921         [ +  + ]:         89 :         format_eth(ds, "tha", key->arp_tha, MASK(mask, arp_tha), verbose);
    2922                 :         89 :         ds_chomp(ds, ',');
    2923                 :         89 :         break;
    2924                 :            :     }
    2925                 :            :     case OVS_KEY_ATTR_ND: {
    2926         [ +  + ]:         68 :         const struct ovs_key_nd *mask = ma ? nl_attr_get(ma) : NULL;
    2927                 :         68 :         const struct ovs_key_nd *key = nl_attr_get(a);
    2928                 :            : 
    2929         [ +  + ]:         68 :         format_ipv6(ds, "target", key->nd_target, MASK(mask, nd_target),
    2930                 :            :                     verbose);
    2931         [ +  + ]:         68 :         format_eth(ds, "sll", key->nd_sll, MASK(mask, nd_sll), verbose);
    2932         [ +  + ]:         68 :         format_eth(ds, "tll", key->nd_tll, MASK(mask, nd_tll), verbose);
    2933                 :            : 
    2934                 :         68 :         ds_chomp(ds, ',');
    2935                 :         68 :         break;
    2936                 :            :     }
    2937                 :            :     case OVS_KEY_ATTR_UNSPEC:
    2938                 :            :     case __OVS_KEY_ATTR_MAX:
    2939                 :            :     default:
    2940                 :          0 :         format_generic_odp_key(a, ds);
    2941         [ #  # ]:          0 :         if (!is_exact) {
    2942                 :          0 :             ds_put_char(ds, '/');
    2943                 :          0 :             format_generic_odp_key(ma, ds);
    2944                 :            :         }
    2945                 :          0 :         break;
    2946                 :            :     }
    2947                 :      23501 :     ds_put_char(ds, ')');
    2948                 :            : }
    2949                 :            : 
    2950                 :            : static struct nlattr *
    2951                 :         16 : generate_all_wildcard_mask(const struct attr_len_tbl tbl[], int max,
    2952                 :            :                            struct ofpbuf *ofp, const struct nlattr *key)
    2953                 :            : {
    2954                 :            :     const struct nlattr *a;
    2955                 :            :     unsigned int left;
    2956                 :         16 :     int type = nl_attr_type(key);
    2957                 :         16 :     int size = nl_attr_get_size(key);
    2958                 :            : 
    2959         [ +  - ]:         16 :     if (odp_key_attr_len(tbl, max, type) != ATTR_LEN_NESTED) {
    2960                 :         16 :         nl_msg_put_unspec_zero(ofp, type, size);
    2961                 :            :     } else {
    2962                 :            :         size_t nested_mask;
    2963                 :            : 
    2964         [ #  # ]:          0 :         if (tbl[type].next) {
    2965                 :          0 :             tbl = tbl[type].next;
    2966                 :          0 :             max = tbl[type].next_max;
    2967                 :            :         }
    2968                 :            : 
    2969                 :          0 :         nested_mask = nl_msg_start_nested(ofp, type);
    2970         [ #  # ]:          0 :         NL_ATTR_FOR_EACH(a, left, key, nl_attr_get_size(key)) {
    2971                 :          0 :             generate_all_wildcard_mask(tbl, max, ofp, nl_attr_get(a));
    2972                 :            :         }
    2973                 :          0 :         nl_msg_end_nested(ofp, nested_mask);
    2974                 :            :     }
    2975                 :            : 
    2976                 :         16 :     return ofp->base;
    2977                 :            : }
    2978                 :            : 
    2979                 :            : static void
    2980                 :       1415 : format_u128(struct ds *ds, const ovs_u128 *key, const ovs_u128 *mask,
    2981                 :            :             bool verbose)
    2982                 :            : {
    2983 [ +  + ][ +  - ]:       1415 :     if (verbose || (mask && !ovs_u128_is_zero(*mask))) {
                 [ +  - ]
    2984                 :            :         ovs_be128 value;
    2985                 :            : 
    2986                 :       1415 :         value = hton128(*key);
    2987                 :       1415 :         ds_put_hex(ds, &value, sizeof value);
    2988 [ +  + ][ +  + ]:       1415 :         if (mask && !(ovs_u128_is_ones(*mask))) {
    2989                 :         86 :             value = hton128(*mask);
    2990                 :         86 :             ds_put_char(ds, '/');
    2991                 :       1415 :             ds_put_hex(ds, &value, sizeof value);
    2992                 :            :         }
    2993                 :            :     }
    2994                 :       1415 : }
    2995                 :            : 
    2996                 :            : /* Read the string from 's_' as a 128-bit value.  If the string contains
    2997                 :            :  * a "/", the rest of the string will be treated as a 128-bit mask.
    2998                 :            :  *
    2999                 :            :  * If either the value or mask is larger than 64 bits, the string must
    3000                 :            :  * be in hexadecimal.
    3001                 :            :  */
    3002                 :            : static int
    3003                 :         43 : scan_u128(const char *s_, ovs_u128 *value, ovs_u128 *mask)
    3004                 :            : {
    3005                 :         43 :     char *s = CONST_CAST(char *, s_);
    3006                 :            :     ovs_be128 be_value;
    3007                 :            :     ovs_be128 be_mask;
    3008                 :            : 
    3009         [ +  - ]:         43 :     if (!parse_int_string(s, (uint8_t *)&be_value, sizeof be_value, &s)) {
    3010                 :         43 :         *value = ntoh128(be_value);
    3011                 :            : 
    3012         [ +  - ]:         43 :         if (mask) {
    3013                 :            :             int n;
    3014                 :            : 
    3015         [ +  + ]:         43 :             if (ovs_scan(s, "/%n", &n)) {
    3016                 :            :                 int error;
    3017                 :            : 
    3018                 :         18 :                 s += n;
    3019                 :         18 :                 error = parse_int_string(s, (uint8_t *)&be_mask,
    3020                 :            :                                          sizeof be_mask, &s);
    3021         [ -  + ]:         18 :                 if (error) {
    3022                 :          0 :                     return error;
    3023                 :            :                 }
    3024                 :         18 :                 *mask = ntoh128(be_mask);
    3025                 :            :             } else {
    3026                 :         43 :                 *mask = OVS_U128_MAX;
    3027                 :            :             }
    3028                 :            :         }
    3029                 :         43 :         return s - s_;
    3030                 :            :     }
    3031                 :            : 
    3032                 :         43 :     return 0;
    3033                 :            : }
    3034                 :            : 
    3035                 :            : int
    3036                 :      12713 : odp_ufid_from_string(const char *s_, ovs_u128 *ufid)
    3037                 :            : {
    3038                 :      12713 :     const char *s = s_;
    3039                 :            : 
    3040         [ +  + ]:      12713 :     if (ovs_scan(s, "ufid:")) {
    3041                 :          4 :         s += 5;
    3042                 :            : 
    3043         [ -  + ]:          4 :         if (!uuid_from_string_prefix((struct uuid *)ufid, s)) {
    3044                 :          0 :             return -EINVAL;
    3045                 :            :         }
    3046                 :          4 :         s += UUID_LEN;
    3047                 :            : 
    3048                 :          4 :         return s - s_;
    3049                 :            :     }
    3050                 :            : 
    3051                 :      12709 :     return 0;
    3052                 :            : }
    3053                 :            : 
    3054                 :            : void
    3055                 :        963 : odp_format_ufid(const ovs_u128 *ufid, struct ds *ds)
    3056                 :            : {
    3057                 :        963 :     ds_put_format(ds, "ufid:"UUID_FMT, UUID_ARGS((struct uuid *)ufid));
    3058                 :        963 : }
    3059                 :            : 
    3060                 :            : /* Appends to 'ds' a string representation of the 'key_len' bytes of
    3061                 :            :  * OVS_KEY_ATTR_* attributes in 'key'. If non-null, additionally formats the
    3062                 :            :  * 'mask_len' bytes of 'mask' which apply to 'key'. If 'portno_names' is
    3063                 :            :  * non-null and 'verbose' is true, translates odp port number to its name. */
    3064                 :            : void
    3065                 :       3002 : odp_flow_format(const struct nlattr *key, size_t key_len,
    3066                 :            :                 const struct nlattr *mask, size_t mask_len,
    3067                 :            :                 const struct hmap *portno_names, struct ds *ds, bool verbose)
    3068                 :            : {
    3069         [ +  + ]:       3002 :     if (key_len) {
    3070                 :            :         const struct nlattr *a;
    3071                 :            :         unsigned int left;
    3072                 :       2466 :         bool has_ethtype_key = false;
    3073                 :       2466 :         const struct nlattr *ma = NULL;
    3074                 :            :         struct ofpbuf ofp;
    3075                 :       2466 :         bool first_field = true;
    3076                 :            : 
    3077                 :       2466 :         ofpbuf_init(&ofp, 100);
    3078         [ +  + ]:      29112 :         NL_ATTR_FOR_EACH (a, left, key, key_len) {
    3079                 :            :             bool is_nested_attr;
    3080                 :      26646 :             bool is_wildcard = false;
    3081                 :      26646 :             int attr_type = nl_attr_type(a);
    3082                 :            : 
    3083         [ +  + ]:      26646 :             if (attr_type == OVS_KEY_ATTR_ETHERTYPE) {
    3084                 :       2455 :                 has_ethtype_key = true;
    3085                 :            :             }
    3086                 :            : 
    3087                 :      26646 :             is_nested_attr = odp_key_attr_len(ovs_flow_key_attr_lens,
    3088                 :            :                                               OVS_KEY_ATTR_MAX, attr_type) ==
    3089                 :            :                              ATTR_LEN_NESTED;
    3090                 :            : 
    3091 [ +  + ][ +  - ]:      26646 :             if (mask && mask_len) {
    3092                 :      18612 :                 ma = nl_attr_find__(mask, mask_len, nl_attr_type(a));
    3093 [ +  + ][ +  + ]:      18612 :                 is_wildcard = ma ? odp_mask_attr_is_wildcard(ma) : true;
    3094                 :            :             }
    3095                 :            : 
    3096 [ +  + ][ +  + ]:      26646 :             if (verbose || !is_wildcard  || is_nested_attr) {
                 [ +  + ]
    3097 [ +  + ][ +  + ]:      23314 :                 if (is_wildcard && !ma) {
    3098                 :          2 :                     ma = generate_all_wildcard_mask(ovs_flow_key_attr_lens,
    3099                 :            :                                                     OVS_KEY_ATTR_MAX,
    3100                 :            :                                                     &ofp, a);
    3101                 :            :                 }
    3102         [ +  + ]:      23314 :                 if (!first_field) {
    3103                 :      20848 :                     ds_put_char(ds, ',');
    3104                 :            :                 }
    3105                 :      23314 :                 format_odp_key_attr(a, ma, portno_names, ds, verbose);
    3106                 :      23314 :                 first_field = false;
    3107                 :            :             }
    3108                 :      26646 :             ofpbuf_clear(&ofp);
    3109                 :            :         }
    3110                 :       2466 :         ofpbuf_uninit(&ofp);
    3111                 :            : 
    3112         [ -  + ]:       2466 :         if (left) {
    3113                 :            :             int i;
    3114                 :            : 
    3115         [ #  # ]:          0 :             if (left == key_len) {
    3116                 :          0 :                 ds_put_cstr(ds, "<empty>");
    3117                 :            :             }
    3118                 :          0 :             ds_put_format(ds, ",***%u leftover bytes*** (", left);
    3119         [ #  # ]:          0 :             for (i = 0; i < left; i++) {
    3120                 :          0 :                 ds_put_format(ds, "%02x", ((const uint8_t *) a)[i]);
    3121                 :            :             }
    3122                 :          0 :             ds_put_char(ds, ')');
    3123                 :            :         }
    3124         [ +  + ]:       2466 :         if (!has_ethtype_key) {
    3125                 :         11 :             ma = nl_attr_find__(mask, mask_len, OVS_KEY_ATTR_ETHERTYPE);
    3126         [ -  + ]:         11 :             if (ma) {
    3127                 :       2466 :                 ds_put_format(ds, ",eth_type(0/0x%04"PRIx16")",
    3128                 :          0 :                               ntohs(nl_attr_get_be16(ma)));
    3129                 :            :             }
    3130                 :            :         }
    3131                 :            :     } else {
    3132                 :        536 :         ds_put_cstr(ds, "<empty>");
    3133                 :            :     }
    3134                 :       3002 : }
    3135                 :            : 
    3136                 :            : /* Appends to 'ds' a string representation of the 'key_len' bytes of
    3137                 :            :  * OVS_KEY_ATTR_* attributes in 'key'. */
    3138                 :            : void
    3139                 :        388 : odp_flow_key_format(const struct nlattr *key,
    3140                 :            :                     size_t key_len, struct ds *ds)
    3141                 :            : {
    3142                 :        388 :     odp_flow_format(key, key_len, NULL, 0, NULL, ds, true);
    3143                 :        388 : }
    3144                 :            : 
    3145                 :            : static bool
    3146                 :       1584 : ovs_frag_type_from_string(const char *s, enum ovs_frag_type *type)
    3147                 :            : {
    3148         [ +  + ]:       1584 :     if (!strcasecmp(s, "no")) {
    3149                 :       1504 :         *type = OVS_FRAG_TYPE_NONE;
    3150         [ +  + ]:         80 :     } else if (!strcasecmp(s, "first")) {
    3151                 :         40 :         *type = OVS_FRAG_TYPE_FIRST;
    3152         [ +  - ]:         40 :     } else if (!strcasecmp(s, "later")) {
    3153                 :         40 :         *type = OVS_FRAG_TYPE_LATER;
    3154                 :            :     } else {
    3155                 :          0 :         return false;
    3156                 :            :     }
    3157                 :       1584 :     return true;
    3158                 :            : }
    3159                 :            : 
    3160                 :            : /* Parsing. */
    3161                 :            : 
    3162                 :            : static int
    3163                 :       4612 : scan_eth(const char *s, struct eth_addr *key, struct eth_addr *mask)
    3164                 :            : {
    3165                 :            :     int n;
    3166                 :            : 
    3167         [ +  - ]:       4612 :     if (ovs_scan(s, ETH_ADDR_SCAN_FMT"%n",
    3168                 :            :                  ETH_ADDR_SCAN_ARGS(*key), &n)) {
    3169                 :       4612 :         int len = n;
    3170                 :            : 
    3171         [ +  + ]:       4612 :         if (mask) {
    3172         [ +  + ]:       1738 :             if (ovs_scan(s + len, "/"ETH_ADDR_SCAN_FMT"%n",
    3173                 :            :                          ETH_ADDR_SCAN_ARGS(*mask), &n)) {
    3174                 :         95 :                 len += n;
    3175                 :            :             } else {
    3176                 :       1643 :                 memset(mask, 0xff, sizeof *mask);
    3177                 :            :             }
    3178                 :            :         }
    3179                 :       4612 :         return len;
    3180                 :            :     }
    3181                 :       4612 :     return 0;
    3182                 :            : }
    3183                 :            : 
    3184                 :            : static int
    3185                 :       3319 : scan_ipv4(const char *s, ovs_be32 *key, ovs_be32 *mask)
    3186                 :            : {
    3187                 :            :     int n;
    3188                 :            : 
    3189         [ +  - ]:       3319 :     if (ovs_scan(s, IP_SCAN_FMT"%n", IP_SCAN_ARGS(key), &n)) {
    3190                 :       3319 :         int len = n;
    3191                 :            : 
    3192         [ +  + ]:       3319 :         if (mask) {
    3193         [ +  + ]:       1111 :             if (ovs_scan(s + len, "/"IP_SCAN_FMT"%n",
    3194                 :            :                          IP_SCAN_ARGS(mask), &n)) {
    3195                 :        180 :                 len += n;
    3196                 :            :             } else {
    3197                 :        931 :                 *mask = OVS_BE32_MAX;
    3198                 :            :             }
    3199                 :            :         }
    3200                 :       3319 :         return len;
    3201                 :            :     }
    3202                 :       3319 :     return 0;
    3203                 :            : }
    3204                 :            : 
    3205                 :            : static int
    3206                 :        484 : scan_in6_addr(const char *s, struct in6_addr *key, struct in6_addr *mask)
    3207                 :            : {
    3208                 :            :     int n;
    3209                 :            :     char ipv6_s[IPV6_SCAN_LEN + 1];
    3210                 :            : 
    3211         [ +  - ]:        484 :     if (ovs_scan(s, IPV6_SCAN_FMT"%n", ipv6_s, &n)
    3212         [ +  - ]:        484 :         && inet_pton(AF_INET6, ipv6_s, key) == 1) {
    3213                 :        484 :         int len = n;
    3214                 :            : 
    3215         [ +  + ]:        484 :         if (mask) {
    3216         [ +  + ]:        454 :             if (ovs_scan(s + len, "/"IPV6_SCAN_FMT"%n", ipv6_s, &n)
    3217         [ +  - ]:         74 :                 && inet_pton(AF_INET6, ipv6_s, mask) == 1) {
    3218                 :         74 :                 len += n;
    3219                 :            :             } else {
    3220                 :        380 :                 memset(mask, 0xff, sizeof *mask);
    3221                 :            :             }
    3222                 :            :         }
    3223                 :        484 :         return len;
    3224                 :            :     }
    3225                 :        484 :     return 0;
    3226                 :            : }
    3227                 :            : 
    3228                 :            : static int
    3229                 :        482 : scan_ipv6(const char *s, ovs_be32 (*key)[4], ovs_be32 (*mask)[4])
    3230                 :            : {
    3231                 :        482 :     return scan_in6_addr(s, key ? (struct in6_addr *) *key : NULL,
    3232                 :            :                          mask ? (struct in6_addr *) *mask : NULL);
    3233                 :            : }
    3234                 :            : 
    3235                 :            : static int
    3236                 :        210 : scan_ipv6_label(const char *s, ovs_be32 *key, ovs_be32 *mask)
    3237                 :            : {
    3238                 :            :     int key_, mask_;
    3239                 :            :     int n;
    3240                 :            : 
    3241         [ +  - ]:        210 :     if (ovs_scan(s, "%i%n", &key_, &n)
    3242         [ +  - ]:        210 :         && (key_ & ~IPV6_LABEL_MASK) == 0) {
    3243                 :        210 :         int len = n;
    3244                 :            : 
    3245                 :        210 :         *key = htonl(key_);
    3246         [ +  + ]:        210 :         if (mask) {
    3247         [ +  + ]:        196 :             if (ovs_scan(s + len, "/%i%n", &mask_, &n)
    3248         [ +  - ]:         18 :                 && (mask_ & ~IPV6_LABEL_MASK) == 0) {
    3249                 :         18 :                 len += n;
    3250                 :         18 :                 *mask = htonl(mask_);
    3251                 :            :             } else {
    3252                 :        178 :                 *mask = htonl(IPV6_LABEL_MASK);
    3253                 :            :             }
    3254                 :            :         }
    3255                 :        210 :         return len;
    3256                 :            :     }
    3257                 :        210 :     return 0;
    3258                 :            : }
    3259                 :            : 
    3260                 :            : static int
    3261                 :       6111 : scan_u8(const char *s, uint8_t *key, uint8_t *mask)
    3262                 :            : {
    3263                 :            :     int n;
    3264                 :            : 
    3265         [ +  - ]:       6111 :     if (ovs_scan(s, "%"SCNi8"%n", key, &n)) {
    3266                 :       6111 :         int len = n;
    3267                 :            : 
    3268         [ +  + ]:       6111 :         if (mask) {
    3269         [ +  + ]:       2267 :             if (ovs_scan(s + len, "/%"SCNi8"%n", mask, &n)) {
    3270                 :        155 :                 len += n;
    3271                 :            :             } else {
    3272                 :       2112 :                 *mask = UINT8_MAX;
    3273                 :            :             }
    3274                 :            :         }
    3275                 :       6111 :         return len;
    3276                 :            :     }
    3277                 :       6111 :     return 0;
    3278                 :            : }
    3279                 :            : 
    3280                 :            : static int
    3281                 :         18 : scan_u16(const char *s, uint16_t *key, uint16_t *mask)
    3282                 :            : {
    3283                 :            :     int n;
    3284                 :            : 
    3285         [ +  - ]:         18 :     if (ovs_scan(s, "%"SCNi16"%n", key, &n)) {
    3286                 :         18 :         int len = n;
    3287                 :            : 
    3288         [ +  - ]:         18 :         if (mask) {
    3289         [ +  + ]:         18 :             if (ovs_scan(s + len, "/%"SCNi16"%n", mask, &n)) {
    3290                 :         17 :                 len += n;
    3291                 :            :             } else {
    3292                 :          1 :                 *mask = UINT16_MAX;
    3293                 :            :             }
    3294                 :            :         }
    3295                 :         18 :         return len;
    3296                 :            :     }
    3297                 :         18 :     return 0;
    3298                 :            : }
    3299                 :            : 
    3300                 :            : static int
    3301                 :        864 : scan_u32(const char *s, uint32_t *key, uint32_t *mask)
    3302                 :            : {
    3303                 :            :     int n;
    3304                 :            : 
    3305         [ +  - ]:        864 :     if (ovs_scan(s, "%"SCNi32"%n", key, &n)) {
    3306                 :        864 :         int len = n;
    3307                 :            : 
    3308         [ +  + ]:        864 :         if (mask) {
    3309         [ +  + ]:        657 :             if (ovs_scan(s + len, "/%"SCNi32"%n", mask, &n)) {
    3310                 :         51 :                 len += n;
    3311                 :            :             } else {
    3312                 :        606 :                 *mask = UINT32_MAX;
    3313                 :            :             }
    3314                 :            :         }
    3315                 :        864 :         return len;
    3316                 :            :     }
    3317                 :        864 :     return 0;
    3318                 :            : }
    3319                 :            : 
    3320                 :            : static int
    3321                 :       4360 : scan_be16(const char *s, ovs_be16 *key, ovs_be16 *mask)
    3322                 :            : {
    3323                 :            :     uint16_t key_, mask_;
    3324                 :            :     int n;
    3325                 :            : 
    3326         [ +  - ]:       4360 :     if (ovs_scan(s, "%"SCNi16"%n", &key_, &n)) {
    3327                 :       4360 :         int len = n;
    3328                 :            : 
    3329                 :       4360 :         *key = htons(key_);
    3330         [ +  + ]:       4360 :         if (mask) {
    3331         [ +  + ]:       2977 :             if (ovs_scan(s + len, "/%"SCNi16"%n", &mask_, &n)) {
    3332                 :        240 :                 len += n;
    3333                 :        240 :                 *mask = htons(mask_);
    3334                 :            :             } else {
    3335                 :       2737 :                 *mask = OVS_BE16_MAX;
    3336                 :            :             }
    3337                 :            :         }
    3338                 :       4360 :         return len;
    3339                 :            :     }
    3340                 :       4360 :     return 0;
    3341                 :            : }
    3342                 :            : 
    3343                 :            : static int
    3344                 :        159 : scan_be64(const char *s, ovs_be64 *key, ovs_be64 *mask)
    3345                 :            : {
    3346                 :            :     uint64_t key_, mask_;
    3347                 :            :     int n;
    3348                 :            : 
    3349         [ +  - ]:        159 :     if (ovs_scan(s, "%"SCNi64"%n", &key_, &n)) {
    3350                 :        159 :         int len = n;
    3351                 :            : 
    3352                 :        159 :         *key = htonll(key_);
    3353         [ +  - ]:        159 :         if (mask) {
    3354         [ +  + ]:        159 :             if (ovs_scan(s + len, "/%"SCNi64"%n", &mask_, &n)) {
    3355                 :         51 :                 len += n;
    3356                 :         51 :                 *mask = htonll(mask_);
    3357                 :            :             } else {
    3358                 :        108 :                 *mask = OVS_BE64_MAX;
    3359                 :            :             }
    3360                 :            :         }
    3361                 :        159 :         return len;
    3362                 :            :     }
    3363                 :        159 :     return 0;
    3364                 :            : }
    3365                 :            : 
    3366                 :            : static int
    3367                 :        167 : scan_tun_flags(const char *s, uint16_t *key, uint16_t *mask)
    3368                 :            : {
    3369                 :            :     uint32_t flags, fmask;
    3370                 :            :     int n;
    3371                 :            : 
    3372         [ +  - ]:        167 :     n = parse_odp_flags(s, flow_tun_flag_to_string, &flags,
    3373                 :            :                         FLOW_TNL_F_MASK, mask ? &fmask : NULL);
    3374 [ +  - ][ +  - ]:        167 :     if (n >= 0 && s[n] == ')') {
    3375                 :        167 :         *key = flags;
    3376         [ +  - ]:        167 :         if (mask) {
    3377                 :        167 :             *mask = fmask;
    3378                 :            :         }
    3379                 :        167 :         return n + 1;
    3380                 :            :     }
    3381                 :        167 :     return 0;
    3382                 :            : }
    3383                 :            : 
    3384                 :            : static int
    3385                 :        329 : scan_tcp_flags(const char *s, ovs_be16 *key, ovs_be16 *mask)
    3386                 :            : {
    3387                 :            :     uint32_t flags, fmask;
    3388                 :            :     int n;
    3389                 :            : 
    3390         [ +  - ]:        658 :     n = parse_odp_flags(s, packet_tcp_flag_to_string, &flags,
    3391                 :        329 :                         TCP_FLAGS(OVS_BE16_MAX), mask ? &fmask : NULL);
    3392         [ +  + ]:        329 :     if (n >= 0) {
    3393                 :        326 :         *key = htons(flags);
    3394         [ +  - ]:        326 :         if (mask) {
    3395                 :        326 :             *mask = htons(fmask);
    3396                 :            :         }
    3397                 :        326 :         return n;
    3398                 :            :     }
    3399                 :        329 :     return 0;
    3400                 :            : }
    3401                 :            : 
    3402                 :            : static uint32_t
    3403                 :      27726 : ovs_to_odp_ct_state(uint8_t state)
    3404                 :            : {
    3405                 :      27726 :     uint32_t odp = 0;
    3406                 :            : 
    3407         [ +  + ]:      27726 :     if (state & CS_NEW) {
    3408                 :       8494 :         odp |= OVS_CS_F_NEW;
    3409                 :            :     }
    3410         [ +  + ]:      27726 :     if (state & CS_ESTABLISHED) {
    3411                 :       7167 :         odp |= OVS_CS_F_ESTABLISHED;
    3412                 :            :     }
    3413         [ +  + ]:      27726 :     if (state & CS_RELATED) {
    3414                 :       6813 :         odp |= OVS_CS_F_RELATED;
    3415                 :            :     }
    3416         [ +  + ]:      27726 :     if (state & CS_INVALID) {
    3417                 :       6800 :         odp |= OVS_CS_F_INVALID;
    3418                 :            :     }
    3419         [ +  + ]:      27726 :     if (state & CS_REPLY_DIR) {
    3420                 :       6738 :         odp |= OVS_CS_F_REPLY_DIR;
    3421                 :            :     }
    3422         [ +  + ]:      27726 :     if (state & CS_TRACKED) {
    3423                 :       8556 :         odp |= OVS_CS_F_TRACKED;
    3424                 :            :     }
    3425         [ +  + ]:      27726 :     if (state & CS_SRC_NAT) {
    3426                 :       7191 :         odp |= OVS_CS_F_SRC_NAT;
    3427                 :            :     }
    3428         [ +  + ]:      27726 :     if (state & CS_DST_NAT) {
    3429                 :       6594 :         odp |= OVS_CS_F_DST_NAT;
    3430                 :            :     }
    3431                 :            : 
    3432                 :      27726 :     return odp;
    3433                 :            : }
    3434                 :            : 
    3435                 :            : static uint8_t
    3436                 :     143832 : odp_to_ovs_ct_state(uint32_t flags)
    3437                 :            : {
    3438                 :     143832 :     uint32_t state = 0;
    3439                 :            : 
    3440         [ +  + ]:     143832 :     if (flags & OVS_CS_F_NEW) {
    3441                 :       2726 :         state |= CS_NEW;
    3442                 :            :     }
    3443         [ +  + ]:     143832 :     if (flags & OVS_CS_F_ESTABLISHED) {
    3444                 :        624 :         state |= CS_ESTABLISHED;
    3445                 :            :     }
    3446         [ +  + ]:     143832 :     if (flags & OVS_CS_F_RELATED) {
    3447                 :         48 :         state |= CS_RELATED;
    3448                 :            :     }
    3449         [ +  + ]:     143832 :     if (flags & OVS_CS_F_INVALID) {
    3450                 :         93 :         state |= CS_INVALID;
    3451                 :            :     }
    3452         [ +  + ]:     143832 :     if (flags & OVS_CS_F_REPLY_DIR) {
    3453                 :        383 :         state |= CS_REPLY_DIR;
    3454                 :            :     }
    3455         [ +  + ]:     143832 :     if (flags & OVS_CS_F_TRACKED) {
    3456                 :       2902 :         state |= CS_TRACKED;
    3457                 :            :     }
    3458         [ +  + ]:     143832 :     if (flags & OVS_CS_F_SRC_NAT) {
    3459                 :        644 :         state |= CS_SRC_NAT;
    3460                 :            :     }
    3461         [ +  + ]:     143832 :     if (flags & OVS_CS_F_DST_NAT) {
    3462                 :        137 :         state |= CS_DST_NAT;
    3463                 :            :     }
    3464                 :            : 
    3465                 :     143832 :     return state;
    3466                 :            : }
    3467                 :            : 
    3468                 :            : static int
    3469                 :         18 : scan_ct_state(const char *s, uint32_t *key, uint32_t *mask)
    3470                 :            : {
    3471                 :            :     uint32_t flags, fmask;
    3472                 :            :     int n;
    3473                 :            : 
    3474         [ +  - ]:         18 :     n = parse_flags(s, odp_ct_state_to_string, ')', NULL, NULL, &flags,
    3475                 :            :                     ovs_to_odp_ct_state(CS_SUPPORTED_MASK),
    3476                 :            :                     mask ? &fmask : NULL);
    3477                 :            : 
    3478         [ +  - ]:         18 :     if (n >= 0) {
    3479                 :         18 :         *key = flags;
    3480         [ +  - ]:         18 :         if (mask) {
    3481                 :         18 :             *mask = fmask;
    3482                 :            :         }
    3483                 :         18 :         return n;
    3484                 :            :     }
    3485                 :         18 :     return 0;
    3486                 :            : }
    3487                 :            : 
    3488                 :            : static int
    3489                 :       1584 : scan_frag(const char *s, uint8_t *key, uint8_t *mask)
    3490                 :            : {
    3491                 :            :     int n;
    3492                 :            :     char frag[8];
    3493                 :            :     enum ovs_frag_type frag_type;
    3494                 :            : 
    3495         [ +  - ]:       1584 :     if (ovs_scan(s, "%7[a-z]%n", frag, &n)
    3496         [ +  - ]:       1584 :         && ovs_frag_type_from_string(frag, &frag_type)) {
    3497                 :       1584 :         int len = n;
    3498                 :            : 
    3499                 :       1584 :         *key = frag_type;
    3500         [ +  + ]:       1584 :         if (mask) {
    3501                 :        514 :             *mask = UINT8_MAX;
    3502                 :            :         }
    3503                 :       1584 :         return len;
    3504                 :            :     }
    3505                 :       1584 :     return 0;
    3506                 :            : }
    3507                 :            : 
    3508                 :            : static int
    3509                 :       2151 : scan_port(const char *s, uint32_t *key, uint32_t *mask,
    3510                 :            :           const struct simap *port_names)
    3511                 :            : {
    3512                 :            :     int n;
    3513                 :            : 
    3514         [ +  + ]:       2151 :     if (ovs_scan(s, "%"SCNi32"%n", key, &n)) {
    3515                 :       2148 :         int len = n;
    3516                 :            : 
    3517         [ +  - ]:       2148 :         if (mask) {
    3518         [ +  + ]:       2148 :             if (ovs_scan(s + len, "/%"SCNi32"%n", mask, &n)) {
    3519                 :          9 :                 len += n;
    3520                 :            :             } else {
    3521                 :       2139 :                 *mask = UINT32_MAX;
    3522                 :            :             }
    3523                 :            :         }
    3524                 :       2148 :         return len;
    3525         [ +  - ]:          3 :     } else if (port_names) {
    3526                 :            :         const struct simap_node *node;
    3527                 :            :         int len;
    3528                 :            : 
    3529                 :          3 :         len = strcspn(s, ")");
    3530                 :          3 :         node = simap_find_len(port_names, s, len);
    3531         [ +  - ]:          3 :         if (node) {
    3532                 :          3 :             *key = node->data;
    3533                 :            : 
    3534         [ +  - ]:          3 :             if (mask) {
    3535                 :          3 :                 *mask = UINT32_MAX;
    3536                 :            :             }
    3537                 :          3 :             return len;
    3538                 :            :         }
    3539                 :            :     }
    3540                 :       2151 :     return 0;
    3541                 :            : }
    3542                 :            : 
    3543                 :            : /* Helper for vlan parsing. */
    3544                 :            : struct ovs_key_vlan__ {
    3545                 :            :     ovs_be16 tci;
    3546                 :            : };
    3547                 :            : 
    3548                 :            : static bool
    3549                 :        720 : set_be16_bf(ovs_be16 *bf, uint8_t bits, uint8_t offset, uint16_t value)
    3550                 :            : {
    3551                 :        720 :     const uint16_t mask = ((1U << bits) - 1) << offset;
    3552                 :            : 
    3553         [ -  + ]:        720 :     if (value >> bits) {
    3554                 :          0 :         return false;
    3555                 :            :     }
    3556                 :            : 
    3557                 :        720 :     *bf = htons((ntohs(*bf) & ~mask) | (value << offset));
    3558                 :        720 :     return true;
    3559                 :            : }
    3560                 :            : 
    3561                 :            : static int
    3562                 :        720 : scan_be16_bf(const char *s, ovs_be16 *key, ovs_be16 *mask, uint8_t bits,
    3563                 :            :              uint8_t offset)
    3564                 :            : {
    3565                 :            :     uint16_t key_, mask_;
    3566                 :            :     int n;
    3567                 :            : 
    3568         [ +  - ]:        720 :     if (ovs_scan(s, "%"SCNi16"%n", &key_, &n)) {
    3569                 :        720 :         int len = n;
    3570                 :            : 
    3571         [ +  - ]:        720 :         if (set_be16_bf(key, bits, offset, key_)) {
    3572         [ +  + ]:        720 :             if (mask) {
    3573         [ -  + ]:        380 :                 if (ovs_scan(s + len, "/%"SCNi16"%n", &mask_, &n)) {
    3574                 :          0 :                     len += n;
    3575                 :            : 
    3576         [ #  # ]:          0 :                     if (!set_be16_bf(mask, bits, offset, mask_)) {
    3577                 :          0 :                         return 0;
    3578                 :            :                     }
    3579                 :            :                 } else {
    3580                 :        380 :                     *mask |= htons(((1U << bits) - 1) << offset);
    3581                 :            :                 }
    3582                 :            :             }
    3583                 :        720 :             return len;
    3584                 :            :         }
    3585                 :            :     }
    3586                 :        720 :     return 0;
    3587                 :            : }
    3588                 :            : 
    3589                 :            : static int
    3590                 :        360 : scan_vid(const char *s, ovs_be16 *key, ovs_be16 *mask)
    3591                 :            : {
    3592                 :        360 :     return scan_be16_bf(s, key, mask, 12, VLAN_VID_SHIFT);
    3593                 :            : }
    3594                 :            : 
    3595                 :            : static int
    3596                 :        360 : scan_pcp(const char *s, ovs_be16 *key, ovs_be16 *mask)
    3597                 :            : {
    3598                 :        360 :     return scan_be16_bf(s, key, mask, 3, VLAN_PCP_SHIFT);
    3599                 :            : }
    3600                 :            : 
    3601                 :            : static int
    3602                 :          0 : scan_cfi(const char *s, ovs_be16 *key, ovs_be16 *mask)
    3603                 :            : {
    3604                 :          0 :     return scan_be16_bf(s, key, mask, 1, VLAN_CFI_SHIFT);
    3605                 :            : }
    3606                 :            : 
    3607                 :            : /* For MPLS. */
    3608                 :            : static bool
    3609                 :        244 : set_be32_bf(ovs_be32 *bf, uint8_t bits, uint8_t offset, uint32_t value)
    3610                 :            : {
    3611                 :        244 :     const uint32_t mask = ((1U << bits) - 1) << offset;
    3612                 :            : 
    3613         [ -  + ]:        244 :     if (value >> bits) {
    3614                 :          0 :         return false;
    3615                 :            :     }
    3616                 :            : 
    3617                 :        244 :     *bf = htonl((ntohl(*bf) & ~mask) | (value << offset));
    3618                 :        244 :     return true;
    3619                 :            : }
    3620                 :            : 
    3621                 :            : static int
    3622                 :        244 : scan_be32_bf(const char *s, ovs_be32 *key, ovs_be32 *mask, uint8_t bits,
    3623                 :            :              uint8_t offset)
    3624                 :            : {
    3625                 :            :     uint32_t key_, mask_;
    3626                 :            :     int n;
    3627                 :            : 
    3628         [ +  - ]:        244 :     if (ovs_scan(s, "%"SCNi32"%n", &key_, &n)) {
    3629                 :        244 :         int len = n;
    3630                 :            : 
    3631         [ +  - ]:        244 :         if (set_be32_bf(key, bits, offset, key_)) {
    3632         [ +  + ]:        244 :             if (mask) {
    3633         [ -  + ]:        172 :                 if (ovs_scan(s + len, "/%"SCNi32"%n", &mask_, &n)) {
    3634                 :          0 :                     len += n;
    3635                 :            : 
    3636         [ #  # ]:          0 :                     if (!set_be32_bf(mask, bits, offset, mask_)) {
    3637                 :          0 :                         return 0;
    3638                 :            :                     }
    3639                 :            :                 } else {
    3640                 :        172 :                     *mask |= htonl(((1U << bits) - 1) << offset);
    3641                 :            :                 }
    3642                 :            :             }
    3643                 :        244 :             return len;
    3644                 :            :         }
    3645                 :            :     }
    3646                 :        244 :     return 0;
    3647                 :            : }
    3648                 :            : 
    3649                 :            : static int
    3650                 :         61 : scan_mpls_label(const char *s, ovs_be32 *key, ovs_be32 *mask)
    3651                 :            : {
    3652                 :         61 :     return scan_be32_bf(s, key, mask, 20, MPLS_LABEL_SHIFT);
    3653                 :            : }
    3654                 :            : 
    3655                 :            : static int
    3656                 :         61 : scan_mpls_tc(const char *s, ovs_be32 *key, ovs_be32 *mask)
    3657                 :            : {
    3658                 :         61 :     return scan_be32_bf(s, key, mask, 3, MPLS_TC_SHIFT);
    3659                 :            : }
    3660                 :            : 
    3661                 :            : static int
    3662                 :         61 : scan_mpls_ttl(const char *s, ovs_be32 *key, ovs_be32 *mask)
    3663                 :            : {
    3664                 :         61 :     return scan_be32_bf(s, key, mask, 8, MPLS_TTL_SHIFT);
    3665                 :            : }
    3666                 :            : 
    3667                 :            : static int
    3668                 :         61 : scan_mpls_bos(const char *s, ovs_be32 *key, ovs_be32 *mask)
    3669                 :            : {
    3670                 :         61 :     return scan_be32_bf(s, key, mask, 1, MPLS_BOS_SHIFT);
    3671                 :            : }
    3672                 :            : 
    3673                 :            : static int
    3674                 :         17 : scan_vxlan_gbp(const char *s, uint32_t *key, uint32_t *mask)
    3675                 :            : {
    3676                 :         17 :     const char *s_base = s;
    3677                 :         17 :     ovs_be16 id = 0, id_mask = 0;
    3678                 :         17 :     uint8_t flags = 0, flags_mask = 0;
    3679                 :            : 
    3680         [ +  - ]:         17 :     if (!strncmp(s, "id=", 3)) {
    3681                 :         17 :         s += 3;
    3682         [ +  - ]:         17 :         s += scan_be16(s, &id, mask ? &id_mask : NULL);
    3683                 :            :     }
    3684                 :            : 
    3685         [ +  - ]:         17 :     if (s[0] == ',') {
    3686                 :         17 :         s++;
    3687                 :            :     }
    3688         [ +  - ]:         17 :     if (!strncmp(s, "flags=", 6)) {
    3689                 :         17 :         s += 6;
    3690         [ +  - ]:         17 :         s += scan_u8(s, &flags, mask ? &flags_mask : NULL);
    3691                 :            :     }
    3692                 :            : 
    3693         [ +  - ]:         17 :     if (!strncmp(s, "))", 2)) {
    3694                 :         17 :         s += 2;
    3695                 :            : 
    3696                 :         17 :         *key = (flags << 16) | ntohs(id);
    3697         [ +  - ]:         17 :         if (mask) {
    3698                 :         17 :             *mask = (flags_mask << 16) | ntohs(id_mask);
    3699                 :            :         }
    3700                 :            : 
    3701                 :         17 :         return s - s_base;
    3702                 :            :     }
    3703                 :            : 
    3704                 :         17 :     return 0;
    3705                 :            : }
    3706                 :            : 
    3707                 :            : static int
    3708                 :         24 : scan_geneve(const char *s, struct geneve_scan *key, struct geneve_scan *mask)
    3709                 :            : {
    3710                 :         24 :     const char *s_base = s;
    3711                 :         24 :     struct geneve_opt *opt = key->d;
    3712         [ +  + ]:         24 :     struct geneve_opt *opt_mask = mask ? mask->d : NULL;
    3713                 :         24 :     int len_remain = sizeof key->d;
    3714                 :            : 
    3715 [ +  + ][ +  - ]:         66 :     while (s[0] == '{' && len_remain >= sizeof *opt) {
    3716                 :         42 :         int data_len = 0;
    3717                 :            : 
    3718                 :         42 :         s++;
    3719                 :         42 :         len_remain -= sizeof *opt;
    3720                 :            : 
    3721         [ +  - ]:         42 :         if (!strncmp(s, "class=", 6)) {
    3722                 :         42 :             s += 6;
    3723         [ +  + ]:         42 :             s += scan_be16(s, &opt->opt_class,
    3724                 :            :                            mask ? &opt_mask->opt_class : NULL);
    3725         [ #  # ]:          0 :         } else if (mask) {
    3726                 :          0 :             memset(&opt_mask->opt_class, 0, sizeof opt_mask->opt_class);
    3727                 :            :         }
    3728                 :            : 
    3729         [ +  - ]:         42 :         if (s[0] == ',') {
    3730                 :         42 :             s++;
    3731                 :            :         }
    3732         [ +  - ]:         42 :         if (!strncmp(s, "type=", 5)) {
    3733                 :         42 :             s += 5;
    3734         [ +  + ]:         42 :             s += scan_u8(s, &opt->type, mask ? &opt_mask->type : NULL);
    3735         [ #  # ]:          0 :         } else if (mask) {
    3736                 :          0 :             memset(&opt_mask->type, 0, sizeof opt_mask->type);
    3737                 :            :         }
    3738                 :            : 
    3739         [ +  - ]:         42 :         if (s[0] == ',') {
    3740                 :         42 :             s++;
    3741                 :            :         }
    3742         [ +  - ]:         42 :         if (!strncmp(s, "len=", 4)) {
    3743                 :            :             uint8_t opt_len, opt_len_mask;
    3744                 :         42 :             s += 4;
    3745         [ +  + ]:         42 :             s += scan_u8(s, &opt_len, mask ? &opt_len_mask : NULL);
    3746                 :            : 
    3747 [ +  - ][ +  - ]:         42 :             if (opt_len > 124 || opt_len % 4 || opt_len > len_remain) {
                 [ -  + ]
    3748                 :          0 :                 return 0;
    3749                 :            :             }
    3750                 :         42 :             opt->length = opt_len / 4;
    3751         [ +  + ]:         42 :             if (mask) {
    3752                 :         40 :                 opt_mask->length = opt_len_mask;
    3753                 :            :             }
    3754                 :         42 :             data_len = opt_len;
    3755         [ #  # ]:          0 :         } else if (mask) {
    3756                 :          0 :             memset(&opt_mask->type, 0, sizeof opt_mask->type);
    3757                 :            :         }
    3758                 :            : 
    3759         [ +  + ]:         42 :         if (s[0] == ',') {
    3760                 :         41 :             s++;
    3761                 :            :         }
    3762         [ -  + ]:         42 :         if (parse_int_string(s, (uint8_t *)(opt + 1), data_len, (char **)&s)) {
    3763                 :          0 :             return 0;
    3764                 :            :         }
    3765                 :            : 
    3766         [ +  + ]:         42 :         if (mask) {
    3767         [ +  + ]:         40 :             if (s[0] == '/') {
    3768                 :         17 :                 s++;
    3769         [ -  + ]:         17 :                 if (parse_int_string(s, (uint8_t *)(opt_mask + 1),
    3770                 :            :                                      data_len, (char **)&s)) {
    3771                 :          0 :                     return 0;
    3772                 :            :                 }
    3773                 :            :             }
    3774                 :         40 :             opt_mask->r1 = 0;
    3775                 :         40 :             opt_mask->r2 = 0;
    3776                 :         40 :             opt_mask->r3 = 0;
    3777                 :            :         }
    3778                 :            : 
    3779         [ +  - ]:         42 :         if (s[0] == '}') {
    3780                 :         42 :             s++;
    3781                 :         42 :             opt += 1 + data_len / 4;
    3782         [ +  + ]:         42 :             if (mask) {
    3783                 :         40 :                 opt_mask += 1 + data_len / 4;
    3784                 :            :             }
    3785                 :         42 :             len_remain -= data_len;
    3786                 :            :         }
    3787                 :            :     }
    3788                 :            : 
    3789         [ +  - ]:         24 :     if (s[0] == ')') {
    3790                 :         24 :         int len = sizeof key->d - len_remain;
    3791                 :            : 
    3792                 :         24 :         s++;
    3793                 :         24 :         key->len = len;
    3794         [ +  + ]:         24 :         if (mask) {
    3795                 :         22 :             mask->len = len;
    3796                 :            :         }
    3797                 :         24 :         return s - s_base;
    3798                 :            :     }
    3799                 :            : 
    3800                 :          0 :     return 0;
    3801                 :            : }
    3802                 :            : 
    3803                 :            : static void
    3804                 :        334 : tun_flags_to_attr(struct ofpbuf *a, const void *data_)
    3805                 :            : {
    3806                 :        334 :     const uint16_t *flags = data_;
    3807                 :            : 
    3808         [ +  + ]:        334 :     if (*flags & FLOW_TNL_F_DONT_FRAGMENT) {
    3809                 :        173 :         nl_msg_put_flag(a, OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT);
    3810                 :            :     }
    3811         [ +  + ]:        334 :     if (*flags & FLOW_TNL_F_CSUM) {
    3812                 :        243 :         nl_msg_put_flag(a, OVS_TUNNEL_KEY_ATTR_CSUM);
    3813                 :            :     }
    3814         [ +  + ]:        334 :     if (*flags & FLOW_TNL_F_OAM) {
    3815                 :        167 :         nl_msg_put_flag(a, OVS_TUNNEL_KEY_ATTR_OAM);
    3816                 :            :     }
    3817                 :        334 : }
    3818                 :            : 
    3819                 :            : static void
    3820                 :         34 : vxlan_gbp_to_attr(struct ofpbuf *a, const void *data_)
    3821                 :            : {
    3822                 :         34 :     const uint32_t *gbp = data_;
    3823                 :            : 
    3824         [ +  - ]:         34 :     if (*gbp) {
    3825                 :            :         size_t vxlan_opts_ofs;
    3826                 :            : 
    3827                 :         34 :         vxlan_opts_ofs = nl_msg_start_nested(a, OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS);
    3828                 :         34 :         nl_msg_put_u32(a, OVS_VXLAN_EXT_GBP, *gbp);
    3829                 :         34 :         nl_msg_end_nested(a, vxlan_opts_ofs);
    3830                 :            :     }
    3831                 :         34 : }
    3832                 :            : 
    3833                 :            : static void
    3834                 :         44 : geneve_to_attr(struct ofpbuf *a, const void *data_)
    3835                 :            : {
    3836                 :         44 :     const struct geneve_scan *geneve = data_;
    3837                 :            : 
    3838                 :         44 :     nl_msg_put_unspec(a, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS, geneve->d,
    3839                 :         44 :                       geneve->len);
    3840                 :         44 : }
    3841                 :            : 
    3842                 :            : #define SCAN_PUT_ATTR(BUF, ATTR, DATA, FUNC)                      \
    3843                 :            :     {                                                             \
    3844                 :            :         unsigned long call_fn = (unsigned long)FUNC;              \
    3845                 :            :         if (call_fn) {                                            \
    3846                 :            :             typedef void (*fn)(struct ofpbuf *, const void *);    \
    3847                 :            :             fn func = FUNC;                                       \
    3848                 :            :             func(BUF, &(DATA));                                   \
    3849                 :            :         } else {                                                  \
    3850                 :            :             nl_msg_put_unspec(BUF, ATTR, &(DATA), sizeof (DATA)); \
    3851                 :            :         }                                                         \
    3852                 :            :     }
    3853                 :            : 
    3854                 :            : #define SCAN_IF(NAME)                           \
    3855                 :            :     if (strncmp(s, NAME, strlen(NAME)) == 0) {  \
    3856                 :            :         const char *start = s;                  \
    3857                 :            :         int len;                                \
    3858                 :            :                                                 \
    3859                 :            :         s += strlen(NAME)
    3860                 :            : 
    3861                 :            : /* Usually no special initialization is needed. */
    3862                 :            : #define SCAN_BEGIN(NAME, TYPE)                  \
    3863                 :            :     SCAN_IF(NAME);                              \
    3864                 :            :         TYPE skey, smask;                       \
    3865                 :            :         memset(&skey, 0, sizeof skey);          \
    3866                 :            :         memset(&smask, 0, sizeof smask);        \
    3867                 :            :         do {                                    \
    3868                 :            :             len = 0;
    3869                 :            : 
    3870                 :            : /* Init as fully-masked as mask will not be scanned. */
    3871                 :            : #define SCAN_BEGIN_FULLY_MASKED(NAME, TYPE)     \
    3872                 :            :     SCAN_IF(NAME);                              \
    3873                 :            :         TYPE skey, smask;                       \
    3874                 :            :         memset(&skey, 0, sizeof skey);          \
    3875                 :            :         memset(&smask, 0xff, sizeof smask);     \
    3876                 :            :         do {                                    \
    3877                 :            :             len = 0;
    3878                 :            : 
    3879                 :            : /* VLAN needs special initialization. */
    3880                 :            : #define SCAN_BEGIN_INIT(NAME, TYPE, KEY_INIT, MASK_INIT)  \
    3881                 :            :     SCAN_IF(NAME);                                        \
    3882                 :            :         TYPE skey = KEY_INIT;                       \
    3883                 :            :         TYPE smask = MASK_INIT;                     \
    3884                 :            :         do {                                        \
    3885                 :            :             len = 0;
    3886                 :            : 
    3887                 :            : /* Scan unnamed entry as 'TYPE' */
    3888                 :            : #define SCAN_TYPE(TYPE, KEY, MASK)              \
    3889                 :            :     len = scan_##TYPE(s, KEY, MASK);            \
    3890                 :            :     if (len == 0) {                             \
    3891                 :            :         return -EINVAL;                         \
    3892                 :            :     }                                           \
    3893                 :            :     s += len
    3894                 :            : 
    3895                 :            : /* Scan named ('NAME') entry 'FIELD' as 'TYPE'. */
    3896                 :            : #define SCAN_FIELD(NAME, TYPE, FIELD)                                   \
    3897                 :            :     if (strncmp(s, NAME, strlen(NAME)) == 0) {                          \
    3898                 :            :         s += strlen(NAME);                                              \
    3899                 :            :         SCAN_TYPE(TYPE, &skey.FIELD, mask ? &smask.FIELD : NULL);       \
    3900                 :            :         continue;                                                       \
    3901                 :            :     }
    3902                 :            : 
    3903                 :            : #define SCAN_FINISH()                           \
    3904                 :            :         } while (*s++ == ',' && len != 0);      \
    3905                 :            :         if (s[-1] != ')') {                     \
    3906                 :            :             return -EINVAL;                     \
    3907                 :            :         }
    3908                 :            : 
    3909                 :            : #define SCAN_FINISH_SINGLE()                    \
    3910                 :            :         } while (false);                        \
    3911                 :            :         if (*s++ != ')') {                      \
    3912                 :            :             return -EINVAL;                     \
    3913                 :            :         }
    3914                 :            : 
    3915                 :            : /* Beginning of nested attribute. */
    3916                 :            : #define SCAN_BEGIN_NESTED(NAME, ATTR)                      \
    3917                 :            :     SCAN_IF(NAME);                                         \
    3918                 :            :         size_t key_offset, mask_offset;                    \
    3919                 :            :         key_offset = nl_msg_start_nested(key, ATTR);       \
    3920                 :            :         if (mask) {                                        \
    3921                 :            :             mask_offset = nl_msg_start_nested(mask, ATTR); \
    3922                 :            :         }                                                  \
    3923                 :            :         do {                                               \
    3924                 :            :             len = 0;
    3925                 :            : 
    3926                 :            : #define SCAN_END_NESTED()                               \
    3927                 :            :         SCAN_FINISH();                                  \
    3928                 :            :         nl_msg_end_nested(key, key_offset);             \
    3929                 :            :         if (mask) {                                     \
    3930                 :            :             nl_msg_end_nested(mask, mask_offset);       \
    3931                 :            :         }                                               \
    3932                 :            :         return s - start;                               \
    3933                 :            :     }
    3934                 :            : 
    3935                 :            : #define SCAN_FIELD_NESTED__(NAME, TYPE, SCAN_AS, ATTR, FUNC)  \
    3936                 :            :     if (strncmp(s, NAME, strlen(NAME)) == 0) {                \
    3937                 :            :         TYPE skey, smask;                                     \
    3938                 :            :         memset(&skey, 0, sizeof skey);                        \
    3939                 :            :         memset(&smask, 0xff, sizeof smask);                   \
    3940                 :            :         s += strlen(NAME);                                    \
    3941                 :            :         SCAN_TYPE(SCAN_AS, &skey, &smask);                    \
    3942                 :            :         SCAN_PUT(ATTR, FUNC);                                 \
    3943                 :            :         continue;                                             \
    3944                 :            :     }
    3945                 :            : 
    3946                 :            : #define SCAN_FIELD_NESTED(NAME, TYPE, SCAN_AS, ATTR)  \
    3947                 :            :         SCAN_FIELD_NESTED__(NAME, TYPE, SCAN_AS, ATTR, NULL)
    3948                 :            : 
    3949                 :            : #define SCAN_FIELD_NESTED_FUNC(NAME, TYPE, SCAN_AS, FUNC)  \
    3950                 :            :         SCAN_FIELD_NESTED__(NAME, TYPE, SCAN_AS, 0, FUNC)
    3951                 :            : 
    3952                 :            : #define SCAN_PUT(ATTR, FUNC)                            \
    3953                 :            :         SCAN_PUT_ATTR(key, ATTR, skey, FUNC);           \
    3954                 :            :         if (mask)                                       \
    3955                 :            :             SCAN_PUT_ATTR(mask, ATTR, smask, FUNC);     \
    3956                 :            : 
    3957                 :            : #define SCAN_END(ATTR)                                  \
    3958                 :            :         SCAN_FINISH();                                  \
    3959                 :            :         SCAN_PUT(ATTR, NULL);                           \
    3960                 :            :         return s - start;                               \
    3961                 :            :     }
    3962                 :            : 
    3963                 :            : #define SCAN_BEGIN_ARRAY(NAME, TYPE, CNT)       \
    3964                 :            :     SCAN_IF(NAME);                              \
    3965                 :            :         TYPE skey[CNT], smask[CNT];             \
    3966                 :            :         memset(&skey, 0, sizeof skey);          \
    3967                 :            :         memset(&smask, 0, sizeof smask);        \
    3968                 :            :         int idx = 0, cnt = CNT;                 \
    3969                 :            :         uint64_t fields = 0;                    \
    3970                 :            :         do {                                    \
    3971                 :            :             int field = 0;                      \
    3972                 :            :             len = 0;
    3973                 :            : 
    3974                 :            : /* Scan named ('NAME') entry 'FIELD' as 'TYPE'. */
    3975                 :            : #define SCAN_FIELD_ARRAY(NAME, TYPE, FIELD)                             \
    3976                 :            :     if (strncmp(s, NAME, strlen(NAME)) == 0) {                          \
    3977                 :            :         if (fields & (1UL << field)) {                                  \
    3978                 :            :             fields = 0;                                                 \
    3979                 :            :             if (++idx == cnt) {                                         \
    3980                 :            :                 break;                                                  \
    3981                 :            :             }                                                           \
    3982                 :            :         }                                                               \
    3983                 :            :         s += strlen(NAME);                                              \
    3984                 :            :         SCAN_TYPE(TYPE, &skey[idx].FIELD, mask ? &smask[idx].FIELD : NULL); \
    3985                 :            :         fields |= 1UL << field;                                         \
    3986                 :            :         continue;                                                       \
    3987                 :            :     }                                                                   \
    3988                 :            :     field++;
    3989                 :            : 
    3990                 :            : #define SCAN_PUT_ATTR_ARRAY(BUF, ATTR, DATA, CNT)                    \
    3991                 :            :     nl_msg_put_unspec(BUF, ATTR, &(DATA), sizeof (DATA)[0] * (CNT)); \
    3992                 :            : 
    3993                 :            : #define SCAN_PUT_ARRAY(ATTR, CNT)                        \
    3994                 :            :     SCAN_PUT_ATTR_ARRAY(key, ATTR, skey, CNT);       \
    3995                 :            :     if (mask) {                                      \
    3996                 :            :         SCAN_PUT_ATTR_ARRAY(mask, ATTR, smask, CNT); \
    3997                 :            :     }
    3998                 :            : 
    3999                 :            : #define SCAN_END_ARRAY(ATTR)             \
    4000                 :            :         SCAN_FINISH();                   \
    4001                 :            :         if (idx == cnt) {                \
    4002                 :            :             return -EINVAL;              \
    4003                 :            :         }                                \
    4004                 :            :         SCAN_PUT_ARRAY(ATTR, idx + 1);   \
    4005                 :            :         return s - start;                \
    4006                 :            :     }
    4007                 :            : 
    4008                 :            : #define SCAN_END_SINGLE(ATTR)                           \
    4009                 :            :         SCAN_FINISH_SINGLE();                           \
    4010                 :            :         SCAN_PUT(ATTR, NULL);                           \
    4011                 :            :         return s - start;                               \
    4012                 :            :     }
    4013                 :            : 
    4014                 :            : #define SCAN_SINGLE(NAME, TYPE, SCAN_AS, ATTR)       \
    4015                 :            :     SCAN_BEGIN(NAME, TYPE) {                         \
    4016                 :            :         SCAN_TYPE(SCAN_AS, &skey, &smask);           \
    4017                 :            :     } SCAN_END_SINGLE(ATTR)
    4018                 :            : 
    4019                 :            : #define SCAN_SINGLE_FULLY_MASKED(NAME, TYPE, SCAN_AS, ATTR) \
    4020                 :            :     SCAN_BEGIN_FULLY_MASKED(NAME, TYPE) {                   \
    4021                 :            :         SCAN_TYPE(SCAN_AS, &skey, NULL);                    \
    4022                 :            :     } SCAN_END_SINGLE(ATTR)
    4023                 :            : 
    4024                 :            : /* scan_port needs one extra argument. */
    4025                 :            : #define SCAN_SINGLE_PORT(NAME, TYPE, ATTR)  \
    4026                 :            :     SCAN_BEGIN(NAME, TYPE) {                            \
    4027                 :            :         len = scan_port(s, &skey, &smask, port_names);  \
    4028                 :            :         if (len == 0) {                                 \
    4029                 :            :             return -EINVAL;                             \
    4030                 :            :         }                                               \
    4031                 :            :         s += len;                                       \
    4032                 :            :     } SCAN_END_SINGLE(ATTR)
    4033                 :            : 
    4034                 :            : static int
    4035                 :      12711 : parse_odp_key_mask_attr(const char *s, const struct simap *port_names,
    4036                 :            :                         struct ofpbuf *key, struct ofpbuf *mask)
    4037                 :            : {
    4038                 :            :     ovs_u128 ufid;
    4039                 :            :     int len;
    4040                 :            : 
    4041                 :            :     /* Skip UFID. */
    4042                 :      12711 :     len = odp_ufid_from_string(s, &ufid);
    4043         [ +  + ]:      12711 :     if (len) {
    4044                 :          2 :         return len;
    4045                 :            :     }
    4046                 :            : 
    4047 [ +  + ][ -  + ]:      12709 :     SCAN_SINGLE("skb_priority(", uint32_t, u32, OVS_KEY_ATTR_PRIORITY);
         [ -  + ][ -  + ]
         [ +  - ][ -  + ]
    4048 [ +  + ][ -  + ]:      12487 :     SCAN_SINGLE("skb_mark(", uint32_t, u32, OVS_KEY_ATTR_SKB_MARK);
         [ -  + ][ -  + ]
         [ +  - ][ -  + ]
    4049 [ +  + ][ -  + ]:      12280 :     SCAN_SINGLE_FULLY_MASKED("recirc_id(", uint32_t, u32,
         [ -  + ][ -  + ]
         [ +  + ][ -  + ]
    4050                 :            :                              OVS_KEY_ATTR_RECIRC_ID);
    4051 [ +  + ][ -  + ]:      12073 :     SCAN_SINGLE("dp_hash(", uint32_t, u32, OVS_KEY_ATTR_DP_HASH);
         [ -  + ][ -  + ]
         [ +  - ][ -  + ]
    4052                 :            : 
    4053 [ +  + ][ -  + ]:      11887 :     SCAN_SINGLE("ct_state(", uint32_t, ct_state, OVS_KEY_ATTR_CT_STATE);
         [ -  + ][ -  + ]
         [ +  - ][ -  + ]
    4054 [ +  + ][ -  + ]:      11869 :     SCAN_SINGLE("ct_zone(", uint16_t, u16, OVS_KEY_ATTR_CT_ZONE);
         [ -  + ][ -  + ]
         [ +  - ][ -  + ]
    4055 [ +  + ][ -  + ]:      11851 :     SCAN_SINGLE("ct_mark(", uint32_t, u32, OVS_KEY_ATTR_CT_MARK);
         [ -  + ][ -  + ]
         [ +  - ][ -  + ]
    4056 [ +  + ][ -  + ]:      11809 :     SCAN_SINGLE("ct_label(", ovs_u128, u128, OVS_KEY_ATTR_CT_LABELS);
         [ -  + ][ -  + ]
         [ +  - ][ -  + ]
    4057                 :            : 
    4058 [ +  + ][ +  - ]:      11767 :     SCAN_BEGIN_NESTED("tunnel(", OVS_KEY_ATTR_TUNNEL) {
    4059 [ +  + ][ -  + ]:        950 :         SCAN_FIELD_NESTED("tun_id=", ovs_be64, be64, OVS_TUNNEL_KEY_ATTR_ID);
         [ -  + ][ +  - ]
                 [ -  + ]
    4060 [ +  + ][ -  + ]:        791 :         SCAN_FIELD_NESTED("src=", ovs_be32, ipv4, OVS_TUNNEL_KEY_ATTR_IPV4_SRC);
         [ -  + ][ +  - ]
                 [ -  + ]
    4061 [ +  + ][ -  + ]:        623 :         SCAN_FIELD_NESTED("dst=", ovs_be32, ipv4, OVS_TUNNEL_KEY_ATTR_IPV4_DST);
         [ -  + ][ +  - ]
                 [ -  + ]
    4062 [ +  + ][ -  + ]:        455 :         SCAN_FIELD_NESTED("ipv6_src=", struct in6_addr, in6_addr, OVS_TUNNEL_KEY_ATTR_IPV6_SRC);
         [ -  + ][ +  - ]
                 [ -  + ]
    4063 [ +  + ][ -  + ]:        454 :         SCAN_FIELD_NESTED("ipv6_dst=", struct in6_addr, in6_addr, OVS_TUNNEL_KEY_ATTR_IPV6_DST);
         [ -  + ][ +  - ]
                 [ -  + ]
    4064 [ +  + ][ -  + ]:        453 :         SCAN_FIELD_NESTED("tos=", uint8_t, u8, OVS_TUNNEL_KEY_ATTR_TOS);
         [ -  + ][ +  - ]
                 [ -  + ]
    4065 [ +  + ][ -  + ]:        381 :         SCAN_FIELD_NESTED("ttl=", uint8_t, u8, OVS_TUNNEL_KEY_ATTR_TTL);
         [ -  + ][ +  - ]
                 [ -  + ]
    4066 [ +  + ][ -  + ]:        212 :         SCAN_FIELD_NESTED("tp_src=", ovs_be16, be16, OVS_TUNNEL_KEY_ATTR_TP_SRC);
         [ -  + ][ +  - ]
                 [ -  + ]
    4067 [ +  + ][ -  + ]:        209 :         SCAN_FIELD_NESTED("tp_dst=", ovs_be16, be16, OVS_TUNNEL_KEY_ATTR_TP_DST);
         [ -  + ][ +  - ]
                 [ -  + ]
    4068 [ +  + ][ -  + ]:        206 :         SCAN_FIELD_NESTED_FUNC("vxlan(gbp(", uint32_t, vxlan_gbp, vxlan_gbp_to_attr);
         [ +  - ][ +  - ]
                 [ +  - ]
    4069 [ +  + ][ -  + ]:        189 :         SCAN_FIELD_NESTED_FUNC("geneve(", struct geneve_scan, geneve,
         [ +  - ][ +  - ]
                 [ +  - ]
    4070                 :            :                                geneve_to_attr);
    4071 [ +  - ][ -  + ]:        167 :         SCAN_FIELD_NESTED_FUNC("flags(", uint16_t, tun_flags, tun_flags_to_attr);
         [ +  - ][ +  - ]
                 [ +  - ]
    4072 [ +  + ][ +  - ]:        950 :     } SCAN_END_NESTED();
         [ -  + ][ +  - ]
    4073                 :            : 
    4074 [ +  + ][ -  + ]:      11598 :     SCAN_SINGLE_PORT("in_port(", uint32_t, OVS_KEY_ATTR_IN_PORT);
         [ -  + ][ -  + ]
         [ +  + ][ -  + ]
    4075                 :            : 
    4076         [ +  + ]:       9447 :     SCAN_BEGIN("eth(", struct ovs_key_ethernet) {
    4077 [ +  + ][ +  + ]:       4272 :         SCAN_FIELD("src=", eth, eth_src);
                 [ -  + ]
    4078 [ +  - ][ +  + ]:       2136 :         SCAN_FIELD("dst=", eth, eth_dst);
                 [ -  + ]
    4079 [ +  + ][ +  - ]:       4272 :     } SCAN_END(OVS_KEY_ATTR_ETHERNET);
         [ -  + ][ -  + ]
         [ +  + ][ -  + ]
    4080                 :            : 
    4081         [ +  + ]:       7311 :     SCAN_BEGIN_INIT("vlan(", struct ovs_key_vlan__,
    4082                 :            :                     { htons(VLAN_CFI) }, { htons(VLAN_CFI) }) {
    4083 [ +  + ][ +  + ]:        720 :         SCAN_FIELD("vid=", vid, tci);
                 [ -  + ]
    4084 [ +  - ][ +  + ]:        360 :         SCAN_FIELD("pcp=", pcp, tci);
                 [ -  + ]
    4085 [ #  # ][ #  # ]:          0 :         SCAN_FIELD("cfi=", cfi, tci);
                 [ #  # ]
    4086 [ +  + ][ +  - ]:        720 :     } SCAN_END(OVS_KEY_ATTR_VLAN);
         [ -  + ][ -  + ]
         [ +  + ][ -  + ]
    4087                 :            : 
    4088 [ +  + ][ -  + ]:       6951 :     SCAN_SINGLE("eth_type(", ovs_be16, be16, OVS_KEY_ATTR_ETHERTYPE);
         [ -  + ][ -  + ]
         [ +  + ][ -  + ]
    4089                 :            : 
    4090         [ +  + ]:       4474 :     SCAN_BEGIN_ARRAY("mpls(", struct ovs_key_mpls, FLOW_MAX_MPLS_LABELS) {
    4091 [ +  + ][ +  + ]:        244 :         SCAN_FIELD_ARRAY("label=", mpls_label, mpls_lse);
         [ -  + ][ +  + ]
                 [ -  + ]
    4092 [ +  + ][ -  + ]:        183 :         SCAN_FIELD_ARRAY("tc=", mpls_tc, mpls_lse);
         [ #  # ][ +  + ]
                 [ -  + ]
    4093 [ +  + ][ -  + ]:        122 :         SCAN_FIELD_ARRAY("ttl=", mpls_ttl, mpls_lse);
         [ #  # ][ +  + ]
                 [ -  + ]
    4094 [ +  - ][ -  + ]:         61 :         SCAN_FIELD_ARRAY("bos=", mpls_bos, mpls_lse);
         [ #  # ][ +  + ]
                 [ -  + ]
    4095 [ +  + ][ +  - ]:        244 :     } SCAN_END_ARRAY(OVS_KEY_ATTR_MPLS);
         [ -  + ][ -  + ]
                 [ +  + ]
    4096                 :            : 
    4097         [ +  + ]:       4414 :     SCAN_BEGIN("ipv4(", struct ovs_key_ipv4) {
    4098 [ +  + ][ +  + ]:       8223 :         SCAN_FIELD("src=", ipv4, ipv4_src);
                 [ -  + ]
    4099 [ +  + ][ +  + ]:       6853 :         SCAN_FIELD("dst=", ipv4, ipv4_dst);
                 [ -  + ]
    4100 [ +  + ][ +  + ]:       5484 :         SCAN_FIELD("proto=", u8, ipv4_proto);
                 [ -  + ]
    4101 [ +  + ][ +  + ]:       4116 :         SCAN_FIELD("tos=", u8, ipv4_tos);
                 [ -  + ]
    4102 [ +  + ][ +  + ]:       2746 :         SCAN_FIELD("ttl=", u8, ipv4_ttl);
                 [ -  + ]
    4103 [ +  - ][ +  + ]:       1376 :         SCAN_FIELD("frag=", frag, ipv4_frag);
                 [ -  + ]
    4104 [ +  + ][ +  - ]:       8223 :     } SCAN_END(OVS_KEY_ATTR_IPV4);
         [ -  + ][ -  + ]
         [ +  + ][ -  + ]
    4105                 :            : 
    4106         [ +  + ]:       3035 :     SCAN_BEGIN("ipv6(", struct ovs_key_ipv6) {
    4107 [ +  + ][ +  + ]:       1461 :         SCAN_FIELD("src=", ipv6, ipv6_src);
                 [ -  + ]
    4108 [ +  + ][ +  + ]:       1254 :         SCAN_FIELD("dst=", ipv6, ipv6_dst);
                 [ -  + ]
    4109 [ +  + ][ +  + ]:       1047 :         SCAN_FIELD("label=", ipv6_label, ipv6_label);
                 [ -  + ]
    4110 [ +  + ][ +  + ]:        837 :         SCAN_FIELD("proto=", u8, ipv6_proto);
                 [ -  + ]
    4111 [ +  + ][ +  + ]:        624 :         SCAN_FIELD("tclass=", u8, ipv6_tclass);
                 [ -  + ]
    4112 [ +  + ][ +  + ]:        416 :         SCAN_FIELD("hlimit=", u8, ipv6_hlimit);
                 [ -  + ]
    4113 [ +  - ][ +  + ]:        208 :         SCAN_FIELD("frag=", frag, ipv6_frag);
                 [ -  + ]
    4114 [ +  + ][ +  - ]:       1461 :     } SCAN_END(OVS_KEY_ATTR_IPV6);
         [ -  + ][ -  + ]
         [ +  + ][ -  + ]
    4115                 :            : 
    4116         [ +  + ]:       2820 :     SCAN_BEGIN("tcp(", struct ovs_key_tcp) {
    4117 [ +  + ][ +  + ]:       1454 :         SCAN_FIELD("src=", be16, tcp_src);
                 [ -  + ]
    4118 [ +  - ][ +  + ]:        727 :         SCAN_FIELD("dst=", be16, tcp_dst);
                 [ -  + ]
    4119 [ +  + ][ +  - ]:       1454 :     } SCAN_END(OVS_KEY_ATTR_TCP);
         [ -  + ][ -  + ]
         [ +  + ][ -  + ]
    4120                 :            : 
    4121 [ +  + ][ +  + ]:       2092 :     SCAN_SINGLE("tcp_flags(", ovs_be16, tcp_flags, OVS_KEY_ATTR_TCP_FLAGS);
         [ -  + ][ -  + ]
         [ +  + ][ -  + ]
    4122                 :            : 
    4123         [ +  + ]:       1763 :     SCAN_BEGIN("udp(", struct ovs_key_udp) {
    4124 [ +  + ][ +  + ]:        236 :         SCAN_FIELD("src=", be16, udp_src);
                 [ -  + ]
    4125 [ +  - ][ +  + ]:        118 :         SCAN_FIELD("dst=", be16, udp_dst);
                 [ -  + ]
    4126 [ +  + ][ +  - ]:        236 :     } SCAN_END(OVS_KEY_ATTR_UDP);
         [ -  + ][ -  + ]
         [ +  + ][ -  + ]
    4127                 :            : 
    4128         [ +  + ]:       1644 :     SCAN_BEGIN("sctp(", struct ovs_key_sctp) {
    4129 [ +  + ][ +  - ]:          6 :         SCAN_FIELD("src=", be16, sctp_src);
                 [ -  + ]
    4130 [ +  - ][ +  - ]:          3 :         SCAN_FIELD("dst=", be16, sctp_dst);
                 [ -  + ]
    4131 [ +  + ][ +  - ]:          6 :     } SCAN_END(OVS_KEY_ATTR_SCTP);
         [ -  + ][ -  + ]
         [ +  - ][ -  + ]
    4132                 :            : 
    4133         [ +  + ]:       1640 :     SCAN_BEGIN("icmp(", struct ovs_key_icmp) {
    4134 [ +  + ][ +  + ]:        854 :         SCAN_FIELD("type=", u8, icmp_type);
                 [ -  + ]
    4135 [ +  - ][ +  + ]:        427 :         SCAN_FIELD("code=", u8, icmp_code);
                 [ -  + ]
    4136 [ +  + ][ +  - ]:        854 :     } SCAN_END(OVS_KEY_ATTR_ICMP);
         [ -  + ][ -  + ]
         [ +  + ][ -  + ]
    4137                 :            : 
    4138         [ +  + ]:       1213 :     SCAN_BEGIN("icmpv6(", struct ovs_key_icmpv6) {
    4139 [ +  + ][ +  + ]:        178 :         SCAN_FIELD("type=", u8, icmpv6_type);
                 [ -  + ]
    4140 [ +  - ][ +  + ]:         87 :         SCAN_FIELD("code=", u8, icmpv6_code);
                 [ -  + ]
    4141 [ +  + ][ +  - ]:        178 :     } SCAN_END(OVS_KEY_ATTR_ICMPV6);
         [ -  + ][ -  + ]
         [ +  + ][ -  + ]
    4142                 :            : 
    4143         [ +  + ]:       1122 :     SCAN_BEGIN("arp(", struct ovs_key_arp) {
    4144 [ +  + ][ +  + ]:        610 :         SCAN_FIELD("sip=", ipv4, arp_sip);
                 [ -  + ]
    4145 [ +  + ][ +  + ]:        488 :         SCAN_FIELD("tip=", ipv4, arp_tip);
                 [ -  + ]
    4146 [ +  + ][ +  + ]:        366 :         SCAN_FIELD("op=", be16, arp_op);
                 [ -  + ]
    4147 [ +  + ][ +  + ]:        244 :         SCAN_FIELD("sha=", eth, arp_sha);
                 [ -  + ]
    4148 [ +  - ][ +  + ]:        122 :         SCAN_FIELD("tha=", eth, arp_tha);
                 [ -  + ]
    4149 [ +  + ][ +  - ]:        610 :     } SCAN_END(OVS_KEY_ATTR_ARP);
         [ -  + ][ -  + ]
         [ +  + ][ -  + ]
    4150                 :            : 
    4151         [ +  + ]:       1000 :     SCAN_BEGIN("nd(", struct ovs_key_nd) {
    4152 [ +  + ][ +  + ]:        164 :         SCAN_FIELD("target=", ipv6, nd_target);
                 [ -  + ]
    4153 [ +  + ][ +  + ]:         96 :         SCAN_FIELD("sll=", eth, nd_sll);
                 [ -  + ]
    4154 [ +  - ][ +  + ]:         48 :         SCAN_FIELD("tll=", eth, nd_tll);
                 [ -  + ]
    4155 [ +  + ][ +  - ]:        164 :     } SCAN_END(OVS_KEY_ATTR_ND);
         [ -  + ][ -  + ]
         [ +  + ][ -  + ]
    4156                 :            : 
    4157                 :            :     /* Encap open-coded. */
    4158         [ +  + ]:        932 :     if (!strncmp(s, "encap(", 6)) {
    4159                 :        360 :         const char *start = s;
    4160                 :        360 :         size_t encap, encap_mask = 0;
    4161                 :            : 
    4162                 :        360 :         encap = nl_msg_start_nested(key, OVS_KEY_ATTR_ENCAP);
    4163         [ +  + ]:        360 :         if (mask) {
    4164                 :        190 :             encap_mask = nl_msg_start_nested(mask, OVS_KEY_ATTR_ENCAP);
    4165                 :            :         }
    4166                 :            : 
    4167                 :        360 :         s += 6;
    4168                 :            :         for (;;) {
    4169                 :            :             int retval;
    4170                 :            : 
    4171                 :        924 :             s += strspn(s, delimiters);
    4172         [ -  + ]:        924 :             if (!*s) {
    4173                 :          0 :                 return -EINVAL;
    4174         [ +  + ]:        924 :             } else if (*s == ')') {
    4175                 :        360 :                 break;
    4176                 :            :             }
    4177                 :            : 
    4178                 :        564 :             retval = parse_odp_key_mask_attr(s, port_names, key, mask);
    4179         [ -  + ]:        564 :             if (retval < 0) {
    4180                 :          0 :                 return retval;
    4181                 :            :             }
    4182                 :        564 :             s += retval;
    4183                 :        564 :         }
    4184                 :        360 :         s++;
    4185                 :            : 
    4186                 :        360 :         nl_msg_end_nested(key, encap);
    4187         [ +  + ]:        360 :         if (mask) {
    4188                 :        190 :             nl_msg_end_nested(mask, encap_mask);
    4189                 :            :         }
    4190                 :            : 
    4191                 :        360 :         return s - start;
    4192                 :            :     }
    4193                 :            : 
    4194                 :      12711 :     return -EINVAL;
    4195                 :            : }
    4196                 :            : 
    4197                 :            : /* Parses the string representation of a datapath flow key, in the
    4198                 :            :  * format output by odp_flow_key_format().  Returns 0 if successful,
    4199                 :            :  * otherwise a positive errno value.  On success, the flow key is
    4200                 :            :  * appended to 'key' as a series of Netlink attributes.  On failure, no
    4201                 :            :  * data is appended to 'key'.  Either way, 'key''s data might be
    4202                 :            :  * reallocated.
    4203                 :            :  *
    4204                 :            :  * If 'port_names' is nonnull, it points to an simap that maps from a port name
    4205                 :            :  * to a port number.  (Port names may be used instead of port numbers in
    4206                 :            :  * in_port.)
    4207                 :            :  *
    4208                 :            :  * On success, the attributes appended to 'key' are individually syntactically
    4209                 :            :  * valid, but they may not be valid as a sequence.  'key' might, for example,
    4210                 :            :  * have duplicated keys.  odp_flow_key_to_flow() will detect those errors. */
    4211                 :            : int
    4212                 :       2730 : odp_flow_from_string(const char *s, const struct simap *port_names,
    4213                 :            :                      struct ofpbuf *key, struct ofpbuf *mask)
    4214                 :            : {
    4215                 :       2730 :     const size_t old_size = key->size;
    4216                 :            :     for (;;) {
    4217                 :            :         int retval;
    4218                 :            : 
    4219                 :      14268 :         s += strspn(s, delimiters);
    4220         [ +  + ]:      14268 :         if (!*s) {
    4221                 :       2155 :             return 0;
    4222                 :            :         }
    4223                 :            : 
    4224                 :      12113 :         retval = parse_odp_key_mask_attr(s, port_names, key, mask);
    4225         [ +  + ]:      12113 :         if (retval < 0) {
    4226                 :        575 :             key->size = old_size;
    4227                 :        575 :             return -retval;
    4228                 :            :         }
    4229                 :      11538 :         s += retval;
    4230                 :      11538 :     }
    4231                 :            : 
    4232                 :            :     return 0;
    4233                 :            : }
    4234                 :            : 
    4235                 :            : static uint8_t
    4236                 :     176898 : ovs_to_odp_frag(uint8_t nw_frag, bool is_mask)
    4237                 :            : {
    4238         [ +  + ]:     176898 :     if (is_mask) {
    4239                 :            :         /* Netlink interface 'enum ovs_frag_type' is an 8-bit enumeration type,
    4240                 :            :          * not a set of flags or bitfields. Hence, if the struct flow nw_frag
    4241                 :            :          * mask, which is a set of bits, has the FLOW_NW_FRAG_ANY as zero, we
    4242                 :            :          * must use a zero mask for the netlink frag field, and all ones mask
    4243                 :            :          * otherwise. */
    4244         [ +  - ]:      61066 :         return (nw_frag & FLOW_NW_FRAG_ANY) ? UINT8_MAX : 0;
    4245                 :            :     }
    4246 [ +  + ][ +  + ]:     115832 :     return !(nw_frag & FLOW_NW_FRAG_ANY) ? OVS_FRAG_TYPE_NONE
    4247                 :        588 :         : nw_frag & FLOW_NW_FRAG_LATER ? OVS_FRAG_TYPE_LATER
    4248                 :            :         : OVS_FRAG_TYPE_FIRST;
    4249                 :            : }
    4250                 :            : 
    4251                 :            : static void get_ethernet_key(const struct flow *, struct ovs_key_ethernet *);
    4252                 :            : static void put_ethernet_key(const struct ovs_key_ethernet *, struct flow *);
    4253                 :            : static void get_ipv4_key(const struct flow *, struct ovs_key_ipv4 *,
    4254                 :            :                          bool is_mask);
    4255                 :            : static void put_ipv4_key(const struct ovs_key_ipv4 *, struct flow *,
    4256                 :            :                          bool is_mask);
    4257                 :            : static void get_ipv6_key(const struct flow *, struct ovs_key_ipv6 *,
    4258                 :            :                          bool is_mask);
    4259                 :            : static void put_ipv6_key(const struct ovs_key_ipv6 *, struct flow *,
    4260                 :            :                          bool is_mask);
    4261                 :            : static void get_arp_key(const struct flow *, struct ovs_key_arp *);
    4262                 :            : static void put_arp_key(const struct ovs_key_arp *, struct flow *);
    4263                 :            : static void get_nd_key(const struct flow *, struct ovs_key_nd *);
    4264                 :            : static void put_nd_key(const struct ovs_key_nd *, struct flow *);
    4265                 :            : 
    4266                 :            : /* These share the same layout. */
    4267                 :            : union ovs_key_tp {
    4268                 :            :     struct ovs_key_tcp tcp;
    4269                 :            :     struct ovs_key_udp udp;
    4270                 :            :     struct ovs_key_sctp sctp;
    4271                 :            : };
    4272                 :            : 
    4273                 :            : static void get_tp_key(const struct flow *, union ovs_key_tp *);
    4274                 :            : static void put_tp_key(const union ovs_key_tp *, struct flow *);
    4275                 :            : 
    4276                 :            : static void
    4277                 :      32151 : odp_flow_key_from_flow__(const struct odp_flow_key_parms *parms,
    4278                 :            :                          bool export_mask, struct ofpbuf *buf)
    4279                 :            : {
    4280                 :            :     struct ovs_key_ethernet *eth_key;
    4281                 :            :     size_t encap;
    4282                 :      32151 :     const struct flow *flow = parms->flow;
    4283         [ +  + ]:      32151 :     const struct flow *data = export_mask ? parms->mask : parms->flow;
    4284                 :            : 
    4285                 :      32151 :     nl_msg_put_u32(buf, OVS_KEY_ATTR_PRIORITY, data->skb_priority);
    4286                 :            : 
    4287 [ +  + ][ +  + ]:      32151 :     if (flow_tnl_dst_is_set(&flow->tunnel) || export_mask) {
    4288                 :      14015 :         tun_key_to_attr(buf, &data->tunnel, &parms->flow->tunnel,
    4289                 :            :                         parms->key_buf);
    4290                 :            :     }
    4291                 :            : 
    4292                 :      32151 :     nl_msg_put_u32(buf, OVS_KEY_ATTR_SKB_MARK, data->pkt_mark);
    4293                 :            : 
    4294         [ +  + ]:      32151 :     if (parms->support.ct_state) {
    4295                 :      27302 :         nl_msg_put_u32(buf, OVS_KEY_ATTR_CT_STATE,
    4296                 :      27302 :                        ovs_to_odp_ct_state(data->ct_state));
    4297                 :            :     }
    4298         [ +  + ]:      32151 :     if (parms->support.ct_zone) {
    4299                 :      26688 :         nl_msg_put_u16(buf, OVS_KEY_ATTR_CT_ZONE, data->ct_zone);
    4300                 :            :     }
    4301         [ +  + ]:      32151 :     if (parms->support.ct_mark) {
    4302                 :      26688 :         nl_msg_put_u32(buf, OVS_KEY_ATTR_CT_MARK, data->ct_mark);
    4303                 :            :     }
    4304         [ +  + ]:      32151 :     if (parms->support.ct_label) {
    4305                 :      26688 :         nl_msg_put_unspec(buf, OVS_KEY_ATTR_CT_LABELS, &data->ct_label,
    4306                 :            :                           sizeof(data->ct_label));
    4307                 :            :     }
    4308         [ +  + ]:      32151 :     if (parms->support.recirc) {
    4309                 :      26688 :         nl_msg_put_u32(buf, OVS_KEY_ATTR_RECIRC_ID, data->recirc_id);
    4310                 :      26688 :         nl_msg_put_u32(buf, OVS_KEY_ATTR_DP_HASH, data->dp_hash);
    4311                 :            :     }
    4312                 :            : 
    4313                 :            :     /* Add an ingress port attribute if this is a mask or 'in_port.odp_port'
    4314                 :            :      * is not the magical value "ODPP_NONE". */
    4315 [ +  + ][ +  - ]:      32151 :     if (export_mask || flow->in_port.odp_port != ODPP_NONE) {
    4316                 :      32151 :         nl_msg_put_odp_port(buf, OVS_KEY_ATTR_IN_PORT, data->in_port.odp_port);
    4317                 :            :     }
    4318                 :            : 
    4319                 :      32151 :     eth_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_ETHERNET,
    4320                 :            :                                        sizeof *eth_key);
    4321                 :      32151 :     get_ethernet_key(data, eth_key);
    4322                 :            : 
    4323 [ +  + ][ -  + ]:      32151 :     if (flow->vlan_tci != htons(0) || flow->dl_type == htons(ETH_TYPE_VLAN)) {
    4324         [ +  + ]:        274 :         if (export_mask) {
    4325                 :        133 :             nl_msg_put_be16(buf, OVS_KEY_ATTR_ETHERTYPE, OVS_BE16_MAX);
    4326                 :            :         } else {
    4327                 :        141 :             nl_msg_put_be16(buf, OVS_KEY_ATTR_ETHERTYPE, htons(ETH_TYPE_VLAN));
    4328                 :            :         }
    4329                 :        274 :         nl_msg_put_be16(buf, OVS_KEY_ATTR_VLAN, data->vlan_tci);
    4330                 :        274 :         encap = nl_msg_start_nested(buf, OVS_KEY_ATTR_ENCAP);
    4331         [ -  + ]:        274 :         if (flow->vlan_tci == htons(0)) {
    4332                 :          0 :             goto unencap;
    4333                 :            :         }
    4334                 :            :     } else {
    4335                 :      31877 :         encap = 0;
    4336                 :            :     }
    4337                 :            : 
    4338         [ +  + ]:      32151 :     if (ntohs(flow->dl_type) < ETH_TYPE_MIN) {
    4339                 :            :         /* For backwards compatibility with kernels that don't support
    4340                 :            :          * wildcarding, the following convention is used to encode the
    4341                 :            :          * OVS_KEY_ATTR_ETHERTYPE for key and mask:
    4342                 :            :          *
    4343                 :            :          *   key      mask    matches
    4344                 :            :          * -------- --------  -------
    4345                 :            :          *  >0x5ff   0xffff   Specified Ethernet II Ethertype.
    4346                 :            :          *  >0x5ff      0     Any Ethernet II or non-Ethernet II frame.
    4347                 :            :          *  <none>   0xffff   Any non-Ethernet II frame (except valid
    4348                 :            :          *                    802.3 SNAP packet with valid eth_type).
    4349                 :            :          */
    4350         [ +  + ]:       9333 :         if (export_mask) {
    4351                 :       2821 :             nl_msg_put_be16(buf, OVS_KEY_ATTR_ETHERTYPE, OVS_BE16_MAX);
    4352                 :            :         }
    4353                 :       9333 :         goto unencap;
    4354                 :            :     }
    4355                 :            : 
    4356                 :      22818 :     nl_msg_put_be16(buf, OVS_KEY_ATTR_ETHERTYPE, data->dl_type);
    4357                 :            : 
    4358         [ +  + ]:      22818 :     if (flow->dl_type == htons(ETH_TYPE_IP)) {
    4359                 :            :         struct ovs_key_ipv4 *ipv4_key;
    4360                 :            : 
    4361                 :      11121 :         ipv4_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_IPV4,
    4362                 :            :                                             sizeof *ipv4_key);
    4363                 :      11121 :         get_ipv4_key(data, ipv4_key, export_mask);
    4364         [ +  + ]:      11697 :     } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
    4365                 :            :         struct ovs_key_ipv6 *ipv6_key;
    4366                 :            : 
    4367                 :       1314 :         ipv6_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_IPV6,
    4368                 :            :                                             sizeof *ipv6_key);
    4369                 :       1314 :         get_ipv6_key(data, ipv6_key, export_mask);
    4370   [ +  +  +  + ]:      19208 :     } else if (flow->dl_type == htons(ETH_TYPE_ARP) ||
    4371                 :      10403 :                flow->dl_type == htons(ETH_TYPE_RARP)) {
    4372                 :            :         struct ovs_key_arp *arp_key;
    4373                 :            : 
    4374                 :       1578 :         arp_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_ARP,
    4375                 :            :                                            sizeof *arp_key);
    4376                 :       1578 :         get_arp_key(data, arp_key);
    4377         [ +  + ]:       8805 :     } else if (eth_type_mpls(flow->dl_type)) {
    4378                 :            :         struct ovs_key_mpls *mpls_key;
    4379                 :            :         int i, n;
    4380                 :            : 
    4381                 :       5224 :         n = flow_count_mpls_labels(flow, NULL);
    4382         [ +  + ]:       5224 :         if (export_mask) {
    4383                 :       1701 :             n = MIN(n, parms->support.max_mpls_depth);
    4384                 :            :         }
    4385                 :       5224 :         mpls_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_MPLS,
    4386                 :            :                                             n * sizeof *mpls_key);
    4387         [ +  + ]:      15514 :         for (i = 0; i < n; i++) {
    4388                 :      10290 :             mpls_key[i].mpls_lse = data->mpls_lse[i];
    4389                 :            :         }
    4390                 :            :     }
    4391                 :            : 
    4392 [ +  + ][ +  + ]:      22818 :     if (is_ip_any(flow) && !(flow->nw_frag & FLOW_NW_FRAG_LATER)) {
    4393         [ +  + ]:      12308 :         if (flow->nw_proto == IPPROTO_TCP) {
    4394                 :            :             union ovs_key_tp *tcp_key;
    4395                 :            : 
    4396                 :       4741 :             tcp_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_TCP,
    4397                 :            :                                                sizeof *tcp_key);
    4398                 :       4741 :             get_tp_key(data, tcp_key);
    4399         [ +  + ]:       4741 :             if (data->tcp_flags) {
    4400                 :       4741 :                 nl_msg_put_be16(buf, OVS_KEY_ATTR_TCP_FLAGS, data->tcp_flags);
    4401                 :            :             }
    4402         [ +  + ]:       7567 :         } else if (flow->nw_proto == IPPROTO_UDP) {
    4403                 :            :             union ovs_key_tp *udp_key;
    4404                 :            : 
    4405                 :       3749 :             udp_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_UDP,
    4406                 :            :                                                sizeof *udp_key);
    4407                 :       3749 :             get_tp_key(data, udp_key);
    4408         [ +  + ]:       3818 :         } else if (flow->nw_proto == IPPROTO_SCTP) {
    4409                 :            :             union ovs_key_tp *sctp_key;
    4410                 :            : 
    4411                 :          2 :             sctp_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_SCTP,
    4412                 :            :                                                sizeof *sctp_key);
    4413                 :          2 :             get_tp_key(data, sctp_key);
    4414         [ +  + ]:       3816 :         } else if (flow->dl_type == htons(ETH_TYPE_IP)
    4415         [ +  + ]:       5094 :                 && flow->nw_proto == IPPROTO_ICMP) {
    4416                 :            :             struct ovs_key_icmp *icmp_key;
    4417                 :            : 
    4418                 :       2480 :             icmp_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_ICMP,
    4419                 :            :                                                 sizeof *icmp_key);
    4420                 :       2480 :             icmp_key->icmp_type = ntohs(data->tp_src);
    4421                 :       2480 :             icmp_key->icmp_code = ntohs(data->tp_dst);
    4422         [ +  + ]:       1336 :         } else if (flow->dl_type == htons(ETH_TYPE_IPV6)
    4423         [ +  + ]:       1202 :                 && flow->nw_proto == IPPROTO_ICMPV6) {
    4424                 :            :             struct ovs_key_icmpv6 *icmpv6_key;
    4425                 :            : 
    4426                 :       1161 :             icmpv6_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_ICMPV6,
    4427                 :            :                                                   sizeof *icmpv6_key);
    4428                 :       1161 :             icmpv6_key->icmpv6_type = ntohs(data->tp_src);
    4429                 :       1161 :             icmpv6_key->icmpv6_code = ntohs(data->tp_dst);
    4430                 :            : 
    4431         [ +  + ]:       1161 :             if (is_nd(flow, NULL)
    4432                 :            :                 /* Even though 'tp_src' and 'tp_dst' are 16 bits wide, ICMP
    4433                 :            :                  * type and code are 8 bits wide.  Therefore, an exact match
    4434                 :            :                  * looks like htons(0xff), not htons(0xffff).  See
    4435                 :            :                  * xlate_wc_finish() for details. */
    4436 [ +  + ][ +  + ]:        319 :                 && (!export_mask || (data->tp_src == htons(0xff)
    4437         [ +  + ]:         45 :                                      && data->tp_dst == htons(0xff)))) {
    4438                 :            : 
    4439                 :            :                 struct ovs_key_nd *nd_key;
    4440                 :            : 
    4441                 :        119 :                 nd_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_ND,
    4442                 :            :                                                     sizeof *nd_key);
    4443                 :        119 :                 memcpy(nd_key->nd_target, &data->nd_target,
    4444                 :            :                         sizeof nd_key->nd_target);
    4445                 :        119 :                 nd_key->nd_sll = data->arp_sha;
    4446                 :        119 :                 nd_key->nd_tll = data->arp_tha;
    4447                 :            :             }
    4448                 :            :         }
    4449                 :            :     }
    4450                 :            : 
    4451                 :            : unencap:
    4452         [ +  + ]:      32151 :     if (encap) {
    4453                 :        274 :         nl_msg_end_nested(buf, encap);
    4454                 :            :     }
    4455                 :      32151 : }
    4456                 :            : 
    4457                 :            : /* Appends a representation of 'flow' as OVS_KEY_ATTR_* attributes to 'buf'.
    4458                 :            :  *
    4459                 :            :  * 'buf' must have at least ODPUTIL_FLOW_KEY_BYTES bytes of space, or be
    4460                 :            :  * capable of being expanded to allow for that much space. */
    4461                 :            : void
    4462                 :      19042 : odp_flow_key_from_flow(const struct odp_flow_key_parms *parms,
    4463                 :            :                        struct ofpbuf *buf)
    4464                 :            : {
    4465                 :      19042 :     odp_flow_key_from_flow__(parms, false, buf);
    4466                 :      19042 : }
    4467                 :            : 
    4468                 :            : /* Appends a representation of 'mask' as OVS_KEY_ATTR_* attributes to
    4469                 :            :  * 'buf'.
    4470                 :            :  *
    4471                 :            :  * 'buf' must have at least ODPUTIL_FLOW_KEY_BYTES bytes of space, or be
    4472                 :            :  * capable of being expanded to allow for that much space. */
    4473                 :            : void
    4474                 :      13109 : odp_flow_key_from_mask(const struct odp_flow_key_parms *parms,
    4475                 :            :                        struct ofpbuf *buf)
    4476                 :            : {
    4477                 :      13109 :     odp_flow_key_from_flow__(parms, true, buf);
    4478                 :      13109 : }
    4479                 :            : 
    4480                 :            : /* Generate ODP flow key from the given packet metadata */
    4481                 :            : void
    4482                 :       1217 : odp_key_from_pkt_metadata(struct ofpbuf *buf, const struct pkt_metadata *md)
    4483                 :            : {
    4484                 :       1217 :     nl_msg_put_u32(buf, OVS_KEY_ATTR_PRIORITY, md->skb_priority);
    4485                 :            : 
    4486         [ +  + ]:       1217 :     if (flow_tnl_dst_is_set(&md->tunnel)) {
    4487                 :         38 :         tun_key_to_attr(buf, &md->tunnel, &md->tunnel, NULL);
    4488                 :            :     }
    4489                 :            : 
    4490                 :       1217 :     nl_msg_put_u32(buf, OVS_KEY_ATTR_SKB_MARK, md->pkt_mark);
    4491                 :            : 
    4492         [ +  + ]:       1217 :     if (md->ct_state) {
    4493                 :        406 :         nl_msg_put_u32(buf, OVS_KEY_ATTR_CT_STATE,
    4494                 :        406 :                        ovs_to_odp_ct_state(md->ct_state));
    4495         [ +  + ]:        406 :         if (md->ct_zone) {
    4496                 :        212 :             nl_msg_put_u16(buf, OVS_KEY_ATTR_CT_ZONE, md->ct_zone);
    4497                 :            :         }
    4498         [ +  + ]:        406 :         if (md->ct_mark) {
    4499                 :          8 :             nl_msg_put_u32(buf, OVS_KEY_ATTR_CT_MARK, md->ct_mark);
    4500                 :            :         }
    4501         [ +  + ]:        406 :         if (!ovs_u128_is_zero(md->ct_label)) {
    4502                 :          5 :             nl_msg_put_unspec(buf, OVS_KEY_ATTR_CT_LABELS, &md->ct_label,
    4503                 :            :                               sizeof(md->ct_label));
    4504                 :            :         }
    4505                 :            :     }
    4506                 :            : 
    4507                 :            :     /* Add an ingress port attribute if 'odp_in_port' is not the magical
    4508                 :            :      * value "ODPP_NONE". */
    4509         [ +  - ]:       1217 :     if (md->in_port.odp_port != ODPP_NONE) {
    4510                 :       1217 :         nl_msg_put_odp_port(buf, OVS_KEY_ATTR_IN_PORT, md->in_port.odp_port);
    4511                 :            :     }
    4512                 :       1217 : }
    4513                 :            : 
    4514                 :            : /* Generate packet metadata from the given ODP flow key. */
    4515                 :            : void
    4516                 :        997 : odp_key_to_pkt_metadata(const struct nlattr *key, size_t key_len,
    4517                 :            :                         struct pkt_metadata *md)
    4518                 :            : {
    4519                 :            :     const struct nlattr *nla;
    4520                 :            :     size_t left;
    4521                 :        997 :     uint32_t wanted_attrs = 1u << OVS_KEY_ATTR_PRIORITY |
    4522                 :            :         1u << OVS_KEY_ATTR_SKB_MARK | 1u << OVS_KEY_ATTR_TUNNEL |
    4523                 :            :         1u << OVS_KEY_ATTR_IN_PORT;
    4524                 :            : 
    4525                 :        997 :     pkt_metadata_init(md, ODPP_NONE);
    4526                 :            : 
    4527         [ +  + ]:      14015 :     NL_ATTR_FOR_EACH (nla, left, key, key_len) {
    4528                 :      13051 :         uint16_t type = nl_attr_type(nla);
    4529                 :      13051 :         size_t len = nl_attr_get_size(nla);
    4530                 :      13051 :         int expected_len = odp_key_attr_len(ovs_flow_key_attr_lens,
    4531                 :            :                                             OVS_KEY_ATTR_MAX, type);
    4532                 :            : 
    4533 [ +  + ][ -  + ]:      13051 :         if (len != expected_len && expected_len >= 0) {
    4534                 :          0 :             continue;
    4535                 :            :         }
    4536                 :            : 
    4537   [ +  +  +  +  :      13051 :         switch (type) {
          +  +  +  +  +  
                   +  + ]
    4538                 :            :         case OVS_KEY_ATTR_RECIRC_ID:
    4539                 :        997 :             md->recirc_id = nl_attr_get_u32(nla);
    4540                 :        997 :             wanted_attrs &= ~(1u << OVS_KEY_ATTR_RECIRC_ID);
    4541                 :        997 :             break;
    4542                 :            :         case OVS_KEY_ATTR_DP_HASH:
    4543                 :        997 :             md->dp_hash = nl_attr_get_u32(nla);
    4544                 :        997 :             wanted_attrs &= ~(1u << OVS_KEY_ATTR_DP_HASH);
    4545                 :        997 :             break;
    4546                 :            :         case OVS_KEY_ATTR_PRIORITY:
    4547                 :        997 :             md->skb_priority = nl_attr_get_u32(nla);
    4548                 :        997 :             wanted_attrs &= ~(1u << OVS_KEY_ATTR_PRIORITY);
    4549                 :        997 :             break;
    4550                 :            :         case OVS_KEY_ATTR_SKB_MARK:
    4551                 :        997 :             md->pkt_mark = nl_attr_get_u32(nla);
    4552                 :        997 :             wanted_attrs &= ~(1u << OVS_KEY_ATTR_SKB_MARK);
    4553                 :        997 :             break;
    4554                 :            :         case OVS_KEY_ATTR_CT_STATE:
    4555                 :        964 :             md->ct_state = odp_to_ovs_ct_state(nl_attr_get_u32(nla));
    4556                 :        964 :             wanted_attrs &= ~(1u << OVS_KEY_ATTR_CT_STATE);
    4557                 :        964 :             break;
    4558                 :            :         case OVS_KEY_ATTR_CT_ZONE:
    4559                 :        964 :             md->ct_zone = nl_attr_get_u16(nla);
    4560                 :        964 :             wanted_attrs &= ~(1u << OVS_KEY_ATTR_CT_ZONE);
    4561                 :        964 :             break;
    4562                 :            :         case OVS_KEY_ATTR_CT_MARK:
    4563                 :        964 :             md->ct_mark = nl_attr_get_u32(nla);
    4564                 :        964 :             wanted_attrs &= ~(1u << OVS_KEY_ATTR_CT_MARK);
    4565                 :        964 :             break;
    4566                 :            :         case OVS_KEY_ATTR_CT_LABELS: {
    4567                 :        964 :             const ovs_u128 *cl = nl_attr_get(nla);
    4568                 :            : 
    4569                 :        964 :             md->ct_label = *cl;
    4570                 :        964 :             wanted_attrs &= ~(1u << OVS_KEY_ATTR_CT_LABELS);
    4571                 :        964 :             break;
    4572                 :            :         }
    4573                 :            :         case OVS_KEY_ATTR_TUNNEL: {
    4574                 :            :             enum odp_key_fitness res;
    4575                 :            : 
    4576                 :         33 :             res = odp_tun_key_from_attr(nla, true, &md->tunnel);
    4577         [ -  + ]:         33 :             if (res == ODP_FIT_ERROR) {
    4578                 :          0 :                 memset(&md->tunnel, 0, sizeof md->tunnel);
    4579         [ +  - ]:         33 :             } else if (res == ODP_FIT_PERFECT) {
    4580                 :         33 :                 wanted_attrs &= ~(1u << OVS_KEY_ATTR_TUNNEL);
    4581                 :            :             }
    4582                 :         33 :             break;
    4583                 :            :         }
    4584                 :            :         case OVS_KEY_ATTR_IN_PORT:
    4585                 :        997 :             md->in_port.odp_port = nl_attr_get_odp_port(nla);
    4586                 :        997 :             wanted_attrs &= ~(1u << OVS_KEY_ATTR_IN_PORT);
    4587                 :        997 :             break;
    4588                 :            :         default:
    4589                 :       4177 :             break;
    4590                 :            :         }
    4591                 :            : 
    4592         [ +  + ]:      13051 :         if (!wanted_attrs) {
    4593                 :         33 :             return; /* Have everything. */
    4594                 :            :         }
    4595                 :            :     }
    4596                 :            : }
    4597                 :            : 
    4598                 :            : uint32_t
    4599                 :          0 : odp_flow_key_hash(const struct nlattr *key, size_t key_len)
    4600                 :            : {
    4601                 :            :     BUILD_ASSERT_DECL(!(NLA_ALIGNTO % sizeof(uint32_t)));
    4602                 :          0 :     return hash_bytes32(ALIGNED_CAST(const uint32_t *, key), key_len, 0);
    4603                 :            : }
    4604                 :            : 
    4605                 :            : static void
    4606                 :        135 : log_odp_key_attributes(struct vlog_rate_limit *rl, const char *title,
    4607                 :            :                        uint64_t attrs, int out_of_range_attr,
    4608                 :            :                        const struct nlattr *key, size_t key_len)
    4609                 :            : {
    4610                 :            :     struct ds s;
    4611                 :            :     int i;
    4612                 :            : 
    4613         [ +  - ]:        135 :     if (VLOG_DROP_DBG(rl)) {
    4614                 :        135 :         return;
    4615                 :            :     }
    4616                 :            : 
    4617                 :          0 :     ds_init(&s);
    4618         [ #  # ]:          0 :     for (i = 0; i < 64; i++) {
    4619         [ #  # ]:          0 :         if (attrs & (UINT64_C(1) << i)) {
    4620                 :            :             char namebuf[OVS_KEY_ATTR_BUFSIZE];
    4621                 :            : 
    4622                 :          0 :             ds_put_format(&s, " %s",
    4623                 :            :                           ovs_key_attr_to_string(i, namebuf, sizeof namebuf));
    4624                 :            :         }
    4625                 :            :     }
    4626         [ #  # ]:          0 :     if (out_of_range_attr) {
    4627                 :          0 :         ds_put_format(&s, " %d (and possibly others)", out_of_range_attr);
    4628                 :            :     }
    4629                 :            : 
    4630                 :          0 :     ds_put_cstr(&s, ": ");
    4631                 :          0 :     odp_flow_key_format(key, key_len, &s);
    4632                 :            : 
    4633         [ #  # ]:          0 :     VLOG_DBG("%s:%s", title, ds_cstr(&s));
    4634                 :          0 :     ds_destroy(&s);
    4635                 :            : }
    4636                 :            : 
    4637                 :            : static uint8_t
    4638                 :      76859 : odp_to_ovs_frag(uint8_t odp_frag, bool is_mask)
    4639                 :            : {
    4640                 :            :     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
    4641                 :            : 
    4642         [ +  + ]:      76859 :     if (is_mask) {
    4643         [ +  - ]:      34346 :         return odp_frag ? FLOW_NW_FRAG_MASK : 0;
    4644                 :            :     }
    4645                 :            : 
    4646         [ -  + ]:      42513 :     if (odp_frag > OVS_FRAG_TYPE_LATER) {
    4647         [ #  # ]:          0 :         VLOG_ERR_RL(&rl, "invalid frag %"PRIu8" in flow key", odp_frag);
    4648                 :          0 :         return 0xff; /* Error. */
    4649                 :            :     }
    4650                 :            : 
    4651 [ +  + ][ +  + ]:      42513 :     return (odp_frag == OVS_FRAG_TYPE_NONE) ? 0
    4652                 :            :         : (odp_frag == OVS_FRAG_TYPE_FIRST) ? FLOW_NW_FRAG_ANY
    4653                 :            :         :  FLOW_NW_FRAG_ANY | FLOW_NW_FRAG_LATER;
    4654                 :            : }
    4655                 :            : 
    4656                 :            : static bool
    4657                 :     157713 : parse_flow_nlattrs(const struct nlattr *key, size_t key_len,
    4658                 :            :                    const struct nlattr *attrs[], uint64_t *present_attrsp,
    4659                 :            :                    int *out_of_range_attrp)
    4660                 :            : {
    4661                 :            :     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(10, 10);
    4662                 :            :     const struct nlattr *nla;
    4663                 :            :     uint64_t present_attrs;
    4664                 :            :     size_t left;
    4665                 :            : 
    4666                 :            :     BUILD_ASSERT(OVS_KEY_ATTR_MAX < CHAR_BIT * sizeof present_attrs);
    4667                 :     157713 :     present_attrs = 0;
    4668                 :     157713 :     *out_of_range_attrp = 0;
    4669         [ +  + ]:    2085036 :     NL_ATTR_FOR_EACH (nla, left, key, key_len) {
    4670                 :    1927323 :         uint16_t type = nl_attr_type(nla);
    4671                 :    1927323 :         size_t len = nl_attr_get_size(nla);
    4672                 :    1927323 :         int expected_len = odp_key_attr_len(ovs_flow_key_attr_lens,
    4673                 :            :                                             OVS_KEY_ATTR_MAX, type);
    4674                 :            : 
    4675 [ +  + ][ -  + ]:    1927323 :         if (len != expected_len && expected_len >= 0) {
    4676                 :            :             char namebuf[OVS_KEY_ATTR_BUFSIZE];
    4677                 :            : 
    4678         [ #  # ]:          0 :             VLOG_ERR_RL(&rl, "attribute %s has length %"PRIuSIZE" but should have "
    4679                 :            :                         "length %d", ovs_key_attr_to_string(type, namebuf,
    4680                 :            :                                                             sizeof namebuf),
    4681                 :            :                         len, expected_len);
    4682                 :          0 :             return false;
    4683                 :            :         }
    4684                 :            : 
    4685         [ -  + ]:    1927323 :         if (type > OVS_KEY_ATTR_MAX) {
    4686                 :          0 :             *out_of_range_attrp = type;
    4687                 :            :         } else {
    4688         [ -  + ]:    1927323 :             if (present_attrs & (UINT64_C(1) << type)) {
    4689                 :            :                 char namebuf[OVS_KEY_ATTR_BUFSIZE];
    4690                 :            : 
    4691         [ #  # ]:          0 :                 VLOG_ERR_RL(&rl, "duplicate %s attribute in flow key",
    4692                 :            :                             ovs_key_attr_to_string(type,
    4693                 :            :                                                    namebuf, sizeof namebuf));
    4694                 :          0 :                 return false;
    4695                 :            :             }
    4696                 :            : 
    4697                 :    1927323 :             present_attrs |= UINT64_C(1) << type;
    4698                 :    1927323 :             attrs[type] = nla;
    4699                 :            :         }
    4700                 :            :     }
    4701         [ -  + ]:     157713 :     if (left) {
    4702         [ #  # ]:          0 :         VLOG_ERR_RL(&rl, "trailing garbage in flow key");
    4703                 :          0 :         return false;
    4704                 :            :     }
    4705                 :            : 
    4706                 :     157713 :     *present_attrsp = present_attrs;
    4707                 :     157713 :     return true;
    4708                 :            : }
    4709                 :            : 
    4710                 :            : static enum odp_key_fitness
    4711                 :     157699 : check_expectations(uint64_t present_attrs, int out_of_range_attr,
    4712                 :            :                    uint64_t expected_attrs,
    4713                 :            :                    const struct nlattr *key, size_t key_len)
    4714                 :            : {
    4715                 :            :     uint64_t missing_attrs;
    4716                 :            :     uint64_t extra_attrs;
    4717                 :            : 
    4718                 :     157699 :     missing_attrs = expected_attrs & ~present_attrs;
    4719         [ +  + ]:     157699 :     if (missing_attrs) {
    4720                 :            :         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(10, 10);
    4721                 :        135 :         log_odp_key_attributes(&rl, "expected but not present",
    4722                 :            :                                missing_attrs, 0, key, key_len);
    4723                 :        135 :         return ODP_FIT_TOO_LITTLE;
    4724                 :            :     }
    4725                 :            : 
    4726                 :     157564 :     extra_attrs = present_attrs & ~expected_attrs;
    4727 [ +  - ][ -  + ]:     157564 :     if (extra_attrs || out_of_range_attr) {
    4728                 :            :         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(10, 10);
    4729                 :          0 :         log_odp_key_attributes(&rl, "present but not expected",
    4730                 :            :                                extra_attrs, out_of_range_attr, key, key_len);
    4731                 :          0 :         return ODP_FIT_TOO_MUCH;
    4732                 :            :     }
    4733                 :            : 
    4734                 :     157564 :     return ODP_FIT_PERFECT;
    4735                 :            : }
    4736                 :            : 
    4737                 :            : static bool
    4738                 :     157713 : parse_ethertype(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
    4739                 :            :                 uint64_t present_attrs, uint64_t *expected_attrs,
    4740                 :            :                 struct flow *flow, const struct flow *src_flow)
    4741                 :            : {
    4742                 :            :     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
    4743                 :     157713 :     bool is_mask = flow != src_flow;
    4744                 :            : 
    4745         [ +  + ]:     157713 :     if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ETHERTYPE)) {
    4746                 :     148713 :         flow->dl_type = nl_attr_get_be16(attrs[OVS_KEY_ATTR_ETHERTYPE]);
    4747 [ +  + ][ -  + ]:     148713 :         if (!is_mask && ntohs(flow->dl_type) < ETH_TYPE_MIN) {
    4748         [ #  # ]:          0 :             VLOG_ERR_RL(&rl, "invalid Ethertype %"PRIu16" in flow key",
    4749                 :            :                         ntohs(flow->dl_type));
    4750                 :          0 :             return false;
    4751                 :            :         }
    4752         [ +  + ]:     148863 :         if (is_mask && ntohs(src_flow->dl_type) < ETH_TYPE_MIN &&
           [ +  +  -  + ]
    4753                 :        150 :             flow->dl_type != htons(0xffff)) {
    4754                 :          0 :             return false;
    4755                 :            :         }
    4756                 :     148713 :         *expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ETHERTYPE;
    4757                 :            :     } else {
    4758         [ +  - ]:       9000 :         if (!is_mask) {
    4759                 :       9000 :             flow->dl_type = htons(FLOW_DL_TYPE_NONE);
    4760         [ #  # ]:          0 :         } else if (ntohs(src_flow->dl_type) < ETH_TYPE_MIN) {
    4761                 :            :             /* See comments in odp_flow_key_from_flow__(). */
    4762         [ #  # ]:          0 :             VLOG_ERR_RL(&rl, "mask expected for non-Ethernet II frame");
    4763                 :          0 :             return false;
    4764                 :            :         }
    4765                 :            :     }
    4766                 :     157713 :     return true;
    4767                 :            : }
    4768                 :            : 
    4769                 :            : static enum odp_key_fitness
    4770                 :     157034 : parse_l2_5_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
    4771                 :            :                   uint64_t present_attrs, int out_of_range_attr,
    4772                 :            :                   uint64_t expected_attrs, struct flow *flow,
    4773                 :            :                   const struct nlattr *key, size_t key_len,
    4774                 :            :                   const struct flow *src_flow)
    4775                 :            : {
    4776                 :            :     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
    4777                 :     157034 :     bool is_mask = src_flow != flow;
    4778                 :     157034 :     const void *check_start = NULL;
    4779                 :     157034 :     size_t check_len = 0;
    4780                 :     157034 :     enum ovs_key_attr expected_bit = 0xff;
    4781                 :            : 
    4782         [ +  + ]:     157034 :     if (eth_type_mpls(src_flow->dl_type)) {
    4783 [ +  + ][ +  - ]:       5056 :         if (!is_mask || present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_MPLS)) {
    4784                 :       5056 :             expected_attrs |= (UINT64_C(1) << OVS_KEY_ATTR_MPLS);
    4785                 :            :         }
    4786         [ +  - ]:       5056 :         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_MPLS)) {
    4787                 :       5056 :             size_t size = nl_attr_get_size(attrs[OVS_KEY_ATTR_MPLS]);
    4788                 :       5056 :             const ovs_be32 *mpls_lse = nl_attr_get(attrs[OVS_KEY_ATTR_MPLS]);
    4789                 :       5056 :             int n = size / sizeof(ovs_be32);
    4790                 :            :             int i;
    4791                 :            : 
    4792 [ +  - ][ -  + ]:       5056 :             if (!size || size % sizeof(ovs_be32)) {
    4793                 :          0 :                 return ODP_FIT_ERROR;
    4794                 :            :             }
    4795 [ -  + ][ #  # ]:       5056 :             if (flow->mpls_lse[0] && flow->dl_type != htons(0xffff)) {
    4796                 :          0 :                 return ODP_FIT_ERROR;
    4797                 :            :             }
    4798                 :            : 
    4799 [ +  + ][ +  - ]:      15086 :             for (i = 0; i < n && i < FLOW_MAX_MPLS_LABELS; i++) {
    4800                 :      10030 :                 flow->mpls_lse[i] = mpls_lse[i];
    4801                 :            :             }
    4802         [ -  + ]:       5056 :             if (n > FLOW_MAX_MPLS_LABELS) {
    4803                 :          0 :                 return ODP_FIT_TOO_MUCH;
    4804                 :            :             }
    4805                 :            : 
    4806         [ +  + ]:       5056 :             if (!is_mask) {
    4807                 :            :                 /* BOS may be set only in the innermost label. */
    4808         [ +  + ]:      10025 :                 for (i = 0; i < n - 1; i++) {
    4809         [ -  + ]:       4972 :                     if (flow->mpls_lse[i] & htonl(MPLS_BOS_MASK)) {
    4810                 :          0 :                         return ODP_FIT_ERROR;
    4811                 :            :                     }
    4812                 :            :                 }
    4813                 :            : 
    4814                 :            :                 /* BOS must be set in the innermost label. */
    4815         [ +  + ]:       5053 :                 if (n < FLOW_MAX_MPLS_LABELS
    4816         [ +  + ]:       3397 :                     && !(flow->mpls_lse[n - 1] & htonl(MPLS_BOS_MASK))) {
    4817                 :         14 :                     return ODP_FIT_TOO_LITTLE;
    4818                 :            :                 }
    4819                 :            :             }
    4820                 :            :         }
    4821                 :            : 
    4822                 :       5042 :         goto done;
    4823         [ +  + ]:     151978 :     } else if (src_flow->dl_type == htons(ETH_TYPE_IP)) {
    4824         [ +  + ]:      65618 :         if (!is_mask) {
    4825                 :      35013 :             expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_IPV4;
    4826                 :            :         }
    4827         [ +  + ]:      65618 :         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_IPV4)) {
    4828                 :            :             const struct ovs_key_ipv4 *ipv4_key;
    4829                 :            : 
    4830                 :      65560 :             ipv4_key = nl_attr_get(attrs[OVS_KEY_ATTR_IPV4]);
    4831                 :      65560 :             put_ipv4_key(ipv4_key, flow, is_mask);
    4832         [ -  + ]:      65560 :             if (flow->nw_frag > FLOW_NW_FRAG_MASK) {
    4833                 :          0 :                 return ODP_FIT_ERROR;
    4834                 :            :             }
    4835         [ +  + ]:      65560 :             if (is_mask) {
    4836                 :      30605 :                 check_start = ipv4_key;
    4837                 :      30605 :                 check_len = sizeof *ipv4_key;
    4838                 :      65618 :                 expected_bit = OVS_KEY_ATTR_IPV4;
    4839                 :            :             }
    4840                 :            :         }
    4841         [ +  + ]:      86360 :     } else if (src_flow->dl_type == htons(ETH_TYPE_IPV6)) {
    4842         [ +  + ]:       8344 :         if (!is_mask) {
    4843                 :       4603 :             expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_IPV6;
    4844                 :            :         }
    4845         [ +  - ]:       8344 :         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_IPV6)) {
    4846                 :            :             const struct ovs_key_ipv6 *ipv6_key;
    4847                 :            : 
    4848                 :       8344 :             ipv6_key = nl_attr_get(attrs[OVS_KEY_ATTR_IPV6]);
    4849                 :       8344 :             put_ipv6_key(ipv6_key, flow, is_mask);
    4850         [ -  + ]:       8344 :             if (flow->nw_frag > FLOW_NW_FRAG_MASK) {
    4851                 :          0 :                 return ODP_FIT_ERROR;
    4852                 :            :             }
    4853         [ +  + ]:       8344 :             if (is_mask) {
    4854                 :       3741 :                 check_start = ipv6_key;
    4855                 :       3741 :                 check_len = sizeof *ipv6_key;
    4856                 :       8344 :                 expected_bit = OVS_KEY_ATTR_IPV6;
    4857                 :            :             }
    4858                 :            :         }
    4859   [ +  +  +  + ]:      90703 :     } else if (src_flow->dl_type == htons(ETH_TYPE_ARP) ||
    4860                 :      12687 :                src_flow->dl_type == htons(ETH_TYPE_RARP)) {
    4861         [ +  + ]:      65335 :         if (!is_mask) {
    4862                 :      32878 :             expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ARP;
    4863                 :            :         }
    4864         [ +  - ]:      65335 :         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ARP)) {
    4865                 :            :             const struct ovs_key_arp *arp_key;
    4866                 :            : 
    4867                 :      65335 :             arp_key = nl_attr_get(attrs[OVS_KEY_ATTR_ARP]);
    4868 [ +  + ][ -  + ]:      65335 :             if (!is_mask && (arp_key->arp_op & htons(0xff00))) {
    4869         [ #  # ]:          0 :                 VLOG_ERR_RL(&rl, "unsupported ARP opcode %"PRIu16" in flow "
    4870                 :            :                             "key", ntohs(arp_key->arp_op));
    4871                 :          0 :                 return ODP_FIT_ERROR;
    4872                 :            :             }
    4873                 :      65335 :             put_arp_key(arp_key, flow);
    4874         [ +  + ]:      65335 :             if (is_mask) {
    4875                 :      32457 :                 check_start = arp_key;
    4876                 :      32457 :                 check_len = sizeof *arp_key;
    4877                 :      32457 :                 expected_bit = OVS_KEY_ATTR_ARP;
    4878                 :            :             }
    4879                 :            :         }
    4880                 :            :     } else {
    4881                 :            :         goto done;
    4882                 :            :     }
    4883         [ +  + ]:     139297 :     if (check_len > 0) { /* Happens only when 'is_mask'. */
    4884   [ +  +  -  + ]:     126155 :         if (!is_all_zeros(check_start, check_len) &&
    4885                 :      59352 :             flow->dl_type != htons(0xffff)) {
    4886                 :          0 :             return ODP_FIT_ERROR;
    4887                 :            :         } else {
    4888                 :      66803 :             expected_attrs |= UINT64_C(1) << expected_bit;
    4889                 :            :         }
    4890                 :            :     }
    4891                 :            : 
    4892                 :     139297 :     expected_bit = OVS_KEY_ATTR_UNSPEC;
    4893         [ +  + ]:     139297 :     if (src_flow->nw_proto == IPPROTO_TCP
    4894   [ +  +  +  - ]:       4076 :         && (src_flow->dl_type == htons(ETH_TYPE_IP) ||
    4895                 :         66 :             src_flow->dl_type == htons(ETH_TYPE_IPV6))
    4896         [ +  + ]:       4010 :         && !(src_flow->nw_frag & FLOW_NW_FRAG_LATER)) {
    4897         [ +  + ]:       3999 :         if (!is_mask) {
    4898                 :       3486 :             expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_TCP;
    4899                 :            :         }
    4900         [ +  + ]:       3999 :         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_TCP)) {
    4901                 :            :             const union ovs_key_tp *tcp_key;
    4902                 :            : 
    4903                 :       3946 :             tcp_key = nl_attr_get(attrs[OVS_KEY_ATTR_TCP]);
    4904                 :       3946 :             put_tp_key(tcp_key, flow);
    4905                 :       3946 :             expected_bit = OVS_KEY_ATTR_TCP;
    4906                 :            :         }
    4907         [ +  + ]:       7002 :         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_TCP_FLAGS)) {
    4908                 :       3003 :             expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_TCP_FLAGS;
    4909                 :       3003 :             flow->tcp_flags = nl_attr_get_be16(attrs[OVS_KEY_ATTR_TCP_FLAGS]);
    4910                 :            :         }
    4911         [ +  + ]:     135298 :     } else if (src_flow->nw_proto == IPPROTO_UDP
    4912   [ +  +  +  - ]:      11827 :                && (src_flow->dl_type == htons(ETH_TYPE_IP) ||
    4913                 :         25 :                    src_flow->dl_type == htons(ETH_TYPE_IPV6))
    4914         [ +  + ]:      11802 :                && !(src_flow->nw_frag & FLOW_NW_FRAG_LATER)) {
    4915         [ +  + ]:      11800 :         if (!is_mask) {
    4916                 :       6046 :             expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_UDP;
    4917                 :            :         }
    4918         [ +  - ]:      23600 :         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_UDP)) {
    4919                 :            :             const union ovs_key_tp *udp_key;
    4920                 :            : 
    4921                 :      11800 :             udp_key = nl_attr_get(attrs[OVS_KEY_ATTR_UDP]);
    4922                 :      11800 :             put_tp_key(udp_key, flow);
    4923                 :      11800 :             expected_bit = OVS_KEY_ATTR_UDP;
    4924                 :            :         }
    4925         [ -  + ]:     123498 :     } else if (src_flow->nw_proto == IPPROTO_SCTP
    4926   [ #  #  #  # ]:          0 :                && (src_flow->dl_type == htons(ETH_TYPE_IP) ||
    4927                 :          0 :                    src_flow->dl_type == htons(ETH_TYPE_IPV6))
    4928         [ #  # ]:          0 :                && !(src_flow->nw_frag & FLOW_NW_FRAG_LATER)) {
    4929         [ #  # ]:          0 :         if (!is_mask) {
    4930                 :          0 :             expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_SCTP;
    4931                 :            :         }
    4932         [ #  # ]:          0 :         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_SCTP)) {
    4933                 :            :             const union ovs_key_tp *sctp_key;
    4934                 :            : 
    4935                 :          0 :             sctp_key = nl_attr_get(attrs[OVS_KEY_ATTR_SCTP]);
    4936                 :          0 :             put_tp_key(sctp_key, flow);
    4937                 :          0 :             expected_bit = OVS_KEY_ATTR_SCTP;
    4938                 :            :         }
    4939         [ +  + ]:     123498 :     } else if (src_flow->nw_proto == IPPROTO_ICMP
    4940         [ +  + ]:      67648 :                && src_flow->dl_type == htons(ETH_TYPE_IP)
    4941         [ +  + ]:      49399 :                && !(src_flow->nw_frag & FLOW_NW_FRAG_LATER)) {
    4942         [ +  + ]:      49336 :         if (!is_mask) {
    4943                 :      25154 :             expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ICMP;
    4944                 :            :         }
    4945         [ +  - ]:      98672 :         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ICMP)) {
    4946                 :            :             const struct ovs_key_icmp *icmp_key;
    4947                 :            : 
    4948                 :      49336 :             icmp_key = nl_attr_get(attrs[OVS_KEY_ATTR_ICMP]);
    4949                 :      49336 :             flow->tp_src = htons(icmp_key->icmp_type);
    4950                 :      49336 :             flow->tp_dst = htons(icmp_key->icmp_code);
    4951                 :      49336 :             expected_bit = OVS_KEY_ATTR_ICMP;
    4952                 :            :         }
    4953         [ +  + ]:      74162 :     } else if (src_flow->nw_proto == IPPROTO_ICMPV6
    4954         [ +  - ]:       8153 :                && src_flow->dl_type == htons(ETH_TYPE_IPV6)
    4955         [ +  + ]:       8153 :                && !(src_flow->nw_frag & FLOW_NW_FRAG_LATER)) {
    4956         [ +  + ]:       8150 :         if (!is_mask) {
    4957                 :       4432 :             expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ICMPV6;
    4958                 :            :         }
    4959         [ +  - ]:       8150 :         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ICMPV6)) {
    4960                 :            :             const struct ovs_key_icmpv6 *icmpv6_key;
    4961                 :            : 
    4962                 :       8150 :             icmpv6_key = nl_attr_get(attrs[OVS_KEY_ATTR_ICMPV6]);
    4963                 :       8150 :             flow->tp_src = htons(icmpv6_key->icmpv6_type);
    4964                 :       8150 :             flow->tp_dst = htons(icmpv6_key->icmpv6_code);
    4965                 :       8150 :             expected_bit = OVS_KEY_ATTR_ICMPV6;
    4966         [ +  + ]:       8150 :             if (is_nd(src_flow, NULL)) {
    4967         [ +  + ]:       1166 :                 if (!is_mask) {
    4968                 :        671 :                     expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ND;
    4969                 :            :                 }
    4970         [ +  + ]:       1166 :                 if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ND)) {
    4971                 :            :                     const struct ovs_key_nd *nd_key;
    4972                 :            : 
    4973                 :        761 :                     nd_key = nl_attr_get(attrs[OVS_KEY_ATTR_ND]);
    4974                 :        761 :                     memcpy(&flow->nd_target, nd_key->nd_target,
    4975                 :            :                            sizeof flow->nd_target);
    4976                 :        761 :                     flow->arp_sha = nd_key->nd_sll;
    4977                 :        761 :                     flow->arp_tha = nd_key->nd_tll;
    4978         [ +  + ]:        761 :                     if (is_mask) {
    4979                 :            :                         /* Even though 'tp_src' and 'tp_dst' are 16 bits wide,
    4980                 :            :                          * ICMP type and code are 8 bits wide.  Therefore, an
    4981                 :            :                          * exact match looks like htons(0xff), not
    4982                 :            :                          * htons(0xffff).  See xlate_wc_finish() for details.
    4983                 :            :                          * */
    4984   [ +  -  +  - ]:        180 :                         if (!is_all_zeros(nd_key, sizeof *nd_key) &&
    4985         [ -  + ]:        180 :                             (flow->tp_src != htons(0xff) ||
    4986                 :         90 :                              flow->tp_dst != htons(0xff))) {
    4987                 :          0 :                             return ODP_FIT_ERROR;
    4988                 :            :                         } else {
    4989                 :         90 :                             expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ND;
    4990                 :            :                         }
    4991                 :            :                     }
    4992                 :            :                 }
    4993                 :            :             }
    4994                 :            :         }
    4995                 :            :     }
    4996 [ +  + ][ +  + ]:     139297 :     if (is_mask && expected_bit != OVS_KEY_ATTR_UNSPEC) {
    4997 [ +  + ][ +  + ]:      34167 :         if ((flow->tp_src || flow->tp_dst) && flow->nw_proto != 0xff) {
                 [ -  + ]
    4998                 :          0 :             return ODP_FIT_ERROR;
    4999                 :            :         } else {
    5000                 :      34167 :             expected_attrs |= UINT64_C(1) << expected_bit;
    5001                 :            :         }
    5002                 :            :     }
    5003                 :            : 
    5004                 :            : done:
    5005                 :     157020 :     return check_expectations(present_attrs, out_of_range_attr, expected_attrs,
    5006                 :            :                               key, key_len);
    5007                 :            : }
    5008                 :            : 
    5009                 :            : /* Parse 802.1Q header then encapsulated L3 attributes. */
    5010                 :            : static enum odp_key_fitness
    5011                 :        679 : parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
    5012                 :            :                    uint64_t present_attrs, int out_of_range_attr,
    5013                 :            :                    uint64_t expected_attrs, struct flow *flow,
    5014                 :            :                    const struct nlattr *key, size_t key_len,
    5015                 :            :                    const struct flow *src_flow)
    5016                 :            : {
    5017                 :            :     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
    5018                 :        679 :     bool is_mask = src_flow != flow;
    5019                 :            : 
    5020                 :        679 :     const struct nlattr *encap
    5021                 :        679 :         = (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ENCAP)
    5022         [ +  - ]:        679 :            ? attrs[OVS_KEY_ATTR_ENCAP] : NULL);
    5023                 :            :     enum odp_key_fitness encap_fitness;
    5024                 :            :     enum odp_key_fitness fitness;
    5025                 :            : 
    5026                 :            :     /* Calculate fitness of outer attributes. */
    5027         [ +  + ]:        679 :     if (!is_mask) {
    5028                 :        553 :         expected_attrs |= ((UINT64_C(1) << OVS_KEY_ATTR_VLAN) |
    5029                 :            :                           (UINT64_C(1) << OVS_KEY_ATTR_ENCAP));
    5030                 :            :     } else {
    5031         [ +  - ]:        126 :         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_VLAN)) {
    5032                 :        126 :             expected_attrs |= (UINT64_C(1) << OVS_KEY_ATTR_VLAN);
    5033                 :            :         }
    5034         [ +  - ]:        126 :         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ENCAP)) {
    5035                 :        126 :             expected_attrs |= (UINT64_C(1) << OVS_KEY_ATTR_ENCAP);
    5036                 :            :         }
    5037                 :            :     }
    5038                 :        679 :     fitness = check_expectations(present_attrs, out_of_range_attr,
    5039                 :            :                                  expected_attrs, key, key_len);
    5040                 :            : 
    5041                 :            :     /* Set vlan_tci.
    5042                 :            :      * Remove the TPID from dl_type since it's not the real Ethertype.  */
    5043                 :        679 :     flow->dl_type = htons(0);
    5044         [ +  - ]:        679 :     flow->vlan_tci = (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_VLAN)
    5045                 :        679 :                       ? nl_attr_get_be16(attrs[OVS_KEY_ATTR_VLAN])
    5046                 :            :                       : htons(0));
    5047         [ +  + ]:        679 :     if (!is_mask) {
    5048         [ -  + ]:        553 :         if (!(present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_VLAN))) {
    5049                 :          0 :             return ODP_FIT_TOO_LITTLE;
    5050         [ -  + ]:        553 :         } else if (flow->vlan_tci == htons(0)) {
    5051                 :            :             /* Corner case for a truncated 802.1Q header. */
    5052 [ #  # ][ #  # ]:          0 :             if (fitness == ODP_FIT_PERFECT && nl_attr_get_size(encap)) {
    5053                 :          0 :                 return ODP_FIT_TOO_MUCH;
    5054                 :            :             }
    5055                 :          0 :             return fitness;
    5056         [ -  + ]:        553 :         } else if (!(flow->vlan_tci & htons(VLAN_CFI))) {
    5057         [ #  # ]:          0 :             VLOG_ERR_RL(&rl, "OVS_KEY_ATTR_VLAN 0x%04"PRIx16" is nonzero "
    5058                 :            :                         "but CFI bit is not set", ntohs(flow->vlan_tci));
    5059                 :          0 :             return ODP_FIT_ERROR;
    5060                 :            :         }
    5061                 :            :     } else {
    5062         [ -  + ]:        126 :         if (!(present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ENCAP))) {
    5063                 :          0 :             return fitness;
    5064                 :            :         }
    5065                 :            :     }
    5066                 :            : 
    5067                 :            :     /* Now parse the encapsulated attributes. */
    5068         [ -  + ]:        679 :     if (!parse_flow_nlattrs(nl_attr_get(encap), nl_attr_get_size(encap),
    5069                 :            :                             attrs, &present_attrs, &out_of_range_attr)) {
    5070                 :          0 :         return ODP_FIT_ERROR;
    5071                 :            :     }
    5072                 :        679 :     expected_attrs = 0;
    5073                 :            : 
    5074         [ -  + ]:        679 :     if (!parse_ethertype(attrs, present_attrs, &expected_attrs, flow, src_flow)) {
    5075                 :          0 :         return ODP_FIT_ERROR;
    5076                 :            :     }
    5077                 :        679 :     encap_fitness = parse_l2_5_onward(attrs, present_attrs, out_of_range_attr,
    5078                 :            :                                       expected_attrs, flow, key, key_len,
    5079                 :            :                                       src_flow);
    5080                 :            : 
    5081                 :            :     /* The overall fitness is the worse of the outer and inner attributes. */
    5082                 :        679 :     return MAX(fitness, encap_fitness);
    5083                 :            : }
    5084                 :            : 
    5085                 :            : static enum odp_key_fitness
    5086                 :     157034 : odp_flow_key_to_flow__(const struct nlattr *key, size_t key_len,
    5087                 :            :                        const struct nlattr *src_key, size_t src_key_len,
    5088                 :            :                        struct flow *flow, const struct flow *src_flow,
    5089                 :            :                        bool udpif)
    5090                 :            : {
    5091                 :            :     const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1];
    5092                 :            :     uint64_t expected_attrs;
    5093                 :            :     uint64_t present_attrs;
    5094                 :            :     int out_of_range_attr;
    5095                 :     157034 :     bool is_mask = src_flow != flow;
    5096                 :            : 
    5097                 :     157034 :     memset(flow, 0, sizeof *flow);
    5098                 :            : 
    5099                 :            :     /* Parse attributes. */
    5100         [ -  + ]:     157034 :     if (!parse_flow_nlattrs(key, key_len, attrs, &present_attrs,
    5101                 :            :                             &out_of_range_attr)) {
    5102                 :          0 :         return ODP_FIT_ERROR;
    5103                 :            :     }
    5104                 :     157034 :     expected_attrs = 0;
    5105                 :            : 
    5106                 :            :     /* Metadata. */
    5107         [ +  + ]:     157034 :     if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_RECIRC_ID)) {
    5108                 :     142522 :         flow->recirc_id = nl_attr_get_u32(attrs[OVS_KEY_ATTR_RECIRC_ID]);
    5109                 :     142522 :         expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_RECIRC_ID;
    5110         [ +  + ]:      14512 :     } else if (is_mask) {
    5111                 :            :         /* Always exact match recirc_id if it is not specified. */
    5112                 :         80 :         flow->recirc_id = UINT32_MAX;
    5113                 :            :     }
    5114                 :            : 
    5115         [ +  + ]:     157034 :     if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_DP_HASH)) {
    5116                 :     142501 :         flow->dp_hash = nl_attr_get_u32(attrs[OVS_KEY_ATTR_DP_HASH]);
    5117                 :     142501 :         expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_DP_HASH;
    5118                 :            :     }
    5119         [ +  + ]:     157034 :     if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_PRIORITY)) {
    5120                 :     155176 :         flow->skb_priority = nl_attr_get_u32(attrs[OVS_KEY_ATTR_PRIORITY]);
    5121                 :     155176 :         expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_PRIORITY;
    5122                 :            :     }
    5123                 :            : 
    5124         [ +  + ]:     157034 :     if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_SKB_MARK)) {
    5125                 :     155184 :         flow->pkt_mark = nl_attr_get_u32(attrs[OVS_KEY_ATTR_SKB_MARK]);
    5126                 :     155184 :         expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_SKB_MARK;
    5127                 :            :     }
    5128                 :            : 
    5129         [ +  + ]:     157034 :     if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_CT_STATE)) {
    5130                 :     142868 :         uint32_t odp_state = nl_attr_get_u32(attrs[OVS_KEY_ATTR_CT_STATE]);
    5131                 :            : 
    5132                 :     142868 :         flow->ct_state = odp_to_ovs_ct_state(odp_state);
    5133                 :     142868 :         expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_CT_STATE;
    5134                 :            :     }
    5135         [ +  + ]:     157034 :     if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_CT_ZONE)) {
    5136                 :     142317 :         flow->ct_zone = nl_attr_get_u16(attrs[OVS_KEY_ATTR_CT_ZONE]);
    5137                 :     142317 :         expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_CT_ZONE;
    5138                 :            :     }
    5139         [ +  + ]:     157034 :     if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_CT_MARK)) {
    5140                 :     142341 :         flow->ct_mark = nl_attr_get_u32(attrs[OVS_KEY_ATTR_CT_MARK]);
    5141                 :     142341 :         expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_CT_MARK;
    5142                 :            :     }
    5143         [ +  + ]:     157034 :     if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_CT_LABELS)) {
    5144                 :     142341 :         const ovs_u128 *cl = nl_attr_get(attrs[OVS_KEY_ATTR_CT_LABELS]);
    5145                 :            : 
    5146                 :     142341 :         flow->ct_label = *cl;
    5147                 :     142341 :         expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_CT_LABELS;
    5148                 :            :     }
    5149                 :            : 
    5150         [ +  + ]:     157034 :     if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_TUNNEL)) {
    5151                 :            :         enum odp_key_fitness res;
    5152                 :            : 
    5153         [ +  + ]:      76675 :         res = odp_tun_key_from_attr__(attrs[OVS_KEY_ATTR_TUNNEL],
    5154                 :            :                                       is_mask ? src_key : NULL,
    5155                 :            :                                       src_key_len, &src_flow->tunnel,
    5156                 :            :                                       &flow->tunnel, udpif);
    5157         [ -  + ]:      76675 :         if (res == ODP_FIT_ERROR) {
    5158                 :          0 :             return ODP_FIT_ERROR;
    5159         [ +  - ]:      76675 :         } else if (res == ODP_FIT_PERFECT) {
    5160                 :      76675 :             expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_TUNNEL;
    5161                 :            :         }
    5162                 :            :     }
    5163                 :            : 
    5164         [ +  + ]:     157034 :     if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_IN_PORT)) {
    5165                 :            :         flow->in_port.odp_port
    5166                 :     157026 :             = nl_attr_get_odp_port(attrs[OVS_KEY_ATTR_IN_PORT]);
    5167                 :     157026 :         expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_IN_PORT;
    5168         [ +  - ]:          8 :     } else if (!is_mask) {
    5169                 :          8 :         flow->in_port.odp_port = ODPP_NONE;
    5170                 :            :     }
    5171                 :            : 
    5172                 :            :     /* Ethernet header. */
    5173         [ +  + ]:     157034 :     if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ETHERNET)) {
    5174                 :            :         const struct ovs_key_ethernet *eth_key;
    5175                 :            : 
    5176                 :     157010 :         eth_key = nl_attr_get(attrs[OVS_KEY_ATTR_ETHERNET]);
    5177                 :     157010 :         put_ethernet_key(eth_key, flow);
    5178         [ +  + ]:     157010 :         if (is_mask) {
    5179                 :      68178 :             expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ETHERNET;
    5180                 :            :         }
    5181                 :            :     }
    5182         [ +  + ]:     157034 :     if (!is_mask) {
    5183                 :      88856 :         expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ETHERNET;
    5184                 :            :     }
    5185                 :            : 
    5186                 :            :     /* Get Ethertype or 802.1Q TPID or FLOW_DL_TYPE_NONE. */
    5187         [ -  + ]:     157034 :     if (!parse_ethertype(attrs, present_attrs, &expected_attrs, flow,
    5188                 :            :         src_flow)) {
    5189                 :          0 :         return ODP_FIT_ERROR;
    5190                 :            :     }
    5191                 :            : 
    5192 [ +  + ][ +  + ]:     314068 :     if (is_mask
    5193                 :      68178 :         ? (src_flow->vlan_tci & htons(VLAN_CFI)) != 0
    5194                 :      88856 :         : src_flow->dl_type == htons(ETH_TYPE_VLAN)) {
    5195                 :        679 :         return parse_8021q_onward(attrs, present_attrs, out_of_range_attr,
    5196                 :            :                                   expected_attrs, flow, key, key_len, src_flow);
    5197                 :            :     }
    5198         [ +  + ]:     156355 :     if (is_mask) {
    5199                 :            :         /* A missing VLAN mask means exact match on vlan_tci 0 (== no VLAN). */
    5200                 :      68052 :         flow->vlan_tci = htons(0xffff);
    5201         [ -  + ]:      68052 :         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_VLAN)) {
    5202                 :          0 :             flow->vlan_tci = nl_attr_get_be16(attrs[OVS_KEY_ATTR_VLAN]);
    5203                 :          0 :             expected_attrs |= (UINT64_C(1) << OVS_KEY_ATTR_VLAN);
    5204                 :            :         }
    5205                 :            :     }
    5206                 :     157034 :     return parse_l2_5_onward(attrs, present_attrs, out_of_range_attr,
    5207                 :            :                              expected_attrs, flow, key, key_len, src_flow);
    5208                 :            : }
    5209                 :            : 
    5210                 :            : /* Converts the 'key_len' bytes of OVS_KEY_ATTR_* attributes in 'key' to a flow
    5211                 :            :  * structure in 'flow'.  Returns an ODP_FIT_* value that indicates how well
    5212                 :            :  * 'key' fits our expectations for what a flow key should contain.
    5213                 :            :  *
    5214                 :            :  * The 'in_port' will be the datapath's understanding of the port.  The
    5215                 :            :  * caller will need to translate with odp_port_to_ofp_port() if the
    5216                 :            :  * OpenFlow port is needed.
    5217                 :            :  *
    5218                 :            :  * This function doesn't take the packet itself as an argument because none of
    5219                 :            :  * the currently understood OVS_KEY_ATTR_* attributes require it.  Currently,
    5220                 :            :  * it is always possible to infer which additional attribute(s) should appear
    5221                 :            :  * by looking at the attributes for lower-level protocols, e.g. if the network
    5222                 :            :  * protocol in OVS_KEY_ATTR_IPV4 or OVS_KEY_ATTR_IPV6 is IPPROTO_TCP then we
    5223                 :            :  * know that a OVS_KEY_ATTR_TCP attribute must appear and that otherwise it
    5224                 :            :  * must be absent. */
    5225                 :            : enum odp_key_fitness
    5226                 :      74168 : odp_flow_key_to_flow(const struct nlattr *key, size_t key_len,
    5227                 :            :                      struct flow *flow)
    5228                 :            : {
    5229                 :      74168 :    return odp_flow_key_to_flow__(key, key_len, NULL, 0, flow, flow, false);
    5230                 :            : }
    5231                 :            : 
    5232                 :            : static enum odp_key_fitness
    5233                 :      73142 : odp_flow_key_to_mask__(const struct nlattr *mask_key, size_t mask_key_len,
    5234                 :            :                        const struct nlattr *flow_key, size_t flow_key_len,
    5235                 :            :                        struct flow_wildcards *mask,
    5236                 :            :                        const struct flow *src_flow,
    5237                 :            :                        bool udpif)
    5238                 :            : {
    5239         [ +  + ]:      73142 :     if (mask_key_len) {
    5240                 :      68178 :         return odp_flow_key_to_flow__(mask_key, mask_key_len,
    5241                 :            :                                       flow_key, flow_key_len,
    5242                 :            :                                       &mask->masks, src_flow, udpif);
    5243                 :            : 
    5244                 :            :     } else {
    5245                 :            :         /* A missing mask means that the flow should be exact matched.
    5246                 :            :          * Generate an appropriate exact wildcard for the flow. */
    5247                 :       4964 :         flow_wildcards_init_for_packet(mask, src_flow);
    5248                 :            : 
    5249                 :       4964 :         return ODP_FIT_PERFECT;
    5250                 :            :     }
    5251                 :            : }
    5252                 :            : /* Converts the 'mask_key_len' bytes of OVS_KEY_ATTR_* attributes in 'mask_key'
    5253                 :            :  * to a mask structure in 'mask'.  'flow' must be a previously translated flow
    5254                 :            :  * corresponding to 'mask' and similarly flow_key/flow_key_len must be the
    5255                 :            :  * attributes from that flow.  Returns an ODP_FIT_* value that indicates how
    5256                 :            :  * well 'key' fits our expectations for what a flow key should contain. */
    5257                 :            : enum odp_key_fitness
    5258                 :      67821 : odp_flow_key_to_mask(const struct nlattr *mask_key, size_t mask_key_len,
    5259                 :            :                      const struct nlattr *flow_key, size_t flow_key_len,
    5260                 :            :                      struct flow_wildcards *mask, const struct flow *flow)
    5261                 :            : {
    5262                 :      67821 :     return odp_flow_key_to_mask__(mask_key, mask_key_len,
    5263                 :            :                                   flow_key, flow_key_len,
    5264                 :            :                                   mask, flow, false);
    5265                 :            : }
    5266                 :            : 
    5267                 :            : /* These functions are similar to their non-"_udpif" variants but output a
    5268                 :            :  * 'flow' that is suitable for fast-path packet processing.
    5269                 :            :  *
    5270                 :            :  * Some fields have different representation for flow setup and per-
    5271                 :            :  * packet processing (i.e. different between ofproto-dpif and userspace
    5272                 :            :  * datapath). In particular, with the non-"_udpif" functions, struct
    5273                 :            :  * tun_metadata is in the per-flow format (using 'present.map' and 'opts.u8');
    5274                 :            :  * with these functions, struct tun_metadata is in the per-packet format
    5275                 :            :  * (using 'present.len' and 'opts.gnv'). */
    5276                 :            : enum odp_key_fitness
    5277                 :      14688 : odp_flow_key_to_flow_udpif(const struct nlattr *key, size_t key_len,
    5278                 :            :                            struct flow *flow)
    5279                 :            : {
    5280                 :      14688 :    return odp_flow_key_to_flow__(key, key_len, NULL, 0, flow, flow, true);
    5281                 :            : }
    5282                 :            : 
    5283                 :            : enum odp_key_fitness
    5284                 :       5321 : odp_flow_key_to_mask_udpif(const struct nlattr *mask_key, size_t mask_key_len,
    5285                 :            :                            const struct nlattr *flow_key, size_t flow_key_len,
    5286                 :            :                            struct flow_wildcards *mask,
    5287                 :            :                            const struct flow *flow)
    5288                 :            : {
    5289                 :       5321 :     return odp_flow_key_to_mask__(mask_key, mask_key_len,
    5290                 :            :                                   flow_key, flow_key_len,
    5291                 :            :                                   mask, flow, true);
    5292                 :            : }
    5293                 :            : 
    5294                 :            : /* Returns 'fitness' as a string, for use in debug messages. */
    5295                 :            : const char *
    5296                 :          0 : odp_key_fitness_to_string(enum odp_key_fitness fitness)
    5297                 :            : {
    5298   [ #  #  #  #  :          0 :     switch (fitness) {
                      # ]
    5299                 :            :     case ODP_FIT_PERFECT:
    5300                 :          0 :         return "OK";
    5301                 :            :     case ODP_FIT_TOO_MUCH:
    5302                 :          0 :         return "too_much";
    5303                 :            :     case ODP_FIT_TOO_LITTLE:
    5304                 :          0 :         return "too_little";
    5305                 :            :     case ODP_FIT_ERROR:
    5306                 :          0 :         return "error";
    5307                 :            :     default:
    5308                 :          0 :         return "<unknown>";
    5309                 :            :     }
    5310                 :            : }
    5311                 :            : 
    5312                 :            : /* Appends an OVS_ACTION_ATTR_USERSPACE action to 'odp_actions' that specifies
    5313                 :            :  * Netlink PID 'pid'.  If 'userdata' is nonnull, adds a userdata attribute
    5314                 :            :  * whose contents are the 'userdata_size' bytes at 'userdata' and returns the
    5315                 :            :  * offset within 'odp_actions' of the start of the cookie.  (If 'userdata' is
    5316                 :            :  * null, then the return value is not meaningful.) */
    5317                 :            : size_t
    5318                 :      27710 : odp_put_userspace_action(uint32_t pid,
    5319                 :            :                          const void *userdata, size_t userdata_size,
    5320                 :            :                          odp_port_t tunnel_out_port,
    5321                 :            :                          bool include_actions,
    5322                 :            :                          struct ofpbuf *odp_actions)
    5323                 :            : {
    5324                 :            :     size_t userdata_ofs;
    5325                 :            :     size_t offset;
    5326                 :            : 
    5327                 :      27710 :     offset = nl_msg_start_nested(odp_actions, OVS_ACTION_ATTR_USERSPACE);
    5328                 :      27710 :     nl_msg_put_u32(odp_actions, OVS_USERSPACE_ATTR_PID, pid);
    5329         [ +  + ]:      27710 :     if (userdata) {
    5330                 :      27708 :         userdata_ofs = odp_actions->size + NLA_HDRLEN;
    5331                 :            : 
    5332                 :            :         /* The OVS kernel module before OVS 1.11 and the upstream Linux kernel
    5333                 :            :          * module before Linux 3.10 required the userdata to be exactly 8 bytes
    5334                 :            :          * long:
    5335                 :            :          *
    5336                 :            :          *   - The kernel rejected shorter userdata with -ERANGE.
    5337                 :            :          *
    5338                 :            :          *   - The kernel silently dropped userdata beyond the first 8 bytes.
    5339                 :            :          *
    5340                 :            :          * Thus, for maximum compatibility, always put at least 8 bytes.  (We
    5341                 :            :          * separately disable features that required more than 8 bytes.) */
    5342                 :      27708 :         memcpy(nl_msg_put_unspec_zero(odp_actions, OVS_USERSPACE_ATTR_USERDATA,
    5343                 :            :                                       MAX(8, userdata_size)),
    5344                 :            :                userdata, userdata_size);
    5345                 :            :     } else {
    5346                 :          2 :         userdata_ofs = 0;
    5347                 :            :     }
    5348         [ +  + ]:      27710 :     if (tunnel_out_port != ODPP_NONE) {
    5349                 :         10 :         nl_msg_put_odp_port(odp_actions, OVS_USERSPACE_ATTR_EGRESS_TUN_PORT,
    5350                 :            :                             tunnel_out_port);
    5351                 :            :     }
    5352         [ +  + ]:      27710 :     if (include_actions) {
    5353                 :         24 :         nl_msg_put_flag(odp_actions, OVS_USERSPACE_ATTR_ACTIONS);
    5354                 :            :     }
    5355                 :      27710 :     nl_msg_end_nested(odp_actions, offset);
    5356                 :            : 
    5357                 :      27710 :     return userdata_ofs;
    5358                 :            : }
    5359                 :            : 
    5360                 :            : void
    5361                 :        120 : odp_put_tunnel_action(const struct flow_tnl *tunnel,
    5362                 :            :                       struct ofpbuf *odp_actions)
    5363                 :            : {
    5364                 :        120 :     size_t offset = nl_msg_start_nested(odp_actions, OVS_ACTION_ATTR_SET);
    5365                 :        120 :     tun_key_to_attr(odp_actions, tunnel, tunnel, NULL);
    5366                 :        120 :     nl_msg_end_nested(odp_actions, offset);
    5367                 :        120 : }
    5368                 :            : 
    5369                 :            : void
    5370                 :       2419 : odp_put_tnl_push_action(struct ofpbuf *odp_actions,
    5371                 :            :                         struct ovs_action_push_tnl *data)
    5372                 :            : {
    5373                 :       2419 :     int size = offsetof(struct ovs_action_push_tnl, header);
    5374                 :            : 
    5375                 :       2419 :     size += data->header_len;
    5376                 :       2419 :     nl_msg_put_unspec(odp_actions, OVS_ACTION_ATTR_TUNNEL_PUSH, data, size);
    5377                 :       2419 : }
    5378                 :            : 
    5379                 :            : 
    5380                 :            : /* The commit_odp_actions() function and its helpers. */
    5381                 :            : 
    5382                 :            : static void
    5383                 :       4710 : commit_set_action(struct ofpbuf *odp_actions, enum ovs_key_attr key_type,
    5384                 :            :                   const void *key, size_t key_size)
    5385                 :            : {
    5386                 :       4710 :     size_t offset = nl_msg_start_nested(odp_actions, OVS_ACTION_ATTR_SET);
    5387                 :       4710 :     nl_msg_put_unspec(odp_actions, key_type, key, key_size);
    5388                 :       4710 :     nl_msg_end_nested(odp_actions, offset);
    5389                 :       4710 : }
    5390                 :            : 
    5391                 :            : /* Masked set actions have a mask following the data within the netlink
    5392                 :            :  * attribute.  The unmasked bits in the data will be cleared as the data
    5393                 :            :  * is copied to the action. */
    5394                 :            : void
    5395                 :       5951 : commit_masked_set_action(struct ofpbuf *odp_actions,
    5396                 :            :                          enum ovs_key_attr key_type,
    5397                 :            :                          const void *key_, const void *mask_, size_t key_size)
    5398                 :            : {
    5399                 :       5951 :     size_t offset = nl_msg_start_nested(odp_actions,
    5400                 :            :                                         OVS_ACTION_ATTR_SET_MASKED);
    5401                 :       5951 :     char *data = nl_msg_put_unspec_uninit(odp_actions, key_type, key_size * 2);
    5402                 :       5951 :     const char *key = key_, *mask = mask_;
    5403                 :            : 
    5404                 :       5951 :     memcpy(data + key_size, mask, key_size);
    5405                 :            :     /* Clear unmasked bits while copying. */
    5406         [ +  + ]:     101611 :     while (key_size--) {
    5407                 :      95660 :         *data++ = *key++ & *mask++;
    5408                 :            :     }
    5409                 :       5951 :     nl_msg_end_nested(odp_actions, offset);
    5410                 :       5951 : }
    5411                 :            : 
    5412                 :            : /* If any of the flow key data that ODP actions can modify are different in
    5413                 :            :  * 'base->tunnel' and 'flow->tunnel', appends a set_tunnel ODP action to
    5414                 :            :  * 'odp_actions' that change the flow tunneling information in key from
    5415                 :            :  * 'base->tunnel' into 'flow->tunnel', and then changes 'base->tunnel' in the
    5416                 :            :  * same way.  In other words, operates the same as commit_odp_actions(), but
    5417                 :            :  * only on tunneling information. */
    5418                 :            : void
    5419                 :        114 : commit_odp_tunnel_action(const struct flow *flow, struct flow *base,
    5420                 :            :                          struct ofpbuf *odp_actions)
    5421                 :            : {
    5422                 :            :     /* A valid IPV4_TUNNEL must have non-zero ip_dst; a valid IPv6 tunnel
    5423                 :            :      * must have non-zero ipv6_dst. */
    5424         [ +  - ]:        114 :     if (flow_tnl_dst_is_set(&flow->tunnel)) {
    5425         [ +  + ]:        114 :         if (!memcmp(&base->tunnel, &flow->tunnel, sizeof base->tunnel)) {
    5426                 :          3 :             return;
    5427                 :            :         }
    5428                 :        111 :         memcpy(&base->tunnel, &flow->tunnel, sizeof base->tunnel);
    5429                 :        111 :         odp_put_tunnel_action(&base->tunnel, odp_actions);
    5430                 :            :     }
    5431                 :            : }
    5432                 :            : 
    5433                 :            : static bool
    5434                 :     508659 : commit(enum ovs_key_attr attr, bool use_masked_set,
    5435                 :            :        const void *key, void *base, void *mask, size_t size,
    5436                 :            :        struct ofpbuf *odp_actions)
    5437                 :            : {
    5438         [ +  + ]:     508659 :     if (memcmp(key, base, size)) {
    5439                 :      10019 :         bool fully_masked = odp_mask_is_exact(attr, mask, size);
    5440                 :            : 
    5441 [ +  + ][ +  + ]:      10019 :         if (use_masked_set && !fully_masked) {
    5442                 :       5337 :             commit_masked_set_action(odp_actions, attr, key, mask, size);
    5443                 :            :         } else {
    5444         [ -  + ]:       4682 :             if (!fully_masked) {
    5445                 :          0 :                 memset(mask, 0xff, size);
    5446                 :            :             }
    5447                 :       4682 :             commit_set_action(odp_actions, attr, key, size);
    5448                 :            :         }
    5449                 :      10019 :         memcpy(base, key, size);
    5450                 :      10019 :         return true;
    5451                 :            :     } else {
    5452                 :            :         /* Mask bits are set when we have either read or set the corresponding
    5453                 :            :          * values.  Masked bits will be exact-matched, no need to set them
    5454                 :            :          * if the value did not actually change. */
    5455                 :     498640 :         return false;
    5456                 :            :     }
    5457                 :            : }
    5458                 :            : 
    5459                 :            : static void
    5460                 :     382578 : get_ethernet_key(const struct flow *flow, struct ovs_key_ethernet *eth)
    5461                 :            : {
    5462                 :     382578 :     eth->eth_src = flow->dl_src;
    5463                 :     382578 :     eth->eth_dst = flow->dl_dst;
    5464                 :     382578 : }
    5465                 :            : 
    5466                 :            : static void
    5467                 :     167004 : put_ethernet_key(const struct ovs_key_ethernet *eth, struct flow *flow)
    5468                 :            : {
    5469                 :     167004 :     flow->dl_src = eth->eth_src;
    5470                 :     167004 :     flow->dl_dst = eth->eth_dst;
    5471                 :     167004 : }
    5472                 :            : 
    5473                 :            : static void
    5474                 :     116809 : commit_set_ether_addr_action(const struct flow *flow, struct flow *base_flow,
    5475                 :            :                              struct ofpbuf *odp_actions,
    5476                 :            :                              struct flow_wildcards *wc,
    5477                 :            :                              bool use_masked)
    5478                 :            : {
    5479                 :            :     struct ovs_key_ethernet key, base, mask;
    5480                 :            : 
    5481                 :     116809 :     get_ethernet_key(flow, &key);
    5482                 :     116809 :     get_ethernet_key(base_flow, &base);
    5483                 :     116809 :     get_ethernet_key(&wc->masks, &mask);
    5484                 :            : 
    5485         [ +  + ]:     116809 :     if (commit(OVS_KEY_ATTR_ETHERNET, use_masked,
    5486                 :            :                &key, &base, &mask, sizeof key, odp_actions)) {
    5487                 :       4997 :         put_ethernet_key(&base, base_flow);
    5488                 :       4997 :         put_ethernet_key(&mask, &wc->masks);
    5489                 :            :     }
    5490                 :     116809 : }
    5491                 :            : 
    5492                 :            : static void
    5493                 :        266 : pop_vlan(struct flow *base,
    5494                 :            :          struct ofpbuf *odp_actions, struct flow_wildcards *wc)
    5495                 :            : {
    5496                 :        266 :     memset(&wc->masks.vlan_tci, 0xff, sizeof wc->masks.vlan_tci);
    5497                 :            : 
    5498         [ +  + ]:        266 :     if (base->vlan_tci & htons(VLAN_CFI)) {
    5499                 :        145 :         nl_msg_put_flag(odp_actions, OVS_ACTION_ATTR_POP_VLAN);
    5500                 :        145 :         base->vlan_tci = 0;
    5501                 :            :     }
    5502                 :        266 : }
    5503                 :            : 
    5504                 :            : static void
    5505                 :     116809 : commit_vlan_action(ovs_be16 vlan_tci, struct flow *base,
    5506                 :            :                    struct ofpbuf *odp_actions, struct flow_wildcards *wc)
    5507                 :            : {
    5508         [ +  + ]:     116809 :     if (base->vlan_tci == vlan_tci) {
    5509                 :     116543 :         return;
    5510                 :            :     }
    5511                 :            : 
    5512                 :        266 :     pop_vlan(base, odp_actions, wc);
    5513         [ +  + ]:        266 :     if (vlan_tci & htons(VLAN_CFI)) {
    5514                 :            :         struct ovs_action_push_vlan vlan;
    5515                 :            : 
    5516                 :        181 :         vlan.vlan_tpid = htons(ETH_TYPE_VLAN);
    5517                 :        181 :         vlan.vlan_tci = vlan_tci;
    5518                 :        181 :         nl_msg_put_unspec(odp_actions, OVS_ACTION_ATTR_PUSH_VLAN,
    5519                 :            :                           &vlan, sizeof vlan);
    5520                 :            :     }
    5521                 :        266 :     base->vlan_tci = vlan_tci;
    5522                 :            : }
    5523                 :            : 
    5524                 :            : /* Wildcarding already done at action translation time. */
    5525                 :            : static void
    5526                 :     116809 : commit_mpls_action(const struct flow *flow, struct flow *base,
    5527                 :            :                    struct ofpbuf *odp_actions)
    5528                 :            : {
    5529                 :     116809 :     int base_n = flow_count_mpls_labels(base, NULL);
    5530                 :     116809 :     int flow_n = flow_count_mpls_labels(flow, NULL);
    5531                 :     116809 :     int common_n = flow_count_common_mpls_labels(flow, flow_n, base, base_n,
    5532                 :            :                                                  NULL);
    5533                 :            : 
    5534         [ +  + ]:     116936 :     while (base_n > common_n) {
    5535 [ +  + ][ +  + ]:        155 :         if (base_n - 1 == common_n && flow_n > common_n) {
    5536                 :            :             /* If there is only one more LSE in base than there are common
    5537                 :            :              * between base and flow; and flow has at least one more LSE than
    5538                 :            :              * is common then the topmost LSE of base may be updated using
    5539                 :            :              * set */
    5540                 :            :             struct ovs_key_mpls mpls_key;
    5541                 :            : 
    5542                 :         28 :             mpls_key.mpls_lse = flow->mpls_lse[flow_n - base_n];
    5543                 :         28 :             commit_set_action(odp_actions, OVS_KEY_ATTR_MPLS,
    5544                 :            :                               &mpls_key, sizeof mpls_key);
    5545                 :         28 :             flow_set_mpls_lse(base, 0, mpls_key.mpls_lse);
    5546                 :         28 :             common_n++;
    5547                 :            :         } else {
    5548                 :            :             /* Otherwise, if there more LSEs in base than are common between
    5549                 :            :              * base and flow then pop the topmost one. */
    5550                 :            :             ovs_be16 dl_type;
    5551                 :            :             bool popped;
    5552                 :            : 
    5553                 :            :             /* If all the LSEs are to be popped and this is not the outermost
    5554                 :            :              * LSE then use ETH_TYPE_MPLS as the ethertype parameter of the
    5555                 :            :              * POP_MPLS action instead of flow->dl_type.
    5556                 :            :              *
    5557                 :            :              * This is because the POP_MPLS action requires its ethertype
    5558                 :            :              * argument to be an MPLS ethernet type but in this case
    5559                 :            :              * flow->dl_type will be a non-MPLS ethernet type.
    5560                 :            :              *
    5561                 :            :              * When the final POP_MPLS action occurs it use flow->dl_type and
    5562                 :            :              * the and the resulting packet will have the desired dl_type. */
    5563 [ +  + ][ +  + ]:         99 :             if ((!eth_type_mpls(flow->dl_type)) && base_n > 1) {
    5564                 :          9 :                 dl_type = htons(ETH_TYPE_MPLS);
    5565                 :            :             } else {
    5566                 :         90 :                 dl_type = flow->dl_type;
    5567                 :            :             }
    5568                 :         99 :             nl_msg_put_be16(odp_actions, OVS_ACTION_ATTR_POP_MPLS, dl_type);
    5569                 :         99 :             popped = flow_pop_mpls(base, base_n, flow->dl_type, NULL);
    5570         [ -  + ]:         99 :             ovs_assert(popped);
    5571                 :         99 :             base_n--;
    5572                 :            :         }
    5573                 :            :     }
    5574                 :            : 
    5575                 :            :     /* If, after the above popping and setting, there are more LSEs in flow
    5576                 :            :      * than base then some LSEs need to be pushed. */
    5577         [ +  + ]:     116917 :     while (base_n < flow_n) {
    5578                 :            :         struct ovs_action_push_mpls *mpls;
    5579                 :            : 
    5580                 :        108 :         mpls = nl_msg_put_unspec_zero(odp_actions,
    5581                 :            :                                       OVS_ACTION_ATTR_PUSH_MPLS,
    5582                 :            :                                       sizeof *mpls);
    5583                 :        108 :         mpls->mpls_ethertype = flow->dl_type;
    5584                 :        108 :         mpls->mpls_lse = flow->mpls_lse[flow_n - base_n - 1];
    5585                 :        108 :         flow_push_mpls(base, base_n, mpls->mpls_ethertype, NULL);
    5586                 :        108 :         flow_set_mpls_lse(base, 0, mpls->mpls_lse);
    5587                 :        108 :         base_n++;
    5588                 :            :     }
    5589                 :     116809 : }
    5590                 :            : 
    5591                 :            : static void
    5592                 :     167676 : get_ipv4_key(const struct flow *flow, struct ovs_key_ipv4 *ipv4, bool is_mask)
    5593                 :            : {
    5594                 :     167676 :     ipv4->ipv4_src = flow->nw_src;
    5595                 :     167676 :     ipv4->ipv4_dst = flow->nw_dst;
    5596                 :     167676 :     ipv4->ipv4_proto = flow->nw_proto;
    5597                 :     167676 :     ipv4->ipv4_tos = flow->nw_tos;
    5598                 :     167676 :     ipv4->ipv4_ttl = flow->nw_ttl;
    5599                 :     167676 :     ipv4->ipv4_frag = ovs_to_odp_frag(flow->nw_frag, is_mask);
    5600                 :     167676 : }
    5601                 :            : 
    5602                 :            : static void
    5603                 :      68512 : put_ipv4_key(const struct ovs_key_ipv4 *ipv4, struct flow *flow, bool is_mask)
    5604                 :            : {
    5605                 :      68512 :     flow->nw_src = ipv4->ipv4_src;
    5606                 :      68512 :     flow->nw_dst = ipv4->ipv4_dst;
    5607                 :      68512 :     flow->nw_proto = ipv4->ipv4_proto;
    5608                 :      68512 :     flow->nw_tos = ipv4->ipv4_tos;
    5609                 :      68512 :     flow->nw_ttl = ipv4->ipv4_ttl;
    5610                 :      68512 :     flow->nw_frag = odp_to_ovs_frag(ipv4->ipv4_frag, is_mask);
    5611                 :      68512 : }
    5612                 :            : 
    5613                 :            : static void
    5614                 :      52185 : commit_set_ipv4_action(const struct flow *flow, struct flow *base_flow,
    5615                 :            :                        struct ofpbuf *odp_actions, struct flow_wildcards *wc,
    5616                 :            :                        bool use_masked)
    5617                 :            : {
    5618                 :            :     struct ovs_key_ipv4 key, mask, base;
    5619                 :            : 
    5620                 :            :     /* Check that nw_proto and nw_frag remain unchanged. */
    5621 [ +  - ][ -  + ]:      52185 :     ovs_assert(flow->nw_proto == base_flow->nw_proto &&
    5622                 :            :                flow->nw_frag == base_flow->nw_frag);
    5623                 :            : 
    5624                 :      52185 :     get_ipv4_key(flow, &key, false);
    5625                 :      52185 :     get_ipv4_key(base_flow, &base, false);
    5626                 :      52185 :     get_ipv4_key(&wc->masks, &mask, true);
    5627                 :      52185 :     mask.ipv4_proto = 0;        /* Not writeable. */
    5628                 :      52185 :     mask.ipv4_frag = 0;         /* Not writable. */
    5629                 :            : 
    5630         [ +  + ]:      52185 :     if (commit(OVS_KEY_ATTR_IPV4, use_masked, &key, &base, &mask, sizeof key,
    5631                 :            :                odp_actions)) {
    5632                 :       2952 :         put_ipv4_key(&base, base_flow, false);
    5633         [ -  + ]:       2952 :         if (mask.ipv4_proto != 0) { /* Mask was changed by commit(). */
    5634                 :          0 :             put_ipv4_key(&mask, &wc->masks, true);
    5635                 :            :         }
    5636                 :            :    }
    5637                 :      52185 : }
    5638                 :            : 
    5639                 :            : static void
    5640                 :       9222 : get_ipv6_key(const struct flow *flow, struct ovs_key_ipv6 *ipv6, bool is_mask)
    5641                 :            : {
    5642                 :       9222 :     memcpy(ipv6->ipv6_src, &flow->ipv6_src, sizeof ipv6->ipv6_src);
    5643                 :       9222 :     memcpy(ipv6->ipv6_dst, &flow->ipv6_dst, sizeof ipv6->ipv6_dst);
    5644                 :       9222 :     ipv6->ipv6_label = flow->ipv6_label;
    5645                 :       9222 :     ipv6->ipv6_proto = flow->nw_proto;
    5646                 :       9222 :     ipv6->ipv6_tclass = flow->nw_tos;
    5647                 :       9222 :     ipv6->ipv6_hlimit = flow->nw_ttl;
    5648                 :       9222 :     ipv6->ipv6_frag = ovs_to_odp_frag(flow->nw_frag, is_mask);
    5649                 :       9222 : }
    5650                 :            : 
    5651                 :            : static void
    5652                 :       8347 : put_ipv6_key(const struct ovs_key_ipv6 *ipv6, struct flow *flow, bool is_mask)
    5653                 :            : {
    5654                 :       8347 :     memcpy(&flow->ipv6_src, ipv6->ipv6_src, sizeof flow->ipv6_src);
    5655                 :       8347 :     memcpy(&flow->ipv6_dst, ipv6->ipv6_dst, sizeof flow->ipv6_dst);
    5656                 :       8347 :     flow->ipv6_label = ipv6->ipv6_label;
    5657                 :       8347 :     flow->nw_proto = ipv6->ipv6_proto;
    5658                 :       8347 :     flow->nw_tos = ipv6->ipv6_tclass;
    5659                 :       8347 :     flow->nw_ttl = ipv6->ipv6_hlimit;
    5660                 :       8347 :     flow->nw_frag = odp_to_ovs_frag(ipv6->ipv6_frag, is_mask);
    5661                 :       8347 : }
    5662                 :            : 
    5663                 :            : static void
    5664                 :       2636 : commit_set_ipv6_action(const struct flow *flow, struct flow *base_flow,
    5665                 :            :                        struct ofpbuf *odp_actions, struct flow_wildcards *wc,
    5666                 :            :                        bool use_masked)
    5667                 :            : {
    5668                 :            :     struct ovs_key_ipv6 key, mask, base;
    5669                 :            : 
    5670                 :            :     /* Check that nw_proto and nw_frag remain unchanged. */
    5671 [ +  - ][ -  + ]:       2636 :     ovs_assert(flow->nw_proto == base_flow->nw_proto &&
    5672                 :            :                flow->nw_frag == base_flow->nw_frag);
    5673                 :            : 
    5674                 :       2636 :     get_ipv6_key(flow, &key, false);
    5675                 :       2636 :     get_ipv6_key(base_flow, &base, false);
    5676                 :       2636 :     get_ipv6_key(&wc->masks, &mask, true);
    5677                 :       2636 :     mask.ipv6_proto = 0;        /* Not writeable. */
    5678                 :       2636 :     mask.ipv6_frag = 0;         /* Not writable. */
    5679                 :            : 
    5680         [ +  + ]:       2636 :     if (commit(OVS_KEY_ATTR_IPV6, use_masked, &key, &base, &mask, sizeof key,
    5681                 :            :                odp_actions)) {
    5682                 :          3 :         put_ipv6_key(&base, base_flow, false);
    5683         [ -  + ]:          3 :         if (mask.ipv6_proto != 0) { /* Mask was changed by commit(). */
    5684                 :          0 :             put_ipv6_key(&mask, &wc->masks, true);
    5685                 :            :         }
    5686                 :            :     }
    5687                 :       2636 : }
    5688                 :            : 
    5689                 :            : static void
    5690                 :     140220 : get_arp_key(const struct flow *flow, struct ovs_key_arp *arp)
    5691                 :            : {
    5692                 :            :     /* ARP key has padding, clear it. */
    5693                 :     140220 :     memset(arp, 0, sizeof *arp);
    5694                 :            : 
    5695                 :     140220 :     arp->arp_sip = flow->nw_src;
    5696                 :     140220 :     arp->arp_tip = flow->nw_dst;
    5697                 :     140220 :     arp->arp_op = htons(flow->nw_proto);
    5698                 :     140220 :     arp->arp_sha = flow->arp_sha;
    5699                 :     140220 :     arp->arp_tha = flow->arp_tha;
    5700                 :     140220 : }
    5701                 :            : 
    5702                 :            : static void
    5703                 :      69373 : put_arp_key(const struct ovs_key_arp *arp, struct flow *flow)
    5704                 :            : {
    5705                 :      69373 :     flow->nw_src = arp->arp_sip;
    5706                 :      69373 :     flow->nw_dst = arp->arp_tip;
    5707                 :      69373 :     flow->nw_proto = ntohs(arp->arp_op);
    5708                 :      69373 :     flow->arp_sha = arp->arp_sha;
    5709                 :      69373 :     flow->arp_tha = arp->arp_tha;
    5710                 :      69373 : }
    5711                 :            : 
    5712                 :            : static enum slow_path_reason
    5713                 :      46214 : commit_set_arp_action(const struct flow *flow, struct flow *base_flow,
    5714                 :            :                       struct ofpbuf *odp_actions, struct flow_wildcards *wc)
    5715                 :            : {
    5716                 :            :     struct ovs_key_arp key, mask, base;
    5717                 :            : 
    5718                 :      46214 :     get_arp_key(flow, &key);
    5719                 :      46214 :     get_arp_key(base_flow, &base);
    5720                 :      46214 :     get_arp_key(&wc->masks, &mask);
    5721                 :            : 
    5722         [ +  + ]:      46214 :     if (commit(OVS_KEY_ATTR_ARP, true, &key, &base, &mask, sizeof key,
    5723                 :            :                odp_actions)) {
    5724                 :       2019 :         put_arp_key(&base, base_flow);
    5725                 :       2019 :         put_arp_key(&mask, &wc->masks);
    5726                 :       2019 :         return SLOW_ACTION;
    5727                 :            :     }
    5728                 :      46214 :     return 0;
    5729                 :            : }
    5730                 :            : 
    5731                 :            : static void
    5732                 :     121989 : get_icmp_key(const struct flow *flow, struct ovs_key_icmp *icmp)
    5733                 :            : {
    5734                 :            :     /* icmp_type and icmp_code are stored in tp_src and tp_dst, respectively */
    5735                 :     121989 :     icmp->icmp_type = ntohs(flow->tp_src);
    5736                 :     121989 :     icmp->icmp_code = ntohs(flow->tp_dst);
    5737                 :     121989 : }
    5738                 :            : 
    5739                 :            : static void
    5740                 :          8 : put_icmp_key(const struct ovs_key_icmp *icmp, struct flow *flow)
    5741                 :            : {
    5742                 :            :     /* icmp_type and icmp_code are stored in tp_src and tp_dst, respectively */
    5743                 :          8 :     flow->tp_src = htons(icmp->icmp_type);
    5744                 :          8 :     flow->tp_dst = htons(icmp->icmp_code);
    5745                 :          8 : }
    5746                 :            : 
    5747                 :            : static enum slow_path_reason
    5748                 :     116809 : commit_set_icmp_action(const struct flow *flow, struct flow *base_flow,
    5749                 :            :                        struct ofpbuf *odp_actions, struct flow_wildcards *wc)
    5750                 :            : {
    5751                 :            :     struct ovs_key_icmp key, mask, base;
    5752                 :            :     enum ovs_key_attr attr;
    5753                 :            : 
    5754         [ +  + ]:     116809 :     if (is_icmpv4(flow, NULL)) {
    5755                 :      38145 :         attr = OVS_KEY_ATTR_ICMP;
    5756         [ +  + ]:      78664 :     } else if (is_icmpv6(flow, NULL)) {
    5757                 :       2518 :         attr = OVS_KEY_ATTR_ICMPV6;
    5758                 :            :     } else {
    5759                 :      76146 :         return 0;
    5760                 :            :     }
    5761                 :            : 
    5762                 :      40663 :     get_icmp_key(flow, &key);
    5763                 :      40663 :     get_icmp_key(base_flow, &base);
    5764                 :      40663 :     get_icmp_key(&wc->masks, &mask);
    5765                 :            : 
    5766         [ +  + ]:      40663 :     if (commit(attr, false, &key, &base, &mask, sizeof key, odp_actions)) {
    5767                 :          4 :         put_icmp_key(&base, base_flow);
    5768                 :          4 :         put_icmp_key(&mask, &wc->masks);
    5769                 :          4 :         return SLOW_ACTION;
    5770                 :            :     }
    5771                 :     116809 :     return 0;
    5772                 :            : }
    5773                 :            : 
    5774                 :            : static void
    5775                 :       7908 : get_nd_key(const struct flow *flow, struct ovs_key_nd *nd)
    5776                 :            : {
    5777                 :       7908 :     memcpy(nd->nd_target, &flow->nd_target, sizeof flow->nd_target);
    5778                 :            :     /* nd_sll and nd_tll are stored in arp_sha and arp_tha, respectively */
    5779                 :       7908 :     nd->nd_sll = flow->arp_sha;
    5780                 :       7908 :     nd->nd_tll = flow->arp_tha;
    5781                 :       7908 : }
    5782                 :            : 
    5783                 :            : static void
    5784                 :          8 : put_nd_key(const struct ovs_key_nd *nd, struct flow *flow)
    5785                 :            : {
    5786                 :          8 :     memcpy(&flow->nd_target, nd->nd_target, sizeof flow->nd_target);
    5787                 :            :     /* nd_sll and nd_tll are stored in arp_sha and arp_tha, respectively */
    5788                 :          8 :     flow->arp_sha = nd->nd_sll;
    5789                 :          8 :     flow->arp_tha = nd->nd_tll;
    5790                 :          8 : }
    5791                 :            : 
    5792                 :            : static enum slow_path_reason
    5793                 :       2636 : commit_set_nd_action(const struct flow *flow, struct flow *base_flow,
    5794                 :            :                      struct ofpbuf *odp_actions,
    5795                 :            :                      struct flow_wildcards *wc, bool use_masked)
    5796                 :            : {
    5797                 :            :     struct ovs_key_nd key, mask, base;
    5798                 :            : 
    5799                 :       2636 :     get_nd_key(flow, &key);
    5800                 :       2636 :     get_nd_key(base_flow, &base);
    5801                 :       2636 :     get_nd_key(&wc->masks, &mask);
    5802                 :            : 
    5803         [ +  + ]:       2636 :     if (commit(OVS_KEY_ATTR_ND, use_masked, &key, &base, &mask, sizeof key,
    5804                 :            :                odp_actions)) {
    5805                 :          4 :         put_nd_key(&base, base_flow);
    5806                 :          4 :         put_nd_key(&mask, &wc->masks);
    5807                 :          4 :         return SLOW_ACTION;
    5808                 :            :     }
    5809                 :            : 
    5810                 :       2636 :     return 0;
    5811                 :            : }
    5812                 :            : 
    5813                 :            : static enum slow_path_reason
    5814                 :     116809 : commit_set_nw_action(const struct flow *flow, struct flow *base,
    5815                 :            :                      struct ofpbuf *odp_actions, struct flow_wildcards *wc,
    5816                 :            :                      bool use_masked)
    5817                 :            : {
    5818                 :            :     /* Check if 'flow' really has an L3 header. */
    5819         [ +  + ]:     116809 :     if (!flow->nw_proto) {
    5820                 :      15760 :         return 0;
    5821                 :            :     }
    5822                 :            : 
    5823   [ +  +  +  + ]:     101049 :     switch (ntohs(base->dl_type)) {
    5824                 :            :     case ETH_TYPE_IP:
    5825                 :      52185 :         commit_set_ipv4_action(flow, base, odp_actions, wc, use_masked);
    5826                 :      52185 :         break;
    5827                 :            : 
    5828                 :            :     case ETH_TYPE_IPV6:
    5829                 :       2636 :         commit_set_ipv6_action(flow, base, odp_actions, wc, use_masked);
    5830                 :       2636 :         return commit_set_nd_action(flow, base, odp_actions, wc, use_masked);
    5831                 :            : 
    5832                 :            :     case ETH_TYPE_ARP:
    5833                 :      46214 :         return commit_set_arp_action(flow, base, odp_actions, wc);
    5834                 :            :     }
    5835                 :            : 
    5836                 :      52199 :     return 0;
    5837                 :            : }
    5838                 :            : 
    5839                 :            : /* TCP, UDP, and SCTP keys have the same layout. */
    5840                 :            : BUILD_ASSERT_DECL(sizeof(struct ovs_key_tcp) == sizeof(struct ovs_key_udp) &&
    5841                 :            :                   sizeof(struct ovs_key_tcp) == sizeof(struct ovs_key_sctp));
    5842                 :            : 
    5843                 :            : static void
    5844                 :      50186 : get_tp_key(const struct flow *flow, union ovs_key_tp *tp)
    5845                 :            : {
    5846                 :      50186 :     tp->tcp.tcp_src = flow->tp_src;
    5847                 :      50186 :     tp->tcp.tcp_dst = flow->tp_dst;
    5848                 :      50186 : }
    5849                 :            : 
    5850                 :            : static void
    5851                 :      15798 : put_tp_key(const union ovs_key_tp *tp, struct flow *flow)
    5852                 :            : {
    5853                 :      15798 :     flow->tp_src = tp->tcp.tcp_src;
    5854                 :      15798 :     flow->tp_dst = tp->tcp.tcp_dst;
    5855                 :      15798 : }
    5856                 :            : 
    5857                 :            : static void
    5858                 :     116809 : commit_set_port_action(const struct flow *flow, struct flow *base_flow,
    5859                 :            :                        struct ofpbuf *odp_actions, struct flow_wildcards *wc,
    5860                 :            :                        bool use_masked)
    5861                 :            : {
    5862                 :            :     enum ovs_key_attr key_type;
    5863                 :            :     union ovs_key_tp key, mask, base;
    5864                 :            : 
    5865                 :            :     /* Check if 'flow' really has an L3 header. */
    5866         [ +  + ]:     116809 :     if (!flow->nw_proto) {
    5867                 :     102911 :         return;
    5868                 :            :     }
    5869                 :            : 
    5870         [ +  + ]:     101049 :     if (!is_ip_any(base_flow)) {
    5871                 :      46228 :         return;
    5872                 :            :     }
    5873                 :            : 
    5874         [ +  + ]:      54821 :     if (flow->nw_proto == IPPROTO_TCP) {
    5875                 :       3366 :         key_type = OVS_KEY_ATTR_TCP;
    5876         [ +  + ]:      51455 :     } else if (flow->nw_proto == IPPROTO_UDP) {
    5877                 :      10523 :         key_type = OVS_KEY_ATTR_UDP;
    5878         [ +  + ]:      40932 :     } else if (flow->nw_proto == IPPROTO_SCTP) {
    5879                 :          9 :         key_type = OVS_KEY_ATTR_SCTP;
    5880                 :            :     } else {
    5881                 :      40923 :         return;
    5882                 :            :     }
    5883                 :            : 
    5884                 :      13898 :     get_tp_key(flow, &key);
    5885                 :      13898 :     get_tp_key(base_flow, &base);
    5886                 :      13898 :     get_tp_key(&wc->masks, &mask);
    5887                 :            : 
    5888         [ +  + ]:      13898 :     if (commit(key_type, use_masked, &key, &base, &mask, sizeof key,
    5889                 :            :                odp_actions)) {
    5890                 :         26 :         put_tp_key(&base, base_flow);
    5891                 :      13898 :         put_tp_key(&mask, &wc->masks);
    5892                 :            :     }
    5893                 :            : }
    5894                 :            : 
    5895                 :            : static void
    5896                 :     116809 : commit_set_priority_action(const struct flow *flow, struct flow *base_flow,
    5897                 :            :                            struct ofpbuf *odp_actions,
    5898                 :            :                            struct flow_wildcards *wc,
    5899                 :            :                            bool use_masked)
    5900                 :            : {
    5901                 :            :     uint32_t key, mask, base;
    5902                 :            : 
    5903                 :     116809 :     key = flow->skb_priority;
    5904                 :     116809 :     base = base_flow->skb_priority;
    5905                 :     116809 :     mask = wc->masks.skb_priority;
    5906                 :            : 
    5907         [ +  + ]:     116809 :     if (commit(OVS_KEY_ATTR_PRIORITY, use_masked, &key, &base, &mask,
    5908                 :            :                sizeof key, odp_actions)) {
    5909                 :          7 :         base_flow->skb_priority = base;
    5910                 :          7 :         wc->masks.skb_priority = mask;
    5911                 :            :     }
    5912                 :     116809 : }
    5913                 :            : 
    5914                 :            : static void
    5915                 :     116809 : commit_set_pkt_mark_action(const struct flow *flow, struct flow *base_flow,
    5916                 :            :                            struct ofpbuf *odp_actions,
    5917                 :            :                            struct flow_wildcards *wc,
    5918                 :            :                            bool use_masked)
    5919                 :            : {
    5920                 :            :     uint32_t key, mask, base;
    5921                 :            : 
    5922                 :     116809 :     key = flow->pkt_mark;
    5923                 :     116809 :     base = base_flow->pkt_mark;
    5924                 :     116809 :     mask = wc->masks.pkt_mark;
    5925                 :            : 
    5926         [ +  + ]:     116809 :     if (commit(OVS_KEY_ATTR_SKB_MARK, use_masked, &key, &base, &mask,
    5927                 :            :                sizeof key, odp_actions)) {
    5928                 :          7 :         base_flow->pkt_mark = base;
    5929                 :          7 :         wc->masks.pkt_mark = mask;
    5930                 :            :     }
    5931                 :     116809 : }
    5932                 :            : 
    5933                 :            : /* If any of the flow key data that ODP actions can modify are different in
    5934                 :            :  * 'base' and 'flow', appends ODP actions to 'odp_actions' that change the flow
    5935                 :            :  * key from 'base' into 'flow', and then changes 'base' the same way.  Does not
    5936                 :            :  * commit set_tunnel actions.  Users should call commit_odp_tunnel_action()
    5937                 :            :  * in addition to this function if needed.  Sets fields in 'wc' that are
    5938                 :            :  * used as part of the action.
    5939                 :            :  *
    5940                 :            :  * Returns a reason to force processing the flow's packets into the userspace
    5941                 :            :  * slow path, if there is one, otherwise 0. */
    5942                 :            : enum slow_path_reason
    5943                 :     116809 : commit_odp_actions(const struct flow *flow, struct flow *base,
    5944                 :            :                    struct ofpbuf *odp_actions, struct flow_wildcards *wc,
    5945                 :            :                    bool use_masked)
    5946                 :            : {
    5947                 :            :     enum slow_path_reason slow1, slow2;
    5948                 :            : 
    5949                 :     116809 :     commit_set_ether_addr_action(flow, base, odp_actions, wc, use_masked);
    5950                 :     116809 :     slow1 = commit_set_nw_action(flow, base, odp_actions, wc, use_masked);
    5951                 :     116809 :     commit_set_port_action(flow, base, odp_actions, wc, use_masked);
    5952                 :     116809 :     slow2 = commit_set_icmp_action(flow, base, odp_actions, wc);
    5953                 :     116809 :     commit_mpls_action(flow, base, odp_actions);
    5954                 :     116809 :     commit_vlan_action(flow->vlan_tci, base, odp_actions, wc);
    5955                 :     116809 :     commit_set_priority_action(flow, base, odp_actions, wc, use_masked);
    5956                 :     116809 :     commit_set_pkt_mark_action(flow, base, odp_actions, wc, use_masked);
    5957                 :            : 
    5958         [ +  + ]:     116809 :     return slow1 ? slow1 : slow2;
    5959                 :            : }

Generated by: LCOV version 1.12