LCOV - code coverage report
Current view: top level - lib - nx-match.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 735 812 90.5 %
Date: 2016-09-14 01:02:56 Functions: 95 95 100.0 %
Branches: 368 486 75.7 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 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                 :            : 
      19                 :            : #include "nx-match.h"
      20                 :            : 
      21                 :            : #include <netinet/icmp6.h>
      22                 :            : 
      23                 :            : #include "classifier.h"
      24                 :            : #include "colors.h"
      25                 :            : #include "openvswitch/hmap.h"
      26                 :            : #include "openflow/nicira-ext.h"
      27                 :            : #include "openvswitch/dynamic-string.h"
      28                 :            : #include "openvswitch/meta-flow.h"
      29                 :            : #include "openvswitch/ofp-actions.h"
      30                 :            : #include "openvswitch/ofp-errors.h"
      31                 :            : #include "openvswitch/ofp-util.h"
      32                 :            : #include "openvswitch/ofpbuf.h"
      33                 :            : #include "openvswitch/vlog.h"
      34                 :            : #include "packets.h"
      35                 :            : #include "openvswitch/shash.h"
      36                 :            : #include "tun-metadata.h"
      37                 :            : #include "unaligned.h"
      38                 :            : #include "util.h"
      39                 :            : 
      40                 :      20190 : VLOG_DEFINE_THIS_MODULE(nx_match);
      41                 :            : 
      42                 :            : /* OXM headers.
      43                 :            :  *
      44                 :            :  *
      45                 :            :  * Standard OXM/NXM
      46                 :            :  * ================
      47                 :            :  *
      48                 :            :  * The header is 32 bits long.  It looks like this:
      49                 :            :  *
      50                 :            :  * |31                              16 15            9| 8 7                0
      51                 :            :  * +----------------------------------+---------------+--+------------------+
      52                 :            :  * |            oxm_class             |   oxm_field   |hm|    oxm_length    |
      53                 :            :  * +----------------------------------+---------------+--+------------------+
      54                 :            :  *
      55                 :            :  * where hm stands for oxm_hasmask.  It is followed by oxm_length bytes of
      56                 :            :  * payload.  When oxm_hasmask is 0, the payload is the value of the field
      57                 :            :  * identified by the header; when oxm_hasmask is 1, the payload is a value for
      58                 :            :  * the field followed by a mask of equal length.
      59                 :            :  *
      60                 :            :  * Internally, we represent a standard OXM header as a 64-bit integer with the
      61                 :            :  * above information in the most-significant bits.
      62                 :            :  *
      63                 :            :  *
      64                 :            :  * Experimenter OXM
      65                 :            :  * ================
      66                 :            :  *
      67                 :            :  * The header is 64 bits long.  It looks like the diagram above except that a
      68                 :            :  * 32-bit experimenter ID, which we call oxm_vendor and which identifies a
      69                 :            :  * vendor, is inserted just before the payload.  Experimenter OXMs are
      70                 :            :  * identified by an all-1-bits oxm_class (OFPXMC12_EXPERIMENTER).  The
      71                 :            :  * oxm_length value *includes* the experimenter ID, so that the real payload is
      72                 :            :  * only oxm_length - 4 bytes long.
      73                 :            :  *
      74                 :            :  * Internally, we represent an experimenter OXM header as a 64-bit integer with
      75                 :            :  * the standard header in the upper 32 bits and the experimenter ID in the
      76                 :            :  * lower 32 bits.  (It would be more convenient to swap the positions of the
      77                 :            :  * two 32-bit words, but this would be more error-prone because experimenter
      78                 :            :  * OXMs are very rarely used, so accidentally passing one through a 32-bit type
      79                 :            :  * somewhere in the OVS code would be hard to find.)
      80                 :            :  */
      81                 :            : 
      82                 :            : /*
      83                 :            :  * OXM Class IDs.
      84                 :            :  * The high order bit differentiate reserved classes from member classes.
      85                 :            :  * Classes 0x0000 to 0x7FFF are member classes, allocated by ONF.
      86                 :            :  * Classes 0x8000 to 0xFFFE are reserved classes, reserved for standardisation.
      87                 :            :  */
      88                 :            : enum ofp12_oxm_class {
      89                 :            :     OFPXMC12_NXM_0          = 0x0000, /* Backward compatibility with NXM */
      90                 :            :     OFPXMC12_NXM_1          = 0x0001, /* Backward compatibility with NXM */
      91                 :            :     OFPXMC12_OPENFLOW_BASIC = 0x8000, /* Basic class for OpenFlow */
      92                 :            :     OFPXMC15_PACKET_REGS    = 0x8001, /* Packet registers (pipeline fields). */
      93                 :            :     OFPXMC12_EXPERIMENTER   = 0xffff, /* Experimenter class */
      94                 :            : };
      95                 :            : 
      96                 :            : /* Functions for extracting raw field values from OXM/NXM headers. */
      97                 :     826408 : static uint32_t nxm_vendor(uint64_t header) { return header; }
      98                 :   13632040 : static int nxm_class(uint64_t header) { return header >> 48; }
      99                 :    2865640 : static int nxm_field(uint64_t header) { return (header >> 41) & 0x7f; }
     100                 :    7300592 : static bool nxm_hasmask(uint64_t header) { return (header >> 40) & 1; }
     101                 :   11678480 : static int nxm_length(uint64_t header) { return (header >> 32) & 0xff; }
     102                 :   10931894 : static uint64_t nxm_no_len(uint64_t header) { return header & 0xffffff80ffffffffULL; }
     103                 :            : 
     104                 :            : static bool
     105                 :    5383200 : is_experimenter_oxm(uint64_t header)
     106                 :            : {
     107                 :    5383200 :     return nxm_class(header) == OFPXMC12_EXPERIMENTER;
     108                 :            : }
     109                 :            : 
     110                 :            : /* The OXM header "length" field is somewhat tricky:
     111                 :            :  *
     112                 :            :  *     - For a standard OXM header, the length is the number of bytes of the
     113                 :            :  *       payload, and the payload consists of just the value (and mask, if
     114                 :            :  *       present).
     115                 :            :  *
     116                 :            :  *     - For an experimenter OXM header, the length is the number of bytes in
     117                 :            :  *       the payload plus 4 (the length of the experimenter ID).  That is, the
     118                 :            :  *       experimenter ID is included in oxm_length.
     119                 :            :  *
     120                 :            :  * This function returns the length of the experimenter ID field in 'header'.
     121                 :            :  * That is, for an experimenter OXM (when an experimenter ID is present), it
     122                 :            :  * returns 4, and for a standard OXM (when no experimenter ID is present), it
     123                 :            :  * returns 0. */
     124                 :            : static int
     125                 :    4177272 : nxm_experimenter_len(uint64_t header)
     126                 :            : {
     127         [ +  + ]:    4177272 :     return is_experimenter_oxm(header) ? 4 : 0;
     128                 :            : }
     129                 :            : 
     130                 :            : /* Returns the number of bytes that follow the header for an NXM/OXM entry
     131                 :            :  * with the given 'header'. */
     132                 :            : static int
     133                 :     765167 : nxm_payload_len(uint64_t header)
     134                 :            : {
     135                 :     765167 :     return nxm_length(header) - nxm_experimenter_len(header);
     136                 :            : }
     137                 :            : 
     138                 :            : /* Returns the number of bytes in the header for an NXM/OXM entry with the
     139                 :            :  * given 'header'. */
     140                 :            : static int
     141                 :    1835160 : nxm_header_len(uint64_t header)
     142                 :            : {
     143                 :    1835160 :     return 4 + nxm_experimenter_len(header);
     144                 :            : }
     145                 :            : 
     146                 :            : #define NXM_HEADER(VENDOR, CLASS, FIELD, HASMASK, LENGTH)       \
     147                 :            :     (((uint64_t) (CLASS) << 48) |                               \
     148                 :            :      ((uint64_t) (FIELD) << 41) |                               \
     149                 :            :      ((uint64_t) (HASMASK) << 40) |                             \
     150                 :            :      ((uint64_t) (LENGTH) << 32) |                              \
     151                 :            :      (VENDOR))
     152                 :            : 
     153                 :            : #define NXM_HEADER_FMT "%#"PRIx32":%d:%d:%d:%d"
     154                 :            : #define NXM_HEADER_ARGS(HEADER)                                 \
     155                 :            :     nxm_vendor(HEADER), nxm_class(HEADER), nxm_field(HEADER),   \
     156                 :            :     nxm_hasmask(HEADER), nxm_length(HEADER)
     157                 :            : 
     158                 :            : /* Functions for turning the "hasmask" bit on or off.  (This also requires
     159                 :            :  * adjusting the length.) */
     160                 :            : static uint64_t
     161                 :     157190 : nxm_make_exact_header(uint64_t header)
     162                 :            : {
     163                 :     157190 :     int new_len = nxm_payload_len(header) / 2 + nxm_experimenter_len(header);
     164                 :     157190 :     return NXM_HEADER(nxm_vendor(header), nxm_class(header),
     165                 :            :                       nxm_field(header), 0, new_len);
     166                 :            : }
     167                 :            : static uint64_t
     168                 :      78739 : nxm_make_wild_header(uint64_t header)
     169                 :            : {
     170                 :      78739 :     int new_len = nxm_payload_len(header) * 2 + nxm_experimenter_len(header);
     171                 :      78739 :     return NXM_HEADER(nxm_vendor(header), nxm_class(header),
     172                 :            :                       nxm_field(header), 1, new_len);
     173                 :            : }
     174                 :            : 
     175                 :            : /* Flow cookie.
     176                 :            :  *
     177                 :            :  * This may be used to gain the OpenFlow 1.1-like ability to restrict
     178                 :            :  * certain NXM-based Flow Mod and Flow Stats Request messages to flows
     179                 :            :  * with specific cookies.  See the "nx_flow_mod" and "nx_flow_stats_request"
     180                 :            :  * structure definitions for more details.  This match is otherwise not
     181                 :            :  * allowed. */
     182                 :            : #define NXM_NX_COOKIE     NXM_HEADER  (0, 0x0001, 30, 0, 8)
     183                 :            : #define NXM_NX_COOKIE_W   nxm_make_wild_header(NXM_NX_COOKIE)
     184                 :            : 
     185                 :            : struct nxm_field {
     186                 :            :     uint64_t header;
     187                 :            :     enum ofp_version version;
     188                 :            :     const char *name;           /* e.g. "NXM_OF_IN_PORT". */
     189                 :            : 
     190                 :            :     enum mf_field_id id;
     191                 :            : };
     192                 :            : 
     193                 :            : static const struct nxm_field *nxm_field_by_header(uint64_t header);
     194                 :            : static const struct nxm_field *nxm_field_by_name(const char *name, size_t len);
     195                 :            : static const struct nxm_field *nxm_field_by_mf_id(enum mf_field_id,
     196                 :            :                                                   enum ofp_version);
     197                 :            : 
     198                 :            : static void nx_put_header__(struct ofpbuf *, uint64_t header, bool masked);
     199                 :            : static void nx_put_header_len(struct ofpbuf *, enum mf_field_id field,
     200                 :            :                               enum ofp_version version, bool masked,
     201                 :            :                               size_t n_bytes);
     202                 :            : 
     203                 :            : /* Rate limit for nx_match parse errors.  These always indicate a bug in the
     204                 :            :  * peer and so there's not much point in showing a lot of them. */
     205                 :            : static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
     206                 :            : 
     207                 :            : static const struct nxm_field *
     208                 :            : mf_parse_subfield_name(const char *name, int name_len, bool *wild);
     209                 :            : 
     210                 :            : /* Returns the preferred OXM header to use for field 'id' in OpenFlow version
     211                 :            :  * 'version'.  Specify 0 for 'version' if an NXM legacy header should be
     212                 :            :  * preferred over any standardized OXM header.  Returns 0 if field 'id' cannot
     213                 :            :  * be expressed in NXM or OXM. */
     214                 :            : static uint64_t
     215                 :    1846454 : mf_oxm_header(enum mf_field_id id, enum ofp_version version)
     216                 :            : {
     217                 :    1846454 :     const struct nxm_field *f = nxm_field_by_mf_id(id, version);
     218         [ +  + ]:    1846454 :     return f ? f->header : 0;
     219                 :            : }
     220                 :            : 
     221                 :            : /* Returns the 32-bit OXM or NXM header to use for field 'id', preferring an
     222                 :            :  * NXM legacy header over any standardized OXM header.  Returns 0 if field 'id'
     223                 :            :  * cannot be expressed with a 32-bit NXM or OXM header.
     224                 :            :  *
     225                 :            :  * Whenever possible, use nx_pull_header() instead of this function, because
     226                 :            :  * this function cannot support 64-bit experimenter OXM headers. */
     227                 :            : uint32_t
     228                 :      42169 : mf_nxm_header(enum mf_field_id id)
     229                 :            : {
     230                 :      42169 :     uint64_t oxm = mf_oxm_header(id, 0);
     231         [ -  + ]:      42169 :     return is_experimenter_oxm(oxm) ? 0 : oxm >> 32;
     232                 :            : }
     233                 :            : 
     234                 :            : static const struct mf_field *
     235                 :    1181709 : mf_from_oxm_header(uint64_t header)
     236                 :            : {
     237                 :    1181709 :     const struct nxm_field *f = nxm_field_by_header(header);
     238         [ +  + ]:    1181709 :     return f ? mf_from_id(f->id) : NULL;
     239                 :            : }
     240                 :            : 
     241                 :            : /* Returns the "struct mf_field" that corresponds to NXM or OXM header
     242                 :            :  * 'header', or NULL if 'header' doesn't correspond to any known field.  */
     243                 :            : const struct mf_field *
     244                 :      17962 : mf_from_nxm_header(uint32_t header)
     245                 :            : {
     246                 :      17962 :     return mf_from_oxm_header((uint64_t) header << 32);
     247                 :            : }
     248                 :            : 
     249                 :            : /* Returns the width of the data for a field with the given 'header', in
     250                 :            :  * bytes. */
     251                 :            : static int
     252                 :     278256 : nxm_field_bytes(uint64_t header)
     253                 :            : {
     254                 :     278256 :     unsigned int length = nxm_payload_len(header);
     255         [ +  + ]:     278256 :     return nxm_hasmask(header) ? length / 2 : length;
     256                 :            : }
     257                 :            : 
     258                 :            : /* nx_pull_match() and helpers. */
     259                 :            : 
     260                 :            : /* Given NXM/OXM value 'value' and mask 'mask' associated with 'header', checks
     261                 :            :  * for any 1-bit in the value where there is a 0-bit in the mask.  Returns 0 if
     262                 :            :  * none, otherwise an error code. */
     263                 :            : static bool
     264                 :      24996 : is_mask_consistent(uint64_t header, const uint8_t *value, const uint8_t *mask)
     265                 :            : {
     266                 :      24996 :     unsigned int width = nxm_field_bytes(header);
     267                 :            :     unsigned int i;
     268                 :            : 
     269         [ +  + ]:     124033 :     for (i = 0; i < width; i++) {
     270         [ +  + ]:      99064 :         if (value[i] & ~mask[i]) {
     271         [ +  + ]:         27 :             if (!VLOG_DROP_WARN(&rl)) {
     272         [ +  - ]:          6 :                 VLOG_WARN_RL(&rl, "Rejecting NXM/OXM entry "NXM_HEADER_FMT " "
     273                 :            :                              "with 1-bits in value for bits wildcarded by the "
     274                 :            :                              "mask.", NXM_HEADER_ARGS(header));
     275                 :            :             }
     276                 :         27 :             return false;
     277                 :            :         }
     278                 :            :     }
     279                 :      24969 :     return true;
     280                 :            : }
     281                 :            : 
     282                 :            : static bool
     283                 :         54 : is_cookie_pseudoheader(uint64_t header)
     284                 :            : {
     285 [ +  + ][ +  + ]:         54 :     return header == NXM_NX_COOKIE || header == NXM_NX_COOKIE_W;
     286                 :            : }
     287                 :            : 
     288                 :            : static enum ofperr
     289                 :    1163747 : nx_pull_header__(struct ofpbuf *b, bool allow_cookie, uint64_t *header,
     290                 :            :                  const struct mf_field **field)
     291                 :            : {
     292         [ -  + ]:    1163747 :     if (b->size < 4) {
     293                 :          0 :         goto bad_len;
     294                 :            :     }
     295                 :            : 
     296                 :    1163747 :     *header = ((uint64_t) ntohl(get_unaligned_be32(b->data))) << 32;
     297         [ +  + ]:    1163747 :     if (is_experimenter_oxm(*header)) {
     298         [ -  + ]:       4100 :         if (b->size < 8) {
     299                 :          0 :             goto bad_len;
     300                 :            :         }
     301                 :       4100 :         *header = ntohll(get_unaligned_be64(b->data));
     302                 :            :     }
     303         [ -  + ]:    1163747 :     if (nxm_length(*header) < nxm_experimenter_len(*header)) {
     304         [ #  # ]:          0 :         VLOG_WARN_RL(&rl, "OXM header "NXM_HEADER_FMT" has invalid length %d "
     305                 :            :                      "(minimum is %d)",
     306                 :            :                      NXM_HEADER_ARGS(*header), nxm_length(*header),
     307                 :            :                      nxm_header_len(*header));
     308                 :          0 :         goto error;
     309                 :            :     }
     310                 :    1163747 :     ofpbuf_pull(b, nxm_header_len(*header));
     311                 :            : 
     312         [ +  - ]:    1163747 :     if (field) {
     313                 :    1163747 :         *field = mf_from_oxm_header(*header);
     314 [ +  + ][ +  + ]:    1163747 :         if (!*field && !(allow_cookie && is_cookie_pseudoheader(*header))) {
                 [ +  + ]
     315         [ -  + ]:         18 :             VLOG_DBG_RL(&rl, "OXM header "NXM_HEADER_FMT" is unknown",
     316                 :            :                         NXM_HEADER_ARGS(*header));
     317                 :         18 :             return OFPERR_OFPBMC_BAD_FIELD;
     318                 :            :         }
     319                 :            :     }
     320                 :            : 
     321                 :    1163729 :     return 0;
     322                 :            : 
     323                 :            : bad_len:
     324         [ #  # ]:          0 :     VLOG_DBG_RL(&rl, "encountered partial (%"PRIu32"-byte) OXM entry",
     325                 :            :                 b->size);
     326                 :            : error:
     327                 :          0 :     *header = 0;
     328         [ #  # ]:          0 :     if (field) {
     329                 :          0 :         *field = NULL;
     330                 :            :     }
     331                 :          0 :     return OFPERR_OFPBMC_BAD_LEN;
     332                 :            : }
     333                 :            : 
     334                 :            : static void
     335                 :     275923 : copy_entry_value(const struct mf_field *field, union mf_value *value,
     336                 :            :                  const uint8_t *payload, int width)
     337                 :            : {
     338                 :            :     int copy_len;
     339                 :            :     void *copy_dst;
     340                 :            : 
     341                 :     275923 :     copy_dst = value;
     342         [ +  + ]:     275923 :     copy_len = MIN(width, field ? field->n_bytes : sizeof *value);
     343                 :            : 
     344 [ +  + ][ +  + ]:     275923 :     if (field && field->variable_len) {
     345                 :       1425 :         memset(value, 0, field->n_bytes);
     346                 :       1425 :         copy_dst = &value->u8 + field->n_bytes - copy_len;
     347                 :            :     }
     348                 :            : 
     349                 :     275923 :     memcpy(copy_dst, payload, copy_len);
     350                 :     275923 : }
     351                 :            : 
     352                 :            : static enum ofperr
     353                 :     250982 : nx_pull_entry__(struct ofpbuf *b, bool allow_cookie, uint64_t *header,
     354                 :            :                 const struct mf_field **field_,
     355                 :            :                 union mf_value *value, union mf_value *mask)
     356                 :            : {
     357                 :            :     const struct mf_field *field;
     358                 :            :     enum ofperr header_error;
     359                 :            :     unsigned int payload_len;
     360                 :            :     const uint8_t *payload;
     361                 :            :     int width;
     362                 :            : 
     363                 :     250982 :     header_error = nx_pull_header__(b, allow_cookie, header, &field);
     364 [ +  + ][ -  + ]:     250982 :     if (header_error && header_error != OFPERR_OFPBMC_BAD_FIELD) {
     365                 :          0 :         return header_error;
     366                 :            :     }
     367                 :            : 
     368                 :     250982 :     payload_len = nxm_payload_len(*header);
     369                 :     250982 :     payload = ofpbuf_try_pull(b, payload_len);
     370         [ -  + ]:     250982 :     if (!payload) {
     371         [ #  # ]:          0 :         VLOG_DBG_RL(&rl, "OXM header "NXM_HEADER_FMT" calls for %u-byte "
     372                 :            :                     "payload but only %"PRIu32" bytes follow OXM header",
     373                 :            :                     NXM_HEADER_ARGS(*header), payload_len, b->size);
     374                 :          0 :         return OFPERR_OFPBMC_BAD_LEN;
     375                 :            :     }
     376                 :            : 
     377                 :     250982 :     width = nxm_field_bytes(*header);
     378         [ +  + ]:     250982 :     if (nxm_hasmask(*header)
     379         [ +  + ]:      24996 :         && !is_mask_consistent(*header, payload, payload + width)) {
     380                 :         27 :         return OFPERR_OFPBMC_BAD_WILDCARDS;
     381                 :            :     }
     382                 :            : 
     383                 :     250955 :     copy_entry_value(field, value, payload, width);
     384                 :            : 
     385         [ +  + ]:     250955 :     if (mask) {
     386         [ +  + ]:     228826 :         if (nxm_hasmask(*header)) {
     387                 :      24968 :             copy_entry_value(field, mask, payload + width, width);
     388                 :            :         } else {
     389                 :     228826 :             memset(mask, 0xff, sizeof *mask);
     390                 :            :         }
     391         [ +  + ]:      22129 :     } else if (nxm_hasmask(*header)) {
     392         [ -  + ]:          1 :         VLOG_DBG_RL(&rl, "OXM header "NXM_HEADER_FMT" includes mask but "
     393                 :            :                     "masked OXMs are not allowed here",
     394                 :            :                     NXM_HEADER_ARGS(*header));
     395                 :          1 :         return OFPERR_OFPBMC_BAD_MASK;
     396                 :            :     }
     397                 :            : 
     398         [ +  + ]:     250954 :     if (field_) {
     399                 :     250347 :         *field_ = field;
     400                 :     250347 :         return header_error;
     401                 :            :     }
     402                 :            : 
     403                 :     250982 :     return 0;
     404                 :            : }
     405                 :            : 
     406                 :            : /* Attempts to pull an NXM or OXM header, value, and mask (if present) from the
     407                 :            :  * beginning of 'b'.  If successful, stores a pointer to the "struct mf_field"
     408                 :            :  * corresponding to the pulled header in '*field', the value into '*value',
     409                 :            :  * and the mask into '*mask', and returns 0.  On error, returns an OpenFlow
     410                 :            :  * error; in this case, some bytes might have been pulled off 'b' anyhow, and
     411                 :            :  * the output parameters might have been modified.
     412                 :            :  *
     413                 :            :  * If a NULL 'mask' is supplied, masked OXM or NXM entries are treated as
     414                 :            :  * errors (with OFPERR_OFPBMC_BAD_MASK).
     415                 :            :  */
     416                 :            : enum ofperr
     417                 :      22831 : nx_pull_entry(struct ofpbuf *b, const struct mf_field **field,
     418                 :            :               union mf_value *value, union mf_value *mask)
     419                 :            : {
     420                 :            :     uint64_t header;
     421                 :            : 
     422                 :      22831 :     return nx_pull_entry__(b, false, &header, field, value, mask);
     423                 :            : }
     424                 :            : 
     425                 :            : /* Attempts to pull an NXM or OXM header from the beginning of 'b'.  If
     426                 :            :  * successful, stores a pointer to the "struct mf_field" corresponding to the
     427                 :            :  * pulled header in '*field', stores the header's hasmask bit in '*masked'
     428                 :            :  * (true if hasmask=1, false if hasmask=0), and returns 0.  On error, returns
     429                 :            :  * an OpenFlow error; in this case, some bytes might have been pulled off 'b'
     430                 :            :  * anyhow, and the output parameters might have been modified.
     431                 :            :  *
     432                 :            :  * If NULL 'masked' is supplied, masked OXM or NXM headers are treated as
     433                 :            :  * errors (with OFPERR_OFPBMC_BAD_MASK).
     434                 :            :  */
     435                 :            : enum ofperr
     436                 :     912765 : nx_pull_header(struct ofpbuf *b, const struct mf_field **field, bool *masked)
     437                 :            : {
     438                 :            :     enum ofperr error;
     439                 :            :     uint64_t header;
     440                 :            : 
     441                 :     912765 :     error = nx_pull_header__(b, false, &header, field);
     442         [ +  + ]:     912765 :     if (masked) {
     443 [ +  - ][ +  + ]:     882160 :         *masked = !error && nxm_hasmask(header);
     444 [ +  - ][ -  + ]:      30605 :     } else if (!error && nxm_hasmask(header)) {
     445                 :          0 :         error = OFPERR_OFPBMC_BAD_MASK;
     446                 :            :     }
     447                 :     912765 :     return error;
     448                 :            : }
     449                 :            : 
     450                 :            : static enum ofperr
     451                 :     227517 : nx_pull_match_entry(struct ofpbuf *b, bool allow_cookie,
     452                 :            :                     const struct mf_field **field,
     453                 :            :                     union mf_value *value, union mf_value *mask)
     454                 :            : {
     455                 :            :     enum ofperr error;
     456                 :            :     uint64_t header;
     457                 :            : 
     458                 :     227517 :     error = nx_pull_entry__(b, allow_cookie, &header, field, value, mask);
     459         [ +  + ]:     227517 :     if (error) {
     460                 :         45 :         return error;
     461                 :            :     }
     462 [ +  - ][ +  + ]:     227472 :     if (field && *field) {
     463         [ -  + ]:     227430 :         if (!mf_is_mask_valid(*field, mask)) {
     464         [ #  # ]:          0 :             VLOG_DBG_RL(&rl, "bad mask for field %s", (*field)->name);
     465                 :          0 :             return OFPERR_OFPBMC_BAD_MASK;
     466                 :            :         }
     467         [ +  + ]:     227430 :         if (!mf_is_value_valid(*field, value)) {
     468         [ -  + ]:         14 :             VLOG_DBG_RL(&rl, "bad value for field %s", (*field)->name);
     469                 :         14 :             return OFPERR_OFPBMC_BAD_VALUE;
     470                 :            :         }
     471                 :            :     }
     472                 :     227517 :     return 0;
     473                 :            : }
     474                 :            : 
     475                 :            : static enum ofperr
     476                 :     124912 : nx_pull_raw(const uint8_t *p, unsigned int match_len, bool strict,
     477                 :            :             struct match *match, ovs_be64 *cookie, ovs_be64 *cookie_mask)
     478                 :            : {
     479         [ -  + ]:     124912 :     ovs_assert((cookie != NULL) == (cookie_mask != NULL));
     480                 :            : 
     481                 :     124912 :     match_init_catchall(match);
     482         [ +  + ]:     124912 :     if (cookie) {
     483                 :      15866 :         *cookie = *cookie_mask = htonll(0);
     484                 :            :     }
     485                 :            : 
     486                 :     124912 :     struct ofpbuf b = ofpbuf_const_initializer(p, match_len);
     487         [ +  + ]:     352283 :     while (b.size) {
     488                 :     227517 :         const uint8_t *pos = b.data;
     489                 :            :         const struct mf_field *field;
     490                 :            :         union mf_value value;
     491                 :            :         union mf_value mask;
     492                 :            :         enum ofperr error;
     493                 :            : 
     494                 :     227517 :         error = nx_pull_match_entry(&b, cookie != NULL, &field, &value, &mask);
     495         [ +  + ]:     227517 :         if (error) {
     496 [ +  + ][ +  + ]:         59 :             if (error == OFPERR_OFPBMC_BAD_FIELD && !strict) {
     497                 :          6 :                 continue;
     498                 :            :             }
     499         [ +  + ]:     227458 :         } else if (!field) {
     500         [ -  + ]:         42 :             if (!cookie) {
     501                 :          0 :                 error = OFPERR_OFPBMC_BAD_FIELD;
     502         [ -  + ]:         42 :             } else if (*cookie_mask) {
     503                 :          0 :                 error = OFPERR_OFPBMC_DUP_FIELD;
     504                 :            :             } else {
     505                 :         42 :                 *cookie = value.be64;
     506                 :         42 :                 *cookie_mask = mask.be64;
     507                 :            :             }
     508         [ +  + ]:     227416 :         } else if (!mf_are_prereqs_ok(field, &match->flow, NULL)) {
     509                 :         88 :             error = OFPERR_OFPBMC_BAD_PREREQ;
     510         [ +  + ]:     227328 :         } else if (!mf_is_all_wild(field, &match->wc)) {
     511                 :          5 :             error = OFPERR_OFPBMC_DUP_FIELD;
     512                 :            :         } else {
     513                 :            :             char *err_str;
     514                 :            : 
     515                 :     227323 :             mf_set(field, &value, &mask, match, &err_str);
     516         [ -  + ]:     227323 :             if (err_str) {
     517         [ #  # ]:          0 :                 VLOG_DBG_RL(&rl, "error parsing OXM at offset %"PRIdPTR" "
     518                 :            :                            "within match (%s)", pos - p, err_str);
     519                 :          0 :                 free(err_str);
     520                 :     227323 :                 return OFPERR_OFPBMC_BAD_VALUE;
     521                 :            :             }
     522                 :            :         }
     523                 :            : 
     524         [ +  + ]:     227511 :         if (error) {
     525         [ -  + ]:        146 :             VLOG_DBG_RL(&rl, "error parsing OXM at offset %"PRIdPTR" "
     526                 :            :                         "within match (%s)", pos -
     527                 :            :                         p, ofperr_to_string(error));
     528                 :     227511 :             return error;
     529                 :            :         }
     530                 :            :     }
     531                 :            : 
     532                 :     124912 :     return 0;
     533                 :            : }
     534                 :            : 
     535                 :            : static enum ofperr
     536                 :      72324 : nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict,
     537                 :            :                 struct match *match,
     538                 :            :                 ovs_be64 *cookie, ovs_be64 *cookie_mask)
     539                 :            : {
     540                 :      72324 :     uint8_t *p = NULL;
     541                 :            : 
     542         [ +  + ]:      72324 :     if (match_len) {
     543                 :      71417 :         p = ofpbuf_try_pull(b, ROUND_UP(match_len, 8));
     544         [ -  + ]:      71417 :         if (!p) {
     545         [ #  # ]:          0 :             VLOG_DBG_RL(&rl, "nx_match length %u, rounded up to a "
     546                 :            :                         "multiple of 8, is longer than space in message (max "
     547                 :            :                         "length %"PRIu32")", match_len, b->size);
     548                 :          0 :             return OFPERR_OFPBMC_BAD_LEN;
     549                 :            :         }
     550                 :            :     }
     551                 :            : 
     552                 :      72324 :     return nx_pull_raw(p, match_len, strict, match, cookie, cookie_mask);
     553                 :            : }
     554                 :            : 
     555                 :            : /* Parses the nx_match formatted match description in 'b' with length
     556                 :            :  * 'match_len'.  Stores the results in 'match'.  If 'cookie' and 'cookie_mask'
     557                 :            :  * are valid pointers, then stores the cookie and mask in them if 'b' contains
     558                 :            :  * a "NXM_NX_COOKIE*" match.  Otherwise, stores 0 in both.
     559                 :            :  *
     560                 :            :  * Fails with an error upon encountering an unknown NXM header.
     561                 :            :  *
     562                 :            :  * Returns 0 if successful, otherwise an OpenFlow error code. */
     563                 :            : enum ofperr
     564                 :      71925 : nx_pull_match(struct ofpbuf *b, unsigned int match_len, struct match *match,
     565                 :            :               ovs_be64 *cookie, ovs_be64 *cookie_mask)
     566                 :            : {
     567                 :      71925 :     return nx_pull_match__(b, match_len, true, match, cookie, cookie_mask);
     568                 :            : }
     569                 :            : 
     570                 :            : /* Behaves the same as nx_pull_match(), but skips over unknown NXM headers,
     571                 :            :  * instead of failing with an error. */
     572                 :            : enum ofperr
     573                 :        399 : nx_pull_match_loose(struct ofpbuf *b, unsigned int match_len,
     574                 :            :                     struct match *match,
     575                 :            :                     ovs_be64 *cookie, ovs_be64 *cookie_mask)
     576                 :            : {
     577                 :        399 :     return nx_pull_match__(b, match_len, false, match, cookie, cookie_mask);
     578                 :            : }
     579                 :            : 
     580                 :            : static enum ofperr
     581                 :      50464 : oxm_pull_match__(struct ofpbuf *b, bool strict, struct match *match)
     582                 :            : {
     583                 :      50464 :     struct ofp11_match_header *omh = b->data;
     584                 :            :     uint8_t *p;
     585                 :            :     uint16_t match_len;
     586                 :            : 
     587         [ -  + ]:      50464 :     if (b->size < sizeof *omh) {
     588                 :          0 :         return OFPERR_OFPBMC_BAD_LEN;
     589                 :            :     }
     590                 :            : 
     591                 :      50464 :     match_len = ntohs(omh->length);
     592         [ -  + ]:      50464 :     if (match_len < sizeof *omh) {
     593                 :          0 :         return OFPERR_OFPBMC_BAD_LEN;
     594                 :            :     }
     595                 :            : 
     596         [ -  + ]:      50464 :     if (omh->type != htons(OFPMT_OXM)) {
     597                 :          0 :         return OFPERR_OFPBMC_BAD_TYPE;
     598                 :            :     }
     599                 :            : 
     600                 :      50464 :     p = ofpbuf_try_pull(b, ROUND_UP(match_len, 8));
     601         [ -  + ]:      50464 :     if (!p) {
     602         [ #  # ]:          0 :         VLOG_DBG_RL(&rl, "oxm length %u, rounded up to a "
     603                 :            :                     "multiple of 8, is longer than space in message (max "
     604                 :            :                     "length %"PRIu32")", match_len, b->size);
     605                 :          0 :         return OFPERR_OFPBMC_BAD_LEN;
     606                 :            :     }
     607                 :            : 
     608                 :      50464 :     return nx_pull_raw(p + sizeof *omh, match_len - sizeof *omh,
     609                 :            :                        strict, match, NULL, NULL);
     610                 :            : }
     611                 :            : 
     612                 :            : /* Parses the oxm formatted match description preceded by a struct
     613                 :            :  * ofp11_match_header in 'b'.  Stores the result in 'match'.
     614                 :            :  *
     615                 :            :  * Fails with an error when encountering unknown OXM headers.
     616                 :            :  *
     617                 :            :  * Returns 0 if successful, otherwise an OpenFlow error code. */
     618                 :            : enum ofperr
     619                 :      50269 : oxm_pull_match(struct ofpbuf *b, struct match *match)
     620                 :            : {
     621                 :      50269 :     return oxm_pull_match__(b, true, match);
     622                 :            : }
     623                 :            : 
     624                 :            : /* Behaves the same as oxm_pull_match() with one exception.  Skips over unknown
     625                 :            :  * OXM headers instead of failing with an error when they are encountered. */
     626                 :            : enum ofperr
     627                 :        195 : oxm_pull_match_loose(struct ofpbuf *b, struct match *match)
     628                 :            : {
     629                 :        195 :     return oxm_pull_match__(b, false, match);
     630                 :            : }
     631                 :            : 
     632                 :            : /* Parses the OXM match description in the 'oxm_len' bytes in 'oxm'.  Stores
     633                 :            :  * the result in 'match'.
     634                 :            :  *
     635                 :            :  * Fails with an error when encountering unknown OXM headers.
     636                 :            :  *
     637                 :            :  * Returns 0 if successful, otherwise an OpenFlow error code. */
     638                 :            : enum ofperr
     639                 :       2124 : oxm_decode_match(const void *oxm, size_t oxm_len, struct match *match)
     640                 :            : {
     641                 :       2124 :     return nx_pull_raw(oxm, oxm_len, true, match, NULL, NULL);
     642                 :            : }
     643                 :            : 
     644                 :            : /* Verify an array of OXM TLVs treating value of each TLV as a mask,
     645                 :            :  * disallowing masks in each TLV and ignoring pre-requisites. */
     646                 :            : enum ofperr
     647                 :         22 : oxm_pull_field_array(const void *fields_data, size_t fields_len,
     648                 :            :                      struct field_array *fa)
     649                 :            : {
     650                 :         22 :     struct ofpbuf b = ofpbuf_const_initializer(fields_data, fields_len);
     651         [ +  + ]:         49 :     while (b.size) {
     652                 :         27 :         const uint8_t *pos = b.data;
     653                 :            :         const struct mf_field *field;
     654                 :            :         union mf_value value;
     655                 :            :         enum ofperr error;
     656                 :            :         uint64_t header;
     657                 :            : 
     658                 :         27 :         error = nx_pull_entry__(&b, false, &header, &field, &value, NULL);
     659         [ -  + ]:         27 :         if (error) {
     660         [ #  # ]:          0 :             VLOG_DBG_RL(&rl, "error pulling field array field");
     661                 :          0 :             return error;
     662         [ -  + ]:         27 :         } else if (!field) {
     663         [ #  # ]:          0 :             VLOG_DBG_RL(&rl, "unknown field array field");
     664                 :          0 :             error = OFPERR_OFPBMC_BAD_FIELD;
     665         [ -  + ]:         27 :         } else if (bitmap_is_set(fa->used.bm, field->id)) {
     666         [ #  # ]:          0 :             VLOG_DBG_RL(&rl, "duplicate field array field '%s'", field->name);
     667                 :          0 :             error = OFPERR_OFPBMC_DUP_FIELD;
     668         [ -  + ]:         27 :         } else if (!mf_is_mask_valid(field, &value)) {
     669         [ #  # ]:          0 :             VLOG_DBG_RL(&rl, "bad mask in field array field '%s'", field->name);
     670                 :          0 :             return OFPERR_OFPBMC_BAD_MASK;
     671                 :            :         } else {
     672                 :         27 :             field_array_set(field->id, &value, fa);
     673                 :            :         }
     674                 :            : 
     675         [ -  + ]:         27 :         if (error) {
     676                 :          0 :             const uint8_t *start = fields_data;
     677                 :            : 
     678         [ #  # ]:          0 :             VLOG_DBG_RL(&rl, "error parsing OXM at offset %"PRIdPTR" "
     679                 :            :                         "within field array (%s)", pos - start,
     680                 :            :                         ofperr_to_string(error));
     681                 :         27 :             return error;
     682                 :            :         }
     683                 :            :     }
     684                 :            : 
     685                 :         22 :     return 0;
     686                 :            : }
     687                 :            : 
     688                 :            : /* nx_put_match() and helpers.
     689                 :            :  *
     690                 :            :  * 'put' functions whose names end in 'w' add a wildcarded field.
     691                 :            :  * 'put' functions whose names end in 'm' add a field that might be wildcarded.
     692                 :            :  * Other 'put' functions add exact-match fields.
     693                 :            :  */
     694                 :            : void
     695                 :     107438 : nxm_put__(struct ofpbuf *b, enum mf_field_id field, enum ofp_version version,
     696                 :            :           const void *value, const void *mask, size_t n_bytes)
     697                 :            : {
     698                 :     107438 :     nx_put_header_len(b, field, version, !!mask, n_bytes);
     699                 :     107438 :     ofpbuf_put(b, value, n_bytes);
     700         [ +  + ]:     107438 :     if (mask) {
     701                 :      12142 :         ofpbuf_put(b, mask, n_bytes);
     702                 :            :     }
     703                 :            : 
     704                 :     107438 : }
     705                 :            : 
     706                 :            : static void
     707                 :    1931395 : nxm_put(struct ofpbuf *b, enum mf_field_id field, enum ofp_version version,
     708                 :            :         const void *value, const void *mask, size_t n_bytes)
     709                 :            : {
     710         [ +  + ]:    1931395 :     if (!is_all_zeros(mask, n_bytes)) {
     711                 :      95096 :         bool masked = !is_all_ones(mask, n_bytes);
     712         [ +  + ]:      95096 :         nxm_put__(b, field, version, value, masked ? mask : NULL, n_bytes);
     713                 :            :     }
     714                 :    1931395 : }
     715                 :            : 
     716                 :            : static void
     717                 :      65709 : nxm_put_8m(struct ofpbuf *b, enum mf_field_id field, enum ofp_version version,
     718                 :            :            uint8_t value, uint8_t mask)
     719                 :            : {
     720                 :      65709 :     nxm_put(b, field, version, &value, &mask, sizeof value);
     721                 :      65709 : }
     722                 :            : 
     723                 :            : static void
     724                 :       7997 : nxm_put_8(struct ofpbuf *b, enum mf_field_id field, enum ofp_version version,
     725                 :            :           uint8_t value)
     726                 :            : {
     727                 :       7997 :     nxm_put__(b, field, version, &value, NULL, sizeof value);
     728                 :       7997 : }
     729                 :            : 
     730                 :            : static void
     731                 :     256523 : nxm_put_16m(struct ofpbuf *b, enum mf_field_id field, enum ofp_version version,
     732                 :            :             ovs_be16 value, ovs_be16 mask)
     733                 :            : {
     734                 :     256523 :     nxm_put(b, field, version, &value, &mask, sizeof value);
     735                 :     256523 : }
     736                 :            : 
     737                 :            : static void
     738                 :       1677 : nxm_put_16(struct ofpbuf *b, enum mf_field_id field, enum ofp_version version,
     739                 :            :            ovs_be16 value)
     740                 :            : {
     741                 :       1677 :     nxm_put__(b, field, version, &value, NULL, sizeof value);
     742                 :       1677 : }
     743                 :            : 
     744                 :            : static void
     745                 :    1200161 : nxm_put_32m(struct ofpbuf *b, enum mf_field_id field, enum ofp_version version,
     746                 :            :             ovs_be32 value, ovs_be32 mask)
     747                 :            : {
     748                 :    1200161 :     nxm_put(b, field, version, &value, &mask, sizeof value);
     749                 :    1200161 : }
     750                 :            : 
     751                 :            : static void
     752                 :       2616 : nxm_put_32(struct ofpbuf *b, enum mf_field_id field, enum ofp_version version,
     753                 :            :            ovs_be32 value)
     754                 :            : {
     755                 :       2616 :     nxm_put__(b, field, version, &value, NULL, sizeof value);
     756                 :       2616 : }
     757                 :            : 
     758                 :            : static void
     759                 :     113092 : nxm_put_64m(struct ofpbuf *b, enum mf_field_id field, enum ofp_version version,
     760                 :            :             ovs_be64 value, ovs_be64 mask)
     761                 :            : {
     762                 :     113092 :     nxm_put(b, field, version, &value, &mask, sizeof value);
     763                 :     113092 : }
     764                 :            : 
     765                 :            : static void
     766                 :      56198 : nxm_put_128m(struct ofpbuf *b,
     767                 :            :              enum mf_field_id field, enum ofp_version version,
     768                 :            :              const ovs_be128 value, const ovs_be128 mask)
     769                 :            : {
     770                 :      56198 :     nxm_put(b, field, version, &value, &mask, sizeof(value));
     771                 :      56198 : }
     772                 :            : 
     773                 :            : static void
     774                 :     116282 : nxm_put_eth_masked(struct ofpbuf *b,
     775                 :            :                    enum mf_field_id field, enum ofp_version version,
     776                 :            :                    const struct eth_addr value, const struct eth_addr mask)
     777                 :            : {
     778                 :     116282 :     nxm_put(b, field, version, value.ea, mask.ea, ETH_ADDR_LEN);
     779                 :     116282 : }
     780                 :            : 
     781                 :            : static void
     782                 :     123430 : nxm_put_ipv6(struct ofpbuf *b,
     783                 :            :              enum mf_field_id field, enum ofp_version version,
     784                 :            :              const struct in6_addr *value, const struct in6_addr *mask)
     785                 :            : {
     786                 :     123430 :     nxm_put(b, field, version, value->s6_addr, mask->s6_addr,
     787                 :            :             sizeof value->s6_addr);
     788                 :     123430 : }
     789                 :            : 
     790                 :            : static void
     791                 :       9511 : nxm_put_frag(struct ofpbuf *b, const struct match *match,
     792                 :            :              enum ofp_version version)
     793                 :            : {
     794                 :       9511 :     uint8_t nw_frag = match->flow.nw_frag & FLOW_NW_FRAG_MASK;
     795                 :       9511 :     uint8_t nw_frag_mask = match->wc.masks.nw_frag & FLOW_NW_FRAG_MASK;
     796                 :            : 
     797         [ +  + ]:       9511 :     nxm_put_8m(b, MFF_IP_FRAG, version, nw_frag,
     798                 :            :                nw_frag_mask == FLOW_NW_FRAG_MASK ? UINT8_MAX : nw_frag_mask);
     799                 :       9511 : }
     800                 :            : 
     801                 :            : /* Appends to 'b' a set of OXM or NXM matches for the IPv4 or IPv6 fields in
     802                 :            :  * 'match'.  */
     803                 :            : static void
     804                 :       9511 : nxm_put_ip(struct ofpbuf *b, const struct match *match, enum ofp_version oxm)
     805                 :            : {
     806                 :       9511 :     const struct flow *flow = &match->flow;
     807                 :            : 
     808         [ +  + ]:       9511 :     if (flow->dl_type == htons(ETH_TYPE_IP)) {
     809                 :       4760 :         nxm_put_32m(b, MFF_IPV4_SRC, oxm,
     810                 :            :                     flow->nw_src, match->wc.masks.nw_src);
     811                 :       4760 :         nxm_put_32m(b, MFF_IPV4_DST, oxm,
     812                 :            :                     flow->nw_dst, match->wc.masks.nw_dst);
     813                 :            :     } else {
     814                 :       4751 :         nxm_put_ipv6(b, MFF_IPV6_SRC, oxm,
     815                 :            :                      &flow->ipv6_src, &match->wc.masks.ipv6_src);
     816                 :       4751 :         nxm_put_ipv6(b, MFF_IPV6_DST, oxm,
     817                 :            :                      &flow->ipv6_dst, &match->wc.masks.ipv6_dst);
     818                 :            :     }
     819                 :            : 
     820                 :       9511 :     nxm_put_frag(b, match, oxm);
     821                 :            : 
     822         [ +  + ]:       9511 :     if (match->wc.masks.nw_tos & IP_DSCP_MASK) {
     823         [ +  + ]:          6 :         if (oxm) {
     824                 :          3 :             nxm_put_8(b, MFF_IP_DSCP_SHIFTED, oxm,
     825                 :          3 :                       flow->nw_tos >> 2);
     826                 :            :         } else {
     827                 :          3 :             nxm_put_8(b, MFF_IP_DSCP, oxm,
     828                 :          3 :                       flow->nw_tos & IP_DSCP_MASK);
     829                 :            :         }
     830                 :            :     }
     831                 :            : 
     832         [ +  + ]:       9511 :     if (match->wc.masks.nw_tos & IP_ECN_MASK) {
     833                 :          4 :         nxm_put_8(b, MFF_IP_ECN, oxm,
     834                 :          4 :                   flow->nw_tos & IP_ECN_MASK);
     835                 :            :     }
     836                 :            : 
     837         [ +  + ]:       9511 :     if (match->wc.masks.nw_ttl) {
     838                 :       1620 :         nxm_put_8(b, MFF_IP_TTL, oxm, flow->nw_ttl);
     839                 :            :     }
     840                 :            : 
     841                 :       9511 :     nxm_put_32m(b, MFF_IPV6_LABEL, oxm,
     842                 :            :                 flow->ipv6_label, match->wc.masks.ipv6_label);
     843                 :            : 
     844         [ +  + ]:       9511 :     if (match->wc.masks.nw_proto) {
     845                 :       2569 :         nxm_put_8(b, MFF_IP_PROTO, oxm, flow->nw_proto);
     846                 :            : 
     847         [ +  + ]:       2569 :         if (flow->nw_proto == IPPROTO_TCP) {
     848                 :        324 :             nxm_put_16m(b, MFF_TCP_SRC, oxm,
     849                 :        648 :                         flow->tp_src, match->wc.masks.tp_src);
     850                 :        324 :             nxm_put_16m(b, MFF_TCP_DST, oxm,
     851                 :        648 :                         flow->tp_dst, match->wc.masks.tp_dst);
     852                 :        324 :             nxm_put_16m(b, MFF_TCP_FLAGS, oxm,
     853                 :        648 :                         flow->tcp_flags, match->wc.masks.tcp_flags);
     854         [ +  + ]:       2245 :         } else if (flow->nw_proto == IPPROTO_UDP) {
     855                 :        155 :             nxm_put_16m(b, MFF_UDP_SRC, oxm,
     856                 :        310 :                         flow->tp_src, match->wc.masks.tp_src);
     857                 :        155 :             nxm_put_16m(b, MFF_UDP_DST, oxm,
     858                 :        310 :                         flow->tp_dst, match->wc.masks.tp_dst);
     859         [ +  + ]:       2090 :         } else if (flow->nw_proto == IPPROTO_SCTP) {
     860                 :         12 :             nxm_put_16m(b, MFF_SCTP_SRC, oxm, flow->tp_src,
     861                 :         12 :                         match->wc.masks.tp_src);
     862                 :         12 :             nxm_put_16m(b, MFF_SCTP_DST, oxm, flow->tp_dst,
     863                 :         12 :                         match->wc.masks.tp_dst);
     864         [ +  + ]:       2078 :         } else if (is_icmpv4(flow, NULL)) {
     865         [ +  + ]:        255 :             if (match->wc.masks.tp_src) {
     866                 :        181 :                 nxm_put_8(b, MFF_ICMPV4_TYPE, oxm,
     867                 :        181 :                           ntohs(flow->tp_src));
     868                 :            :             }
     869         [ +  + ]:        255 :             if (match->wc.masks.tp_dst) {
     870                 :        255 :                 nxm_put_8(b, MFF_ICMPV4_CODE, oxm,
     871                 :        181 :                           ntohs(flow->tp_dst));
     872                 :            :             }
     873         [ +  + ]:       1823 :         } else if (is_icmpv6(flow, NULL)) {
     874         [ +  + ]:       1812 :             if (match->wc.masks.tp_src) {
     875                 :       1779 :                 nxm_put_8(b, MFF_ICMPV6_TYPE, oxm,
     876                 :       1779 :                           ntohs(flow->tp_src));
     877                 :            :             }
     878         [ +  + ]:       1812 :             if (match->wc.masks.tp_dst) {
     879                 :       1648 :                 nxm_put_8(b, MFF_ICMPV6_CODE, oxm,
     880                 :       1648 :                           ntohs(flow->tp_dst));
     881                 :            :             }
     882         [ +  + ]:       1812 :             if (is_nd(flow, NULL)) {
     883                 :       1532 :                 nxm_put_ipv6(b, MFF_ND_TARGET, oxm,
     884                 :            :                              &flow->nd_target, &match->wc.masks.nd_target);
     885         [ +  + ]:       1532 :                 if (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT)) {
     886                 :        981 :                     nxm_put_eth_masked(b, MFF_ND_SLL, oxm,
     887                 :            :                                        flow->arp_sha, match->wc.masks.arp_sha);
     888                 :            :                 }
     889         [ +  + ]:       1532 :                 if (flow->tp_src == htons(ND_NEIGHBOR_ADVERT)) {
     890                 :        551 :                     nxm_put_eth_masked(b, MFF_ND_TLL, oxm,
     891                 :            :                                        flow->arp_tha, match->wc.masks.arp_tha);
     892                 :            :                 }
     893                 :            :             }
     894                 :            :         }
     895                 :            :     }
     896                 :       9511 : }
     897                 :            : 
     898                 :            : /* Appends to 'b' the nx_match format that expresses 'match'.  For Flow Mod and
     899                 :            :  * Flow Stats Requests messages, a 'cookie' and 'cookie_mask' may be supplied.
     900                 :            :  * Otherwise, 'cookie_mask' should be zero.
     901                 :            :  *
     902                 :            :  * Specify 'oxm' as 0 to express the match in NXM format; otherwise, specify
     903                 :            :  * 'oxm' as the OpenFlow version number for the OXM format to use.
     904                 :            :  *
     905                 :            :  * This function can cause 'b''s data to be reallocated.
     906                 :            :  *
     907                 :            :  * Returns the number of bytes appended to 'b', excluding padding.
     908                 :            :  *
     909                 :            :  * If 'match' is a catch-all rule that matches every packet, then this function
     910                 :            :  * appends nothing to 'b' and returns 0. */
     911                 :            : static int
     912                 :      56198 : nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match,
     913                 :            :            ovs_be64 cookie, ovs_be64 cookie_mask)
     914                 :            : {
     915                 :      56198 :     const struct flow *flow = &match->flow;
     916                 :      56198 :     const size_t start_len = b->size;
     917                 :            :     int match_len;
     918                 :            :     int i;
     919                 :            : 
     920                 :            :     BUILD_ASSERT_DECL(FLOW_WC_SEQ == 36);
     921                 :            : 
     922                 :            :     /* Metadata. */
     923         [ +  + ]:      56198 :     if (match->wc.masks.dp_hash) {
     924                 :         10 :         nxm_put_32m(b, MFF_DP_HASH, oxm,
     925                 :            :                     htonl(flow->dp_hash), htonl(match->wc.masks.dp_hash));
     926                 :            :     }
     927                 :            : 
     928         [ -  + ]:      56198 :     if (match->wc.masks.recirc_id) {
     929                 :          0 :         nxm_put_32(b, MFF_RECIRC_ID, oxm, htonl(flow->recirc_id));
     930                 :            :     }
     931                 :            : 
     932         [ +  + ]:      56198 :     if (match->wc.masks.conj_id) {
     933                 :          6 :         nxm_put_32(b, MFF_CONJ_ID, oxm, htonl(flow->conj_id));
     934                 :            :     }
     935                 :            : 
     936         [ +  + ]:      56198 :     if (match->wc.masks.in_port.ofp_port) {
     937                 :       3434 :         ofp_port_t in_port = flow->in_port.ofp_port;
     938         [ +  + ]:       3434 :         if (oxm) {
     939                 :       2584 :             nxm_put_32(b, MFF_IN_PORT_OXM, oxm,
     940                 :            :                        ofputil_port_to_ofp11(in_port));
     941                 :            :         } else {
     942                 :        850 :             nxm_put_16(b, MFF_IN_PORT, oxm,
     943                 :        850 :                        htons(ofp_to_u16(in_port)));
     944                 :            :         }
     945                 :            :     }
     946         [ +  + ]:      56198 :     if (match->wc.masks.actset_output) {
     947                 :         17 :         nxm_put_32(b, MFF_ACTSET_OUTPUT, oxm,
     948                 :            :                    ofputil_port_to_ofp11(flow->actset_output));
     949                 :            :     }
     950                 :            : 
     951                 :            :     /* Ethernet. */
     952                 :      56198 :     nxm_put_eth_masked(b, MFF_ETH_SRC, oxm,
     953                 :            :                        flow->dl_src, match->wc.masks.dl_src);
     954                 :      56198 :     nxm_put_eth_masked(b, MFF_ETH_DST, oxm,
     955                 :            :                        flow->dl_dst, match->wc.masks.dl_dst);
     956                 :      56198 :     nxm_put_16m(b, MFF_ETH_TYPE, oxm,
     957                 :      56198 :                 ofputil_dl_type_to_openflow(flow->dl_type),
     958                 :      56198 :                 match->wc.masks.dl_type);
     959                 :            : 
     960                 :            :     /* 802.1Q. */
     961         [ +  + ]:      56198 :     if (oxm) {
     962                 :      26129 :         ovs_be16 VID_CFI_MASK = htons(VLAN_VID_MASK | VLAN_CFI);
     963                 :      26129 :         ovs_be16 vid = flow->vlan_tci & VID_CFI_MASK;
     964                 :      26129 :         ovs_be16 mask = match->wc.masks.vlan_tci & VID_CFI_MASK;
     965                 :            : 
     966         [ +  + ]:      26129 :         if (mask == htons(VLAN_VID_MASK | VLAN_CFI)) {
     967                 :         86 :             nxm_put_16(b, MFF_VLAN_VID, oxm, vid);
     968         [ +  + ]:      26043 :         } else if (mask) {
     969                 :        356 :             nxm_put_16m(b, MFF_VLAN_VID, oxm, vid, mask);
     970                 :            :         }
     971                 :            : 
     972 [ +  + ][ +  + ]:      26129 :         if (vid && vlan_tci_to_pcp(match->wc.masks.vlan_tci)) {
     973                 :      26129 :             nxm_put_8(b, MFF_VLAN_PCP, oxm,
     974                 :          7 :                       vlan_tci_to_pcp(flow->vlan_tci));
     975                 :            :         }
     976                 :            : 
     977                 :            :     } else {
     978                 :      30069 :         nxm_put_16m(b, MFF_VLAN_TCI, oxm, flow->vlan_tci,
     979                 :      30069 :                     match->wc.masks.vlan_tci);
     980                 :            :     }
     981                 :            : 
     982                 :            :     /* MPLS. */
     983         [ +  + ]:      56198 :     if (eth_type_mpls(flow->dl_type)) {
     984         [ +  + ]:         21 :         if (match->wc.masks.mpls_lse[0] & htonl(MPLS_TC_MASK)) {
     985                 :          1 :             nxm_put_8(b, MFF_MPLS_TC, oxm,
     986                 :          1 :                       mpls_lse_to_tc(flow->mpls_lse[0]));
     987                 :            :         }
     988                 :            : 
     989         [ +  + ]:         21 :         if (match->wc.masks.mpls_lse[0] & htonl(MPLS_BOS_MASK)) {
     990                 :          1 :             nxm_put_8(b, MFF_MPLS_BOS, oxm,
     991                 :          1 :                       mpls_lse_to_bos(flow->mpls_lse[0]));
     992                 :            :         }
     993                 :            : 
     994         [ +  + ]:         21 :         if (match->wc.masks.mpls_lse[0] & htonl(MPLS_LABEL_MASK)) {
     995                 :          9 :             nxm_put_32(b, MFF_MPLS_LABEL, oxm,
     996                 :            :                        htonl(mpls_lse_to_label(flow->mpls_lse[0])));
     997                 :            :         }
     998                 :            :     }
     999                 :            : 
    1000                 :            :     /* L3. */
    1001         [ +  + ]:      56198 :     if (is_ip_any(flow)) {
    1002                 :       9511 :         nxm_put_ip(b, match, oxm);
    1003   [ +  +  +  + ]:      92206 :     } else if (flow->dl_type == htons(ETH_TYPE_ARP) ||
    1004                 :      45519 :                flow->dl_type == htons(ETH_TYPE_RARP)) {
    1005                 :            :         /* ARP. */
    1006         [ +  + ]:       1177 :         if (match->wc.masks.nw_proto) {
    1007                 :        741 :             nxm_put_16(b, MFF_ARP_OP, oxm,
    1008                 :        741 :                        htons(flow->nw_proto));
    1009                 :            :         }
    1010                 :       1177 :         nxm_put_32m(b, MFF_ARP_SPA, oxm,
    1011                 :            :                     flow->nw_src, match->wc.masks.nw_src);
    1012                 :       1177 :         nxm_put_32m(b, MFF_ARP_TPA, oxm,
    1013                 :            :                     flow->nw_dst, match->wc.masks.nw_dst);
    1014                 :       1177 :         nxm_put_eth_masked(b, MFF_ARP_SHA, oxm,
    1015                 :            :                            flow->arp_sha, match->wc.masks.arp_sha);
    1016                 :       1177 :         nxm_put_eth_masked(b, MFF_ARP_THA, oxm,
    1017                 :            :                            flow->arp_tha, match->wc.masks.arp_tha);
    1018                 :            :     }
    1019                 :            : 
    1020                 :            :     /* Tunnel ID. */
    1021                 :      56198 :     nxm_put_64m(b, MFF_TUN_ID, oxm,
    1022                 :            :                 flow->tunnel.tun_id, match->wc.masks.tunnel.tun_id);
    1023                 :            : 
    1024                 :            :     /* Other tunnel metadata. */
    1025                 :      56198 :     nxm_put_16m(b, MFF_TUN_FLAGS, oxm,
    1026                 :      56198 :                 htons(flow->tunnel.flags), htons(match->wc.masks.tunnel.flags));
    1027                 :      56198 :     nxm_put_32m(b, MFF_TUN_SRC, oxm,
    1028                 :            :                 flow->tunnel.ip_src, match->wc.masks.tunnel.ip_src);
    1029                 :      56198 :     nxm_put_32m(b, MFF_TUN_DST, oxm,
    1030                 :            :                 flow->tunnel.ip_dst, match->wc.masks.tunnel.ip_dst);
    1031                 :      56198 :     nxm_put_ipv6(b, MFF_TUN_IPV6_SRC, oxm,
    1032                 :            :                  &flow->tunnel.ipv6_src, &match->wc.masks.tunnel.ipv6_src);
    1033                 :      56198 :     nxm_put_ipv6(b, MFF_TUN_IPV6_DST, oxm,
    1034                 :            :                  &flow->tunnel.ipv6_dst, &match->wc.masks.tunnel.ipv6_dst);
    1035                 :      56198 :     nxm_put_16m(b, MFF_TUN_GBP_ID, oxm,
    1036                 :     112396 :                 flow->tunnel.gbp_id, match->wc.masks.tunnel.gbp_id);
    1037                 :      56198 :     nxm_put_8m(b, MFF_TUN_GBP_FLAGS, oxm,
    1038                 :     112396 :                flow->tunnel.gbp_flags, match->wc.masks.tunnel.gbp_flags);
    1039                 :      56198 :     tun_metadata_to_nx_match(b, oxm, match);
    1040                 :            : 
    1041                 :            :     /* Registers. */
    1042         [ +  + ]:      56198 :     if (oxm < OFP15_VERSION) {
    1043         [ +  + ]:     953887 :         for (i = 0; i < FLOW_N_REGS; i++) {
    1044                 :     897776 :             nxm_put_32m(b, MFF_REG0 + i, oxm,
    1045                 :            :                         htonl(flow->regs[i]), htonl(match->wc.masks.regs[i]));
    1046                 :            :         }
    1047                 :            :     } else {
    1048         [ +  + ]:        783 :         for (i = 0; i < FLOW_N_XREGS; i++) {
    1049                 :        696 :             nxm_put_64m(b, MFF_XREG0 + i, oxm,
    1050                 :            :                         htonll(flow_get_xreg(flow, i)),
    1051                 :            :                         htonll(flow_get_xreg(&match->wc.masks, i)));
    1052                 :            :         }
    1053                 :            :     }
    1054                 :            : 
    1055                 :            :     /* Packet mark. */
    1056                 :      56198 :     nxm_put_32m(b, MFF_PKT_MARK, oxm, htonl(flow->pkt_mark),
    1057                 :            :                 htonl(match->wc.masks.pkt_mark));
    1058                 :            : 
    1059                 :            :     /* Connection tracking. */
    1060                 :      56198 :     nxm_put_32m(b, MFF_CT_STATE, oxm, htonl(flow->ct_state),
    1061                 :      56198 :                 htonl(match->wc.masks.ct_state));
    1062                 :      56198 :     nxm_put_16m(b, MFF_CT_ZONE, oxm, htons(flow->ct_zone),
    1063                 :      56198 :                 htons(match->wc.masks.ct_zone));
    1064                 :      56198 :     nxm_put_32m(b, MFF_CT_MARK, oxm, htonl(flow->ct_mark),
    1065                 :            :                 htonl(match->wc.masks.ct_mark));
    1066                 :      56198 :     nxm_put_128m(b, MFF_CT_LABEL, oxm, hton128(flow->ct_label),
    1067                 :            :                  hton128(match->wc.masks.ct_label));
    1068                 :            : 
    1069                 :            :     /* OpenFlow 1.1+ Metadata. */
    1070                 :      56198 :     nxm_put_64m(b, MFF_METADATA, oxm,
    1071                 :            :                 flow->metadata, match->wc.masks.metadata);
    1072                 :            : 
    1073                 :            :     /* Cookie. */
    1074         [ +  + ]:      56198 :     if (cookie_mask) {
    1075                 :         22 :         bool masked = cookie_mask != OVS_BE64_MAX;
    1076                 :            : 
    1077                 :         22 :         cookie &= cookie_mask;
    1078                 :         22 :         nx_put_header__(b, NXM_NX_COOKIE, masked);
    1079                 :         22 :         ofpbuf_put(b, &cookie, sizeof cookie);
    1080         [ +  + ]:         22 :         if (masked) {
    1081                 :          4 :             ofpbuf_put(b, &cookie_mask, sizeof cookie_mask);
    1082                 :            :         }
    1083                 :            :     }
    1084                 :            : 
    1085                 :      56198 :     match_len = b->size - start_len;
    1086                 :      56198 :     return match_len;
    1087                 :            : }
    1088                 :            : 
    1089                 :            : /* Appends to 'b' the nx_match format that expresses 'match', plus enough zero
    1090                 :            :  * bytes to pad the nx_match out to a multiple of 8.  For Flow Mod and Flow
    1091                 :            :  * Stats Requests messages, a 'cookie' and 'cookie_mask' may be supplied.
    1092                 :            :  * Otherwise, 'cookie_mask' should be zero.
    1093                 :            :  *
    1094                 :            :  * This function can cause 'b''s data to be reallocated.
    1095                 :            :  *
    1096                 :            :  * Returns the number of bytes appended to 'b', excluding padding.  The return
    1097                 :            :  * value can be zero if it appended nothing at all to 'b' (which happens if
    1098                 :            :  * 'cr' is a catch-all rule that matches every packet). */
    1099                 :            : int
    1100                 :      30069 : nx_put_match(struct ofpbuf *b, const struct match *match,
    1101                 :            :              ovs_be64 cookie, ovs_be64 cookie_mask)
    1102                 :            : {
    1103                 :      30069 :     int match_len = nx_put_raw(b, 0, match, cookie, cookie_mask);
    1104                 :            : 
    1105                 :      30069 :     ofpbuf_put_zeros(b, PAD_SIZE(match_len, 8));
    1106                 :      30069 :     return match_len;
    1107                 :            : }
    1108                 :            : 
    1109                 :            : /* Appends to 'b' an struct ofp11_match_header followed by the OXM format that
    1110                 :            :  * expresses 'match', plus enough zero bytes to pad the data appended out to a
    1111                 :            :  * multiple of 8.
    1112                 :            :  *
    1113                 :            :  * OXM differs slightly among versions of OpenFlow.  Specify the OpenFlow
    1114                 :            :  * version in use as 'version'.
    1115                 :            :  *
    1116                 :            :  * This function can cause 'b''s data to be reallocated.
    1117                 :            :  *
    1118                 :            :  * Returns the number of bytes appended to 'b', excluding the padding.  Never
    1119                 :            :  * returns zero. */
    1120                 :            : int
    1121                 :      25262 : oxm_put_match(struct ofpbuf *b, const struct match *match,
    1122                 :            :               enum ofp_version version)
    1123                 :            : {
    1124                 :            :     int match_len;
    1125                 :            :     struct ofp11_match_header *omh;
    1126                 :      25262 :     size_t start_len = b->size;
    1127                 :      25262 :     ovs_be64 cookie = htonll(0), cookie_mask = htonll(0);
    1128                 :            : 
    1129                 :      25262 :     ofpbuf_put_uninit(b, sizeof *omh);
    1130                 :      25262 :     match_len = (nx_put_raw(b, version, match, cookie, cookie_mask)
    1131                 :            :                  + sizeof *omh);
    1132                 :      25262 :     ofpbuf_put_zeros(b, PAD_SIZE(match_len, 8));
    1133                 :            : 
    1134                 :      25262 :     omh = ofpbuf_at(b, start_len, sizeof *omh);
    1135                 :      25262 :     omh->type = htons(OFPMT_OXM);
    1136                 :      25262 :     omh->length = htons(match_len);
    1137                 :            : 
    1138                 :      25262 :     return match_len;
    1139                 :            : }
    1140                 :            : 
    1141                 :            : /* Appends to 'b' the OXM formats that expresses 'match', without header or
    1142                 :            :  * padding.
    1143                 :            :  *
    1144                 :            :  * OXM differs slightly among versions of OpenFlow.  Specify the OpenFlow
    1145                 :            :  * version in use as 'version'.
    1146                 :            :  *
    1147                 :            :  * This function can cause 'b''s data to be reallocated. */
    1148                 :            : void
    1149                 :        867 : oxm_put_raw(struct ofpbuf *b, const struct match *match,
    1150                 :            :             enum ofp_version version)
    1151                 :            : {
    1152                 :        867 :     nx_put_raw(b, version, match, 0, 0);
    1153                 :        867 : }
    1154                 :            : 
    1155                 :            : /* Appends to 'b' the nx_match format that expresses the tlv corresponding
    1156                 :            :  * to 'id'. If mask is not all-ones then it is also formated as the value
    1157                 :            :  * of the tlv. */
    1158                 :            : static void
    1159                 :         21 : nx_format_mask_tlv(struct ds *ds, enum mf_field_id id,
    1160                 :            :                    const union mf_value *mask)
    1161                 :            : {
    1162                 :         21 :     const struct mf_field *mf = mf_from_id(id);
    1163                 :            : 
    1164                 :         21 :     ds_put_format(ds, "%s", mf->name);
    1165                 :            : 
    1166         [ +  + ]:         21 :     if (!is_all_ones(mask, mf->n_bytes)) {
    1167                 :          1 :         ds_put_char(ds, '=');
    1168                 :          1 :         mf_format(mf, mask, NULL, ds);
    1169                 :            :     }
    1170                 :            : 
    1171                 :         21 :     ds_put_char(ds, ',');
    1172                 :         21 : }
    1173                 :            : 
    1174                 :            : /* Appends a string representation of 'fa_' to 'ds'.
    1175                 :            :  * The TLVS value of 'fa_' is treated as a mask and
    1176                 :            :  * only the name of fields is formated if it is all ones. */
    1177                 :            : void
    1178                 :          7 : oxm_format_field_array(struct ds *ds, const struct field_array *fa)
    1179                 :            : {
    1180                 :          7 :     size_t start_len = ds->length;
    1181                 :          7 :     size_t i, offset = 0;
    1182                 :            : 
    1183         [ +  + ]:         28 :     BITMAP_FOR_EACH_1 (i, MFF_N_IDS, fa->used.bm) {
    1184                 :         21 :         const struct mf_field *mf = mf_from_id(i);
    1185                 :            :         union mf_value value;
    1186                 :            : 
    1187                 :         21 :         memcpy(&value, fa->values + offset, mf->n_bytes);
    1188                 :         21 :         nx_format_mask_tlv(ds, i, &value);
    1189                 :         21 :         offset += mf->n_bytes;
    1190                 :            :     }
    1191                 :            : 
    1192         [ +  - ]:          7 :     if (ds->length > start_len) {
    1193                 :          7 :         ds_chomp(ds, ',');
    1194                 :            :     }
    1195                 :          7 : }
    1196                 :            : 
    1197                 :            : /* Appends to 'b' a series of OXM TLVs corresponding to the series
    1198                 :            :  * of enum mf_field_id and value tuples in 'fa_'.
    1199                 :            :  *
    1200                 :            :  * OXM differs slightly among versions of OpenFlow.  Specify the OpenFlow
    1201                 :            :  * version in use as 'version'.
    1202                 :            :  *
    1203                 :            :  * This function can cause 'b''s data to be reallocated.
    1204                 :            :  *
    1205                 :            :  * Returns the number of bytes appended to 'b'.  May return zero. */
    1206                 :            : int
    1207                 :         11 : oxm_put_field_array(struct ofpbuf *b, const struct field_array *fa,
    1208                 :            :                     enum ofp_version version)
    1209                 :            : {
    1210                 :         11 :     size_t start_len = b->size;
    1211                 :            : 
    1212                 :            :     /* Field arrays are only used with the group selection method
    1213                 :            :      * property and group properties are only available in OpenFlow 1.5+.
    1214                 :            :      * So the following assertion should never fail.
    1215                 :            :      *
    1216                 :            :      * If support for older OpenFlow versions is desired then some care
    1217                 :            :      * will need to be taken of different TLVs that handle the same
    1218                 :            :      * flow fields. In particular:
    1219                 :            :      * - VLAN_TCI, VLAN_VID and MFF_VLAN_PCP
    1220                 :            :      * - IP_DSCP_MASK and DSCP_SHIFTED
    1221                 :            :      * - REGS and XREGS
    1222                 :            :      */
    1223         [ -  + ]:         11 :     ovs_assert(version >= OFP15_VERSION);
    1224                 :            : 
    1225                 :         11 :     size_t i, offset = 0;
    1226                 :            : 
    1227         [ +  + ]:         26 :     BITMAP_FOR_EACH_1 (i, MFF_N_IDS, fa->used.bm) {
    1228                 :         15 :         const struct mf_field *mf = mf_from_id(i);
    1229                 :            :         union mf_value value;
    1230                 :            : 
    1231                 :         15 :         memcpy(&value, fa->values + offset, mf->n_bytes);
    1232                 :            : 
    1233                 :         15 :         int len = mf_field_len(mf, &value, NULL, NULL);
    1234                 :         15 :         nxm_put__(b, i, version, &value + mf->n_bytes - len, NULL, len);
    1235                 :         15 :         offset += mf->n_bytes;
    1236                 :            :     }
    1237                 :            : 
    1238                 :         11 :     return b->size - start_len;
    1239                 :            : }
    1240                 :            : 
    1241                 :            : static void
    1242                 :     669715 : nx_put_header__(struct ofpbuf *b, uint64_t header, bool masked)
    1243                 :            : {
    1244         [ +  + ]:     669715 :     uint64_t masked_header = masked ? nxm_make_wild_header(header) : header;
    1245                 :     669715 :     ovs_be64 network_header = htonll(masked_header);
    1246                 :            : 
    1247                 :     669715 :     ofpbuf_put(b, &network_header, nxm_header_len(header));
    1248                 :     669715 : }
    1249                 :            : 
    1250                 :            : void
    1251                 :     492424 : nx_put_header(struct ofpbuf *b, enum mf_field_id field,
    1252                 :            :               enum ofp_version version, bool masked)
    1253                 :            : {
    1254                 :     492424 :     nx_put_header__(b, mf_oxm_header(field, version), masked);
    1255                 :     492424 : }
    1256                 :            : 
    1257                 :            : static void
    1258                 :     177269 : nx_put_header_len(struct ofpbuf *b, enum mf_field_id field,
    1259                 :            :                   enum ofp_version version, bool masked, size_t n_bytes)
    1260                 :            : {
    1261                 :     177269 :     uint64_t header = mf_oxm_header(field, version);
    1262                 :            : 
    1263                 :     177269 :     header = NXM_HEADER(nxm_vendor(header), nxm_class(header),
    1264                 :            :                         nxm_field(header), false,
    1265                 :            :                         nxm_experimenter_len(header) + n_bytes);
    1266                 :            : 
    1267                 :     177269 :     nx_put_header__(b, header, masked);
    1268                 :     177269 : }
    1269                 :            : 
    1270                 :            : void
    1271                 :      69831 : nx_put_entry(struct ofpbuf *b,
    1272                 :            :              enum mf_field_id field, enum ofp_version version,
    1273                 :            :              const union mf_value *value, const union mf_value *mask)
    1274                 :            : {
    1275                 :      69831 :     const struct mf_field *mf = mf_from_id(field);
    1276                 :            :     bool masked;
    1277                 :            :     int len, offset;
    1278                 :            : 
    1279                 :      69831 :     len = mf_field_len(mf, value, mask, &masked);
    1280                 :      69831 :     offset = mf->n_bytes - len;
    1281                 :            : 
    1282                 :      69831 :     nx_put_header_len(b, field, version, masked, len);
    1283                 :      69831 :     ofpbuf_put(b, &value->u8 + offset, len);
    1284         [ +  + ]:      69831 :     if (masked) {
    1285                 :        330 :         ofpbuf_put(b, &mask->u8 + offset, len);
    1286                 :            :     }
    1287                 :      69831 : }
    1288                 :            : 
    1289                 :            : /* nx_match_to_string() and helpers. */
    1290                 :            : 
    1291                 :            : static void format_nxm_field_name(struct ds *, uint64_t header);
    1292                 :            : 
    1293                 :            : char *
    1294                 :        336 : nx_match_to_string(const uint8_t *p, unsigned int match_len)
    1295                 :            : {
    1296         [ +  + ]:        336 :     if (!match_len) {
    1297                 :         15 :         return xstrdup("<any>");
    1298                 :            :     }
    1299                 :            : 
    1300                 :        321 :     struct ofpbuf b = ofpbuf_const_initializer(p, match_len);
    1301                 :        321 :     struct ds s = DS_EMPTY_INITIALIZER;
    1302         [ +  + ]:        928 :     while (b.size) {
    1303                 :            :         union mf_value value;
    1304                 :            :         union mf_value mask;
    1305                 :            :         enum ofperr error;
    1306                 :            :         uint64_t header;
    1307                 :            :         int value_len;
    1308                 :            : 
    1309                 :        607 :         error = nx_pull_entry__(&b, true, &header, NULL, &value, &mask);
    1310         [ -  + ]:        607 :         if (error) {
    1311                 :          0 :             break;
    1312                 :            :         }
    1313         [ +  - ]:        607 :         value_len = MIN(sizeof value, nxm_field_bytes(header));
    1314                 :            : 
    1315         [ +  + ]:        607 :         if (s.length) {
    1316                 :        286 :             ds_put_cstr(&s, ", ");
    1317                 :            :         }
    1318                 :            : 
    1319                 :        607 :         format_nxm_field_name(&s, header);
    1320                 :        607 :         ds_put_char(&s, '(');
    1321                 :            : 
    1322         [ +  + ]:       2619 :         for (int i = 0; i < value_len; i++) {
    1323                 :       2012 :             ds_put_format(&s, "%02x", ((const uint8_t *) &value)[i]);
    1324                 :            :         }
    1325         [ +  + ]:        607 :         if (nxm_hasmask(header)) {
    1326                 :        113 :             ds_put_char(&s, '/');
    1327         [ +  + ]:        649 :             for (int i = 0; i < value_len; i++) {
    1328                 :        536 :                 ds_put_format(&s, "%02x", ((const uint8_t *) &mask)[i]);
    1329                 :            :             }
    1330                 :            :         }
    1331                 :        607 :         ds_put_char(&s, ')');
    1332                 :            :     }
    1333                 :            : 
    1334         [ -  + ]:        321 :     if (b.size) {
    1335         [ #  # ]:          0 :         if (s.length) {
    1336                 :          0 :             ds_put_cstr(&s, ", ");
    1337                 :            :         }
    1338                 :            : 
    1339                 :          0 :         ds_put_format(&s, "<%u invalid bytes>", b.size);
    1340                 :            :     }
    1341                 :            : 
    1342                 :        336 :     return ds_steal_cstr(&s);
    1343                 :            : }
    1344                 :            : 
    1345                 :            : char *
    1346                 :        168 : oxm_match_to_string(const struct ofpbuf *p, unsigned int match_len)
    1347                 :            : {
    1348                 :        168 :     const struct ofp11_match_header *omh = p->data;
    1349                 :            :     uint16_t match_len_;
    1350                 :            :     struct ds s;
    1351                 :            : 
    1352                 :        168 :     ds_init(&s);
    1353                 :            : 
    1354         [ -  + ]:        168 :     if (match_len < sizeof *omh) {
    1355                 :          0 :         ds_put_format(&s, "<match too short: %u>", match_len);
    1356                 :          0 :         goto err;
    1357                 :            :     }
    1358                 :            : 
    1359         [ -  + ]:        168 :     if (omh->type != htons(OFPMT_OXM)) {
    1360                 :          0 :         ds_put_format(&s, "<bad match type field: %u>", ntohs(omh->type));
    1361                 :          0 :         goto err;
    1362                 :            :     }
    1363                 :            : 
    1364                 :        168 :     match_len_ = ntohs(omh->length);
    1365         [ -  + ]:        168 :     if (match_len_ < sizeof *omh) {
    1366                 :          0 :         ds_put_format(&s, "<match length field too short: %u>", match_len_);
    1367                 :          0 :         goto err;
    1368                 :            :     }
    1369                 :            : 
    1370         [ -  + ]:        168 :     if (match_len_ != match_len) {
    1371                 :          0 :         ds_put_format(&s, "<match length field incorrect: %u != %u>",
    1372                 :            :                       match_len_, match_len);
    1373                 :          0 :         goto err;
    1374                 :            :     }
    1375                 :            : 
    1376                 :        168 :     return nx_match_to_string(ofpbuf_at(p, sizeof *omh, 0),
    1377                 :            :                               match_len - sizeof *omh);
    1378                 :            : 
    1379                 :            : err:
    1380                 :        168 :     return ds_steal_cstr(&s);
    1381                 :            : }
    1382                 :            : 
    1383                 :            : void
    1384                 :         94 : nx_format_field_name(enum mf_field_id id, enum ofp_version version,
    1385                 :            :                      struct ds *s)
    1386                 :            : {
    1387                 :         94 :     format_nxm_field_name(s, mf_oxm_header(id, version));
    1388                 :         94 : }
    1389                 :            : 
    1390                 :            : static void
    1391                 :        701 : format_nxm_field_name(struct ds *s, uint64_t header)
    1392                 :            : {
    1393                 :        701 :     const struct nxm_field *f = nxm_field_by_header(header);
    1394         [ +  + ]:        701 :     if (f) {
    1395                 :        698 :         ds_put_cstr(s, f->name);
    1396         [ +  + ]:        698 :         if (nxm_hasmask(header)) {
    1397                 :        698 :             ds_put_cstr(s, "_W");
    1398                 :            :         }
    1399         [ +  + ]:          3 :     } else if (header == NXM_NX_COOKIE) {
    1400                 :          2 :         ds_put_cstr(s, "NXM_NX_COOKIE");
    1401         [ +  - ]:          1 :     } else if (header == NXM_NX_COOKIE_W) {
    1402                 :          1 :         ds_put_cstr(s, "NXM_NX_COOKIE_W");
    1403                 :            :     } else {
    1404                 :          0 :         ds_put_format(s, "%d:%d", nxm_class(header), nxm_field(header));
    1405                 :            :     }
    1406                 :        701 : }
    1407                 :            : 
    1408                 :            : static bool
    1409                 :         43 : streq_len(const char *a, size_t a_len, const char *b)
    1410                 :            : {
    1411 [ +  + ][ +  - ]:         43 :     return strlen(b) == a_len && !memcmp(a, b, a_len);
    1412                 :            : }
    1413                 :            : 
    1414                 :            : static uint64_t
    1415                 :        849 : parse_nxm_field_name(const char *name, int name_len)
    1416                 :            : {
    1417                 :            :     const struct nxm_field *f;
    1418                 :            :     bool wild;
    1419                 :            : 
    1420                 :        849 :     f = mf_parse_subfield_name(name, name_len, &wild);
    1421         [ +  + ]:        849 :     if (f) {
    1422         [ +  + ]:        827 :         if (!wild) {
    1423                 :        627 :             return f->header;
    1424         [ +  - ]:        200 :         } else if (mf_from_id(f->id)->maskable != MFM_NONE) {
    1425                 :        200 :             return nxm_make_wild_header(f->header);
    1426                 :            :         }
    1427                 :            :     }
    1428                 :            : 
    1429         [ +  + ]:         22 :     if (streq_len(name, name_len, "NXM_NX_COOKIE")) {
    1430                 :          1 :         return NXM_NX_COOKIE;
    1431         [ +  + ]:         21 :     } else if (streq_len(name, name_len, "NXM_NX_COOKIE_W")) {
    1432                 :          3 :         return NXM_NX_COOKIE_W;
    1433                 :            :     }
    1434                 :            : 
    1435                 :            :     /* Check whether it's a field header value as hex.
    1436                 :            :      * (This isn't ordinarily useful except for testing error behavior.) */
    1437         [ +  + ]:         18 :     if (name_len == 8) {
    1438                 :            :         uint64_t header;
    1439                 :            :         bool ok;
    1440                 :            : 
    1441                 :          6 :         header = hexits_value(name, name_len, &ok) << 32;
    1442         [ +  - ]:          6 :         if (ok) {
    1443                 :          6 :             return header;
    1444                 :            :         }
    1445         [ +  - ]:         12 :     } else if (name_len == 16) {
    1446                 :            :         uint64_t header;
    1447                 :            :         bool ok;
    1448                 :            : 
    1449                 :         12 :         header = hexits_value(name, name_len, &ok);
    1450 [ +  - ][ +  - ]:         12 :         if (ok && is_experimenter_oxm(header)) {
    1451                 :         12 :             return header;
    1452                 :            :         }
    1453                 :            :     }
    1454                 :            : 
    1455                 :        849 :     return 0;
    1456                 :            : }
    1457                 :            : 
    1458                 :            : /* nx_match_from_string(). */
    1459                 :            : 
    1460                 :            : static int
    1461                 :        429 : nx_match_from_string_raw(const char *s, struct ofpbuf *b)
    1462                 :            : {
    1463                 :        429 :     const char *full_s = s;
    1464                 :        429 :     const size_t start_len = b->size;
    1465                 :            : 
    1466         [ +  + ]:        429 :     if (!strcmp(s, "<any>")) {
    1467                 :            :         /* Ensure that 'b->data' isn't actually null. */
    1468                 :          2 :         ofpbuf_prealloc_tailroom(b, 1);
    1469                 :          2 :         return 0;
    1470                 :            :     }
    1471                 :            : 
    1472         [ +  + ]:       1276 :     for (s += strspn(s, ", "); *s; s += strspn(s, ", ")) {
    1473                 :            :         const char *name;
    1474                 :            :         uint64_t header;
    1475                 :            :         ovs_be64 nw_header;
    1476                 :            :         int name_len;
    1477                 :            :         size_t n;
    1478                 :            : 
    1479                 :        849 :         name = s;
    1480                 :        849 :         name_len = strcspn(s, "(");
    1481         [ -  + ]:        849 :         if (s[name_len] != '(') {
    1482                 :          0 :             ovs_fatal(0, "%s: missing ( at end of nx_match", full_s);
    1483                 :            :         }
    1484                 :            : 
    1485                 :        849 :         header = parse_nxm_field_name(name, name_len);
    1486         [ -  + ]:        849 :         if (!header) {
    1487                 :          0 :             ovs_fatal(0, "%s: unknown field `%.*s'", full_s, name_len, s);
    1488                 :            :         }
    1489                 :            : 
    1490                 :        849 :         s += name_len + 1;
    1491                 :            : 
    1492                 :        849 :         b->header = ofpbuf_put_uninit(b, nxm_header_len(header));
    1493                 :        849 :         s = ofpbuf_put_hex(b, s, &n);
    1494         [ -  + ]:        849 :         if (n != nxm_field_bytes(header)) {
    1495                 :          0 :             const struct mf_field *field = mf_from_oxm_header(header);
    1496                 :            : 
    1497 [ #  # ][ #  # ]:          0 :             if (field && field->variable_len) {
    1498         [ #  # ]:          0 :                 if (n <= field->n_bytes) {
    1499         [ #  # ]:          0 :                     int len = (nxm_hasmask(header) ? n * 2 : n) +
    1500                 :          0 :                               nxm_experimenter_len(header);
    1501                 :            : 
    1502         [ #  # ]:          0 :                     header = NXM_HEADER(nxm_vendor(header), nxm_class(header),
    1503                 :            :                                         nxm_field(header),
    1504                 :            :                                         nxm_hasmask(header) ? 1 : 0, len);
    1505                 :            :                 } else {
    1506                 :          0 :                     ovs_fatal(0, "expected to read at most %d bytes but got "
    1507                 :            :                               "%"PRIuSIZE, field->n_bytes, n);
    1508                 :            :                 }
    1509                 :            :             } else {
    1510                 :          0 :                 ovs_fatal(0, "expected to read %d bytes but got %"PRIuSIZE,
    1511                 :            :                           nxm_field_bytes(header), n);
    1512                 :            :             }
    1513                 :            :         }
    1514                 :        849 :         nw_header = htonll(header);
    1515                 :        849 :         memcpy(b->header, &nw_header, nxm_header_len(header));
    1516                 :            : 
    1517         [ +  + ]:        849 :         if (nxm_hasmask(header)) {
    1518                 :        215 :             s += strspn(s, " ");
    1519         [ -  + ]:        215 :             if (*s != '/') {
    1520                 :          0 :                 ovs_fatal(0, "%s: missing / in masked field %.*s",
    1521                 :            :                           full_s, name_len, name);
    1522                 :            :             }
    1523                 :        215 :             s = ofpbuf_put_hex(b, s + 1, &n);
    1524         [ -  + ]:        215 :             if (n != nxm_field_bytes(header)) {
    1525                 :          0 :                 ovs_fatal(0, "%.2s: hex digits expected", s);
    1526                 :            :             }
    1527                 :            :         }
    1528                 :            : 
    1529                 :        849 :         s += strspn(s, " ");
    1530         [ -  + ]:        849 :         if (*s != ')') {
    1531                 :          0 :             ovs_fatal(0, "%s: missing ) following field %.*s",
    1532                 :            :                       full_s, name_len, name);
    1533                 :            :         }
    1534                 :        849 :         s++;
    1535                 :            :     }
    1536                 :            : 
    1537                 :        427 :     return b->size - start_len;
    1538                 :            : }
    1539                 :            : 
    1540                 :            : int
    1541                 :        212 : nx_match_from_string(const char *s, struct ofpbuf *b)
    1542                 :            : {
    1543                 :        212 :     int match_len = nx_match_from_string_raw(s, b);
    1544                 :        212 :     ofpbuf_put_zeros(b, PAD_SIZE(match_len, 8));
    1545                 :        212 :     return match_len;
    1546                 :            : }
    1547                 :            : 
    1548                 :            : int
    1549                 :        217 : oxm_match_from_string(const char *s, struct ofpbuf *b)
    1550                 :            : {
    1551                 :            :     int match_len;
    1552                 :            :     struct ofp11_match_header *omh;
    1553                 :        217 :     size_t start_len = b->size;
    1554                 :            : 
    1555                 :        217 :     ofpbuf_put_uninit(b, sizeof *omh);
    1556                 :        217 :     match_len = nx_match_from_string_raw(s, b) + sizeof *omh;
    1557                 :        217 :     ofpbuf_put_zeros(b, PAD_SIZE(match_len, 8));
    1558                 :            : 
    1559                 :        217 :     omh = ofpbuf_at(b, start_len, sizeof *omh);
    1560                 :        217 :     omh->type = htons(OFPMT_OXM);
    1561                 :        217 :     omh->length = htons(match_len);
    1562                 :            : 
    1563                 :        217 :     return match_len;
    1564                 :            : }
    1565                 :            : 
    1566                 :            : /* Parses 's' as a "move" action, in the form described in ovs-ofctl(8), into
    1567                 :            :  * '*move'.
    1568                 :            :  *
    1569                 :            :  * Returns NULL if successful, otherwise a malloc()'d string describing the
    1570                 :            :  * error.  The caller is responsible for freeing the returned string. */
    1571                 :            : char * OVS_WARN_UNUSED_RESULT
    1572                 :          5 : nxm_parse_reg_move(struct ofpact_reg_move *move, const char *s)
    1573                 :            : {
    1574                 :          5 :     const char *full_s = s;
    1575                 :            :     char *error;
    1576                 :            : 
    1577                 :          5 :     error = mf_parse_subfield__(&move->src, &s);
    1578         [ -  + ]:          5 :     if (error) {
    1579                 :          0 :         return error;
    1580                 :            :     }
    1581         [ -  + ]:          5 :     if (strncmp(s, "->", 2)) {
    1582                 :          0 :         return xasprintf("%s: missing `->' following source", full_s);
    1583                 :            :     }
    1584                 :          5 :     s += 2;
    1585                 :          5 :     error = mf_parse_subfield(&move->dst, s);
    1586         [ -  + ]:          5 :     if (error) {
    1587                 :          0 :         return error;
    1588                 :            :     }
    1589                 :            : 
    1590         [ -  + ]:          5 :     if (move->src.n_bits != move->dst.n_bits) {
    1591                 :          0 :         return xasprintf("%s: source field is %d bits wide but destination is "
    1592                 :            :                          "%d bits wide", full_s,
    1593                 :            :                          move->src.n_bits, move->dst.n_bits);
    1594                 :            :     }
    1595                 :          5 :     return NULL;
    1596                 :            : }
    1597                 :            : 
    1598                 :            : /* nxm_format_reg_move(). */
    1599                 :            : 
    1600                 :            : void
    1601                 :       4726 : nxm_format_reg_move(const struct ofpact_reg_move *move, struct ds *s)
    1602                 :            : {
    1603                 :       4726 :     ds_put_format(s, "%smove:%s", colors.special, colors.end);
    1604                 :       4726 :     mf_format_subfield(&move->src, s);
    1605                 :       4726 :     ds_put_format(s, "%s->%s", colors.special, colors.end);
    1606                 :       4726 :     mf_format_subfield(&move->dst, s);
    1607                 :       4726 : }
    1608                 :            : 
    1609                 :            : 
    1610                 :            : enum ofperr
    1611                 :      11871 : nxm_reg_move_check(const struct ofpact_reg_move *move, const struct flow *flow)
    1612                 :            : {
    1613                 :            :     enum ofperr error;
    1614                 :            : 
    1615                 :      11871 :     error = mf_check_src(&move->src, flow);
    1616         [ +  + ]:      11871 :     if (error) {
    1617                 :          1 :         return error;
    1618                 :            :     }
    1619                 :            : 
    1620                 :      11870 :     return mf_check_dst(&move->dst, flow);
    1621                 :            : }
    1622                 :            : 
    1623                 :            : /* nxm_execute_reg_move(). */
    1624                 :            : 
    1625                 :            : void
    1626                 :   33030152 : nxm_reg_load(const struct mf_subfield *dst, uint64_t src_data,
    1627                 :            :              struct flow *flow, struct flow_wildcards *wc)
    1628                 :            : {
    1629                 :            :     union mf_subvalue src_subvalue;
    1630                 :            :     union mf_subvalue mask_value;
    1631                 :   33030152 :     ovs_be64 src_data_be = htonll(src_data);
    1632                 :            : 
    1633                 :   33030152 :     memset(&mask_value, 0xff, sizeof mask_value);
    1634                 :   33030152 :     mf_write_subfield_flow(dst, &mask_value, &wc->masks);
    1635                 :            : 
    1636                 :   33030152 :     bitwise_copy(&src_data_be, sizeof src_data_be, 0,
    1637                 :            :                  &src_subvalue, sizeof src_subvalue, 0,
    1638                 :            :                  sizeof src_data_be * 8);
    1639                 :   33030152 :     mf_write_subfield_flow(dst, &src_subvalue, flow);
    1640                 :   33030152 : }
    1641                 :            : 
    1642                 :            : /* nxm_parse_stack_action, works for both push() and pop(). */
    1643                 :            : 
    1644                 :            : /* Parses 's' as a "push" or "pop" action, in the form described in
    1645                 :            :  * ovs-ofctl(8), into '*stack_action'.
    1646                 :            :  *
    1647                 :            :  * Returns NULL if successful, otherwise a malloc()'d string describing the
    1648                 :            :  * error.  The caller is responsible for freeing the returned string. */
    1649                 :            : char * OVS_WARN_UNUSED_RESULT
    1650                 :         43 : nxm_parse_stack_action(struct ofpact_stack *stack_action, const char *s)
    1651                 :            : {
    1652                 :            :     char *error;
    1653                 :            : 
    1654                 :         43 :     error = mf_parse_subfield__(&stack_action->subfield, &s);
    1655         [ -  + ]:         43 :     if (error) {
    1656                 :          0 :         return error;
    1657                 :            :     }
    1658                 :            : 
    1659         [ -  + ]:         43 :     if (*s != '\0') {
    1660                 :          0 :         return xasprintf("%s: trailing garbage following push or pop", s);
    1661                 :            :     }
    1662                 :            : 
    1663                 :         43 :     return NULL;
    1664                 :            : }
    1665                 :            : 
    1666                 :            : void
    1667                 :       6042 : nxm_format_stack_push(const struct ofpact_stack *push, struct ds *s)
    1668                 :            : {
    1669                 :       6042 :     ds_put_format(s, "%spush:%s", colors.param, colors.end);
    1670                 :       6042 :     mf_format_subfield(&push->subfield, s);
    1671                 :       6042 : }
    1672                 :            : 
    1673                 :            : void
    1674                 :       5522 : nxm_format_stack_pop(const struct ofpact_stack *pop, struct ds *s)
    1675                 :            : {
    1676                 :       5522 :     ds_put_format(s, "%spop:%s", colors.param, colors.end);
    1677                 :       5522 :     mf_format_subfield(&pop->subfield, s);
    1678                 :       5522 : }
    1679                 :            : 
    1680                 :            : enum ofperr
    1681                 :      12482 : nxm_stack_push_check(const struct ofpact_stack *push,
    1682                 :            :                      const struct flow *flow)
    1683                 :            : {
    1684                 :      12482 :     return mf_check_src(&push->subfield, flow);
    1685                 :            : }
    1686                 :            : 
    1687                 :            : enum ofperr
    1688                 :      12437 : nxm_stack_pop_check(const struct ofpact_stack *pop,
    1689                 :            :                     const struct flow *flow)
    1690                 :            : {
    1691                 :      12437 :     return mf_check_dst(&pop->subfield, flow);
    1692                 :            : }
    1693                 :            : 
    1694                 :            : /* nxm_execute_stack_push(), nxm_execute_stack_pop(). */
    1695                 :            : static void
    1696                 :     104207 : nx_stack_push(struct ofpbuf *stack, union mf_subvalue *v)
    1697                 :            : {
    1698                 :     104207 :     ofpbuf_put(stack, v, sizeof *v);
    1699                 :     104207 : }
    1700                 :            : 
    1701                 :            : static union mf_subvalue *
    1702                 :     103693 : nx_stack_pop(struct ofpbuf *stack)
    1703                 :            : {
    1704                 :     103693 :     union mf_subvalue *v = NULL;
    1705                 :            : 
    1706         [ +  + ]:     103693 :     if (stack->size) {
    1707                 :            : 
    1708                 :     103692 :         stack->size -= sizeof *v;
    1709                 :     103692 :         v = (union mf_subvalue *) ofpbuf_tail(stack);
    1710                 :            :     }
    1711                 :            : 
    1712                 :     103693 :     return v;
    1713                 :            : }
    1714                 :            : 
    1715                 :            : void
    1716                 :     104207 : nxm_execute_stack_push(const struct ofpact_stack *push,
    1717                 :            :                        const struct flow *flow, struct flow_wildcards *wc,
    1718                 :            :                        struct ofpbuf *stack)
    1719                 :            : {
    1720                 :            :     union mf_subvalue mask_value;
    1721                 :            :     union mf_subvalue dst_value;
    1722                 :            : 
    1723                 :     104207 :     memset(&mask_value, 0xff, sizeof mask_value);
    1724                 :     104207 :     mf_write_subfield_flow(&push->subfield, &mask_value, &wc->masks);
    1725                 :            : 
    1726                 :     104207 :     mf_read_subfield(&push->subfield, flow, &dst_value);
    1727                 :     104207 :     nx_stack_push(stack, &dst_value);
    1728                 :     104207 : }
    1729                 :            : 
    1730                 :            : void
    1731                 :     103693 : nxm_execute_stack_pop(const struct ofpact_stack *pop,
    1732                 :            :                       struct flow *flow, struct flow_wildcards *wc,
    1733                 :            :                       struct ofpbuf *stack)
    1734                 :            : {
    1735                 :            :     union mf_subvalue *src_value;
    1736                 :            : 
    1737                 :     103693 :     src_value = nx_stack_pop(stack);
    1738                 :            : 
    1739                 :            :     /* Only pop if stack is not empty. Otherwise, give warning. */
    1740         [ +  + ]:     103693 :     if (src_value) {
    1741                 :            :         union mf_subvalue mask_value;
    1742                 :            : 
    1743                 :     103692 :         memset(&mask_value, 0xff, sizeof mask_value);
    1744                 :     103692 :         mf_write_subfield_flow(&pop->subfield, &mask_value, &wc->masks);
    1745                 :     103692 :         mf_write_subfield_flow(&pop->subfield, src_value, flow);
    1746                 :            :     } else {
    1747         [ +  - ]:          1 :         if (!VLOG_DROP_WARN(&rl)) {
    1748                 :          1 :             char *flow_str = flow_to_string(flow);
    1749         [ +  - ]:          1 :             VLOG_WARN_RL(&rl, "Failed to pop from an empty stack. On flow\n"
    1750                 :            :                            " %s", flow_str);
    1751                 :          1 :             free(flow_str);
    1752                 :            :         }
    1753                 :            :     }
    1754                 :     103693 : }
    1755                 :            : 
    1756                 :            : /* Formats 'sf' into 's' in a format normally acceptable to
    1757                 :            :  * mf_parse_subfield().  (It won't be acceptable if sf->field is NULL or if
    1758                 :            :  * sf->field has no NXM name.) */
    1759                 :            : void
    1760                 :      34660 : mf_format_subfield(const struct mf_subfield *sf, struct ds *s)
    1761                 :            : {
    1762         [ -  + ]:      34660 :     if (!sf->field) {
    1763                 :          0 :         ds_put_cstr(s, "<unknown>");
    1764                 :            :     } else {
    1765                 :      34660 :         const struct nxm_field *f = nxm_field_by_mf_id(sf->field->id, 0);
    1766         [ +  - ]:      34660 :         ds_put_cstr(s, f ? f->name : sf->field->name);
    1767                 :            :     }
    1768                 :            : 
    1769 [ +  - ][ +  + ]:      34660 :     if (sf->field && sf->ofs == 0 && sf->n_bits == sf->field->n_bits) {
                 [ +  + ]
    1770                 :      24120 :         ds_put_cstr(s, "[]");
    1771         [ +  + ]:      10540 :     } else if (sf->n_bits == 1) {
    1772                 :       3280 :         ds_put_format(s, "[%d]", sf->ofs);
    1773                 :            :     } else {
    1774                 :       7260 :         ds_put_format(s, "[%d..%d]", sf->ofs, sf->ofs + sf->n_bits - 1);
    1775                 :            :     }
    1776                 :      34660 : }
    1777                 :            : 
    1778                 :            : static const struct nxm_field *
    1779                 :       1536 : mf_parse_subfield_name(const char *name, int name_len, bool *wild)
    1780                 :            : {
    1781 [ +  - ][ +  + ]:       1536 :     *wild = name_len > 2 && !memcmp(&name[name_len - 2], "_W", 2);
    1782         [ +  + ]:       1536 :     if (*wild) {
    1783                 :        203 :         name_len -= 2;
    1784                 :            :     }
    1785                 :            : 
    1786                 :       1536 :     return nxm_field_by_name(name, name_len);
    1787                 :            : }
    1788                 :            : 
    1789                 :            : /* Parses a subfield from the beginning of '*sp' into 'sf'.  If successful,
    1790                 :            :  * returns NULL and advances '*sp' to the first byte following the parsed
    1791                 :            :  * string.  On failure, returns a malloc()'d error message, does not modify
    1792                 :            :  * '*sp', and does not properly initialize 'sf'.
    1793                 :            :  *
    1794                 :            :  * The syntax parsed from '*sp' takes the form "header[start..end]" where
    1795                 :            :  * 'header' is the name of an NXM field and 'start' and 'end' are (inclusive)
    1796                 :            :  * bit indexes.  "..end" may be omitted to indicate a single bit.  "start..end"
    1797                 :            :  * may both be omitted (the [] are still required) to indicate an entire
    1798                 :            :  * field. */
    1799                 :            : char * OVS_WARN_UNUSED_RESULT
    1800                 :        687 : mf_parse_subfield__(struct mf_subfield *sf, const char **sp)
    1801                 :            : {
    1802                 :            :     const struct mf_field *field;
    1803                 :            :     const struct nxm_field *f;
    1804                 :            :     const char *name;
    1805                 :            :     int start, end;
    1806                 :            :     const char *s;
    1807                 :            :     int name_len;
    1808                 :            :     bool wild;
    1809                 :            : 
    1810                 :        687 :     s = *sp;
    1811                 :        687 :     name = s;
    1812                 :        687 :     name_len = strcspn(s, "[");
    1813         [ -  + ]:        687 :     if (s[name_len] != '[') {
    1814                 :          0 :         return xasprintf("%s: missing [ looking for field name", *sp);
    1815                 :            :     }
    1816                 :            : 
    1817                 :        687 :     f = mf_parse_subfield_name(name, name_len, &wild);
    1818         [ -  + ]:        687 :     if (!f) {
    1819                 :          0 :         return xasprintf("%s: unknown field `%.*s'", *sp, name_len, s);
    1820                 :            :     }
    1821                 :        687 :     field = mf_from_id(f->id);
    1822                 :            : 
    1823                 :        687 :     s += name_len;
    1824         [ +  + ]:        687 :     if (ovs_scan(s, "[%d..%d]", &start, &end)) {
    1825                 :            :         /* Nothing to do. */
    1826         [ +  + ]:        510 :     } else if (ovs_scan(s, "[%d]", &start)) {
    1827                 :          5 :         end = start;
    1828         [ +  - ]:        505 :     } else if (!strncmp(s, "[]", 2)) {
    1829                 :        505 :         start = 0;
    1830                 :        505 :         end = field->n_bits - 1;
    1831                 :            :     } else {
    1832                 :          0 :         return xasprintf("%s: syntax error expecting [] or [<bit>] or "
    1833                 :            :                          "[<start>..<end>]", *sp);
    1834                 :            :     }
    1835                 :        687 :     s = strchr(s, ']') + 1;
    1836                 :            : 
    1837         [ -  + ]:        687 :     if (start > end) {
    1838                 :          0 :         return xasprintf("%s: starting bit %d is after ending bit %d",
    1839                 :            :                          *sp, start, end);
    1840         [ -  + ]:        687 :     } else if (start >= field->n_bits) {
    1841                 :          0 :         return xasprintf("%s: starting bit %d is not valid because field is "
    1842                 :            :                          "only %d bits wide", *sp, start, field->n_bits);
    1843         [ -  + ]:        687 :     } else if (end >= field->n_bits){
    1844                 :          0 :         return xasprintf("%s: ending bit %d is not valid because field is "
    1845                 :            :                          "only %d bits wide", *sp, end, field->n_bits);
    1846                 :            :     }
    1847                 :            : 
    1848                 :        687 :     sf->field = field;
    1849                 :        687 :     sf->ofs = start;
    1850                 :        687 :     sf->n_bits = end - start + 1;
    1851                 :            : 
    1852                 :        687 :     *sp = s;
    1853                 :        687 :     return NULL;
    1854                 :            : }
    1855                 :            : 
    1856                 :            : /* Parses a subfield from the entirety of 's' into 'sf'.  Returns NULL if
    1857                 :            :  * successful, otherwise a malloc()'d string describing the error.  The caller
    1858                 :            :  * is responsible for freeing the returned string.
    1859                 :            :  *
    1860                 :            :  * The syntax parsed from 's' takes the form "header[start..end]" where
    1861                 :            :  * 'header' is the name of an NXM field and 'start' and 'end' are (inclusive)
    1862                 :            :  * bit indexes.  "..end" may be omitted to indicate a single bit.  "start..end"
    1863                 :            :  * may both be omitted (the [] are still required) to indicate an entire
    1864                 :            :  * field.  */
    1865                 :            : char * OVS_WARN_UNUSED_RESULT
    1866                 :        512 : mf_parse_subfield(struct mf_subfield *sf, const char *s)
    1867                 :            : {
    1868                 :        512 :     char *error = mf_parse_subfield__(sf, &s);
    1869 [ +  - ][ -  + ]:        512 :     if (!error && s[0]) {
    1870                 :          0 :         error = xstrdup("unexpected input following field syntax");
    1871                 :            :     }
    1872                 :        512 :     return error;
    1873                 :            : }
    1874                 :            : 
    1875                 :            : /* Returns an bitmap in which each bit corresponds to the like-numbered field
    1876                 :            :  * in the OFPXMC12_OPENFLOW_BASIC OXM class, in which the bit values are taken
    1877                 :            :  * from the 'fields' bitmap.  Only fields defined in OpenFlow 'version' are
    1878                 :            :  * considered.
    1879                 :            :  *
    1880                 :            :  * This is useful for encoding OpenFlow 1.2 table stats messages. */
    1881                 :            : ovs_be64
    1882                 :       2032 : oxm_bitmap_from_mf_bitmap(const struct mf_bitmap *fields,
    1883                 :            :                           enum ofp_version version)
    1884                 :            : {
    1885                 :       2032 :     uint64_t oxm_bitmap = 0;
    1886                 :            :     int i;
    1887                 :            : 
    1888         [ +  + ]:     299720 :     BITMAP_FOR_EACH_1 (i, MFF_N_IDS, fields->bm) {
    1889                 :     297688 :         uint64_t oxm = mf_oxm_header(i, version);
    1890                 :     297688 :         uint32_t class = nxm_class(oxm);
    1891                 :     297688 :         int field = nxm_field(oxm);
    1892                 :            : 
    1893 [ +  + ][ +  - ]:     297688 :         if (class == OFPXMC12_OPENFLOW_BASIC && field < 64) {
    1894                 :      70104 :             oxm_bitmap |= UINT64_C(1) << field;
    1895                 :            :         }
    1896                 :            :     }
    1897                 :       2032 :     return htonll(oxm_bitmap);
    1898                 :            : }
    1899                 :            : 
    1900                 :            : /* Opposite conversion from oxm_bitmap_from_mf_bitmap().
    1901                 :            :  *
    1902                 :            :  * This is useful for decoding OpenFlow 1.2 table stats messages. */
    1903                 :            : struct mf_bitmap
    1904                 :       5084 : oxm_bitmap_to_mf_bitmap(ovs_be64 oxm_bitmap, enum ofp_version version)
    1905                 :            : {
    1906                 :       5084 :     struct mf_bitmap fields = MF_BITMAP_INITIALIZER;
    1907                 :            : 
    1908         [ +  + ]:     803272 :     for (enum mf_field_id id = 0; id < MFF_N_IDS; id++) {
    1909                 :     798188 :         uint64_t oxm = mf_oxm_header(id, version);
    1910 [ +  + ][ +  + ]:     798188 :         if (oxm && version >= nxm_field_by_header(oxm)->version) {
    1911                 :     721928 :             uint32_t class = nxm_class(oxm);
    1912                 :     721928 :             int field = nxm_field(oxm);
    1913                 :            : 
    1914         [ +  + ]:     721928 :             if (class == OFPXMC12_OPENFLOW_BASIC
    1915         [ +  - ]:     177940 :                 && field < 64
    1916         [ +  + ]:     177940 :                 && oxm_bitmap & htonll(UINT64_C(1) << field)) {
    1917                 :     173876 :                 bitmap_set1(fields.bm, id);
    1918                 :            :             }
    1919                 :            :         }
    1920                 :            :     }
    1921                 :       5084 :     return fields;
    1922                 :            : }
    1923                 :            : 
    1924                 :            : /* Returns a bitmap of fields that can be encoded in OXM and that can be
    1925                 :            :  * modified with a "set_field" action.  */
    1926                 :            : struct mf_bitmap
    1927                 :         82 : oxm_writable_fields(void)
    1928                 :            : {
    1929                 :         82 :     struct mf_bitmap b = MF_BITMAP_INITIALIZER;
    1930                 :            :     int i;
    1931                 :            : 
    1932         [ +  + ]:      12956 :     for (i = 0; i < MFF_N_IDS; i++) {
    1933 [ +  + ][ +  + ]:      12874 :         if (mf_oxm_header(i, 0) && mf_from_id(i)->writable) {
    1934                 :      11562 :             bitmap_set1(b.bm, i);
    1935                 :            :         }
    1936                 :            :     }
    1937                 :         82 :     return b;
    1938                 :            : }
    1939                 :            : 
    1940                 :            : /* Returns a bitmap of fields that can be encoded in OXM and that can be
    1941                 :            :  * matched in a flow table.  */
    1942                 :            : struct mf_bitmap
    1943                 :         82 : oxm_matchable_fields(void)
    1944                 :            : {
    1945                 :         82 :     struct mf_bitmap b = MF_BITMAP_INITIALIZER;
    1946                 :            :     int i;
    1947                 :            : 
    1948         [ +  + ]:      12956 :     for (i = 0; i < MFF_N_IDS; i++) {
    1949         [ +  + ]:      12874 :         if (mf_oxm_header(i, 0)) {
    1950                 :      12464 :             bitmap_set1(b.bm, i);
    1951                 :            :         }
    1952                 :            :     }
    1953                 :         82 :     return b;
    1954                 :            : }
    1955                 :            : 
    1956                 :            : /* Returns a bitmap of fields that can be encoded in OXM and that can be
    1957                 :            :  * matched in a flow table with an arbitrary bitmask.  */
    1958                 :            : struct mf_bitmap
    1959                 :         82 : oxm_maskable_fields(void)
    1960                 :            : {
    1961                 :         82 :     struct mf_bitmap b = MF_BITMAP_INITIALIZER;
    1962                 :            :     int i;
    1963                 :            : 
    1964         [ +  + ]:      12956 :     for (i = 0; i < MFF_N_IDS; i++) {
    1965 [ +  + ][ +  + ]:      12874 :         if (mf_oxm_header(i, 0) && mf_from_id(i)->maskable == MFM_FULLY) {
    1966                 :      10660 :             bitmap_set1(b.bm, i);
    1967                 :            :         }
    1968                 :            :     }
    1969                 :         82 :     return b;
    1970                 :            : }
    1971                 :            : 
    1972                 :            : struct nxm_field_index {
    1973                 :            :     struct hmap_node header_node; /* In nxm_header_map. */
    1974                 :            :     struct hmap_node name_node;   /* In nxm_name_map. */
    1975                 :            :     struct ovs_list mf_node;      /* In mf_mf_map[nf.id]. */
    1976                 :            :     const struct nxm_field nf;
    1977                 :            : };
    1978                 :            : 
    1979                 :            : #include "nx-match.inc"
    1980                 :            : 
    1981                 :            : static struct hmap nxm_header_map;
    1982                 :            : static struct hmap nxm_name_map;
    1983                 :            : static struct ovs_list nxm_mf_map[MFF_N_IDS];
    1984                 :            : 
    1985                 :            : static void
    1986                 :    3837828 : nxm_init(void)
    1987                 :            : {
    1988                 :            :     static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
    1989         [ +  + ]:    3837828 :     if (ovsthread_once_start(&once)) {
    1990                 :       1347 :         hmap_init(&nxm_header_map);
    1991                 :       1347 :         hmap_init(&nxm_name_map);
    1992         [ +  + ]:     212826 :         for (int i = 0; i < MFF_N_IDS; i++) {
    1993                 :     211479 :             ovs_list_init(&nxm_mf_map[i]);
    1994                 :            :         }
    1995         [ +  + ]:     247848 :         for (struct nxm_field_index *nfi = all_nxm_fields;
    1996                 :     246501 :              nfi < &all_nxm_fields[ARRAY_SIZE(all_nxm_fields)]; nfi++) {
    1997                 :     246501 :             hmap_insert(&nxm_header_map, &nfi->header_node,
    1998                 :            :                         hash_uint64(nxm_no_len(nfi->nf.header)));
    1999                 :     246501 :             hmap_insert(&nxm_name_map, &nfi->name_node,
    2000                 :            :                         hash_string(nfi->nf.name, 0));
    2001                 :     246501 :             ovs_list_push_back(&nxm_mf_map[nfi->nf.id], &nfi->mf_node);
    2002                 :            :         }
    2003                 :       1347 :         ovsthread_once_done(&once);
    2004                 :            :     }
    2005                 :    3837828 : }
    2006                 :            : 
    2007                 :            : static const struct nxm_field *
    2008                 :    1955178 : nxm_field_by_header(uint64_t header)
    2009                 :            : {
    2010                 :            :     const struct nxm_field_index *nfi;
    2011                 :            :     uint64_t header_no_len;
    2012                 :            : 
    2013                 :    1955178 :     nxm_init();
    2014         [ +  + ]:    1955178 :     if (nxm_hasmask(header)) {
    2015                 :     157190 :         header = nxm_make_exact_header(header);
    2016                 :            :     }
    2017                 :            : 
    2018                 :    1955178 :     header_no_len = nxm_no_len(header);
    2019                 :            : 
    2020 [ +  + ][ -  + ]:    3264286 :     HMAP_FOR_EACH_IN_BUCKET (nfi, header_node, hash_uint64(header_no_len),
    2021                 :            :                              &nxm_header_map) {
    2022         [ +  + ]:    3264268 :         if (header_no_len == nxm_no_len(nfi->nf.header)) {
    2023   [ +  +  +  + ]:    1955951 :             if (nxm_length(header) == nxm_length(nfi->nf.header) ||
    2024                 :        791 :                 mf_from_id(nfi->nf.id)->variable_len) {
    2025                 :    1955112 :                 return &nfi->nf;
    2026                 :            :             } else {
    2027                 :         48 :                 return NULL;
    2028                 :            :             }
    2029                 :            :         }
    2030                 :            :     }
    2031                 :         18 :     return NULL;
    2032                 :            : }
    2033                 :            : 
    2034                 :            : static const struct nxm_field *
    2035                 :       1536 : nxm_field_by_name(const char *name, size_t len)
    2036                 :            : {
    2037                 :            :     const struct nxm_field_index *nfi;
    2038                 :            : 
    2039                 :       1536 :     nxm_init();
    2040 [ +  + ][ -  + ]:       1536 :     HMAP_FOR_EACH_WITH_HASH (nfi, name_node, hash_bytes(name, len, 0),
    2041                 :            :                              &nxm_name_map) {
    2042 [ +  - ][ +  - ]:       1514 :         if (strlen(nfi->nf.name) == len && !memcmp(nfi->nf.name, name, len)) {
    2043                 :       1514 :             return &nfi->nf;
    2044                 :            :         }
    2045                 :            :     }
    2046                 :         22 :     return NULL;
    2047                 :            : }
    2048                 :            : 
    2049                 :            : static const struct nxm_field *
    2050                 :    1881114 : nxm_field_by_mf_id(enum mf_field_id id, enum ofp_version version)
    2051                 :            : {
    2052                 :            :     const struct nxm_field_index *nfi;
    2053                 :            :     const struct nxm_field *f;
    2054                 :            : 
    2055                 :    1881114 :     nxm_init();
    2056                 :            : 
    2057                 :    1881114 :     f = NULL;
    2058         [ +  + ]:    4159903 :     LIST_FOR_EACH (nfi, mf_node, &nxm_mf_map[id]) {
    2059 [ +  + ][ +  + ]:    2278789 :         if (!f || version >= nfi->nf.version) {
    2060                 :    2200444 :             f = &nfi->nf;
    2061                 :            :         }
    2062                 :            :     }
    2063                 :    1881114 :     return f;
    2064                 :            : }

Generated by: LCOV version 1.12