LCOV - code coverage report
Current view: top level - lib - match.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 691 758 91.2 %
Date: 2016-09-14 01:02:56 Functions: 119 131 90.8 %
Branches: 208 240 86.7 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
       3                 :            :  *
       4                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
       5                 :            :  * you may not use this file except in compliance with the License.
       6                 :            :  * You may obtain a copy of the License at:
       7                 :            :  *
       8                 :            :  *     http://www.apache.org/licenses/LICENSE-2.0
       9                 :            :  *
      10                 :            :  * Unless required by applicable law or agreed to in writing, software
      11                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      12                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13                 :            :  * See the License for the specific language governing permissions and
      14                 :            :  * limitations under the License.
      15                 :            :  */
      16                 :            : 
      17                 :            : #include <config.h>
      18                 :            : #include "openvswitch/match.h"
      19                 :            : #include <stdlib.h>
      20                 :            : #include "flow.h"
      21                 :            : #include "byte-order.h"
      22                 :            : #include "colors.h"
      23                 :            : #include "openvswitch/dynamic-string.h"
      24                 :            : #include "openvswitch/ofp-util.h"
      25                 :            : #include "packets.h"
      26                 :            : #include "tun-metadata.h"
      27                 :            : 
      28                 :            : /* Converts the flow in 'flow' into a match in 'match', with the given
      29                 :            :  * 'wildcards'. */
      30                 :            : void
      31                 :       7733 : match_init(struct match *match,
      32                 :            :            const struct flow *flow, const struct flow_wildcards *wc)
      33                 :            : {
      34                 :       7733 :     match->flow = *flow;
      35                 :       7733 :     match->wc = *wc;
      36                 :       7733 :     match_zero_wildcarded_fields(match);
      37                 :       7733 :     memset(&match->tun_md, 0, sizeof match->tun_md);
      38                 :       7733 : }
      39                 :            : 
      40                 :            : /* Converts a flow into a match.  It sets the wildcard masks based on
      41                 :            :  * the packet contents.  It will not set the mask for fields that do not
      42                 :            :  * make sense for the packet type. */
      43                 :            : void
      44                 :       6725 : match_wc_init(struct match *match, const struct flow *flow)
      45                 :            : {
      46                 :       6725 :     match->flow = *flow;
      47                 :            : 
      48                 :       6725 :     flow_wildcards_init_for_packet(&match->wc, flow);
      49                 :       6725 :     WC_MASK_FIELD(&match->wc, regs);
      50                 :       6725 :     WC_MASK_FIELD(&match->wc, metadata);
      51                 :            : 
      52                 :       6725 :     memset(&match->tun_md, 0, sizeof match->tun_md);
      53                 :       6725 : }
      54                 :            : 
      55                 :            : /* Initializes 'match' as a "catch-all" match that matches every packet. */
      56                 :            : void
      57                 :    1506874 : match_init_catchall(struct match *match)
      58                 :            : {
      59                 :    1506874 :     memset(&match->flow, 0, sizeof match->flow);
      60                 :    1506874 :     flow_wildcards_init_catchall(&match->wc);
      61                 :    1506874 :     memset(&match->tun_md, 0, sizeof match->tun_md);
      62                 :    1506874 : }
      63                 :            : 
      64                 :            : /* For each bit or field wildcarded in 'match', sets the corresponding bit or
      65                 :            :  * field in 'flow' to all-0-bits.  It is important to maintain this invariant
      66                 :            :  * in a match that might be inserted into a classifier.
      67                 :            :  *
      68                 :            :  * It is never necessary to call this function directly for a match that is
      69                 :            :  * initialized or modified only by match_*() functions.  It is useful to
      70                 :            :  * restore the invariant in a match whose 'wc' member is modified by hand.
      71                 :            :  */
      72                 :            : void
      73                 :      14501 : match_zero_wildcarded_fields(struct match *match)
      74                 :            : {
      75                 :      14501 :     flow_zero_wildcards(&match->flow, &match->wc);
      76                 :      14501 : }
      77                 :            : 
      78                 :            : void
      79                 :          6 : match_set_dp_hash(struct match *match, uint32_t value)
      80                 :            : {
      81                 :          6 :     match_set_dp_hash_masked(match, value, UINT32_MAX);
      82                 :          6 : }
      83                 :            : 
      84                 :            : void
      85                 :       1803 : match_set_dp_hash_masked(struct match *match, uint32_t value, uint32_t mask)
      86                 :            : {
      87                 :       1803 :     match->wc.masks.dp_hash = mask;
      88                 :       1803 :     match->flow.dp_hash = value & mask;
      89                 :       1803 : }
      90                 :            : 
      91                 :            : void
      92                 :       2541 : match_set_recirc_id(struct match *match, uint32_t value)
      93                 :            : {
      94                 :       2541 :     match->flow.recirc_id = value;
      95                 :       2541 :     match->wc.masks.recirc_id = UINT32_MAX;
      96                 :       2541 : }
      97                 :            : 
      98                 :            : void
      99                 :        430 : match_set_conj_id(struct match *match, uint32_t value)
     100                 :            : {
     101                 :        430 :     match->flow.conj_id = value;
     102                 :        430 :     match->wc.masks.conj_id = UINT32_MAX;
     103                 :        430 : }
     104                 :            : 
     105                 :            : void
     106                 :     788409 : match_set_reg(struct match *match, unsigned int reg_idx, uint32_t value)
     107                 :            : {
     108                 :     788409 :     match_set_reg_masked(match, reg_idx, value, UINT32_MAX);
     109                 :     788409 : }
     110                 :            : 
     111                 :            : void
     112                 :    1332918 : match_set_reg_masked(struct match *match, unsigned int reg_idx,
     113                 :            :                      uint32_t value, uint32_t mask)
     114                 :            : {
     115         [ -  + ]:    1332918 :     ovs_assert(reg_idx < FLOW_N_REGS);
     116                 :    1332918 :     flow_wildcards_set_reg_mask(&match->wc, reg_idx, mask);
     117                 :    1332918 :     match->flow.regs[reg_idx] = value & mask;
     118                 :    1332918 : }
     119                 :            : 
     120                 :            : void
     121                 :         31 : match_set_xreg(struct match *match, unsigned int xreg_idx, uint64_t value)
     122                 :            : {
     123                 :         31 :     match_set_xreg_masked(match, xreg_idx, value, UINT64_MAX);
     124                 :         31 : }
     125                 :            : 
     126                 :            : void
     127                 :         66 : match_set_xreg_masked(struct match *match, unsigned int xreg_idx,
     128                 :            :                       uint64_t value, uint64_t mask)
     129                 :            : {
     130         [ -  + ]:         66 :     ovs_assert(xreg_idx < FLOW_N_XREGS);
     131                 :         66 :     flow_wildcards_set_xreg_mask(&match->wc, xreg_idx, mask);
     132                 :         66 :     flow_set_xreg(&match->flow, xreg_idx, value & mask);
     133                 :         66 : }
     134                 :            : 
     135                 :            : void
     136                 :      21502 : match_set_xxreg(struct match *match, unsigned int xxreg_idx, ovs_u128 value)
     137                 :            : {
     138                 :      21502 :     match_set_xxreg_masked(match, xxreg_idx, value, OVS_U128_MAX);
     139                 :      21502 : }
     140                 :            : 
     141                 :            : void
     142                 :     146375 : match_set_xxreg_masked(struct match *match, unsigned int xxreg_idx,
     143                 :            :                       ovs_u128 value, ovs_u128 mask)
     144                 :            : {
     145         [ -  + ]:     146375 :     ovs_assert(xxreg_idx < FLOW_N_XXREGS);
     146                 :     146375 :     flow_wildcards_set_xxreg_mask(&match->wc, xxreg_idx, mask);
     147                 :     146375 :     flow_set_xxreg(&match->flow, xxreg_idx, ovs_u128_and(value, mask));
     148                 :     146375 : }
     149                 :            : 
     150                 :            : void
     151                 :         17 : match_set_actset_output(struct match *match, ofp_port_t actset_output)
     152                 :            : {
     153                 :         17 :     match->wc.masks.actset_output = u16_to_ofp(UINT16_MAX);
     154                 :         17 :     match->flow.actset_output = actset_output;
     155                 :         17 : }
     156                 :            : 
     157                 :            : void
     158                 :    1036706 : match_set_metadata(struct match *match, ovs_be64 metadata)
     159                 :            : {
     160                 :    1036706 :     match_set_metadata_masked(match, metadata, OVS_BE64_MAX);
     161                 :    1036706 : }
     162                 :            : 
     163                 :            : void
     164                 :    1036911 : match_set_metadata_masked(struct match *match,
     165                 :            :                           ovs_be64 metadata, ovs_be64 mask)
     166                 :            : {
     167                 :    1036911 :     match->wc.masks.metadata = mask;
     168                 :    1036911 :     match->flow.metadata = metadata & mask;
     169                 :    1036911 : }
     170                 :            : 
     171                 :            : void
     172                 :         99 : match_set_tun_id(struct match *match, ovs_be64 tun_id)
     173                 :            : {
     174                 :         99 :     match_set_tun_id_masked(match, tun_id, OVS_BE64_MAX);
     175                 :         99 : }
     176                 :            : 
     177                 :            : void
     178                 :        107 : match_set_tun_id_masked(struct match *match, ovs_be64 tun_id, ovs_be64 mask)
     179                 :            : {
     180                 :        107 :     match->wc.masks.tunnel.tun_id = mask;
     181                 :        107 :     match->flow.tunnel.tun_id = tun_id & mask;
     182                 :        107 : }
     183                 :            : 
     184                 :            : void
     185                 :          8 : match_set_tun_src(struct match *match, ovs_be32 src)
     186                 :            : {
     187                 :          8 :     match_set_tun_src_masked(match, src, OVS_BE32_MAX);
     188                 :          8 : }
     189                 :            : 
     190                 :            : void
     191                 :         10 : match_set_tun_src_masked(struct match *match, ovs_be32 src, ovs_be32 mask)
     192                 :            : {
     193                 :         10 :     match->wc.masks.tunnel.ip_src = mask;
     194                 :         10 :     match->flow.tunnel.ip_src = src & mask;
     195                 :         10 : }
     196                 :            : 
     197                 :            : void
     198                 :          8 : match_set_tun_dst(struct match *match, ovs_be32 dst)
     199                 :            : {
     200                 :          8 :     match_set_tun_dst_masked(match, dst, OVS_BE32_MAX);
     201                 :          8 : }
     202                 :            : 
     203                 :            : void
     204                 :         10 : match_set_tun_dst_masked(struct match *match, ovs_be32 dst, ovs_be32 mask)
     205                 :            : {
     206                 :         10 :     match->wc.masks.tunnel.ip_dst = mask;
     207                 :         10 :     match->flow.tunnel.ip_dst = dst & mask;
     208                 :         10 : }
     209                 :            : 
     210                 :            : void
     211                 :          3 : match_set_tun_ipv6_src(struct match *match, const struct in6_addr *src)
     212                 :            : {
     213                 :          3 :     match->flow.tunnel.ipv6_src = *src;
     214                 :          3 :     match->wc.masks.tunnel.ipv6_src = in6addr_exact;
     215                 :          3 : }
     216                 :            : 
     217                 :            : void
     218                 :          0 : match_set_tun_ipv6_src_masked(struct match *match, const struct in6_addr *src,
     219                 :            :                               const struct in6_addr *mask)
     220                 :            : {
     221                 :          0 :     match->flow.tunnel.ipv6_src = ipv6_addr_bitand(src, mask);
     222                 :          0 :     match->wc.masks.tunnel.ipv6_src = *mask;
     223                 :          0 : }
     224                 :            : 
     225                 :            : void
     226                 :          3 : match_set_tun_ipv6_dst(struct match *match, const struct in6_addr *dst)
     227                 :            : {
     228                 :          3 :     match->flow.tunnel.ipv6_dst = *dst;
     229                 :          3 :     match->wc.masks.tunnel.ipv6_dst = in6addr_exact;
     230                 :          3 : }
     231                 :            : 
     232                 :            : void
     233                 :          0 : match_set_tun_ipv6_dst_masked(struct match *match, const struct in6_addr *dst,
     234                 :            :                               const struct in6_addr *mask)
     235                 :            : {
     236                 :          0 :     match->flow.tunnel.ipv6_dst = ipv6_addr_bitand(dst, mask);
     237                 :          0 :     match->wc.masks.tunnel.ipv6_dst = *mask;
     238                 :          0 : }
     239                 :            : 
     240                 :            : void
     241                 :          1 : match_set_tun_ttl(struct match *match, uint8_t ttl)
     242                 :            : {
     243                 :          1 :     match_set_tun_ttl_masked(match, ttl, UINT8_MAX);
     244                 :          1 : }
     245                 :            : 
     246                 :            : void
     247                 :          1 : match_set_tun_ttl_masked(struct match *match, uint8_t ttl, uint8_t mask)
     248                 :            : {
     249                 :          1 :     match->wc.masks.tunnel.ip_ttl = mask;
     250                 :          1 :     match->flow.tunnel.ip_ttl = ttl & mask;
     251                 :          1 : }
     252                 :            : 
     253                 :            : void
     254                 :          1 : match_set_tun_tos(struct match *match, uint8_t tos)
     255                 :            : {
     256                 :          1 :     match_set_tun_tos_masked(match, tos, UINT8_MAX);
     257                 :          1 : }
     258                 :            : 
     259                 :            : void
     260                 :          1 : match_set_tun_tos_masked(struct match *match, uint8_t tos, uint8_t mask)
     261                 :            : {
     262                 :          1 :     match->wc.masks.tunnel.ip_tos = mask;
     263                 :          1 :     match->flow.tunnel.ip_tos = tos & mask;
     264                 :          1 : }
     265                 :            : 
     266                 :            : void
     267                 :          1 : match_set_tun_flags(struct match *match, uint16_t flags)
     268                 :            : {
     269                 :          1 :     match_set_tun_flags_masked(match, flags, UINT16_MAX);
     270                 :          1 : }
     271                 :            : 
     272                 :            : void
     273                 :          4 : match_set_tun_flags_masked(struct match *match, uint16_t flags, uint16_t mask)
     274                 :            : {
     275                 :          4 :     mask &= FLOW_TNL_PUB_F_MASK;
     276                 :            : 
     277                 :          4 :     match->wc.masks.tunnel.flags = mask;
     278                 :          4 :     match->flow.tunnel.flags = flags & mask;
     279                 :          4 : }
     280                 :            : 
     281                 :            : void
     282                 :          4 : match_set_tun_gbp_id_masked(struct match *match, ovs_be16 gbp_id, ovs_be16 mask)
     283                 :            : {
     284                 :          4 :     match->wc.masks.tunnel.gbp_id = mask;
     285                 :          4 :     match->flow.tunnel.gbp_id = gbp_id & mask;
     286                 :          4 : }
     287                 :            : 
     288                 :            : void
     289                 :          2 : match_set_tun_gbp_id(struct match *match, ovs_be16 gbp_id)
     290                 :            : {
     291                 :          2 :     match_set_tun_gbp_id_masked(match, gbp_id, OVS_BE16_MAX);
     292                 :          2 : }
     293                 :            : 
     294                 :            : void
     295                 :          4 : match_set_tun_gbp_flags_masked(struct match *match, uint8_t flags, uint8_t mask)
     296                 :            : {
     297                 :          4 :     match->wc.masks.tunnel.gbp_flags = mask;
     298                 :          4 :     match->flow.tunnel.gbp_flags = flags & mask;
     299                 :          4 : }
     300                 :            : 
     301                 :            : void
     302                 :          2 : match_set_tun_gbp_flags(struct match *match, uint8_t flags)
     303                 :            : {
     304                 :          2 :     match_set_tun_gbp_flags_masked(match, flags, UINT8_MAX);
     305                 :          2 : }
     306                 :            : 
     307                 :            : void
     308                 :      49118 : match_set_in_port(struct match *match, ofp_port_t ofp_port)
     309                 :            : {
     310                 :      49118 :     match->wc.masks.in_port.ofp_port = u16_to_ofp(UINT16_MAX);
     311                 :      49118 :     match->flow.in_port.ofp_port = ofp_port;
     312                 :      49118 : }
     313                 :            : 
     314                 :            : void
     315                 :          2 : match_set_skb_priority(struct match *match, uint32_t skb_priority)
     316                 :            : {
     317                 :          2 :     match->wc.masks.skb_priority = UINT32_MAX;
     318                 :          2 :     match->flow.skb_priority = skb_priority;
     319                 :          2 : }
     320                 :            : 
     321                 :            : void
     322                 :         10 : match_set_pkt_mark(struct match *match, uint32_t pkt_mark)
     323                 :            : {
     324                 :         10 :     match_set_pkt_mark_masked(match, pkt_mark, UINT32_MAX);
     325                 :         10 : }
     326                 :            : 
     327                 :            : void
     328                 :         12 : match_set_pkt_mark_masked(struct match *match, uint32_t pkt_mark, uint32_t mask)
     329                 :            : {
     330                 :         12 :     match->flow.pkt_mark = pkt_mark & mask;
     331                 :         12 :     match->wc.masks.pkt_mark = mask;
     332                 :         12 : }
     333                 :            : 
     334                 :            : void
     335                 :         22 : match_set_ct_state(struct match *match, uint32_t ct_state)
     336                 :            : {
     337                 :         22 :     match_set_ct_state_masked(match, ct_state, UINT32_MAX);
     338                 :         22 : }
     339                 :            : 
     340                 :            : void
     341                 :       1269 : match_set_ct_state_masked(struct match *match, uint32_t ct_state, uint32_t mask)
     342                 :            : {
     343                 :       1269 :     match->flow.ct_state = ct_state & mask & UINT16_MAX;
     344                 :       1269 :     match->wc.masks.ct_state = mask & UINT16_MAX;
     345                 :       1269 : }
     346                 :            : 
     347                 :            : void
     348                 :        107 : match_set_ct_zone(struct match *match, uint16_t ct_zone)
     349                 :            : {
     350                 :        107 :     match->flow.ct_zone = ct_zone;
     351                 :        107 :     match->wc.masks.ct_zone = UINT16_MAX;
     352                 :        107 : }
     353                 :            : 
     354                 :            : void
     355                 :         58 : match_set_ct_mark(struct match *match, uint32_t ct_mark)
     356                 :            : {
     357                 :         58 :     match_set_ct_mark_masked(match, ct_mark, UINT32_MAX);
     358                 :         58 : }
     359                 :            : 
     360                 :            : void
     361                 :         61 : match_set_ct_mark_masked(struct match *match, uint32_t ct_mark,
     362                 :            :                            uint32_t mask)
     363                 :            : {
     364                 :         61 :     match->flow.ct_mark = ct_mark & mask;
     365                 :         61 :     match->wc.masks.ct_mark = mask;
     366                 :         61 : }
     367                 :            : 
     368                 :            : void
     369                 :         31 : match_set_ct_label(struct match *match, ovs_u128 ct_label)
     370                 :            : {
     371                 :            :     ovs_u128 mask;
     372                 :            : 
     373                 :         31 :     mask.u64.lo = UINT64_MAX;
     374                 :         31 :     mask.u64.hi = UINT64_MAX;
     375                 :         31 :     match_set_ct_label_masked(match, ct_label, mask);
     376                 :         31 : }
     377                 :            : 
     378                 :            : void
     379                 :        228 : match_set_ct_label_masked(struct match *match, ovs_u128 value, ovs_u128 mask)
     380                 :            : {
     381                 :        228 :     match->flow.ct_label.u64.lo = value.u64.lo & mask.u64.lo;
     382                 :        228 :     match->flow.ct_label.u64.hi = value.u64.hi & mask.u64.hi;
     383                 :        228 :     match->wc.masks.ct_label = mask;
     384                 :        228 : }
     385                 :            : 
     386                 :            : void
     387                 :     348344 : match_set_dl_type(struct match *match, ovs_be16 dl_type)
     388                 :            : {
     389                 :     348344 :     match->wc.masks.dl_type = OVS_BE16_MAX;
     390                 :     348344 :     match->flow.dl_type = dl_type;
     391                 :     348344 : }
     392                 :            : 
     393                 :            : /* Modifies 'value_src' so that the Ethernet address must match 'value_dst'
     394                 :            :  * exactly.  'mask_dst' is set to all 1s. */
     395                 :            : static void
     396                 :     105857 : set_eth(const struct eth_addr value_src,
     397                 :            :         struct eth_addr *value_dst,
     398                 :            :         struct eth_addr *mask_dst)
     399                 :            : {
     400                 :     105857 :     *value_dst = value_src;
     401                 :     105857 :     *mask_dst = eth_addr_exact;
     402                 :     105857 : }
     403                 :            : 
     404                 :            : /* Modifies 'value_src' so that the Ethernet address must match 'value_src'
     405                 :            :  * after each byte is ANDed with the appropriate byte in 'mask_src'.
     406                 :            :  * 'mask_dst' is set to 'mask_src' */
     407                 :            : static void
     408                 :      35700 : set_eth_masked(const struct eth_addr value_src,
     409                 :            :                const struct eth_addr mask_src,
     410                 :            :                struct eth_addr *value_dst, struct eth_addr *mask_dst)
     411                 :            : {
     412                 :            :     size_t i;
     413                 :            : 
     414         [ +  + ]:     142800 :     for (i = 0; i < ARRAY_SIZE(value_dst->be16); i++) {
     415                 :     107100 :         value_dst->be16[i] = value_src.be16[i] & mask_src.be16[i];
     416                 :            :     }
     417                 :      35700 :     *mask_dst = mask_src;
     418                 :      35700 : }
     419                 :            : 
     420                 :            : /* Modifies 'rule' so that the source Ethernet address must match 'dl_src'
     421                 :            :  * exactly. */
     422                 :            : void
     423                 :      28232 : match_set_dl_src(struct match *match, const struct eth_addr dl_src)
     424                 :            : {
     425                 :      28232 :     set_eth(dl_src, &match->flow.dl_src, &match->wc.masks.dl_src);
     426                 :      28232 : }
     427                 :            : 
     428                 :            : /* Modifies 'rule' so that the source Ethernet address must match 'dl_src'
     429                 :            :  * after each byte is ANDed with the appropriate byte in 'mask'. */
     430                 :            : void
     431                 :       9375 : match_set_dl_src_masked(struct match *match,
     432                 :            :                         const struct eth_addr dl_src,
     433                 :            :                         const struct eth_addr mask)
     434                 :            : {
     435                 :       9375 :     set_eth_masked(dl_src, mask, &match->flow.dl_src, &match->wc.masks.dl_src);
     436                 :       9375 : }
     437                 :            : 
     438                 :            : /* Modifies 'match' so that the Ethernet address must match 'dl_dst'
     439                 :            :  * exactly. */
     440                 :            : void
     441                 :      77625 : match_set_dl_dst(struct match *match, const struct eth_addr dl_dst)
     442                 :            : {
     443                 :      77625 :     set_eth(dl_dst, &match->flow.dl_dst, &match->wc.masks.dl_dst);
     444                 :      77625 : }
     445                 :            : 
     446                 :            : /* Modifies 'match' so that the Ethernet address must match 'dl_dst' after each
     447                 :            :  * byte is ANDed with the appropriate byte in 'mask'.
     448                 :            :  *
     449                 :            :  * This function will assert-fail if 'mask' is invalid.  Only 'mask' values
     450                 :            :  * accepted by flow_wildcards_is_dl_dst_mask_valid() are allowed. */
     451                 :            : void
     452                 :      26319 : match_set_dl_dst_masked(struct match *match,
     453                 :            :                         const struct eth_addr dl_dst,
     454                 :            :                         const struct eth_addr mask)
     455                 :            : {
     456                 :      26319 :     set_eth_masked(dl_dst, mask, &match->flow.dl_dst, &match->wc.masks.dl_dst);
     457                 :      26319 : }
     458                 :            : 
     459                 :            : void
     460                 :         70 : match_set_dl_tci(struct match *match, ovs_be16 tci)
     461                 :            : {
     462                 :         70 :     match_set_dl_tci_masked(match, tci, htons(0xffff));
     463                 :         70 : }
     464                 :            : 
     465                 :            : void
     466                 :      15079 : match_set_dl_tci_masked(struct match *match, ovs_be16 tci, ovs_be16 mask)
     467                 :            : {
     468                 :      15079 :     match->flow.vlan_tci = tci & mask;
     469                 :      15079 :     match->wc.masks.vlan_tci = mask;
     470                 :      15079 : }
     471                 :            : 
     472                 :            : /* Modifies 'match' so that the VLAN VID is wildcarded.  If the PCP is already
     473                 :            :  * wildcarded, then 'match' will match a packet regardless of whether it has an
     474                 :            :  * 802.1Q header or not. */
     475                 :            : void
     476                 :          1 : match_set_any_vid(struct match *match)
     477                 :            : {
     478         [ -  + ]:          1 :     if (match->wc.masks.vlan_tci & htons(VLAN_PCP_MASK)) {
     479                 :          0 :         match->wc.masks.vlan_tci &= ~htons(VLAN_VID_MASK);
     480                 :          0 :         match->flow.vlan_tci &= ~htons(VLAN_VID_MASK);
     481                 :            :     } else {
     482                 :          1 :         match_set_dl_tci_masked(match, htons(0), htons(0));
     483                 :            :     }
     484                 :          1 : }
     485                 :            : 
     486                 :            : /* Modifies 'match' depending on 'dl_vlan':
     487                 :            :  *
     488                 :            :  *   - If 'dl_vlan' is htons(OFP_VLAN_NONE), makes 'match' match only packets
     489                 :            :  *     without an 802.1Q header.
     490                 :            :  *
     491                 :            :  *   - Otherwise, makes 'match' match only packets with an 802.1Q header whose
     492                 :            :  *     VID equals the low 12 bits of 'dl_vlan'.
     493                 :            :  */
     494                 :            : void
     495                 :       5004 : match_set_dl_vlan(struct match *match, ovs_be16 dl_vlan)
     496                 :            : {
     497                 :       5004 :     flow_set_dl_vlan(&match->flow, dl_vlan);
     498         [ +  + ]:       5004 :     if (dl_vlan == htons(OFP10_VLAN_NONE)) {
     499                 :          3 :         match->wc.masks.vlan_tci = OVS_BE16_MAX;
     500                 :            :     } else {
     501                 :       5001 :         match->wc.masks.vlan_tci |= htons(VLAN_VID_MASK | VLAN_CFI);
     502                 :            :     }
     503                 :       5004 : }
     504                 :            : 
     505                 :            : /* Sets the VLAN VID that 'match' matches to 'vid', which is interpreted as an
     506                 :            :  * OpenFlow 1.2 "vlan_vid" value, that is, the low 13 bits of 'vlan_tci' (VID
     507                 :            :  * plus CFI). */
     508                 :            : void
     509                 :        170 : match_set_vlan_vid(struct match *match, ovs_be16 vid)
     510                 :            : {
     511                 :        170 :     match_set_vlan_vid_masked(match, vid, htons(VLAN_VID_MASK | VLAN_CFI));
     512                 :        170 : }
     513                 :            : 
     514                 :            : 
     515                 :            : /* Sets the VLAN VID that 'flow' matches to 'vid', which is interpreted as an
     516                 :            :  * OpenFlow 1.2 "vlan_vid" value, that is, the low 13 bits of 'vlan_tci' (VID
     517                 :            :  * plus CFI), with the corresponding 'mask'. */
     518                 :            : void
     519                 :        873 : match_set_vlan_vid_masked(struct match *match, ovs_be16 vid, ovs_be16 mask)
     520                 :            : {
     521                 :        873 :     ovs_be16 pcp_mask = htons(VLAN_PCP_MASK);
     522                 :        873 :     ovs_be16 vid_mask = htons(VLAN_VID_MASK | VLAN_CFI);
     523                 :            : 
     524                 :        873 :     mask &= vid_mask;
     525                 :        873 :     flow_set_vlan_vid(&match->flow, vid & mask);
     526                 :        873 :     match->wc.masks.vlan_tci = mask | (match->wc.masks.vlan_tci & pcp_mask);
     527                 :        873 : }
     528                 :            : 
     529                 :            : /* Modifies 'match' so that the VLAN PCP is wildcarded.  If the VID is already
     530                 :            :  * wildcarded, then 'match' will match a packet regardless of whether it has an
     531                 :            :  * 802.1Q header or not. */
     532                 :            : void
     533                 :          0 : match_set_any_pcp(struct match *match)
     534                 :            : {
     535         [ #  # ]:          0 :     if (match->wc.masks.vlan_tci & htons(VLAN_VID_MASK)) {
     536                 :          0 :         match->wc.masks.vlan_tci &= ~htons(VLAN_PCP_MASK);
     537                 :          0 :         match->flow.vlan_tci &= ~htons(VLAN_PCP_MASK);
     538                 :            :     } else {
     539                 :          0 :         match_set_dl_tci_masked(match, htons(0), htons(0));
     540                 :            :     }
     541                 :          0 : }
     542                 :            : 
     543                 :            : /* Modifies 'match' so that it matches only packets with an 802.1Q header whose
     544                 :            :  * PCP equals the low 3 bits of 'dl_vlan_pcp'. */
     545                 :            : void
     546                 :         29 : match_set_dl_vlan_pcp(struct match *match, uint8_t dl_vlan_pcp)
     547                 :            : {
     548                 :         29 :     flow_set_vlan_pcp(&match->flow, dl_vlan_pcp);
     549                 :         29 :     match->wc.masks.vlan_tci |= htons(VLAN_CFI | VLAN_PCP_MASK);
     550                 :         29 : }
     551                 :            : 
     552                 :            : /* Modifies 'match' so that the MPLS label 'idx' matches 'lse' exactly. */
     553                 :            : void
     554                 :          0 : match_set_mpls_lse(struct match *match, int idx, ovs_be32 lse)
     555                 :            : {
     556                 :          0 :     match->wc.masks.mpls_lse[idx] = OVS_BE32_MAX;
     557                 :          0 :     match->flow.mpls_lse[idx] = lse;
     558                 :          0 : }
     559                 :            : 
     560                 :            : /* Modifies 'match' so that the MPLS label is wildcarded. */
     561                 :            : void
     562                 :          0 : match_set_any_mpls_label(struct match *match, int idx)
     563                 :            : {
     564                 :          0 :     match->wc.masks.mpls_lse[idx] &= ~htonl(MPLS_LABEL_MASK);
     565                 :          0 :     flow_set_mpls_label(&match->flow, idx, htonl(0));
     566                 :          0 : }
     567                 :            : 
     568                 :            : /* Modifies 'match' so that it matches only packets with an MPLS header whose
     569                 :            :  * label equals the low 20 bits of 'mpls_label'. */
     570                 :            : void
     571                 :         27 : match_set_mpls_label(struct match *match, int idx, ovs_be32 mpls_label)
     572                 :            : {
     573                 :         27 :     match->wc.masks.mpls_lse[idx] |= htonl(MPLS_LABEL_MASK);
     574                 :         27 :     flow_set_mpls_label(&match->flow, idx, mpls_label);
     575                 :         27 : }
     576                 :            : 
     577                 :            : /* Modifies 'match' so that the MPLS TC is wildcarded. */
     578                 :            : void
     579                 :          0 : match_set_any_mpls_tc(struct match *match, int idx)
     580                 :            : {
     581                 :          0 :     match->wc.masks.mpls_lse[idx] &= ~htonl(MPLS_TC_MASK);
     582                 :          0 :     flow_set_mpls_tc(&match->flow, idx, 0);
     583                 :          0 : }
     584                 :            : 
     585                 :            : /* Modifies 'match' so that it matches only packets with an MPLS header whose
     586                 :            :  * Traffic Class equals the low 3 bits of 'mpls_tc'. */
     587                 :            : void
     588                 :          3 : match_set_mpls_tc(struct match *match, int idx, uint8_t mpls_tc)
     589                 :            : {
     590                 :          3 :     match->wc.masks.mpls_lse[idx] |= htonl(MPLS_TC_MASK);
     591                 :          3 :     flow_set_mpls_tc(&match->flow, idx, mpls_tc);
     592                 :          3 : }
     593                 :            : 
     594                 :            : /* Modifies 'match' so that the MPLS stack flag is wildcarded. */
     595                 :            : void
     596                 :          0 : match_set_any_mpls_bos(struct match *match, int idx)
     597                 :            : {
     598                 :          0 :     match->wc.masks.mpls_lse[idx] &= ~htonl(MPLS_BOS_MASK);
     599                 :          0 :     flow_set_mpls_bos(&match->flow, idx, 0);
     600                 :          0 : }
     601                 :            : 
     602                 :            : /* Modifies 'match' so that it matches only packets with an MPLS header whose
     603                 :            :  * Stack Flag equals the lower bit of 'mpls_bos' */
     604                 :            : void
     605                 :          2 : match_set_mpls_bos(struct match *match, int idx, uint8_t mpls_bos)
     606                 :            : {
     607                 :          2 :     match->wc.masks.mpls_lse[idx] |= htonl(MPLS_BOS_MASK);
     608                 :          2 :     flow_set_mpls_bos(&match->flow, idx, mpls_bos);
     609                 :          2 : }
     610                 :            : 
     611                 :            : /* Modifies 'match' so that the TTL of MPLS label 'idx' is wildcarded. */
     612                 :            : void
     613                 :          0 : match_set_any_mpls_ttl(struct match *match, int idx)
     614                 :            : {
     615                 :          0 :     match->wc.masks.mpls_lse[idx] &= ~htonl(MPLS_TTL_MASK);
     616                 :          0 :     flow_set_mpls_ttl(&match->flow, idx, 0);
     617                 :          0 : }
     618                 :            : 
     619                 :            : /* Modifies 'match' so that it matches only packets in which the TTL of MPLS
     620                 :            :  * label 'idx' equals 'mpls_ttl'. */
     621                 :            : void
     622                 :          0 : match_set_mpls_ttl(struct match *match, int idx, uint8_t mpls_ttl)
     623                 :            : {
     624                 :          0 :     match->wc.masks.mpls_lse[idx] |= htonl(MPLS_TTL_MASK);
     625                 :          0 :     flow_set_mpls_ttl(&match->flow, idx, mpls_ttl);
     626                 :          0 : }
     627                 :            : 
     628                 :            : /* Modifies 'match' so that the MPLS LSE is wildcarded. */
     629                 :            : void
     630                 :          0 : match_set_any_mpls_lse(struct match *match, int idx)
     631                 :            : {
     632                 :          0 :     match->wc.masks.mpls_lse[idx] = htonl(0);
     633                 :          0 :     flow_set_mpls_lse(&match->flow, idx, htonl(0));
     634                 :          0 : }
     635                 :            : 
     636                 :            : void
     637                 :      81306 : match_set_tp_src(struct match *match, ovs_be16 tp_src)
     638                 :            : {
     639                 :      81306 :     match_set_tp_src_masked(match, tp_src, OVS_BE16_MAX);
     640                 :      81306 : }
     641                 :            : 
     642                 :            : void
     643                 :      81321 : match_set_tp_src_masked(struct match *match, ovs_be16 port, ovs_be16 mask)
     644                 :            : {
     645                 :      81321 :     match->flow.tp_src = port & mask;
     646                 :      81321 :     match->wc.masks.tp_src = mask;
     647                 :      81321 : }
     648                 :            : 
     649                 :            : void
     650                 :      79869 : match_set_tp_dst(struct match *match, ovs_be16 tp_dst)
     651                 :            : {
     652                 :      79869 :     match_set_tp_dst_masked(match, tp_dst, OVS_BE16_MAX);
     653                 :      79869 : }
     654                 :            : 
     655                 :            : void
     656                 :      79882 : match_set_tp_dst_masked(struct match *match, ovs_be16 port, ovs_be16 mask)
     657                 :            : {
     658                 :      79882 :     match->flow.tp_dst = port & mask;
     659                 :      79882 :     match->wc.masks.tp_dst = mask;
     660                 :      79882 : }
     661                 :            : 
     662                 :            : void
     663                 :          7 : match_set_tcp_flags(struct match *match, ovs_be16 flags)
     664                 :            : {
     665                 :          7 :     match_set_tcp_flags_masked(match, flags, OVS_BE16_MAX);
     666                 :          7 : }
     667                 :            : 
     668                 :            : void
     669                 :         23 : match_set_tcp_flags_masked(struct match *match, ovs_be16 flags, ovs_be16 mask)
     670                 :            : {
     671                 :         23 :     match->flow.tcp_flags = flags & mask;
     672                 :         23 :     match->wc.masks.tcp_flags = mask;
     673                 :         23 : }
     674                 :            : 
     675                 :            : void
     676                 :     131751 : match_set_nw_proto(struct match *match, uint8_t nw_proto)
     677                 :            : {
     678                 :     131751 :     match->flow.nw_proto = nw_proto;
     679                 :     131751 :     match->wc.masks.nw_proto = UINT8_MAX;
     680                 :     131751 : }
     681                 :            : 
     682                 :            : void
     683                 :      30861 : match_set_nw_src(struct match *match, ovs_be32 nw_src)
     684                 :            : {
     685                 :      30861 :     match->flow.nw_src = nw_src;
     686                 :      30861 :     match->wc.masks.nw_src = OVS_BE32_MAX;
     687                 :      30861 : }
     688                 :            : 
     689                 :            : void
     690                 :       5220 : match_set_nw_src_masked(struct match *match,
     691                 :            :                         ovs_be32 nw_src, ovs_be32 mask)
     692                 :            : {
     693                 :       5220 :     match->flow.nw_src = nw_src & mask;
     694                 :       5220 :     match->wc.masks.nw_src = mask;
     695                 :       5220 : }
     696                 :            : 
     697                 :            : void
     698                 :      74406 : match_set_nw_dst(struct match *match, ovs_be32 nw_dst)
     699                 :            : {
     700                 :      74406 :     match->flow.nw_dst = nw_dst;
     701                 :      74406 :     match->wc.masks.nw_dst = OVS_BE32_MAX;
     702                 :      74406 : }
     703                 :            : 
     704                 :            : void
     705                 :      22172 : match_set_nw_dst_masked(struct match *match, ovs_be32 ip, ovs_be32 mask)
     706                 :            : {
     707                 :      22172 :     match->flow.nw_dst = ip & mask;
     708                 :      22172 :     match->wc.masks.nw_dst = mask;
     709                 :      22172 : }
     710                 :            : 
     711                 :            : void
     712                 :         31 : match_set_nw_dscp(struct match *match, uint8_t nw_dscp)
     713                 :            : {
     714                 :         31 :     match->wc.masks.nw_tos |= IP_DSCP_MASK;
     715                 :         31 :     match->flow.nw_tos &= ~IP_DSCP_MASK;
     716                 :         31 :     match->flow.nw_tos |= nw_dscp & IP_DSCP_MASK;
     717                 :         31 : }
     718                 :            : 
     719                 :            : void
     720                 :          6 : match_set_nw_ecn(struct match *match, uint8_t nw_ecn)
     721                 :            : {
     722                 :          6 :     match->wc.masks.nw_tos |= IP_ECN_MASK;
     723                 :          6 :     match->flow.nw_tos &= ~IP_ECN_MASK;
     724                 :          6 :     match->flow.nw_tos |= nw_ecn & IP_ECN_MASK;
     725                 :          6 : }
     726                 :            : 
     727                 :            : void
     728                 :      57918 : match_set_nw_ttl(struct match *match, uint8_t nw_ttl)
     729                 :            : {
     730                 :      57918 :     match->wc.masks.nw_ttl = UINT8_MAX;
     731                 :      57918 :     match->flow.nw_ttl = nw_ttl;
     732                 :      57918 : }
     733                 :            : 
     734                 :            : void
     735                 :         63 : match_set_nw_frag(struct match *match, uint8_t nw_frag)
     736                 :            : {
     737                 :         63 :     match->wc.masks.nw_frag |= FLOW_NW_FRAG_MASK;
     738                 :         63 :     match->flow.nw_frag = nw_frag;
     739                 :         63 : }
     740                 :            : 
     741                 :            : void
     742                 :         12 : match_set_nw_frag_masked(struct match *match,
     743                 :            :                          uint8_t nw_frag, uint8_t mask)
     744                 :            : {
     745                 :         12 :     match->flow.nw_frag = nw_frag & mask;
     746                 :         12 :     match->wc.masks.nw_frag = mask;
     747                 :         12 : }
     748                 :            : 
     749                 :            : void
     750                 :      80013 : match_set_icmp_type(struct match *match, uint8_t icmp_type)
     751                 :            : {
     752                 :      80013 :     match_set_tp_src(match, htons(icmp_type));
     753                 :      80013 : }
     754                 :            : 
     755                 :            : void
     756                 :      78532 : match_set_icmp_code(struct match *match, uint8_t icmp_code)
     757                 :            : {
     758                 :      78532 :     match_set_tp_dst(match, htons(icmp_code));
     759                 :      78532 : }
     760                 :            : 
     761                 :            : void
     762                 :       9547 : match_set_arp_sha(struct match *match, const struct eth_addr sha)
     763                 :            : {
     764                 :       9547 :     match->flow.arp_sha = sha;
     765                 :       9547 :     match->wc.masks.arp_sha = eth_addr_exact;
     766                 :       9547 : }
     767                 :            : 
     768                 :            : void
     769                 :          3 : match_set_arp_sha_masked(struct match *match,
     770                 :            :                          const struct eth_addr arp_sha,
     771                 :            :                          const struct eth_addr mask)
     772                 :            : {
     773                 :          3 :     set_eth_masked(arp_sha, mask,
     774                 :            :                    &match->flow.arp_sha, &match->wc.masks.arp_sha);
     775                 :          3 : }
     776                 :            : 
     777                 :            : void
     778                 :       7076 : match_set_arp_tha(struct match *match, const struct eth_addr tha)
     779                 :            : {
     780                 :       7076 :     match->flow.arp_tha = tha;
     781                 :       7076 :     match->wc.masks.arp_tha = eth_addr_exact;
     782                 :       7076 : }
     783                 :            : 
     784                 :            : void
     785                 :          3 : match_set_arp_tha_masked(struct match *match,
     786                 :            :                          const struct eth_addr arp_tha,
     787                 :            :                          const struct eth_addr mask)
     788                 :            : {
     789                 :          3 :     set_eth_masked(arp_tha, mask,
     790                 :            :                    &match->flow.arp_tha, &match->wc.masks.arp_tha);
     791                 :          3 : }
     792                 :            : 
     793                 :            : void
     794                 :      15239 : match_set_ipv6_src(struct match *match, const struct in6_addr *src)
     795                 :            : {
     796                 :      15239 :     match->flow.ipv6_src = *src;
     797                 :      15239 :     match->wc.masks.ipv6_src = in6addr_exact;
     798                 :      15239 : }
     799                 :            : 
     800                 :            : void
     801                 :          8 : match_set_ipv6_src_masked(struct match *match, const struct in6_addr *src,
     802                 :            :                           const struct in6_addr *mask)
     803                 :            : {
     804                 :          8 :     match->flow.ipv6_src = ipv6_addr_bitand(src, mask);
     805                 :          8 :     match->wc.masks.ipv6_src = *mask;
     806                 :          8 : }
     807                 :            : 
     808                 :            : void
     809                 :      54579 : match_set_ipv6_dst(struct match *match, const struct in6_addr *dst)
     810                 :            : {
     811                 :      54579 :     match->flow.ipv6_dst = *dst;
     812                 :      54579 :     match->wc.masks.ipv6_dst = in6addr_exact;
     813                 :      54579 : }
     814                 :            : 
     815                 :            : void
     816                 :      14678 : match_set_ipv6_dst_masked(struct match *match, const struct in6_addr *dst,
     817                 :            :                           const struct in6_addr *mask)
     818                 :            : {
     819                 :      14678 :     match->flow.ipv6_dst = ipv6_addr_bitand(dst, mask);
     820                 :      14678 :     match->wc.masks.ipv6_dst = *mask;
     821                 :      14678 : }
     822                 :            : 
     823                 :            : void
     824                 :         11 : match_set_ipv6_label(struct match *match, ovs_be32 ipv6_label)
     825                 :            : {
     826                 :         11 :     match->wc.masks.ipv6_label = OVS_BE32_MAX;
     827                 :         11 :     match->flow.ipv6_label = ipv6_label;
     828                 :         11 : }
     829                 :            : 
     830                 :            : 
     831                 :            : void
     832                 :          4 : match_set_ipv6_label_masked(struct match *match, ovs_be32 ipv6_label,
     833                 :            :                             ovs_be32 mask)
     834                 :            : {
     835                 :          4 :     match->flow.ipv6_label = ipv6_label & mask;
     836                 :          4 :     match->wc.masks.ipv6_label = mask;
     837                 :          4 : }
     838                 :            : 
     839                 :            : void
     840                 :      29712 : match_set_nd_target(struct match *match, const struct in6_addr *target)
     841                 :            : {
     842                 :      29712 :     match->flow.nd_target = *target;
     843                 :      29712 :     match->wc.masks.nd_target = in6addr_exact;
     844                 :      29712 : }
     845                 :            : 
     846                 :            : void
     847                 :          4 : match_set_nd_target_masked(struct match *match,
     848                 :            :                            const struct in6_addr *target,
     849                 :            :                            const struct in6_addr *mask)
     850                 :            : {
     851                 :          4 :     match->flow.nd_target = ipv6_addr_bitand(target, mask);
     852                 :          4 :     match->wc.masks.nd_target = *mask;
     853                 :          4 : }
     854                 :            : 
     855                 :            : /* Returns true if 'a' and 'b' wildcard the same fields and have the same
     856                 :            :  * values for fixed fields, otherwise false. */
     857                 :            : bool
     858                 :    1023362 : match_equal(const struct match *a, const struct match *b)
     859                 :            : {
     860                 :    2046724 :     return (flow_wildcards_equal(&a->wc, &b->wc)
     861 [ +  - ][ +  - ]:    1023362 :             && flow_equal(&a->flow, &b->flow));
     862                 :            : }
     863                 :            : 
     864                 :            : /* Returns a hash value for the flow and wildcards in 'match', starting from
     865                 :            :  * 'basis'. */
     866                 :            : uint32_t
     867                 :    2185334 : match_hash(const struct match *match, uint32_t basis)
     868                 :            : {
     869                 :    2185334 :     return flow_wildcards_hash(&match->wc, flow_hash(&match->flow, basis));
     870                 :            : }
     871                 :            : 
     872                 :            : static bool
     873                 :      27222 : match_has_default_recirc_id(const struct match *m)
     874                 :            : {
     875 [ +  - ][ +  - ]:      27222 :     return m->flow.recirc_id == 0 && (m->wc.masks.recirc_id == UINT32_MAX ||
                 [ +  - ]
     876                 :      27222 :                                       m->wc.masks.recirc_id == 0);
     877                 :            : }
     878                 :            : 
     879                 :            : static bool
     880                 :      27222 : match_has_default_dp_hash(const struct match *m)
     881                 :            : {
     882                 :      27222 :     return ((m->flow.dp_hash | m->wc.masks.dp_hash) == 0);
     883                 :            : }
     884                 :            : 
     885                 :            : /* Return true if the hidden fields of the match are set to the default values.
     886                 :            :  * The default values equals to those set up by match_init_hidden_fields(). */
     887                 :            : bool
     888                 :      27222 : match_has_default_hidden_fields(const struct match *m)
     889                 :            : {
     890 [ +  - ][ +  - ]:      27222 :     return match_has_default_recirc_id(m) && match_has_default_dp_hash(m);
     891                 :            : }
     892                 :            : 
     893                 :            : void
     894                 :          0 : match_init_hidden_fields(struct match *m)
     895                 :            : {
     896                 :          0 :     match_set_recirc_id(m, 0);
     897                 :          0 :     match_set_dp_hash_masked(m, 0, 0);
     898                 :          0 : }
     899                 :            : 
     900                 :            : static void
     901                 :     232908 : format_eth_masked(struct ds *s, const char *name,
     902                 :            :                   const struct eth_addr eth, const struct eth_addr mask)
     903                 :            : {
     904         [ +  + ]:     232908 :     if (!eth_addr_is_zero(mask)) {
     905                 :      25841 :         ds_put_format(s, "%s%s=%s", colors.param, name, colors.end);
     906                 :      25841 :         eth_format_masked(eth, &mask, s);
     907                 :      25841 :         ds_put_char(s, ',');
     908                 :            :     }
     909                 :     232908 : }
     910                 :            : 
     911                 :            : static void
     912                 :     429198 : format_ip_netmask(struct ds *s, const char *name, ovs_be32 ip,
     913                 :            :                   ovs_be32 netmask)
     914                 :            : {
     915         [ +  + ]:     429198 :     if (netmask) {
     916                 :      17059 :         ds_put_format(s, "%s%s=%s", colors.param, name, colors.end);
     917                 :      17059 :         ip_format_masked(ip, netmask, s);
     918                 :      17059 :         ds_put_char(s, ',');
     919                 :            :     }
     920                 :     429198 : }
     921                 :            : 
     922                 :            : static void
     923                 :     235971 : format_ipv6_netmask(struct ds *s, const char *name,
     924                 :            :                     const struct in6_addr *addr,
     925                 :            :                     const struct in6_addr *netmask)
     926                 :            : {
     927         [ +  + ]:     235971 :     if (!ipv6_mask_is_any(netmask)) {
     928                 :       3384 :         ds_put_format(s, "%s%s=%s", colors.param, name, colors.end);
     929                 :       3384 :         ipv6_format_masked(addr, netmask, s);
     930                 :       3384 :         ds_put_char(s, ',');
     931                 :            :     }
     932                 :     235971 : }
     933                 :            : 
     934                 :            : static void
     935                 :         36 : format_uint16_masked(struct ds *s, const char *name,
     936                 :            :                    uint16_t value, uint16_t mask)
     937                 :            : {
     938         [ +  - ]:         36 :     if (mask != 0) {
     939                 :         36 :         ds_put_format(s, "%s%s=%s", colors.param, name, colors.end);
     940         [ +  - ]:         36 :         if (mask == UINT16_MAX) {
     941                 :         36 :             ds_put_format(s, "%"PRIu16, value);
     942                 :            :         } else {
     943                 :          0 :             ds_put_format(s, "0x%"PRIx16"/0x%"PRIx16, value, mask);
     944                 :            :         }
     945                 :         36 :         ds_put_char(s, ',');
     946                 :            :     }
     947                 :         36 : }
     948                 :            : 
     949                 :            : static void
     950                 :     220997 : format_be16_masked(struct ds *s, const char *name,
     951                 :            :                    ovs_be16 value, ovs_be16 mask)
     952                 :            : {
     953         [ +  + ]:     220997 :     if (mask != htons(0)) {
     954                 :      14721 :         ds_put_format(s, "%s%s=%s", colors.param, name, colors.end);
     955         [ +  + ]:      14721 :         if (mask == OVS_BE16_MAX) {
     956                 :      14416 :             ds_put_format(s, "%"PRIu16, ntohs(value));
     957                 :            :         } else {
     958                 :        305 :             ds_put_format(s, "0x%"PRIx16"/0x%"PRIx16,
     959                 :        305 :                           ntohs(value), ntohs(mask));
     960                 :            :         }
     961                 :      14721 :         ds_put_char(s, ',');
     962                 :            :     }
     963                 :     220997 : }
     964                 :            : 
     965                 :            : static void
     966                 :     220852 : format_be32_masked(struct ds *s, const char *name,
     967                 :            :                    ovs_be32 value, ovs_be32 mask)
     968                 :            : {
     969         [ +  + ]:     220852 :     if (mask != htonl(0)) {
     970                 :         32 :         ds_put_format(s, "%s%s=%s", colors.param, name, colors.end);
     971         [ +  - ]:         32 :         if (mask == OVS_BE32_MAX) {
     972                 :         32 :             ds_put_format(s, "%"PRIu32, ntohl(value));
     973                 :            :         } else {
     974                 :          0 :             ds_put_format(s, "0x%"PRIx32"/0x%"PRIx32,
     975                 :            :                           ntohl(value), ntohl(mask));
     976                 :            :         }
     977                 :         32 :         ds_put_char(s, ',');
     978                 :            :     }
     979                 :     220852 : }
     980                 :            : 
     981                 :            : static void
     982                 :    1885287 : format_uint32_masked(struct ds *s, const char *name,
     983                 :            :                    uint32_t value, uint32_t mask)
     984                 :            : {
     985         [ +  + ]:    1885287 :     if (mask) {
     986                 :      75104 :         ds_put_format(s, "%s%s=%s%#"PRIx32,
     987                 :            :                       colors.param, name, colors.end, value);
     988         [ +  + ]:      75104 :         if (mask != UINT32_MAX) {
     989                 :       7397 :             ds_put_format(s, "/%#"PRIx32, mask);
     990                 :            :         }
     991                 :      75104 :         ds_put_char(s, ',');
     992                 :            :     }
     993                 :    1885287 : }
     994                 :            : 
     995                 :            : static void
     996                 :     220852 : format_be64_masked(struct ds *s, const char *name,
     997                 :            :                    ovs_be64 value, ovs_be64 mask)
     998                 :            : {
     999         [ +  + ]:     220852 :     if (mask != htonll(0)) {
    1000                 :      36115 :         ds_put_format(s, "%s%s=%s%#"PRIx64,
    1001                 :            :                       colors.param, name, colors.end, ntohll(value));
    1002         [ +  + ]:      36115 :         if (mask != OVS_BE64_MAX) {
    1003                 :          8 :             ds_put_format(s, "/%#"PRIx64, ntohll(mask));
    1004                 :            :         }
    1005                 :      36115 :         ds_put_char(s, ',');
    1006                 :            :     }
    1007                 :     220852 : }
    1008                 :            : 
    1009                 :            : static void
    1010                 :     110426 : format_flow_tunnel(struct ds *s, const struct match *match)
    1011                 :            : {
    1012                 :     110426 :     const struct flow_wildcards *wc = &match->wc;
    1013                 :     110426 :     const struct flow_tnl *tnl = &match->flow.tunnel;
    1014                 :            : 
    1015                 :     110426 :     format_be64_masked(s, "tun_id", tnl->tun_id, wc->masks.tunnel.tun_id);
    1016                 :     110426 :     format_ip_netmask(s, "tun_src", tnl->ip_src, wc->masks.tunnel.ip_src);
    1017                 :     110426 :     format_ip_netmask(s, "tun_dst", tnl->ip_dst, wc->masks.tunnel.ip_dst);
    1018                 :     110426 :     format_ipv6_netmask(s, "tun_ipv6_src", &tnl->ipv6_src,
    1019                 :            :                         &wc->masks.tunnel.ipv6_src);
    1020                 :     110426 :     format_ipv6_netmask(s, "tun_ipv6_dst", &tnl->ipv6_dst,
    1021                 :            :                         &wc->masks.tunnel.ipv6_dst);
    1022                 :            : 
    1023         [ +  + ]:     110426 :     if (wc->masks.tunnel.gbp_id) {
    1024                 :        145 :         format_be16_masked(s, "tun_gbp_id", tnl->gbp_id,
    1025                 :        145 :                            wc->masks.tunnel.gbp_id);
    1026                 :            :     }
    1027                 :            : 
    1028         [ +  + ]:     110426 :     if (wc->masks.tunnel.gbp_flags) {
    1029                 :        145 :         ds_put_format(s, "tun_gbp_flags=%#"PRIx8",", tnl->gbp_flags);
    1030                 :            :     }
    1031                 :            : 
    1032         [ +  + ]:     110426 :     if (wc->masks.tunnel.ip_tos) {
    1033                 :        172 :         ds_put_format(s, "tun_tos=%"PRIx8",", tnl->ip_tos);
    1034                 :            :     }
    1035         [ +  + ]:     110426 :     if (wc->masks.tunnel.ip_ttl) {
    1036                 :        143 :         ds_put_format(s, "tun_ttl=%"PRIu8",", tnl->ip_ttl);
    1037                 :            :     }
    1038         [ +  + ]:     110426 :     if (wc->masks.tunnel.flags & FLOW_TNL_F_MASK) {
    1039                 :        174 :         format_flags_masked(s, "tun_flags", flow_tun_flag_to_string,
    1040                 :        174 :                             tnl->flags & FLOW_TNL_F_MASK,
    1041                 :        174 :                             wc->masks.tunnel.flags & FLOW_TNL_F_MASK,
    1042                 :            :                             FLOW_TNL_F_MASK);
    1043                 :        174 :         ds_put_char(s, ',');
    1044                 :            :     }
    1045                 :     110426 :     tun_metadata_match_format(s, match);
    1046                 :     110426 : }
    1047                 :            : 
    1048                 :            : static void
    1049                 :         59 : format_ct_label_masked(struct ds *s, const ovs_u128 *key, const ovs_u128 *mask)
    1050                 :            : {
    1051         [ +  - ]:         59 :     if (!ovs_u128_is_zero(*mask)) {
    1052                 :         59 :         ovs_be128 value = hton128(*key);
    1053                 :         59 :         ds_put_format(s, "%sct_label=%s", colors.param, colors.end);
    1054                 :         59 :         ds_put_hex(s, &value, sizeof value);
    1055         [ +  + ]:         59 :         if (!is_all_ones(mask, sizeof(*mask))) {
    1056                 :         48 :             value = hton128(*mask);
    1057                 :         48 :             ds_put_char(s, '/');
    1058                 :         48 :             ds_put_hex(s, &value, sizeof value);
    1059                 :            :         }
    1060                 :         59 :         ds_put_char(s, ',');
    1061                 :            :     }
    1062                 :         59 : }
    1063                 :            : 
    1064                 :            : /* Appends a string representation of 'match' to 's'.  If 'priority' is
    1065                 :            :  * different from OFP_DEFAULT_PRIORITY, includes it in 's'. */
    1066                 :            : void
    1067                 :     110426 : match_format(const struct match *match, struct ds *s, int priority)
    1068                 :            : {
    1069                 :     110426 :     const struct flow_wildcards *wc = &match->wc;
    1070                 :     110426 :     size_t start_len = s->length;
    1071                 :     110426 :     const struct flow *f = &match->flow;
    1072                 :     110426 :     bool skip_type = false;
    1073                 :            : 
    1074                 :     110426 :     bool skip_proto = false;
    1075                 :            : 
    1076                 :            :     int i;
    1077                 :            : 
    1078                 :            :     BUILD_ASSERT_DECL(FLOW_WC_SEQ == 36);
    1079                 :            : 
    1080         [ +  + ]:     110426 :     if (priority != OFP_DEFAULT_PRIORITY) {
    1081                 :      39017 :         ds_put_format(s, "%spriority=%s%d,",
    1082                 :            :                       colors.special, colors.end, priority);
    1083                 :            :     }
    1084                 :            : 
    1085                 :     110426 :     format_uint32_masked(s, "pkt_mark", f->pkt_mark, wc->masks.pkt_mark);
    1086                 :            : 
    1087         [ +  + ]:     110426 :     if (wc->masks.recirc_id) {
    1088                 :       7763 :         format_uint32_masked(s, "recirc_id", f->recirc_id,
    1089                 :            :                              wc->masks.recirc_id);
    1090                 :            :     }
    1091                 :            : 
    1092         [ +  + ]:     110426 :     if (wc->masks.dp_hash) {
    1093                 :        257 :         format_uint32_masked(s, "dp_hash", f->dp_hash,
    1094                 :            :                              wc->masks.dp_hash);
    1095                 :            :     }
    1096                 :            : 
    1097         [ +  + ]:     110426 :     if (wc->masks.conj_id) {
    1098                 :        338 :         ds_put_format(s, "%sconj_id%s=%"PRIu32",",
    1099                 :            :                       colors.param, colors.end, f->conj_id);
    1100                 :            :     }
    1101                 :            : 
    1102         [ +  + ]:     110426 :     if (wc->masks.skb_priority) {
    1103                 :          5 :         ds_put_format(s, "%sskb_priority=%s%#"PRIx32",",
    1104                 :            :                       colors.param, colors.end, f->skb_priority);
    1105                 :            :     }
    1106                 :            : 
    1107         [ -  + ]:     110426 :     if (wc->masks.actset_output) {
    1108                 :          0 :         ds_put_format(s, "%sactset_output=%s", colors.param, colors.end);
    1109                 :          0 :         ofputil_format_port(f->actset_output, s);
    1110                 :          0 :         ds_put_char(s, ',');
    1111                 :            :     }
    1112                 :            : 
    1113         [ +  + ]:     110426 :     if (wc->masks.ct_state) {
    1114         [ +  + ]:        387 :         if (wc->masks.ct_state == UINT16_MAX) {
    1115                 :         29 :             ds_put_format(s, "%sct_state=%s", colors.param, colors.end);
    1116         [ +  - ]:         29 :             if (f->ct_state) {
    1117                 :         29 :                 format_flags(s, ct_state_to_string, f->ct_state, '|');
    1118                 :            :             } else {
    1119                 :         29 :                 ds_put_cstr(s, "0"); /* No state. */
    1120                 :            :             }
    1121                 :            :         } else {
    1122                 :        358 :             format_flags_masked(s, "ct_state", ct_state_to_string,
    1123                 :        716 :                                 f->ct_state, wc->masks.ct_state, UINT16_MAX);
    1124                 :            :         }
    1125                 :        387 :         ds_put_char(s, ',');
    1126                 :            :     }
    1127                 :            : 
    1128         [ +  + ]:     110426 :     if (wc->masks.ct_zone) {
    1129                 :         36 :         format_uint16_masked(s, "ct_zone", f->ct_zone, wc->masks.ct_zone);
    1130                 :            :     }
    1131                 :            : 
    1132         [ +  + ]:     110426 :     if (wc->masks.ct_mark) {
    1133                 :         25 :         format_uint32_masked(s, "ct_mark", f->ct_mark, wc->masks.ct_mark);
    1134                 :            :     }
    1135                 :            : 
    1136         [ +  + ]:     110426 :     if (!ovs_u128_is_zero(wc->masks.ct_label)) {
    1137                 :         59 :         format_ct_label_masked(s, &f->ct_label, &wc->masks.ct_label);
    1138                 :            :     }
    1139                 :            : 
    1140         [ +  + ]:     110426 :     if (wc->masks.dl_type) {
    1141                 :      28030 :         skip_type = true;
    1142         [ +  + ]:      28030 :         if (f->dl_type == htons(ETH_TYPE_IP)) {
    1143         [ +  + ]:      11256 :             if (wc->masks.nw_proto) {
    1144                 :       5465 :                 skip_proto = true;
    1145         [ +  + ]:       5465 :                 if (f->nw_proto == IPPROTO_ICMP) {
    1146                 :       3030 :                     ds_put_format(s, "%sicmp%s,", colors.value, colors.end);
    1147         [ -  + ]:       2435 :                 } else if (f->nw_proto == IPPROTO_IGMP) {
    1148                 :          0 :                     ds_put_format(s, "%sigmp%s,", colors.value, colors.end);
    1149         [ +  + ]:       2435 :                 } else if (f->nw_proto == IPPROTO_TCP) {
    1150                 :       1590 :                     ds_put_format(s, "%stcp%s,", colors.value, colors.end);
    1151         [ +  + ]:        845 :                 } else if (f->nw_proto == IPPROTO_UDP) {
    1152                 :        626 :                     ds_put_format(s, "%sudp%s,", colors.value, colors.end);
    1153         [ +  + ]:        219 :                 } else if (f->nw_proto == IPPROTO_SCTP) {
    1154                 :         33 :                     ds_put_format(s, "%ssctp%s,", colors.value, colors.end);
    1155                 :            :                 } else {
    1156                 :        186 :                     ds_put_format(s, "%sip%s,", colors.value, colors.end);
    1157                 :       5465 :                     skip_proto = false;
    1158                 :            :                 }
    1159                 :            :             } else {
    1160                 :      11256 :                 ds_put_format(s, "%sip%s,", colors.value, colors.end);
    1161                 :            :             }
    1162         [ +  + ]:      16774 :         } else if (f->dl_type == htons(ETH_TYPE_IPV6)) {
    1163         [ +  + ]:       6253 :             if (wc->masks.nw_proto) {
    1164                 :       2693 :                 skip_proto = true;
    1165         [ +  + ]:       2693 :                 if (f->nw_proto == IPPROTO_ICMPV6) {
    1166                 :       2613 :                     ds_put_format(s, "%sicmp6%s,", colors.value, colors.end);
    1167         [ +  + ]:         80 :                 } else if (f->nw_proto == IPPROTO_TCP) {
    1168                 :         27 :                     ds_put_format(s, "%stcp6%s,", colors.value, colors.end);
    1169         [ +  + ]:         53 :                 } else if (f->nw_proto == IPPROTO_UDP) {
    1170                 :         45 :                     ds_put_format(s, "%sudp6%s,", colors.value, colors.end);
    1171         [ -  + ]:          8 :                 } else if (f->nw_proto == IPPROTO_SCTP) {
    1172                 :          0 :                     ds_put_format(s, "%ssctp6%s,", colors.value, colors.end);
    1173                 :            :                 } else {
    1174                 :          8 :                     ds_put_format(s, "%sipv6%s,", colors.value, colors.end);
    1175                 :       2693 :                     skip_proto = false;
    1176                 :            :                 }
    1177                 :            :             } else {
    1178                 :       6253 :                 ds_put_format(s, "%sipv6%s,", colors.value, colors.end);
    1179                 :            :             }
    1180         [ +  + ]:      10521 :         } else if (f->dl_type == htons(ETH_TYPE_ARP)) {
    1181                 :       3403 :             ds_put_format(s, "%sarp%s,", colors.value, colors.end);
    1182         [ +  + ]:       7118 :         } else if (f->dl_type == htons(ETH_TYPE_RARP)) {
    1183                 :         12 :             ds_put_format(s, "%srarp%s,", colors.value, colors.end);
    1184         [ +  + ]:       7106 :         } else if (f->dl_type == htons(ETH_TYPE_MPLS)) {
    1185                 :        207 :             ds_put_format(s, "%smpls%s,", colors.value, colors.end);
    1186         [ +  + ]:       6899 :         } else if (f->dl_type == htons(ETH_TYPE_MPLS_MCAST)) {
    1187                 :         67 :             ds_put_format(s, "%smplsm%s,", colors.value, colors.end);
    1188                 :            :         } else {
    1189                 :       6832 :             skip_type = false;
    1190                 :            :         }
    1191                 :            :     }
    1192         [ +  + ]:    1877242 :     for (i = 0; i < FLOW_N_REGS; i++) {
    1193                 :            :         #define REGNAME_LEN 20
    1194                 :            :         char regname[REGNAME_LEN];
    1195         [ -  + ]:    1766816 :         if (snprintf(regname, REGNAME_LEN, "reg%d", i) >= REGNAME_LEN) {
    1196                 :          0 :             strcpy(regname, "reg?");
    1197                 :            :         }
    1198                 :    1766816 :         format_uint32_masked(s, regname, f->regs[i], wc->masks.regs[i]);
    1199                 :            :     }
    1200                 :            : 
    1201                 :     110426 :     format_flow_tunnel(s, match);
    1202                 :            : 
    1203                 :     110426 :     format_be64_masked(s, "metadata", f->metadata, wc->masks.metadata);
    1204                 :            : 
    1205         [ +  + ]:     110426 :     if (wc->masks.in_port.ofp_port) {
    1206                 :      21854 :         ds_put_format(s, "%sin_port=%s", colors.param, colors.end);
    1207                 :      21854 :         ofputil_format_port(f->in_port.ofp_port, s);
    1208                 :      21854 :         ds_put_char(s, ',');
    1209                 :            :     }
    1210         [ +  + ]:     110426 :     if (wc->masks.vlan_tci) {
    1211                 :      14334 :         ovs_be16 vid_mask = wc->masks.vlan_tci & htons(VLAN_VID_MASK);
    1212                 :      14334 :         ovs_be16 pcp_mask = wc->masks.vlan_tci & htons(VLAN_PCP_MASK);
    1213                 :      14334 :         ovs_be16 cfi = wc->masks.vlan_tci & htons(VLAN_CFI);
    1214                 :            : 
    1215 [ +  + ][ +  + ]:      14334 :         if (cfi && f->vlan_tci & htons(VLAN_CFI)
    1216 [ +  + ][ +  + ]:       7723 :             && (!vid_mask || vid_mask == htons(VLAN_VID_MASK))
    1217 [ +  + ][ +  + ]:       7722 :             && (!pcp_mask || pcp_mask == htons(VLAN_PCP_MASK))
    1218 [ +  + ][ +  + ]:       7721 :             && (vid_mask || pcp_mask)) {
    1219         [ +  + ]:       7195 :             if (vid_mask) {
    1220                 :       7175 :                 ds_put_format(s, "%sdl_vlan=%s%"PRIu16",", colors.param,
    1221                 :       7175 :                               colors.end, vlan_tci_to_vid(f->vlan_tci));
    1222                 :            :             }
    1223         [ +  + ]:       7522 :             if (pcp_mask) {
    1224                 :        327 :                 ds_put_format(s, "%sdl_vlan_pcp=%s%d,", colors.param,
    1225                 :        327 :                               colors.end, vlan_tci_to_pcp(f->vlan_tci));
    1226                 :            :             }
    1227         [ +  + ]:       7139 :         } else if (wc->masks.vlan_tci == htons(0xffff)) {
    1228                 :       6322 :             ds_put_format(s, "%svlan_tci=%s0x%04"PRIx16",", colors.param,
    1229                 :       6322 :                           colors.end, ntohs(f->vlan_tci));
    1230                 :            :         } else {
    1231                 :        817 :             ds_put_format(s, "%svlan_tci=%s0x%04"PRIx16"/0x%04"PRIx16",",
    1232                 :            :                           colors.param, colors.end,
    1233                 :        817 :                           ntohs(f->vlan_tci), ntohs(wc->masks.vlan_tci));
    1234                 :            :         }
    1235                 :            :     }
    1236                 :     110426 :     format_eth_masked(s, "dl_src", f->dl_src, wc->masks.dl_src);
    1237                 :     110426 :     format_eth_masked(s, "dl_dst", f->dl_dst, wc->masks.dl_dst);
    1238 [ +  + ][ +  + ]:     110426 :     if (!skip_type && wc->masks.dl_type) {
    1239                 :       6832 :         ds_put_format(s, "%sdl_type=%s0x%04"PRIx16",",
    1240                 :       6832 :                       colors.param, colors.end, ntohs(f->dl_type));
    1241                 :            :     }
    1242         [ +  + ]:     110426 :     if (f->dl_type == htons(ETH_TYPE_IPV6)) {
    1243                 :       6253 :         format_ipv6_netmask(s, "ipv6_src", &f->ipv6_src, &wc->masks.ipv6_src);
    1244                 :       6253 :         format_ipv6_netmask(s, "ipv6_dst", &f->ipv6_dst, &wc->masks.ipv6_dst);
    1245         [ +  + ]:       6253 :         if (wc->masks.ipv6_label) {
    1246         [ +  + ]:         58 :             if (wc->masks.ipv6_label == OVS_BE32_MAX) {
    1247                 :         57 :                 ds_put_format(s, "%sipv6_label=%s0x%05"PRIx32",",
    1248                 :            :                               colors.param, colors.end,
    1249                 :            :                               ntohl(f->ipv6_label));
    1250                 :            :             } else {
    1251                 :       6253 :                 ds_put_format(s, "%sipv6_label=%s0x%05"PRIx32"/0x%05"PRIx32",",
    1252                 :            :                               colors.param, colors.end, ntohl(f->ipv6_label),
    1253                 :            :                               ntohl(wc->masks.ipv6_label));
    1254                 :            :             }
    1255                 :            :         }
    1256   [ +  +  +  + ]:     204943 :     } else if (f->dl_type == htons(ETH_TYPE_ARP) ||
    1257                 :     100770 :                f->dl_type == htons(ETH_TYPE_RARP)) {
    1258                 :       3415 :         format_ip_netmask(s, "arp_spa", f->nw_src, wc->masks.nw_src);
    1259                 :       3415 :         format_ip_netmask(s, "arp_tpa", f->nw_dst, wc->masks.nw_dst);
    1260                 :            :     } else {
    1261                 :     100758 :         format_ip_netmask(s, "nw_src", f->nw_src, wc->masks.nw_src);
    1262                 :     100758 :         format_ip_netmask(s, "nw_dst", f->nw_dst, wc->masks.nw_dst);
    1263                 :            :     }
    1264 [ +  + ][ +  + ]:     110426 :     if (!skip_proto && wc->masks.nw_proto) {
    1265   [ +  +  +  + ]:       3234 :         if (f->dl_type == htons(ETH_TYPE_ARP) ||
    1266                 :        209 :             f->dl_type == htons(ETH_TYPE_RARP)) {
    1267                 :       2828 :             ds_put_format(s, "%sarp_op=%s%"PRIu8",",
    1268                 :       2828 :                           colors.param, colors.end, f->nw_proto);
    1269                 :            :         } else {
    1270                 :        197 :             ds_put_format(s, "%snw_proto=%s%"PRIu8",",
    1271                 :        197 :                           colors.param, colors.end, f->nw_proto);
    1272                 :            :         }
    1273                 :            :     }
    1274   [ +  +  +  + ]:     217449 :     if (f->dl_type == htons(ETH_TYPE_ARP) ||
    1275                 :     107023 :         f->dl_type == htons(ETH_TYPE_RARP)) {
    1276                 :       3415 :         format_eth_masked(s, "arp_sha", f->arp_sha, wc->masks.arp_sha);
    1277                 :       3415 :         format_eth_masked(s, "arp_tha", f->arp_tha, wc->masks.arp_tha);
    1278                 :            :     }
    1279         [ +  + ]:     110426 :     if (wc->masks.nw_tos & IP_DSCP_MASK) {
    1280                 :       4148 :         ds_put_format(s, "%snw_tos=%s%"PRIu8",",
    1281                 :       4148 :                       colors.param, colors.end, f->nw_tos & IP_DSCP_MASK);
    1282                 :            :     }
    1283         [ +  + ]:     110426 :     if (wc->masks.nw_tos & IP_ECN_MASK) {
    1284                 :       4155 :         ds_put_format(s, "%snw_ecn=%s%"PRIu8",",
    1285                 :       4155 :                       colors.param, colors.end, f->nw_tos & IP_ECN_MASK);
    1286                 :            :     }
    1287         [ +  + ]:     110426 :     if (wc->masks.nw_ttl) {
    1288                 :       6575 :         ds_put_format(s, "%snw_ttl=%s%"PRIu8",",
    1289                 :       6575 :                       colors.param, colors.end, f->nw_ttl);
    1290                 :            :     }
    1291         [ +  + ]:     110426 :     if (wc->masks.mpls_lse[0] & htonl(MPLS_LABEL_MASK)) {
    1292                 :        256 :         ds_put_format(s, "%smpls_label=%s%"PRIu32",", colors.param,
    1293                 :            :                       colors.end, mpls_lse_to_label(f->mpls_lse[0]));
    1294                 :            :     }
    1295         [ +  + ]:     110426 :     if (wc->masks.mpls_lse[0] & htonl(MPLS_TC_MASK)) {
    1296                 :        231 :         ds_put_format(s, "%smpls_tc=%s%"PRIu8",", colors.param, colors.end,
    1297                 :        231 :                       mpls_lse_to_tc(f->mpls_lse[0]));
    1298                 :            :     }
    1299         [ +  + ]:     110426 :     if (wc->masks.mpls_lse[0] & htonl(MPLS_TTL_MASK)) {
    1300                 :        229 :         ds_put_format(s, "%smpls_ttl=%s%"PRIu8",", colors.param, colors.end,
    1301                 :        229 :                       mpls_lse_to_ttl(f->mpls_lse[0]));
    1302                 :            :     }
    1303         [ +  + ]:     110426 :     if (wc->masks.mpls_lse[0] & htonl(MPLS_BOS_MASK)) {
    1304                 :        238 :         ds_put_format(s, "%smpls_bos=%s%"PRIu8",", colors.param, colors.end,
    1305                 :        238 :                       mpls_lse_to_bos(f->mpls_lse[0]));
    1306                 :            :     }
    1307                 :     110426 :     format_be32_masked(s, "mpls_lse1", f->mpls_lse[1], wc->masks.mpls_lse[1]);
    1308                 :     110426 :     format_be32_masked(s, "mpls_lse2", f->mpls_lse[2], wc->masks.mpls_lse[2]);
    1309                 :            : 
    1310   [ +  -  -  + ]:     110426 :     switch (wc->masks.nw_frag) {
    1311                 :            :     case FLOW_NW_FRAG_ANY | FLOW_NW_FRAG_LATER:
    1312         [ +  + ]:       2116 :         ds_put_format(s, "%snw_frag=%s%s,", colors.param, colors.end,
    1313                 :       1058 :                       f->nw_frag & FLOW_NW_FRAG_ANY
    1314         [ +  + ]:         18 :                       ? (f->nw_frag & FLOW_NW_FRAG_LATER ? "later" : "first")
    1315         [ -  + ]:       1040 :                       : (f->nw_frag & FLOW_NW_FRAG_LATER ? "<error>" : "no"));
    1316                 :       1058 :         break;
    1317                 :            : 
    1318                 :            :     case FLOW_NW_FRAG_ANY:
    1319         [ #  # ]:          0 :         ds_put_format(s, "%snw_frag=%s%s,", colors.param, colors.end,
    1320                 :          0 :                       f->nw_frag & FLOW_NW_FRAG_ANY ? "yes" : "no");
    1321                 :          0 :         break;
    1322                 :            : 
    1323                 :            :     case FLOW_NW_FRAG_LATER:
    1324         [ #  # ]:          0 :         ds_put_format(s, "%snw_frag=%s%s,", colors.param, colors.end,
    1325                 :          0 :                       f->nw_frag & FLOW_NW_FRAG_LATER ? "later" : "not_later");
    1326                 :          0 :         break;
    1327                 :            :     }
    1328 [ +  + ][ +  + ]:     110426 :     if (f->dl_type == htons(ETH_TYPE_IP) &&
    1329                 :      11256 :         f->nw_proto == IPPROTO_ICMP) {
    1330                 :       3030 :         format_be16_masked(s, "icmp_type", f->tp_src, wc->masks.tp_src);
    1331                 :       3030 :         format_be16_masked(s, "icmp_code", f->tp_dst, wc->masks.tp_dst);
    1332 [ +  + ][ -  + ]:     107396 :     } else if (f->dl_type == htons(ETH_TYPE_IP) &&
    1333                 :       8226 :                f->nw_proto == IPPROTO_IGMP) {
    1334                 :          0 :         format_be16_masked(s, "igmp_type", f->tp_src, wc->masks.tp_src);
    1335                 :          0 :         format_be16_masked(s, "igmp_code", f->tp_dst, wc->masks.tp_dst);
    1336 [ +  + ][ +  + ]:     107396 :     } else if (f->dl_type == htons(ETH_TYPE_IPV6) &&
    1337                 :       6253 :                f->nw_proto == IPPROTO_ICMPV6) {
    1338                 :       2613 :         format_be16_masked(s, "icmp_type", f->tp_src, wc->masks.tp_src);
    1339                 :       2613 :         format_be16_masked(s, "icmp_code", f->tp_dst, wc->masks.tp_dst);
    1340                 :       2613 :         format_ipv6_netmask(s, "nd_target", &f->nd_target,
    1341                 :            :                             &wc->masks.nd_target);
    1342                 :       2613 :         format_eth_masked(s, "nd_sll", f->arp_sha, wc->masks.arp_sha);
    1343                 :       2613 :         format_eth_masked(s, "nd_tll", f->arp_tha, wc->masks.arp_tha);
    1344                 :            :     } else {
    1345                 :     104783 :         format_be16_masked(s, "tp_src", f->tp_src, wc->masks.tp_src);
    1346                 :     104783 :         format_be16_masked(s, "tp_dst", f->tp_dst, wc->masks.tp_dst);
    1347                 :            :     }
    1348 [ +  + ][ +  + ]:     110426 :     if (is_ip_any(f) && f->nw_proto == IPPROTO_TCP && wc->masks.tcp_flags) {
                 [ +  + ]
    1349                 :        786 :         format_flags_masked(s, "tcp_flags", packet_tcp_flag_to_string,
    1350                 :        786 :                             ntohs(f->tcp_flags), TCP_FLAGS(wc->masks.tcp_flags),
    1351                 :        786 :                             TCP_FLAGS(OVS_BE16_MAX));
    1352                 :            :     }
    1353                 :            : 
    1354         [ +  + ]:     110426 :     if (s->length > start_len) {
    1355                 :     108927 :         ds_chomp(s, ',');
    1356                 :            :     }
    1357                 :     110426 : }
    1358                 :            : 
    1359                 :            : /* Converts 'match' to a string and returns the string.  If 'priority' is
    1360                 :            :  * different from OFP_DEFAULT_PRIORITY, includes it in the string.  The caller
    1361                 :            :  * must free the string (with free()). */
    1362                 :            : char *
    1363                 :        153 : match_to_string(const struct match *match, int priority)
    1364                 :            : {
    1365                 :        153 :     struct ds s = DS_EMPTY_INITIALIZER;
    1366                 :        153 :     match_format(match, &s, priority);
    1367                 :        153 :     return ds_steal_cstr(&s);
    1368                 :            : }
    1369                 :            : 
    1370                 :            : void
    1371                 :         78 : match_print(const struct match *match)
    1372                 :            : {
    1373                 :         78 :     char *s = match_to_string(match, OFP_DEFAULT_PRIORITY);
    1374                 :         78 :     puts(s);
    1375                 :         78 :     free(s);
    1376                 :         78 : }
    1377                 :            : 
    1378                 :            : /* Initializes 'dst' as a copy of 'src'.  The caller must eventually free 'dst'
    1379                 :            :  * with minimatch_destroy(). */
    1380                 :            : void
    1381                 :     499437 : minimatch_init(struct minimatch *dst, const struct match *src)
    1382                 :            : {
    1383                 :            :     struct miniflow tmp;
    1384                 :            : 
    1385                 :     499437 :     miniflow_map_init(&tmp, &src->wc.masks);
    1386                 :            :     /* Allocate two consecutive miniflows. */
    1387                 :     499437 :     miniflow_alloc(dst->flows, 2, &tmp);
    1388                 :     499437 :     miniflow_init(dst->flow, &src->flow);
    1389                 :     499437 :     minimask_init(dst->mask, &src->wc);
    1390                 :     499437 : }
    1391                 :            : 
    1392                 :            : /* Initializes 'dst' as a copy of 'src'.  The caller must eventually free 'dst'
    1393                 :            :  * with minimatch_destroy(). */
    1394                 :            : void
    1395                 :      41095 : minimatch_clone(struct minimatch *dst, const struct minimatch *src)
    1396                 :            : {
    1397                 :            :     /* Allocate two consecutive miniflows. */
    1398                 :      41095 :     size_t data_size = miniflow_alloc(dst->flows, 2, &src->mask->masks);
    1399                 :            : 
    1400                 :      41095 :     memcpy(miniflow_values(dst->flow),
    1401                 :      41095 :            miniflow_get_values(src->flow), data_size);
    1402                 :      41095 :     memcpy(miniflow_values(&dst->mask->masks),
    1403                 :      41095 :            miniflow_get_values(&src->mask->masks), data_size);
    1404                 :      41095 : }
    1405                 :            : 
    1406                 :            : /* Initializes 'dst' with the data in 'src', destroying 'src'.  The caller must
    1407                 :            :  * eventually free 'dst' with minimatch_destroy(). */
    1408                 :            : void
    1409                 :      32020 : minimatch_move(struct minimatch *dst, struct minimatch *src)
    1410                 :            : {
    1411                 :      32020 :     dst->flow = src->flow;
    1412                 :      32020 :     dst->mask = src->mask;
    1413                 :      32020 : }
    1414                 :            : 
    1415                 :            : /* Frees any memory owned by 'match'.  Does not free the storage in which
    1416                 :            :  * 'match' itself resides; the caller is responsible for that. */
    1417                 :            : void
    1418                 :     476689 : minimatch_destroy(struct minimatch *match)
    1419                 :            : {
    1420                 :     476689 :     free(match->flow);
    1421                 :     476689 : }
    1422                 :            : 
    1423                 :            : /* Initializes 'dst' as a copy of 'src'. */
    1424                 :            : void
    1425                 :  221575106 : minimatch_expand(const struct minimatch *src, struct match *dst)
    1426                 :            : {
    1427                 :  221575106 :     miniflow_expand(src->flow, &dst->flow);
    1428                 :  221575106 :     minimask_expand(src->mask, &dst->wc);
    1429                 :  221575106 :     memset(&dst->tun_md, 0, sizeof dst->tun_md);
    1430                 :  221575106 : }
    1431                 :            : 
    1432                 :            : /* Returns true if 'a' and 'b' match the same packets, false otherwise.  */
    1433                 :            : bool
    1434                 :      27823 : minimatch_equal(const struct minimatch *a, const struct minimatch *b)
    1435                 :            : {
    1436                 :      55646 :     return minimask_equal(a->mask, b->mask)
    1437 [ +  - ][ +  - ]:      27823 :         && miniflow_equal(a->flow, b->flow);
    1438                 :            : }
    1439                 :            : 
    1440                 :            : /* Returns true if 'target' satisifies 'match', that is, if each bit for which
    1441                 :            :  * 'match' specifies a particular value has the correct value in 'target'.
    1442                 :            :  *
    1443                 :            :  * This function is equivalent to miniflow_equal_flow_in_minimask(&match->flow,
    1444                 :            :  * target, &match->mask) but it is faster because of the invariant that
    1445                 :            :  * match->flow.map and match->mask.map are the same. */
    1446                 :            : bool
    1447                 :         80 : minimatch_matches_flow(const struct minimatch *match,
    1448                 :            :                        const struct flow *target)
    1449                 :            : {
    1450                 :         80 :     const uint64_t *flowp = miniflow_get_values(match->flow);
    1451                 :         80 :     const uint64_t *maskp = miniflow_get_values(&match->mask->masks);
    1452                 :            :     size_t idx;
    1453                 :            : 
    1454         [ +  + ]:        127 :     FLOWMAP_FOR_EACH_INDEX(idx, match->flow->map) {
    1455         [ +  + ]:        113 :         if ((*flowp++ ^ flow_u64_value(target, idx)) & *maskp++) {
    1456                 :         66 :             return false;
    1457                 :            :         }
    1458                 :            :     }
    1459                 :            : 
    1460                 :         80 :     return true;
    1461                 :            : }
    1462                 :            : 
    1463                 :            : /* Appends a string representation of 'match' to 's'.  If 'priority' is
    1464                 :            :  * different from OFP_DEFAULT_PRIORITY, includes it in 's'. */
    1465                 :            : void
    1466                 :       8790 : minimatch_format(const struct minimatch *match, struct ds *s, int priority)
    1467                 :            : {
    1468                 :            :     struct match megamatch;
    1469                 :            : 
    1470                 :       8790 :     minimatch_expand(match, &megamatch);
    1471                 :       8790 :     match_format(&megamatch, s, priority);
    1472                 :       8790 : }
    1473                 :            : 
    1474                 :            : /* Converts 'match' to a string and returns the string.  If 'priority' is
    1475                 :            :  * different from OFP_DEFAULT_PRIORITY, includes it in the string.  The caller
    1476                 :            :  * must free the string (with free()). */
    1477                 :            : char *
    1478                 :          0 : minimatch_to_string(const struct minimatch *match, int priority)
    1479                 :            : {
    1480                 :            :     struct match megamatch;
    1481                 :            : 
    1482                 :          0 :     minimatch_expand(match, &megamatch);
    1483                 :          0 :     return match_to_string(&megamatch, priority);
    1484                 :            : }

Generated by: LCOV version 1.12