LCOV - code coverage report
Current view: top level - ofproto - ofproto.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2822 3383 83.4 %
Date: 2016-09-14 01:02:56 Functions: 331 366 90.4 %
Branches: 1205 1867 64.5 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2009-2016 Nicira, Inc.
       3                 :            :  * Copyright (c) 2010 Jean Tourrilhes - HP-Labs.
       4                 :            :  *
       5                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
       6                 :            :  * you may not use this file except in compliance with the License.
       7                 :            :  * You may obtain a copy of the License at:
       8                 :            :  *
       9                 :            :  *     http://www.apache.org/licenses/LICENSE-2.0
      10                 :            :  *
      11                 :            :  * Unless required by applicable law or agreed to in writing, software
      12                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      13                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14                 :            :  * See the License for the specific language governing permissions and
      15                 :            :  * limitations under the License.
      16                 :            :  */
      17                 :            : 
      18                 :            : #include <config.h>
      19                 :            : #include <errno.h>
      20                 :            : #include <inttypes.h>
      21                 :            : #include <stdbool.h>
      22                 :            : #include <stdlib.h>
      23                 :            : #include <unistd.h>
      24                 :            : 
      25                 :            : #include "bitmap.h"
      26                 :            : #include "bundles.h"
      27                 :            : #include "byte-order.h"
      28                 :            : #include "classifier.h"
      29                 :            : #include "connectivity.h"
      30                 :            : #include "connmgr.h"
      31                 :            : #include "coverage.h"
      32                 :            : #include "dp-packet.h"
      33                 :            : #include "hash.h"
      34                 :            : #include "openvswitch/hmap.h"
      35                 :            : #include "netdev.h"
      36                 :            : #include "nx-match.h"
      37                 :            : #include "ofproto.h"
      38                 :            : #include "ofproto-provider.h"
      39                 :            : #include "openflow/nicira-ext.h"
      40                 :            : #include "openflow/openflow.h"
      41                 :            : #include "openvswitch/dynamic-string.h"
      42                 :            : #include "openvswitch/meta-flow.h"
      43                 :            : #include "openvswitch/ofp-actions.h"
      44                 :            : #include "openvswitch/ofp-errors.h"
      45                 :            : #include "openvswitch/ofp-msgs.h"
      46                 :            : #include "openvswitch/ofp-print.h"
      47                 :            : #include "openvswitch/ofp-util.h"
      48                 :            : #include "openvswitch/ofpbuf.h"
      49                 :            : #include "openvswitch/vlog.h"
      50                 :            : #include "ovs-rcu.h"
      51                 :            : #include "packets.h"
      52                 :            : #include "pinsched.h"
      53                 :            : #include "poll-loop.h"
      54                 :            : #include "random.h"
      55                 :            : #include "seq.h"
      56                 :            : #include "openvswitch/shash.h"
      57                 :            : #include "simap.h"
      58                 :            : #include "smap.h"
      59                 :            : #include "sset.h"
      60                 :            : #include "timeval.h"
      61                 :            : #include "tun-metadata.h"
      62                 :            : #include "unaligned.h"
      63                 :            : #include "unixctl.h"
      64                 :            : #include "util.h"
      65                 :            : 
      66                 :       1288 : VLOG_DEFINE_THIS_MODULE(ofproto);
      67                 :            : 
      68                 :      72544 : COVERAGE_DEFINE(ofproto_flush);
      69                 :      81040 : COVERAGE_DEFINE(ofproto_packet_out);
      70                 :      71878 : COVERAGE_DEFINE(ofproto_queue_req);
      71                 :     387982 : COVERAGE_DEFINE(ofproto_recv_openflow);
      72                 :      71668 : COVERAGE_DEFINE(ofproto_reinit_ports);
      73                 :     120166 : COVERAGE_DEFINE(ofproto_update_port);
      74                 :            : 
      75                 :            : /* Default fields to use for prefix tries in each flow table, unless something
      76                 :            :  * else is configured. */
      77                 :            : const enum mf_field_id default_prefix_fields[2] =
      78                 :            :     { MFF_IPV4_DST, MFF_IPV4_SRC };
      79                 :            : 
      80                 :            : /* oftable. */
      81                 :            : static void oftable_init(struct oftable *);
      82                 :            : static void oftable_destroy(struct oftable *);
      83                 :            : 
      84                 :            : static void oftable_set_name(struct oftable *, const char *name);
      85                 :            : 
      86                 :            : static enum ofperr evict_rules_from_table(struct oftable *)
      87                 :            :     OVS_REQUIRES(ofproto_mutex);
      88                 :            : static void oftable_configure_eviction(struct oftable *,
      89                 :            :                                        unsigned int eviction,
      90                 :            :                                        const struct mf_subfield *fields,
      91                 :            :                                        size_t n_fields)
      92                 :            :     OVS_REQUIRES(ofproto_mutex);
      93                 :            : 
      94                 :            : /* This is the only combination of OpenFlow eviction flags that OVS supports: a
      95                 :            :  * combination of OF1.4+ importance, the remaining lifetime of the flow, and
      96                 :            :  * fairness based on user-specified fields. */
      97                 :            : #define OFPROTO_EVICTION_FLAGS \
      98                 :            :     (OFPTMPEF14_OTHER | OFPTMPEF14_IMPORTANCE | OFPTMPEF14_LIFETIME)
      99                 :            : 
     100                 :            : /* A set of rules within a single OpenFlow table (oftable) that have the same
     101                 :            :  * values for the oftable's eviction_fields.  A rule to be evicted, when one is
     102                 :            :  * needed, is taken from the eviction group that contains the greatest number
     103                 :            :  * of rules.
     104                 :            :  *
     105                 :            :  * An oftable owns any number of eviction groups, each of which contains any
     106                 :            :  * number of rules.
     107                 :            :  *
     108                 :            :  * Membership in an eviction group is imprecise, based on the hash of the
     109                 :            :  * oftable's eviction_fields (in the eviction_group's id_node.hash member).
     110                 :            :  * That is, if two rules have different eviction_fields, but those
     111                 :            :  * eviction_fields hash to the same value, then they will belong to the same
     112                 :            :  * eviction_group anyway.
     113                 :            :  *
     114                 :            :  * (When eviction is not enabled on an oftable, we don't track any eviction
     115                 :            :  * groups, to save time and space.) */
     116                 :            : struct eviction_group {
     117                 :            :     struct hmap_node id_node;   /* In oftable's "eviction_groups_by_id". */
     118                 :            :     struct heap_node size_node; /* In oftable's "eviction_groups_by_size". */
     119                 :            :     struct heap rules;          /* Contains "struct rule"s. */
     120                 :            : };
     121                 :            : 
     122                 :            : static bool choose_rule_to_evict(struct oftable *table, struct rule **rulep)
     123                 :            :     OVS_REQUIRES(ofproto_mutex);
     124                 :            : static uint64_t rule_eviction_priority(struct ofproto *ofproto, struct rule *)
     125                 :            :     OVS_REQUIRES(ofproto_mutex);
     126                 :            : static void eviction_group_add_rule(struct rule *)
     127                 :            :     OVS_REQUIRES(ofproto_mutex);
     128                 :            : static void eviction_group_remove_rule(struct rule *)
     129                 :            :     OVS_REQUIRES(ofproto_mutex);
     130                 :            : 
     131                 :            : static void rule_criteria_init(struct rule_criteria *, uint8_t table_id,
     132                 :            :                                const struct match *match, int priority,
     133                 :            :                                ovs_version_t version,
     134                 :            :                                ovs_be64 cookie, ovs_be64 cookie_mask,
     135                 :            :                                ofp_port_t out_port, uint32_t out_group);
     136                 :            : static void rule_criteria_require_rw(struct rule_criteria *,
     137                 :            :                                      bool can_write_readonly);
     138                 :            : static void rule_criteria_destroy(struct rule_criteria *);
     139                 :            : 
     140                 :            : static enum ofperr collect_rules_loose(struct ofproto *,
     141                 :            :                                        const struct rule_criteria *,
     142                 :            :                                        struct rule_collection *);
     143                 :            : 
     144                 :            : struct learned_cookie {
     145                 :            :     union {
     146                 :            :         /* In struct ofproto's 'learned_cookies' hmap. */
     147                 :            :         struct hmap_node hmap_node OVS_GUARDED_BY(ofproto_mutex);
     148                 :            : 
     149                 :            :         /* In 'dead_cookies' list when removed from hmap. */
     150                 :            :         struct ovs_list list_node;
     151                 :            :     } u;
     152                 :            : 
     153                 :            :     /* Key. */
     154                 :            :     ovs_be64 cookie OVS_GUARDED_BY(ofproto_mutex);
     155                 :            :     uint8_t table_id OVS_GUARDED_BY(ofproto_mutex);
     156                 :            : 
     157                 :            :     /* Number of references from "learn" actions.
     158                 :            :      *
     159                 :            :      * When this drops to 0, all of the flows in 'table_id' with the specified
     160                 :            :      * 'cookie' are deleted. */
     161                 :            :     int n OVS_GUARDED_BY(ofproto_mutex);
     162                 :            : };
     163                 :            : 
     164                 :            : static const struct ofpact_learn *next_learn_with_delete(
     165                 :            :     const struct rule_actions *, const struct ofpact_learn *start);
     166                 :            : 
     167                 :            : static void learned_cookies_inc(struct ofproto *, const struct rule_actions *)
     168                 :            :     OVS_REQUIRES(ofproto_mutex);
     169                 :            : static void learned_cookies_dec(struct ofproto *, const struct rule_actions *,
     170                 :            :                                 struct ovs_list *dead_cookies)
     171                 :            :     OVS_REQUIRES(ofproto_mutex);
     172                 :            : static void learned_cookies_flush(struct ofproto *, struct ovs_list *dead_cookies)
     173                 :            :     OVS_REQUIRES(ofproto_mutex);
     174                 :            : 
     175                 :            : /* ofport. */
     176                 :            : static void ofport_destroy__(struct ofport *) OVS_EXCLUDED(ofproto_mutex);
     177                 :            : static void ofport_destroy(struct ofport *, bool del);
     178                 :            : static bool ofport_is_mtu_overridden(const struct ofproto *,
     179                 :            :                                      const struct ofport *);
     180                 :            : 
     181                 :            : static int update_port(struct ofproto *, const char *devname);
     182                 :            : static int init_ports(struct ofproto *);
     183                 :            : static void reinit_ports(struct ofproto *);
     184                 :            : 
     185                 :            : static long long int ofport_get_usage(const struct ofproto *,
     186                 :            :                                       ofp_port_t ofp_port);
     187                 :            : static void ofport_set_usage(struct ofproto *, ofp_port_t ofp_port,
     188                 :            :                              long long int last_used);
     189                 :            : static void ofport_remove_usage(struct ofproto *, ofp_port_t ofp_port);
     190                 :            : 
     191                 :            : /* Ofport usage.
     192                 :            :  *
     193                 :            :  * Keeps track of the currently used and recently used ofport values and is
     194                 :            :  * used to prevent immediate recycling of ofport values. */
     195                 :            : struct ofport_usage {
     196                 :            :     struct hmap_node hmap_node; /* In struct ofproto's "ofport_usage" hmap. */
     197                 :            :     ofp_port_t ofp_port;        /* OpenFlow port number. */
     198                 :            :     long long int last_used;    /* Last time the 'ofp_port' was used. LLONG_MAX
     199                 :            :                                    represents in-use ofports. */
     200                 :            : };
     201                 :            : 
     202                 :            : /* rule. */
     203                 :            : static void ofproto_rule_send_removed(struct rule *)
     204                 :            :         OVS_EXCLUDED(ofproto_mutex);
     205                 :            : static bool rule_is_readonly(const struct rule *);
     206                 :            : static void ofproto_rule_insert__(struct ofproto *, struct rule *)
     207                 :            :     OVS_REQUIRES(ofproto_mutex);
     208                 :            : static void ofproto_rule_remove__(struct ofproto *, struct rule *)
     209                 :            :     OVS_REQUIRES(ofproto_mutex);
     210                 :            : 
     211                 :            : /* The source of an OpenFlow request.
     212                 :            :  *
     213                 :            :  * A table modification request can be generated externally, via OpenFlow, or
     214                 :            :  * internally through a function call.  This structure indicates the source of
     215                 :            :  * an OpenFlow-generated table modification.  For an internal flow_mod, it
     216                 :            :  * isn't meaningful and thus supplied as NULL. */
     217                 :            : struct openflow_mod_requester {
     218                 :            :     struct ofconn *ofconn;      /* Connection on which flow_mod arrived. */
     219                 :            :     const struct ofp_header *request;
     220                 :            : };
     221                 :            : 
     222                 :            : /* OpenFlow. */
     223                 :            : static enum ofperr ofproto_rule_create(struct ofproto *, struct cls_rule *,
     224                 :            :                                        uint8_t table_id, ovs_be64 new_cookie,
     225                 :            :                                        uint16_t idle_timeout,
     226                 :            :                                        uint16_t hard_timeout,
     227                 :            :                                        enum ofputil_flow_mod_flags flags,
     228                 :            :                                        uint16_t importance,
     229                 :            :                                        const struct ofpact *ofpacts,
     230                 :            :                                        size_t ofpacts_len,
     231                 :            :                                        struct rule **new_rule)
     232                 :            :     OVS_NO_THREAD_SAFETY_ANALYSIS;
     233                 :            : 
     234                 :            : static void replace_rule_start(struct ofproto *, struct ofproto_flow_mod *,
     235                 :            :                                struct rule *old_rule, struct rule *new_rule)
     236                 :            :     OVS_REQUIRES(ofproto_mutex);
     237                 :            : 
     238                 :            : static void replace_rule_revert(struct ofproto *, struct rule *old_rule,
     239                 :            :                                 struct rule *new_rule)
     240                 :            :     OVS_REQUIRES(ofproto_mutex);
     241                 :            : 
     242                 :            : static void replace_rule_finish(struct ofproto *, struct ofproto_flow_mod *,
     243                 :            :                                 const struct openflow_mod_requester *,
     244                 :            :                                 struct rule *old_rule, struct rule *new_rule,
     245                 :            :                                 struct ovs_list *dead_cookies)
     246                 :            :     OVS_REQUIRES(ofproto_mutex);
     247                 :            : static void delete_flows__(struct rule_collection *,
     248                 :            :                            enum ofp_flow_removed_reason,
     249                 :            :                            const struct openflow_mod_requester *)
     250                 :            :     OVS_REQUIRES(ofproto_mutex);
     251                 :            : 
     252                 :            : static bool ofproto_group_exists(const struct ofproto *, uint32_t group_id);
     253                 :            : static void handle_openflow(struct ofconn *, const struct ofpbuf *);
     254                 :            : static enum ofperr ofproto_flow_mod_init(struct ofproto *,
     255                 :            :                                          struct ofproto_flow_mod *,
     256                 :            :                                          const struct ofputil_flow_mod *fm)
     257                 :            :     OVS_EXCLUDED(ofproto_mutex);
     258                 :            : static enum ofperr ofproto_flow_mod_start(struct ofproto *,
     259                 :            :                                           struct ofproto_flow_mod *)
     260                 :            :     OVS_REQUIRES(ofproto_mutex);
     261                 :            : static void ofproto_flow_mod_finish(struct ofproto *,
     262                 :            :                                     struct ofproto_flow_mod *,
     263                 :            :                                     const struct openflow_mod_requester *)
     264                 :            :     OVS_REQUIRES(ofproto_mutex);
     265                 :            : static enum ofperr handle_flow_mod__(struct ofproto *,
     266                 :            :                                      const struct ofputil_flow_mod *,
     267                 :            :                                      const struct openflow_mod_requester *)
     268                 :            :     OVS_EXCLUDED(ofproto_mutex);
     269                 :            : static void calc_duration(long long int start, long long int now,
     270                 :            :                           uint32_t *sec, uint32_t *nsec);
     271                 :            : 
     272                 :            : /* ofproto. */
     273                 :            : static uint64_t pick_datapath_id(const struct ofproto *);
     274                 :            : static uint64_t pick_fallback_dpid(void);
     275                 :            : static void ofproto_destroy__(struct ofproto *);
     276                 :            : static void update_mtu(struct ofproto *, struct ofport *);
     277                 :            : static void update_mtu_ofproto(struct ofproto *);
     278                 :            : static void meter_delete(struct ofproto *, uint32_t first, uint32_t last);
     279                 :            : static void meter_insert_rule(struct rule *);
     280                 :            : 
     281                 :            : /* unixctl. */
     282                 :            : static void ofproto_unixctl_init(void);
     283                 :            : 
     284                 :            : /* All registered ofproto classes, in probe order. */
     285                 :            : static const struct ofproto_class **ofproto_classes;
     286                 :            : static size_t n_ofproto_classes;
     287                 :            : static size_t allocated_ofproto_classes;
     288                 :            : 
     289                 :            : /* Global lock that protects all flow table operations. */
     290                 :            : struct ovs_mutex ofproto_mutex = OVS_MUTEX_INITIALIZER;
     291                 :            : 
     292                 :            : unsigned ofproto_flow_limit = OFPROTO_FLOW_LIMIT_DEFAULT;
     293                 :            : unsigned ofproto_max_idle = OFPROTO_MAX_IDLE_DEFAULT;
     294                 :            : 
     295                 :            : size_t n_handlers, n_revalidators;
     296                 :            : char *pmd_cpu_mask;
     297                 :            : 
     298                 :            : /* Map from datapath name to struct ofproto, for use by unixctl commands. */
     299                 :            : static struct hmap all_ofprotos = HMAP_INITIALIZER(&all_ofprotos);
     300                 :            : 
     301                 :            : /* Initial mappings of port to OpenFlow number mappings. */
     302                 :            : static struct shash init_ofp_ports = SHASH_INITIALIZER(&init_ofp_ports);
     303                 :            : 
     304                 :            : static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
     305                 :            : 
     306                 :            : /* The default value of true waits for flow restore. */
     307                 :            : static bool flow_restore_wait = true;
     308                 :            : 
     309                 :            : /* Must be called to initialize the ofproto library.
     310                 :            :  *
     311                 :            :  * The caller may pass in 'iface_hints', which contains an shash of
     312                 :            :  * "iface_hint" elements indexed by the interface's name.  The provider
     313                 :            :  * may use these hints to describe the startup configuration in order to
     314                 :            :  * reinitialize its state.  The caller owns the provided data, so a
     315                 :            :  * provider will make copies of anything required.  An ofproto provider
     316                 :            :  * will remove any existing state that is not described by the hint, and
     317                 :            :  * may choose to remove it all. */
     318                 :            : void
     319                 :        615 : ofproto_init(const struct shash *iface_hints)
     320                 :            : {
     321                 :            :     struct shash_node *node;
     322                 :            :     size_t i;
     323                 :            : 
     324                 :        615 :     ofproto_class_register(&ofproto_dpif_class);
     325                 :            : 
     326                 :            :     /* Make a local copy, since we don't own 'iface_hints' elements. */
     327 [ +  + ][ -  + ]:        624 :     SHASH_FOR_EACH(node, iface_hints) {
     328                 :          9 :         const struct iface_hint *orig_hint = node->data;
     329                 :          9 :         struct iface_hint *new_hint = xmalloc(sizeof *new_hint);
     330                 :          9 :         const char *br_type = ofproto_normalize_type(orig_hint->br_type);
     331                 :            : 
     332                 :          9 :         new_hint->br_name = xstrdup(orig_hint->br_name);
     333                 :          9 :         new_hint->br_type = xstrdup(br_type);
     334                 :          9 :         new_hint->ofp_port = orig_hint->ofp_port;
     335                 :            : 
     336                 :          9 :         shash_add(&init_ofp_ports, node->name, new_hint);
     337                 :            :     }
     338                 :            : 
     339         [ +  + ]:       1230 :     for (i = 0; i < n_ofproto_classes; i++) {
     340                 :        615 :         ofproto_classes[i]->init(&init_ofp_ports);
     341                 :            :     }
     342                 :            : 
     343                 :        615 :     ofproto_unixctl_init();
     344                 :        615 : }
     345                 :            : 
     346                 :            : /* 'type' should be a normalized datapath type, as returned by
     347                 :            :  * ofproto_normalize_type().  Returns the corresponding ofproto_class
     348                 :            :  * structure, or a null pointer if there is none registered for 'type'. */
     349                 :            : static const struct ofproto_class *
     350                 :     557537 : ofproto_class_find__(const char *type)
     351                 :            : {
     352                 :            :     size_t i;
     353                 :            : 
     354         [ +  + ]:     557543 :     for (i = 0; i < n_ofproto_classes; i++) {
     355                 :     557537 :         const struct ofproto_class *class = ofproto_classes[i];
     356                 :            :         struct sset types;
     357                 :            :         bool found;
     358                 :            : 
     359                 :     557537 :         sset_init(&types);
     360                 :     557537 :         class->enumerate_types(&types);
     361                 :     557537 :         found = sset_contains(&types, type);
     362                 :     557537 :         sset_destroy(&types);
     363                 :            : 
     364         [ +  + ]:     557537 :         if (found) {
     365                 :     557531 :             return class;
     366                 :            :         }
     367                 :            :     }
     368         [ +  - ]:          6 :     VLOG_WARN("unknown datapath type %s", type);
     369                 :          6 :     return NULL;
     370                 :            : }
     371                 :            : 
     372                 :            : /* Registers a new ofproto class.  After successful registration, new ofprotos
     373                 :            :  * of that type can be created using ofproto_create(). */
     374                 :            : int
     375                 :        615 : ofproto_class_register(const struct ofproto_class *new_class)
     376                 :            : {
     377                 :            :     size_t i;
     378                 :            : 
     379         [ -  + ]:        615 :     for (i = 0; i < n_ofproto_classes; i++) {
     380         [ #  # ]:          0 :         if (ofproto_classes[i] == new_class) {
     381                 :          0 :             return EEXIST;
     382                 :            :         }
     383                 :            :     }
     384                 :            : 
     385         [ +  - ]:        615 :     if (n_ofproto_classes >= allocated_ofproto_classes) {
     386                 :        615 :         ofproto_classes = x2nrealloc(ofproto_classes,
     387                 :            :                                      &allocated_ofproto_classes,
     388                 :            :                                      sizeof *ofproto_classes);
     389                 :            :     }
     390                 :        615 :     ofproto_classes[n_ofproto_classes++] = new_class;
     391                 :        615 :     return 0;
     392                 :            : }
     393                 :            : 
     394                 :            : /* Unregisters a datapath provider.  'type' must have been previously
     395                 :            :  * registered and not currently be in use by any ofprotos.  After
     396                 :            :  * unregistration new datapaths of that type cannot be opened using
     397                 :            :  * ofproto_create(). */
     398                 :            : int
     399                 :          0 : ofproto_class_unregister(const struct ofproto_class *class)
     400                 :            : {
     401                 :            :     size_t i;
     402                 :            : 
     403         [ #  # ]:          0 :     for (i = 0; i < n_ofproto_classes; i++) {
     404         [ #  # ]:          0 :         if (ofproto_classes[i] == class) {
     405         [ #  # ]:          0 :             for (i++; i < n_ofproto_classes; i++) {
     406                 :          0 :                 ofproto_classes[i - 1] = ofproto_classes[i];
     407                 :            :             }
     408                 :          0 :             n_ofproto_classes--;
     409                 :          0 :             return 0;
     410                 :            :         }
     411                 :            :     }
     412         [ #  # ]:          0 :     VLOG_WARN("attempted to unregister an ofproto class that is not "
     413                 :            :               "registered");
     414                 :          0 :     return EAFNOSUPPORT;
     415                 :            : }
     416                 :            : 
     417                 :            : /* Clears 'types' and enumerates all registered ofproto types into it.  The
     418                 :            :  * caller must first initialize the sset. */
     419                 :            : void
     420                 :     217642 : ofproto_enumerate_types(struct sset *types)
     421                 :            : {
     422                 :            :     size_t i;
     423                 :            : 
     424                 :     217642 :     sset_clear(types);
     425         [ +  + ]:     434031 :     for (i = 0; i < n_ofproto_classes; i++) {
     426                 :     216389 :         ofproto_classes[i]->enumerate_types(types);
     427                 :            :     }
     428                 :     217642 : }
     429                 :            : 
     430                 :            : /* Returns the fully spelled out name for the given ofproto 'type'.
     431                 :            :  *
     432                 :            :  * Normalized type string can be compared with strcmp().  Unnormalized type
     433                 :            :  * string might be the same even if they have different spellings. */
     434                 :            : const char *
     435                 :     553842 : ofproto_normalize_type(const char *type)
     436                 :            : {
     437 [ +  - ][ +  + ]:     553842 :     return type && type[0] ? type : "system";
     438                 :            : }
     439                 :            : 
     440                 :            : /* Clears 'names' and enumerates the names of all known created ofprotos with
     441                 :            :  * the given 'type'.  The caller must first initialize the sset.  Returns 0 if
     442                 :            :  * successful, otherwise a positive errno value.
     443                 :            :  *
     444                 :            :  * Some kinds of datapaths might not be practically enumerable.  This is not
     445                 :            :  * considered an error. */
     446                 :            : int
     447                 :       8408 : ofproto_enumerate_names(const char *type, struct sset *names)
     448                 :            : {
     449                 :       8408 :     const struct ofproto_class *class = ofproto_class_find__(type);
     450         [ +  - ]:       8408 :     return class ? class->enumerate_names(type, names) : EAFNOSUPPORT;
     451                 :            : }
     452                 :            : 
     453                 :            : static void
     454                 :      41304 : ofproto_bump_tables_version(struct ofproto *ofproto)
     455                 :            : {
     456                 :      41304 :     ++ofproto->tables_version;
     457                 :      41304 :     ofproto->ofproto_class->set_tables_version(ofproto,
     458                 :            :                                                ofproto->tables_version);
     459                 :      41304 : }
     460                 :            : 
     461                 :            : int
     462                 :        752 : ofproto_create(const char *datapath_name, const char *datapath_type,
     463                 :            :                struct ofproto **ofprotop)
     464                 :            : {
     465                 :            :     const struct ofproto_class *class;
     466                 :            :     struct ofproto *ofproto;
     467                 :            :     int error;
     468                 :            :     int i;
     469                 :            : 
     470                 :        752 :     *ofprotop = NULL;
     471                 :            : 
     472                 :        752 :     datapath_type = ofproto_normalize_type(datapath_type);
     473                 :        752 :     class = ofproto_class_find__(datapath_type);
     474         [ +  + ]:        752 :     if (!class) {
     475         [ +  - ]:          3 :         VLOG_WARN("could not create datapath %s of unknown type %s",
     476                 :            :                   datapath_name, datapath_type);
     477                 :          3 :         return EAFNOSUPPORT;
     478                 :            :     }
     479                 :            : 
     480                 :        749 :     ofproto = class->alloc();
     481         [ -  + ]:        749 :     if (!ofproto) {
     482         [ #  # ]:          0 :         VLOG_ERR("failed to allocate datapath %s of type %s",
     483                 :            :                  datapath_name, datapath_type);
     484                 :          0 :         return ENOMEM;
     485                 :            :     }
     486                 :            : 
     487                 :            :     /* Initialize. */
     488                 :        749 :     ovs_mutex_lock(&ofproto_mutex);
     489                 :        749 :     memset(ofproto, 0, sizeof *ofproto);
     490                 :        749 :     ofproto->ofproto_class = class;
     491                 :        749 :     ofproto->name = xstrdup(datapath_name);
     492                 :        749 :     ofproto->type = xstrdup(datapath_type);
     493                 :        749 :     hmap_insert(&all_ofprotos, &ofproto->hmap_node,
     494                 :            :                 hash_string(ofproto->name, 0));
     495                 :        749 :     ofproto->datapath_id = 0;
     496                 :        749 :     ofproto->forward_bpdu = false;
     497                 :        749 :     ofproto->fallback_dpid = pick_fallback_dpid();
     498                 :        749 :     ofproto->mfr_desc = NULL;
     499                 :        749 :     ofproto->hw_desc = NULL;
     500                 :        749 :     ofproto->sw_desc = NULL;
     501                 :        749 :     ofproto->serial_desc = NULL;
     502                 :        749 :     ofproto->dp_desc = NULL;
     503                 :        749 :     ofproto->frag_handling = OFPUTIL_FRAG_NORMAL;
     504                 :        749 :     hmap_init(&ofproto->ports);
     505                 :        749 :     hmap_init(&ofproto->ofport_usage);
     506                 :        749 :     shash_init(&ofproto->port_by_name);
     507                 :        749 :     simap_init(&ofproto->ofp_requests);
     508                 :        749 :     ofproto->max_ports = ofp_to_u16(OFPP_MAX);
     509                 :        749 :     ofproto->eviction_group_timer = LLONG_MIN;
     510                 :        749 :     ofproto->tables = NULL;
     511                 :        749 :     ofproto->n_tables = 0;
     512                 :        749 :     ofproto->tables_version = OVS_VERSION_MIN;
     513                 :        749 :     hindex_init(&ofproto->cookies);
     514                 :        749 :     hmap_init(&ofproto->learned_cookies);
     515                 :        749 :     ovs_list_init(&ofproto->expirable);
     516                 :        749 :     ofproto->connmgr = connmgr_create(ofproto, datapath_name, datapath_name);
     517                 :        749 :     ofproto->min_mtu = INT_MAX;
     518                 :        749 :     cmap_init(&ofproto->groups);
     519                 :        749 :     ovs_mutex_unlock(&ofproto_mutex);
     520                 :        749 :     ofproto->ogf.types = 0xf;
     521                 :        749 :     ofproto->ogf.capabilities = OFPGFC_CHAINING | OFPGFC_SELECT_LIVENESS |
     522                 :            :                                 OFPGFC_SELECT_WEIGHT;
     523         [ +  + ]:       3745 :     for (i = 0; i < 4; i++) {
     524                 :       2996 :         ofproto->ogf.max_groups[i] = OFPG_MAX;
     525                 :       2996 :         ofproto->ogf.ofpacts[i] = (UINT64_C(1) << N_OFPACTS) - 1;
     526                 :            :     }
     527                 :        749 :     tun_metadata_init();
     528                 :            : 
     529                 :        749 :     error = ofproto->ofproto_class->construct(ofproto);
     530         [ -  + ]:        749 :     if (error) {
     531         [ #  # ]:          0 :         VLOG_ERR("failed to open datapath %s: %s",
     532                 :            :                  datapath_name, ovs_strerror(error));
     533                 :          0 :         connmgr_destroy(ofproto->connmgr);
     534                 :          0 :         ofproto_destroy__(ofproto);
     535                 :          0 :         return error;
     536                 :            :     }
     537                 :            : 
     538                 :            :     /* Check that hidden tables, if any, are at the end. */
     539         [ -  + ]:        749 :     ovs_assert(ofproto->n_tables);
     540         [ +  + ]:     190995 :     for (i = 0; i + 1 < ofproto->n_tables; i++) {
     541                 :     190246 :         enum oftable_flags flags = ofproto->tables[i].flags;
     542                 :     190246 :         enum oftable_flags next_flags = ofproto->tables[i + 1].flags;
     543                 :            : 
     544 [ -  + ][ #  # ]:     190246 :         ovs_assert(!(flags & OFTABLE_HIDDEN) || next_flags & OFTABLE_HIDDEN);
     545                 :            :     }
     546                 :            : 
     547                 :        749 :     ofproto->datapath_id = pick_datapath_id(ofproto);
     548                 :        749 :     init_ports(ofproto);
     549                 :            : 
     550                 :            :     /* Initialize meters table. */
     551         [ -  + ]:        749 :     if (ofproto->ofproto_class->meter_get_features) {
     552                 :          0 :         ofproto->ofproto_class->meter_get_features(ofproto,
     553                 :            :                                                    &ofproto->meter_features);
     554                 :            :     } else {
     555                 :        749 :         memset(&ofproto->meter_features, 0, sizeof ofproto->meter_features);
     556                 :            :     }
     557                 :        749 :     ofproto->meters = xzalloc((ofproto->meter_features.max_meters + 1)
     558                 :            :                               * sizeof(struct meter *));
     559                 :            : 
     560                 :            :     /* Set the initial tables version. */
     561                 :        749 :     ofproto_bump_tables_version(ofproto);
     562                 :            : 
     563                 :        749 :     *ofprotop = ofproto;
     564                 :        749 :     return 0;
     565                 :            : }
     566                 :            : 
     567                 :            : /* Must be called (only) by an ofproto implementation in its constructor
     568                 :            :  * function.  See the large comment on 'construct' in struct ofproto_class for
     569                 :            :  * details. */
     570                 :            : void
     571                 :        749 : ofproto_init_tables(struct ofproto *ofproto, int n_tables)
     572                 :            : {
     573                 :            :     struct oftable *table;
     574                 :            : 
     575         [ -  + ]:        749 :     ovs_assert(!ofproto->n_tables);
     576 [ +  - ][ -  + ]:        749 :     ovs_assert(n_tables >= 1 && n_tables <= 255);
     577                 :            : 
     578                 :        749 :     ofproto->n_tables = n_tables;
     579                 :        749 :     ofproto->tables = xmalloc(n_tables * sizeof *ofproto->tables);
     580         [ +  + ]:     191744 :     OFPROTO_FOR_EACH_TABLE (table, ofproto) {
     581                 :     190995 :         oftable_init(table);
     582                 :            :     }
     583                 :        749 : }
     584                 :            : 
     585                 :            : /* To be optionally called (only) by an ofproto implementation in its
     586                 :            :  * constructor function.  See the large comment on 'construct' in struct
     587                 :            :  * ofproto_class for details.
     588                 :            :  *
     589                 :            :  * Sets the maximum number of ports to 'max_ports'.  The ofproto generic layer
     590                 :            :  * will then ensure that actions passed into the ofproto implementation will
     591                 :            :  * not refer to OpenFlow ports numbered 'max_ports' or higher.  If this
     592                 :            :  * function is not called, there will be no such restriction.
     593                 :            :  *
     594                 :            :  * Reserved ports numbered OFPP_MAX and higher are special and not subject to
     595                 :            :  * the 'max_ports' restriction. */
     596                 :            : void
     597                 :          0 : ofproto_init_max_ports(struct ofproto *ofproto, uint16_t max_ports)
     598                 :            : {
     599         [ #  # ]:          0 :     ovs_assert(max_ports <= ofp_to_u16(OFPP_MAX));
     600                 :          0 :     ofproto->max_ports = max_ports;
     601                 :          0 : }
     602                 :            : 
     603                 :            : uint64_t
     604                 :       4714 : ofproto_get_datapath_id(const struct ofproto *ofproto)
     605                 :            : {
     606                 :       4714 :     return ofproto->datapath_id;
     607                 :            : }
     608                 :            : 
     609                 :            : void
     610                 :        749 : ofproto_set_datapath_id(struct ofproto *p, uint64_t datapath_id)
     611                 :            : {
     612                 :        749 :     uint64_t old_dpid = p->datapath_id;
     613         [ -  + ]:        749 :     p->datapath_id = datapath_id ? datapath_id : pick_datapath_id(p);
     614         [ +  - ]:        749 :     if (p->datapath_id != old_dpid) {
     615                 :            :         /* Force all active connections to reconnect, since there is no way to
     616                 :            :          * notify a controller that the datapath ID has changed. */
     617                 :        749 :         ofproto_reconnect_controllers(p);
     618                 :            :     }
     619                 :        749 : }
     620                 :            : 
     621                 :            : void
     622                 :       4700 : ofproto_set_controllers(struct ofproto *p,
     623                 :            :                         const struct ofproto_controller *controllers,
     624                 :            :                         size_t n_controllers, uint32_t allowed_versions)
     625                 :            : {
     626                 :       4700 :     connmgr_set_controllers(p->connmgr, controllers, n_controllers,
     627                 :            :                             allowed_versions);
     628                 :       4700 : }
     629                 :            : 
     630                 :            : void
     631                 :       4700 : ofproto_set_fail_mode(struct ofproto *p, enum ofproto_fail_mode fail_mode)
     632                 :            : {
     633                 :       4700 :     connmgr_set_fail_mode(p->connmgr, fail_mode);
     634                 :       4700 : }
     635                 :            : 
     636                 :            : /* Drops the connections between 'ofproto' and all of its controllers, forcing
     637                 :            :  * them to reconnect. */
     638                 :            : void
     639                 :        749 : ofproto_reconnect_controllers(struct ofproto *ofproto)
     640                 :            : {
     641                 :        749 :     connmgr_reconnect(ofproto->connmgr);
     642                 :        749 : }
     643                 :            : 
     644                 :            : /* Sets the 'n' TCP port addresses in 'extras' as ones to which 'ofproto''s
     645                 :            :  * in-band control should guarantee access, in the same way that in-band
     646                 :            :  * control guarantees access to OpenFlow controllers. */
     647                 :            : void
     648                 :       4700 : ofproto_set_extra_in_band_remotes(struct ofproto *ofproto,
     649                 :            :                                   const struct sockaddr_in *extras, size_t n)
     650                 :            : {
     651                 :       4700 :     connmgr_set_extra_in_band_remotes(ofproto->connmgr, extras, n);
     652                 :       4700 : }
     653                 :            : 
     654                 :            : /* Sets the OpenFlow queue used by flows set up by in-band control on
     655                 :            :  * 'ofproto' to 'queue_id'.  If 'queue_id' is negative, then in-band control
     656                 :            :  * flows will use the default queue. */
     657                 :            : void
     658                 :       4700 : ofproto_set_in_band_queue(struct ofproto *ofproto, int queue_id)
     659                 :            : {
     660                 :       4700 :     connmgr_set_in_band_queue(ofproto->connmgr, queue_id);
     661                 :       4700 : }
     662                 :            : 
     663                 :            : /* Sets the number of flows at which eviction from the kernel flow table
     664                 :            :  * will occur. */
     665                 :            : void
     666                 :       4238 : ofproto_set_flow_limit(unsigned limit)
     667                 :            : {
     668                 :       4238 :     ofproto_flow_limit = limit;
     669                 :       4238 : }
     670                 :            : 
     671                 :            : /* Sets the maximum idle time for flows in the datapath before they are
     672                 :            :  * expired. */
     673                 :            : void
     674                 :       4238 : ofproto_set_max_idle(unsigned max_idle)
     675                 :            : {
     676                 :       4238 :     ofproto_max_idle = max_idle;
     677                 :       4238 : }
     678                 :            : 
     679                 :            : /* If forward_bpdu is true, the NORMAL action will forward frames with
     680                 :            :  * reserved (e.g. STP) destination Ethernet addresses. if forward_bpdu is false,
     681                 :            :  * the NORMAL action will drop these frames. */
     682                 :            : void
     683                 :       4700 : ofproto_set_forward_bpdu(struct ofproto *ofproto, bool forward_bpdu)
     684                 :            : {
     685                 :       4700 :     bool old_val = ofproto->forward_bpdu;
     686                 :       4700 :     ofproto->forward_bpdu = forward_bpdu;
     687         [ -  + ]:       4700 :     if (old_val != ofproto->forward_bpdu) {
     688         [ #  # ]:          0 :         if (ofproto->ofproto_class->forward_bpdu_changed) {
     689                 :          0 :             ofproto->ofproto_class->forward_bpdu_changed(ofproto);
     690                 :            :         }
     691                 :            :     }
     692                 :       4700 : }
     693                 :            : 
     694                 :            : /* Sets the MAC aging timeout for the OFPP_NORMAL action on 'ofproto' to
     695                 :            :  * 'idle_time', in seconds, and the maximum number of MAC table entries to
     696                 :            :  * 'max_entries'. */
     697                 :            : void
     698                 :       4700 : ofproto_set_mac_table_config(struct ofproto *ofproto, unsigned idle_time,
     699                 :            :                              size_t max_entries)
     700                 :            : {
     701         [ +  - ]:       4700 :     if (ofproto->ofproto_class->set_mac_table_config) {
     702                 :       4700 :         ofproto->ofproto_class->set_mac_table_config(ofproto, idle_time,
     703                 :            :                                                      max_entries);
     704                 :            :     }
     705                 :       4700 : }
     706                 :            : 
     707                 :            : /* Multicast snooping configuration. */
     708                 :            : 
     709                 :            : /* Configures multicast snooping on 'ofproto' using the settings
     710                 :            :  * defined in 's'.  If 's' is NULL, disables multicast snooping.
     711                 :            :  *
     712                 :            :  * Returns 0 if successful, otherwise a positive errno value. */
     713                 :            : int
     714                 :       4700 : ofproto_set_mcast_snooping(struct ofproto *ofproto,
     715                 :            :                            const struct ofproto_mcast_snooping_settings *s)
     716                 :            : {
     717                 :       4700 :     return (ofproto->ofproto_class->set_mcast_snooping
     718                 :       4700 :             ? ofproto->ofproto_class->set_mcast_snooping(ofproto, s)
     719         [ +  - ]:       4700 :             : EOPNOTSUPP);
     720                 :            : }
     721                 :            : 
     722                 :            : /* Configures multicast snooping flood settings on 'ofp_port' of 'ofproto'.
     723                 :            :  *
     724                 :            :  * Returns 0 if successful, otherwise a positive errno value.*/
     725                 :            : int
     726                 :          0 : ofproto_port_set_mcast_snooping(struct ofproto *ofproto, void *aux,
     727                 :            :                            const struct ofproto_mcast_snooping_port_settings *s)
     728                 :            : {
     729                 :          0 :     return (ofproto->ofproto_class->set_mcast_snooping_port
     730                 :          0 :             ? ofproto->ofproto_class->set_mcast_snooping_port(ofproto, aux, s)
     731         [ #  # ]:          0 :             : EOPNOTSUPP);
     732                 :            : }
     733                 :            : 
     734                 :            : void
     735                 :       4238 : ofproto_set_cpu_mask(const char *cmask)
     736                 :            : {
     737                 :       4238 :     free(pmd_cpu_mask);
     738                 :       4238 :     pmd_cpu_mask = nullable_xstrdup(cmask);
     739                 :       4238 : }
     740                 :            : 
     741                 :            : void
     742                 :       4238 : ofproto_set_threads(int n_handlers_, int n_revalidators_)
     743                 :            : {
     744         [ -  + ]:       4238 :     int threads = MAX(count_cpu_cores(), 2);
     745                 :            : 
     746                 :       4238 :     n_revalidators = MAX(n_revalidators_, 0);
     747                 :       4238 :     n_handlers = MAX(n_handlers_, 0);
     748                 :            : 
     749         [ +  + ]:       4238 :     if (!n_revalidators) {
     750         [ -  + ]:       4237 :         n_revalidators = n_handlers
     751                 :       4237 :             ? MAX(threads - (int) n_handlers, 1)
     752                 :       4237 :             : threads / 4 + 1;
     753                 :            :     }
     754                 :            : 
     755         [ +  - ]:       4238 :     if (!n_handlers) {
     756                 :       4238 :         n_handlers = MAX(threads - (int) n_revalidators, 1);
     757                 :            :     }
     758                 :       4238 : }
     759                 :            : 
     760                 :            : void
     761                 :       4700 : ofproto_set_dp_desc(struct ofproto *p, const char *dp_desc)
     762                 :            : {
     763                 :       4700 :     free(p->dp_desc);
     764                 :       4700 :     p->dp_desc = nullable_xstrdup(dp_desc);
     765                 :       4700 : }
     766                 :            : 
     767                 :            : int
     768                 :        749 : ofproto_set_snoops(struct ofproto *ofproto, const struct sset *snoops)
     769                 :            : {
     770                 :        749 :     return connmgr_set_snoops(ofproto->connmgr, snoops);
     771                 :            : }
     772                 :            : 
     773                 :            : int
     774                 :       4700 : ofproto_set_netflow(struct ofproto *ofproto,
     775                 :            :                     const struct netflow_options *nf_options)
     776                 :            : {
     777 [ +  + ][ -  + ]:       4700 :     if (nf_options && sset_is_empty(&nf_options->collectors)) {
     778                 :          0 :         nf_options = NULL;
     779                 :            :     }
     780                 :            : 
     781         [ +  - ]:       4700 :     if (ofproto->ofproto_class->set_netflow) {
     782                 :       4700 :         return ofproto->ofproto_class->set_netflow(ofproto, nf_options);
     783                 :            :     } else {
     784         [ #  # ]:          0 :         return nf_options ? EOPNOTSUPP : 0;
     785                 :            :     }
     786                 :            : }
     787                 :            : 
     788                 :            : int
     789                 :       4700 : ofproto_set_sflow(struct ofproto *ofproto,
     790                 :            :                   const struct ofproto_sflow_options *oso)
     791                 :            : {
     792 [ +  + ][ -  + ]:       4700 :     if (oso && sset_is_empty(&oso->targets)) {
     793                 :          0 :         oso = NULL;
     794                 :            :     }
     795                 :            : 
     796         [ +  - ]:       4700 :     if (ofproto->ofproto_class->set_sflow) {
     797                 :       4700 :         return ofproto->ofproto_class->set_sflow(ofproto, oso);
     798                 :            :     } else {
     799         [ #  # ]:          0 :         return oso ? EOPNOTSUPP : 0;
     800                 :            :     }
     801                 :            : }
     802                 :            : 
     803                 :            : int
     804                 :       4700 : ofproto_set_ipfix(struct ofproto *ofproto,
     805                 :            :                   const struct ofproto_ipfix_bridge_exporter_options *bo,
     806                 :            :                   const struct ofproto_ipfix_flow_exporter_options *fo,
     807                 :            :                   size_t n_fo)
     808                 :            : {
     809         [ +  - ]:       4700 :     if (ofproto->ofproto_class->set_ipfix) {
     810                 :       4700 :         return ofproto->ofproto_class->set_ipfix(ofproto, bo, fo, n_fo);
     811                 :            :     } else {
     812 [ #  # ][ #  # ]:          0 :         return (bo || fo) ? EOPNOTSUPP : 0;
     813                 :            :     }
     814                 :            : }
     815                 :            : 
     816                 :            : static int
     817                 :          6 : ofproto_get_ipfix_stats(struct ofproto *ofproto,
     818                 :            :                         bool bridge_ipfix,
     819                 :            :                         struct ovs_list *replies)
     820                 :            : {
     821                 :            :     int error;
     822                 :            : 
     823         [ +  - ]:          6 :     if (ofproto->ofproto_class->get_ipfix_stats) {
     824                 :          6 :         error = ofproto->ofproto_class->get_ipfix_stats(ofproto,
     825                 :            :                                                           bridge_ipfix,
     826                 :            :                                                           replies);
     827                 :            :     } else {
     828                 :          0 :         error = EOPNOTSUPP;
     829                 :            :     }
     830                 :            : 
     831                 :          6 :     return error;
     832                 :            : }
     833                 :            : 
     834                 :            : static enum ofperr
     835                 :          3 : handle_ipfix_bridge_stats_request(struct ofconn *ofconn,
     836                 :            :                                   const struct ofp_header *request)
     837                 :            : {
     838                 :          3 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
     839                 :            :     struct ovs_list replies;
     840                 :            :     enum ofperr error;
     841                 :            : 
     842                 :          3 :     ofpmp_init(&replies, request);
     843                 :          3 :     error = ofproto_get_ipfix_stats(ofproto, true, &replies);
     844                 :            : 
     845         [ +  + ]:          3 :     if (!error) {
     846                 :          1 :         ofconn_send_replies(ofconn, &replies);
     847                 :            :     } else {
     848                 :          2 :         ofpbuf_list_delete(&replies);
     849                 :            :     }
     850                 :            : 
     851                 :          3 :     return error;
     852                 :            : }
     853                 :            : 
     854                 :            : static enum ofperr
     855                 :          3 : handle_ipfix_flow_stats_request(struct ofconn *ofconn,
     856                 :            :                                 const struct ofp_header *request)
     857                 :            : {
     858                 :          3 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
     859                 :            :     struct ovs_list replies;
     860                 :            :     enum ofperr error;
     861                 :            : 
     862                 :          3 :     ofpmp_init(&replies, request);
     863                 :          3 :     error = ofproto_get_ipfix_stats(ofproto, false, &replies);
     864                 :            : 
     865         [ +  + ]:          3 :     if (!error) {
     866                 :          1 :         ofconn_send_replies(ofconn, &replies);
     867                 :            :     } else {
     868                 :          2 :         ofpbuf_list_delete(&replies);
     869                 :            :     }
     870                 :            : 
     871                 :          3 :     return error;
     872                 :            : }
     873                 :            : 
     874                 :            : void
     875                 :        653 : ofproto_set_flow_restore_wait(bool flow_restore_wait_db)
     876                 :            : {
     877                 :        653 :     flow_restore_wait = flow_restore_wait_db;
     878                 :        653 : }
     879                 :            : 
     880                 :            : bool
     881                 :     415815 : ofproto_get_flow_restore_wait(void)
     882                 :            : {
     883                 :     415815 :     return flow_restore_wait;
     884                 :            : }
     885                 :            : 
     886                 :            : 
     887                 :            : /* Spanning Tree Protocol (STP) configuration. */
     888                 :            : 
     889                 :            : /* Configures STP on 'ofproto' using the settings defined in 's'.  If
     890                 :            :  * 's' is NULL, disables STP.
     891                 :            :  *
     892                 :            :  * Returns 0 if successful, otherwise a positive errno value. */
     893                 :            : int
     894                 :       4700 : ofproto_set_stp(struct ofproto *ofproto,
     895                 :            :                 const struct ofproto_stp_settings *s)
     896                 :            : {
     897                 :       4700 :     return (ofproto->ofproto_class->set_stp
     898                 :       4700 :             ? ofproto->ofproto_class->set_stp(ofproto, s)
     899         [ +  - ]:       4700 :             : EOPNOTSUPP);
     900                 :            : }
     901                 :            : 
     902                 :            : /* Retrieves STP status of 'ofproto' and stores it in 's'.  If the
     903                 :            :  * 'enabled' member of 's' is false, then the other members are not
     904                 :            :  * meaningful.
     905                 :            :  *
     906                 :            :  * Returns 0 if successful, otherwise a positive errno value. */
     907                 :            : int
     908                 :       6579 : ofproto_get_stp_status(struct ofproto *ofproto,
     909                 :            :                        struct ofproto_stp_status *s)
     910                 :            : {
     911                 :       6579 :     return (ofproto->ofproto_class->get_stp_status
     912                 :       6579 :             ? ofproto->ofproto_class->get_stp_status(ofproto, s)
     913         [ +  - ]:       6579 :             : EOPNOTSUPP);
     914                 :            : }
     915                 :            : 
     916                 :            : /* Configures STP on 'ofp_port' of 'ofproto' using the settings defined
     917                 :            :  * in 's'.  The caller is responsible for assigning STP port numbers
     918                 :            :  * (using the 'port_num' member in the range of 1 through 255, inclusive)
     919                 :            :  * and ensuring there are no duplicates.  If the 's' is NULL, then STP
     920                 :            :  * is disabled on the port.
     921                 :            :  *
     922                 :            :  * Returns 0 if successful, otherwise a positive errno value.*/
     923                 :            : int
     924                 :         20 : ofproto_port_set_stp(struct ofproto *ofproto, ofp_port_t ofp_port,
     925                 :            :                      const struct ofproto_port_stp_settings *s)
     926                 :            : {
     927                 :         20 :     struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
     928         [ -  + ]:         20 :     if (!ofport) {
     929         [ #  # ]:          0 :         VLOG_WARN("%s: cannot configure STP on nonexistent port %"PRIu16,
     930                 :            :                   ofproto->name, ofp_port);
     931                 :          0 :         return ENODEV;
     932                 :            :     }
     933                 :            : 
     934                 :         20 :     return (ofproto->ofproto_class->set_stp_port
     935                 :         20 :             ? ofproto->ofproto_class->set_stp_port(ofport, s)
     936         [ +  - ]:         20 :             : EOPNOTSUPP);
     937                 :            : }
     938                 :            : 
     939                 :            : /* Retrieves STP port status of 'ofp_port' on 'ofproto' and stores it in
     940                 :            :  * 's'.  If the 'enabled' member in 's' is false, then the other members
     941                 :            :  * are not meaningful.
     942                 :            :  *
     943                 :            :  * Returns 0 if successful, otherwise a positive errno value.*/
     944                 :            : int
     945                 :      36257 : ofproto_port_get_stp_status(struct ofproto *ofproto, ofp_port_t ofp_port,
     946                 :            :                             struct ofproto_port_stp_status *s)
     947                 :            : {
     948                 :      36257 :     struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
     949         [ +  + ]:      36257 :     if (!ofport) {
     950         [ +  - ]:          1 :         VLOG_WARN_RL(&rl, "%s: cannot get STP status on nonexistent "
     951                 :            :                      "port %"PRIu16, ofproto->name, ofp_port);
     952                 :          1 :         return ENODEV;
     953                 :            :     }
     954                 :            : 
     955                 :      36256 :     return (ofproto->ofproto_class->get_stp_port_status
     956                 :      36256 :             ? ofproto->ofproto_class->get_stp_port_status(ofport, s)
     957         [ +  - ]:      36256 :             : EOPNOTSUPP);
     958                 :            : }
     959                 :            : 
     960                 :            : /* Retrieves STP port statistics of 'ofp_port' on 'ofproto' and stores it in
     961                 :            :  * 's'.  If the 'enabled' member in 's' is false, then the other members
     962                 :            :  * are not meaningful.
     963                 :            :  *
     964                 :            :  * Returns 0 if successful, otherwise a positive errno value.*/
     965                 :            : int
     966                 :       5240 : ofproto_port_get_stp_stats(struct ofproto *ofproto, ofp_port_t ofp_port,
     967                 :            :                            struct ofproto_port_stp_stats *s)
     968                 :            : {
     969                 :       5240 :     struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
     970         [ -  + ]:       5240 :     if (!ofport) {
     971         [ #  # ]:          0 :         VLOG_WARN_RL(&rl, "%s: cannot get STP stats on nonexistent "
     972                 :            :                      "port %"PRIu16, ofproto->name, ofp_port);
     973                 :          0 :         return ENODEV;
     974                 :            :     }
     975                 :            : 
     976                 :       5240 :     return (ofproto->ofproto_class->get_stp_port_stats
     977                 :       5240 :             ? ofproto->ofproto_class->get_stp_port_stats(ofport, s)
     978         [ +  - ]:       5240 :             : EOPNOTSUPP);
     979                 :            : }
     980                 :            : 
     981                 :            : /* Rapid Spanning Tree Protocol (RSTP) configuration. */
     982                 :            : 
     983                 :            : /* Configures RSTP on 'ofproto' using the settings defined in 's'.  If
     984                 :            :  * 's' is NULL, disables RSTP.
     985                 :            :  *
     986                 :            :  * Returns 0 if successful, otherwise a positive errno value. */
     987                 :            : int
     988                 :       4700 : ofproto_set_rstp(struct ofproto *ofproto,
     989                 :            :                  const struct ofproto_rstp_settings *s)
     990                 :            : {
     991         [ -  + ]:       4700 :     if (!ofproto->ofproto_class->set_rstp) {
     992                 :          0 :         return EOPNOTSUPP;
     993                 :            :     }
     994                 :       4700 :     ofproto->ofproto_class->set_rstp(ofproto, s);
     995                 :       4700 :     return 0;
     996                 :            : }
     997                 :            : 
     998                 :            : /* Retrieves RSTP status of 'ofproto' and stores it in 's'.  If the
     999                 :            :  * 'enabled' member of 's' is false, then the other members are not
    1000                 :            :  * meaningful.
    1001                 :            :  *
    1002                 :            :  * Returns 0 if successful, otherwise a positive errno value. */
    1003                 :            : int
    1004                 :       6579 : ofproto_get_rstp_status(struct ofproto *ofproto,
    1005                 :            :                         struct ofproto_rstp_status *s)
    1006                 :            : {
    1007         [ -  + ]:       6579 :     if (!ofproto->ofproto_class->get_rstp_status) {
    1008                 :          0 :         return EOPNOTSUPP;
    1009                 :            :     }
    1010                 :       6579 :     ofproto->ofproto_class->get_rstp_status(ofproto, s);
    1011                 :       6579 :     return 0;
    1012                 :            : }
    1013                 :            : 
    1014                 :            : /* Configures RSTP on 'ofp_port' of 'ofproto' using the settings defined
    1015                 :            :  * in 's'.  The caller is responsible for assigning RSTP port numbers
    1016                 :            :  * (using the 'port_num' member in the range of 1 through 255, inclusive)
    1017                 :            :  * and ensuring there are no duplicates.  If the 's' is NULL, then RSTP
    1018                 :            :  * is disabled on the port.
    1019                 :            :  *
    1020                 :            :  * Returns 0 if successful, otherwise a positive errno value.*/
    1021                 :            : int
    1022                 :         30 : ofproto_port_set_rstp(struct ofproto *ofproto, ofp_port_t ofp_port,
    1023                 :            :                       const struct ofproto_port_rstp_settings *s)
    1024                 :            : {
    1025                 :         30 :     struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
    1026         [ -  + ]:         30 :     if (!ofport) {
    1027         [ #  # ]:          0 :         VLOG_WARN("%s: cannot configure RSTP on nonexistent port %"PRIu16,
    1028                 :            :                 ofproto->name, ofp_port);
    1029                 :          0 :         return ENODEV;
    1030                 :            :     }
    1031                 :            : 
    1032         [ -  + ]:         30 :     if (!ofproto->ofproto_class->set_rstp_port) {
    1033                 :          0 :         return  EOPNOTSUPP;
    1034                 :            :     }
    1035                 :         30 :     ofproto->ofproto_class->set_rstp_port(ofport, s);
    1036                 :         30 :     return 0;
    1037                 :            : }
    1038                 :            : 
    1039                 :            : /* Retrieves RSTP port status of 'ofp_port' on 'ofproto' and stores it in
    1040                 :            :  * 's'.  If the 'enabled' member in 's' is false, then the other members
    1041                 :            :  * are not meaningful.
    1042                 :            :  *
    1043                 :            :  * Returns 0 if successful, otherwise a positive errno value.*/
    1044                 :            : int
    1045                 :      36257 : ofproto_port_get_rstp_status(struct ofproto *ofproto, ofp_port_t ofp_port,
    1046                 :            :                              struct ofproto_port_rstp_status *s)
    1047                 :            : {
    1048                 :      36257 :     struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
    1049         [ +  + ]:      36257 :     if (!ofport) {
    1050         [ +  - ]:          1 :         VLOG_WARN_RL(&rl, "%s: cannot get RSTP status on nonexistent "
    1051                 :            :                 "port %"PRIu16, ofproto->name, ofp_port);
    1052                 :          1 :         return ENODEV;
    1053                 :            :     }
    1054                 :            : 
    1055         [ -  + ]:      36256 :     if (!ofproto->ofproto_class->get_rstp_port_status) {
    1056                 :          0 :         return  EOPNOTSUPP;
    1057                 :            :     }
    1058                 :      36256 :     ofproto->ofproto_class->get_rstp_port_status(ofport, s);
    1059                 :      36256 :     return 0;
    1060                 :            : }
    1061                 :            : 
    1062                 :            : /* Queue DSCP configuration. */
    1063                 :            : 
    1064                 :            : /* Registers meta-data associated with the 'n_qdscp' Qualities of Service
    1065                 :            :  * 'queues' attached to 'ofport'.  This data is not intended to be sufficient
    1066                 :            :  * to implement QoS.  Instead, it is used to implement features which require
    1067                 :            :  * knowledge of what queues exist on a port, and some basic information about
    1068                 :            :  * them.
    1069                 :            :  *
    1070                 :            :  * Returns 0 if successful, otherwise a positive errno value. */
    1071                 :            : int
    1072                 :      31837 : ofproto_port_set_queues(struct ofproto *ofproto, ofp_port_t ofp_port,
    1073                 :            :                         const struct ofproto_port_queue *queues,
    1074                 :            :                         size_t n_queues)
    1075                 :            : {
    1076                 :      31837 :     struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
    1077                 :            : 
    1078         [ -  + ]:      31837 :     if (!ofport) {
    1079         [ #  # ]:          0 :         VLOG_WARN("%s: cannot set queues on nonexistent port %"PRIu16,
    1080                 :            :                   ofproto->name, ofp_port);
    1081                 :          0 :         return ENODEV;
    1082                 :            :     }
    1083                 :            : 
    1084                 :      31837 :     return (ofproto->ofproto_class->set_queues
    1085                 :      31837 :             ? ofproto->ofproto_class->set_queues(ofport, queues, n_queues)
    1086         [ +  - ]:      31837 :             : EOPNOTSUPP);
    1087                 :            : }
    1088                 :            : 
    1089                 :            : /* LLDP configuration. */
    1090                 :            : void
    1091                 :      31837 : ofproto_port_set_lldp(struct ofproto *ofproto,
    1092                 :            :                       ofp_port_t ofp_port,
    1093                 :            :                       const struct smap *cfg)
    1094                 :            : {
    1095                 :            :     struct ofport *ofport;
    1096                 :            :     int error;
    1097                 :            : 
    1098                 :      31837 :     ofport = ofproto_get_port(ofproto, ofp_port);
    1099         [ -  + ]:      31837 :     if (!ofport) {
    1100         [ #  # ]:          0 :         VLOG_WARN("%s: cannot configure LLDP on nonexistent port %"PRIu16,
    1101                 :            :                   ofproto->name, ofp_port);
    1102                 :          0 :         return;
    1103                 :            :     }
    1104                 :      63674 :     error = (ofproto->ofproto_class->set_lldp
    1105                 :      31837 :              ? ofproto->ofproto_class->set_lldp(ofport, cfg)
    1106         [ +  - ]:      31837 :              : EOPNOTSUPP);
    1107         [ -  + ]:      31837 :     if (error) {
    1108         [ #  # ]:          0 :         VLOG_WARN("%s: lldp configuration on port %"PRIu16" (%s) failed (%s)",
    1109                 :            :                   ofproto->name, ofp_port, netdev_get_name(ofport->netdev),
    1110                 :            :                   ovs_strerror(error));
    1111                 :            :     }
    1112                 :            : }
    1113                 :            : 
    1114                 :            : int
    1115                 :       4700 : ofproto_set_aa(struct ofproto *ofproto, void *aux OVS_UNUSED,
    1116                 :            :                const struct aa_settings *s)
    1117                 :            : {
    1118         [ -  + ]:       4700 :     if (!ofproto->ofproto_class->set_aa) {
    1119                 :          0 :         return EOPNOTSUPP;
    1120                 :            :     }
    1121                 :       4700 :     ofproto->ofproto_class->set_aa(ofproto, s);
    1122                 :       4700 :     return 0;
    1123                 :            : }
    1124                 :            : 
    1125                 :            : int
    1126                 :          0 : ofproto_aa_mapping_register(struct ofproto *ofproto, void *aux,
    1127                 :            :                             const struct aa_mapping_settings *s)
    1128                 :            : {
    1129         [ #  # ]:          0 :     if (!ofproto->ofproto_class->aa_mapping_set) {
    1130                 :          0 :         return EOPNOTSUPP;
    1131                 :            :     }
    1132                 :          0 :     ofproto->ofproto_class->aa_mapping_set(ofproto, aux, s);
    1133                 :          0 :     return 0;
    1134                 :            : }
    1135                 :            : 
    1136                 :            : int
    1137                 :          0 : ofproto_aa_mapping_unregister(struct ofproto *ofproto, void *aux)
    1138                 :            : {
    1139         [ #  # ]:          0 :     if (!ofproto->ofproto_class->aa_mapping_unset) {
    1140                 :          0 :         return EOPNOTSUPP;
    1141                 :            :     }
    1142                 :          0 :     ofproto->ofproto_class->aa_mapping_unset(ofproto, aux);
    1143                 :          0 :     return 0;
    1144                 :            : }
    1145                 :            : 
    1146                 :            : int
    1147                 :          0 : ofproto_aa_vlan_get_queued(struct ofproto *ofproto,
    1148                 :            :                            struct ovs_list *list)
    1149                 :            : {
    1150         [ #  # ]:          0 :     if (!ofproto->ofproto_class->aa_vlan_get_queued) {
    1151                 :          0 :         return EOPNOTSUPP;
    1152                 :            :     }
    1153                 :          0 :     ofproto->ofproto_class->aa_vlan_get_queued(ofproto, list);
    1154                 :          0 :     return 0;
    1155                 :            : }
    1156                 :            : 
    1157                 :            : unsigned int
    1158                 :       5132 : ofproto_aa_vlan_get_queue_size(struct ofproto *ofproto)
    1159                 :            : {
    1160         [ -  + ]:       5132 :     if (!ofproto->ofproto_class->aa_vlan_get_queue_size) {
    1161                 :          0 :         return EOPNOTSUPP;
    1162                 :            :     }
    1163                 :       5132 :     return ofproto->ofproto_class->aa_vlan_get_queue_size(ofproto);
    1164                 :            : }
    1165                 :            : 
    1166                 :            : /* Connectivity Fault Management configuration. */
    1167                 :            : 
    1168                 :            : /* Clears the CFM configuration from 'ofp_port' on 'ofproto'. */
    1169                 :            : void
    1170                 :      31805 : ofproto_port_clear_cfm(struct ofproto *ofproto, ofp_port_t ofp_port)
    1171                 :            : {
    1172                 :      31805 :     struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
    1173 [ +  - ][ +  - ]:      31805 :     if (ofport && ofproto->ofproto_class->set_cfm) {
    1174                 :      31805 :         ofproto->ofproto_class->set_cfm(ofport, NULL);
    1175                 :            :     }
    1176                 :      31805 : }
    1177                 :            : 
    1178                 :            : /* Configures connectivity fault management on 'ofp_port' in 'ofproto'.  Takes
    1179                 :            :  * basic configuration from the configuration members in 'cfm', and the remote
    1180                 :            :  * maintenance point ID from  remote_mpid.  Ignores the statistics members of
    1181                 :            :  * 'cfm'.
    1182                 :            :  *
    1183                 :            :  * This function has no effect if 'ofproto' does not have a port 'ofp_port'. */
    1184                 :            : void
    1185                 :         32 : ofproto_port_set_cfm(struct ofproto *ofproto, ofp_port_t ofp_port,
    1186                 :            :                      const struct cfm_settings *s)
    1187                 :            : {
    1188                 :            :     struct ofport *ofport;
    1189                 :            :     int error;
    1190                 :            : 
    1191                 :         32 :     ofport = ofproto_get_port(ofproto, ofp_port);
    1192         [ -  + ]:         32 :     if (!ofport) {
    1193         [ #  # ]:          0 :         VLOG_WARN("%s: cannot configure CFM on nonexistent port %"PRIu16,
    1194                 :            :                   ofproto->name, ofp_port);
    1195                 :          0 :         return;
    1196                 :            :     }
    1197                 :            : 
    1198                 :            :     /* XXX: For configuration simplicity, we only support one remote_mpid
    1199                 :            :      * outside of the CFM module.  It's not clear if this is the correct long
    1200                 :            :      * term solution or not. */
    1201                 :         64 :     error = (ofproto->ofproto_class->set_cfm
    1202                 :         32 :              ? ofproto->ofproto_class->set_cfm(ofport, s)
    1203         [ +  - ]:         32 :              : EOPNOTSUPP);
    1204         [ -  + ]:         32 :     if (error) {
    1205         [ #  # ]:          0 :         VLOG_WARN("%s: CFM configuration on port %"PRIu16" (%s) failed (%s)",
    1206                 :            :                   ofproto->name, ofp_port, netdev_get_name(ofport->netdev),
    1207                 :            :                   ovs_strerror(error));
    1208                 :            :     }
    1209                 :            : }
    1210                 :            : 
    1211                 :            : /* Configures BFD on 'ofp_port' in 'ofproto'.  This function has no effect if
    1212                 :            :  * 'ofproto' does not have a port 'ofp_port'. */
    1213                 :            : void
    1214                 :      31837 : ofproto_port_set_bfd(struct ofproto *ofproto, ofp_port_t ofp_port,
    1215                 :            :                      const struct smap *cfg)
    1216                 :            : {
    1217                 :            :     struct ofport *ofport;
    1218                 :            :     int error;
    1219                 :            : 
    1220                 :      31837 :     ofport = ofproto_get_port(ofproto, ofp_port);
    1221         [ -  + ]:      31837 :     if (!ofport) {
    1222         [ #  # ]:          0 :         VLOG_WARN("%s: cannot configure bfd on nonexistent port %"PRIu16,
    1223                 :            :                   ofproto->name, ofp_port);
    1224                 :          0 :         return;
    1225                 :            :     }
    1226                 :            : 
    1227                 :      63674 :     error = (ofproto->ofproto_class->set_bfd
    1228                 :      31837 :              ? ofproto->ofproto_class->set_bfd(ofport, cfg)
    1229         [ +  - ]:      31837 :              : EOPNOTSUPP);
    1230         [ -  + ]:      31837 :     if (error) {
    1231         [ #  # ]:          0 :         VLOG_WARN("%s: bfd configuration on port %"PRIu16" (%s) failed (%s)",
    1232                 :            :                   ofproto->name, ofp_port, netdev_get_name(ofport->netdev),
    1233                 :            :                   ovs_strerror(error));
    1234                 :            :     }
    1235                 :            : }
    1236                 :            : 
    1237                 :            : /* Checks the status change of BFD on 'ofport'.
    1238                 :            :  *
    1239                 :            :  * Returns true if 'ofproto_class' does not support 'bfd_status_changed'. */
    1240                 :            : bool
    1241                 :      36469 : ofproto_port_bfd_status_changed(struct ofproto *ofproto, ofp_port_t ofp_port)
    1242                 :            : {
    1243                 :      36469 :     struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
    1244 [ +  + ][ -  + ]:      72938 :     return (ofport && ofproto->ofproto_class->bfd_status_changed
    1245                 :      36468 :             ? ofproto->ofproto_class->bfd_status_changed(ofport)
    1246   [ +  +  +  + ]:      72937 :             : true);
    1247                 :            : }
    1248                 :            : 
    1249                 :            : /* Populates 'status' with the status of BFD on 'ofport'.  Returns 0 on
    1250                 :            :  * success.  Returns a positive errno otherwise.  Has no effect if 'ofp_port'
    1251                 :            :  * is not an OpenFlow port in 'ofproto'.
    1252                 :            :  *
    1253                 :            :  * The caller must provide and own '*status'. */
    1254                 :            : int
    1255                 :      36410 : ofproto_port_get_bfd_status(struct ofproto *ofproto, ofp_port_t ofp_port,
    1256                 :            :                             struct smap *status)
    1257                 :            : {
    1258                 :      36410 :     struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
    1259         [ +  - ]:      72819 :     return (ofport && ofproto->ofproto_class->get_bfd_status
    1260                 :      36409 :             ? ofproto->ofproto_class->get_bfd_status(ofport, status)
    1261         [ +  + ]:      72819 :             : EOPNOTSUPP);
    1262                 :            : }
    1263                 :            : 
    1264                 :            : /* Checks the status of LACP negotiation for 'ofp_port' within ofproto.
    1265                 :            :  * Returns 1 if LACP partner information for 'ofp_port' is up-to-date,
    1266                 :            :  * 0 if LACP partner information is not current (generally indicating a
    1267                 :            :  * connectivity problem), or -1 if LACP is not enabled on 'ofp_port'. */
    1268                 :            : int
    1269                 :      36469 : ofproto_port_is_lacp_current(struct ofproto *ofproto, ofp_port_t ofp_port)
    1270                 :            : {
    1271                 :      36469 :     struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
    1272         [ +  - ]:      72937 :     return (ofport && ofproto->ofproto_class->port_is_lacp_current
    1273                 :      36468 :             ? ofproto->ofproto_class->port_is_lacp_current(ofport)
    1274         [ +  + ]:      72937 :             : -1);
    1275                 :            : }
    1276                 :            : 
    1277                 :            : int
    1278                 :         14 : ofproto_port_get_lacp_stats(const struct ofport *port, struct lacp_slave_stats *stats)
    1279                 :            : {
    1280                 :         14 :     struct ofproto *ofproto = port->ofproto;
    1281                 :            :     int error;
    1282                 :            : 
    1283         [ +  - ]:         14 :     if (ofproto->ofproto_class->port_get_lacp_stats) {
    1284                 :         14 :         error = ofproto->ofproto_class->port_get_lacp_stats(port, stats);
    1285                 :            :     } else {
    1286                 :          0 :         error = EOPNOTSUPP;
    1287                 :            :     }
    1288                 :            : 
    1289                 :         14 :     return error;
    1290                 :            : }
    1291                 :            : 
    1292                 :            : /* Bundles. */
    1293                 :            : 
    1294                 :            : /* Registers a "bundle" associated with client data pointer 'aux' in 'ofproto'.
    1295                 :            :  * A bundle is the same concept as a Port in OVSDB, that is, it consists of one
    1296                 :            :  * or more "slave" devices (Interfaces, in OVSDB) along with a VLAN
    1297                 :            :  * configuration plus, if there is more than one slave, a bonding
    1298                 :            :  * configuration.
    1299                 :            :  *
    1300                 :            :  * If 'aux' is already registered then this function updates its configuration
    1301                 :            :  * to 's'.  Otherwise, this function registers a new bundle.
    1302                 :            :  *
    1303                 :            :  * Bundles only affect the NXAST_AUTOPATH action and output to the OFPP_NORMAL
    1304                 :            :  * port. */
    1305                 :            : int
    1306                 :      34469 : ofproto_bundle_register(struct ofproto *ofproto, void *aux,
    1307                 :            :                         const struct ofproto_bundle_settings *s)
    1308                 :            : {
    1309                 :      34469 :     return (ofproto->ofproto_class->bundle_set
    1310                 :      34469 :             ? ofproto->ofproto_class->bundle_set(ofproto, aux, s)
    1311         [ +  - ]:      34469 :             : EOPNOTSUPP);
    1312                 :            : }
    1313                 :            : 
    1314                 :            : /* Unregisters the bundle registered on 'ofproto' with auxiliary data 'aux'.
    1315                 :            :  * If no such bundle has been registered, this has no effect. */
    1316                 :            : int
    1317                 :       2667 : ofproto_bundle_unregister(struct ofproto *ofproto, void *aux)
    1318                 :            : {
    1319                 :       2667 :     return ofproto_bundle_register(ofproto, aux, NULL);
    1320                 :            : }
    1321                 :            : 
    1322                 :            : 
    1323                 :            : /* Registers a mirror associated with client data pointer 'aux' in 'ofproto'.
    1324                 :            :  * If 'aux' is already registered then this function updates its configuration
    1325                 :            :  * to 's'.  Otherwise, this function registers a new mirror. */
    1326                 :            : int
    1327                 :         44 : ofproto_mirror_register(struct ofproto *ofproto, void *aux,
    1328                 :            :                         const struct ofproto_mirror_settings *s)
    1329                 :            : {
    1330                 :         44 :     return (ofproto->ofproto_class->mirror_set
    1331                 :         44 :             ? ofproto->ofproto_class->mirror_set(ofproto, aux, s)
    1332         [ +  - ]:         44 :             : EOPNOTSUPP);
    1333                 :            : }
    1334                 :            : 
    1335                 :            : /* Unregisters the mirror registered on 'ofproto' with auxiliary data 'aux'.
    1336                 :            :  * If no mirror has been registered, this has no effect. */
    1337                 :            : int
    1338                 :         22 : ofproto_mirror_unregister(struct ofproto *ofproto, void *aux)
    1339                 :            : {
    1340                 :         22 :     return ofproto_mirror_register(ofproto, aux, NULL);
    1341                 :            : }
    1342                 :            : 
    1343                 :            : /* Retrieves statistics from mirror associated with client data pointer
    1344                 :            :  * 'aux' in 'ofproto'.  Stores packet and byte counts in 'packets' and
    1345                 :            :  * 'bytes', respectively.  If a particular counters is not supported,
    1346                 :            :  * the appropriate argument is set to UINT64_MAX.
    1347                 :            :  */
    1348                 :            : int
    1349                 :          0 : ofproto_mirror_get_stats(struct ofproto *ofproto, void *aux,
    1350                 :            :                          uint64_t *packets, uint64_t *bytes)
    1351                 :            : {
    1352         [ #  # ]:          0 :     if (!ofproto->ofproto_class->mirror_get_stats) {
    1353                 :          0 :         *packets = *bytes = UINT64_MAX;
    1354                 :          0 :         return EOPNOTSUPP;
    1355                 :            :     }
    1356                 :            : 
    1357                 :          0 :     return ofproto->ofproto_class->mirror_get_stats(ofproto, aux,
    1358                 :            :                                                     packets, bytes);
    1359                 :            : }
    1360                 :            : 
    1361                 :            : /* Configures the VLANs whose bits are set to 1 in 'flood_vlans' as VLANs on
    1362                 :            :  * which all packets are flooded, instead of using MAC learning.  If
    1363                 :            :  * 'flood_vlans' is NULL, then MAC learning applies to all VLANs.
    1364                 :            :  *
    1365                 :            :  * Flood VLANs affect only the treatment of packets output to the OFPP_NORMAL
    1366                 :            :  * port. */
    1367                 :            : int
    1368                 :       4700 : ofproto_set_flood_vlans(struct ofproto *ofproto, unsigned long *flood_vlans)
    1369                 :            : {
    1370                 :       4700 :     return (ofproto->ofproto_class->set_flood_vlans
    1371                 :       4700 :             ? ofproto->ofproto_class->set_flood_vlans(ofproto, flood_vlans)
    1372         [ +  - ]:       4700 :             : EOPNOTSUPP);
    1373                 :            : }
    1374                 :            : 
    1375                 :            : /* Returns true if 'aux' is a registered bundle that is currently in use as the
    1376                 :            :  * output for a mirror. */
    1377                 :            : bool
    1378                 :         15 : ofproto_is_mirror_output_bundle(const struct ofproto *ofproto, void *aux)
    1379                 :            : {
    1380                 :         15 :     return (ofproto->ofproto_class->is_mirror_output_bundle
    1381                 :         15 :             ? ofproto->ofproto_class->is_mirror_output_bundle(ofproto, aux)
    1382   [ +  -  -  + ]:         30 :             : false);
    1383                 :            : }
    1384                 :            : 
    1385                 :            : /* Configuration of OpenFlow tables. */
    1386                 :            : 
    1387                 :            : /* Returns the number of OpenFlow tables in 'ofproto'. */
    1388                 :            : int
    1389                 :       4700 : ofproto_get_n_tables(const struct ofproto *ofproto)
    1390                 :            : {
    1391                 :       4700 :     return ofproto->n_tables;
    1392                 :            : }
    1393                 :            : 
    1394                 :            : /* Returns the number of Controller visible OpenFlow tables
    1395                 :            :  * in 'ofproto'. This number will exclude Hidden tables.
    1396                 :            :  * This funtion's return value should be less or equal to that of
    1397                 :            :  * ofproto_get_n_tables() . */
    1398                 :            : uint8_t
    1399                 :         70 : ofproto_get_n_visible_tables(const struct ofproto *ofproto)
    1400                 :            : {
    1401                 :         70 :     uint8_t n = ofproto->n_tables;
    1402                 :            : 
    1403                 :            :     /* Count only non-hidden tables in the number of tables.  (Hidden tables,
    1404                 :            :      * if present, are always at the end.) */
    1405 [ +  - ][ +  + ]:        140 :     while(n && (ofproto->tables[n - 1].flags & OFTABLE_HIDDEN)) {
    1406                 :         70 :         n--;
    1407                 :            :     }
    1408                 :            : 
    1409                 :         70 :     return n;
    1410                 :            : }
    1411                 :            : 
    1412                 :            : /* Configures the OpenFlow table in 'ofproto' with id 'table_id' with the
    1413                 :            :  * settings from 's'.  'table_id' must be in the range 0 through the number of
    1414                 :            :  * OpenFlow tables in 'ofproto' minus 1, inclusive.
    1415                 :            :  *
    1416                 :            :  * For read-only tables, only the name may be configured. */
    1417                 :            : void
    1418                 :    1198500 : ofproto_configure_table(struct ofproto *ofproto, int table_id,
    1419                 :            :                         const struct ofproto_table_settings *s)
    1420                 :            : {
    1421                 :            :     struct oftable *table;
    1422                 :            : 
    1423 [ +  - ][ -  + ]:    1198500 :     ovs_assert(table_id >= 0 && table_id < ofproto->n_tables);
    1424                 :    1198500 :     table = &ofproto->tables[table_id];
    1425                 :            : 
    1426                 :    1198500 :     oftable_set_name(table, s->name);
    1427                 :            : 
    1428         [ +  + ]:    1198500 :     if (table->flags & OFTABLE_READONLY) {
    1429                 :       4700 :         return;
    1430                 :            :     }
    1431                 :            : 
    1432                 :    1193800 :     if (classifier_set_prefix_fields(&table->cls,
    1433                 :    1193800 :                                      s->prefix_fields, s->n_prefix_fields)) {
    1434                 :            :         /* XXX: Trigger revalidation. */
    1435                 :            :     }
    1436                 :            : 
    1437                 :    1193800 :     ovs_mutex_lock(&ofproto_mutex);
    1438                 :    2387600 :     unsigned int new_eviction = (s->enable_eviction
    1439                 :         10 :                                  ? table->eviction | EVICTION_CLIENT
    1440         [ +  + ]:    1193800 :                                  : table->eviction & ~EVICTION_CLIENT);
    1441                 :    1193800 :     oftable_configure_eviction(table, new_eviction, s->groups, s->n_groups);
    1442                 :    1193800 :     table->max_flows = s->max_flows;
    1443                 :    1193800 :     evict_rules_from_table(table);
    1444                 :    1193800 :     ovs_mutex_unlock(&ofproto_mutex);
    1445                 :            : }
    1446                 :            : 
    1447                 :            : bool
    1448                 :       4700 : ofproto_has_snoops(const struct ofproto *ofproto)
    1449                 :            : {
    1450                 :       4700 :     return connmgr_has_snoops(ofproto->connmgr);
    1451                 :            : }
    1452                 :            : 
    1453                 :            : void
    1454                 :          0 : ofproto_get_snoops(const struct ofproto *ofproto, struct sset *snoops)
    1455                 :            : {
    1456                 :          0 :     connmgr_get_snoops(ofproto->connmgr, snoops);
    1457                 :          0 : }
    1458                 :            : 
    1459                 :            : /* Deletes 'rule' from 'ofproto'.
    1460                 :            :  *
    1461                 :            :  * Within an ofproto implementation, this function allows an ofproto
    1462                 :            :  * implementation to destroy any rules that remain when its ->destruct()
    1463                 :            :  * function is called.  This function is not suitable for use elsewhere in an
    1464                 :            :  * ofproto implementation.
    1465                 :            :  *
    1466                 :            :  * This function implements steps 4.4 and 4.5 in the section titled "Rule Life
    1467                 :            :  * Cycle" in ofproto-provider.h. */
    1468                 :            : void
    1469                 :       4276 : ofproto_rule_delete(struct ofproto *ofproto, struct rule *rule)
    1470                 :            :     OVS_EXCLUDED(ofproto_mutex)
    1471                 :            : {
    1472                 :            :     /* This skips the ofmonitor and flow-removed notifications because the
    1473                 :            :      * switch is being deleted and any OpenFlow channels have been or soon will
    1474                 :            :      * be killed. */
    1475                 :       4276 :     ovs_mutex_lock(&ofproto_mutex);
    1476                 :            : 
    1477         [ +  - ]:       4276 :     if (!rule->removed) {
    1478                 :            :         /* Make sure there is no postponed removal of the rule. */
    1479         [ -  + ]:       4276 :         ovs_assert(cls_rule_visible_in_version(&rule->cr, OVS_VERSION_MAX));
    1480                 :            : 
    1481         [ -  + ]:       4276 :         if (!classifier_remove(&rule->ofproto->tables[rule->table_id].cls,
    1482                 :            :                                &rule->cr)) {
    1483                 :          0 :             OVS_NOT_REACHED();
    1484                 :            :         }
    1485                 :       4276 :         ofproto_rule_remove__(rule->ofproto, rule);
    1486         [ -  + ]:       4276 :         if (ofproto->ofproto_class->rule_delete) {
    1487                 :          0 :             ofproto->ofproto_class->rule_delete(rule);
    1488                 :            :         }
    1489                 :       4276 :         ofproto_rule_unref(rule);
    1490                 :            :     }
    1491                 :       4276 :     ovs_mutex_unlock(&ofproto_mutex);
    1492                 :       4276 : }
    1493                 :            : 
    1494                 :            : static void
    1495                 :        895 : ofproto_flush__(struct ofproto *ofproto)
    1496                 :            :     OVS_EXCLUDED(ofproto_mutex)
    1497                 :            : {
    1498                 :            :     struct oftable *table;
    1499                 :            : 
    1500                 :            :     /* This will flush all datapath flows. */
    1501         [ +  - ]:        895 :     if (ofproto->ofproto_class->flush) {
    1502                 :        895 :         ofproto->ofproto_class->flush(ofproto);
    1503                 :            :     }
    1504                 :            : 
    1505                 :            :     /* XXX: There is a small race window here, where new datapath flows can be
    1506                 :            :      * created by upcall handlers based on the existing flow table.  We can not
    1507                 :            :      * call ofproto class flush while holding 'ofproto_mutex' to prevent this,
    1508                 :            :      * as then we could deadlock on syncing with the handler threads waiting on
    1509                 :            :      * the same mutex. */
    1510                 :            : 
    1511                 :        895 :     ovs_mutex_lock(&ofproto_mutex);
    1512         [ +  + ]:     229120 :     OFPROTO_FOR_EACH_TABLE (table, ofproto) {
    1513                 :            :         struct rule_collection rules;
    1514                 :            :         struct rule *rule;
    1515                 :            : 
    1516         [ +  + ]:     228225 :         if (table->flags & OFTABLE_HIDDEN) {
    1517                 :        895 :             continue;
    1518                 :            :         }
    1519                 :            : 
    1520                 :     227330 :         rule_collection_init(&rules);
    1521                 :            : 
    1522 [ +  + ][ +  + ]:     240087 :         CLS_FOR_EACH (rule, cr, &table->cls) {
    1523                 :      12757 :             rule_collection_add(&rules, rule);
    1524                 :            :         }
    1525                 :     227330 :         delete_flows__(&rules, OFPRR_DELETE, NULL);
    1526                 :            :     }
    1527                 :            :     /* XXX: Concurrent handler threads may insert new learned flows based on
    1528                 :            :      * learn actions of the now deleted flows right after we release
    1529                 :            :      * 'ofproto_mutex'. */
    1530                 :        895 :     ovs_mutex_unlock(&ofproto_mutex);
    1531                 :        895 : }
    1532                 :            : 
    1533                 :            : static void
    1534                 :        123 : ofproto_destroy__(struct ofproto *ofproto)
    1535                 :            :     OVS_EXCLUDED(ofproto_mutex)
    1536                 :            : {
    1537                 :            :     struct oftable *table;
    1538                 :            : 
    1539                 :        123 :     cmap_destroy(&ofproto->groups);
    1540                 :            : 
    1541                 :        123 :     hmap_remove(&all_ofprotos, &ofproto->hmap_node);
    1542                 :        123 :     free(ofproto->name);
    1543                 :        123 :     free(ofproto->type);
    1544                 :        123 :     free(ofproto->mfr_desc);
    1545                 :        123 :     free(ofproto->hw_desc);
    1546                 :        123 :     free(ofproto->sw_desc);
    1547                 :        123 :     free(ofproto->serial_desc);
    1548                 :        123 :     free(ofproto->dp_desc);
    1549                 :        123 :     hmap_destroy(&ofproto->ports);
    1550                 :        123 :     hmap_destroy(&ofproto->ofport_usage);
    1551                 :        123 :     shash_destroy(&ofproto->port_by_name);
    1552                 :        123 :     simap_destroy(&ofproto->ofp_requests);
    1553                 :            : 
    1554         [ +  + ]:      31488 :     OFPROTO_FOR_EACH_TABLE (table, ofproto) {
    1555                 :      31365 :         oftable_destroy(table);
    1556                 :            :     }
    1557                 :        123 :     free(ofproto->tables);
    1558                 :            : 
    1559         [ -  + ]:        123 :     ovs_assert(hindex_is_empty(&ofproto->cookies));
    1560                 :        123 :     hindex_destroy(&ofproto->cookies);
    1561                 :            : 
    1562         [ -  + ]:        123 :     ovs_assert(hmap_is_empty(&ofproto->learned_cookies));
    1563                 :        123 :     hmap_destroy(&ofproto->learned_cookies);
    1564                 :            : 
    1565                 :        123 :     ofproto->ofproto_class->dealloc(ofproto);
    1566                 :        123 : }
    1567                 :            : 
    1568                 :            : /* Destroying rules is doubly deferred, must have 'ofproto' around for them.
    1569                 :            :  * - 1st we defer the removal of the rules from the classifier
    1570                 :            :  * - 2nd we defer the actual destruction of the rules. */
    1571                 :            : static void
    1572                 :        133 : ofproto_destroy_defer__(struct ofproto *ofproto)
    1573                 :            :     OVS_EXCLUDED(ofproto_mutex)
    1574                 :            : {
    1575                 :        133 :     ovsrcu_postpone(ofproto_destroy__, ofproto);
    1576                 :        133 : }
    1577                 :            : 
    1578                 :            : void
    1579                 :        752 : ofproto_destroy(struct ofproto *p, bool del)
    1580                 :            :     OVS_EXCLUDED(ofproto_mutex)
    1581                 :            : {
    1582                 :            :     struct ofport *ofport, *next_ofport;
    1583                 :            :     struct ofport_usage *usage;
    1584                 :            : 
    1585         [ +  + ]:        752 :     if (!p) {
    1586                 :          3 :         return;
    1587                 :            :     }
    1588                 :            : 
    1589         [ +  - ]:        749 :     if (p->meters) {
    1590                 :        749 :         meter_delete(p, 1, p->meter_features.max_meters);
    1591                 :        749 :         p->meter_features.max_meters = 0;
    1592                 :        749 :         free(p->meters);
    1593                 :        749 :         p->meters = NULL;
    1594                 :            :     }
    1595                 :            : 
    1596                 :        749 :     ofproto_flush__(p);
    1597 [ +  + ][ -  + ]:       3051 :     HMAP_FOR_EACH_SAFE (ofport, next_ofport, hmap_node, &p->ports) {
                 [ +  + ]
    1598                 :       2302 :         ofport_destroy(ofport, del);
    1599                 :            :     }
    1600                 :            : 
    1601 [ +  + ][ -  + ]:       2451 :     HMAP_FOR_EACH_POP (usage, hmap_node, &p->ofport_usage) {
                 [ +  + ]
    1602                 :       1702 :         free(usage);
    1603                 :            :     }
    1604                 :            : 
    1605                 :        749 :     p->ofproto_class->destruct(p);
    1606                 :            : 
    1607                 :            :     /* We should not postpone this because it involves deleting a listening
    1608                 :            :      * socket which we may want to reopen soon. 'connmgr' should not be used
    1609                 :            :      * by other threads */
    1610                 :        749 :     connmgr_destroy(p->connmgr);
    1611                 :            : 
    1612                 :            :     /* Destroying rules is deferred, must have 'ofproto' around for them. */
    1613                 :        749 :     ovsrcu_postpone(ofproto_destroy_defer__, p);
    1614                 :            : }
    1615                 :            : 
    1616                 :            : /* Destroys the datapath with the respective 'name' and 'type'.  With the Linux
    1617                 :            :  * kernel datapath, for example, this destroys the datapath in the kernel, and
    1618                 :            :  * with the netdev-based datapath, it tears down the data structures that
    1619                 :            :  * represent the datapath.
    1620                 :            :  *
    1621                 :            :  * The datapath should not be currently open as an ofproto. */
    1622                 :            : int
    1623                 :          0 : ofproto_delete(const char *name, const char *type)
    1624                 :            : {
    1625                 :          0 :     const struct ofproto_class *class = ofproto_class_find__(type);
    1626                 :          0 :     return (!class ? EAFNOSUPPORT
    1627         [ #  # ]:          0 :             : !class->del ? EACCES
    1628         [ #  # ]:          0 :             : class->del(type, name));
    1629                 :            : }
    1630                 :            : 
    1631                 :            : static void
    1632                 :          1 : process_port_change(struct ofproto *ofproto, int error, char *devname)
    1633                 :            : {
    1634         [ -  + ]:          1 :     if (error == ENOBUFS) {
    1635                 :          0 :         reinit_ports(ofproto);
    1636         [ +  - ]:          1 :     } else if (!error) {
    1637                 :          1 :         update_port(ofproto, devname);
    1638                 :          1 :         free(devname);
    1639                 :            :     }
    1640                 :          1 : }
    1641                 :            : 
    1642                 :            : int
    1643                 :     245845 : ofproto_type_run(const char *datapath_type)
    1644                 :            : {
    1645                 :            :     const struct ofproto_class *class;
    1646                 :            :     int error;
    1647                 :            : 
    1648                 :     245845 :     datapath_type = ofproto_normalize_type(datapath_type);
    1649                 :     245845 :     class = ofproto_class_find__(datapath_type);
    1650                 :            : 
    1651         [ +  - ]:     245845 :     error = class->type_run ? class->type_run(datapath_type) : 0;
    1652 [ -  + ][ #  # ]:     245845 :     if (error && error != EAGAIN) {
    1653         [ #  # ]:          0 :         VLOG_ERR_RL(&rl, "%s: type_run failed (%s)",
    1654                 :            :                     datapath_type, ovs_strerror(error));
    1655                 :            :     }
    1656                 :     245845 :     return error;
    1657                 :            : }
    1658                 :            : 
    1659                 :            : void
    1660                 :     237444 : ofproto_type_wait(const char *datapath_type)
    1661                 :            : {
    1662                 :            :     const struct ofproto_class *class;
    1663                 :            : 
    1664                 :     237444 :     datapath_type = ofproto_normalize_type(datapath_type);
    1665                 :     237444 :     class = ofproto_class_find__(datapath_type);
    1666                 :            : 
    1667         [ +  - ]:     237444 :     if (class->type_wait) {
    1668                 :     237444 :         class->type_wait(datapath_type);
    1669                 :            :     }
    1670                 :     237444 : }
    1671                 :            : 
    1672                 :            : int
    1673                 :     157605 : ofproto_run(struct ofproto *p)
    1674                 :            : {
    1675                 :            :     int error;
    1676                 :            :     uint64_t new_seq;
    1677                 :            : 
    1678                 :     157605 :     error = p->ofproto_class->run(p);
    1679 [ -  + ][ #  # ]:     157605 :     if (error && error != EAGAIN) {
    1680         [ #  # ]:          0 :         VLOG_ERR_RL(&rl, "%s: run failed (%s)", p->name, ovs_strerror(error));
    1681                 :            :     }
    1682                 :            : 
    1683                 :            :     /* Restore the eviction group heap invariant occasionally. */
    1684         [ +  + ]:     157605 :     if (p->eviction_group_timer < time_msec()) {
    1685                 :            :         size_t i;
    1686                 :            : 
    1687                 :       5228 :         p->eviction_group_timer = time_msec() + 1000;
    1688                 :            : 
    1689         [ +  + ]:    1338368 :         for (i = 0; i < p->n_tables; i++) {
    1690                 :    1333140 :             struct oftable *table = &p->tables[i];
    1691                 :            :             struct eviction_group *evg;
    1692                 :            :             struct rule *rule;
    1693                 :            : 
    1694         [ +  + ]:    1333140 :             if (!table->eviction) {
    1695                 :    1333131 :                 continue;
    1696                 :            :             }
    1697                 :            : 
    1698         [ -  + ]:          9 :             if (table->n_flows > 100000) {
    1699                 :            :                 static struct vlog_rate_limit count_rl =
    1700                 :            :                     VLOG_RATE_LIMIT_INIT(1, 1);
    1701         [ #  # ]:          0 :                 VLOG_WARN_RL(&count_rl, "Table %"PRIuSIZE" has an excessive"
    1702                 :            :                              " number of rules: %d", i, table->n_flows);
    1703                 :            :             }
    1704                 :            : 
    1705                 :          9 :             ovs_mutex_lock(&ofproto_mutex);
    1706 [ +  + ][ +  + ]:         41 :             CLS_FOR_EACH (rule, cr, &table->cls) {
    1707 [ +  + ][ +  + ]:         32 :                 if (rule->idle_timeout || rule->hard_timeout) {
    1708         [ -  + ]:         26 :                     if (!rule->eviction_group) {
    1709                 :          0 :                         eviction_group_add_rule(rule);
    1710                 :            :                     } else {
    1711                 :         26 :                         heap_raw_change(&rule->evg_node,
    1712                 :            :                                         rule_eviction_priority(p, rule));
    1713                 :            :                     }
    1714                 :            :                 }
    1715                 :            :             }
    1716                 :            : 
    1717 [ +  + ][ -  + ]:         16 :             HEAP_FOR_EACH (evg, size_node, &table->eviction_groups_by_size) {
                 [ +  + ]
    1718                 :          7 :                 heap_rebuild(&evg->rules);
    1719                 :            :             }
    1720                 :          9 :             ovs_mutex_unlock(&ofproto_mutex);
    1721                 :            :         }
    1722                 :            :     }
    1723                 :            : 
    1724         [ +  - ]:     157605 :     if (p->ofproto_class->port_poll) {
    1725                 :            :         char *devname;
    1726                 :            : 
    1727         [ +  + ]:     157606 :         while ((error = p->ofproto_class->port_poll(p, &devname)) != EAGAIN) {
    1728                 :          1 :             process_port_change(p, error, devname);
    1729                 :            :         }
    1730                 :            :     }
    1731                 :            : 
    1732                 :     157605 :     new_seq = seq_read(connectivity_seq_get());
    1733         [ +  + ]:     157605 :     if (new_seq != p->change_seq) {
    1734                 :            :         struct sset devnames;
    1735                 :            :         const char *devname;
    1736                 :            :         struct ofport *ofport;
    1737                 :            : 
    1738                 :            :         /* Update OpenFlow port status for any port whose netdev has changed.
    1739                 :            :          *
    1740                 :            :          * Refreshing a given 'ofport' can cause an arbitrary ofport to be
    1741                 :            :          * destroyed, so it's not safe to update ports directly from the
    1742                 :            :          * HMAP_FOR_EACH loop, or even to use HMAP_FOR_EACH_SAFE.  Instead, we
    1743                 :            :          * need this two-phase approach. */
    1744                 :       6100 :         sset_init(&devnames);
    1745 [ +  + ][ -  + ]:      41836 :         HMAP_FOR_EACH (ofport, hmap_node, &p->ports) {
    1746                 :            :             uint64_t port_change_seq;
    1747                 :            : 
    1748                 :      35736 :             port_change_seq = netdev_get_change_seq(ofport->netdev);
    1749         [ +  + ]:      35736 :             if (ofport->change_seq != port_change_seq) {
    1750                 :       5086 :                 ofport->change_seq = port_change_seq;
    1751                 :       5086 :                 sset_add(&devnames, netdev_get_name(ofport->netdev));
    1752                 :            :             }
    1753                 :            :         }
    1754 [ +  + ][ +  + ]:      11186 :         SSET_FOR_EACH (devname, &devnames) {
                 [ +  + ]
    1755                 :       5086 :             update_port(p, devname);
    1756                 :            :         }
    1757                 :       6100 :         sset_destroy(&devnames);
    1758                 :            : 
    1759                 :       6100 :         p->change_seq = new_seq;
    1760                 :            :     }
    1761                 :            : 
    1762                 :     157605 :     connmgr_run(p->connmgr, handle_openflow);
    1763                 :            : 
    1764                 :     157605 :     return error;
    1765                 :            : }
    1766                 :            : 
    1767                 :            : void
    1768                 :     153645 : ofproto_wait(struct ofproto *p)
    1769                 :            : {
    1770                 :     153645 :     p->ofproto_class->wait(p);
    1771         [ +  - ]:     153645 :     if (p->ofproto_class->port_poll_wait) {
    1772                 :     153645 :         p->ofproto_class->port_poll_wait(p);
    1773                 :            :     }
    1774                 :     153645 :     seq_wait(connectivity_seq_get(), p->change_seq);
    1775                 :     153645 :     connmgr_wait(p->connmgr);
    1776                 :     153645 : }
    1777                 :            : 
    1778                 :            : bool
    1779                 :          0 : ofproto_is_alive(const struct ofproto *p)
    1780                 :            : {
    1781                 :          0 :     return connmgr_has_controllers(p->connmgr);
    1782                 :            : }
    1783                 :            : 
    1784                 :            : /* Adds some memory usage statistics for 'ofproto' into 'usage', for use with
    1785                 :            :  * memory_report(). */
    1786                 :            : void
    1787                 :        109 : ofproto_get_memory_usage(const struct ofproto *ofproto, struct simap *usage)
    1788                 :            : {
    1789                 :            :     const struct oftable *table;
    1790                 :            :     unsigned int n_rules;
    1791                 :            : 
    1792                 :        109 :     simap_increase(usage, "ports", hmap_count(&ofproto->ports));
    1793                 :            : 
    1794                 :        109 :     n_rules = 0;
    1795         [ +  + ]:      27904 :     OFPROTO_FOR_EACH_TABLE (table, ofproto) {
    1796                 :      27795 :         n_rules += table->n_flows;
    1797                 :            :     }
    1798                 :        109 :     simap_increase(usage, "rules", n_rules);
    1799                 :            : 
    1800         [ -  + ]:        109 :     if (ofproto->ofproto_class->get_memory_usage) {
    1801                 :          0 :         ofproto->ofproto_class->get_memory_usage(ofproto, usage);
    1802                 :            :     }
    1803                 :            : 
    1804                 :        109 :     connmgr_get_memory_usage(ofproto->connmgr, usage);
    1805                 :        109 : }
    1806                 :            : 
    1807                 :            : void
    1808                 :        162 : ofproto_type_get_memory_usage(const char *datapath_type, struct simap *usage)
    1809                 :            : {
    1810                 :            :     const struct ofproto_class *class;
    1811                 :            : 
    1812                 :        162 :     datapath_type = ofproto_normalize_type(datapath_type);
    1813                 :        162 :     class = ofproto_class_find__(datapath_type);
    1814                 :            : 
    1815 [ +  - ][ +  - ]:        162 :     if (class && class->type_get_memory_usage) {
    1816                 :        162 :         class->type_get_memory_usage(datapath_type, usage);
    1817                 :            :     }
    1818                 :        162 : }
    1819                 :            : 
    1820                 :            : void
    1821                 :        901 : ofproto_get_ofproto_controller_info(const struct ofproto *ofproto,
    1822                 :            :                                     struct shash *info)
    1823                 :            : {
    1824                 :        901 :     connmgr_get_controller_info(ofproto->connmgr, info);
    1825                 :        901 : }
    1826                 :            : 
    1827                 :            : void
    1828                 :       1178 : ofproto_free_ofproto_controller_info(struct shash *info)
    1829                 :            : {
    1830                 :       1178 :     connmgr_free_controller_info(info);
    1831                 :       1178 : }
    1832                 :            : 
    1833                 :            : /* Makes a deep copy of 'old' into 'port'. */
    1834                 :            : void
    1835                 :          0 : ofproto_port_clone(struct ofproto_port *port, const struct ofproto_port *old)
    1836                 :            : {
    1837                 :          0 :     port->name = xstrdup(old->name);
    1838                 :          0 :     port->type = xstrdup(old->type);
    1839                 :          0 :     port->ofp_port = old->ofp_port;
    1840                 :          0 : }
    1841                 :            : 
    1842                 :            : /* Frees memory allocated to members of 'ofproto_port'.
    1843                 :            :  *
    1844                 :            :  * Do not call this function on an ofproto_port obtained from
    1845                 :            :  * ofproto_port_dump_next(): that function retains ownership of the data in the
    1846                 :            :  * ofproto_port. */
    1847                 :            : void
    1848                 :      40210 : ofproto_port_destroy(struct ofproto_port *ofproto_port)
    1849                 :            : {
    1850                 :      40210 :     free(ofproto_port->name);
    1851                 :      40210 :     free(ofproto_port->type);
    1852                 :      40210 : }
    1853                 :            : 
    1854                 :            : /* Initializes 'dump' to begin dumping the ports in an ofproto.
    1855                 :            :  *
    1856                 :            :  * This function provides no status indication.  An error status for the entire
    1857                 :            :  * dump operation is provided when it is completed by calling
    1858                 :            :  * ofproto_port_dump_done().
    1859                 :            :  */
    1860                 :            : void
    1861                 :       4700 : ofproto_port_dump_start(struct ofproto_port_dump *dump,
    1862                 :            :                         const struct ofproto *ofproto)
    1863                 :            : {
    1864                 :       4700 :     dump->ofproto = ofproto;
    1865                 :       4700 :     dump->error = ofproto->ofproto_class->port_dump_start(ofproto,
    1866                 :            :                                                           &dump->state);
    1867                 :       4700 : }
    1868                 :            : 
    1869                 :            : /* Attempts to retrieve another port from 'dump', which must have been created
    1870                 :            :  * with ofproto_port_dump_start().  On success, stores a new ofproto_port into
    1871                 :            :  * 'port' and returns true.  On failure, returns false.
    1872                 :            :  *
    1873                 :            :  * Failure might indicate an actual error or merely that the last port has been
    1874                 :            :  * dumped.  An error status for the entire dump operation is provided when it
    1875                 :            :  * is completed by calling ofproto_port_dump_done().
    1876                 :            :  *
    1877                 :            :  * The ofproto owns the data stored in 'port'.  It will remain valid until at
    1878                 :            :  * least the next time 'dump' is passed to ofproto_port_dump_next() or
    1879                 :            :  * ofproto_port_dump_done(). */
    1880                 :            : bool
    1881                 :      34138 : ofproto_port_dump_next(struct ofproto_port_dump *dump,
    1882                 :            :                        struct ofproto_port *port)
    1883                 :            : {
    1884                 :      34138 :     const struct ofproto *ofproto = dump->ofproto;
    1885                 :            : 
    1886         [ -  + ]:      34138 :     if (dump->error) {
    1887                 :          0 :         return false;
    1888                 :            :     }
    1889                 :            : 
    1890                 :      34138 :     dump->error = ofproto->ofproto_class->port_dump_next(ofproto, dump->state,
    1891                 :            :                                                          port);
    1892         [ +  + ]:      34138 :     if (dump->error) {
    1893                 :       4700 :         ofproto->ofproto_class->port_dump_done(ofproto, dump->state);
    1894                 :       4700 :         return false;
    1895                 :            :     }
    1896                 :      29438 :     return true;
    1897                 :            : }
    1898                 :            : 
    1899                 :            : /* Completes port table dump operation 'dump', which must have been created
    1900                 :            :  * with ofproto_port_dump_start().  Returns 0 if the dump operation was
    1901                 :            :  * error-free, otherwise a positive errno value describing the problem. */
    1902                 :            : int
    1903                 :       4700 : ofproto_port_dump_done(struct ofproto_port_dump *dump)
    1904                 :            : {
    1905                 :       4700 :     const struct ofproto *ofproto = dump->ofproto;
    1906         [ -  + ]:       4700 :     if (!dump->error) {
    1907                 :          0 :         dump->error = ofproto->ofproto_class->port_dump_done(ofproto,
    1908                 :            :                                                              dump->state);
    1909                 :            :     }
    1910         [ -  + ]:       4700 :     return dump->error == EOF ? 0 : dump->error;
    1911                 :            : }
    1912                 :            : 
    1913                 :            : /* Returns the type to pass to netdev_open() when a datapath of type
    1914                 :            :  * 'datapath_type' has a port of type 'port_type', for a few special
    1915                 :            :  * cases when a netdev type differs from a port type.  For example, when
    1916                 :            :  * using the userspace datapath, a port of type "internal" needs to be
    1917                 :            :  * opened as "tap".
    1918                 :            :  *
    1919                 :            :  * Returns either 'type' itself or a string literal, which must not be
    1920                 :            :  * freed. */
    1921                 :            : const char *
    1922                 :      64926 : ofproto_port_open_type(const char *datapath_type, const char *port_type)
    1923                 :            : {
    1924                 :            :     const struct ofproto_class *class;
    1925                 :            : 
    1926                 :      64926 :     datapath_type = ofproto_normalize_type(datapath_type);
    1927                 :      64926 :     class = ofproto_class_find__(datapath_type);
    1928         [ +  + ]:      64926 :     if (!class) {
    1929                 :          3 :         return port_type;
    1930                 :            :     }
    1931                 :            : 
    1932                 :      64923 :     return (class->port_open_type
    1933                 :      64923 :             ? class->port_open_type(datapath_type, port_type)
    1934         [ +  - ]:      64923 :             : port_type);
    1935                 :            : }
    1936                 :            : 
    1937                 :            : /* Attempts to add 'netdev' as a port on 'ofproto'.  If 'ofp_portp' is
    1938                 :            :  * non-null and '*ofp_portp' is not OFPP_NONE, attempts to use that as
    1939                 :            :  * the port's OpenFlow port number.
    1940                 :            :  *
    1941                 :            :  * If successful, returns 0 and sets '*ofp_portp' to the new port's
    1942                 :            :  * OpenFlow port number (if 'ofp_portp' is non-null).  On failure,
    1943                 :            :  * returns a positive errno value and sets '*ofp_portp' to OFPP_NONE (if
    1944                 :            :  * 'ofp_portp' is non-null). */
    1945                 :            : int
    1946                 :       2690 : ofproto_port_add(struct ofproto *ofproto, struct netdev *netdev,
    1947                 :            :                  ofp_port_t *ofp_portp)
    1948                 :            : {
    1949         [ +  - ]:       2690 :     ofp_port_t ofp_port = ofp_portp ? *ofp_portp : OFPP_NONE;
    1950                 :            :     int error;
    1951                 :            : 
    1952                 :       2690 :     error = ofproto->ofproto_class->port_add(ofproto, netdev);
    1953         [ +  - ]:       2690 :     if (!error) {
    1954                 :       2690 :         const char *netdev_name = netdev_get_name(netdev);
    1955                 :            : 
    1956                 :       2690 :         simap_put(&ofproto->ofp_requests, netdev_name,
    1957                 :       2690 :                   ofp_to_u16(ofp_port));
    1958                 :       2690 :         error = update_port(ofproto, netdev_name);
    1959                 :            :     }
    1960         [ +  - ]:       2690 :     if (ofp_portp) {
    1961                 :       2690 :         *ofp_portp = OFPP_NONE;
    1962         [ +  + ]:       2690 :         if (!error) {
    1963                 :            :             struct ofproto_port ofproto_port;
    1964                 :            : 
    1965                 :       2689 :             error = ofproto_port_query_by_name(ofproto,
    1966                 :            :                                                netdev_get_name(netdev),
    1967                 :            :                                                &ofproto_port);
    1968         [ +  - ]:       2689 :             if (!error) {
    1969                 :       2689 :                 *ofp_portp = ofproto_port.ofp_port;
    1970                 :       2689 :                 ofproto_port_destroy(&ofproto_port);
    1971                 :            :             }
    1972                 :            :         }
    1973                 :            :     }
    1974                 :       2690 :     return error;
    1975                 :            : }
    1976                 :            : 
    1977                 :            : /* Looks up a port named 'devname' in 'ofproto'.  On success, returns 0 and
    1978                 :            :  * initializes '*port' appropriately; on failure, returns a positive errno
    1979                 :            :  * value.
    1980                 :            :  *
    1981                 :            :  * The caller owns the data in 'ofproto_port' and must free it with
    1982                 :            :  * ofproto_port_destroy() when it is no longer needed. */
    1983                 :            : int
    1984                 :      10772 : ofproto_port_query_by_name(const struct ofproto *ofproto, const char *devname,
    1985                 :            :                            struct ofproto_port *port)
    1986                 :            : {
    1987                 :            :     int error;
    1988                 :            : 
    1989                 :      10772 :     error = ofproto->ofproto_class->port_query_by_name(ofproto, devname, port);
    1990         [ +  + ]:      10772 :     if (error) {
    1991                 :        387 :         memset(port, 0, sizeof *port);
    1992                 :            :     }
    1993                 :      10772 :     return error;
    1994                 :            : }
    1995                 :            : 
    1996                 :            : /* Deletes port number 'ofp_port' from the datapath for 'ofproto'.
    1997                 :            :  * Returns 0 if successful, otherwise a positive errno. */
    1998                 :            : int
    1999                 :        388 : ofproto_port_del(struct ofproto *ofproto, ofp_port_t ofp_port)
    2000                 :            : {
    2001                 :        388 :     struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
    2002         [ +  + ]:        388 :     const char *name = ofport ? netdev_get_name(ofport->netdev) : "<unknown>";
    2003                 :            :     struct simap_node *ofp_request_node;
    2004                 :            :     int error;
    2005                 :            : 
    2006                 :        388 :     ofp_request_node = simap_find(&ofproto->ofp_requests, name);
    2007         [ +  + ]:        388 :     if (ofp_request_node) {
    2008                 :        306 :         simap_delete(&ofproto->ofp_requests, ofp_request_node);
    2009                 :            :     }
    2010                 :            : 
    2011                 :        388 :     error = ofproto->ofproto_class->port_del(ofproto, ofp_port);
    2012 [ +  - ][ +  + ]:        388 :     if (!error && ofport) {
    2013                 :            :         /* 'name' is the netdev's name and update_port() is going to close the
    2014                 :            :          * netdev.  Just in case update_port() refers to 'name' after it
    2015                 :            :          * destroys 'ofport', make a copy of it around the update_port()
    2016                 :            :          * call. */
    2017                 :        306 :         char *devname = xstrdup(name);
    2018                 :        306 :         update_port(ofproto, devname);
    2019                 :        306 :         free(devname);
    2020                 :            :     }
    2021                 :        388 :     return error;
    2022                 :            : }
    2023                 :            : 
    2024                 :            : /* Refreshes datapath configuration of port number 'ofp_port' in 'ofproto'.
    2025                 :            :  *
    2026                 :            :  * This function has no effect if 'ofproto' does not have a port 'ofp_port'. */
    2027                 :            : void
    2028                 :      31837 : ofproto_port_set_config(struct ofproto *ofproto, ofp_port_t ofp_port,
    2029                 :            :                         const struct smap *cfg)
    2030                 :            : {
    2031                 :            :     struct ofport *ofport;
    2032                 :            :     int error;
    2033                 :            : 
    2034                 :      31837 :     ofport = ofproto_get_port(ofproto, ofp_port);
    2035         [ -  + ]:      31837 :     if (!ofport) {
    2036         [ #  # ]:          0 :         VLOG_WARN("%s: cannot configure datapath on nonexistent port %"PRIu16,
    2037                 :            :                   ofproto->name, ofp_port);
    2038                 :          0 :         return;
    2039                 :            :     }
    2040                 :            : 
    2041                 :      63674 :     error = (ofproto->ofproto_class->port_set_config
    2042                 :      31837 :              ? ofproto->ofproto_class->port_set_config(ofport, cfg)
    2043         [ +  - ]:      31837 :              : EOPNOTSUPP);
    2044         [ -  + ]:      31837 :     if (error) {
    2045         [ #  # ]:          0 :         VLOG_WARN("%s: datapath configuration on port %"PRIu16
    2046                 :            :                   " (%s) failed (%s)",
    2047                 :            :                   ofproto->name, ofp_port, netdev_get_name(ofport->netdev),
    2048                 :            :                   ovs_strerror(error));
    2049                 :            :     }
    2050                 :            : }
    2051                 :            : 
    2052                 :            : 
    2053                 :            : static void
    2054                 :        152 : flow_mod_init(struct ofputil_flow_mod *fm,
    2055                 :            :               const struct match *match, int priority,
    2056                 :            :               const struct ofpact *ofpacts, size_t ofpacts_len,
    2057                 :            :               enum ofp_flow_mod_command command)
    2058                 :            : {
    2059                 :        152 :     *fm = (struct ofputil_flow_mod) {
    2060                 :        152 :         .match = *match,
    2061                 :            :         .priority = priority,
    2062                 :            :         .table_id = 0,
    2063                 :            :         .command = command,
    2064                 :            :         .buffer_id = UINT32_MAX,
    2065                 :            :         .out_port = OFPP_ANY,
    2066                 :            :         .out_group = OFPG_ANY,
    2067                 :            :         .ofpacts = CONST_CAST(struct ofpact *, ofpacts),
    2068                 :            :         .ofpacts_len = ofpacts_len,
    2069                 :            :     };
    2070                 :        152 : }
    2071                 :            : 
    2072                 :            : static int
    2073                 :        152 : simple_flow_mod(struct ofproto *ofproto,
    2074                 :            :                 const struct match *match, int priority,
    2075                 :            :                 const struct ofpact *ofpacts, size_t ofpacts_len,
    2076                 :            :                 enum ofp_flow_mod_command command)
    2077                 :            : {
    2078                 :            :     struct ofputil_flow_mod fm;
    2079                 :            : 
    2080                 :        152 :     flow_mod_init(&fm, match, priority, ofpacts, ofpacts_len, command);
    2081                 :            : 
    2082                 :        152 :     return handle_flow_mod__(ofproto, &fm, NULL);
    2083                 :            : }
    2084                 :            : 
    2085                 :            : /* Adds a flow to OpenFlow flow table 0 in 'p' that matches 'cls_rule' and
    2086                 :            :  * performs the 'n_actions' actions in 'actions'.  The new flow will not
    2087                 :            :  * timeout.
    2088                 :            :  *
    2089                 :            :  * If cls_rule->priority is in the range of priorities supported by OpenFlow
    2090                 :            :  * (0...65535, inclusive) then the flow will be visible to OpenFlow
    2091                 :            :  * controllers; otherwise, it will be hidden.
    2092                 :            :  *
    2093                 :            :  * The caller retains ownership of 'cls_rule' and 'ofpacts'.
    2094                 :            :  *
    2095                 :            :  * This is a helper function for in-band control and fail-open. */
    2096                 :            : void
    2097                 :        481 : ofproto_add_flow(struct ofproto *ofproto, const struct match *match,
    2098                 :            :                  int priority,
    2099                 :            :                  const struct ofpact *ofpacts, size_t ofpacts_len)
    2100                 :            :     OVS_EXCLUDED(ofproto_mutex)
    2101                 :            : {
    2102                 :            :     const struct rule *rule;
    2103                 :            :     bool must_add;
    2104                 :            : 
    2105                 :            :     /* First do a cheap check whether the rule we're looking for already exists
    2106                 :            :      * with the actions that we want.  If it does, then we're done. */
    2107                 :        481 :     rule = rule_from_cls_rule(classifier_find_match_exactly(
    2108                 :        481 :                                   &ofproto->tables[0].cls, match, priority,
    2109                 :            :                                   OVS_VERSION_MAX));
    2110         [ +  + ]:        481 :     if (rule) {
    2111                 :        329 :         const struct rule_actions *actions = rule_get_actions(rule);
    2112                 :        329 :         must_add = !ofpacts_equal(actions->ofpacts, actions->ofpacts_len,
    2113                 :        329 :                                   ofpacts, ofpacts_len);
    2114                 :            :     } else {
    2115                 :        152 :         must_add = true;
    2116                 :            :     }
    2117                 :            : 
    2118                 :            :     /* If there's no such rule or the rule doesn't have the actions we want,
    2119                 :            :      * fall back to a executing a full flow mod.  We can't optimize this at
    2120                 :            :      * all because we didn't take enough locks above to ensure that the flow
    2121                 :            :      * table didn't already change beneath us.  */
    2122         [ +  + ]:        481 :     if (must_add) {
    2123                 :        152 :         simple_flow_mod(ofproto, match, priority, ofpacts, ofpacts_len,
    2124                 :            :                         OFPFC_MODIFY_STRICT);
    2125                 :            :     }
    2126                 :        481 : }
    2127                 :            : 
    2128                 :            : /* Executes the flow modification specified in 'fm'.  Returns 0 on success, or
    2129                 :            :  * an OFPERR_* OpenFlow error code on failure.
    2130                 :            :  *
    2131                 :            :  * This is a helper function for in-band control and fail-open and the "learn"
    2132                 :            :  * action. */
    2133                 :            : enum ofperr
    2134                 :       5351 : ofproto_flow_mod(struct ofproto *ofproto, const struct ofputil_flow_mod *fm)
    2135                 :            :     OVS_EXCLUDED(ofproto_mutex)
    2136                 :            : {
    2137                 :            :     /* Optimize for the most common case of a repeated learn action.
    2138                 :            :      * If an identical flow already exists we only need to update its
    2139                 :            :      * 'modified' time. */
    2140 [ +  + ][ +  - ]:       5351 :     if (fm->command == OFPFC_MODIFY_STRICT && fm->table_id != OFPTT_ALL
    2141         [ +  - ]:         51 :         && !(fm->flags & OFPUTIL_FF_RESET_COUNTS)) {
    2142                 :         51 :         struct oftable *table = &ofproto->tables[fm->table_id];
    2143                 :            :         struct rule *rule;
    2144                 :         51 :         bool done = false;
    2145                 :            : 
    2146                 :         51 :         rule = rule_from_cls_rule(classifier_find_match_exactly(
    2147                 :         51 :                                       &table->cls, &fm->match, fm->priority,
    2148                 :            :                                       OVS_VERSION_MAX));
    2149         [ +  + ]:         51 :         if (rule) {
    2150                 :            :             /* Reading many of the rule fields and writing on 'modified'
    2151                 :            :              * requires the rule->mutex. */
    2152                 :            :             const struct rule_actions *actions;
    2153                 :            : 
    2154                 :         35 :             ovs_mutex_lock(&rule->mutex);
    2155                 :         35 :             actions = rule_get_actions(rule);
    2156         [ +  - ]:         35 :             if (rule->idle_timeout == fm->idle_timeout
    2157         [ +  - ]:         35 :                 && rule->hard_timeout == fm->hard_timeout
    2158         [ +  - ]:         35 :                 && rule->importance == fm->importance
    2159         [ +  - ]:         35 :                 && rule->flags == (fm->flags & OFPUTIL_FF_STATE)
    2160 [ +  - ][ +  - ]:         35 :                 && (!fm->modify_cookie || (fm->new_cookie == rule->flow_cookie))
    2161         [ +  + ]:         35 :                 && ofpacts_equal(fm->ofpacts, fm->ofpacts_len,
    2162                 :         70 :                                  actions->ofpacts, actions->ofpacts_len)) {
    2163                 :            :                 /* Rule already exists and need not change, only update the
    2164                 :            :                    modified timestamp. */
    2165                 :         34 :                 rule->modified = time_msec();
    2166                 :         34 :                 done = true;
    2167                 :            :             }
    2168                 :         35 :             ovs_mutex_unlock(&rule->mutex);
    2169                 :            :         }
    2170                 :            : 
    2171         [ +  + ]:         51 :         if (done) {
    2172                 :         34 :             return 0;
    2173                 :            :         }
    2174                 :            :     }
    2175                 :            : 
    2176                 :       5317 :     return handle_flow_mod__(ofproto, fm, NULL);
    2177                 :            : }
    2178                 :            : 
    2179                 :            : /* Searches for a rule with matching criteria exactly equal to 'target' in
    2180                 :            :  * ofproto's table 0 and, if it finds one, deletes it.
    2181                 :            :  *
    2182                 :            :  * This is a helper function for in-band control and fail-open. */
    2183                 :            : void
    2184                 :          0 : ofproto_delete_flow(struct ofproto *ofproto,
    2185                 :            :                     const struct match *target, int priority)
    2186                 :            :     OVS_EXCLUDED(ofproto_mutex)
    2187                 :            : {
    2188                 :          0 :     struct classifier *cls = &ofproto->tables[0].cls;
    2189                 :            :     struct rule *rule;
    2190                 :            : 
    2191                 :            :     /* First do a cheap check whether the rule we're looking for has already
    2192                 :            :      * been deleted.  If so, then we're done. */
    2193                 :          0 :     rule = rule_from_cls_rule(classifier_find_match_exactly(
    2194                 :            :                                   cls, target, priority, OVS_VERSION_MAX));
    2195         [ #  # ]:          0 :     if (!rule) {
    2196                 :          0 :         return;
    2197                 :            :     }
    2198                 :            : 
    2199                 :            :     /* Execute a flow mod.  We can't optimize this at all because we didn't
    2200                 :            :      * take enough locks above to ensure that the flow table didn't already
    2201                 :            :      * change beneath us. */
    2202                 :          0 :     simple_flow_mod(ofproto, target, priority, NULL, 0, OFPFC_DELETE_STRICT);
    2203                 :            : }
    2204                 :            : 
    2205                 :            : /* Delete all of the flows from all of ofproto's flow tables, then reintroduce
    2206                 :            :  * the flows required by in-band control and fail-open.  */
    2207                 :            : void
    2208                 :        146 : ofproto_flush_flows(struct ofproto *ofproto)
    2209                 :            : {
    2210                 :        146 :     COVERAGE_INC(ofproto_flush);
    2211                 :        146 :     ofproto_flush__(ofproto);
    2212                 :        146 :     connmgr_flushed(ofproto->connmgr);
    2213                 :        146 : }
    2214                 :            : 
    2215                 :            : static void
    2216                 :          0 : reinit_ports(struct ofproto *p)
    2217                 :            : {
    2218                 :            :     struct ofproto_port_dump dump;
    2219                 :            :     struct sset devnames;
    2220                 :            :     struct ofport *ofport;
    2221                 :            :     struct ofproto_port ofproto_port;
    2222                 :            :     const char *devname;
    2223                 :            : 
    2224                 :          0 :     COVERAGE_INC(ofproto_reinit_ports);
    2225                 :            : 
    2226                 :          0 :     sset_init(&devnames);
    2227 [ #  # ][ #  # ]:          0 :     HMAP_FOR_EACH (ofport, hmap_node, &p->ports) {
    2228                 :          0 :         sset_add(&devnames, netdev_get_name(ofport->netdev));
    2229                 :            :     }
    2230 [ #  # ][ #  # ]:          0 :     OFPROTO_PORT_FOR_EACH (&ofproto_port, &dump, p) {
    2231                 :          0 :         sset_add(&devnames, ofproto_port.name);
    2232                 :            :     }
    2233                 :            : 
    2234 [ #  # ][ #  # ]:          0 :     SSET_FOR_EACH (devname, &devnames) {
                 [ #  # ]
    2235                 :          0 :         update_port(p, devname);
    2236                 :            :     }
    2237                 :          0 :     sset_destroy(&devnames);
    2238                 :          0 : }
    2239                 :            : 
    2240                 :            : static ofp_port_t
    2241                 :       1941 : alloc_ofp_port(struct ofproto *ofproto, const char *netdev_name)
    2242                 :            : {
    2243                 :            :     uint16_t port_idx;
    2244                 :            : 
    2245                 :       1941 :     port_idx = simap_get(&ofproto->ofp_requests, netdev_name);
    2246         [ +  - ]:       1941 :     port_idx = port_idx ? port_idx : UINT16_MAX;
    2247                 :            : 
    2248         [ +  + ]:       1941 :     if (port_idx >= ofproto->max_ports
    2249         [ +  + ]:       1002 :         || ofport_get_usage(ofproto, u16_to_ofp(port_idx)) == LLONG_MAX) {
    2250                 :        995 :         uint16_t lru_ofport = 0, end_port_no = ofproto->alloc_port_no;
    2251                 :        995 :         long long int last_used_at, lru = LLONG_MAX;
    2252                 :            : 
    2253                 :            :         /* Search for a free OpenFlow port number.  We try not to
    2254                 :            :          * immediately reuse them to prevent problems due to old
    2255                 :            :          * flows.
    2256                 :            :          *
    2257                 :            :          * We limit the automatically assigned port numbers to the lower half
    2258                 :            :          * of the port range, to reserve the upper half for assignment by
    2259                 :            :          * controllers. */
    2260                 :            :         for (;;) {
    2261 [ -  + ][ -  + ]:       1015 :             if (++ofproto->alloc_port_no >= MIN(ofproto->max_ports, 32768)) {
    2262                 :          0 :                 ofproto->alloc_port_no = 1;
    2263                 :            :             }
    2264                 :       1015 :             last_used_at = ofport_get_usage(ofproto,
    2265                 :       1015 :                                          u16_to_ofp(ofproto->alloc_port_no));
    2266         [ +  + ]:       1015 :             if (!last_used_at) {
    2267                 :        995 :                 port_idx = ofproto->alloc_port_no;
    2268                 :        995 :                 break;
    2269         [ -  + ]:         20 :             } else if ( last_used_at < time_msec() - 60*60*1000) {
    2270                 :            :                 /* If the port with ofport 'ofproto->alloc_port_no' was deleted
    2271                 :            :                  * more than an hour ago, consider it usable. */
    2272                 :          0 :                 ofport_remove_usage(ofproto,
    2273                 :          0 :                     u16_to_ofp(ofproto->alloc_port_no));
    2274                 :          0 :                 port_idx = ofproto->alloc_port_no;
    2275                 :          0 :                 break;
    2276         [ +  + ]:         20 :             } else if (last_used_at < lru) {
    2277                 :          3 :                 lru = last_used_at;
    2278                 :          3 :                 lru_ofport = ofproto->alloc_port_no;
    2279                 :            :             }
    2280                 :            : 
    2281         [ -  + ]:         20 :             if (ofproto->alloc_port_no == end_port_no) {
    2282         [ #  # ]:          0 :                 if (lru_ofport) {
    2283                 :          0 :                     port_idx = lru_ofport;
    2284                 :          0 :                     break;
    2285                 :            :                 }
    2286                 :          0 :                 return OFPP_NONE;
    2287                 :            :             }
    2288                 :         20 :         }
    2289                 :            :     }
    2290                 :       1941 :     ofport_set_usage(ofproto, u16_to_ofp(port_idx), LLONG_MAX);
    2291                 :       1941 :     return u16_to_ofp(port_idx);
    2292                 :            : }
    2293                 :            : 
    2294                 :            : static void
    2295                 :       2689 : dealloc_ofp_port(struct ofproto *ofproto, ofp_port_t ofp_port)
    2296                 :            : {
    2297         [ +  + ]:       2689 :     if (ofp_to_u16(ofp_port) < ofproto->max_ports) {
    2298                 :       1940 :         ofport_set_usage(ofproto, ofp_port, time_msec());
    2299                 :            :     }
    2300                 :       2689 : }
    2301                 :            : 
    2302                 :            : /* Opens and returns a netdev for 'ofproto_port' in 'ofproto', or a null
    2303                 :            :  * pointer if the netdev cannot be opened.  On success, also fills in
    2304                 :            :  * '*pp'.  */
    2305                 :            : static struct netdev *
    2306                 :       7696 : ofport_open(struct ofproto *ofproto,
    2307                 :            :             struct ofproto_port *ofproto_port,
    2308                 :            :             struct ofputil_phy_port *pp)
    2309                 :            : {
    2310                 :            :     enum netdev_flags flags;
    2311                 :            :     struct netdev *netdev;
    2312                 :            :     int error;
    2313                 :            : 
    2314                 :       7696 :     error = netdev_open(ofproto_port->name, ofproto_port->type, &netdev);
    2315         [ -  + ]:       7696 :     if (error) {
    2316         [ #  # ]:          0 :         VLOG_WARN_RL(&rl, "%s: ignoring port %s (%"PRIu16") because netdev %s "
    2317                 :            :                      "cannot be opened (%s)",
    2318                 :            :                      ofproto->name,
    2319                 :            :                      ofproto_port->name, ofproto_port->ofp_port,
    2320                 :            :                      ofproto_port->name, ovs_strerror(error));
    2321                 :          0 :         return NULL;
    2322                 :            :     }
    2323                 :            : 
    2324         [ +  + ]:       7696 :     if (ofproto_port->ofp_port == OFPP_NONE) {
    2325         [ +  + ]:       2690 :         if (!strcmp(ofproto->name, ofproto_port->name)) {
    2326                 :        749 :             ofproto_port->ofp_port = OFPP_LOCAL;
    2327                 :            :         } else {
    2328                 :       1941 :             ofproto_port->ofp_port = alloc_ofp_port(ofproto,
    2329                 :       1941 :                                                     ofproto_port->name);
    2330                 :            :         }
    2331                 :            :     }
    2332                 :       7696 :     pp->port_no = ofproto_port->ofp_port;
    2333                 :       7696 :     netdev_get_etheraddr(netdev, &pp->hw_addr);
    2334                 :       7696 :     ovs_strlcpy(pp->name, ofproto_port->name, sizeof pp->name);
    2335                 :       7696 :     netdev_get_flags(netdev, &flags);
    2336                 :       7696 :     pp->config = flags & NETDEV_UP ? 0 : OFPUTIL_PC_PORT_DOWN;
    2337         [ +  + ]:       7696 :     pp->state = netdev_get_carrier(netdev) ? 0 : OFPUTIL_PS_LINK_DOWN;
    2338                 :       7696 :     netdev_get_features(netdev, &pp->curr, &pp->advertised,
    2339                 :            :                         &pp->supported, &pp->peer);
    2340                 :       7696 :     pp->curr_speed = netdev_features_to_bps(pp->curr, 0) / 1000;
    2341                 :       7696 :     pp->max_speed = netdev_features_to_bps(pp->supported, 0) / 1000;
    2342                 :            : 
    2343                 :       7696 :     return netdev;
    2344                 :            : }
    2345                 :            : 
    2346                 :            : /* Returns true if most fields of 'a' and 'b' are equal.  Differences in name,
    2347                 :            :  * port number, and 'config' bits other than OFPUTIL_PC_PORT_DOWN are
    2348                 :            :  * disregarded. */
    2349                 :            : static bool
    2350                 :       5006 : ofport_equal(const struct ofputil_phy_port *a,
    2351                 :            :              const struct ofputil_phy_port *b)
    2352                 :            : {
    2353                 :      10012 :     return (eth_addr_equals(a->hw_addr, b->hw_addr)
    2354         [ +  + ]:       4254 :             && a->state == b->state
    2355         [ +  - ]:       4081 :             && !((a->config ^ b->config) & OFPUTIL_PC_PORT_DOWN)
    2356         [ +  - ]:       4081 :             && a->curr == b->curr
    2357         [ +  - ]:       4081 :             && a->advertised == b->advertised
    2358         [ +  - ]:       4081 :             && a->supported == b->supported
    2359         [ +  - ]:       4081 :             && a->peer == b->peer
    2360         [ +  - ]:       4081 :             && a->curr_speed == b->curr_speed
    2361 [ +  + ][ +  - ]:       9260 :             && a->max_speed == b->max_speed);
    2362                 :            : }
    2363                 :            : 
    2364                 :            : /* Adds an ofport to 'p' initialized based on the given 'netdev' and 'opp'.
    2365                 :            :  * The caller must ensure that 'p' does not have a conflicting ofport (that is,
    2366                 :            :  * one with the same name or port number). */
    2367                 :            : static int
    2368                 :       2690 : ofport_install(struct ofproto *p,
    2369                 :            :                struct netdev *netdev, const struct ofputil_phy_port *pp)
    2370                 :            : {
    2371                 :       2690 :     const char *netdev_name = netdev_get_name(netdev);
    2372                 :            :     struct ofport *ofport;
    2373                 :            :     int error;
    2374                 :            : 
    2375                 :            :     /* Create ofport. */
    2376                 :       2690 :     ofport = p->ofproto_class->port_alloc();
    2377         [ -  + ]:       2690 :     if (!ofport) {
    2378                 :          0 :         error = ENOMEM;
    2379                 :          0 :         goto error;
    2380                 :            :     }
    2381                 :       2690 :     ofport->ofproto = p;
    2382                 :       2690 :     ofport->netdev = netdev;
    2383                 :       2690 :     ofport->change_seq = netdev_get_change_seq(netdev);
    2384                 :       2690 :     ofport->pp = *pp;
    2385                 :       2690 :     ofport->ofp_port = pp->port_no;
    2386                 :       2690 :     ofport->created = time_msec();
    2387                 :            : 
    2388                 :            :     /* Add port to 'p'. */
    2389                 :       2690 :     hmap_insert(&p->ports, &ofport->hmap_node,
    2390                 :            :                 hash_ofp_port(ofport->ofp_port));
    2391                 :       2690 :     shash_add(&p->port_by_name, netdev_name, ofport);
    2392                 :            : 
    2393                 :       2690 :     update_mtu(p, ofport);
    2394                 :            : 
    2395                 :            :     /* Let the ofproto_class initialize its private data. */
    2396                 :       2690 :     error = p->ofproto_class->port_construct(ofport);
    2397         [ +  + ]:       2690 :     if (error) {
    2398                 :          1 :         goto error;
    2399                 :            :     }
    2400                 :       2689 :     connmgr_send_port_status(p->connmgr, NULL, pp, OFPPR_ADD);
    2401                 :       2689 :     return 0;
    2402                 :            : 
    2403                 :            : error:
    2404         [ +  - ]:          1 :     VLOG_WARN_RL(&rl, "%s: could not add port %s (%s)",
    2405                 :            :                  p->name, netdev_name, ovs_strerror(error));
    2406         [ +  - ]:          1 :     if (ofport) {
    2407                 :          1 :         ofport_destroy__(ofport);
    2408                 :            :     } else {
    2409                 :          0 :         netdev_close(netdev);
    2410                 :            :     }
    2411                 :          1 :     return error;
    2412                 :            : }
    2413                 :            : 
    2414                 :            : /* Removes 'ofport' from 'p' and destroys it. */
    2415                 :            : static void
    2416                 :        387 : ofport_remove(struct ofport *ofport)
    2417                 :            : {
    2418                 :        387 :     struct ofproto *p = ofport->ofproto;
    2419                 :        387 :     bool is_mtu_overridden = ofport_is_mtu_overridden(p, ofport);
    2420                 :            : 
    2421                 :        387 :     connmgr_send_port_status(ofport->ofproto->connmgr, NULL, &ofport->pp,
    2422                 :            :                              OFPPR_DELETE);
    2423                 :        387 :     ofport_destroy(ofport, true);
    2424         [ +  - ]:        387 :     if (!is_mtu_overridden) {
    2425                 :        387 :         update_mtu_ofproto(p);
    2426                 :            :     }
    2427                 :        387 : }
    2428                 :            : 
    2429                 :            : /* If 'ofproto' contains an ofport named 'name', removes it from 'ofproto' and
    2430                 :            :  * destroys it. */
    2431                 :            : static void
    2432                 :       3077 : ofport_remove_with_name(struct ofproto *ofproto, const char *name)
    2433                 :            : {
    2434                 :       3077 :     struct ofport *port = shash_find_data(&ofproto->port_by_name, name);
    2435         [ +  + ]:       3077 :     if (port) {
    2436                 :        387 :         ofport_remove(port);
    2437                 :            :     }
    2438                 :       3077 : }
    2439                 :            : 
    2440                 :            : /* Updates 'port' with new 'pp' description.
    2441                 :            :  *
    2442                 :            :  * Does not handle a name or port number change.  The caller must implement
    2443                 :            :  * such a change as a delete followed by an add.  */
    2444                 :            : static void
    2445                 :        925 : ofport_modified(struct ofport *port, struct ofputil_phy_port *pp)
    2446                 :            : {
    2447                 :        925 :     port->pp.hw_addr = pp->hw_addr;
    2448                 :       1850 :     port->pp.config = ((port->pp.config & ~OFPUTIL_PC_PORT_DOWN)
    2449                 :        925 :                         | (pp->config & OFPUTIL_PC_PORT_DOWN));
    2450                 :       1850 :     port->pp.state = ((port->pp.state & ~OFPUTIL_PS_LINK_DOWN)
    2451                 :        925 :                       | (pp->state & OFPUTIL_PS_LINK_DOWN));
    2452                 :        925 :     port->pp.curr = pp->curr;
    2453                 :        925 :     port->pp.advertised = pp->advertised;
    2454                 :        925 :     port->pp.supported = pp->supported;
    2455                 :        925 :     port->pp.peer = pp->peer;
    2456                 :        925 :     port->pp.curr_speed = pp->curr_speed;
    2457                 :        925 :     port->pp.max_speed = pp->max_speed;
    2458                 :            : 
    2459                 :        925 :     connmgr_send_port_status(port->ofproto->connmgr, NULL,
    2460                 :        925 :                              &port->pp, OFPPR_MODIFY);
    2461                 :        925 : }
    2462                 :            : 
    2463                 :            : /* Update OpenFlow 'state' in 'port' and notify controller. */
    2464                 :            : void
    2465                 :         14 : ofproto_port_set_state(struct ofport *port, enum ofputil_port_state state)
    2466                 :            : {
    2467         [ +  + ]:         14 :     if (port->pp.state != state) {
    2468                 :         10 :         port->pp.state = state;
    2469                 :         10 :         connmgr_send_port_status(port->ofproto->connmgr, NULL,
    2470                 :         10 :                                  &port->pp, OFPPR_MODIFY);
    2471                 :            :     }
    2472                 :         14 : }
    2473                 :            : 
    2474                 :            : void
    2475                 :       2689 : ofproto_port_unregister(struct ofproto *ofproto, ofp_port_t ofp_port)
    2476                 :            : {
    2477                 :       2689 :     struct ofport *port = ofproto_get_port(ofproto, ofp_port);
    2478         [ +  + ]:       2689 :     if (port) {
    2479         [ +  - ]:       2688 :         if (port->ofproto->ofproto_class->set_stp_port) {
    2480                 :       2688 :             port->ofproto->ofproto_class->set_stp_port(port, NULL);
    2481                 :            :         }
    2482         [ +  - ]:       2688 :         if (port->ofproto->ofproto_class->set_rstp_port) {
    2483                 :       2688 :             port->ofproto->ofproto_class->set_rstp_port(port, NULL);
    2484                 :            :         }
    2485         [ +  - ]:       2688 :         if (port->ofproto->ofproto_class->set_cfm) {
    2486                 :       2688 :             port->ofproto->ofproto_class->set_cfm(port, NULL);
    2487                 :            :         }
    2488         [ +  - ]:       2688 :         if (port->ofproto->ofproto_class->bundle_remove) {
    2489                 :       2688 :             port->ofproto->ofproto_class->bundle_remove(port);
    2490                 :            :         }
    2491                 :            :     }
    2492                 :       2689 : }
    2493                 :            : 
    2494                 :            : static void
    2495                 :       2690 : ofport_destroy__(struct ofport *port)
    2496                 :            : {
    2497                 :       2690 :     struct ofproto *ofproto = port->ofproto;
    2498                 :       2690 :     const char *name = netdev_get_name(port->netdev);
    2499                 :            : 
    2500                 :       2690 :     hmap_remove(&ofproto->ports, &port->hmap_node);
    2501                 :       2690 :     shash_delete(&ofproto->port_by_name,
    2502                 :       2690 :                  shash_find(&ofproto->port_by_name, name));
    2503                 :            : 
    2504                 :       2690 :     netdev_close(port->netdev);
    2505                 :       2690 :     ofproto->ofproto_class->port_dealloc(port);
    2506                 :       2690 : }
    2507                 :            : 
    2508                 :            : static void
    2509                 :       2689 : ofport_destroy(struct ofport *port, bool del)
    2510                 :            : {
    2511         [ +  - ]:       2689 :     if (port) {
    2512                 :       2689 :         dealloc_ofp_port(port->ofproto, port->ofp_port);
    2513                 :       2689 :         port->ofproto->ofproto_class->port_destruct(port, del);
    2514                 :       2689 :         ofport_destroy__(port);
    2515                 :            :      }
    2516                 :       2689 : }
    2517                 :            : 
    2518                 :            : struct ofport *
    2519                 :     471465 : ofproto_get_port(const struct ofproto *ofproto, ofp_port_t ofp_port)
    2520                 :            : {
    2521                 :            :     struct ofport *port;
    2522                 :            : 
    2523 [ +  + ][ -  + ]:     752933 :     HMAP_FOR_EACH_IN_BUCKET (port, hmap_node, hash_ofp_port(ofp_port),
    2524                 :            :                              &ofproto->ports) {
    2525         [ +  + ]:     747856 :         if (port->ofp_port == ofp_port) {
    2526                 :     466388 :             return port;
    2527                 :            :         }
    2528                 :            :     }
    2529                 :       5077 :     return NULL;
    2530                 :            : }
    2531                 :            : 
    2532                 :            : static long long int
    2533                 :       2017 : ofport_get_usage(const struct ofproto *ofproto, ofp_port_t ofp_port)
    2534                 :            : {
    2535                 :            :     struct ofport_usage *usage;
    2536                 :            : 
    2537 [ +  + ][ -  + ]:       3333 :     HMAP_FOR_EACH_IN_BUCKET (usage, hmap_node, hash_ofp_port(ofp_port),
    2538                 :            :                              &ofproto->ofport_usage) {
    2539         [ +  + ]:       1631 :         if (usage->ofp_port == ofp_port) {
    2540                 :        315 :             return usage->last_used;
    2541                 :            :         }
    2542                 :            :     }
    2543                 :       1702 :     return 0;
    2544                 :            : }
    2545                 :            : 
    2546                 :            : static void
    2547                 :       3881 : ofport_set_usage(struct ofproto *ofproto, ofp_port_t ofp_port,
    2548                 :            :                  long long int last_used)
    2549                 :            : {
    2550                 :            :     struct ofport_usage *usage;
    2551 [ +  + ][ -  + ]:       5787 :     HMAP_FOR_EACH_IN_BUCKET (usage, hmap_node, hash_ofp_port(ofp_port),
    2552                 :            :                              &ofproto->ofport_usage) {
    2553         [ +  + ]:       4085 :         if (usage->ofp_port == ofp_port) {
    2554                 :       2179 :             usage->last_used = last_used;
    2555                 :       2179 :             return;
    2556                 :            :         }
    2557                 :            :     }
    2558         [ -  + ]:       1702 :     ovs_assert(last_used == LLONG_MAX);
    2559                 :            : 
    2560                 :       1702 :     usage = xmalloc(sizeof *usage);
    2561                 :       1702 :     usage->ofp_port = ofp_port;
    2562                 :       1702 :     usage->last_used = last_used;
    2563                 :       1702 :     hmap_insert(&ofproto->ofport_usage, &usage->hmap_node,
    2564                 :            :                 hash_ofp_port(ofp_port));
    2565                 :            : }
    2566                 :            : 
    2567                 :            : static void
    2568                 :          0 : ofport_remove_usage(struct ofproto *ofproto, ofp_port_t ofp_port)
    2569                 :            : {
    2570                 :            :     struct ofport_usage *usage;
    2571 [ #  # ][ #  # ]:          0 :     HMAP_FOR_EACH_IN_BUCKET (usage, hmap_node, hash_ofp_port(ofp_port),
    2572                 :            :                              &ofproto->ofport_usage) {
    2573         [ #  # ]:          0 :         if (usage->ofp_port == ofp_port) {
    2574                 :          0 :             hmap_remove(&ofproto->ofport_usage, &usage->hmap_node);
    2575                 :          0 :             free(usage);
    2576                 :          0 :             break;
    2577                 :            :         }
    2578                 :            :     }
    2579                 :          0 : }
    2580                 :            : 
    2581                 :            : int
    2582                 :         60 : ofproto_port_get_stats(const struct ofport *port, struct netdev_stats *stats)
    2583                 :            : {
    2584                 :         60 :     struct ofproto *ofproto = port->ofproto;
    2585                 :            :     int error;
    2586                 :            : 
    2587         [ +  - ]:         60 :     if (ofproto->ofproto_class->port_get_stats) {
    2588                 :         60 :         error = ofproto->ofproto_class->port_get_stats(port, stats);
    2589                 :            :     } else {
    2590                 :          0 :         error = EOPNOTSUPP;
    2591                 :            :     }
    2592                 :            : 
    2593                 :         60 :     return error;
    2594                 :            : }
    2595                 :            : 
    2596                 :            : static int
    2597                 :       8083 : update_port(struct ofproto *ofproto, const char *name)
    2598                 :            : {
    2599                 :            :     struct ofproto_port ofproto_port;
    2600                 :            :     struct ofputil_phy_port pp;
    2601                 :            :     struct netdev *netdev;
    2602                 :            :     struct ofport *port;
    2603                 :       8083 :     int error = 0;
    2604                 :            : 
    2605                 :       8083 :     COVERAGE_INC(ofproto_update_port);
    2606                 :            : 
    2607                 :            :     /* Fetch 'name''s location and properties from the datapath. */
    2608                 :       8083 :     netdev = (!ofproto_port_query_by_name(ofproto, name, &ofproto_port)
    2609                 :            :               ? ofport_open(ofproto, &ofproto_port, &pp)
    2610         [ +  + ]:       8083 :               : NULL);
    2611                 :            : 
    2612         [ +  + ]:       8083 :     if (netdev) {
    2613                 :       7696 :         port = ofproto_get_port(ofproto, ofproto_port.ofp_port);
    2614 [ +  + ][ +  - ]:      12702 :         if (port && !strcmp(netdev_get_name(port->netdev), name)) {
    2615                 :       5006 :             struct netdev *old_netdev = port->netdev;
    2616                 :            : 
    2617                 :            :             /* 'name' hasn't changed location.  Any properties changed? */
    2618         [ +  + ]:       5006 :             if (!ofport_equal(&port->pp, &pp)) {
    2619                 :        925 :                 ofport_modified(port, &pp);
    2620                 :            :             }
    2621                 :            : 
    2622                 :       5006 :             update_mtu(ofproto, port);
    2623                 :            : 
    2624                 :            :             /* Install the newly opened netdev in case it has changed.
    2625                 :            :              * Don't close the old netdev yet in case port_modified has to
    2626                 :            :              * remove a retained reference to it.*/
    2627                 :       5006 :             port->netdev = netdev;
    2628                 :       5006 :             port->change_seq = netdev_get_change_seq(netdev);
    2629                 :            : 
    2630         [ +  - ]:       5006 :             if (port->ofproto->ofproto_class->port_modified) {
    2631                 :       5006 :                 port->ofproto->ofproto_class->port_modified(port);
    2632                 :            :             }
    2633                 :            : 
    2634                 :       5006 :             netdev_close(old_netdev);
    2635                 :            :         } else {
    2636                 :            :             /* If 'port' is nonnull then its name differs from 'name' and thus
    2637                 :            :              * we should delete it.  If we think there's a port named 'name'
    2638                 :            :              * then its port number must be wrong now so delete it too. */
    2639         [ -  + ]:       2690 :             if (port) {
    2640                 :          0 :                 ofport_remove(port);
    2641                 :            :             }
    2642                 :       2690 :             ofport_remove_with_name(ofproto, name);
    2643                 :       7696 :             error = ofport_install(ofproto, netdev, &pp);
    2644                 :            :         }
    2645                 :            :     } else {
    2646                 :            :         /* Any port named 'name' is gone now. */
    2647                 :        387 :         ofport_remove_with_name(ofproto, name);
    2648                 :            :     }
    2649                 :       8083 :     ofproto_port_destroy(&ofproto_port);
    2650                 :            : 
    2651                 :       8083 :     return error;
    2652                 :            : }
    2653                 :            : 
    2654                 :            : static int
    2655                 :        749 : init_ports(struct ofproto *p)
    2656                 :            : {
    2657                 :            :     struct ofproto_port_dump dump;
    2658                 :            :     struct ofproto_port ofproto_port;
    2659                 :            :     struct shash_node *node, *next;
    2660                 :            : 
    2661 [ -  + ][ -  + ]:        749 :     OFPROTO_PORT_FOR_EACH (&ofproto_port, &dump, p) {
    2662                 :          0 :         const char *name = ofproto_port.name;
    2663                 :            : 
    2664         [ #  # ]:          0 :         if (shash_find(&p->port_by_name, name)) {
    2665         [ #  # ]:          0 :             VLOG_WARN_RL(&rl, "%s: ignoring duplicate device %s in datapath",
    2666                 :            :                          p->name, name);
    2667                 :            :         } else {
    2668                 :            :             struct ofputil_phy_port pp;
    2669                 :            :             struct netdev *netdev;
    2670                 :            : 
    2671                 :            :             /* Check if an OpenFlow port number had been requested. */
    2672                 :          0 :             node = shash_find(&init_ofp_ports, name);
    2673         [ #  # ]:          0 :             if (node) {
    2674                 :          0 :                 const struct iface_hint *iface_hint = node->data;
    2675                 :          0 :                 simap_put(&p->ofp_requests, name,
    2676                 :          0 :                           ofp_to_u16(iface_hint->ofp_port));
    2677                 :            :             }
    2678                 :            : 
    2679                 :          0 :             netdev = ofport_open(p, &ofproto_port, &pp);
    2680         [ #  # ]:          0 :             if (netdev) {
    2681                 :          0 :                 ofport_install(p, netdev, &pp);
    2682         [ #  # ]:          0 :                 if (ofp_to_u16(ofproto_port.ofp_port) < p->max_ports) {
    2683         [ #  # ]:          0 :                     p->alloc_port_no = MAX(p->alloc_port_no,
    2684                 :            :                                            ofp_to_u16(ofproto_port.ofp_port));
    2685                 :            :                 }
    2686                 :            :             }
    2687                 :            :         }
    2688                 :            :     }
    2689                 :            : 
    2690 [ +  + ][ -  + ]:        762 :     SHASH_FOR_EACH_SAFE(node, next, &init_ofp_ports) {
                 [ +  + ]
    2691                 :         13 :         struct iface_hint *iface_hint = node->data;
    2692                 :            : 
    2693         [ +  + ]:         13 :         if (!strcmp(iface_hint->br_name, p->name)) {
    2694                 :          9 :             free(iface_hint->br_name);
    2695                 :          9 :             free(iface_hint->br_type);
    2696                 :          9 :             free(iface_hint);
    2697                 :          9 :             shash_delete(&init_ofp_ports, node);
    2698                 :            :         }
    2699                 :            :     }
    2700                 :            : 
    2701                 :        749 :     return 0;
    2702                 :            : }
    2703                 :            : 
    2704                 :            : static bool
    2705                 :      27695 : ofport_is_internal(const struct ofproto *p, const struct ofport *port)
    2706                 :            : {
    2707                 :      27695 :     return !strcmp(netdev_get_type(port->netdev),
    2708                 :      27695 :                    ofproto_port_open_type(p->type, "internal"));
    2709                 :            : }
    2710                 :            : 
    2711                 :            : /* If 'port' is internal and if the user didn't explicitly specify an mtu
    2712                 :            :  * through the database, we have to override it. */
    2713                 :            : static bool
    2714                 :      27695 : ofport_is_mtu_overridden(const struct ofproto *p, const struct ofport *port)
    2715                 :            : {
    2716                 :      55390 :     return ofport_is_internal(p, port)
    2717 [ +  + ][ +  + ]:      27695 :            && !netdev_mtu_is_user_config(port->netdev);
    2718                 :            : }
    2719                 :            : 
    2720                 :            : /* Find the minimum MTU of all non-overridden devices attached to 'p'.
    2721                 :            :  * Returns ETH_PAYLOAD_MAX or the minimum of the ports. */
    2722                 :            : static int
    2723                 :       3795 : find_min_mtu(struct ofproto *p)
    2724                 :            : {
    2725                 :            :     struct ofport *ofport;
    2726                 :       3795 :     int mtu = 0;
    2727                 :            : 
    2728 [ +  + ][ -  + ]:      22983 :     HMAP_FOR_EACH (ofport, hmap_node, &p->ports) {
    2729                 :      19188 :         struct netdev *netdev = ofport->netdev;
    2730                 :            :         int dev_mtu;
    2731                 :            : 
    2732                 :            :         /* Skip any overridden port, since that's what we're trying to set. */
    2733         [ +  + ]:      19188 :         if (ofport_is_mtu_overridden(p, ofport)) {
    2734                 :       9923 :             continue;
    2735                 :            :         }
    2736                 :            : 
    2737         [ +  + ]:      15515 :         if (netdev_get_mtu(netdev, &dev_mtu)) {
    2738                 :       6250 :             continue;
    2739                 :            :         }
    2740 [ +  + ][ +  + ]:       9265 :         if (!mtu || dev_mtu < mtu) {
    2741                 :       9265 :             mtu = dev_mtu;
    2742                 :            :         }
    2743                 :            :     }
    2744                 :            : 
    2745         [ +  + ]:       3795 :     return mtu ? mtu: ETH_PAYLOAD_MAX;
    2746                 :            : }
    2747                 :            : 
    2748                 :            : /* Update MTU of all overridden devices on 'p' to the minimum of the
    2749                 :            :  * non-overridden ports in event of 'port' added or changed. */
    2750                 :            : static void
    2751                 :       7696 : update_mtu(struct ofproto *p, struct ofport *port)
    2752                 :            : {
    2753                 :       7696 :     struct netdev *netdev = port->netdev;
    2754                 :            :     int dev_mtu;
    2755                 :            : 
    2756         [ +  + ]:       7696 :     if (netdev_get_mtu(netdev, &dev_mtu)) {
    2757                 :        651 :         port->mtu = 0;
    2758                 :       4288 :         return;
    2759                 :            :     }
    2760         [ +  + ]:       7045 :     if (ofport_is_mtu_overridden(p, port)) {
    2761         [ +  + ]:       3637 :         if (dev_mtu > p->min_mtu) {
    2762         [ +  - ]:          1 :             if (!netdev_set_mtu(port->netdev, p->min_mtu)) {
    2763                 :          1 :                 dev_mtu = p->min_mtu;
    2764                 :            :             }
    2765                 :            :         }
    2766                 :       3637 :         port->mtu = dev_mtu;
    2767                 :       3637 :         return;
    2768                 :            :     }
    2769                 :            : 
    2770                 :       3408 :     port->mtu = dev_mtu;
    2771                 :            :     /* For non-overridden port find new min mtu. */
    2772                 :            : 
    2773                 :       3408 :     update_mtu_ofproto(p);
    2774                 :            : }
    2775                 :            : 
    2776                 :            : static void
    2777                 :       3795 : update_mtu_ofproto(struct ofproto *p)
    2778                 :            : {
    2779                 :            :     struct ofport *ofport;
    2780                 :       3795 :     int old_min = p->min_mtu;
    2781                 :            : 
    2782                 :       3795 :     p->min_mtu = find_min_mtu(p);
    2783         [ +  + ]:       3795 :     if (p->min_mtu == old_min) {
    2784                 :       3309 :         return;
    2785                 :            :     }
    2786                 :            : 
    2787 [ +  + ][ -  + ]:       1561 :     HMAP_FOR_EACH (ofport, hmap_node, &p->ports) {
    2788                 :       1075 :         struct netdev *netdev = ofport->netdev;
    2789                 :            : 
    2790         [ +  + ]:       1075 :         if (ofport_is_mtu_overridden(p, ofport)) {
    2791         [ +  - ]:        419 :             if (!netdev_set_mtu(netdev, p->min_mtu)) {
    2792                 :        419 :                 ofport->mtu = p->min_mtu;
    2793                 :            :             }
    2794                 :            :         }
    2795                 :            :     }
    2796                 :            : }
    2797                 :            : 
    2798                 :            : static void
    2799                 :      28492 : ofproto_rule_destroy__(struct rule *rule)
    2800                 :            :     OVS_NO_THREAD_SAFETY_ANALYSIS
    2801                 :            : {
    2802                 :      28492 :     cls_rule_destroy(CONST_CAST(struct cls_rule *, &rule->cr));
    2803                 :      28492 :     rule_actions_destroy(rule_get_actions(rule));
    2804                 :      28492 :     ovs_mutex_destroy(&rule->mutex);
    2805                 :      28492 :     rule->ofproto->ofproto_class->rule_dealloc(rule);
    2806                 :      28492 : }
    2807                 :            : 
    2808                 :            : static void
    2809                 :      27934 : rule_destroy_cb(struct rule *rule)
    2810                 :            :     OVS_NO_THREAD_SAFETY_ANALYSIS
    2811                 :            : {
    2812                 :            :     /* Send rule removed if needed. */
    2813         [ +  + ]:      27934 :     if (rule->flags & OFPUTIL_FF_SEND_FLOW_REM
    2814         [ +  - ]:         38 :         && rule->removed_reason != OVS_OFPRR_NONE
    2815         [ +  - ]:         38 :         && !rule_is_hidden(rule)) {
    2816                 :         38 :         ofproto_rule_send_removed(rule);
    2817                 :            :     }
    2818                 :      27934 :     rule->ofproto->ofproto_class->rule_destruct(rule);
    2819                 :      27934 :     ofproto_rule_destroy__(rule);
    2820                 :      27934 : }
    2821                 :            : 
    2822                 :            : void
    2823                 :    1158469 : ofproto_rule_ref(struct rule *rule)
    2824                 :            : {
    2825         [ +  - ]:    1158469 :     if (rule) {
    2826                 :    1158469 :         ovs_refcount_ref(&rule->ref_count);
    2827                 :            :     }
    2828                 :    1158469 : }
    2829                 :            : 
    2830                 :            : bool
    2831                 :          0 : ofproto_rule_try_ref(struct rule *rule)
    2832                 :            : {
    2833         [ #  # ]:          0 :     if (rule) {
    2834                 :          0 :         return ovs_refcount_try_ref_rcu(&rule->ref_count);
    2835                 :            :     }
    2836                 :          0 :     return false;
    2837                 :            : }
    2838                 :            : 
    2839                 :            : /* Decrements 'rule''s ref_count and schedules 'rule' to be destroyed if the
    2840                 :            :  * ref_count reaches 0.
    2841                 :            :  *
    2842                 :            :  * Use of RCU allows short term use (between RCU quiescent periods) without
    2843                 :            :  * keeping a reference.  A reference must be taken if the rule needs to
    2844                 :            :  * stay around accross the RCU quiescent periods. */
    2845                 :            : void
    2846                 :    1188976 : ofproto_rule_unref(struct rule *rule)
    2847                 :            : {
    2848 [ +  - ][ +  + ]:    1188976 :     if (rule && ovs_refcount_unref_relaxed(&rule->ref_count) == 1) {
    2849                 :      30526 :         ovsrcu_postpone(rule_destroy_cb, rule);
    2850                 :            :     }
    2851                 :    1188976 : }
    2852                 :            : 
    2853                 :            : static void
    2854                 :      26218 : remove_rule_rcu__(struct rule *rule)
    2855                 :            :     OVS_REQUIRES(ofproto_mutex)
    2856                 :            : {
    2857                 :      26218 :     struct ofproto *ofproto = rule->ofproto;
    2858                 :      26218 :     struct oftable *table = &ofproto->tables[rule->table_id];
    2859                 :            : 
    2860         [ -  + ]:      26218 :     ovs_assert(!cls_rule_visible_in_version(&rule->cr, OVS_VERSION_MAX));
    2861         [ -  + ]:      26218 :     if (!classifier_remove(&table->cls, &rule->cr)) {
    2862                 :          0 :         OVS_NOT_REACHED();
    2863                 :            :     }
    2864         [ -  + ]:      26218 :     if (ofproto->ofproto_class->rule_delete) {
    2865                 :          0 :         ofproto->ofproto_class->rule_delete(rule);
    2866                 :            :     }
    2867                 :      26218 :     ofproto_rule_unref(rule);
    2868                 :      26218 : }
    2869                 :            : 
    2870                 :            : static void
    2871                 :       7664 : remove_rule_rcu(struct rule *rule)
    2872                 :            :     OVS_EXCLUDED(ofproto_mutex)
    2873                 :            : {
    2874                 :       7664 :     ovs_mutex_lock(&ofproto_mutex);
    2875                 :       7664 :     remove_rule_rcu__(rule);
    2876                 :       7664 :     ovs_mutex_unlock(&ofproto_mutex);
    2877                 :       7664 : }
    2878                 :            : 
    2879                 :            : /* Removes and deletes rules from a NULL-terminated array of rule pointers. */
    2880                 :            : static void
    2881                 :       1134 : remove_rules_rcu(struct rule **rules)
    2882                 :            :     OVS_EXCLUDED(ofproto_mutex)
    2883                 :            : {
    2884                 :       1134 :     struct rule **orig_rules = rules;
    2885                 :            : 
    2886         [ +  - ]:       1134 :     if (*rules) {
    2887                 :       1134 :         struct ofproto *ofproto = rules[0]->ofproto;
    2888                 :            :         unsigned long tables[BITMAP_N_LONGS(256)];
    2889                 :            :         struct rule *rule;
    2890                 :            :         size_t table_id;
    2891                 :            : 
    2892                 :       1134 :         memset(tables, 0, sizeof tables);
    2893                 :            : 
    2894                 :       1134 :         ovs_mutex_lock(&ofproto_mutex);
    2895         [ +  + ]:      19688 :         while ((rule = *rules++)) {
    2896                 :            :             /* Defer once for each new table.  This defers the subtable cleanup
    2897                 :            :              * until later, so that when removing large number of flows the
    2898                 :            :              * operation is faster. */
    2899         [ +  + ]:      18554 :             if (!bitmap_is_set(tables, rule->table_id)) {
    2900                 :       1188 :                 struct classifier *cls = &ofproto->tables[rule->table_id].cls;
    2901                 :            : 
    2902                 :       1188 :                 bitmap_set1(tables, rule->table_id);
    2903                 :       1188 :                 classifier_defer(cls);
    2904                 :            :             }
    2905                 :      18554 :             remove_rule_rcu__(rule);
    2906                 :            :         }
    2907                 :            : 
    2908         [ +  + ]:       2322 :         BITMAP_FOR_EACH_1(table_id, 256, tables) {
    2909                 :       1188 :             struct classifier *cls = &ofproto->tables[table_id].cls;
    2910                 :            : 
    2911                 :       1188 :             classifier_publish(cls);
    2912                 :            :         }
    2913                 :       1134 :         ovs_mutex_unlock(&ofproto_mutex);
    2914                 :            :     }
    2915                 :            : 
    2916                 :       1134 :     free(orig_rules);
    2917                 :       1134 : }
    2918                 :            : 
    2919                 :            : void
    2920                 :          0 : ofproto_group_ref(struct ofgroup *group)
    2921                 :            : {
    2922         [ #  # ]:          0 :     if (group) {
    2923                 :          0 :         ovs_refcount_ref(&group->ref_count);
    2924                 :            :     }
    2925                 :          0 : }
    2926                 :            : 
    2927                 :            : bool
    2928                 :         50 : ofproto_group_try_ref(struct ofgroup *group)
    2929                 :            : {
    2930         [ +  - ]:         50 :     if (group) {
    2931                 :         50 :         return ovs_refcount_try_ref_rcu(&group->ref_count);
    2932                 :            :     }
    2933                 :          0 :     return false;
    2934                 :            : }
    2935                 :            : 
    2936                 :            : static void
    2937                 :         74 : group_destroy_cb(struct ofgroup *group)
    2938                 :            : {
    2939                 :         74 :     group->ofproto->ofproto_class->group_destruct(group);
    2940                 :         74 :     ofputil_group_properties_destroy(CONST_CAST(struct ofputil_group_props *,
    2941                 :            :                                                 &group->props));
    2942                 :         74 :     ofputil_bucket_list_destroy(CONST_CAST(struct ovs_list *,
    2943                 :            :                                            &group->buckets));
    2944                 :         74 :     group->ofproto->ofproto_class->group_dealloc(group);
    2945                 :         74 : }
    2946                 :            : 
    2947                 :            : void
    2948                 :        124 : ofproto_group_unref(struct ofgroup *group)
    2949                 :            :     OVS_NO_THREAD_SAFETY_ANALYSIS
    2950                 :            : {
    2951 [ +  - ][ +  + ]:        124 :     if (group && ovs_refcount_unref_relaxed(&group->ref_count) == 1) {
    2952         [ -  + ]:         74 :         ovs_assert(rule_collection_n(&group->rules) == 0);
    2953                 :         74 :         ovsrcu_postpone(group_destroy_cb, group);
    2954                 :            :     }
    2955                 :        124 : }
    2956                 :            : 
    2957                 :            : static void
    2958                 :         69 : remove_group_rcu__(struct ofgroup *group)
    2959                 :            :     OVS_REQUIRES(ofproto_mutex)
    2960                 :            : {
    2961                 :         69 :     struct ofproto *ofproto = group->ofproto;
    2962                 :            : 
    2963         [ -  + ]:         69 :     ovs_assert(!versions_visible_in_version(&group->versions, OVS_VERSION_MAX));
    2964                 :            : 
    2965                 :         69 :     cmap_remove(&ofproto->groups, &group->cmap_node,
    2966                 :            :                 hash_int(group->group_id, 0));
    2967                 :         69 :     ofproto_group_unref(group);
    2968                 :         69 : }
    2969                 :            : 
    2970                 :            : static void
    2971                 :         57 : remove_group_rcu(struct ofgroup *group)
    2972                 :            :     OVS_EXCLUDED(ofproto_mutex)
    2973                 :            : {
    2974                 :         57 :     ovs_mutex_lock(&ofproto_mutex);
    2975                 :         57 :     remove_group_rcu__(group);
    2976                 :         57 :     ovs_mutex_unlock(&ofproto_mutex);
    2977                 :         57 : }
    2978                 :            : 
    2979                 :            : /* Removes and deletes groups from a NULL-terminated array of group
    2980                 :            :  * pointers. */
    2981                 :            : static void
    2982                 :          5 : remove_groups_rcu(struct ofgroup **groups)
    2983                 :            :     OVS_EXCLUDED(ofproto_mutex)
    2984                 :            : {
    2985                 :          5 :     ovs_mutex_lock(&ofproto_mutex);
    2986         [ +  + ]:         17 :     for (struct ofgroup **g = groups; *g; g++) {
    2987                 :         12 :         remove_group_rcu__(*g);
    2988                 :            :     }
    2989                 :          5 :     ovs_mutex_unlock(&ofproto_mutex);
    2990                 :          5 :     free(groups);
    2991                 :          5 : }
    2992                 :            : 
    2993                 :            : static uint32_t get_provider_meter_id(const struct ofproto *,
    2994                 :            :                                       uint32_t of_meter_id);
    2995                 :            : 
    2996                 :            : /* Creates and returns a new 'struct rule_actions', whose actions are a copy
    2997                 :            :  * of from the 'ofpacts_len' bytes of 'ofpacts'. */
    2998                 :            : const struct rule_actions *
    2999                 :      32020 : rule_actions_create(const struct ofpact *ofpacts, size_t ofpacts_len)
    3000                 :            : {
    3001                 :            :     struct rule_actions *actions;
    3002                 :            : 
    3003                 :      32020 :     actions = xmalloc(sizeof *actions + ofpacts_len);
    3004                 :      32020 :     actions->ofpacts_len = ofpacts_len;
    3005                 :      32020 :     memcpy(actions->ofpacts, ofpacts, ofpacts_len);
    3006                 :      32020 :     actions->has_meter = ofpacts_get_meter(ofpacts, ofpacts_len) != 0;
    3007                 :      32020 :     actions->has_groups =
    3008                 :      32020 :         (ofpact_find_type_flattened(ofpacts, OFPACT_GROUP,
    3009                 :      32020 :                                     ofpact_end(ofpacts, ofpacts_len))
    3010                 :      32020 :          != NULL);
    3011                 :      32020 :     actions->has_learn_with_delete = (next_learn_with_delete(actions, NULL)
    3012                 :      32020 :                                       != NULL);
    3013                 :            : 
    3014                 :      32020 :     return actions;
    3015                 :            : }
    3016                 :            : 
    3017                 :            : /* Free the actions after the RCU quiescent period is reached. */
    3018                 :            : void
    3019                 :      28492 : rule_actions_destroy(const struct rule_actions *actions)
    3020                 :            : {
    3021         [ +  - ]:      28492 :     if (actions) {
    3022                 :      28492 :         ovsrcu_postpone(free, CONST_CAST(struct rule_actions *, actions));
    3023                 :            :     }
    3024                 :      28492 : }
    3025                 :            : 
    3026                 :            : /* Returns true if 'rule' has an OpenFlow OFPAT_OUTPUT or OFPAT_ENQUEUE action
    3027                 :            :  * that outputs to 'port' (output to OFPP_FLOOD and OFPP_ALL doesn't count). */
    3028                 :            : bool
    3029                 :      38230 : ofproto_rule_has_out_port(const struct rule *rule, ofp_port_t port)
    3030                 :            :     OVS_REQUIRES(ofproto_mutex)
    3031                 :            : {
    3032         [ +  + ]:      38230 :     if (port == OFPP_ANY) {
    3033                 :      37676 :         return true;
    3034                 :            :     } else {
    3035                 :        554 :         const struct rule_actions *actions = rule_get_actions(rule);
    3036                 :        554 :         return ofpacts_output_to_port(actions->ofpacts,
    3037                 :        554 :                                       actions->ofpacts_len, port);
    3038                 :            :     }
    3039                 :            : }
    3040                 :            : 
    3041                 :            : /* Returns true if 'rule' has group and equals group_id. */
    3042                 :            : static bool
    3043                 :      32400 : ofproto_rule_has_out_group(const struct rule *rule, uint32_t group_id)
    3044                 :            :     OVS_REQUIRES(ofproto_mutex)
    3045                 :            : {
    3046         [ +  - ]:      32400 :     if (group_id == OFPG_ANY) {
    3047                 :      32400 :         return true;
    3048                 :            :     } else {
    3049                 :          0 :         const struct rule_actions *actions = rule_get_actions(rule);
    3050                 :          0 :         return ofpacts_output_to_group(actions->ofpacts,
    3051                 :          0 :                                        actions->ofpacts_len, group_id);
    3052                 :            :     }
    3053                 :            : }
    3054                 :            : 
    3055                 :            : static bool
    3056                 :      32389 : rule_is_readonly(const struct rule *rule)
    3057                 :            : {
    3058                 :      32389 :     const struct oftable *table = &rule->ofproto->tables[rule->table_id];
    3059                 :      32389 :     return (table->flags & OFTABLE_READONLY) != 0;
    3060                 :            : }
    3061                 :            : 
    3062                 :            : static uint32_t
    3063                 :         22 : hash_learned_cookie(ovs_be64 cookie_, uint8_t table_id)
    3064                 :            : {
    3065                 :         22 :     uint64_t cookie = (OVS_FORCE uint64_t) cookie_;
    3066                 :         22 :     return hash_3words(cookie, cookie >> 32, table_id);
    3067                 :            : }
    3068                 :            : 
    3069                 :            : static void
    3070                 :         22 : learned_cookies_update_one__(struct ofproto *ofproto,
    3071                 :            :                              const struct ofpact_learn *learn,
    3072                 :            :                              int delta, struct ovs_list *dead_cookies)
    3073                 :            :     OVS_REQUIRES(ofproto_mutex)
    3074                 :            : {
    3075                 :         22 :     uint32_t hash = hash_learned_cookie(learn->cookie, learn->table_id);
    3076                 :            :     struct learned_cookie *c;
    3077                 :            : 
    3078 [ +  + ][ -  + ]:         22 :     HMAP_FOR_EACH_WITH_HASH (c, u.hmap_node, hash, &ofproto->learned_cookies) {
    3079 [ +  - ][ +  - ]:         15 :         if (c->cookie == learn->cookie && c->table_id == learn->table_id) {
    3080                 :         15 :             c->n += delta;
    3081         [ -  + ]:         15 :             ovs_assert(c->n >= 0);
    3082                 :            : 
    3083         [ +  + ]:         15 :             if (!c->n) {
    3084                 :          7 :                 hmap_remove(&ofproto->learned_cookies, &c->u.hmap_node);
    3085                 :          7 :                 ovs_list_push_back(dead_cookies, &c->u.list_node);
    3086                 :            :             }
    3087                 :            : 
    3088                 :         15 :             return;
    3089                 :            :         }
    3090                 :            :     }
    3091                 :            : 
    3092         [ -  + ]:          7 :     ovs_assert(delta > 0);
    3093                 :          7 :     c = xmalloc(sizeof *c);
    3094                 :          7 :     hmap_insert(&ofproto->learned_cookies, &c->u.hmap_node, hash);
    3095                 :          7 :     c->cookie = learn->cookie;
    3096                 :          7 :     c->table_id = learn->table_id;
    3097                 :          7 :     c->n = delta;
    3098                 :            : }
    3099                 :            : 
    3100                 :            : static const struct ofpact_learn *
    3101                 :      32064 : next_learn_with_delete(const struct rule_actions *actions,
    3102                 :            :                        const struct ofpact_learn *start)
    3103                 :            : {
    3104                 :            :     const struct ofpact *pos;
    3105                 :            : 
    3106 [ +  + ][ +  + ]:     104359 :     for (pos = start ? ofpact_next(&start->ofpact) : actions->ofpacts;
    3107                 :      72295 :          pos < ofpact_end(actions->ofpacts, actions->ofpacts_len);
    3108                 :      40231 :          pos = ofpact_next(pos)) {
    3109         [ +  + ]:      40264 :         if (pos->type == OFPACT_LEARN) {
    3110                 :         53 :             const struct ofpact_learn *learn = ofpact_get_LEARN(pos);
    3111         [ +  + ]:         53 :             if (learn->flags & NX_LEARN_F_DELETE_LEARNED) {
    3112                 :         33 :                 return learn;
    3113                 :            :             }
    3114                 :            :         }
    3115                 :            :     }
    3116                 :            : 
    3117                 :      32031 :     return NULL;
    3118                 :            : }
    3119                 :            : 
    3120                 :            : static void
    3121                 :      58584 : learned_cookies_update__(struct ofproto *ofproto,
    3122                 :            :                          const struct rule_actions *actions,
    3123                 :            :                          int delta, struct ovs_list *dead_cookies)
    3124                 :            :     OVS_REQUIRES(ofproto_mutex)
    3125                 :            : {
    3126         [ +  + ]:      58584 :     if (actions->has_learn_with_delete) {
    3127                 :            :         const struct ofpact_learn *learn;
    3128                 :            : 
    3129         [ +  + ]:         44 :         for (learn = next_learn_with_delete(actions, NULL); learn;
    3130                 :         22 :              learn = next_learn_with_delete(actions, learn)) {
    3131                 :         22 :             learned_cookies_update_one__(ofproto, learn, delta, dead_cookies);
    3132                 :            :         }
    3133                 :            :     }
    3134                 :      58584 : }
    3135                 :            : 
    3136                 :            : static void
    3137                 :      31430 : learned_cookies_inc(struct ofproto *ofproto,
    3138                 :            :                     const struct rule_actions *actions)
    3139                 :            :     OVS_REQUIRES(ofproto_mutex)
    3140                 :            : {
    3141                 :      31430 :     learned_cookies_update__(ofproto, actions, +1, NULL);
    3142                 :      31430 : }
    3143                 :            : 
    3144                 :            : static void
    3145                 :      27154 : learned_cookies_dec(struct ofproto *ofproto,
    3146                 :            :                     const struct rule_actions *actions,
    3147                 :            :                     struct ovs_list *dead_cookies)
    3148                 :            :     OVS_REQUIRES(ofproto_mutex)
    3149                 :            : {
    3150                 :      27154 :     learned_cookies_update__(ofproto, actions, -1, dead_cookies);
    3151                 :      27154 : }
    3152                 :            : 
    3153                 :            : static void
    3154                 :      39455 : learned_cookies_flush(struct ofproto *ofproto, struct ovs_list *dead_cookies)
    3155                 :            :     OVS_REQUIRES(ofproto_mutex)
    3156                 :            : {
    3157                 :            :     struct learned_cookie *c;
    3158                 :            : 
    3159         [ +  + ]:      39462 :     LIST_FOR_EACH_POP (c, u.list_node, dead_cookies) {
    3160                 :            :         struct rule_criteria criteria;
    3161                 :            :         struct rule_collection rules;
    3162                 :            :         struct match match;
    3163                 :            : 
    3164                 :          7 :         match_init_catchall(&match);
    3165                 :          7 :         rule_criteria_init(&criteria, c->table_id, &match, 0, OVS_VERSION_MAX,
    3166                 :            :                            c->cookie, OVS_BE64_MAX, OFPP_ANY, OFPG_ANY);
    3167                 :          7 :         rule_criteria_require_rw(&criteria, false);
    3168                 :          7 :         collect_rules_loose(ofproto, &criteria, &rules);
    3169                 :          7 :         rule_criteria_destroy(&criteria);
    3170                 :          7 :         delete_flows__(&rules, OFPRR_DELETE, NULL);
    3171                 :            : 
    3172                 :          7 :         free(c);
    3173                 :            :     }
    3174                 :      39455 : }
    3175                 :            : 
    3176                 :            : static enum ofperr
    3177                 :          1 : handle_echo_request(struct ofconn *ofconn, const struct ofp_header *oh)
    3178                 :            : {
    3179                 :          1 :     ofconn_send_reply(ofconn, make_echo_reply(oh));
    3180                 :          1 :     return 0;
    3181                 :            : }
    3182                 :            : 
    3183                 :            : static void
    3184                 :         82 : query_tables(struct ofproto *ofproto,
    3185                 :            :              struct ofputil_table_features **featuresp,
    3186                 :            :              struct ofputil_table_stats **statsp)
    3187                 :            : {
    3188                 :         82 :     struct mf_bitmap rw_fields = oxm_writable_fields();
    3189                 :         82 :     struct mf_bitmap match = oxm_matchable_fields();
    3190                 :         82 :     struct mf_bitmap mask = oxm_maskable_fields();
    3191                 :            : 
    3192                 :            :     struct ofputil_table_features *features;
    3193                 :            :     struct ofputil_table_stats *stats;
    3194                 :            :     int i;
    3195                 :            : 
    3196                 :         82 :     features = *featuresp = xcalloc(ofproto->n_tables, sizeof *features);
    3197         [ +  + ]:      20992 :     for (i = 0; i < ofproto->n_tables; i++) {
    3198                 :      20910 :         struct ofputil_table_features *f = &features[i];
    3199                 :            : 
    3200                 :      20910 :         f->table_id = i;
    3201                 :      20910 :         sprintf(f->name, "table%d", i);
    3202                 :      20910 :         f->metadata_match = OVS_BE64_MAX;
    3203                 :      20910 :         f->metadata_write = OVS_BE64_MAX;
    3204                 :      20910 :         atomic_read_relaxed(&ofproto->tables[i].miss_config, &f->miss_config);
    3205                 :      20910 :         f->max_entries = 1000000;
    3206                 :            : 
    3207                 :      20910 :         bool more_tables = false;
    3208         [ +  + ]:    2676480 :         for (int j = i + 1; j < ofproto->n_tables; j++) {
    3209         [ +  + ]:    2655570 :             if (!(ofproto->tables[j].flags & OFTABLE_HIDDEN)) {
    3210                 :    2634742 :                 bitmap_set1(f->nonmiss.next, j);
    3211                 :    2634742 :                 more_tables = true;
    3212                 :            :             }
    3213                 :            :         }
    3214                 :      20910 :         f->nonmiss.instructions = (1u << N_OVS_INSTRUCTIONS) - 1;
    3215         [ +  + ]:      20910 :         if (!more_tables) {
    3216                 :        164 :             f->nonmiss.instructions &= ~(1u << OVSINST_OFPIT11_GOTO_TABLE);
    3217                 :            :         }
    3218                 :      20910 :         f->nonmiss.write.ofpacts = (UINT64_C(1) << N_OFPACTS) - 1;
    3219                 :      20910 :         f->nonmiss.write.set_fields = rw_fields;
    3220                 :      20910 :         f->nonmiss.apply = f->nonmiss.write;
    3221                 :      20910 :         f->miss = f->nonmiss;
    3222                 :            : 
    3223                 :      20910 :         f->match = match;
    3224                 :      20910 :         f->mask = mask;
    3225                 :      20910 :         f->wildcard = match;
    3226                 :            :     }
    3227                 :            : 
    3228         [ +  + ]:         82 :     if (statsp) {
    3229                 :         10 :         stats = *statsp = xcalloc(ofproto->n_tables, sizeof *stats);
    3230         [ +  + ]:       2560 :         for (i = 0; i < ofproto->n_tables; i++) {
    3231                 :       2550 :             struct ofputil_table_stats *s = &stats[i];
    3232                 :            : 
    3233                 :       2550 :             s->table_id = i;
    3234                 :       2550 :             s->active_count = ofproto->tables[i].n_flows;
    3235         [ +  + ]:       2550 :             if (i == 0) {
    3236                 :         10 :                 s->active_count -= connmgr_count_hidden_rules(
    3237                 :         10 :                     ofproto->connmgr);
    3238                 :            :             }
    3239                 :            :         }
    3240                 :            :     } else {
    3241                 :         72 :         stats = NULL;
    3242                 :            :     }
    3243                 :            : 
    3244                 :         82 :     ofproto->ofproto_class->query_tables(ofproto, features, stats);
    3245                 :            : 
    3246         [ +  + ]:      20992 :     for (i = 0; i < ofproto->n_tables; i++) {
    3247                 :      20910 :         const struct oftable *table = &ofproto->tables[i];
    3248                 :      20910 :         struct ofputil_table_features *f = &features[i];
    3249                 :            : 
    3250         [ +  + ]:      20910 :         if (table->name) {
    3251                 :          3 :             ovs_strzcpy(f->name, table->name, sizeof f->name);
    3252                 :            :         }
    3253                 :            : 
    3254         [ +  + ]:      20910 :         if (table->max_flows < f->max_entries) {
    3255                 :          3 :             f->max_entries = table->max_flows;
    3256                 :            :         }
    3257                 :            :     }
    3258                 :         82 : }
    3259                 :            : 
    3260                 :            : static void
    3261                 :         70 : query_switch_features(struct ofproto *ofproto,
    3262                 :            :                       bool *arp_match_ip, uint64_t *ofpacts)
    3263                 :            : {
    3264                 :            :     struct ofputil_table_features *features, *f;
    3265                 :            : 
    3266                 :         70 :     *arp_match_ip = false;
    3267                 :         70 :     *ofpacts = 0;
    3268                 :            : 
    3269                 :         70 :     query_tables(ofproto, &features, NULL);
    3270         [ +  + ]:      17920 :     for (f = features; f < &features[ofproto->n_tables]; f++) {
    3271                 :      17850 :         *ofpacts |= f->nonmiss.apply.ofpacts | f->miss.apply.ofpacts;
    3272   [ -  +  #  # ]:      17850 :         if (bitmap_is_set(f->match.bm, MFF_ARP_SPA) ||
    3273                 :          0 :             bitmap_is_set(f->match.bm, MFF_ARP_TPA)) {
    3274                 :      17850 :             *arp_match_ip = true;
    3275                 :            :         }
    3276                 :            :     }
    3277                 :         70 :     free(features);
    3278                 :            : 
    3279                 :            :     /* Sanity check. */
    3280         [ -  + ]:         70 :     ovs_assert(*ofpacts & (UINT64_C(1) << OFPACT_OUTPUT));
    3281                 :         70 : }
    3282                 :            : 
    3283                 :            : static enum ofperr
    3284                 :         70 : handle_features_request(struct ofconn *ofconn, const struct ofp_header *oh)
    3285                 :            : {
    3286                 :         70 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
    3287                 :            :     struct ofputil_switch_features features;
    3288                 :            :     struct ofport *port;
    3289                 :            :     bool arp_match_ip;
    3290                 :            :     struct ofpbuf *b;
    3291                 :            : 
    3292                 :         70 :     query_switch_features(ofproto, &arp_match_ip, &features.ofpacts);
    3293                 :            : 
    3294                 :         70 :     features.datapath_id = ofproto->datapath_id;
    3295                 :         70 :     features.n_buffers = 0;
    3296                 :         70 :     features.n_tables = ofproto_get_n_visible_tables(ofproto);
    3297                 :         70 :     features.capabilities = (OFPUTIL_C_FLOW_STATS | OFPUTIL_C_TABLE_STATS |
    3298                 :            :                              OFPUTIL_C_PORT_STATS | OFPUTIL_C_QUEUE_STATS |
    3299                 :            :                              OFPUTIL_C_GROUP_STATS);
    3300         [ +  - ]:         70 :     if (arp_match_ip) {
    3301                 :         70 :         features.capabilities |= OFPUTIL_C_ARP_MATCH_IP;
    3302                 :            :     }
    3303                 :            :     /* FIXME: Fill in proper features.auxiliary_id for auxiliary connections */
    3304                 :         70 :     features.auxiliary_id = 0;
    3305                 :         70 :     b = ofputil_encode_switch_features(&features, ofconn_get_protocol(ofconn),
    3306                 :            :                                        oh->xid);
    3307 [ +  + ][ -  + ]:        262 :     HMAP_FOR_EACH (port, hmap_node, &ofproto->ports) {
    3308                 :        192 :         ofputil_put_switch_features_port(&port->pp, b);
    3309                 :            :     }
    3310                 :            : 
    3311                 :         70 :     ofconn_send_reply(ofconn, b);
    3312                 :         70 :     return 0;
    3313                 :            : }
    3314                 :            : 
    3315                 :            : static enum ofperr
    3316                 :        282 : handle_get_config_request(struct ofconn *ofconn, const struct ofp_header *oh)
    3317                 :            : {
    3318                 :            :     struct ofputil_switch_config config;
    3319                 :        282 :     config.frag = ofconn_get_ofproto(ofconn)->frag_handling;
    3320                 :            :     config.invalid_ttl_to_controller
    3321                 :        282 :         = ofconn_get_invalid_ttl_to_controller(ofconn);
    3322                 :        282 :     config.miss_send_len = ofconn_get_miss_send_len(ofconn);
    3323                 :            : 
    3324                 :        282 :     ofconn_send_reply(ofconn, ofputil_encode_get_config_reply(oh, &config));
    3325                 :            : 
    3326                 :        282 :     return 0;
    3327                 :            : }
    3328                 :            : 
    3329                 :            : static enum ofperr
    3330                 :        215 : handle_set_config(struct ofconn *ofconn, const struct ofp_header *oh)
    3331                 :            : {
    3332                 :        215 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
    3333                 :            :     struct ofputil_switch_config config;
    3334                 :            :     enum ofperr error;
    3335                 :            : 
    3336                 :        215 :     error = ofputil_decode_set_config(oh, &config);
    3337         [ -  + ]:        215 :     if (error) {
    3338                 :          0 :         return error;
    3339                 :            :     }
    3340                 :            : 
    3341         [ -  + ]:        215 :     if (ofconn_get_type(ofconn) != OFCONN_PRIMARY
    3342         [ #  # ]:          0 :         || ofconn_get_role(ofconn) != OFPCR12_ROLE_SLAVE) {
    3343                 :        215 :         enum ofputil_frag_handling cur = ofproto->frag_handling;
    3344                 :        215 :         enum ofputil_frag_handling next = config.frag;
    3345                 :            : 
    3346         [ +  + ]:        215 :         if (cur != next) {
    3347         [ +  - ]:          4 :             if (ofproto->ofproto_class->set_frag_handling(ofproto, next)) {
    3348                 :          4 :                 ofproto->frag_handling = next;
    3349                 :            :             } else {
    3350         [ #  # ]:          0 :                 VLOG_WARN_RL(&rl, "%s: unsupported fragment handling mode %s",
    3351                 :            :                              ofproto->name,
    3352                 :            :                              ofputil_frag_handling_to_string(next));
    3353                 :            :             }
    3354                 :            :         }
    3355                 :            :     }
    3356                 :            : 
    3357         [ +  + ]:        215 :     if (config.invalid_ttl_to_controller >= 0) {
    3358                 :        159 :         ofconn_set_invalid_ttl_to_controller(ofconn,
    3359                 :        159 :                                              config.invalid_ttl_to_controller);
    3360                 :            :     }
    3361                 :            : 
    3362                 :        215 :     ofconn_set_miss_send_len(ofconn, config.miss_send_len);
    3363                 :            : 
    3364                 :        215 :     return 0;
    3365                 :            : }
    3366                 :            : 
    3367                 :            : /* Checks whether 'ofconn' is a slave controller.  If so, returns an OpenFlow
    3368                 :            :  * error message code for the caller to propagate upward.  Otherwise, returns
    3369                 :            :  * 0.
    3370                 :            :  *
    3371                 :            :  * The log message mentions 'msg_type'. */
    3372                 :            : static enum ofperr
    3373                 :      35579 : reject_slave_controller(struct ofconn *ofconn)
    3374                 :            : {
    3375         [ -  + ]:      35579 :     if (ofconn_get_type(ofconn) == OFCONN_PRIMARY
    3376         [ #  # ]:          0 :         && ofconn_get_role(ofconn) == OFPCR12_ROLE_SLAVE) {
    3377                 :          0 :         return OFPERR_OFPBRC_IS_SLAVE;
    3378                 :            :     } else {
    3379                 :      35579 :         return 0;
    3380                 :            :     }
    3381                 :            : }
    3382                 :            : 
    3383                 :            : /* Checks that the 'ofpacts_len' bytes of action in 'ofpacts' are appropriate
    3384                 :            :  * for 'ofproto':
    3385                 :            :  *
    3386                 :            :  *    - If they use a meter, then 'ofproto' has that meter configured.
    3387                 :            :  *
    3388                 :            :  *    - If they use any groups, then 'ofproto' has that group configured.
    3389                 :            :  *
    3390                 :            :  * Returns 0 if successful, otherwise an OpenFlow error. */
    3391                 :            : enum ofperr
    3392                 :      32994 : ofproto_check_ofpacts(struct ofproto *ofproto,
    3393                 :            :                       const struct ofpact ofpacts[], size_t ofpacts_len)
    3394                 :            : {
    3395                 :            :     uint32_t mid;
    3396                 :            : 
    3397                 :      32994 :     mid = ofpacts_get_meter(ofpacts, ofpacts_len);
    3398 [ -  + ][ #  # ]:      32994 :     if (mid && get_provider_meter_id(ofproto, mid) == UINT32_MAX) {
    3399                 :          0 :         return OFPERR_OFPMMFC_INVALID_METER;
    3400                 :            :     }
    3401                 :            : 
    3402                 :            :     const struct ofpact_group *a;
    3403         [ +  + ]:      33033 :     OFPACT_FOR_EACH_TYPE_FLATTENED (a, GROUP, ofpacts, ofpacts_len) {
    3404         [ +  + ]:         42 :         if (!ofproto_group_exists(ofproto, a->group_id)) {
    3405                 :          3 :             return OFPERR_OFPBAC_BAD_OUT_GROUP;
    3406                 :            :         }
    3407                 :            :     }
    3408                 :            : 
    3409                 :      32991 :     return 0;
    3410                 :            : }
    3411                 :            : 
    3412                 :            : static enum ofperr
    3413                 :       1562 : handle_packet_out(struct ofconn *ofconn, const struct ofp_header *oh)
    3414                 :            : {
    3415                 :       1562 :     struct ofproto *p = ofconn_get_ofproto(ofconn);
    3416                 :            :     struct ofputil_packet_out po;
    3417                 :            :     struct dp_packet *payload;
    3418                 :            :     uint64_t ofpacts_stub[1024 / 8];
    3419                 :            :     struct ofpbuf ofpacts;
    3420                 :            :     struct flow flow;
    3421                 :            :     enum ofperr error;
    3422                 :            : 
    3423                 :       1562 :     COVERAGE_INC(ofproto_packet_out);
    3424                 :            : 
    3425                 :       1562 :     error = reject_slave_controller(ofconn);
    3426         [ -  + ]:       1562 :     if (error) {
    3427                 :          0 :         goto exit;
    3428                 :            :     }
    3429                 :            : 
    3430                 :            :     /* Decode message. */
    3431                 :       1562 :     ofpbuf_use_stub(&ofpacts, ofpacts_stub, sizeof ofpacts_stub);
    3432                 :       1562 :     error = ofputil_decode_packet_out(&po, oh, &ofpacts);
    3433         [ -  + ]:       1562 :     if (error) {
    3434                 :          0 :         goto exit_free_ofpacts;
    3435                 :            :     }
    3436         [ +  + ]:       1562 :     if (ofp_to_u16(po.in_port) >= p->max_ports
    3437         [ -  + ]:        316 :         && ofp_to_u16(po.in_port) < ofp_to_u16(OFPP_MAX)) {
    3438                 :          0 :         error = OFPERR_OFPBRC_BAD_PORT;
    3439                 :          0 :         goto exit_free_ofpacts;
    3440                 :            :     }
    3441                 :            : 
    3442                 :            :     /* Get payload. */
    3443         [ -  + ]:       1562 :     if (po.buffer_id != UINT32_MAX) {
    3444                 :          0 :         error = OFPERR_OFPBRC_BUFFER_UNKNOWN;
    3445                 :          0 :         goto exit_free_ofpacts;
    3446                 :            :     }
    3447                 :            :     /* Ensure that the L3 header is 32-bit aligned. */
    3448                 :       1562 :     payload = dp_packet_clone_data_with_headroom(po.packet, po.packet_len, 2);
    3449                 :            : 
    3450                 :            :     /* Verify actions against packet, then send packet if successful. */
    3451                 :       1562 :     flow_extract(payload, &flow);
    3452                 :       1562 :     flow.in_port.ofp_port = po.in_port;
    3453                 :            : 
    3454                 :            :     /* Check actions like for flow mods.  We pass a 'table_id' of 0 to
    3455                 :            :      * ofproto_check_consistency(), which isn't strictly correct because these
    3456                 :            :      * actions aren't in any table.  This is OK as 'table_id' is only used to
    3457                 :            :      * check instructions (e.g., goto-table), which can't appear on the action
    3458                 :            :      * list of a packet-out. */
    3459                 :       1562 :     error = ofpacts_check_consistency(po.ofpacts, po.ofpacts_len,
    3460                 :       1562 :                                       &flow, u16_to_ofp(p->max_ports),
    3461                 :       1562 :                                       0, p->n_tables,
    3462                 :            :                                       ofconn_get_protocol(ofconn));
    3463         [ +  - ]:       1562 :     if (!error) {
    3464                 :            :         /* Should hold ofproto_mutex to guarantee state don't
    3465                 :            :          * change between the check and the execution. */
    3466                 :       1562 :         error = ofproto_check_ofpacts(p, po.ofpacts, po.ofpacts_len);
    3467         [ +  - ]:       1562 :         if (!error) {
    3468                 :       1562 :             error = p->ofproto_class->packet_out(p, payload, &flow,
    3469                 :       1562 :                                                  po.ofpacts, po.ofpacts_len);
    3470                 :            :         }
    3471                 :            :     }
    3472                 :       1562 :     dp_packet_delete(payload);
    3473                 :            : 
    3474                 :            : exit_free_ofpacts:
    3475                 :       1562 :     ofpbuf_uninit(&ofpacts);
    3476                 :            : exit:
    3477                 :       1562 :     return error;
    3478                 :            : }
    3479                 :            : 
    3480                 :            : static enum ofperr
    3481                 :        199 : handle_nxt_resume(struct ofconn *ofconn, const struct ofp_header *oh)
    3482                 :            : {
    3483                 :        199 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
    3484                 :            :     struct ofputil_packet_in_private pin;
    3485                 :            :     enum ofperr error;
    3486                 :            : 
    3487                 :        199 :     error = ofputil_decode_packet_in_private(oh, false, &pin, NULL, NULL);
    3488         [ -  + ]:        199 :     if (error) {
    3489                 :          0 :         return error;
    3490                 :            :     }
    3491                 :            : 
    3492         [ +  - ]:        199 :     error = (ofproto->ofproto_class->nxt_resume
    3493                 :        199 :              ? ofproto->ofproto_class->nxt_resume(ofproto, &pin)
    3494                 :            :              : OFPERR_NXR_NOT_SUPPORTED);
    3495                 :            : 
    3496                 :        199 :     ofputil_packet_in_private_destroy(&pin);
    3497                 :            : 
    3498                 :        199 :     return error;
    3499                 :            : }
    3500                 :            : 
    3501                 :            : static void
    3502                 :         39 : update_port_config(struct ofconn *ofconn, struct ofport *port,
    3503                 :            :                    enum ofputil_port_config config,
    3504                 :            :                    enum ofputil_port_config mask)
    3505                 :            : {
    3506                 :         39 :     enum ofputil_port_config toggle = (config ^ port->pp.config) & mask;
    3507                 :            : 
    3508         [ +  + ]:         39 :     if (toggle & OFPUTIL_PC_PORT_DOWN
    3509 [ +  + ][ -  + ]:         34 :         && (config & OFPUTIL_PC_PORT_DOWN
    3510                 :          3 :             ? netdev_turn_flags_off(port->netdev, NETDEV_UP, NULL)
    3511                 :         14 :             : netdev_turn_flags_on(port->netdev, NETDEV_UP, NULL))) {
    3512                 :            :         /* We tried to bring the port up or down, but it failed, so don't
    3513                 :            :          * update the "down" bit. */
    3514                 :          0 :         toggle &= ~OFPUTIL_PC_PORT_DOWN;
    3515                 :            :     }
    3516                 :            : 
    3517         [ +  - ]:         39 :     if (toggle) {
    3518                 :         39 :         enum ofputil_port_config old_config = port->pp.config;
    3519                 :         39 :         port->pp.config ^= toggle;
    3520                 :         39 :         port->ofproto->ofproto_class->port_reconfigured(port, old_config);
    3521                 :         39 :         connmgr_send_port_status(port->ofproto->connmgr, ofconn, &port->pp,
    3522                 :            :                                  OFPPR_MODIFY);
    3523                 :            :     }
    3524                 :         39 : }
    3525                 :            : 
    3526                 :            : static enum ofperr
    3527                 :         39 : port_mod_start(struct ofconn *ofconn, struct ofputil_port_mod *pm,
    3528                 :            :                struct ofport **port)
    3529                 :            : {
    3530                 :         39 :     struct ofproto *p = ofconn_get_ofproto(ofconn);
    3531                 :            : 
    3532                 :         39 :     *port = ofproto_get_port(p, pm->port_no);
    3533         [ -  + ]:         39 :     if (!*port) {
    3534                 :          0 :         return OFPERR_OFPPMFC_BAD_PORT;
    3535                 :            :     }
    3536         [ -  + ]:         39 :     if (!eth_addr_equals((*port)->pp.hw_addr, pm->hw_addr)) {
    3537                 :          0 :         return OFPERR_OFPPMFC_BAD_HW_ADDR;
    3538                 :            :     }
    3539                 :         39 :     return 0;
    3540                 :            : }
    3541                 :            : 
    3542                 :            : static void
    3543                 :         39 : port_mod_finish(struct ofconn *ofconn, struct ofputil_port_mod *pm,
    3544                 :            :                 struct ofport *port)
    3545                 :            : {
    3546                 :         39 :     update_port_config(ofconn, port, pm->config, pm->mask);
    3547         [ -  + ]:         39 :     if (pm->advertise) {
    3548                 :          0 :         netdev_set_advertisements(port->netdev, pm->advertise);
    3549                 :            :     }
    3550                 :         39 : }
    3551                 :            : 
    3552                 :            : static enum ofperr
    3553                 :         39 : handle_port_mod(struct ofconn *ofconn, const struct ofp_header *oh)
    3554                 :            : {
    3555                 :            :     struct ofputil_port_mod pm;
    3556                 :            :     struct ofport *port;
    3557                 :            :     enum ofperr error;
    3558                 :            : 
    3559                 :         39 :     error = reject_slave_controller(ofconn);
    3560         [ -  + ]:         39 :     if (error) {
    3561                 :          0 :         return error;
    3562                 :            :     }
    3563                 :            : 
    3564                 :         39 :     error = ofputil_decode_port_mod(oh, &pm, false);
    3565         [ -  + ]:         39 :     if (error) {
    3566                 :          0 :         return error;
    3567                 :            :     }
    3568                 :            : 
    3569                 :         39 :     error = port_mod_start(ofconn, &pm, &port);
    3570         [ +  - ]:         39 :     if (!error) {
    3571                 :         39 :         port_mod_finish(ofconn, &pm, port);
    3572                 :            :     }
    3573                 :         39 :     return error;
    3574                 :            : }
    3575                 :            : 
    3576                 :            : static enum ofperr
    3577                 :          0 : handle_desc_stats_request(struct ofconn *ofconn,
    3578                 :            :                           const struct ofp_header *request)
    3579                 :            : {
    3580                 :            :     static const char *default_mfr_desc = "Nicira, Inc.";
    3581                 :            :     static const char *default_hw_desc = "Open vSwitch";
    3582                 :            :     static const char *default_sw_desc = VERSION;
    3583                 :            :     static const char *default_serial_desc = "None";
    3584                 :            :     static const char *default_dp_desc = "None";
    3585                 :            : 
    3586                 :          0 :     struct ofproto *p = ofconn_get_ofproto(ofconn);
    3587                 :            :     struct ofp_desc_stats *ods;
    3588                 :            :     struct ofpbuf *msg;
    3589                 :            : 
    3590                 :          0 :     msg = ofpraw_alloc_stats_reply(request, 0);
    3591                 :          0 :     ods = ofpbuf_put_zeros(msg, sizeof *ods);
    3592         [ #  # ]:          0 :     ovs_strlcpy(ods->mfr_desc, p->mfr_desc ? p->mfr_desc : default_mfr_desc,
    3593                 :            :                 sizeof ods->mfr_desc);
    3594         [ #  # ]:          0 :     ovs_strlcpy(ods->hw_desc, p->hw_desc ? p->hw_desc : default_hw_desc,
    3595                 :            :                 sizeof ods->hw_desc);
    3596         [ #  # ]:          0 :     ovs_strlcpy(ods->sw_desc, p->sw_desc ? p->sw_desc : default_sw_desc,
    3597                 :            :                 sizeof ods->sw_desc);
    3598         [ #  # ]:          0 :     ovs_strlcpy(ods->serial_num,
    3599                 :          0 :                 p->serial_desc ? p->serial_desc : default_serial_desc,
    3600                 :            :                 sizeof ods->serial_num);
    3601         [ #  # ]:          0 :     ovs_strlcpy(ods->dp_desc, p->dp_desc ? p->dp_desc : default_dp_desc,
    3602                 :            :                 sizeof ods->dp_desc);
    3603                 :          0 :     ofconn_send_reply(ofconn, msg);
    3604                 :            : 
    3605                 :          0 :     return 0;
    3606                 :            : }
    3607                 :            : 
    3608                 :            : static enum ofperr
    3609                 :         10 : handle_table_stats_request(struct ofconn *ofconn,
    3610                 :            :                            const struct ofp_header *request)
    3611                 :            : {
    3612                 :         10 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
    3613                 :            :     struct ofputil_table_features *features;
    3614                 :            :     struct ofputil_table_stats *stats;
    3615                 :            :     struct ofpbuf *reply;
    3616                 :            :     size_t i;
    3617                 :            : 
    3618                 :         10 :     query_tables(ofproto, &features, &stats);
    3619                 :            : 
    3620                 :         10 :     reply = ofputil_encode_table_stats_reply(request);
    3621         [ +  + ]:       2560 :     for (i = 0; i < ofproto->n_tables; i++) {
    3622         [ +  + ]:       2550 :         if (!(ofproto->tables[i].flags & OFTABLE_HIDDEN)) {
    3623                 :       2540 :             ofputil_append_table_stats_reply(reply, &stats[i], &features[i]);
    3624                 :            :         }
    3625                 :            :     }
    3626                 :         10 :     ofconn_send_reply(ofconn, reply);
    3627                 :            : 
    3628                 :         10 :     free(features);
    3629                 :         10 :     free(stats);
    3630                 :            : 
    3631                 :         10 :     return 0;
    3632                 :            : }
    3633                 :            : 
    3634                 :            : static enum ofperr
    3635                 :          2 : handle_table_features_request(struct ofconn *ofconn,
    3636                 :            :                               const struct ofp_header *request)
    3637                 :            : {
    3638                 :          2 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
    3639                 :          2 :     struct ofpbuf msg = ofpbuf_const_initializer(request,
    3640                 :          2 :                                                  ntohs(request->length));
    3641                 :          2 :     ofpraw_pull_assert(&msg);
    3642 [ +  - ][ -  + ]:          2 :     if (msg.size || ofpmp_more(request)) {
    3643                 :          0 :         return OFPERR_OFPTFFC_EPERM;
    3644                 :            :     }
    3645                 :            : 
    3646                 :            :     struct ofputil_table_features *features;
    3647                 :          2 :     query_tables(ofproto, &features, NULL);
    3648                 :            : 
    3649                 :            :     struct ovs_list replies;
    3650                 :          2 :     ofpmp_init(&replies, request);
    3651         [ +  + ]:        512 :     for (size_t i = 0; i < ofproto->n_tables; i++) {
    3652         [ +  + ]:        510 :         if (!(ofproto->tables[i].flags & OFTABLE_HIDDEN)) {
    3653                 :        508 :             ofputil_append_table_features_reply(&features[i], &replies);
    3654                 :            :         }
    3655                 :            :     }
    3656                 :          2 :     ofconn_send_replies(ofconn, &replies);
    3657                 :            : 
    3658                 :          2 :     free(features);
    3659                 :            : 
    3660                 :          2 :     return 0;
    3661                 :            : }
    3662                 :            : 
    3663                 :            : /* Returns the vacancy of 'oftable', a number that ranges from 0 (if the table
    3664                 :            :  * is full) to 100 (if the table is empty).
    3665                 :            :  *
    3666                 :            :  * A table without a limit on flows is considered to be empty. */
    3667                 :            : static uint8_t
    3668                 :       2593 : oftable_vacancy(const struct oftable *t)
    3669                 :            : {
    3670 [ +  - ][ +  + ]:       2593 :     return (!t->max_flows ? 100
    3671                 :       2593 :             : t->n_flows >= t->max_flows ? 0
    3672                 :       2590 :             : (t->max_flows - t->n_flows) * 100.0 / t->max_flows);
    3673                 :            : }
    3674                 :            : 
    3675                 :            : static void
    3676                 :       2553 : query_table_desc__(struct ofputil_table_desc *td,
    3677                 :            :                    struct ofproto *ofproto, uint8_t table_id)
    3678                 :            : {
    3679                 :       2553 :     const struct oftable *t = &ofproto->tables[table_id];
    3680                 :            : 
    3681                 :       2553 :     td->table_id = table_id;
    3682         [ +  + ]:       2553 :     td->eviction = (t->eviction & EVICTION_OPENFLOW
    3683                 :            :                     ? OFPUTIL_TABLE_EVICTION_ON
    3684                 :            :                     : OFPUTIL_TABLE_EVICTION_OFF);
    3685                 :       2553 :     td->eviction_flags = OFPROTO_EVICTION_FLAGS;
    3686         [ +  + ]:       2553 :     td->vacancy = (t->vacancy_event
    3687                 :            :                    ? OFPUTIL_TABLE_VACANCY_ON
    3688                 :            :                    : OFPUTIL_TABLE_VACANCY_OFF);
    3689                 :       2553 :     td->table_vacancy.vacancy_down = t->vacancy_down;
    3690                 :       2553 :     td->table_vacancy.vacancy_up = t->vacancy_up;
    3691                 :       2553 :     td->table_vacancy.vacancy = oftable_vacancy(t);
    3692                 :       2553 : }
    3693                 :            : 
    3694                 :            : /* This function queries the database for dumping table-desc. */
    3695                 :            : static void
    3696                 :         10 : query_tables_desc(struct ofproto *ofproto, struct ofputil_table_desc **descp)
    3697                 :            : {
    3698                 :            :     struct ofputil_table_desc *table_desc;
    3699                 :            :     size_t i;
    3700                 :            : 
    3701                 :         10 :     table_desc = *descp = xcalloc(ofproto->n_tables, sizeof *table_desc);
    3702         [ +  + ]:       2560 :     for (i = 0; i < ofproto->n_tables; i++) {
    3703                 :       2550 :         struct ofputil_table_desc *td = &table_desc[i];
    3704                 :       2550 :         query_table_desc__(td, ofproto, i);
    3705                 :            :     }
    3706                 :         10 : }
    3707                 :            : 
    3708                 :            : /* Function to handle dump-table-desc request. */
    3709                 :            : static enum ofperr
    3710                 :         10 : handle_table_desc_request(struct ofconn *ofconn,
    3711                 :            :                           const struct ofp_header *request)
    3712                 :            : {
    3713                 :         10 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
    3714                 :            :     struct ofputil_table_desc *table_desc;
    3715                 :            :     struct ovs_list replies;
    3716                 :            :     size_t i;
    3717                 :            : 
    3718                 :         10 :     query_tables_desc(ofproto, &table_desc);
    3719                 :         10 :     ofpmp_init(&replies, request);
    3720         [ +  + ]:       2560 :     for (i = 0; i < ofproto->n_tables; i++) {
    3721         [ +  + ]:       2550 :         if (!(ofproto->tables[i].flags & OFTABLE_HIDDEN)) {
    3722                 :       2540 :             ofputil_append_table_desc_reply(&table_desc[i], &replies,
    3723                 :       2540 :                                             request->version);
    3724                 :            :         }
    3725                 :            :     }
    3726                 :         10 :     ofconn_send_replies(ofconn, &replies);
    3727                 :         10 :     free(table_desc);
    3728                 :         10 :     return 0;
    3729                 :            : }
    3730                 :            : 
    3731                 :            : /* This function determines and sends the vacancy event, based on the value
    3732                 :            :  * of current vacancy and threshold vacancy. If the current vacancy is less
    3733                 :            :  * than or equal to vacancy_down, vacancy up events must be enabled, and when
    3734                 :            :  * the current vacancy is greater or equal to vacancy_up, vacancy down events
    3735                 :            :  * must be enabled. */
    3736                 :            : static void
    3737                 :      56568 : send_table_status(struct ofproto *ofproto, uint8_t table_id)
    3738                 :            : {
    3739                 :      56568 :     struct oftable *t = &ofproto->tables[table_id];
    3740         [ +  + ]:      56568 :     if (!t->vacancy_event) {
    3741                 :      56531 :         return;
    3742                 :            :     }
    3743                 :            : 
    3744                 :         37 :     uint8_t vacancy = oftable_vacancy(t);
    3745                 :            :     enum ofp14_table_reason event;
    3746         [ +  + ]:         37 :     if (vacancy < t->vacancy_down) {
    3747                 :          6 :         event = OFPTR_VACANCY_DOWN;
    3748         [ +  + ]:         31 :     } else if (vacancy > t->vacancy_up) {
    3749                 :          5 :         event = OFPTR_VACANCY_UP;
    3750                 :            :     } else {
    3751                 :         26 :         return;
    3752                 :            :     }
    3753                 :            : 
    3754         [ +  + ]:         11 :     if (event == t->vacancy_event) {
    3755                 :            :         struct ofputil_table_desc td;
    3756                 :          3 :         query_table_desc__(&td, ofproto, table_id);
    3757                 :          3 :         connmgr_send_table_status(ofproto->connmgr, &td, event);
    3758                 :            : 
    3759         [ +  + ]:          3 :         t->vacancy_event = (event == OFPTR_VACANCY_DOWN
    3760                 :            :                             ? OFPTR_VACANCY_UP
    3761                 :            :                             : OFPTR_VACANCY_DOWN);
    3762                 :            :     }
    3763                 :            : }
    3764                 :            : 
    3765                 :            : static void
    3766                 :         46 : append_port_stat(struct ofport *port, struct ovs_list *replies)
    3767                 :            : {
    3768                 :         46 :     struct ofputil_port_stats ops = { .port_no = port->pp.port_no };
    3769                 :            : 
    3770                 :         46 :     calc_duration(port->created, time_msec(),
    3771                 :            :                   &ops.duration_sec, &ops.duration_nsec);
    3772                 :            : 
    3773                 :            :     /* Intentionally ignore return value, since errors will set
    3774                 :            :      * 'stats' to all-1s, which is correct for OpenFlow, and
    3775                 :            :      * netdev_get_stats() will log errors. */
    3776                 :         46 :     ofproto_port_get_stats(port, &ops.stats);
    3777                 :            : 
    3778                 :         46 :     ofputil_append_port_stat(replies, &ops);
    3779                 :         46 : }
    3780                 :            : 
    3781                 :            : static void
    3782                 :         55 : handle_port_request(struct ofconn *ofconn,
    3783                 :            :                     const struct ofp_header *request, ofp_port_t port_no,
    3784                 :            :                     void (*cb)(struct ofport *, struct ovs_list *replies))
    3785                 :            : {
    3786                 :         55 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
    3787                 :            :     struct ofport *port;
    3788                 :            :     struct ovs_list replies;
    3789                 :            : 
    3790                 :         55 :     ofpmp_init(&replies, request);
    3791         [ +  + ]:         55 :     if (port_no != OFPP_ANY) {
    3792                 :          9 :         port = ofproto_get_port(ofproto, port_no);
    3793         [ +  - ]:          9 :         if (port) {
    3794                 :          9 :             cb(port, &replies);
    3795                 :            :         }
    3796                 :            :     } else {
    3797 [ +  + ][ -  + ]:        153 :         HMAP_FOR_EACH (port, hmap_node, &ofproto->ports) {
    3798                 :        107 :             cb(port, &replies);
    3799                 :            :         }
    3800                 :            :     }
    3801                 :            : 
    3802                 :         55 :     ofconn_send_replies(ofconn, &replies);
    3803                 :         55 : }
    3804                 :            : 
    3805                 :            : static enum ofperr
    3806                 :         19 : handle_port_stats_request(struct ofconn *ofconn,
    3807                 :            :                           const struct ofp_header *request)
    3808                 :            : {
    3809                 :            :     ofp_port_t port_no;
    3810                 :            :     enum ofperr error;
    3811                 :            : 
    3812                 :         19 :     error = ofputil_decode_port_stats_request(request, &port_no);
    3813         [ +  - ]:         19 :     if (!error) {
    3814                 :         19 :         handle_port_request(ofconn, request, port_no, append_port_stat);
    3815                 :            :     }
    3816                 :         19 :     return error;
    3817                 :            : }
    3818                 :            : 
    3819                 :            : static void
    3820                 :         70 : append_port_desc(struct ofport *port, struct ovs_list *replies)
    3821                 :            : {
    3822                 :         70 :     ofputil_append_port_desc_stats_reply(&port->pp, replies);
    3823                 :         70 : }
    3824                 :            : 
    3825                 :            : static enum ofperr
    3826                 :         36 : handle_port_desc_stats_request(struct ofconn *ofconn,
    3827                 :            :                                const struct ofp_header *request)
    3828                 :            : {
    3829                 :            :     ofp_port_t port_no;
    3830                 :            :     enum ofperr error;
    3831                 :            : 
    3832                 :         36 :     error = ofputil_decode_port_desc_stats_request(request, &port_no);
    3833         [ +  - ]:         36 :     if (!error) {
    3834                 :         36 :         handle_port_request(ofconn, request, port_no, append_port_desc);
    3835                 :            :     }
    3836                 :         36 :     return error;
    3837                 :            : }
    3838                 :            : 
    3839                 :            : static uint32_t
    3840                 :      31454 : hash_cookie(ovs_be64 cookie)
    3841                 :            : {
    3842                 :      31454 :     return hash_uint64((OVS_FORCE uint64_t)cookie);
    3843                 :            : }
    3844                 :            : 
    3845                 :            : static void
    3846                 :      31431 : cookies_insert(struct ofproto *ofproto, struct rule *rule)
    3847                 :            :     OVS_REQUIRES(ofproto_mutex)
    3848                 :            : {
    3849                 :      31431 :     hindex_insert(&ofproto->cookies, &rule->cookie_node,
    3850                 :      31431 :                   hash_cookie(rule->flow_cookie));
    3851                 :      31431 : }
    3852                 :            : 
    3853                 :            : static void
    3854                 :      31431 : cookies_remove(struct ofproto *ofproto, struct rule *rule)
    3855                 :            :     OVS_REQUIRES(ofproto_mutex)
    3856                 :            : {
    3857                 :      31431 :     hindex_remove(&ofproto->cookies, &rule->cookie_node);
    3858                 :      31431 : }
    3859                 :            : 
    3860                 :            : static void
    3861                 :      18734 : calc_duration(long long int start, long long int now,
    3862                 :            :               uint32_t *sec, uint32_t *nsec)
    3863                 :            : {
    3864                 :      18734 :     long long int msecs = now - start;
    3865                 :      18734 :     *sec = msecs / 1000;
    3866                 :      18734 :     *nsec = (msecs % 1000) * (1000 * 1000);
    3867                 :      18734 : }
    3868                 :            : 
    3869                 :            : /* Checks whether 'table_id' is 0xff or a valid table ID in 'ofproto'.  Returns
    3870                 :            :  * true if 'table_id' is OK, false otherwise.  */
    3871                 :            : static bool
    3872                 :      39881 : check_table_id(const struct ofproto *ofproto, uint8_t table_id)
    3873                 :            : {
    3874 [ +  + ][ +  - ]:      39881 :     return table_id == OFPTT_ALL || table_id < ofproto->n_tables;
    3875                 :            : }
    3876                 :            : 
    3877                 :            : static struct oftable *
    3878                 :     272595 : next_visible_table(const struct ofproto *ofproto, uint8_t table_id)
    3879                 :            : {
    3880                 :            :     struct oftable *table;
    3881                 :            : 
    3882         [ +  + ]:     273664 :     for (table = &ofproto->tables[table_id];
    3883                 :     273664 :          table < &ofproto->tables[ofproto->n_tables];
    3884                 :       1069 :          table++) {
    3885         [ +  + ]:     272595 :         if (!(table->flags & OFTABLE_HIDDEN)) {
    3886                 :     271526 :             return table;
    3887                 :            :         }
    3888                 :            :     }
    3889                 :            : 
    3890                 :       1069 :     return NULL;
    3891                 :            : }
    3892                 :            : 
    3893                 :            : static struct oftable *
    3894                 :       7837 : first_matching_table(const struct ofproto *ofproto, uint8_t table_id)
    3895                 :            : {
    3896         [ +  + ]:       7837 :     if (table_id == 0xff) {
    3897                 :       1069 :         return next_visible_table(ofproto, 0);
    3898         [ +  - ]:       6768 :     } else if (table_id < ofproto->n_tables) {
    3899                 :       6768 :         return &ofproto->tables[table_id];
    3900                 :            :     } else {
    3901                 :          0 :         return NULL;
    3902                 :            :     }
    3903                 :            : }
    3904                 :            : 
    3905                 :            : static struct oftable *
    3906                 :     278294 : next_matching_table(const struct ofproto *ofproto,
    3907                 :            :                     const struct oftable *table, uint8_t table_id)
    3908                 :            : {
    3909                 :     278294 :     return (table_id == 0xff
    3910                 :     271526 :             ? next_visible_table(ofproto, (table - ofproto->tables) + 1)
    3911         [ +  + ]:     278294 :             : NULL);
    3912                 :            : }
    3913                 :            : 
    3914                 :            : /* Assigns TABLE to each oftable, in turn, that matches TABLE_ID in OFPROTO:
    3915                 :            :  *
    3916                 :            :  *   - If TABLE_ID is 0xff, this iterates over every classifier table in
    3917                 :            :  *     OFPROTO, skipping tables marked OFTABLE_HIDDEN.
    3918                 :            :  *
    3919                 :            :  *   - If TABLE_ID is the number of a table in OFPROTO, then the loop iterates
    3920                 :            :  *     only once, for that table.  (This can be used to access tables marked
    3921                 :            :  *     OFTABLE_HIDDEN.)
    3922                 :            :  *
    3923                 :            :  *   - Otherwise, TABLE_ID isn't valid for OFPROTO, so the loop won't be
    3924                 :            :  *     entered at all.  (Perhaps you should have validated TABLE_ID with
    3925                 :            :  *     check_table_id().)
    3926                 :            :  *
    3927                 :            :  * All parameters are evaluated multiple times.
    3928                 :            :  */
    3929                 :            : #define FOR_EACH_MATCHING_TABLE(TABLE, TABLE_ID, OFPROTO)         \
    3930                 :            :     for ((TABLE) = first_matching_table(OFPROTO, TABLE_ID);       \
    3931                 :            :          (TABLE) != NULL;                                         \
    3932                 :            :          (TABLE) = next_matching_table(OFPROTO, TABLE, TABLE_ID))
    3933                 :            : 
    3934                 :            : /* Initializes 'criteria' in a straightforward way based on the other
    3935                 :            :  * parameters.
    3936                 :            :  *
    3937                 :            :  * By default, the criteria include flows that are read-only, on the assumption
    3938                 :            :  * that the collected flows won't be modified.  Call rule_criteria_require_rw()
    3939                 :            :  * if flows will be modified.
    3940                 :            :  *
    3941                 :            :  * For "loose" matching, the 'priority' parameter is unimportant and may be
    3942                 :            :  * supplied as 0. */
    3943                 :            : static void
    3944                 :       7861 : rule_criteria_init(struct rule_criteria *criteria, uint8_t table_id,
    3945                 :            :                    const struct match *match, int priority,
    3946                 :            :                    ovs_version_t version, ovs_be64 cookie,
    3947                 :            :                    ovs_be64 cookie_mask, ofp_port_t out_port,
    3948                 :            :                    uint32_t out_group)
    3949                 :            : {
    3950                 :       7861 :     criteria->table_id = table_id;
    3951                 :       7861 :     cls_rule_init(&criteria->cr, match, priority);
    3952                 :       7861 :     criteria->version = version;
    3953                 :       7861 :     criteria->cookie = cookie;
    3954                 :       7861 :     criteria->cookie_mask = cookie_mask;
    3955                 :       7861 :     criteria->out_port = out_port;
    3956                 :       7861 :     criteria->out_group = out_group;
    3957                 :            : 
    3958                 :            :     /* We ordinarily want to skip hidden rules, but there has to be a way for
    3959                 :            :      * code internal to OVS to modify and delete them, so if the criteria
    3960                 :            :      * specify a priority that can only be for a hidden flow, then allow hidden
    3961                 :            :      * rules to be selected.  (This doesn't allow OpenFlow clients to meddle
    3962                 :            :      * with hidden flows because OpenFlow uses only a 16-bit field to specify
    3963                 :            :      * priority.) */
    3964                 :       7861 :     criteria->include_hidden = priority > UINT16_MAX;
    3965                 :            : 
    3966                 :            :     /* We assume that the criteria are being used to collect flows for reading
    3967                 :            :      * but not modification.  Thus, we should collect read-only flows. */
    3968                 :       7861 :     criteria->include_readonly = true;
    3969                 :       7861 : }
    3970                 :            : 
    3971                 :            : /* By default, criteria initialized by rule_criteria_init() will match flows
    3972                 :            :  * that are read-only, on the assumption that the collected flows won't be
    3973                 :            :  * modified.  Call this function to match only flows that are be modifiable.
    3974                 :            :  *
    3975                 :            :  * Specify 'can_write_readonly' as false in ordinary circumstances, true if the
    3976                 :            :  * caller has special privileges that allow it to modify even "read-only"
    3977                 :            :  * flows. */
    3978                 :            : static void
    3979                 :       7472 : rule_criteria_require_rw(struct rule_criteria *criteria,
    3980                 :            :                          bool can_write_readonly)
    3981                 :            : {
    3982                 :       7472 :     criteria->include_readonly = can_write_readonly;
    3983                 :       7472 : }
    3984                 :            : 
    3985                 :            : static void
    3986                 :       7861 : rule_criteria_destroy(struct rule_criteria *criteria)
    3987                 :            : {
    3988                 :       7861 :     cls_rule_destroy(&criteria->cr);
    3989                 :       7861 :     criteria->version = OVS_VERSION_NOT_REMOVED; /* Mark as destroyed. */
    3990                 :       7861 : }
    3991                 :            : 
    3992                 :            : /* Schedules postponed removal of rules, destroys 'rules'. */
    3993                 :            : static void
    3994                 :       8404 : remove_rules_postponed(struct rule_collection *rules)
    3995                 :            :     OVS_REQUIRES(ofproto_mutex)
    3996                 :            : {
    3997         [ +  - ]:       8404 :     if (rule_collection_n(rules) > 0) {
    3998         [ +  + ]:       8404 :         if (rule_collection_n(rules) == 1) {
    3999                 :       7163 :             ovsrcu_postpone(remove_rule_rcu, rule_collection_rules(rules)[0]);
    4000                 :       7163 :             rule_collection_init(rules);
    4001                 :            :         } else {
    4002                 :       1241 :             ovsrcu_postpone(remove_rules_rcu, rule_collection_detach(rules));
    4003                 :            :         }
    4004                 :            :     }
    4005                 :       8404 : }
    4006                 :            : 
    4007                 :            : /* Schedules postponed removal of groups, destroys 'groups'. */
    4008                 :            : static void
    4009                 :        925 : remove_groups_postponed(struct group_collection *groups)
    4010                 :            :     OVS_REQUIRES(ofproto_mutex)
    4011                 :            : {
    4012         [ +  + ]:        925 :     if (group_collection_n(groups) > 0) {
    4013         [ +  + ]:         85 :         if (group_collection_n(groups) == 1) {
    4014                 :         74 :             ovsrcu_postpone(remove_group_rcu,
    4015                 :            :                             group_collection_groups(groups)[0]);
    4016                 :         74 :             group_collection_init(groups);
    4017                 :            :         } else {
    4018                 :         11 :             ovsrcu_postpone(remove_groups_rcu,
    4019                 :            :                             group_collection_detach(groups));
    4020                 :            :         }
    4021                 :            :     }
    4022                 :        925 : }
    4023                 :            : 
    4024                 :            : /* Checks whether 'rule' matches 'c' and, if so, adds it to 'rules'.  This
    4025                 :            :  * function verifies most of the criteria in 'c' itself, but the caller must
    4026                 :            :  * check 'c->cr' itself.
    4027                 :            :  *
    4028                 :            :  * Rules that have already been marked for removal are not collected.
    4029                 :            :  *
    4030                 :            :  * Increments '*n_readonly' if 'rule' wasn't added because it's read-only (and
    4031                 :            :  * 'c' only includes modifiable rules). */
    4032                 :            : static void
    4033                 :      32931 : collect_rule(struct rule *rule, const struct rule_criteria *c,
    4034                 :            :              struct rule_collection *rules, size_t *n_readonly)
    4035                 :            :     OVS_REQUIRES(ofproto_mutex)
    4036                 :            : {
    4037 [ +  + ][ +  + ]:      32931 :     if ((c->table_id == rule->table_id || c->table_id == 0xff)
    4038         [ +  + ]:      32930 :         && ofproto_rule_has_out_port(rule, c->out_port)
    4039         [ +  - ]:      32400 :         && ofproto_rule_has_out_group(rule, c->out_group)
    4040         [ +  + ]:      32400 :         && !((rule->flow_cookie ^ c->cookie) & c->cookie_mask)
    4041 [ +  + ][ -  + ]:      32396 :         && (!rule_is_hidden(rule) || c->include_hidden)
    4042         [ +  - ]:      32389 :         && cls_rule_visible_in_version(&rule->cr, c->version)) {
    4043                 :            :         /* Rule matches all the criteria... */
    4044 [ -  + ][ #  # ]:      32389 :         if (!rule_is_readonly(rule) || c->include_readonly) {
    4045                 :            :             /* ...add it. */
    4046                 :      32389 :             rule_collection_add(rules, rule);
    4047                 :            :         } else {
    4048                 :            :             /* ...except it's read-only. */
    4049                 :          0 :             ++*n_readonly;
    4050                 :            :         }
    4051                 :            :     }
    4052                 :      32931 : }
    4053                 :            : 
    4054                 :            : /* Searches 'ofproto' for rules that match the criteria in 'criteria'.  Matches
    4055                 :            :  * on classifiers rules are done in the "loose" way required for OpenFlow
    4056                 :            :  * OFPFC_MODIFY and OFPFC_DELETE requests.  Puts the selected rules on list
    4057                 :            :  * 'rules'.
    4058                 :            :  *
    4059                 :            :  * Returns 0 on success, otherwise an OpenFlow error code. */
    4060                 :            : static enum ofperr
    4061                 :       1159 : collect_rules_loose(struct ofproto *ofproto,
    4062                 :            :                     const struct rule_criteria *criteria,
    4063                 :            :                     struct rule_collection *rules)
    4064                 :            :     OVS_REQUIRES(ofproto_mutex)
    4065                 :            : {
    4066                 :            :     struct oftable *table;
    4067                 :       1159 :     enum ofperr error = 0;
    4068                 :       1159 :     size_t n_readonly = 0;
    4069                 :            : 
    4070                 :       1159 :     rule_collection_init(rules);
    4071                 :            : 
    4072         [ -  + ]:       1159 :     if (!check_table_id(ofproto, criteria->table_id)) {
    4073                 :          0 :         error = OFPERR_OFPBRC_BAD_TABLE_ID;
    4074                 :          0 :         goto exit;
    4075                 :            :     }
    4076                 :            : 
    4077         [ +  + ]:       1159 :     if (criteria->cookie_mask == OVS_BE64_MAX) {
    4078                 :            :         struct rule *rule;
    4079                 :            : 
    4080         [ +  + ]:       7208 :         HINDEX_FOR_EACH_WITH_HASH (rule, cookie_node,
    4081                 :            :                                    hash_cookie(criteria->cookie),
    4082                 :            :                                    &ofproto->cookies) {
    4083         [ +  - ]:       7185 :             if (cls_rule_is_loose_match(&rule->cr, &criteria->cr.match)) {
    4084                 :       7185 :                 collect_rule(rule, criteria, rules, &n_readonly);
    4085                 :            :             }
    4086                 :            :         }
    4087                 :            :     } else {
    4088         [ +  + ]:     264380 :         FOR_EACH_MATCHING_TABLE (table, criteria->table_id, ofproto) {
    4089                 :            :             struct rule *rule;
    4090                 :            : 
    4091 [ +  + ][ +  + ]:     282750 :             CLS_FOR_EACH_TARGET (rule, cr, &table->cls, &criteria->cr,
    4092                 :            :                                  criteria->version) {
    4093                 :      19506 :                 collect_rule(rule, criteria, rules, &n_readonly);
    4094                 :            :             }
    4095                 :            :         }
    4096                 :            :     }
    4097                 :            : 
    4098                 :            : exit:
    4099 [ +  - ][ +  + ]:       1159 :     if (!error && !rule_collection_n(rules) && n_readonly) {
                 [ -  + ]
    4100                 :            :         /* We didn't find any rules to modify.  We did find some read-only
    4101                 :            :          * rules that we're not allowed to modify, so report that. */
    4102                 :          0 :         error = OFPERR_OFPBRC_EPERM;
    4103                 :            :     }
    4104         [ -  + ]:       1159 :     if (error) {
    4105                 :          0 :         rule_collection_destroy(rules);
    4106                 :            :     }
    4107                 :       1159 :     return error;
    4108                 :            : }
    4109                 :            : 
    4110                 :            : /* Searches 'ofproto' for rules that match the criteria in 'criteria'.  Matches
    4111                 :            :  * on classifiers rules are done in the "strict" way required for OpenFlow
    4112                 :            :  * OFPFC_MODIFY_STRICT and OFPFC_DELETE_STRICT requests.  Puts the selected
    4113                 :            :  * rules on list 'rules'.
    4114                 :            :  *
    4115                 :            :  * Returns 0 on success, otherwise an OpenFlow error code. */
    4116                 :            : static enum ofperr
    4117                 :       6696 : collect_rules_strict(struct ofproto *ofproto,
    4118                 :            :                      const struct rule_criteria *criteria,
    4119                 :            :                      struct rule_collection *rules)
    4120                 :            :     OVS_REQUIRES(ofproto_mutex)
    4121                 :            : {
    4122                 :            :     struct oftable *table;
    4123                 :       6696 :     size_t n_readonly = 0;
    4124                 :       6696 :     enum ofperr error = 0;
    4125                 :            : 
    4126                 :       6696 :     rule_collection_init(rules);
    4127                 :            : 
    4128         [ -  + ]:       6696 :     if (!check_table_id(ofproto, criteria->table_id)) {
    4129                 :          0 :         error = OFPERR_OFPBRC_BAD_TABLE_ID;
    4130                 :          0 :         goto exit;
    4131                 :            :     }
    4132                 :            : 
    4133         [ -  + ]:       6696 :     if (criteria->cookie_mask == OVS_BE64_MAX) {
    4134                 :            :         struct rule *rule;
    4135                 :            : 
    4136         [ #  # ]:          0 :         HINDEX_FOR_EACH_WITH_HASH (rule, cookie_node,
    4137                 :            :                                    hash_cookie(criteria->cookie),
    4138                 :            :                                    &ofproto->cookies) {
    4139         [ #  # ]:          0 :             if (cls_rule_equal(&rule->cr, &criteria->cr)) {
    4140                 :          0 :                 collect_rule(rule, criteria, rules, &n_readonly);
    4141                 :            :             }
    4142                 :            :         }
    4143                 :            :     } else {
    4144         [ +  + ]:      20476 :         FOR_EACH_MATCHING_TABLE (table, criteria->table_id, ofproto) {
    4145                 :            :             struct rule *rule;
    4146                 :            : 
    4147                 :      13780 :             rule = rule_from_cls_rule(classifier_find_rule_exactly(
    4148                 :      13780 :                                           &table->cls, &criteria->cr,
    4149                 :            :                                           criteria->version));
    4150         [ +  + ]:      13780 :             if (rule) {
    4151                 :       6240 :                 collect_rule(rule, criteria, rules, &n_readonly);
    4152                 :            :             }
    4153                 :            :         }
    4154                 :            :     }
    4155                 :            : 
    4156                 :            : exit:
    4157 [ +  - ][ +  + ]:       6696 :     if (!error && !rule_collection_n(rules) && n_readonly) {
                 [ -  + ]
    4158                 :            :         /* We didn't find any rules to modify.  We did find some read-only
    4159                 :            :          * rules that we're not allowed to modify, so report that. */
    4160                 :          0 :         error = OFPERR_OFPBRC_EPERM;
    4161                 :            :     }
    4162         [ -  + ]:       6696 :     if (error) {
    4163                 :          0 :         rule_collection_destroy(rules);
    4164                 :            :     }
    4165                 :       6696 :     return error;
    4166                 :            : }
    4167                 :            : 
    4168                 :            : /* Returns 'age_ms' (a duration in milliseconds), converted to seconds and
    4169                 :            :  * forced into the range of a uint16_t. */
    4170                 :            : static int
    4171                 :      37278 : age_secs(long long int age_ms)
    4172                 :            : {
    4173 [ +  - ][ +  - ]:      37278 :     return (age_ms < 0 ? 0
    4174                 :            :             : age_ms >= UINT16_MAX * 1000 ? UINT16_MAX
    4175                 :      37278 :             : (unsigned int) age_ms / 1000);
    4176                 :            : }
    4177                 :            : 
    4178                 :            : static enum ofperr
    4179                 :        384 : handle_flow_stats_request(struct ofconn *ofconn,
    4180                 :            :                           const struct ofp_header *request)
    4181                 :            :     OVS_EXCLUDED(ofproto_mutex)
    4182                 :            : {
    4183                 :        384 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
    4184                 :            :     struct ofputil_flow_stats_request fsr;
    4185                 :            :     struct rule_criteria criteria;
    4186                 :            :     struct rule_collection rules;
    4187                 :            :     struct ovs_list replies;
    4188                 :            :     enum ofperr error;
    4189                 :            : 
    4190                 :        384 :     error = ofputil_decode_flow_stats_request(&fsr, request);
    4191         [ -  + ]:        384 :     if (error) {
    4192                 :          0 :         return error;
    4193                 :            :     }
    4194                 :            : 
    4195                 :        384 :     rule_criteria_init(&criteria, fsr.table_id, &fsr.match, 0, OVS_VERSION_MAX,
    4196                 :            :                        fsr.cookie, fsr.cookie_mask, fsr.out_port,
    4197                 :            :                        fsr.out_group);
    4198                 :            : 
    4199                 :        384 :     ovs_mutex_lock(&ofproto_mutex);
    4200                 :        384 :     error = collect_rules_loose(ofproto, &criteria, &rules);
    4201                 :        384 :     rule_criteria_destroy(&criteria);
    4202         [ +  - ]:        384 :     if (!error) {
    4203                 :        384 :         rule_collection_ref(&rules);
    4204                 :            :     }
    4205                 :        384 :     ovs_mutex_unlock(&ofproto_mutex);
    4206                 :            : 
    4207         [ -  + ]:        384 :     if (error) {
    4208                 :          0 :         return error;
    4209                 :            :     }
    4210                 :            : 
    4211                 :        384 :     ofpmp_init(&replies, request);
    4212                 :            :     struct rule *rule;
    4213 [ +  + ][ +  - ]:      19023 :     RULE_COLLECTION_FOR_EACH (rule, &rules) {
    4214                 :      18639 :         long long int now = time_msec();
    4215                 :            :         struct ofputil_flow_stats fs;
    4216                 :            :         long long int created, used, modified;
    4217                 :            :         const struct rule_actions *actions;
    4218                 :            :         enum ofputil_flow_mod_flags flags;
    4219                 :            : 
    4220                 :      18639 :         ovs_mutex_lock(&rule->mutex);
    4221                 :      18639 :         fs.cookie = rule->flow_cookie;
    4222                 :      18639 :         fs.idle_timeout = rule->idle_timeout;
    4223                 :      18639 :         fs.hard_timeout = rule->hard_timeout;
    4224                 :      18639 :         fs.importance = rule->importance;
    4225                 :      18639 :         created = rule->created;
    4226                 :      18639 :         modified = rule->modified;
    4227                 :      18639 :         actions = rule_get_actions(rule);
    4228                 :      18639 :         flags = rule->flags;
    4229                 :      18639 :         ovs_mutex_unlock(&rule->mutex);
    4230                 :            : 
    4231                 :      18639 :         ofproto->ofproto_class->rule_get_stats(rule, &fs.packet_count,
    4232                 :            :                                                &fs.byte_count, &used);
    4233                 :            : 
    4234                 :      18639 :         minimatch_expand(&rule->cr.match, &fs.match);
    4235                 :      18639 :         fs.table_id = rule->table_id;
    4236                 :      18639 :         calc_duration(created, now, &fs.duration_sec, &fs.duration_nsec);
    4237                 :      18639 :         fs.priority = rule->cr.priority;
    4238                 :      18639 :         fs.idle_age = age_secs(now - used);
    4239                 :      18639 :         fs.hard_age = age_secs(now - modified);
    4240                 :      18639 :         fs.ofpacts = actions->ofpacts;
    4241                 :      18639 :         fs.ofpacts_len = actions->ofpacts_len;
    4242                 :            : 
    4243                 :      18639 :         fs.flags = flags;
    4244                 :      18639 :         ofputil_append_flow_stats_reply(&fs, &replies);
    4245                 :            :     }
    4246                 :            : 
    4247                 :        384 :     rule_collection_unref(&rules);
    4248                 :        384 :     rule_collection_destroy(&rules);
    4249                 :            : 
    4250                 :        384 :     ofconn_send_replies(ofconn, &replies);
    4251                 :            : 
    4252                 :        384 :     return 0;
    4253                 :            : }
    4254                 :            : 
    4255                 :            : static void
    4256                 :        272 : flow_stats_ds(struct rule *rule, struct ds *results)
    4257                 :            : {
    4258                 :            :     uint64_t packet_count, byte_count;
    4259                 :            :     const struct rule_actions *actions;
    4260                 :            :     long long int created, used;
    4261                 :            : 
    4262                 :        272 :     rule->ofproto->ofproto_class->rule_get_stats(rule, &packet_count,
    4263                 :            :                                                  &byte_count, &used);
    4264                 :            : 
    4265                 :        272 :     ovs_mutex_lock(&rule->mutex);
    4266                 :        272 :     actions = rule_get_actions(rule);
    4267                 :        272 :     created = rule->created;
    4268                 :        272 :     ovs_mutex_unlock(&rule->mutex);
    4269                 :            : 
    4270         [ +  + ]:        272 :     if (rule->table_id != 0) {
    4271                 :        264 :         ds_put_format(results, "table_id=%"PRIu8", ", rule->table_id);
    4272                 :            :     }
    4273                 :        272 :     ds_put_format(results, "duration=%llds, ", (time_msec() - created) / 1000);
    4274                 :        272 :     ds_put_format(results, "n_packets=%"PRIu64", ", packet_count);
    4275                 :        272 :     ds_put_format(results, "n_bytes=%"PRIu64", ", byte_count);
    4276                 :        272 :     cls_rule_format(&rule->cr, results);
    4277                 :        272 :     ds_put_char(results, ',');
    4278                 :            : 
    4279                 :        272 :     ds_put_cstr(results, "actions=");
    4280                 :        272 :     ofpacts_format(actions->ofpacts, actions->ofpacts_len, results);
    4281                 :            : 
    4282                 :        272 :     ds_put_cstr(results, "\n");
    4283                 :        272 : }
    4284                 :            : 
    4285                 :            : /* Adds a pretty-printed description of all flows to 'results', including
    4286                 :            :  * hidden flows (e.g., set up by in-band control). */
    4287                 :            : void
    4288                 :          2 : ofproto_get_all_flows(struct ofproto *p, struct ds *results)
    4289                 :            : {
    4290                 :            :     struct oftable *table;
    4291                 :            : 
    4292         [ +  + ]:        512 :     OFPROTO_FOR_EACH_TABLE (table, p) {
    4293                 :            :         struct rule *rule;
    4294                 :            : 
    4295 [ +  + ][ +  + ]:        782 :         CLS_FOR_EACH (rule, cr, &table->cls) {
    4296                 :        272 :             flow_stats_ds(rule, results);
    4297                 :            :         }
    4298                 :            :     }
    4299                 :          2 : }
    4300                 :            : 
    4301                 :            : /* Obtains the NetFlow engine type and engine ID for 'ofproto' into
    4302                 :            :  * '*engine_type' and '*engine_id', respectively. */
    4303                 :            : void
    4304                 :          6 : ofproto_get_netflow_ids(const struct ofproto *ofproto,
    4305                 :            :                         uint8_t *engine_type, uint8_t *engine_id)
    4306                 :            : {
    4307                 :          6 :     ofproto->ofproto_class->get_netflow_ids(ofproto, engine_type, engine_id);
    4308                 :          6 : }
    4309                 :            : 
    4310                 :            : /* Checks the status change of CFM on 'ofport'.
    4311                 :            :  *
    4312                 :            :  * Returns true if 'ofproto_class' does not support 'cfm_status_changed'. */
    4313                 :            : bool
    4314                 :      36469 : ofproto_port_cfm_status_changed(struct ofproto *ofproto, ofp_port_t ofp_port)
    4315                 :            : {
    4316                 :      36469 :     struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
    4317 [ +  + ][ -  + ]:      72938 :     return (ofport && ofproto->ofproto_class->cfm_status_changed
    4318                 :      36468 :             ? ofproto->ofproto_class->cfm_status_changed(ofport)
    4319   [ +  +  +  + ]:      72937 :             : true);
    4320                 :            : }
    4321                 :            : 
    4322                 :            : /* Checks the status of CFM configured on 'ofp_port' within 'ofproto'.
    4323                 :            :  * Returns 0 if the port's CFM status was successfully stored into
    4324                 :            :  * '*status'.  Returns positive errno if the port did not have CFM
    4325                 :            :  * configured.
    4326                 :            :  *
    4327                 :            :  * The caller must provide and own '*status', and must free 'status->rmps'.
    4328                 :            :  * '*status' is indeterminate if the return value is non-zero. */
    4329                 :            : int
    4330                 :      36454 : ofproto_port_get_cfm_status(const struct ofproto *ofproto, ofp_port_t ofp_port,
    4331                 :            :                             struct cfm_status *status)
    4332                 :            : {
    4333                 :      36454 :     struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
    4334         [ +  - ]:      72907 :     return (ofport && ofproto->ofproto_class->get_cfm_status
    4335                 :      36453 :             ? ofproto->ofproto_class->get_cfm_status(ofport, status)
    4336         [ +  + ]:      72907 :             : EOPNOTSUPP);
    4337                 :            : }
    4338                 :            : 
    4339                 :            : static enum ofperr
    4340                 :          5 : handle_aggregate_stats_request(struct ofconn *ofconn,
    4341                 :            :                                const struct ofp_header *oh)
    4342                 :            :     OVS_EXCLUDED(ofproto_mutex)
    4343                 :            : {
    4344                 :          5 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
    4345                 :            :     struct ofputil_flow_stats_request request;
    4346                 :            :     struct ofputil_aggregate_stats stats;
    4347                 :            :     bool unknown_packets, unknown_bytes;
    4348                 :            :     struct rule_criteria criteria;
    4349                 :            :     struct rule_collection rules;
    4350                 :            :     struct ofpbuf *reply;
    4351                 :            :     enum ofperr error;
    4352                 :            : 
    4353                 :          5 :     error = ofputil_decode_flow_stats_request(&request, oh);
    4354         [ -  + ]:          5 :     if (error) {
    4355                 :          0 :         return error;
    4356                 :            :     }
    4357                 :            : 
    4358                 :          5 :     rule_criteria_init(&criteria, request.table_id, &request.match, 0,
    4359                 :            :                        OVS_VERSION_MAX, request.cookie, request.cookie_mask,
    4360                 :            :                        request.out_port, request.out_group);
    4361                 :            : 
    4362                 :          5 :     ovs_mutex_lock(&ofproto_mutex);
    4363                 :          5 :     error = collect_rules_loose(ofproto, &criteria, &rules);
    4364                 :          5 :     rule_criteria_destroy(&criteria);
    4365         [ +  - ]:          5 :     if (!error) {
    4366                 :          5 :         rule_collection_ref(&rules);
    4367                 :            :     }
    4368                 :          5 :     ovs_mutex_unlock(&ofproto_mutex);
    4369                 :            : 
    4370         [ -  + ]:          5 :     if (error) {
    4371                 :          0 :         return error;
    4372                 :            :     }
    4373                 :            : 
    4374                 :          5 :     memset(&stats, 0, sizeof stats);
    4375                 :          5 :     unknown_packets = unknown_bytes = false;
    4376                 :            : 
    4377                 :            :     struct rule *rule;
    4378 [ +  + ][ +  - ]:         15 :     RULE_COLLECTION_FOR_EACH (rule, &rules) {
    4379                 :            :         uint64_t packet_count;
    4380                 :            :         uint64_t byte_count;
    4381                 :            :         long long int used;
    4382                 :            : 
    4383                 :         10 :         ofproto->ofproto_class->rule_get_stats(rule, &packet_count,
    4384                 :            :                                                &byte_count, &used);
    4385                 :            : 
    4386         [ -  + ]:         10 :         if (packet_count == UINT64_MAX) {
    4387                 :          0 :             unknown_packets = true;
    4388                 :            :         } else {
    4389                 :         10 :             stats.packet_count += packet_count;
    4390                 :            :         }
    4391                 :            : 
    4392         [ -  + ]:         10 :         if (byte_count == UINT64_MAX) {
    4393                 :          0 :             unknown_bytes = true;
    4394                 :            :         } else {
    4395                 :         10 :             stats.byte_count += byte_count;
    4396                 :            :         }
    4397                 :            : 
    4398                 :         10 :         stats.flow_count++;
    4399                 :            :     }
    4400         [ -  + ]:          5 :     if (unknown_packets) {
    4401                 :          0 :         stats.packet_count = UINT64_MAX;
    4402                 :            :     }
    4403         [ -  + ]:          5 :     if (unknown_bytes) {
    4404                 :          0 :         stats.byte_count = UINT64_MAX;
    4405                 :            :     }
    4406                 :            : 
    4407                 :          5 :     rule_collection_unref(&rules);
    4408                 :          5 :     rule_collection_destroy(&rules);
    4409                 :            : 
    4410                 :          5 :     reply = ofputil_encode_aggregate_stats_reply(&stats, oh);
    4411                 :          5 :     ofconn_send_reply(ofconn, reply);
    4412                 :            : 
    4413                 :          5 :     return 0;
    4414                 :            : }
    4415                 :            : 
    4416                 :            : struct queue_stats_cbdata {
    4417                 :            :     struct ofport *ofport;
    4418                 :            :     struct ovs_list replies;
    4419                 :            :     long long int now;
    4420                 :            : };
    4421                 :            : 
    4422                 :            : static void
    4423                 :         20 : put_queue_stats(struct queue_stats_cbdata *cbdata, uint32_t queue_id,
    4424                 :            :                 const struct netdev_queue_stats *stats)
    4425                 :            : {
    4426                 :            :     struct ofputil_queue_stats oqs;
    4427                 :            : 
    4428                 :         20 :     oqs.port_no = cbdata->ofport->pp.port_no;
    4429                 :         20 :     oqs.queue_id = queue_id;
    4430                 :         20 :     oqs.tx_bytes = stats->tx_bytes;
    4431                 :         20 :     oqs.tx_packets = stats->tx_packets;
    4432                 :         20 :     oqs.tx_errors = stats->tx_errors;
    4433         [ -  + ]:         20 :     if (stats->created != LLONG_MIN) {
    4434                 :          0 :         calc_duration(stats->created, cbdata->now,
    4435                 :            :                       &oqs.duration_sec, &oqs.duration_nsec);
    4436                 :            :     } else {
    4437                 :         20 :         oqs.duration_sec = oqs.duration_nsec = UINT32_MAX;
    4438                 :            :     }
    4439                 :         20 :     ofputil_append_queue_stat(&cbdata->replies, &oqs);
    4440                 :         20 : }
    4441                 :            : 
    4442                 :            : static void
    4443                 :         10 : handle_queue_stats_dump_cb(uint32_t queue_id,
    4444                 :            :                            struct netdev_queue_stats *stats,
    4445                 :            :                            void *cbdata_)
    4446                 :            : {
    4447                 :         10 :     struct queue_stats_cbdata *cbdata = cbdata_;
    4448                 :            : 
    4449                 :         10 :     put_queue_stats(cbdata, queue_id, stats);
    4450                 :         10 : }
    4451                 :            : 
    4452                 :            : static enum ofperr
    4453                 :         30 : handle_queue_stats_for_port(struct ofport *port, uint32_t queue_id,
    4454                 :            :                             struct queue_stats_cbdata *cbdata)
    4455                 :            : {
    4456                 :         30 :     cbdata->ofport = port;
    4457         [ +  + ]:         30 :     if (queue_id == OFPQ_ALL) {
    4458                 :         10 :         netdev_dump_queue_stats(port->netdev,
    4459                 :            :                                 handle_queue_stats_dump_cb, cbdata);
    4460                 :            :     } else {
    4461                 :            :         struct netdev_queue_stats stats;
    4462                 :            : 
    4463         [ +  + ]:         20 :         if (!netdev_get_queue_stats(port->netdev, queue_id, &stats)) {
    4464                 :         10 :             put_queue_stats(cbdata, queue_id, &stats);
    4465                 :            :         } else {
    4466                 :         10 :             return OFPERR_OFPQOFC_BAD_QUEUE;
    4467                 :            :         }
    4468                 :            :     }
    4469                 :         20 :     return 0;
    4470                 :            : }
    4471                 :            : 
    4472                 :            : static enum ofperr
    4473                 :         35 : handle_queue_stats_request(struct ofconn *ofconn,
    4474                 :            :                            const struct ofp_header *rq)
    4475                 :            : {
    4476                 :         35 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
    4477                 :            :     struct queue_stats_cbdata cbdata;
    4478                 :            :     struct ofport *port;
    4479                 :            :     enum ofperr error;
    4480                 :            :     struct ofputil_queue_stats_request oqsr;
    4481                 :            : 
    4482                 :         35 :     COVERAGE_INC(ofproto_queue_req);
    4483                 :            : 
    4484                 :         35 :     ofpmp_init(&cbdata.replies, rq);
    4485                 :         35 :     cbdata.now = time_msec();
    4486                 :            : 
    4487                 :         35 :     error = ofputil_decode_queue_stats_request(rq, &oqsr);
    4488         [ -  + ]:         35 :     if (error) {
    4489                 :          0 :         return error;
    4490                 :            :     }
    4491                 :            : 
    4492         [ +  + ]:         35 :     if (oqsr.port_no == OFPP_ANY) {
    4493                 :         15 :         error = OFPERR_OFPQOFC_BAD_QUEUE;
    4494 [ +  + ][ -  + ]:         30 :         HMAP_FOR_EACH (port, hmap_node, &ofproto->ports) {
    4495         [ +  + ]:         15 :             if (!handle_queue_stats_for_port(port, oqsr.queue_id, &cbdata)) {
    4496                 :         10 :                 error = 0;
    4497                 :            :             }
    4498                 :            :         }
    4499                 :            :     } else {
    4500                 :         20 :         port = ofproto_get_port(ofproto, oqsr.port_no);
    4501         [ +  + ]:         20 :         error = (port
    4502                 :         15 :                  ? handle_queue_stats_for_port(port, oqsr.queue_id, &cbdata)
    4503                 :            :                  : OFPERR_OFPQOFC_BAD_PORT);
    4504                 :            :     }
    4505         [ +  + ]:         35 :     if (!error) {
    4506                 :         20 :         ofconn_send_replies(ofconn, &cbdata.replies);
    4507                 :            :     } else {
    4508                 :         15 :         ofpbuf_list_delete(&cbdata.replies);
    4509                 :            :     }
    4510                 :            : 
    4511                 :         35 :     return error;
    4512                 :            : }
    4513                 :            : 
    4514                 :            : static enum ofperr
    4515                 :    1193800 : evict_rules_from_table(struct oftable *table)
    4516                 :            :     OVS_REQUIRES(ofproto_mutex)
    4517                 :            : {
    4518                 :    1193800 :     enum ofperr error = 0;
    4519                 :            :     struct rule_collection rules;
    4520                 :    1193800 :     unsigned int count = table->n_flows;
    4521                 :    1193800 :     unsigned int max_flows = table->max_flows;
    4522                 :            : 
    4523                 :    1193800 :     rule_collection_init(&rules);
    4524                 :            : 
    4525         [ +  + ]:    1193806 :     while (count-- > max_flows) {
    4526                 :            :         struct rule *rule;
    4527                 :            : 
    4528         [ -  + ]:          6 :         if (!choose_rule_to_evict(table, &rule)) {
    4529                 :          0 :             error = OFPERR_OFPFMFC_TABLE_FULL;
    4530                 :          0 :             break;
    4531                 :            :         } else {
    4532                 :          6 :             eviction_group_remove_rule(rule);
    4533                 :          6 :             rule_collection_add(&rules, rule);
    4534                 :            :         }
    4535                 :            :     }
    4536                 :    1193800 :     delete_flows__(&rules, OFPRR_EVICTION, NULL);
    4537                 :            : 
    4538                 :    1193800 :     return error;
    4539                 :            : }
    4540                 :            : 
    4541                 :            : static void
    4542                 :      31452 : get_conjunctions(const struct ofputil_flow_mod *fm,
    4543                 :            :                  struct cls_conjunction **conjsp, size_t *n_conjsp)
    4544                 :            : {
    4545                 :      31452 :     struct cls_conjunction *conjs = NULL;
    4546                 :      31452 :     int n_conjs = 0;
    4547                 :            : 
    4548                 :            :     const struct ofpact *ofpact;
    4549         [ +  + ]:      31497 :     OFPACT_FOR_EACH (ofpact, fm->ofpacts, fm->ofpacts_len) {
    4550         [ +  + ]:      18567 :         if (ofpact->type == OFPACT_CONJUNCTION) {
    4551                 :         43 :             n_conjs++;
    4552         [ +  + ]:      18524 :         } else if (ofpact->type != OFPACT_NOTE) {
    4553                 :            :             /* "conjunction" may appear with "note" actions but not with any
    4554                 :            :              * other type of actions. */
    4555         [ -  + ]:      18522 :             ovs_assert(!n_conjs);
    4556                 :      18522 :             break;
    4557                 :            :         }
    4558                 :            :     }
    4559         [ +  + ]:      31452 :     if (n_conjs) {
    4560                 :         36 :         int i = 0;
    4561                 :            : 
    4562                 :         36 :         conjs = xzalloc(n_conjs * sizeof *conjs);
    4563         [ +  + ]:         81 :         OFPACT_FOR_EACH (ofpact, fm->ofpacts, fm->ofpacts_len) {
    4564         [ +  + ]:         45 :             if (ofpact->type == OFPACT_CONJUNCTION) {
    4565                 :         43 :                 struct ofpact_conjunction *oc = ofpact_get_CONJUNCTION(ofpact);
    4566                 :         43 :                 conjs[i].clause = oc->clause;
    4567                 :         43 :                 conjs[i].n_clauses = oc->n_clauses;
    4568                 :         43 :                 conjs[i].id = oc->id;
    4569                 :         43 :                 i++;
    4570                 :            :             }
    4571                 :            :         }
    4572                 :            :     }
    4573                 :            : 
    4574                 :      31452 :     *conjsp = conjs;
    4575                 :      31452 :     *n_conjsp = n_conjs;
    4576                 :      31452 : }
    4577                 :            : 
    4578                 :            : /* add_flow_init(), add_flow_start(), add_flow_revert(), and add_flow_finish()
    4579                 :            :  * implement OFPFC_ADD and the cases for OFPFC_MODIFY and OFPFC_MODIFY_STRICT
    4580                 :            :  * in which no matching flow already exists in the flow table.
    4581                 :            :  *
    4582                 :            :  * add_flow_init() creates a new flow according to 'fm' and stores it to 'ofm'
    4583                 :            :  * for later reference.  If the flow replaces other flow, it will be updated to
    4584                 :            :  * match modify semantics later by add_flow_start() (by calling
    4585                 :            :  * replace_rule_start()).
    4586                 :            :  *
    4587                 :            :  * Returns 0 on success, or an OpenFlow error code on failure.
    4588                 :            :  *
    4589                 :            :  * On successful return the caller must complete the operation by calling
    4590                 :            :  * add_flow_start(), and if that succeeds, then either add_flow_finish(), or
    4591                 :            :  * add_flow_revert() if the operation needs to be reverted due to a later
    4592                 :            :  * failure.
    4593                 :            :  */
    4594                 :            : static enum ofperr
    4595                 :      32012 : add_flow_init(struct ofproto *ofproto, struct ofproto_flow_mod *ofm,
    4596                 :            :               const struct ofputil_flow_mod *fm)
    4597                 :            :     OVS_EXCLUDED(ofproto_mutex)
    4598                 :            : {
    4599                 :            :     struct oftable *table;
    4600                 :            :     struct cls_rule cr;
    4601                 :            :     uint8_t table_id;
    4602                 :            :     enum ofperr error;
    4603                 :            : 
    4604         [ -  + ]:      32012 :     if (!check_table_id(ofproto, fm->table_id)) {
    4605                 :          0 :         return OFPERR_OFPBRC_BAD_TABLE_ID;
    4606                 :            :     }
    4607                 :            : 
    4608                 :            :     /* Pick table. */
    4609         [ +  + ]:      32012 :     if (fm->table_id == 0xff) {
    4610         [ -  + ]:       9662 :         if (ofproto->ofproto_class->rule_choose_table) {
    4611                 :          0 :             error = ofproto->ofproto_class->rule_choose_table(ofproto,
    4612                 :            :                                                               &fm->match,
    4613                 :            :                                                               &table_id);
    4614         [ #  # ]:          0 :             if (error) {
    4615                 :          0 :                 return error;
    4616                 :            :             }
    4617         [ #  # ]:          0 :             ovs_assert(table_id < ofproto->n_tables);
    4618                 :            :         } else {
    4619                 :       9662 :             table_id = 0;
    4620                 :            :         }
    4621         [ +  - ]:      22350 :     } else if (fm->table_id < ofproto->n_tables) {
    4622                 :      22350 :         table_id = fm->table_id;
    4623                 :            :     } else {
    4624                 :          0 :         return OFPERR_OFPBRC_BAD_TABLE_ID;
    4625                 :            :     }
    4626                 :            : 
    4627                 :      32012 :     table = &ofproto->tables[table_id];
    4628         [ +  + ]:      32012 :     if (table->flags & OFTABLE_READONLY
    4629         [ +  + ]:       1794 :         && !(fm->flags & OFPUTIL_FF_NO_READONLY)) {
    4630                 :          2 :         return OFPERR_OFPBRC_EPERM;
    4631                 :            :     }
    4632                 :            : 
    4633         [ +  + ]:      32010 :     if (!(fm->flags & OFPUTIL_FF_HIDDEN_FIELDS)
    4634         [ -  + ]:      27222 :         && !match_has_default_hidden_fields(&fm->match)) {
    4635         [ #  # ]:          0 :         VLOG_WARN_RL(&rl, "%s: (add_flow) only internal flows can set "
    4636                 :            :                      "non-default values to hidden fields", ofproto->name);
    4637                 :          0 :         return OFPERR_OFPBRC_EPERM;
    4638                 :            :     }
    4639                 :            : 
    4640                 :      32010 :     cls_rule_init(&cr, &fm->match, fm->priority);
    4641                 :            : 
    4642                 :            :     /* Allocate new rule.  Destroys 'cr'. */
    4643                 :      32010 :     error = ofproto_rule_create(ofproto, &cr, table - ofproto->tables,
    4644                 :      32010 :                                 fm->new_cookie, fm->idle_timeout,
    4645                 :      64020 :                                 fm->hard_timeout, fm->flags, fm->importance,
    4646                 :      32010 :                                 fm->ofpacts, fm->ofpacts_len, &ofm->temp_rule);
    4647         [ +  + ]:      32010 :     if (error) {
    4648                 :        558 :         return error;
    4649                 :            :     }
    4650                 :            : 
    4651                 :      31452 :     get_conjunctions(fm, &ofm->conjs, &ofm->n_conjs);
    4652                 :      32012 :     return 0;
    4653                 :            : }
    4654                 :            : 
    4655                 :            : static enum ofperr
    4656                 :      31063 : add_flow_start(struct ofproto *ofproto, struct ofproto_flow_mod *ofm)
    4657                 :            :     OVS_REQUIRES(ofproto_mutex)
    4658                 :            : {
    4659                 :      31063 :     struct rule *old_rule = NULL;
    4660                 :      31063 :     struct rule *new_rule = ofm->temp_rule;
    4661                 :      31063 :     const struct rule_actions *actions = rule_get_actions(new_rule);
    4662                 :      31063 :     struct oftable *table = &ofproto->tables[new_rule->table_id];
    4663                 :            :     enum ofperr error;
    4664                 :            : 
    4665                 :            :     /* Must check actions while holding ofproto_mutex to avoid a race. */
    4666                 :      31063 :     error = ofproto_check_ofpacts(ofproto, actions->ofpacts,
    4667                 :      31063 :                                   actions->ofpacts_len);
    4668         [ +  + ]:      31063 :     if (error) {
    4669                 :          3 :         return error;
    4670                 :            :     }
    4671                 :            : 
    4672                 :            :     /* Check for the existence of an identical rule.
    4673                 :            :      * This will not return rules earlier marked for removal. */
    4674                 :      31060 :     old_rule = rule_from_cls_rule(classifier_find_rule_exactly(&table->cls,
    4675                 :            :                                                                &new_rule->cr,
    4676                 :            :                                                                ofm->version));
    4677         [ +  + ]:      31060 :     if (!old_rule) {
    4678                 :            :         /* Check for overlap, if requested. */
    4679         [ +  + ]:      30443 :         if (new_rule->flags & OFPUTIL_FF_CHECK_OVERLAP
    4680         [ -  + ]:          1 :             && classifier_rule_overlaps(&table->cls, &new_rule->cr,
    4681                 :            :                                         ofm->version)) {
    4682                 :          0 :             return OFPERR_OFPFMFC_OVERLAP;
    4683                 :            :         }
    4684                 :            : 
    4685                 :            :         /* If necessary, evict an existing rule to clear out space. */
    4686         [ +  + ]:      30443 :         if (table->n_flows >= table->max_flows) {
    4687         [ +  + ]:         20 :             if (!choose_rule_to_evict(table, &old_rule)) {
    4688                 :          7 :                 return OFPERR_OFPFMFC_TABLE_FULL;
    4689                 :            :             }
    4690                 :         13 :             eviction_group_remove_rule(old_rule);
    4691                 :            :             /* Marks 'old_rule' as an evicted rule rather than replaced rule.
    4692                 :            :              */
    4693                 :      30436 :             old_rule->removed_reason = OFPRR_EVICTION;
    4694                 :            :         }
    4695                 :            :     } else {
    4696                 :        617 :         ofm->modify_cookie = true;
    4697                 :            :     }
    4698                 :            : 
    4699         [ +  + ]:      31053 :     if (old_rule) {
    4700                 :        630 :         rule_collection_add(&ofm->old_rules, old_rule);
    4701                 :            :     }
    4702                 :            :     /* Take ownership of the temp_rule. */
    4703                 :      31053 :     rule_collection_add(&ofm->new_rules, new_rule);
    4704                 :      31053 :     ofm->temp_rule = NULL;
    4705                 :            : 
    4706                 :      31053 :     replace_rule_start(ofproto, ofm, old_rule, new_rule);
    4707                 :      31063 :     return 0;
    4708                 :            : }
    4709                 :            : 
    4710                 :            : /* Revert the effects of add_flow_start(). */
    4711                 :            : static void
    4712                 :          1 : add_flow_revert(struct ofproto *ofproto, struct ofproto_flow_mod *ofm)
    4713                 :            :     OVS_REQUIRES(ofproto_mutex)
    4714                 :            : {
    4715                 :          1 :     struct rule *old_rule = rule_collection_n(&ofm->old_rules)
    4716         [ -  + ]:          1 :         ? rule_collection_rules(&ofm->old_rules)[0] : NULL;
    4717                 :          1 :     struct rule *new_rule = rule_collection_rules(&ofm->new_rules)[0];
    4718                 :            : 
    4719                 :          1 :     replace_rule_revert(ofproto, old_rule, new_rule);
    4720                 :          1 : }
    4721                 :            : 
    4722                 :            : /* To be called after version bump. */
    4723                 :            : static void
    4724                 :      31051 : add_flow_finish(struct ofproto *ofproto, struct ofproto_flow_mod *ofm,
    4725                 :            :                 const struct openflow_mod_requester *req)
    4726                 :            :     OVS_REQUIRES(ofproto_mutex)
    4727                 :            : {
    4728                 :      31051 :     struct rule *old_rule = rule_collection_n(&ofm->old_rules)
    4729         [ +  + ]:      31051 :         ? rule_collection_rules(&ofm->old_rules)[0] : NULL;
    4730                 :      31051 :     struct rule *new_rule = rule_collection_rules(&ofm->new_rules)[0];
    4731                 :      31051 :     struct ovs_list dead_cookies = OVS_LIST_INITIALIZER(&dead_cookies);
    4732                 :            : 
    4733                 :      31051 :     replace_rule_finish(ofproto, ofm, req, old_rule, new_rule, &dead_cookies);
    4734                 :      31051 :     learned_cookies_flush(ofproto, &dead_cookies);
    4735                 :            : 
    4736         [ +  + ]:      31051 :     if (old_rule) {
    4737                 :        629 :         ovsrcu_postpone(remove_rule_rcu, old_rule);
    4738                 :            :     } else {
    4739 [ +  + ][ +  + ]:      30422 :         ofmonitor_report(ofproto->connmgr, new_rule, NXFME_ADDED, 0,
    4740                 :            :                          req ? req->ofconn : NULL,
    4741                 :      25978 :                          req ? req->request->xid : 0, NULL);
    4742                 :            : 
    4743                 :            :         /* Send Vacancy Events for OF1.4+. */
    4744                 :      30422 :         send_table_status(ofproto, new_rule->table_id);
    4745                 :            :     }
    4746                 :      31051 : }
    4747                 :            : 
    4748                 :            : /* OFPFC_MODIFY and OFPFC_MODIFY_STRICT. */
    4749                 :            : 
    4750                 :            : /* Create a new rule.  Note that the rule is NOT inserted into a any data
    4751                 :            :  * structures yet.  Takes ownership of 'cr'. */
    4752                 :            : static enum ofperr
    4753                 :      32020 : ofproto_rule_create(struct ofproto *ofproto, struct cls_rule *cr,
    4754                 :            :                     uint8_t table_id, ovs_be64 new_cookie,
    4755                 :            :                     uint16_t idle_timeout, uint16_t hard_timeout,
    4756                 :            :                     enum ofputil_flow_mod_flags flags, uint16_t importance,
    4757                 :            :                     const struct ofpact *ofpacts, size_t ofpacts_len,
    4758                 :            :                     struct rule **new_rule)
    4759                 :            :     OVS_NO_THREAD_SAFETY_ANALYSIS
    4760                 :            : {
    4761                 :            :     struct rule *rule;
    4762                 :            :     enum ofperr error;
    4763                 :            : 
    4764                 :            :     /* Allocate new rule. */
    4765                 :      32020 :     rule = ofproto->ofproto_class->rule_alloc();
    4766         [ -  + ]:      32020 :     if (!rule) {
    4767                 :          0 :         cls_rule_destroy(cr);
    4768         [ #  # ]:          0 :         VLOG_WARN_RL(&rl, "%s: failed to allocate a rule.", ofproto->name);
    4769                 :          0 :         return OFPERR_OFPFMFC_UNKNOWN;
    4770                 :            :     }
    4771                 :            : 
    4772                 :            :     /* Initialize base state. */
    4773                 :      32020 :     *CONST_CAST(struct ofproto **, &rule->ofproto) = ofproto;
    4774                 :      32020 :     cls_rule_move(CONST_CAST(struct cls_rule *, &rule->cr), cr);
    4775                 :      32020 :     ovs_refcount_init(&rule->ref_count);
    4776                 :            : 
    4777                 :      32020 :     ovs_mutex_init(&rule->mutex);
    4778                 :      32020 :     ovs_mutex_lock(&rule->mutex);
    4779                 :      32020 :     rule->flow_cookie = new_cookie;
    4780                 :      32020 :     rule->created = rule->modified = time_msec();
    4781                 :      32020 :     rule->idle_timeout = idle_timeout;
    4782                 :      32020 :     rule->hard_timeout = hard_timeout;
    4783                 :      32020 :     *CONST_CAST(uint16_t *, &rule->importance) = importance;
    4784                 :      32020 :     rule->removed_reason = OVS_OFPRR_NONE;
    4785                 :            : 
    4786                 :      32020 :     *CONST_CAST(uint8_t *, &rule->table_id) = table_id;
    4787                 :      32020 :     rule->flags = flags & OFPUTIL_FF_STATE;
    4788                 :            : 
    4789                 :      32020 :     *CONST_CAST(const struct rule_actions **, &rule->actions)
    4790                 :      32020 :         = rule_actions_create(ofpacts, ofpacts_len);
    4791                 :            : 
    4792                 :      32020 :     ovs_list_init(&rule->meter_list_node);
    4793                 :      32020 :     rule->eviction_group = NULL;
    4794                 :      32020 :     rule->monitor_flags = 0;
    4795                 :      32020 :     rule->add_seqno = 0;
    4796                 :      32020 :     rule->modify_seqno = 0;
    4797                 :      32020 :     ovs_list_init(&rule->expirable);
    4798                 :      32020 :     ovs_mutex_unlock(&rule->mutex);
    4799                 :            : 
    4800                 :            :     /* Construct rule, initializing derived state. */
    4801                 :      32020 :     error = ofproto->ofproto_class->rule_construct(rule);
    4802         [ +  + ]:      32020 :     if (error) {
    4803                 :        558 :         ofproto_rule_destroy__(rule);
    4804                 :        558 :         return error;
    4805                 :            :     }
    4806                 :            : 
    4807                 :      31462 :     rule->removed = true;   /* Not yet in ofproto data structures. */
    4808                 :            : 
    4809                 :      31462 :     *new_rule = rule;
    4810                 :      31462 :     return 0;
    4811                 :            : }
    4812                 :            : 
    4813                 :            : static void
    4814                 :      31431 : replace_rule_start(struct ofproto *ofproto, struct ofproto_flow_mod *ofm,
    4815                 :            :                    struct rule *old_rule, struct rule *new_rule)
    4816                 :            : {
    4817                 :      31431 :     struct oftable *table = &ofproto->tables[new_rule->table_id];
    4818                 :            : 
    4819                 :            :     /* 'old_rule' may be either an evicted rule or replaced rule. */
    4820         [ +  + ]:      31431 :     if (old_rule) {
    4821                 :            :         /* Copy values from old rule for modify semantics. */
    4822         [ +  + ]:       1008 :         if (old_rule->removed_reason != OFPRR_EVICTION) {
    4823                 :       1990 :             bool change_cookie = (ofm->modify_cookie
    4824         [ +  - ]:        640 :                                   && new_rule->flow_cookie != OVS_BE64_MAX
    4825 [ +  + ][ +  + ]:       1635 :                                   && new_rule->flow_cookie != old_rule->flow_cookie);
    4826                 :            : 
    4827                 :        995 :             ovs_mutex_lock(&new_rule->mutex);
    4828                 :        995 :             ovs_mutex_lock(&old_rule->mutex);
    4829         [ +  + ]:        995 :             if (ofm->command != OFPFC_ADD) {
    4830                 :        378 :                 new_rule->idle_timeout = old_rule->idle_timeout;
    4831                 :        378 :                 new_rule->hard_timeout = old_rule->hard_timeout;
    4832                 :        378 :                 *CONST_CAST(uint16_t *, &new_rule->importance) = old_rule->importance;
    4833                 :        378 :                 new_rule->flags = old_rule->flags;
    4834                 :        378 :                 new_rule->created = old_rule->created;
    4835                 :            :             }
    4836         [ +  + ]:        995 :             if (!change_cookie) {
    4837                 :        986 :                 new_rule->flow_cookie = old_rule->flow_cookie;
    4838                 :            :             }
    4839                 :        995 :             ovs_mutex_unlock(&old_rule->mutex);
    4840                 :        995 :             ovs_mutex_unlock(&new_rule->mutex);
    4841                 :            :         }
    4842                 :            : 
    4843                 :            :         /* Mark the old rule for removal in the next version. */
    4844                 :       1008 :         cls_rule_make_invisible_in_version(&old_rule->cr, ofm->version);
    4845                 :            : 
    4846                 :            :         /* Remove the old rule from data structures. */
    4847                 :       1008 :         ofproto_rule_remove__(ofproto, old_rule);
    4848                 :            :     } else {
    4849                 :      30423 :         table->n_flows++;
    4850                 :            :     }
    4851                 :            :     /* Insert flow to ofproto data structures, so that later flow_mods may
    4852                 :            :      * relate to it.  This is reversible, in case later errors require this to
    4853                 :            :      * be reverted. */
    4854                 :      31431 :     ofproto_rule_insert__(ofproto, new_rule);
    4855                 :            :     /* Make the new rule visible for classifier lookups only from the next
    4856                 :            :      * version. */
    4857                 :      31431 :     classifier_insert(&table->cls, &new_rule->cr, ofm->version, ofm->conjs,
    4858                 :            :                       ofm->n_conjs);
    4859                 :      31431 : }
    4860                 :            : 
    4861                 :            : static void
    4862                 :          1 : replace_rule_revert(struct ofproto *ofproto,
    4863                 :            :                     struct rule *old_rule, struct rule *new_rule)
    4864                 :            : {
    4865                 :          1 :     struct oftable *table = &ofproto->tables[new_rule->table_id];
    4866                 :            : 
    4867         [ -  + ]:          1 :     if (old_rule) {
    4868         [ #  # ]:          0 :         if (old_rule->removed_reason == OFPRR_EVICTION) {
    4869                 :            :             /* Revert the eviction. */
    4870                 :          0 :             eviction_group_add_rule(old_rule);
    4871                 :            :         }
    4872                 :            : 
    4873                 :            :         /* Restore the old rule to data structures. */
    4874                 :          0 :         ofproto_rule_insert__(ofproto, old_rule);
    4875                 :            : 
    4876                 :            :         /* Restore the original visibility of the old rule. */
    4877                 :          0 :         cls_rule_restore_visibility(&old_rule->cr);
    4878                 :            :     } else {
    4879                 :            :         /* Restore table's rule count. */
    4880                 :          1 :         table->n_flows--;
    4881                 :            :     }
    4882                 :            : 
    4883                 :            :     /* Remove the new rule immediately.  It was never visible to lookups. */
    4884         [ -  + ]:          1 :     if (!classifier_remove(&table->cls, &new_rule->cr)) {
    4885                 :          0 :         OVS_NOT_REACHED();
    4886                 :            :     }
    4887                 :          1 :     ofproto_rule_remove__(ofproto, new_rule);
    4888                 :          1 :     ofproto_rule_unref(new_rule);
    4889                 :          1 : }
    4890                 :            : 
    4891                 :            : /* Adds the 'new_rule', replacing the 'old_rule'. */
    4892                 :            : static void
    4893                 :      31430 : replace_rule_finish(struct ofproto *ofproto, struct ofproto_flow_mod *ofm,
    4894                 :            :                     const struct openflow_mod_requester *req,
    4895                 :            :                     struct rule *old_rule, struct rule *new_rule,
    4896                 :            :                     struct ovs_list *dead_cookies)
    4897                 :            :     OVS_REQUIRES(ofproto_mutex)
    4898                 :            : {
    4899                 :      31430 :     bool forward_counts = !(new_rule->flags & OFPUTIL_FF_RESET_COUNTS);
    4900                 :            :     struct rule *replaced_rule;
    4901                 :            : 
    4902         [ +  + ]:       1008 :     replaced_rule = (old_rule && old_rule->removed_reason != OFPRR_EVICTION)
    4903         [ +  + ]:      32438 :         ? old_rule : NULL;
    4904                 :            : 
    4905                 :            :     /* Insert the new flow to the ofproto provider.  A non-NULL 'replaced_rule'
    4906                 :            :      * is a duplicate rule the 'new_rule' is replacing.  The provider should
    4907                 :            :      * link the packet and byte counts from the old rule to the new one if
    4908                 :            :      * 'forward_counts' is 'true'.  The 'replaced_rule' will be deleted right
    4909                 :            :      * after this call. */
    4910                 :      31430 :     ofproto->ofproto_class->rule_insert(new_rule, replaced_rule,
    4911                 :            :                                         forward_counts);
    4912                 :      31430 :     learned_cookies_inc(ofproto, rule_get_actions(new_rule));
    4913                 :            : 
    4914         [ +  + ]:      31430 :     if (old_rule) {
    4915                 :       1008 :         const struct rule_actions *old_actions = rule_get_actions(old_rule);
    4916                 :       1008 :         const struct rule_actions *new_actions = rule_get_actions(new_rule);
    4917                 :            : 
    4918                 :       1008 :         learned_cookies_dec(ofproto, old_actions, dead_cookies);
    4919                 :            : 
    4920         [ +  + ]:       1008 :         if (replaced_rule) {
    4921         [ +  + ]:        995 :             enum nx_flow_update_event event = ofm->command == OFPFC_ADD
    4922                 :            :                 ? NXFME_ADDED : NXFME_MODIFIED;
    4923                 :            : 
    4924                 :       1990 :             bool changed_cookie = (new_rule->flow_cookie
    4925                 :        995 :                                    != old_rule->flow_cookie);
    4926                 :            : 
    4927                 :        995 :             bool changed_actions = !ofpacts_equal(new_actions->ofpacts,
    4928                 :        995 :                                                   new_actions->ofpacts_len,
    4929                 :        995 :                                                   old_actions->ofpacts,
    4930                 :       1990 :                                                   old_actions->ofpacts_len);
    4931                 :            : 
    4932 [ +  + ][ +  + ]:        995 :             if (event != NXFME_MODIFIED || changed_actions
    4933         [ +  + ]:          9 :                 || changed_cookie) {
    4934 [ +  + ][ +  + ]:        995 :                 ofmonitor_report(ofproto->connmgr, new_rule, event, 0,
                 [ +  + ]
    4935                 :            :                                  req ? req->ofconn : NULL,
    4936                 :        479 :                                  req ? req->request->xid : 0,
    4937                 :            :                                  changed_actions ? old_actions : NULL);
    4938                 :            :             }
    4939                 :            :         } else {
    4940                 :            :             /* XXX: This is slight duplication with delete_flows_finish__() */
    4941 [ +  - ][ +  - ]:         13 :             ofmonitor_report(ofproto->connmgr, old_rule, NXFME_DELETED,
    4942                 :            :                              OFPRR_EVICTION,
    4943                 :            :                              req ? req->ofconn : NULL,
    4944                 :         13 :                              req ? req->request->xid : 0, NULL);
    4945                 :            :         }
    4946                 :            :     }
    4947                 :      31430 : }
    4948                 :            : 
    4949                 :            : static enum ofperr
    4950                 :        546 : modify_flows_start__(struct ofproto *ofproto, struct ofproto_flow_mod *ofm)
    4951                 :            :     OVS_REQUIRES(ofproto_mutex)
    4952                 :            : {
    4953                 :        546 :     struct rule_collection *old_rules = &ofm->old_rules;
    4954                 :        546 :     struct rule_collection *new_rules = &ofm->new_rules;
    4955                 :            :     enum ofperr error;
    4956                 :            : 
    4957         [ +  + ]:        546 :     if (rule_collection_n(old_rules) > 0) {
    4958                 :            :         /* Create a new 'modified' rule for each old rule. */
    4959                 :            :         struct rule *old_rule, *new_rule;
    4960                 :        368 :         const struct rule_actions *actions = rule_get_actions(ofm->temp_rule);
    4961                 :            : 
    4962                 :            :         /* Must check actions while holding ofproto_mutex to avoid a race. */
    4963                 :        368 :         error = ofproto_check_ofpacts(ofproto, actions->ofpacts,
    4964                 :        368 :                                       actions->ofpacts_len);
    4965         [ -  + ]:        368 :         if (error) {
    4966                 :          0 :             return error;
    4967                 :            :         }
    4968                 :            : 
    4969                 :            :         /* Use the temp rule as the first new rule, and as the template for
    4970                 :            :          * the rest. */
    4971                 :        368 :         struct rule *temp = ofm->temp_rule;
    4972                 :        368 :         ofm->temp_rule = NULL;   /* We consume the template. */
    4973                 :            : 
    4974                 :        368 :         bool first = true;
    4975 [ +  + ][ +  - ]:        746 :         RULE_COLLECTION_FOR_EACH (old_rule, old_rules) {
    4976         [ +  + ]:        378 :             if (first) {
    4977                 :            :                 /* The template rule's match is possibly a loose one, so it
    4978                 :            :                  * must be replaced with the old rule's match so that the new
    4979                 :            :                  * rule actually replaces the old one. */
    4980                 :        368 :                 cls_rule_destroy(CONST_CAST(struct cls_rule *, &temp->cr));
    4981                 :        368 :                 cls_rule_clone(CONST_CAST(struct cls_rule *, &temp->cr),
    4982                 :            :                                &old_rule->cr);
    4983                 :        368 :                 *CONST_CAST(uint8_t *, &temp->table_id) = old_rule->table_id;
    4984                 :        368 :                 rule_collection_add(new_rules, temp);
    4985                 :        368 :                 first = false;
    4986                 :            :             } else {
    4987                 :            :                 struct cls_rule cr;
    4988                 :         10 :                 cls_rule_clone(&cr, &old_rule->cr);
    4989                 :         10 :                 error = ofproto_rule_create(ofproto, &cr, old_rule->table_id,
    4990                 :            :                                             temp->flow_cookie,
    4991                 :         10 :                                             temp->idle_timeout,
    4992                 :         10 :                                             temp->hard_timeout, temp->flags,
    4993                 :         10 :                                             temp->importance,
    4994                 :         10 :                                             temp->actions->ofpacts,
    4995                 :         10 :                                             temp->actions->ofpacts_len,
    4996                 :            :                                             &new_rule);
    4997         [ +  - ]:         10 :                 if (!error) {
    4998                 :         10 :                     rule_collection_add(new_rules, new_rule);
    4999                 :            :                 } else {
    5000                 :          0 :                     rule_collection_unref(new_rules);
    5001                 :          0 :                     rule_collection_destroy(new_rules);
    5002                 :          0 :                     return error;
    5003                 :            :                 }
    5004                 :            :             }
    5005                 :            :         }
    5006         [ -  + ]:        368 :         ovs_assert(rule_collection_n(new_rules)
    5007                 :            :                    == rule_collection_n(old_rules));
    5008                 :            : 
    5009 [ +  + ][ +  + ]:        746 :         RULE_COLLECTIONS_FOR_EACH (old_rule, new_rule, old_rules, new_rules) {
    5010                 :        378 :             replace_rule_start(ofproto, ofm, old_rule, new_rule);
    5011                 :            :         }
    5012         [ +  + ]:        178 :     } else if (ofm->modify_may_add_flow) {
    5013                 :            :         /* No match, add a new flow, consumes 'temp'. */
    5014                 :        173 :         error = add_flow_start(ofproto, ofm);
    5015                 :        173 :         new_rules->collection.n = 1;
    5016                 :            :     } else {
    5017                 :          5 :         error = 0;
    5018                 :            :     }
    5019                 :            : 
    5020                 :        546 :     return error;
    5021                 :            : }
    5022                 :            : 
    5023                 :            : static enum ofperr
    5024                 :         39 : modify_flows_init_loose(struct ofproto *ofproto,
    5025                 :            :                         struct ofproto_flow_mod *ofm,
    5026                 :            :                         const struct ofputil_flow_mod *fm)
    5027                 :            :     OVS_EXCLUDED(ofproto_mutex)
    5028                 :            : {
    5029                 :         39 :     rule_criteria_init(&ofm->criteria, fm->table_id, &fm->match, 0,
    5030                 :            :                        OVS_VERSION_MAX, fm->cookie, fm->cookie_mask, OFPP_ANY,
    5031                 :            :                        OFPG_ANY);
    5032                 :         39 :     rule_criteria_require_rw(&ofm->criteria,
    5033                 :         39 :                              (fm->flags & OFPUTIL_FF_NO_READONLY) != 0);
    5034                 :            :     /* Must create a new flow in advance for the case that no matches are
    5035                 :            :      * found.  Also used for template for multiple modified flows. */
    5036                 :         39 :     add_flow_init(ofproto, ofm, fm);
    5037                 :            : 
    5038                 :         39 :     return 0;
    5039                 :            : }
    5040                 :            : 
    5041                 :            : /* Implements OFPFC_MODIFY.  Returns 0 on success or an OpenFlow error code on
    5042                 :            :  * failure. */
    5043                 :            : static enum ofperr
    5044                 :         37 : modify_flows_start_loose(struct ofproto *ofproto, struct ofproto_flow_mod *ofm)
    5045                 :            :     OVS_REQUIRES(ofproto_mutex)
    5046                 :            : {
    5047                 :         37 :     struct rule_collection *old_rules = &ofm->old_rules;
    5048                 :            :     enum ofperr error;
    5049                 :            : 
    5050                 :         37 :     error = collect_rules_loose(ofproto, &ofm->criteria, old_rules);
    5051                 :            : 
    5052         [ +  - ]:         37 :     if (!error) {
    5053                 :         37 :         error = modify_flows_start__(ofproto, ofm);
    5054                 :            :     }
    5055                 :            : 
    5056         [ +  + ]:         37 :     if (error) {
    5057                 :          2 :         rule_collection_destroy(old_rules);
    5058                 :            :     }
    5059                 :            : 
    5060                 :         37 :     return error;
    5061                 :            : }
    5062                 :            : 
    5063                 :            : static void
    5064                 :          0 : modify_flows_revert(struct ofproto *ofproto, struct ofproto_flow_mod *ofm)
    5065                 :            :     OVS_REQUIRES(ofproto_mutex)
    5066                 :            : {
    5067                 :          0 :     struct rule_collection *old_rules = &ofm->old_rules;
    5068                 :          0 :     struct rule_collection *new_rules = &ofm->new_rules;
    5069                 :            : 
    5070                 :            :     /* Old rules were not changed yet, only need to revert new rules. */
    5071         [ #  # ]:          0 :     if (rule_collection_n(old_rules) > 0) {
    5072                 :            :         struct rule *old_rule, *new_rule;
    5073 [ #  # ][ #  # ]:          0 :         RULE_COLLECTIONS_FOR_EACH (old_rule, new_rule, old_rules, new_rules) {
    5074                 :          0 :             replace_rule_revert(ofproto, old_rule, new_rule);
    5075                 :            :         }
    5076                 :          0 :         rule_collection_destroy(new_rules);
    5077                 :          0 :         rule_collection_destroy(old_rules);
    5078                 :            :     }
    5079                 :          0 : }
    5080                 :            : 
    5081                 :            : static void
    5082                 :        544 : modify_flows_finish(struct ofproto *ofproto, struct ofproto_flow_mod *ofm,
    5083                 :            :                     const struct openflow_mod_requester *req)
    5084                 :            :     OVS_REQUIRES(ofproto_mutex)
    5085                 :            : {
    5086                 :        544 :     struct rule_collection *old_rules = &ofm->old_rules;
    5087                 :        544 :     struct rule_collection *new_rules = &ofm->new_rules;
    5088                 :            : 
    5089         [ +  + ]:        544 :     if (rule_collection_n(old_rules) == 0
    5090         [ +  + ]:        175 :         && rule_collection_n(new_rules) == 1) {
    5091                 :        170 :         add_flow_finish(ofproto, ofm, req);
    5092         [ +  + ]:        374 :     } else if (rule_collection_n(old_rules) > 0) {
    5093                 :        369 :         struct ovs_list dead_cookies = OVS_LIST_INITIALIZER(&dead_cookies);
    5094                 :            : 
    5095         [ -  + ]:        369 :         ovs_assert(rule_collection_n(new_rules)
    5096                 :            :                    == rule_collection_n(old_rules));
    5097                 :            : 
    5098                 :            :         struct rule *old_rule, *new_rule;
    5099 [ +  + ][ +  + ]:        748 :         RULE_COLLECTIONS_FOR_EACH (old_rule, new_rule, old_rules, new_rules) {
    5100                 :        379 :             replace_rule_finish(ofproto, ofm, req, old_rule, new_rule,
    5101                 :            :                                 &dead_cookies);
    5102                 :            :         }
    5103                 :        369 :         learned_cookies_flush(ofproto, &dead_cookies);
    5104                 :        369 :         remove_rules_postponed(old_rules);
    5105                 :        369 :         rule_collection_destroy(new_rules);
    5106                 :            :     }
    5107                 :        544 : }
    5108                 :            : 
    5109                 :            : static enum ofperr
    5110                 :        509 : modify_flow_init_strict(struct ofproto *ofproto OVS_UNUSED,
    5111                 :            :                         struct ofproto_flow_mod *ofm,
    5112                 :            :                         const struct ofputil_flow_mod *fm)
    5113                 :            :     OVS_EXCLUDED(ofproto_mutex)
    5114                 :            : {
    5115                 :        509 :     rule_criteria_init(&ofm->criteria, fm->table_id, &fm->match, fm->priority,
    5116                 :            :                        OVS_VERSION_MAX, fm->cookie, fm->cookie_mask, OFPP_ANY,
    5117                 :            :                        OFPG_ANY);
    5118                 :        509 :     rule_criteria_require_rw(&ofm->criteria,
    5119                 :        509 :                              (fm->flags & OFPUTIL_FF_NO_READONLY) != 0);
    5120                 :            :     /* Must create a new flow in advance for the case that no matches are
    5121                 :            :      * found.  Also used for template for multiple modified flows. */
    5122                 :        509 :     add_flow_init(ofproto, ofm, fm);
    5123                 :            : 
    5124                 :        509 :     return 0;
    5125                 :            : }
    5126                 :            : 
    5127                 :            : /* Implements OFPFC_MODIFY_STRICT.  Returns 0 on success or an OpenFlow error
    5128                 :            :  * code on failure. */
    5129                 :            : static enum ofperr
    5130                 :        509 : modify_flow_start_strict(struct ofproto *ofproto, struct ofproto_flow_mod *ofm)
    5131                 :            :     OVS_REQUIRES(ofproto_mutex)
    5132                 :            : {
    5133                 :        509 :     struct rule_collection *old_rules = &ofm->old_rules;
    5134                 :            :     enum ofperr error;
    5135                 :            : 
    5136                 :        509 :     error = collect_rules_strict(ofproto, &ofm->criteria, old_rules);
    5137                 :            : 
    5138         [ +  - ]:        509 :     if (!error) {
    5139                 :            :         /* collect_rules_strict() can return max 1 rule. */
    5140                 :        509 :         error = modify_flows_start__(ofproto, ofm);
    5141                 :            :     }
    5142                 :            : 
    5143                 :        509 :     return error;
    5144                 :            : }
    5145                 :            : 
    5146                 :            : /* OFPFC_DELETE implementation. */
    5147                 :            : 
    5148                 :            : static void
    5149                 :       8953 : delete_flows_start__(struct ofproto *ofproto, ovs_version_t version,
    5150                 :            :                      const struct rule_collection *rules)
    5151                 :            :     OVS_REQUIRES(ofproto_mutex)
    5152                 :            : {
    5153                 :            :     struct rule *rule;
    5154                 :            : 
    5155 [ +  + ][ +  - ]:      35099 :     RULE_COLLECTION_FOR_EACH (rule, rules) {
    5156                 :      26146 :         struct oftable *table = &ofproto->tables[rule->table_id];
    5157                 :            : 
    5158                 :      26146 :         table->n_flows--;
    5159                 :      26146 :         cls_rule_make_invisible_in_version(&rule->cr, version);
    5160                 :            : 
    5161                 :            :         /* Remove rule from ofproto data structures. */
    5162                 :      26146 :         ofproto_rule_remove__(ofproto, rule);
    5163                 :            :     }
    5164                 :       8953 : }
    5165                 :            : 
    5166                 :            : static void
    5167                 :          0 : delete_flows_revert__(struct ofproto *ofproto,
    5168                 :            :                       const struct rule_collection *rules)
    5169                 :            :     OVS_REQUIRES(ofproto_mutex)
    5170                 :            : {
    5171                 :            :     struct rule *rule;
    5172                 :            : 
    5173 [ #  # ][ #  # ]:          0 :     RULE_COLLECTION_FOR_EACH (rule, rules) {
    5174                 :          0 :         struct oftable *table = &ofproto->tables[rule->table_id];
    5175                 :            : 
    5176                 :            :         /* Add rule back to ofproto data structures. */
    5177                 :          0 :         ofproto_rule_insert__(ofproto, rule);
    5178                 :            : 
    5179                 :            :         /* Restore table's rule count. */
    5180                 :          0 :         table->n_flows++;
    5181                 :            : 
    5182                 :            :         /* Restore the original visibility of the rule. */
    5183                 :          0 :         cls_rule_restore_visibility(&rule->cr);
    5184                 :            :     }
    5185                 :          0 : }
    5186                 :            : 
    5187                 :            : static void
    5188                 :       8984 : delete_flows_finish__(struct ofproto *ofproto,
    5189                 :            :                       struct rule_collection *rules,
    5190                 :            :                       enum ofp_flow_removed_reason reason,
    5191                 :            :                       const struct openflow_mod_requester *req)
    5192                 :            :     OVS_REQUIRES(ofproto_mutex)
    5193                 :            : {
    5194         [ +  + ]:       8984 :     if (rule_collection_n(rules)) {
    5195                 :       8035 :         struct ovs_list dead_cookies = OVS_LIST_INITIALIZER(&dead_cookies);
    5196                 :            :         struct rule *rule;
    5197                 :            : 
    5198 [ +  + ][ +  - ]:      34181 :         RULE_COLLECTION_FOR_EACH (rule, rules) {
    5199                 :            :             /* This value will be used to send the flow removed message right
    5200                 :            :              * before the rule is actually destroyed. */
    5201                 :      26146 :             rule->removed_reason = reason;
    5202                 :            : 
    5203 [ +  + ][ +  + ]:      26146 :             ofmonitor_report(ofproto->connmgr, rule, NXFME_DELETED, reason,
    5204                 :            :                              req ? req->ofconn : NULL,
    5205                 :      13352 :                              req ? req->request->xid : 0, NULL);
    5206                 :            : 
    5207                 :            :             /* Send Vacancy Event for OF1.4+. */
    5208                 :      26146 :             send_table_status(ofproto, rule->table_id);
    5209                 :            : 
    5210                 :      26146 :             learned_cookies_dec(ofproto, rule_get_actions(rule),
    5211                 :            :                                 &dead_cookies);
    5212                 :            :         }
    5213                 :       8035 :         remove_rules_postponed(rules);
    5214                 :            : 
    5215                 :       8035 :         learned_cookies_flush(ofproto, &dead_cookies);
    5216                 :            :     }
    5217                 :       8984 : }
    5218                 :            : 
    5219                 :            : /* Deletes the rules listed in 'rules'.
    5220                 :            :  * The deleted rules will become invisible to the lookups in the next version.
    5221                 :            :  * Destroys 'rules'. */
    5222                 :            : static void
    5223                 :    1421142 : delete_flows__(struct rule_collection *rules,
    5224                 :            :                enum ofp_flow_removed_reason reason,
    5225                 :            :                const struct openflow_mod_requester *req)
    5226                 :            :     OVS_REQUIRES(ofproto_mutex)
    5227                 :            : {
    5228         [ +  + ]:    1421142 :     if (rule_collection_n(rules)) {
    5229                 :       1973 :         struct ofproto *ofproto = rule_collection_rules(rules)[0]->ofproto;
    5230                 :            : 
    5231                 :       1973 :         delete_flows_start__(ofproto, ofproto->tables_version + 1, rules);
    5232                 :       1973 :         ofproto_bump_tables_version(ofproto);
    5233                 :       1973 :         delete_flows_finish__(ofproto, rules, reason, req);
    5234                 :       1973 :         ofmonitor_flush(ofproto->connmgr);
    5235                 :            :     }
    5236                 :    1421142 : }
    5237                 :            : 
    5238                 :            : static enum ofperr
    5239                 :        730 : delete_flows_init_loose(struct ofproto *ofproto OVS_UNUSED,
    5240                 :            :                         struct ofproto_flow_mod *ofm,
    5241                 :            :                         const struct ofputil_flow_mod *fm)
    5242                 :            :     OVS_EXCLUDED(ofproto_mutex)
    5243                 :            : {
    5244                 :        730 :     rule_criteria_init(&ofm->criteria, fm->table_id, &fm->match, 0,
    5245                 :            :                        OVS_VERSION_MAX, fm->cookie, fm->cookie_mask,
    5246                 :            :                        fm->out_port, fm->out_group);
    5247                 :        730 :     rule_criteria_require_rw(&ofm->criteria,
    5248                 :        730 :                              (fm->flags & OFPUTIL_FF_NO_READONLY) != 0);
    5249                 :        730 :     return 0;
    5250                 :            : }
    5251                 :            : 
    5252                 :            : /* Implements OFPFC_DELETE. */
    5253                 :            : static enum ofperr
    5254                 :        726 : delete_flows_start_loose(struct ofproto *ofproto, struct ofproto_flow_mod *ofm)
    5255                 :            :     OVS_REQUIRES(ofproto_mutex)
    5256                 :            : {
    5257                 :        726 :     struct rule_collection *rules = &ofm->old_rules;
    5258                 :            :     enum ofperr error;
    5259                 :            : 
    5260                 :        726 :     error = collect_rules_loose(ofproto, &ofm->criteria, rules);
    5261                 :            : 
    5262         [ +  - ]:        726 :     if (!error) {
    5263                 :        726 :         delete_flows_start__(ofproto, ofm->version, rules);
    5264                 :            :     }
    5265                 :            : 
    5266                 :        726 :     return error;
    5267                 :            : }
    5268                 :            : 
    5269                 :            : static void
    5270                 :          0 : delete_flows_revert(struct ofproto *ofproto, struct ofproto_flow_mod *ofm)
    5271                 :            :     OVS_REQUIRES(ofproto_mutex)
    5272                 :            : {
    5273                 :          0 :     delete_flows_revert__(ofproto, &ofm->old_rules);
    5274                 :          0 : }
    5275                 :            : 
    5276                 :            : static void
    5277                 :       6913 : delete_flows_finish(struct ofproto *ofproto,
    5278                 :            :                     struct ofproto_flow_mod *ofm,
    5279                 :            :                     const struct openflow_mod_requester *req)
    5280                 :            :     OVS_REQUIRES(ofproto_mutex)
    5281                 :            : {
    5282                 :       6913 :     delete_flows_finish__(ofproto, &ofm->old_rules, OFPRR_DELETE, req);
    5283                 :       6913 : }
    5284                 :            : 
    5285                 :            : static enum ofperr
    5286                 :       6187 : delete_flows_init_strict(struct ofproto *ofproto OVS_UNUSED,
    5287                 :            :                          struct ofproto_flow_mod *ofm,
    5288                 :            :                          const struct ofputil_flow_mod *fm)
    5289                 :            :     OVS_EXCLUDED(ofproto_mutex)
    5290                 :            : {
    5291                 :       6187 :     rule_criteria_init(&ofm->criteria, fm->table_id, &fm->match, fm->priority,
    5292                 :            :                        OVS_VERSION_MAX, fm->cookie, fm->cookie_mask,
    5293                 :            :                        fm->out_port, fm->out_group);
    5294                 :       6187 :     rule_criteria_require_rw(&ofm->criteria,
    5295                 :       6187 :                              (fm->flags & OFPUTIL_FF_NO_READONLY) != 0);
    5296                 :       6187 :     return 0;
    5297                 :            : }
    5298                 :            : 
    5299                 :            : /* Implements OFPFC_DELETE_STRICT. */
    5300                 :            : static enum ofperr
    5301                 :       6187 : delete_flow_start_strict(struct ofproto *ofproto,
    5302                 :            :                          struct ofproto_flow_mod *ofm)
    5303                 :            :     OVS_REQUIRES(ofproto_mutex)
    5304                 :            : {
    5305                 :       6187 :     struct rule_collection *rules = &ofm->old_rules;
    5306                 :            :     enum ofperr error;
    5307                 :            : 
    5308                 :       6187 :     error = collect_rules_strict(ofproto, &ofm->criteria, rules);
    5309                 :            : 
    5310         [ +  - ]:       6187 :     if (!error) {
    5311                 :       6187 :         delete_flows_start__(ofproto, ofm->version, rules);
    5312                 :            :     }
    5313                 :            : 
    5314                 :       6187 :     return error;
    5315                 :            : }
    5316                 :            : 
    5317                 :            : /* This may only be called by rule_destroy_cb()! */
    5318                 :            : static void
    5319                 :         38 : ofproto_rule_send_removed(struct rule *rule)
    5320                 :            :     OVS_EXCLUDED(ofproto_mutex)
    5321                 :            : {
    5322                 :            :     struct ofputil_flow_removed fr;
    5323                 :            :     long long int used;
    5324                 :            : 
    5325                 :         38 :     minimatch_expand(&rule->cr.match, &fr.match);
    5326                 :         38 :     fr.priority = rule->cr.priority;
    5327                 :            : 
    5328                 :         38 :     ovs_mutex_lock(&ofproto_mutex);
    5329                 :         38 :     fr.cookie = rule->flow_cookie;
    5330                 :         38 :     fr.reason = rule->removed_reason;
    5331                 :         38 :     fr.table_id = rule->table_id;
    5332                 :         38 :     calc_duration(rule->created, time_msec(),
    5333                 :            :                   &fr.duration_sec, &fr.duration_nsec);
    5334                 :         38 :     ovs_mutex_lock(&rule->mutex);
    5335                 :         38 :     fr.idle_timeout = rule->idle_timeout;
    5336                 :         38 :     fr.hard_timeout = rule->hard_timeout;
    5337                 :         38 :     ovs_mutex_unlock(&rule->mutex);
    5338                 :         38 :     rule->ofproto->ofproto_class->rule_get_stats(rule, &fr.packet_count,
    5339                 :            :                                                  &fr.byte_count, &used);
    5340                 :         38 :     connmgr_send_flow_removed(rule->ofproto->connmgr, &fr);
    5341                 :         38 :     ovs_mutex_unlock(&ofproto_mutex);
    5342                 :         38 : }
    5343                 :            : 
    5344                 :            : /* Sends an OpenFlow "flow removed" message with the given 'reason' (either
    5345                 :            :  * OFPRR_HARD_TIMEOUT or OFPRR_IDLE_TIMEOUT), and then removes 'rule' from its
    5346                 :            :  * ofproto.
    5347                 :            :  *
    5348                 :            :  * ofproto implementation ->run() functions should use this function to expire
    5349                 :            :  * OpenFlow flows. */
    5350                 :            : void
    5351                 :          5 : ofproto_rule_expire(struct rule *rule, uint8_t reason)
    5352                 :            :     OVS_REQUIRES(ofproto_mutex)
    5353                 :            : {
    5354                 :            :     struct rule_collection rules;
    5355                 :            : 
    5356                 :          5 :     rule_collection_init(&rules);
    5357                 :          5 :     rule_collection_add(&rules, rule);
    5358                 :          5 :     delete_flows__(&rules, reason, NULL);
    5359                 :          5 : }
    5360                 :            : 
    5361                 :            : /* Reduces '*timeout' to no more than 'max'.  A value of zero in either case
    5362                 :            :  * means "infinite". */
    5363                 :            : static void
    5364                 :          2 : reduce_timeout(uint16_t max, uint16_t *timeout)
    5365                 :            : {
    5366 [ +  + ][ +  - ]:          2 :     if (max && (!*timeout || *timeout > max)) {
                 [ +  - ]
    5367                 :          1 :         *timeout = max;
    5368                 :            :     }
    5369                 :          2 : }
    5370                 :            : 
    5371                 :            : /* If 'idle_timeout' is nonzero, and 'rule' has no idle timeout or an idle
    5372                 :            :  * timeout greater than 'idle_timeout', lowers 'rule''s idle timeout to
    5373                 :            :  * 'idle_timeout' seconds.  Similarly for 'hard_timeout'.
    5374                 :            :  *
    5375                 :            :  * Suitable for implementing OFPACT_FIN_TIMEOUT. */
    5376                 :            : void
    5377                 :          1 : ofproto_rule_reduce_timeouts(struct rule *rule,
    5378                 :            :                              uint16_t idle_timeout, uint16_t hard_timeout)
    5379                 :            :     OVS_EXCLUDED(ofproto_mutex, rule->mutex)
    5380                 :            : {
    5381 [ -  + ][ #  # ]:          1 :     if (!idle_timeout && !hard_timeout) {
    5382                 :          0 :         return;
    5383                 :            :     }
    5384                 :            : 
    5385                 :          1 :     ovs_mutex_lock(&ofproto_mutex);
    5386         [ -  + ]:          1 :     if (ovs_list_is_empty(&rule->expirable)) {
    5387                 :          0 :         ovs_list_insert(&rule->ofproto->expirable, &rule->expirable);
    5388                 :            :     }
    5389                 :          1 :     ovs_mutex_unlock(&ofproto_mutex);
    5390                 :            : 
    5391                 :          1 :     ovs_mutex_lock(&rule->mutex);
    5392                 :          1 :     reduce_timeout(idle_timeout, &rule->idle_timeout);
    5393                 :          1 :     reduce_timeout(hard_timeout, &rule->hard_timeout);
    5394                 :          1 :     ovs_mutex_unlock(&rule->mutex);
    5395                 :            : }
    5396                 :            : 
    5397                 :            : static enum ofperr
    5398                 :      32791 : handle_flow_mod(struct ofconn *ofconn, const struct ofp_header *oh)
    5399                 :            :     OVS_EXCLUDED(ofproto_mutex)
    5400                 :            : {
    5401                 :      32791 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
    5402                 :            :     struct ofputil_flow_mod fm;
    5403                 :            :     uint64_t ofpacts_stub[1024 / 8];
    5404                 :            :     struct ofpbuf ofpacts;
    5405                 :            :     enum ofperr error;
    5406                 :            : 
    5407                 :      32791 :     error = reject_slave_controller(ofconn);
    5408         [ -  + ]:      32791 :     if (error) {
    5409                 :          0 :         return error;
    5410                 :            :     }
    5411                 :            : 
    5412                 :      32791 :     ofpbuf_use_stub(&ofpacts, ofpacts_stub, sizeof ofpacts_stub);
    5413                 :      32791 :     error = ofputil_decode_flow_mod(&fm, oh, ofconn_get_protocol(ofconn),
    5414                 :            :                                     &ofpacts,
    5415                 :      32791 :                                     u16_to_ofp(ofproto->max_ports),
    5416                 :      32791 :                                     ofproto->n_tables);
    5417         [ +  - ]:      32791 :     if (!error) {
    5418                 :      32791 :         struct openflow_mod_requester req = { ofconn, oh };
    5419                 :      32791 :         error = handle_flow_mod__(ofproto, &fm, &req);
    5420                 :            :     }
    5421                 :            : 
    5422                 :      32791 :     ofpbuf_uninit(&ofpacts);
    5423                 :      32791 :     return error;
    5424                 :            : }
    5425                 :            : 
    5426                 :            : static enum ofperr
    5427                 :      38260 : handle_flow_mod__(struct ofproto *ofproto, const struct ofputil_flow_mod *fm,
    5428                 :            :                   const struct openflow_mod_requester *req)
    5429                 :            :     OVS_EXCLUDED(ofproto_mutex)
    5430                 :            : {
    5431                 :            :     struct ofproto_flow_mod ofm;
    5432                 :            :     enum ofperr error;
    5433                 :            : 
    5434                 :      38260 :     error = ofproto_flow_mod_init(ofproto, &ofm, fm);
    5435         [ +  + ]:      38260 :     if (error) {
    5436                 :        558 :         return error;
    5437                 :            :     }
    5438                 :            : 
    5439                 :      37702 :     ovs_mutex_lock(&ofproto_mutex);
    5440                 :      37702 :     ofm.version = ofproto->tables_version + 1;
    5441                 :      37702 :     error = ofproto_flow_mod_start(ofproto, &ofm);
    5442         [ +  + ]:      37702 :     if (!error) {
    5443                 :      37694 :         ofproto_bump_tables_version(ofproto);
    5444                 :      37694 :         ofproto_flow_mod_finish(ofproto, &ofm, req);
    5445                 :            :     }
    5446                 :      37702 :     ofmonitor_flush(ofproto->connmgr);
    5447                 :      37702 :     ovs_mutex_unlock(&ofproto_mutex);
    5448                 :            : 
    5449                 :      38260 :     return error;
    5450                 :            : }
    5451                 :            : 
    5452                 :            : static enum ofperr
    5453                 :         24 : handle_role_request(struct ofconn *ofconn, const struct ofp_header *oh)
    5454                 :            : {
    5455                 :            :     struct ofputil_role_request request;
    5456                 :            :     struct ofputil_role_request reply;
    5457                 :            :     struct ofpbuf *buf;
    5458                 :            :     enum ofperr error;
    5459                 :            : 
    5460                 :         24 :     error = ofputil_decode_role_message(oh, &request);
    5461         [ -  + ]:         24 :     if (error) {
    5462                 :          0 :         return error;
    5463                 :            :     }
    5464                 :            : 
    5465         [ +  + ]:         24 :     if (request.role != OFPCR12_ROLE_NOCHANGE) {
    5466         [ +  - ]:         20 :         if (request.role != OFPCR12_ROLE_EQUAL
    5467         [ +  + ]:         20 :             && request.have_generation_id
    5468         [ +  + ]:         18 :             && !ofconn_set_master_election_id(ofconn, request.generation_id)) {
    5469                 :          2 :                 return OFPERR_OFPRRFC_STALE;
    5470                 :            :         }
    5471                 :            : 
    5472                 :         18 :         ofconn_set_role(ofconn, request.role);
    5473                 :            :     }
    5474                 :            : 
    5475                 :         22 :     reply.role = ofconn_get_role(ofconn);
    5476                 :         22 :     reply.have_generation_id = ofconn_get_master_election_id(
    5477                 :            :         ofconn, &reply.generation_id);
    5478                 :         22 :     buf = ofputil_encode_role_reply(oh, &reply);
    5479                 :         22 :     ofconn_send_reply(ofconn, buf);
    5480                 :            : 
    5481                 :         24 :     return 0;
    5482                 :            : }
    5483                 :            : 
    5484                 :            : static enum ofperr
    5485                 :         99 : handle_nxt_flow_mod_table_id(struct ofconn *ofconn,
    5486                 :            :                              const struct ofp_header *oh)
    5487                 :            : {
    5488                 :         99 :     const struct nx_flow_mod_table_id *msg = ofpmsg_body(oh);
    5489                 :            :     enum ofputil_protocol cur, next;
    5490                 :            : 
    5491                 :         99 :     cur = ofconn_get_protocol(ofconn);
    5492                 :         99 :     next = ofputil_protocol_set_tid(cur, msg->set != 0);
    5493                 :         99 :     ofconn_set_protocol(ofconn, next);
    5494                 :            : 
    5495                 :         99 :     return 0;
    5496                 :            : }
    5497                 :            : 
    5498                 :            : static enum ofperr
    5499                 :        347 : handle_nxt_set_flow_format(struct ofconn *ofconn, const struct ofp_header *oh)
    5500                 :            : {
    5501                 :        347 :     const struct nx_set_flow_format *msg = ofpmsg_body(oh);
    5502                 :            :     enum ofputil_protocol cur, next;
    5503                 :            :     enum ofputil_protocol next_base;
    5504                 :            : 
    5505                 :        347 :     next_base = ofputil_nx_flow_format_to_protocol(ntohl(msg->format));
    5506         [ -  + ]:        347 :     if (!next_base) {
    5507                 :          0 :         return OFPERR_OFPBRC_EPERM;
    5508                 :            :     }
    5509                 :            : 
    5510                 :        347 :     cur = ofconn_get_protocol(ofconn);
    5511                 :        347 :     next = ofputil_protocol_set_base(cur, next_base);
    5512                 :        347 :     ofconn_set_protocol(ofconn, next);
    5513                 :            : 
    5514                 :        347 :     return 0;
    5515                 :            : }
    5516                 :            : 
    5517                 :            : static enum ofperr
    5518                 :        211 : handle_nxt_set_packet_in_format(struct ofconn *ofconn,
    5519                 :            :                                 const struct ofp_header *oh)
    5520                 :            : {
    5521                 :        211 :     const struct nx_set_packet_in_format *msg = ofpmsg_body(oh);
    5522                 :            :     uint32_t format;
    5523                 :            : 
    5524                 :        211 :     format = ntohl(msg->format);
    5525         [ -  + ]:        211 :     if (!ofputil_packet_in_format_is_valid(format)) {
    5526                 :          0 :         return OFPERR_OFPBRC_EPERM;
    5527                 :            :     }
    5528                 :            : 
    5529                 :        211 :     ofconn_set_packet_in_format(ofconn, format);
    5530                 :        211 :     return 0;
    5531                 :            : }
    5532                 :            : 
    5533                 :            : static enum ofperr
    5534                 :          8 : handle_nxt_set_async_config(struct ofconn *ofconn, const struct ofp_header *oh)
    5535                 :            : {
    5536                 :          8 :     struct ofputil_async_cfg basis = ofconn_get_async_config(ofconn);
    5537                 :            :     struct ofputil_async_cfg ac;
    5538                 :            :     enum ofperr error;
    5539                 :            : 
    5540                 :          8 :     error = ofputil_decode_set_async_config(oh, false, &basis, &ac);
    5541         [ -  + ]:          8 :     if (error) {
    5542                 :          0 :         return error;
    5543                 :            :     }
    5544                 :            : 
    5545                 :          8 :     ofconn_set_async_config(ofconn, &ac);
    5546   [ +  -  +  + ]:         16 :     if (ofconn_get_type(ofconn) == OFCONN_SERVICE &&
    5547                 :          8 :         !ofconn_get_miss_send_len(ofconn)) {
    5548                 :          3 :         ofconn_set_miss_send_len(ofconn, OFP_DEFAULT_MISS_SEND_LEN);
    5549                 :            :     }
    5550                 :            : 
    5551                 :          8 :     return 0;
    5552                 :            : }
    5553                 :            : 
    5554                 :            : static enum ofperr
    5555                 :          1 : handle_nxt_get_async_request(struct ofconn *ofconn, const struct ofp_header *oh)
    5556                 :            : {
    5557                 :          1 :     struct ofputil_async_cfg ac = ofconn_get_async_config(ofconn);
    5558                 :          1 :     ofconn_send_reply(ofconn, ofputil_encode_get_async_reply(oh, &ac));
    5559                 :            : 
    5560                 :          1 :     return 0;
    5561                 :            : }
    5562                 :            : 
    5563                 :            : static enum ofperr
    5564                 :          8 : handle_nxt_set_controller_id(struct ofconn *ofconn,
    5565                 :            :                              const struct ofp_header *oh)
    5566                 :            : {
    5567                 :          8 :     const struct nx_controller_id *nci = ofpmsg_body(oh);
    5568                 :            : 
    5569         [ -  + ]:          8 :     if (!is_all_zeros(nci->zero, sizeof nci->zero)) {
    5570                 :          0 :         return OFPERR_NXBRC_MUST_BE_ZERO;
    5571                 :            :     }
    5572                 :            : 
    5573                 :          8 :     ofconn_set_controller_id(ofconn, ntohs(nci->controller_id));
    5574                 :          8 :     return 0;
    5575                 :            : }
    5576                 :            : 
    5577                 :            : static enum ofperr
    5578                 :      15031 : handle_barrier_request(struct ofconn *ofconn, const struct ofp_header *oh)
    5579                 :            : {
    5580                 :            :     struct ofpbuf *buf;
    5581                 :            : 
    5582         [ +  + ]:      15031 :     buf = ofpraw_alloc_reply((oh->version == OFP10_VERSION
    5583                 :            :                               ? OFPRAW_OFPT10_BARRIER_REPLY
    5584                 :            :                               : OFPRAW_OFPT11_BARRIER_REPLY), oh, 0);
    5585                 :      15031 :     ofconn_send_reply(ofconn, buf);
    5586                 :      15031 :     return 0;
    5587                 :            : }
    5588                 :            : 
    5589                 :            : static void
    5590                 :          5 : ofproto_compose_flow_refresh_update(const struct rule *rule,
    5591                 :            :                                     enum nx_flow_monitor_flags flags,
    5592                 :            :                                     struct ovs_list *msgs)
    5593                 :            :     OVS_REQUIRES(ofproto_mutex)
    5594                 :            : {
    5595                 :            :     const struct rule_actions *actions;
    5596                 :            :     struct ofputil_flow_update fu;
    5597                 :            :     struct match match;
    5598                 :            : 
    5599         [ +  + ]:          5 :     fu.event = (flags & (NXFMF_INITIAL | NXFMF_ADD)
    5600                 :            :                 ? NXFME_ADDED : NXFME_MODIFIED);
    5601                 :          5 :     fu.reason = 0;
    5602                 :          5 :     ovs_mutex_lock(&rule->mutex);
    5603                 :          5 :     fu.idle_timeout = rule->idle_timeout;
    5604                 :          5 :     fu.hard_timeout = rule->hard_timeout;
    5605                 :          5 :     ovs_mutex_unlock(&rule->mutex);
    5606                 :          5 :     fu.table_id = rule->table_id;
    5607                 :          5 :     fu.cookie = rule->flow_cookie;
    5608                 :          5 :     minimatch_expand(&rule->cr.match, &match);
    5609                 :          5 :     fu.match = &match;
    5610                 :          5 :     fu.priority = rule->cr.priority;
    5611                 :            : 
    5612         [ +  - ]:          5 :     actions = flags & NXFMF_ACTIONS ? rule_get_actions(rule) : NULL;
    5613         [ +  - ]:          5 :     fu.ofpacts = actions ? actions->ofpacts : NULL;
    5614         [ +  - ]:          5 :     fu.ofpacts_len = actions ? actions->ofpacts_len : 0;
    5615                 :            : 
    5616         [ +  + ]:          5 :     if (ovs_list_is_empty(msgs)) {
    5617                 :          1 :         ofputil_start_flow_update(msgs);
    5618                 :            :     }
    5619                 :          5 :     ofputil_append_flow_update(&fu, msgs);
    5620                 :          5 : }
    5621                 :            : 
    5622                 :            : void
    5623                 :          5 : ofmonitor_compose_refresh_updates(struct rule_collection *rules,
    5624                 :            :                                   struct ovs_list *msgs)
    5625                 :            :     OVS_REQUIRES(ofproto_mutex)
    5626                 :            : {
    5627                 :            :     struct rule *rule;
    5628                 :            : 
    5629 [ +  + ][ +  - ]:         10 :     RULE_COLLECTION_FOR_EACH (rule, rules) {
    5630                 :          5 :         enum nx_flow_monitor_flags flags = rule->monitor_flags;
    5631                 :          5 :         rule->monitor_flags = 0;
    5632                 :            : 
    5633                 :          5 :         ofproto_compose_flow_refresh_update(rule, flags, msgs);
    5634                 :            :     }
    5635                 :          5 : }
    5636                 :            : 
    5637                 :            : static void
    5638                 :          7 : ofproto_collect_ofmonitor_refresh_rule(const struct ofmonitor *m,
    5639                 :            :                                        struct rule *rule, uint64_t seqno,
    5640                 :            :                                        struct rule_collection *rules)
    5641                 :            :     OVS_REQUIRES(ofproto_mutex)
    5642                 :            : {
    5643                 :            :     enum nx_flow_monitor_flags update;
    5644                 :            : 
    5645         [ -  + ]:          7 :     if (rule_is_hidden(rule)) {
    5646                 :          0 :         return;
    5647                 :            :     }
    5648                 :            : 
    5649         [ +  + ]:          7 :     if (!ofproto_rule_has_out_port(rule, m->out_port)) {
    5650                 :          2 :         return;
    5651                 :            :     }
    5652                 :            : 
    5653         [ +  + ]:          5 :     if (seqno) {
    5654         [ +  + ]:          2 :         if (rule->add_seqno > seqno) {
    5655                 :          1 :             update = NXFMF_ADD | NXFMF_MODIFY;
    5656         [ +  - ]:          1 :         } else if (rule->modify_seqno > seqno) {
    5657                 :          1 :             update = NXFMF_MODIFY;
    5658                 :            :         } else {
    5659                 :          0 :             return;
    5660                 :            :         }
    5661                 :            : 
    5662         [ -  + ]:          2 :         if (!(m->flags & update)) {
    5663                 :          0 :             return;
    5664                 :            :         }
    5665                 :            :     } else {
    5666                 :          3 :         update = NXFMF_INITIAL;
    5667                 :            :     }
    5668                 :            : 
    5669         [ +  - ]:          5 :     if (!rule->monitor_flags) {
    5670                 :          5 :         rule_collection_add(rules, rule);
    5671                 :            :     }
    5672                 :          5 :     rule->monitor_flags |= update | (m->flags & NXFMF_ACTIONS);
    5673                 :            : }
    5674                 :            : 
    5675                 :            : static void
    5676                 :          5 : ofproto_collect_ofmonitor_refresh_rules(const struct ofmonitor *m,
    5677                 :            :                                         uint64_t seqno,
    5678                 :            :                                         struct rule_collection *rules)
    5679                 :            :     OVS_REQUIRES(ofproto_mutex)
    5680                 :            : {
    5681                 :          5 :     const struct ofproto *ofproto = ofconn_get_ofproto(m->ofconn);
    5682                 :            :     const struct oftable *table;
    5683                 :            :     struct cls_rule target;
    5684                 :            : 
    5685                 :          5 :     cls_rule_init_from_minimatch(&target, &m->match, 0);
    5686         [ +  + ]:       1275 :     FOR_EACH_MATCHING_TABLE (table, m->table_id, ofproto) {
    5687                 :            :         struct rule *rule;
    5688                 :            : 
    5689 [ +  + ][ +  + ]:       1277 :         CLS_FOR_EACH_TARGET (rule, cr, &table->cls, &target, OVS_VERSION_MAX) {
    5690                 :          7 :             ofproto_collect_ofmonitor_refresh_rule(m, rule, seqno, rules);
    5691                 :            :         }
    5692                 :            :     }
    5693                 :          5 :     cls_rule_destroy(&target);
    5694                 :          5 : }
    5695                 :            : 
    5696                 :            : static void
    5697                 :          4 : ofproto_collect_ofmonitor_initial_rules(struct ofmonitor *m,
    5698                 :            :                                         struct rule_collection *rules)
    5699                 :            :     OVS_REQUIRES(ofproto_mutex)
    5700                 :            : {
    5701         [ +  - ]:          4 :     if (m->flags & NXFMF_INITIAL) {
    5702                 :          4 :         ofproto_collect_ofmonitor_refresh_rules(m, 0, rules);
    5703                 :            :     }
    5704                 :          4 : }
    5705                 :            : 
    5706                 :            : void
    5707                 :          1 : ofmonitor_collect_resume_rules(struct ofmonitor *m,
    5708                 :            :                                uint64_t seqno, struct rule_collection *rules)
    5709                 :            :     OVS_REQUIRES(ofproto_mutex)
    5710                 :            : {
    5711                 :          1 :     ofproto_collect_ofmonitor_refresh_rules(m, seqno, rules);
    5712                 :          1 : }
    5713                 :            : 
    5714                 :            : static enum ofperr
    5715                 :          0 : flow_monitor_delete(struct ofconn *ofconn, uint32_t id)
    5716                 :            :     OVS_REQUIRES(ofproto_mutex)
    5717                 :            : {
    5718                 :            :     struct ofmonitor *m;
    5719                 :            :     enum ofperr error;
    5720                 :            : 
    5721                 :          0 :     m = ofmonitor_lookup(ofconn, id);
    5722         [ #  # ]:          0 :     if (m) {
    5723                 :          0 :         ofmonitor_destroy(m);
    5724                 :          0 :         error = 0;
    5725                 :            :     } else {
    5726                 :          0 :         error = OFPERR_OFPMOFC_UNKNOWN_MONITOR;
    5727                 :            :     }
    5728                 :            : 
    5729                 :          0 :     return error;
    5730                 :            : }
    5731                 :            : 
    5732                 :            : static enum ofperr
    5733                 :          4 : handle_flow_monitor_request(struct ofconn *ofconn, const struct ofp_header *oh)
    5734                 :            :     OVS_EXCLUDED(ofproto_mutex)
    5735                 :            : {
    5736                 :          4 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
    5737                 :            : 
    5738                 :          4 :     struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
    5739                 :            : 
    5740                 :          4 :     struct ofmonitor **monitors = NULL;
    5741                 :          4 :     size_t allocated_monitors = 0;
    5742                 :          4 :     size_t n_monitors = 0;
    5743                 :            : 
    5744                 :            :     enum ofperr error;
    5745                 :            : 
    5746                 :          4 :     ovs_mutex_lock(&ofproto_mutex);
    5747                 :            :     for (;;) {
    5748                 :            :         struct ofputil_flow_monitor_request request;
    5749                 :            :         struct ofmonitor *m;
    5750                 :            :         int retval;
    5751                 :            : 
    5752                 :          8 :         retval = ofputil_decode_flow_monitor_request(&request, &b);
    5753         [ +  + ]:          8 :         if (retval == EOF) {
    5754                 :          4 :             break;
    5755         [ -  + ]:          4 :         } else if (retval) {
    5756                 :          0 :             error = retval;
    5757                 :          0 :             goto error;
    5758                 :            :         }
    5759                 :            : 
    5760         [ -  + ]:          4 :         if (request.table_id != 0xff
    5761         [ #  # ]:          0 :             && request.table_id >= ofproto->n_tables) {
    5762                 :          0 :             error = OFPERR_OFPBRC_BAD_TABLE_ID;
    5763                 :          0 :             goto error;
    5764                 :            :         }
    5765                 :            : 
    5766                 :          4 :         error = ofmonitor_create(&request, ofconn, &m);
    5767         [ -  + ]:          4 :         if (error) {
    5768                 :          0 :             goto error;
    5769                 :            :         }
    5770                 :            : 
    5771         [ +  - ]:          4 :         if (n_monitors >= allocated_monitors) {
    5772                 :          4 :             monitors = x2nrealloc(monitors, &allocated_monitors,
    5773                 :            :                                   sizeof *monitors);
    5774                 :            :         }
    5775                 :          4 :         monitors[n_monitors++] = m;
    5776                 :          4 :     }
    5777                 :            : 
    5778                 :            :     struct rule_collection rules;
    5779                 :          4 :     rule_collection_init(&rules);
    5780         [ +  + ]:          8 :     for (size_t i = 0; i < n_monitors; i++) {
    5781                 :          4 :         ofproto_collect_ofmonitor_initial_rules(monitors[i], &rules);
    5782                 :            :     }
    5783                 :            : 
    5784                 :            :     struct ovs_list replies;
    5785                 :          4 :     ofpmp_init(&replies, oh);
    5786                 :          4 :     ofmonitor_compose_refresh_updates(&rules, &replies);
    5787                 :          4 :     ovs_mutex_unlock(&ofproto_mutex);
    5788                 :            : 
    5789                 :          4 :     rule_collection_destroy(&rules);
    5790                 :            : 
    5791                 :          4 :     ofconn_send_replies(ofconn, &replies);
    5792                 :          4 :     free(monitors);
    5793                 :            : 
    5794                 :          4 :     return 0;
    5795                 :            : 
    5796                 :            : error:
    5797         [ #  # ]:          0 :     for (size_t i = 0; i < n_monitors; i++) {
    5798                 :          0 :         ofmonitor_destroy(monitors[i]);
    5799                 :            :     }
    5800                 :          0 :     free(monitors);
    5801                 :          0 :     ovs_mutex_unlock(&ofproto_mutex);
    5802                 :            : 
    5803                 :          4 :     return error;
    5804                 :            : }
    5805                 :            : 
    5806                 :            : static enum ofperr
    5807                 :          0 : handle_flow_monitor_cancel(struct ofconn *ofconn, const struct ofp_header *oh)
    5808                 :            :     OVS_EXCLUDED(ofproto_mutex)
    5809                 :            : {
    5810                 :            :     enum ofperr error;
    5811                 :            :     uint32_t id;
    5812                 :            : 
    5813                 :          0 :     id = ofputil_decode_flow_monitor_cancel(oh);
    5814                 :            : 
    5815                 :          0 :     ovs_mutex_lock(&ofproto_mutex);
    5816                 :          0 :     error = flow_monitor_delete(ofconn, id);
    5817                 :          0 :     ovs_mutex_unlock(&ofproto_mutex);
    5818                 :            : 
    5819                 :          0 :     return error;
    5820                 :            : }
    5821                 :            : 
    5822                 :            : /* Meters implementation.
    5823                 :            :  *
    5824                 :            :  * Meter table entry, indexed by the OpenFlow meter_id.
    5825                 :            :  * 'created' is used to compute the duration for meter stats.
    5826                 :            :  * 'list rules' is needed so that we can delete the dependent rules when the
    5827                 :            :  * meter table entry is deleted.
    5828                 :            :  * 'provider_meter_id' is for the provider's private use.
    5829                 :            :  */
    5830                 :            : struct meter {
    5831                 :            :     long long int created;      /* Time created. */
    5832                 :            :     struct ovs_list rules;      /* List of "struct rule_dpif"s. */
    5833                 :            :     ofproto_meter_id provider_meter_id;
    5834                 :            :     uint16_t flags;             /* Meter flags. */
    5835                 :            :     uint16_t n_bands;           /* Number of meter bands. */
    5836                 :            :     struct ofputil_meter_band *bands;
    5837                 :            : };
    5838                 :            : 
    5839                 :            : /*
    5840                 :            :  * This is used in instruction validation at flow set-up time,
    5841                 :            :  * as flows may not use non-existing meters.
    5842                 :            :  * Return value of UINT32_MAX signifies an invalid meter.
    5843                 :            :  */
    5844                 :            : static uint32_t
    5845                 :          0 : get_provider_meter_id(const struct ofproto *ofproto, uint32_t of_meter_id)
    5846                 :            : {
    5847 [ #  # ][ #  # ]:          0 :     if (of_meter_id && of_meter_id <= ofproto->meter_features.max_meters) {
    5848                 :          0 :         const struct meter *meter = ofproto->meters[of_meter_id];
    5849         [ #  # ]:          0 :         if (meter) {
    5850                 :          0 :             return meter->provider_meter_id.uint32;
    5851                 :            :         }
    5852                 :            :     }
    5853                 :          0 :     return UINT32_MAX;
    5854                 :            : }
    5855                 :            : 
    5856                 :            : /* Finds the meter invoked by 'rule''s actions and adds 'rule' to the meter's
    5857                 :            :  * list of rules. */
    5858                 :            : static void
    5859                 :          0 : meter_insert_rule(struct rule *rule)
    5860                 :            : {
    5861                 :          0 :     const struct rule_actions *a = rule_get_actions(rule);
    5862                 :          0 :     uint32_t meter_id = ofpacts_get_meter(a->ofpacts, a->ofpacts_len);
    5863                 :          0 :     struct meter *meter = rule->ofproto->meters[meter_id];
    5864                 :            : 
    5865                 :          0 :     ovs_list_insert(&meter->rules, &rule->meter_list_node);
    5866                 :          0 : }
    5867                 :            : 
    5868                 :            : static void
    5869                 :          0 : meter_update(struct meter *meter, const struct ofputil_meter_config *config)
    5870                 :            : {
    5871                 :          0 :     free(meter->bands);
    5872                 :            : 
    5873                 :          0 :     meter->flags = config->flags;
    5874                 :          0 :     meter->n_bands = config->n_bands;
    5875                 :          0 :     meter->bands = xmemdup(config->bands,
    5876                 :          0 :                            config->n_bands * sizeof *meter->bands);
    5877                 :          0 : }
    5878                 :            : 
    5879                 :            : static struct meter *
    5880                 :          0 : meter_create(const struct ofputil_meter_config *config,
    5881                 :            :              ofproto_meter_id provider_meter_id)
    5882                 :            : {
    5883                 :            :     struct meter *meter;
    5884                 :            : 
    5885                 :          0 :     meter = xzalloc(sizeof *meter);
    5886                 :          0 :     meter->provider_meter_id = provider_meter_id;
    5887                 :          0 :     meter->created = time_msec();
    5888                 :          0 :     ovs_list_init(&meter->rules);
    5889                 :            : 
    5890                 :          0 :     meter_update(meter, config);
    5891                 :            : 
    5892                 :          0 :     return meter;
    5893                 :            : }
    5894                 :            : 
    5895                 :            : static void
    5896                 :        749 : meter_delete(struct ofproto *ofproto, uint32_t first, uint32_t last)
    5897                 :            :     OVS_REQUIRES(ofproto_mutex)
    5898                 :            : {
    5899                 :            :     uint32_t mid;
    5900         [ -  + ]:        749 :     for (mid = first; mid <= last; ++mid) {
    5901                 :          0 :         struct meter *meter = ofproto->meters[mid];
    5902         [ #  # ]:          0 :         if (meter) {
    5903                 :          0 :             ofproto->meters[mid] = NULL;
    5904                 :          0 :             ofproto->ofproto_class->meter_del(ofproto,
    5905                 :            :                                               meter->provider_meter_id);
    5906                 :          0 :             free(meter->bands);
    5907                 :          0 :             free(meter);
    5908                 :            :         }
    5909                 :            :     }
    5910                 :        749 : }
    5911                 :            : 
    5912                 :            : static enum ofperr
    5913                 :          0 : handle_add_meter(struct ofproto *ofproto, struct ofputil_meter_mod *mm)
    5914                 :            : {
    5915                 :          0 :     ofproto_meter_id provider_meter_id = { UINT32_MAX };
    5916                 :          0 :     struct meter **meterp = &ofproto->meters[mm->meter.meter_id];
    5917                 :            :     enum ofperr error;
    5918                 :            : 
    5919         [ #  # ]:          0 :     if (*meterp) {
    5920                 :          0 :         return OFPERR_OFPMMFC_METER_EXISTS;
    5921                 :            :     }
    5922                 :            : 
    5923                 :          0 :     error = ofproto->ofproto_class->meter_set(ofproto, &provider_meter_id,
    5924                 :          0 :                                               &mm->meter);
    5925         [ #  # ]:          0 :     if (!error) {
    5926         [ #  # ]:          0 :         ovs_assert(provider_meter_id.uint32 != UINT32_MAX);
    5927                 :          0 :         *meterp = meter_create(&mm->meter, provider_meter_id);
    5928                 :            :     }
    5929                 :          0 :     return error;
    5930                 :            : }
    5931                 :            : 
    5932                 :            : static enum ofperr
    5933                 :          0 : handle_modify_meter(struct ofproto *ofproto, struct ofputil_meter_mod *mm)
    5934                 :            : {
    5935                 :          0 :     struct meter *meter = ofproto->meters[mm->meter.meter_id];
    5936                 :            :     enum ofperr error;
    5937                 :            :     uint32_t provider_meter_id;
    5938                 :            : 
    5939         [ #  # ]:          0 :     if (!meter) {
    5940                 :          0 :         return OFPERR_OFPMMFC_UNKNOWN_METER;
    5941                 :            :     }
    5942                 :            : 
    5943                 :          0 :     provider_meter_id = meter->provider_meter_id.uint32;
    5944                 :          0 :     error = ofproto->ofproto_class->meter_set(ofproto,
    5945                 :            :                                               &meter->provider_meter_id,
    5946                 :          0 :                                               &mm->meter);
    5947         [ #  # ]:          0 :     ovs_assert(meter->provider_meter_id.uint32 == provider_meter_id);
    5948         [ #  # ]:          0 :     if (!error) {
    5949                 :          0 :         meter_update(meter, &mm->meter);
    5950                 :            :     }
    5951                 :          0 :     return error;
    5952                 :            : }
    5953                 :            : 
    5954                 :            : static enum ofperr
    5955                 :          0 : handle_delete_meter(struct ofconn *ofconn, struct ofputil_meter_mod *mm)
    5956                 :            :     OVS_EXCLUDED(ofproto_mutex)
    5957                 :            : {
    5958                 :          0 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
    5959                 :          0 :     uint32_t meter_id = mm->meter.meter_id;
    5960                 :            :     struct rule_collection rules;
    5961                 :          0 :     enum ofperr error = 0;
    5962                 :            :     uint32_t first, last;
    5963                 :            : 
    5964         [ #  # ]:          0 :     if (meter_id == OFPM13_ALL) {
    5965                 :          0 :         first = 1;
    5966                 :          0 :         last = ofproto->meter_features.max_meters;
    5967                 :            :     } else {
    5968 [ #  # ][ #  # ]:          0 :         if (!meter_id || meter_id > ofproto->meter_features.max_meters) {
    5969                 :          0 :             return 0;
    5970                 :            :         }
    5971                 :          0 :         first = last = meter_id;
    5972                 :            :     }
    5973                 :            : 
    5974                 :            :     /* First delete the rules that use this meter.  If any of those rules are
    5975                 :            :      * currently being modified, postpone the whole operation until later. */
    5976                 :          0 :     rule_collection_init(&rules);
    5977                 :          0 :     ovs_mutex_lock(&ofproto_mutex);
    5978         [ #  # ]:          0 :     for (meter_id = first; meter_id <= last; ++meter_id) {
    5979                 :          0 :         struct meter *meter = ofproto->meters[meter_id];
    5980 [ #  # ][ #  # ]:          0 :         if (meter && !ovs_list_is_empty(&meter->rules)) {
    5981                 :            :             struct rule *rule;
    5982                 :            : 
    5983         [ #  # ]:          0 :             LIST_FOR_EACH (rule, meter_list_node, &meter->rules) {
    5984                 :          0 :                 rule_collection_add(&rules, rule);
    5985                 :            :             }
    5986                 :            :         }
    5987                 :            :     }
    5988                 :          0 :     delete_flows__(&rules, OFPRR_METER_DELETE, NULL);
    5989                 :            : 
    5990                 :            :     /* Delete the meters. */
    5991                 :          0 :     meter_delete(ofproto, first, last);
    5992                 :            : 
    5993                 :          0 :     ovs_mutex_unlock(&ofproto_mutex);
    5994                 :            : 
    5995                 :          0 :     return error;
    5996                 :            : }
    5997                 :            : 
    5998                 :            : static enum ofperr
    5999                 :          0 : handle_meter_mod(struct ofconn *ofconn, const struct ofp_header *oh)
    6000                 :            : {
    6001                 :          0 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
    6002                 :            :     struct ofputil_meter_mod mm;
    6003                 :            :     uint64_t bands_stub[256 / 8];
    6004                 :            :     struct ofpbuf bands;
    6005                 :            :     uint32_t meter_id;
    6006                 :            :     enum ofperr error;
    6007                 :            : 
    6008                 :          0 :     error = reject_slave_controller(ofconn);
    6009         [ #  # ]:          0 :     if (error) {
    6010                 :          0 :         return error;
    6011                 :            :     }
    6012                 :            : 
    6013                 :          0 :     ofpbuf_use_stub(&bands, bands_stub, sizeof bands_stub);
    6014                 :            : 
    6015                 :          0 :     error = ofputil_decode_meter_mod(oh, &mm, &bands);
    6016         [ #  # ]:          0 :     if (error) {
    6017                 :          0 :         goto exit_free_bands;
    6018                 :            :     }
    6019                 :            : 
    6020                 :          0 :     meter_id = mm.meter.meter_id;
    6021                 :            : 
    6022         [ #  # ]:          0 :     if (mm.command != OFPMC13_DELETE) {
    6023                 :            :         /* Fails also when meters are not implemented by the provider. */
    6024 [ #  # ][ #  # ]:          0 :         if (meter_id == 0 || meter_id > OFPM13_MAX) {
    6025                 :          0 :             error = OFPERR_OFPMMFC_INVALID_METER;
    6026                 :          0 :             goto exit_free_bands;
    6027         [ #  # ]:          0 :         } else if (meter_id > ofproto->meter_features.max_meters) {
    6028                 :          0 :             error = OFPERR_OFPMMFC_OUT_OF_METERS;
    6029                 :          0 :             goto exit_free_bands;
    6030                 :            :         }
    6031         [ #  # ]:          0 :         if (mm.meter.n_bands > ofproto->meter_features.max_bands) {
    6032                 :          0 :             error = OFPERR_OFPMMFC_OUT_OF_BANDS;
    6033                 :          0 :             goto exit_free_bands;
    6034                 :            :         }
    6035                 :            :     }
    6036                 :            : 
    6037   [ #  #  #  # ]:          0 :     switch (mm.command) {
    6038                 :            :     case OFPMC13_ADD:
    6039                 :          0 :         error = handle_add_meter(ofproto, &mm);
    6040                 :          0 :         break;
    6041                 :            : 
    6042                 :            :     case OFPMC13_MODIFY:
    6043                 :          0 :         error = handle_modify_meter(ofproto, &mm);
    6044                 :          0 :         break;
    6045                 :            : 
    6046                 :            :     case OFPMC13_DELETE:
    6047                 :          0 :         error = handle_delete_meter(ofconn, &mm);
    6048                 :          0 :         break;
    6049                 :            : 
    6050                 :            :     default:
    6051                 :          0 :         error = OFPERR_OFPMMFC_BAD_COMMAND;
    6052                 :          0 :         break;
    6053                 :            :     }
    6054                 :            : 
    6055         [ #  # ]:          0 :     if (!error) {
    6056                 :            :         struct ofputil_requestforward rf;
    6057                 :          0 :         rf.xid = oh->xid;
    6058                 :          0 :         rf.reason = OFPRFR_METER_MOD;
    6059                 :          0 :         rf.meter_mod = &mm;
    6060                 :          0 :         connmgr_send_requestforward(ofproto->connmgr, ofconn, &rf);
    6061                 :            :     }
    6062                 :            : 
    6063                 :            : exit_free_bands:
    6064                 :          0 :     ofpbuf_uninit(&bands);
    6065                 :          0 :     return error;
    6066                 :            : }
    6067                 :            : 
    6068                 :            : static enum ofperr
    6069                 :          0 : handle_meter_features_request(struct ofconn *ofconn,
    6070                 :            :                               const struct ofp_header *request)
    6071                 :            : {
    6072                 :          0 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
    6073                 :            :     struct ofputil_meter_features features;
    6074                 :            :     struct ofpbuf *b;
    6075                 :            : 
    6076         [ #  # ]:          0 :     if (ofproto->ofproto_class->meter_get_features) {
    6077                 :          0 :         ofproto->ofproto_class->meter_get_features(ofproto, &features);
    6078                 :            :     } else {
    6079                 :          0 :         memset(&features, 0, sizeof features);
    6080                 :            :     }
    6081                 :          0 :     b = ofputil_encode_meter_features_reply(&features, request);
    6082                 :            : 
    6083                 :          0 :     ofconn_send_reply(ofconn, b);
    6084                 :          0 :     return 0;
    6085                 :            : }
    6086                 :            : 
    6087                 :            : static enum ofperr
    6088                 :          0 : handle_meter_request(struct ofconn *ofconn, const struct ofp_header *request,
    6089                 :            :                      enum ofptype type)
    6090                 :            : {
    6091                 :          0 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
    6092                 :            :     struct ovs_list replies;
    6093                 :            :     uint64_t bands_stub[256 / 8];
    6094                 :            :     struct ofpbuf bands;
    6095                 :            :     uint32_t meter_id, first, last;
    6096                 :            : 
    6097                 :          0 :     ofputil_decode_meter_request(request, &meter_id);
    6098                 :            : 
    6099         [ #  # ]:          0 :     if (meter_id == OFPM13_ALL) {
    6100                 :          0 :         first = 1;
    6101                 :          0 :         last = ofproto->meter_features.max_meters;
    6102                 :            :     } else {
    6103 [ #  # ][ #  # ]:          0 :         if (!meter_id || meter_id > ofproto->meter_features.max_meters ||
                 [ #  # ]
    6104                 :          0 :             !ofproto->meters[meter_id]) {
    6105                 :          0 :             return OFPERR_OFPMMFC_UNKNOWN_METER;
    6106                 :            :         }
    6107                 :          0 :         first = last = meter_id;
    6108                 :            :     }
    6109                 :            : 
    6110                 :          0 :     ofpbuf_use_stub(&bands, bands_stub, sizeof bands_stub);
    6111                 :          0 :     ofpmp_init(&replies, request);
    6112                 :            : 
    6113         [ #  # ]:          0 :     for (meter_id = first; meter_id <= last; ++meter_id) {
    6114                 :          0 :         struct meter *meter = ofproto->meters[meter_id];
    6115         [ #  # ]:          0 :         if (!meter) {
    6116                 :          0 :             continue; /* Skip non-existing meters. */
    6117                 :            :         }
    6118         [ #  # ]:          0 :         if (type == OFPTYPE_METER_STATS_REQUEST) {
    6119                 :            :             struct ofputil_meter_stats stats;
    6120                 :            : 
    6121                 :          0 :             stats.meter_id = meter_id;
    6122                 :            : 
    6123                 :            :             /* Provider sets the packet and byte counts, we do the rest. */
    6124                 :          0 :             stats.flow_count = ovs_list_size(&meter->rules);
    6125                 :          0 :             calc_duration(meter->created, time_msec(),
    6126                 :            :                           &stats.duration_sec, &stats.duration_nsec);
    6127                 :          0 :             stats.n_bands = meter->n_bands;
    6128                 :          0 :             ofpbuf_clear(&bands);
    6129                 :            :             stats.bands
    6130                 :          0 :                 = ofpbuf_put_uninit(&bands,
    6131                 :          0 :                                     meter->n_bands * sizeof *stats.bands);
    6132                 :            : 
    6133         [ #  # ]:          0 :             if (!ofproto->ofproto_class->meter_get(ofproto,
    6134                 :            :                                                    meter->provider_meter_id,
    6135                 :            :                                                    &stats)) {
    6136                 :          0 :                 ofputil_append_meter_stats(&replies, &stats);
    6137                 :            :             }
    6138                 :            :         } else { /* type == OFPTYPE_METER_CONFIG_REQUEST */
    6139                 :            :             struct ofputil_meter_config config;
    6140                 :            : 
    6141                 :          0 :             config.meter_id = meter_id;
    6142                 :          0 :             config.flags = meter->flags;
    6143                 :          0 :             config.n_bands = meter->n_bands;
    6144                 :          0 :             config.bands = meter->bands;
    6145                 :          0 :             ofputil_append_meter_config(&replies, &config);
    6146                 :            :         }
    6147                 :            :     }
    6148                 :            : 
    6149                 :          0 :     ofconn_send_replies(ofconn, &replies);
    6150                 :          0 :     ofpbuf_uninit(&bands);
    6151                 :          0 :     return 0;
    6152                 :            : }
    6153                 :            : 
    6154                 :            : /* Returned group is RCU protected. */
    6155                 :            : static struct ofgroup *
    6156                 :        532 : ofproto_group_lookup__(const struct ofproto *ofproto, uint32_t group_id,
    6157                 :            :                        ovs_version_t version)
    6158                 :            : {
    6159                 :            :     struct ofgroup *group;
    6160                 :            : 
    6161         [ +  + ]:        533 :     CMAP_FOR_EACH_WITH_HASH (group, cmap_node, hash_int(group_id, 0),
    6162                 :            :                              &ofproto->groups) {
    6163         [ +  - ]:        452 :         if (group->group_id == group_id
    6164         [ +  + ]:        452 :             && versions_visible_in_version(&group->versions, version)) {
    6165                 :        451 :             return group;
    6166                 :            :         }
    6167                 :            :     }
    6168                 :            : 
    6169                 :         81 :     return NULL;
    6170                 :            : }
    6171                 :            : 
    6172                 :            : /* If the group exists, this function increments the groups's reference count.
    6173                 :            :  *
    6174                 :            :  * Make sure to call ofproto_group_unref() after no longer needing to maintain
    6175                 :            :  * a reference to the group. */
    6176                 :            : struct ofgroup *
    6177                 :        342 : ofproto_group_lookup(const struct ofproto *ofproto, uint32_t group_id,
    6178                 :            :                      ovs_version_t version, bool take_ref)
    6179                 :            : {
    6180                 :            :     struct ofgroup *group;
    6181                 :            : 
    6182                 :        342 :     group = ofproto_group_lookup__(ofproto, group_id, version);
    6183 [ +  - ][ +  + ]:        342 :     if (group && take_ref) {
    6184                 :            :         /* Not holding a lock, so it is possible that another thread releases
    6185                 :            :          * the last reference just before we manage to get one. */
    6186         [ +  - ]:         50 :         return ofproto_group_try_ref(group) ? group : NULL;
    6187                 :            :     }
    6188                 :        292 :     return group;
    6189                 :            : }
    6190                 :            : 
    6191                 :            : /* Caller should hold 'ofproto_mutex' if it is important that the
    6192                 :            :  * group is not removed by someone else. */
    6193                 :            : static bool
    6194                 :        114 : ofproto_group_exists(const struct ofproto *ofproto, uint32_t group_id)
    6195                 :            : {
    6196                 :        114 :     return ofproto_group_lookup__(ofproto, group_id, OVS_VERSION_MAX) != NULL;
    6197                 :            : }
    6198                 :            : 
    6199                 :            : static void
    6200                 :         39 : group_add_rule(struct ofgroup *group, struct rule *rule)
    6201                 :            : {
    6202                 :         39 :     rule_collection_add(&group->rules, rule);
    6203                 :         39 : }
    6204                 :            : 
    6205                 :            : static void
    6206                 :         23 : group_remove_rule(struct ofgroup *group, struct rule *rule)
    6207                 :            : {
    6208                 :         23 :     rule_collection_remove(&group->rules, rule);
    6209                 :         23 : }
    6210                 :            : 
    6211                 :            : static void
    6212                 :         11 : append_group_stats(struct ofgroup *group, struct ovs_list *replies)
    6213                 :            :     OVS_REQUIRES(ofproto_mutex)
    6214                 :            : {
    6215                 :            :     struct ofputil_group_stats ogs;
    6216                 :         11 :     const struct ofproto *ofproto = group->ofproto;
    6217                 :         11 :     long long int now = time_msec();
    6218                 :            :     int error;
    6219                 :            : 
    6220                 :         11 :     ogs.bucket_stats = xmalloc(group->n_buckets * sizeof *ogs.bucket_stats);
    6221                 :            : 
    6222                 :            :     /* Provider sets the packet and byte counts, we do the rest. */
    6223                 :         11 :     ogs.ref_count = rule_collection_n(&group->rules);
    6224                 :         11 :     ogs.n_buckets = group->n_buckets;
    6225                 :            : 
    6226         [ +  - ]:         22 :     error = (ofproto->ofproto_class->group_get_stats
    6227                 :         11 :              ? ofproto->ofproto_class->group_get_stats(group, &ogs)
    6228                 :            :              : EOPNOTSUPP);
    6229         [ -  + ]:         11 :     if (error) {
    6230                 :          0 :         ogs.packet_count = UINT64_MAX;
    6231                 :          0 :         ogs.byte_count = UINT64_MAX;
    6232                 :          0 :         memset(ogs.bucket_stats, 0xff,
    6233                 :          0 :                ogs.n_buckets * sizeof *ogs.bucket_stats);
    6234                 :            :     }
    6235                 :            : 
    6236                 :         11 :     ogs.group_id = group->group_id;
    6237                 :         11 :     calc_duration(group->created, now, &ogs.duration_sec, &ogs.duration_nsec);
    6238                 :            : 
    6239                 :         11 :     ofputil_append_group_stats(replies, &ogs);
    6240                 :            : 
    6241                 :         11 :     free(ogs.bucket_stats);
    6242                 :         11 : }
    6243                 :            : 
    6244                 :            : static void
    6245                 :         60 : handle_group_request(struct ofconn *ofconn,
    6246                 :            :                      const struct ofp_header *request, uint32_t group_id,
    6247                 :            :                      void (*cb)(struct ofgroup *, struct ovs_list *replies))
    6248                 :            :     OVS_EXCLUDED(ofproto_mutex)
    6249                 :            : {
    6250                 :         60 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
    6251                 :            :     struct ofgroup *group;
    6252                 :            :     struct ovs_list replies;
    6253                 :            : 
    6254                 :         60 :     ofpmp_init(&replies, request);
    6255                 :            :     /* Must exclude modifications to guarantee iterating groups. */
    6256                 :         60 :     ovs_mutex_lock(&ofproto_mutex);
    6257         [ +  + ]:         60 :     if (group_id == OFPG_ALL) {
    6258 [ +  + ][ +  + ]:        101 :         CMAP_FOR_EACH (group, cmap_node, &ofproto->groups) {
    6259                 :         54 :             cb(group, &replies);
    6260                 :            :         }
    6261                 :            :     } else {
    6262                 :         13 :         group = ofproto_group_lookup__(ofproto, group_id, OVS_VERSION_MAX);
    6263         [ +  - ]:         13 :         if (group) {
    6264                 :         13 :             cb(group, &replies);
    6265                 :            :         }
    6266                 :            :     }
    6267                 :         60 :     ovs_mutex_unlock(&ofproto_mutex);
    6268                 :         60 :     ofconn_send_replies(ofconn, &replies);
    6269                 :         60 : }
    6270                 :            : 
    6271                 :            : static enum ofperr
    6272                 :          8 : handle_group_stats_request(struct ofconn *ofconn,
    6273                 :            :                            const struct ofp_header *request)
    6274                 :            : {
    6275                 :            :     uint32_t group_id;
    6276                 :            :     enum ofperr error;
    6277                 :            : 
    6278                 :          8 :     error = ofputil_decode_group_stats_request(request, &group_id);
    6279         [ -  + ]:          8 :     if (error) {
    6280                 :          0 :         return error;
    6281                 :            :     }
    6282                 :            : 
    6283                 :          8 :     handle_group_request(ofconn, request, group_id, append_group_stats);
    6284                 :          8 :     return 0;
    6285                 :            : }
    6286                 :            : 
    6287                 :            : static void
    6288                 :         56 : append_group_desc(struct ofgroup *group, struct ovs_list *replies)
    6289                 :            : {
    6290                 :            :     struct ofputil_group_desc gds;
    6291                 :            : 
    6292                 :         56 :     gds.group_id = group->group_id;
    6293                 :         56 :     gds.type = group->type;
    6294                 :         56 :     gds.props = group->props;
    6295                 :            : 
    6296                 :         56 :     ofputil_append_group_desc_reply(&gds, &group->buckets, replies);
    6297                 :         56 : }
    6298                 :            : 
    6299                 :            : static enum ofperr
    6300                 :         52 : handle_group_desc_stats_request(struct ofconn *ofconn,
    6301                 :            :                                 const struct ofp_header *request)
    6302                 :            : {
    6303                 :         52 :     handle_group_request(ofconn, request,
    6304                 :            :                          ofputil_decode_group_desc_request(request),
    6305                 :            :                          append_group_desc);
    6306                 :         52 :     return 0;
    6307                 :            : }
    6308                 :            : 
    6309                 :            : static enum ofperr
    6310                 :          1 : handle_group_features_stats_request(struct ofconn *ofconn,
    6311                 :            :                                     const struct ofp_header *request)
    6312                 :            : {
    6313                 :          1 :     struct ofproto *p = ofconn_get_ofproto(ofconn);
    6314                 :            :     struct ofpbuf *msg;
    6315                 :            : 
    6316                 :          1 :     msg = ofputil_encode_group_features_reply(&p->ogf, request);
    6317         [ +  - ]:          1 :     if (msg) {
    6318                 :          1 :         ofconn_send_reply(ofconn, msg);
    6319                 :            :     }
    6320                 :            : 
    6321                 :          1 :     return 0;
    6322                 :            : }
    6323                 :            : 
    6324                 :            : static void
    6325                 :         12 : put_queue_get_config_reply(struct ofport *port, uint32_t queue,
    6326                 :            :                            struct ovs_list *replies)
    6327                 :            : {
    6328                 :            :     struct ofputil_queue_config qc;
    6329                 :            : 
    6330                 :            :     /* None of the existing queues have compatible properties, so we hard-code
    6331                 :            :      * omitting min_rate and max_rate. */
    6332                 :         12 :     qc.port = port->ofp_port;
    6333                 :         12 :     qc.queue = queue;
    6334                 :         12 :     qc.min_rate = UINT16_MAX;
    6335                 :         12 :     qc.max_rate = UINT16_MAX;
    6336                 :         12 :     ofputil_append_queue_get_config_reply(&qc, replies);
    6337                 :         12 : }
    6338                 :            : 
    6339                 :            : static int
    6340                 :         13 : handle_queue_get_config_request_for_port(struct ofport *port, uint32_t queue,
    6341                 :            :                                          struct ovs_list *replies)
    6342                 :            : {
    6343                 :         13 :     struct smap details = SMAP_INITIALIZER(&details);
    6344         [ +  + ]:         13 :     if (queue != OFPQ_ALL) {
    6345                 :          1 :         int error = netdev_get_queue(port->netdev, queue, &details);
    6346      [ -  +  - ]:          1 :         switch (error) {
    6347                 :            :         case 0:
    6348                 :          0 :             put_queue_get_config_reply(port, queue, replies);
    6349                 :          0 :             break;
    6350                 :            :         case EOPNOTSUPP:
    6351                 :            :         case EINVAL:
    6352                 :          1 :             return OFPERR_OFPQOFC_BAD_QUEUE;
    6353                 :            :         default:
    6354                 :          0 :             return OFPERR_NXQOFC_QUEUE_ERROR;
    6355                 :            :         }
    6356                 :            :     } else {
    6357                 :            :         struct netdev_queue_dump queue_dump;
    6358                 :            :         uint32_t queue_id;
    6359                 :            : 
    6360 [ +  + ][ +  + ]:         24 :         NETDEV_QUEUE_FOR_EACH (&queue_id, &details, &queue_dump,
    6361                 :            :                                port->netdev) {
    6362                 :         12 :             put_queue_get_config_reply(port, queue_id, replies);
    6363                 :            :         }
    6364                 :            :     }
    6365                 :         12 :     smap_destroy(&details);
    6366                 :         13 :     return 0;
    6367                 :            : }
    6368                 :            : 
    6369                 :            : static enum ofperr
    6370                 :         13 : handle_queue_get_config_request(struct ofconn *ofconn,
    6371                 :            :                                 const struct ofp_header *oh)
    6372                 :            : {
    6373                 :         13 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
    6374                 :            :     struct ovs_list replies;
    6375                 :            :     struct ofport *port;
    6376                 :            :     ofp_port_t req_port;
    6377                 :            :     uint32_t req_queue;
    6378                 :            :     enum ofperr error;
    6379                 :            : 
    6380                 :         13 :     error = ofputil_decode_queue_get_config_request(oh, &req_port, &req_queue);
    6381         [ -  + ]:         13 :     if (error) {
    6382                 :          0 :         return error;
    6383                 :            :     }
    6384                 :            : 
    6385                 :         13 :     ofputil_start_queue_get_config_reply(oh, &replies);
    6386         [ +  + ]:         13 :     if (req_port == OFPP_ANY) {
    6387                 :          2 :         error = OFPERR_OFPQOFC_BAD_QUEUE;
    6388 [ +  + ][ -  + ]:          8 :         HMAP_FOR_EACH (port, hmap_node, &ofproto->ports) {
    6389         [ +  - ]:          6 :             if (!handle_queue_get_config_request_for_port(port, req_queue,
    6390                 :            :                                                           &replies)) {
    6391                 :          6 :                 error = 0;
    6392                 :            :             }
    6393                 :            :         }
    6394                 :            :     } else {
    6395                 :         11 :         port = ofproto_get_port(ofproto, req_port);
    6396         [ +  + ]:         18 :         error = (port
    6397                 :          7 :                  ? handle_queue_get_config_request_for_port(port, req_queue,
    6398                 :            :                                                             &replies)
    6399                 :            :                  : OFPERR_OFPQOFC_BAD_PORT);
    6400                 :            :     }
    6401         [ +  + ]:         13 :     if (!error) {
    6402                 :          8 :         ofconn_send_replies(ofconn, &replies);
    6403                 :            :     } else {
    6404                 :          5 :         ofpbuf_list_delete(&replies);
    6405                 :            :     }
    6406                 :            : 
    6407                 :         13 :     return error;
    6408                 :            : }
    6409                 :            : 
    6410                 :            : static enum ofperr
    6411                 :        103 : init_group(struct ofproto *ofproto, const struct ofputil_group_mod *gm,
    6412                 :            :            ovs_version_t version, struct ofgroup **ofgroup)
    6413                 :            : {
    6414                 :            :     enum ofperr error;
    6415                 :        103 :     const long long int now = time_msec();
    6416                 :            : 
    6417         [ -  + ]:        103 :     if (gm->group_id > OFPG_MAX) {
    6418                 :          0 :         return OFPERR_OFPGMFC_INVALID_GROUP;
    6419                 :            :     }
    6420         [ -  + ]:        103 :     if (gm->type > OFPGT11_FF) {
    6421                 :          0 :         return OFPERR_OFPGMFC_BAD_TYPE;
    6422                 :            :     }
    6423                 :            : 
    6424                 :        103 :     *ofgroup = ofproto->ofproto_class->group_alloc();
    6425         [ -  + ]:        103 :     if (!*ofgroup) {
    6426         [ #  # ]:          0 :         VLOG_WARN_RL(&rl, "%s: failed to allocate group", ofproto->name);
    6427                 :          0 :         return OFPERR_OFPGMFC_OUT_OF_GROUPS;
    6428                 :            :     }
    6429                 :            : 
    6430                 :        103 :     *CONST_CAST(struct ofproto **, &(*ofgroup)->ofproto) = ofproto;
    6431                 :        103 :     *CONST_CAST(uint32_t *, &((*ofgroup)->group_id)) = gm->group_id;
    6432                 :        103 :     *CONST_CAST(enum ofp11_group_type *, &(*ofgroup)->type) = gm->type;
    6433                 :        103 :     *CONST_CAST(long long int *, &((*ofgroup)->created)) = now;
    6434                 :        103 :     *CONST_CAST(long long int *, &((*ofgroup)->modified)) = now;
    6435                 :        103 :     ovs_refcount_init(&(*ofgroup)->ref_count);
    6436                 :        103 :     (*ofgroup)->being_deleted = false;
    6437                 :            : 
    6438                 :        103 :     ovs_list_init(CONST_CAST(struct ovs_list *, &(*ofgroup)->buckets));
    6439                 :        103 :     ofputil_bucket_clone_list(CONST_CAST(struct ovs_list *,
    6440                 :            :                                          &(*ofgroup)->buckets),
    6441                 :            :                               &gm->buckets, NULL);
    6442                 :            : 
    6443                 :        206 :     *CONST_CAST(uint32_t *, &(*ofgroup)->n_buckets) =
    6444                 :        103 :         ovs_list_size(&(*ofgroup)->buckets);
    6445                 :            : 
    6446                 :        103 :     ofputil_group_properties_copy(CONST_CAST(struct ofputil_group_props *,
    6447                 :            :                                              &(*ofgroup)->props),
    6448                 :            :                                   &gm->props);
    6449                 :        103 :     rule_collection_init(&(*ofgroup)->rules);
    6450                 :            : 
    6451                 :            :     /* Make group visible from 'version'. */
    6452                 :        103 :     (*ofgroup)->versions = VERSIONS_INITIALIZER(version,
    6453                 :            :                                                 OVS_VERSION_NOT_REMOVED);
    6454                 :            : 
    6455                 :            :     /* Construct called BEFORE any locks are held. */
    6456                 :        103 :     error = ofproto->ofproto_class->group_construct(*ofgroup);
    6457         [ -  + ]:        103 :     if (error) {
    6458                 :          0 :         ofputil_group_properties_destroy(CONST_CAST(struct ofputil_group_props *,
    6459                 :            :                                                     &(*ofgroup)->props));
    6460                 :          0 :         ofputil_bucket_list_destroy(CONST_CAST(struct ovs_list *,
    6461                 :            :                                                &(*ofgroup)->buckets));
    6462                 :          0 :         ofproto->ofproto_class->group_dealloc(*ofgroup);
    6463                 :            :     }
    6464                 :        103 :     return error;
    6465                 :            : }
    6466                 :            : 
    6467                 :            : /* Implements the OFPGC11_ADD operation specified by 'gm', adding a group to
    6468                 :            :  * 'ofproto''s group table.  Returns 0 on success or an OpenFlow error code on
    6469                 :            :  * failure. */
    6470                 :            : static enum ofperr
    6471                 :         68 : add_group_start(struct ofproto *ofproto, struct ofproto_group_mod *ogm)
    6472                 :            :     OVS_REQUIRES(ofproto_mutex)
    6473                 :            : {
    6474                 :            :     enum ofperr error;
    6475                 :            : 
    6476         [ -  + ]:         68 :     if (ofproto_group_exists(ofproto, ogm->gm.group_id)) {
    6477                 :          0 :         return OFPERR_OFPGMFC_GROUP_EXISTS;
    6478                 :            :     }
    6479                 :            : 
    6480         [ -  + ]:         68 :     if (ofproto->n_groups[ogm->gm.type]
    6481                 :         68 :         >= ofproto->ogf.max_groups[ogm->gm.type]) {
    6482                 :          0 :         return OFPERR_OFPGMFC_OUT_OF_GROUPS;
    6483                 :            :     }
    6484                 :            : 
    6485                 :            :     /* Allocate new group and initialize it. */
    6486                 :         68 :     error = init_group(ofproto, &ogm->gm, ogm->version, &ogm->new_group);
    6487         [ +  - ]:         68 :     if (!error) {
    6488                 :            :         /* Insert new group. */
    6489                 :         68 :         cmap_insert(&ofproto->groups, &ogm->new_group->cmap_node,
    6490                 :         68 :                     hash_int(ogm->new_group->group_id, 0));
    6491                 :         68 :         ofproto->n_groups[ogm->new_group->type]++;
    6492                 :            :     }
    6493                 :         68 :     return error;
    6494                 :            : }
    6495                 :            : 
    6496                 :            : /* Adds all of the buckets from 'ofgroup' to 'new_ofgroup'.  The buckets
    6497                 :            :  * already in 'new_ofgroup' will be placed just after the (copy of the) bucket
    6498                 :            :  * in 'ofgroup' with bucket ID 'command_bucket_id'.  Special
    6499                 :            :  * 'command_bucket_id' values OFPG15_BUCKET_FIRST and OFPG15_BUCKET_LAST are
    6500                 :            :  * also honored. */
    6501                 :            : static enum ofperr
    6502                 :         16 : copy_buckets_for_insert_bucket(const struct ofgroup *ofgroup,
    6503                 :            :                                struct ofgroup *new_ofgroup,
    6504                 :            :                                uint32_t command_bucket_id)
    6505                 :            : {
    6506                 :         16 :     struct ofputil_bucket *last = NULL;
    6507                 :            : 
    6508         [ +  + ]:         16 :     if (command_bucket_id <= OFPG15_BUCKET_MAX) {
    6509                 :            :         /* Check here to ensure that a bucket corresponding to
    6510                 :            :          * command_bucket_id exists in the old bucket list.
    6511                 :            :          *
    6512                 :            :          * The subsequent search of below of new_ofgroup covers
    6513                 :            :          * both buckets in the old bucket list and buckets added
    6514                 :            :          * by the insert buckets group mod message this function processes. */
    6515         [ -  + ]:          6 :         if (!ofputil_bucket_find(&ofgroup->buckets, command_bucket_id)) {
    6516                 :          0 :             return OFPERR_OFPGMFC_UNKNOWN_BUCKET;
    6517                 :            :         }
    6518                 :            : 
    6519         [ +  + ]:          6 :         if (!ovs_list_is_empty(&new_ofgroup->buckets)) {
    6520                 :          4 :             last = ofputil_bucket_list_back(&new_ofgroup->buckets);
    6521                 :            :         }
    6522                 :            :     }
    6523                 :            : 
    6524                 :         16 :     ofputil_bucket_clone_list(CONST_CAST(struct ovs_list *,
    6525                 :            :                                          &new_ofgroup->buckets),
    6526                 :            :                               &ofgroup->buckets, NULL);
    6527                 :            : 
    6528         [ +  + ]:         16 :     if (ofputil_bucket_check_duplicate_id(&new_ofgroup->buckets)) {
    6529         [ +  - ]:          2 :             VLOG_INFO_RL(&rl, "Duplicate bucket id");
    6530                 :          2 :             return OFPERR_OFPGMFC_BUCKET_EXISTS;
    6531                 :            :     }
    6532                 :            : 
    6533                 :            :     /* Rearrange list according to command_bucket_id */
    6534         [ +  + ]:         14 :     if (command_bucket_id == OFPG15_BUCKET_LAST) {
    6535         [ +  + ]:          4 :         if (!ovs_list_is_empty(&ofgroup->buckets)) {
    6536                 :            :             struct ofputil_bucket *new_first;
    6537                 :            :             const struct ofputil_bucket *first;
    6538                 :            : 
    6539                 :          2 :             first = ofputil_bucket_list_front(&ofgroup->buckets);
    6540                 :          2 :             new_first = ofputil_bucket_find(&new_ofgroup->buckets,
    6541                 :            :                                             first->bucket_id);
    6542                 :            : 
    6543                 :          4 :             ovs_list_splice(new_ofgroup->buckets.next, &new_first->list_node,
    6544                 :          2 :                             CONST_CAST(struct ovs_list *,
    6545                 :            :                                        &new_ofgroup->buckets));
    6546                 :            :         }
    6547 [ +  + ][ +  + ]:         10 :     } else if (command_bucket_id <= OFPG15_BUCKET_MAX && last) {
    6548                 :            :         struct ofputil_bucket *after;
    6549                 :            : 
    6550                 :            :         /* Presence of bucket is checked above so after should never be NULL */
    6551                 :          4 :         after = ofputil_bucket_find(&new_ofgroup->buckets, command_bucket_id);
    6552                 :            : 
    6553                 :          4 :         ovs_list_splice(after->list_node.next, new_ofgroup->buckets.next,
    6554                 :            :                     last->list_node.next);
    6555                 :            :     }
    6556                 :            : 
    6557                 :         14 :     return 0;
    6558                 :            : }
    6559                 :            : 
    6560                 :            : /* Appends all of the a copy of all the buckets from 'ofgroup' to 'new_ofgroup'
    6561                 :            :  * with the exception of the bucket whose bucket id is 'command_bucket_id'.
    6562                 :            :  * Special 'command_bucket_id' values OFPG15_BUCKET_FIRST, OFPG15_BUCKET_LAST
    6563                 :            :  * and OFPG15_BUCKET_ALL are also honored. */
    6564                 :            : static enum ofperr
    6565                 :         16 : copy_buckets_for_remove_bucket(const struct ofgroup *ofgroup,
    6566                 :            :                                struct ofgroup *new_ofgroup,
    6567                 :            :                                uint32_t command_bucket_id)
    6568                 :            : {
    6569                 :         16 :     const struct ofputil_bucket *skip = NULL;
    6570                 :            : 
    6571         [ +  + ]:         16 :     if (command_bucket_id == OFPG15_BUCKET_ALL) {
    6572                 :          4 :         return 0;
    6573                 :            :     }
    6574                 :            : 
    6575         [ +  + ]:         12 :     if (command_bucket_id == OFPG15_BUCKET_FIRST) {
    6576         [ +  + ]:          4 :         if (!ovs_list_is_empty(&ofgroup->buckets)) {
    6577                 :          4 :             skip = ofputil_bucket_list_front(&ofgroup->buckets);
    6578                 :            :         }
    6579         [ +  + ]:          8 :     } else if (command_bucket_id == OFPG15_BUCKET_LAST) {
    6580         [ +  + ]:          4 :         if (!ovs_list_is_empty(&ofgroup->buckets)) {
    6581                 :          4 :             skip = ofputil_bucket_list_back(&ofgroup->buckets);
    6582                 :            :         }
    6583                 :            :     } else {
    6584                 :          4 :         skip = ofputil_bucket_find(&ofgroup->buckets, command_bucket_id);
    6585         [ +  + ]:          4 :         if (!skip) {
    6586                 :          2 :             return OFPERR_OFPGMFC_UNKNOWN_BUCKET;
    6587                 :            :         }
    6588                 :            :     }
    6589                 :            : 
    6590                 :         10 :     ofputil_bucket_clone_list(CONST_CAST(struct ovs_list *,
    6591                 :            :                                          &new_ofgroup->buckets),
    6592                 :            :                               &ofgroup->buckets, skip);
    6593                 :            : 
    6594                 :         10 :     return 0;
    6595                 :            : }
    6596                 :            : 
    6597                 :            : /* Implements OFPGC11_MODIFY, OFPGC15_INSERT_BUCKET and
    6598                 :            :  * OFPGC15_REMOVE_BUCKET.  Returns 0 on success or an OpenFlow error code
    6599                 :            :  * on failure.
    6600                 :            :  *
    6601                 :            :  * Note that the group is re-created and then replaces the old group in
    6602                 :            :  * ofproto's ofgroup hash map. Thus, the group is never altered while users of
    6603                 :            :  * the xlate module hold a pointer to the group. */
    6604                 :            : static enum ofperr
    6605                 :         37 : modify_group_start(struct ofproto *ofproto, struct ofproto_group_mod *ogm)
    6606                 :            :     OVS_REQUIRES(ofproto_mutex)
    6607                 :            : {
    6608                 :            :     struct ofgroup *old_group;          /* Modified group. */
    6609                 :            :     struct ofgroup *new_group;
    6610                 :            :     enum ofperr error;
    6611                 :            : 
    6612                 :         37 :     old_group = ofproto_group_lookup__(ofproto, ogm->gm.group_id,
    6613                 :            :                                        OVS_VERSION_MAX);
    6614         [ +  + ]:         37 :     if (!old_group) {
    6615                 :          2 :         return OFPERR_OFPGMFC_UNKNOWN_GROUP;
    6616                 :            :     }
    6617                 :            : 
    6618         [ +  + ]:         35 :     if (old_group->type != ogm->gm.type
    6619         [ -  + ]:          1 :         && (ofproto->n_groups[ogm->gm.type]
    6620                 :          1 :             >= ofproto->ogf.max_groups[ogm->gm.type])) {
    6621                 :          0 :         return OFPERR_OFPGMFC_OUT_OF_GROUPS;
    6622                 :            :     }
    6623                 :            : 
    6624                 :         35 :     error = init_group(ofproto, &ogm->gm, ogm->version, &ogm->new_group);
    6625         [ -  + ]:         35 :     if (error) {
    6626                 :          0 :         return error;
    6627                 :            :     }
    6628                 :         35 :     new_group = ogm->new_group;
    6629                 :            : 
    6630                 :            :     /* Manipulate bucket list for bucket commands */
    6631         [ +  + ]:         35 :     if (ogm->gm.command == OFPGC15_INSERT_BUCKET) {
    6632                 :         16 :         error = copy_buckets_for_insert_bucket(old_group, new_group,
    6633                 :            :                                                ogm->gm.command_bucket_id);
    6634         [ +  + ]:         19 :     } else if (ogm->gm.command == OFPGC15_REMOVE_BUCKET) {
    6635                 :         16 :         error = copy_buckets_for_remove_bucket(old_group, new_group,
    6636                 :            :                                                ogm->gm.command_bucket_id);
    6637                 :            :     }
    6638         [ +  + ]:         35 :     if (error) {
    6639                 :          4 :         goto out;
    6640                 :            :     }
    6641                 :            : 
    6642                 :            :     /* The group creation time does not change during modification. */
    6643                 :         31 :     *CONST_CAST(long long int *, &(new_group->created)) = old_group->created;
    6644                 :         31 :     *CONST_CAST(long long int *, &(new_group->modified)) = time_msec();
    6645                 :            : 
    6646                 :         31 :     group_collection_add(&ogm->old_groups, old_group);
    6647                 :            : 
    6648                 :            :     /* Mark the old group for deletion. */
    6649                 :         31 :     versions_set_remove_version(&old_group->versions, ogm->version);
    6650                 :            :     /* Insert replacement group. */
    6651                 :         31 :     cmap_insert(&ofproto->groups, &new_group->cmap_node,
    6652                 :            :                     hash_int(new_group->group_id, 0));
    6653                 :            :     /* Transfer rules. */
    6654                 :         31 :     rule_collection_move(&new_group->rules, &old_group->rules);
    6655                 :            : 
    6656         [ +  + ]:         31 :     if (old_group->type != new_group->type) {
    6657                 :          1 :         ofproto->n_groups[old_group->type]--;
    6658                 :          1 :         ofproto->n_groups[new_group->type]++;
    6659                 :            :     }
    6660                 :         31 :     return 0;
    6661                 :            : 
    6662                 :            : out:
    6663                 :          4 :     ofproto_group_unref(new_group);
    6664                 :          4 :     return error;
    6665                 :            : }
    6666                 :            : 
    6667                 :            : /* Implements the OFPGC11_ADD_OR_MOD command which creates the group when it does not
    6668                 :            :  * exist yet and modifies it otherwise */
    6669                 :            : static enum ofperr
    6670                 :          4 : add_or_modify_group_start(struct ofproto *ofproto,
    6671                 :            :                           struct ofproto_group_mod *ogm)
    6672                 :            :     OVS_REQUIRES(ofproto_mutex)
    6673                 :            : {
    6674                 :            :     enum ofperr error;
    6675                 :            : 
    6676         [ +  + ]:          4 :     if (!ofproto_group_exists(ofproto, ogm->gm.group_id)) {
    6677                 :          2 :         error = add_group_start(ofproto, ogm);
    6678                 :            :     } else {
    6679                 :          2 :         error = modify_group_start(ofproto, ogm);
    6680                 :            :     }
    6681                 :            : 
    6682                 :          4 :     return error;
    6683                 :            : }
    6684                 :            : 
    6685                 :            : static void
    6686                 :         67 : delete_group_start(struct ofproto *ofproto, ovs_version_t version,
    6687                 :            :                    struct group_collection *groups, struct ofgroup *group)
    6688                 :            :     OVS_REQUIRES(ofproto_mutex)
    6689                 :            : {
    6690                 :            :     /* Makes flow deletion code leave the rule pointers in 'group->rules'
    6691                 :            :      * intact, so that we can later refer to the rules deleted due to the group
    6692                 :            :      * deletion.  Rule pointers will be removed from all other groups, if any,
    6693                 :            :      * so we will never try to delete the same rule twice. */
    6694                 :         67 :     group->being_deleted = true;
    6695                 :            : 
    6696                 :            :     /* Mark all the referring groups for deletion. */
    6697                 :         67 :     delete_flows_start__(ofproto, version, &group->rules);
    6698                 :         67 :     group_collection_add(groups, group);
    6699                 :         67 :     versions_set_remove_version(&group->versions, version);
    6700                 :         67 :     ofproto->n_groups[group->type]--;
    6701                 :         67 : }
    6702                 :            : 
    6703                 :            : static void
    6704                 :         98 : delete_group_finish(struct ofproto *ofproto, struct ofgroup *group)
    6705                 :            :     OVS_REQUIRES(ofproto_mutex)
    6706                 :            : {
    6707                 :            :     /* Finish deletion of all flow entries containing this group in a group
    6708                 :            :      * action. */
    6709                 :         98 :     delete_flows_finish__(ofproto, &group->rules, OFPRR_GROUP_DELETE, NULL);
    6710                 :            : 
    6711                 :            :     /* Group removal is postponed by the caller. */
    6712                 :         98 : }
    6713                 :            : 
    6714                 :            : /* Implements OFPGC11_DELETE. */
    6715                 :            : static void
    6716                 :        827 : delete_groups_start(struct ofproto *ofproto, struct ofproto_group_mod *ogm)
    6717                 :            :     OVS_REQUIRES(ofproto_mutex)
    6718                 :            : {
    6719                 :            :     struct ofgroup *group;
    6720                 :            : 
    6721         [ +  + ]:        827 :     if (ogm->gm.group_id == OFPG_ALL) {
    6722 [ +  + ][ +  + ]:        848 :         CMAP_FOR_EACH (group, cmap_node, &ofproto->groups) {
    6723         [ +  - ]:         47 :             if (versions_visible_in_version(&group->versions, ogm->version)) {
    6724                 :         47 :                 delete_group_start(ofproto, ogm->version, &ogm->old_groups,
    6725                 :            :                                    group);
    6726                 :            :             }
    6727                 :            :         }
    6728                 :            :     } else {
    6729                 :         26 :         group = ofproto_group_lookup__(ofproto, ogm->gm.group_id, ogm->version);
    6730         [ +  + ]:         26 :         if (group) {
    6731                 :         20 :             delete_group_start(ofproto, ogm->version, &ogm->old_groups, group);
    6732                 :            :         }
    6733                 :            :     }
    6734                 :        827 : }
    6735                 :            : 
    6736                 :            : static enum ofperr
    6737                 :        932 : ofproto_group_mod_start(struct ofproto *ofproto, struct ofproto_group_mod *ogm)
    6738                 :            :     OVS_REQUIRES(ofproto_mutex)
    6739                 :            : {
    6740                 :            :     enum ofperr error;
    6741                 :            : 
    6742                 :        932 :     ogm->new_group = NULL;
    6743                 :        932 :     group_collection_init(&ogm->old_groups);
    6744                 :            : 
    6745   [ +  +  +  +  :        932 :     switch (ogm->gm.command) {
                +  +  - ]
    6746                 :            :     case OFPGC11_ADD:
    6747                 :         66 :         error = add_group_start(ofproto, ogm);
    6748                 :         66 :         break;
    6749                 :            : 
    6750                 :            :     case OFPGC11_MODIFY:
    6751                 :          3 :         error = modify_group_start(ofproto, ogm);
    6752                 :          3 :         break;
    6753                 :            : 
    6754                 :            :     case OFPGC11_ADD_OR_MOD:
    6755                 :          4 :         error = add_or_modify_group_start(ofproto, ogm);
    6756                 :          4 :         break;
    6757                 :            : 
    6758                 :            :     case OFPGC11_DELETE:
    6759                 :        827 :         delete_groups_start(ofproto, ogm);
    6760                 :        827 :         error = 0;
    6761                 :        827 :         break;
    6762                 :            : 
    6763                 :            :     case OFPGC15_INSERT_BUCKET:
    6764                 :         16 :         error = modify_group_start(ofproto, ogm);
    6765                 :         16 :         break;
    6766                 :            : 
    6767                 :            :     case OFPGC15_REMOVE_BUCKET:
    6768                 :         16 :         error = modify_group_start(ofproto, ogm);
    6769                 :         16 :         break;
    6770                 :            : 
    6771                 :            :     default:
    6772         [ #  # ]:          0 :         if (ogm->gm.command > OFPGC11_DELETE) {
    6773         [ #  # ]:          0 :             VLOG_INFO_RL(&rl, "%s: Invalid group_mod command type %d",
    6774                 :            :                          ofproto->name, ogm->gm.command);
    6775                 :            :         }
    6776                 :          0 :         error = OFPERR_OFPGMFC_BAD_COMMAND;
    6777                 :          0 :         break;
    6778                 :            :     }
    6779                 :        932 :     return error;
    6780                 :            : }
    6781                 :            : 
    6782                 :            : static void
    6783                 :          1 : ofproto_group_mod_revert(struct ofproto *ofproto,
    6784                 :            :                          struct ofproto_group_mod *ogm)
    6785                 :            :     OVS_REQUIRES(ofproto_mutex)
    6786                 :            : {
    6787                 :          1 :     struct ofgroup *new_group = ogm->new_group;
    6788                 :            :     struct ofgroup *old_group;
    6789                 :            : 
    6790                 :            :     /* Restore replaced or deleted groups. */
    6791 [ -  + ][ #  # ]:          1 :     GROUP_COLLECTION_FOR_EACH (old_group, &ogm->old_groups) {
    6792                 :          0 :         ofproto->n_groups[old_group->type]++;
    6793         [ #  # ]:          0 :         if (new_group) {
    6794         [ #  # ]:          0 :             ovs_assert(group_collection_n(&ogm->old_groups) == 1);
    6795                 :            :             /* Transfer rules back. */
    6796                 :          0 :             rule_collection_move(&old_group->rules, &new_group->rules);
    6797                 :            :         } else {
    6798                 :          0 :             old_group->being_deleted = false;
    6799                 :            :             /* Revert rule deletion. */
    6800                 :          0 :             delete_flows_revert__(ofproto, &old_group->rules);
    6801                 :            :         }
    6802                 :            :         /* Restore visibility. */
    6803                 :          0 :         versions_set_remove_version(&old_group->versions,
    6804                 :            :                                     OVS_VERSION_NOT_REMOVED);
    6805                 :            :     }
    6806         [ +  - ]:          1 :     if (new_group) {
    6807                 :            :         /* Remove the new group immediately.  It was never visible to
    6808                 :            :          * lookups. */
    6809                 :          1 :         cmap_remove(&ofproto->groups, &new_group->cmap_node,
    6810                 :            :                     hash_int(new_group->group_id, 0));
    6811                 :          1 :         ofproto->n_groups[new_group->type]--;
    6812                 :          1 :         ofproto_group_unref(new_group);
    6813                 :            :     }
    6814                 :          1 : }
    6815                 :            : 
    6816                 :            : static void
    6817                 :        925 : ofproto_group_mod_finish(struct ofproto *ofproto,
    6818                 :            :                          struct ofproto_group_mod *ogm,
    6819                 :            :                          const struct openflow_mod_requester *req)
    6820                 :            :     OVS_REQUIRES(ofproto_mutex)
    6821                 :            : {
    6822                 :        925 :     struct ofgroup *new_group = ogm->new_group;
    6823                 :            :     struct ofgroup *old_group;
    6824                 :            : 
    6825 [ +  + ][ +  + ]:        925 :     if (new_group && group_collection_n(&ogm->old_groups)) {
    6826                 :            :         /* Modify a group. */
    6827         [ -  + ]:         31 :         ovs_assert(group_collection_n(&ogm->old_groups) == 1);
    6828                 :            : 
    6829                 :            :         /* XXX: OK to lose old group's stats? */
    6830                 :         31 :         ofproto->ofproto_class->group_modify(new_group);
    6831                 :            :     }
    6832                 :            : 
    6833                 :            :     /* Delete old groups. */
    6834 [ +  + ][ +  - ]:       1023 :     GROUP_COLLECTION_FOR_EACH(old_group, &ogm->old_groups) {
    6835                 :         98 :         delete_group_finish(ofproto, old_group);
    6836                 :            :     }
    6837                 :        925 :     remove_groups_postponed(&ogm->old_groups);
    6838                 :            : 
    6839         [ +  + ]:        925 :     if (req) {
    6840                 :            :         struct ofputil_requestforward rf;
    6841                 :        176 :         rf.xid = req->request->xid;
    6842                 :        176 :         rf.reason = OFPRFR_GROUP_MOD;
    6843                 :        176 :         rf.group_mod = &ogm->gm;
    6844                 :        176 :         connmgr_send_requestforward(ofproto->connmgr, req->ofconn, &rf);
    6845                 :            :     }
    6846                 :        925 : }
    6847                 :            : 
    6848                 :            : /* Delete all groups from 'ofproto'.
    6849                 :            :  *
    6850                 :            :  * This is intended for use within an ofproto provider's 'destruct'
    6851                 :            :  * function. */
    6852                 :            : void
    6853                 :        749 : ofproto_group_delete_all(struct ofproto *ofproto)
    6854                 :            :     OVS_EXCLUDED(ofproto_mutex)
    6855                 :            : {
    6856                 :            :     struct ofproto_group_mod ogm;
    6857                 :            : 
    6858                 :        749 :     ogm.gm.command = OFPGC11_DELETE;
    6859                 :        749 :     ogm.gm.group_id = OFPG_ALL;
    6860                 :            : 
    6861                 :        749 :     ovs_mutex_lock(&ofproto_mutex);
    6862                 :        749 :     ogm.version = ofproto->tables_version + 1;
    6863                 :        749 :     ofproto_group_mod_start(ofproto, &ogm);
    6864                 :        749 :     ofproto_bump_tables_version(ofproto);
    6865                 :        749 :     ofproto_group_mod_finish(ofproto, &ogm, NULL);
    6866                 :        749 :     ovs_mutex_unlock(&ofproto_mutex);
    6867                 :        749 : }
    6868                 :            : 
    6869                 :            : static enum ofperr
    6870                 :        143 : handle_group_mod(struct ofconn *ofconn, const struct ofp_header *oh)
    6871                 :            :     OVS_EXCLUDED(ofproto_mutex)
    6872                 :            : {
    6873                 :        143 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
    6874                 :            :     struct ofproto_group_mod ogm;
    6875                 :            :     enum ofperr error;
    6876                 :            : 
    6877                 :        143 :     error = reject_slave_controller(ofconn);
    6878         [ -  + ]:        143 :     if (error) {
    6879                 :          0 :         return error;
    6880                 :            :     }
    6881                 :            : 
    6882                 :        143 :     error = ofputil_decode_group_mod(oh, &ogm.gm);
    6883         [ +  + ]:        143 :     if (error) {
    6884                 :          1 :         return error;
    6885                 :            :     }
    6886                 :            : 
    6887                 :        142 :     ovs_mutex_lock(&ofproto_mutex);
    6888                 :        142 :     ogm.version = ofproto->tables_version + 1;
    6889                 :        142 :     error = ofproto_group_mod_start(ofproto, &ogm);
    6890         [ +  + ]:        142 :     if (!error) {
    6891                 :        139 :         struct openflow_mod_requester req = { ofconn, oh };
    6892                 :            : 
    6893                 :        139 :         ofproto_bump_tables_version(ofproto);
    6894                 :        139 :         ofproto_group_mod_finish(ofproto, &ogm, &req);
    6895                 :            :     }
    6896                 :        142 :     ofmonitor_flush(ofproto->connmgr);
    6897                 :        142 :     ovs_mutex_unlock(&ofproto_mutex);
    6898                 :            : 
    6899                 :        142 :     ofputil_uninit_group_mod(&ogm.gm);
    6900                 :            : 
    6901                 :        143 :     return error;
    6902                 :            : }
    6903                 :            : 
    6904                 :            : enum ofputil_table_miss
    6905                 :       5948 : ofproto_table_get_miss_config(const struct ofproto *ofproto, uint8_t table_id)
    6906                 :            : {
    6907                 :            :     enum ofputil_table_miss miss;
    6908                 :            : 
    6909                 :       5948 :     atomic_read_relaxed(&ofproto->tables[table_id].miss_config, &miss);
    6910                 :       5948 :     return miss;
    6911                 :            : }
    6912                 :            : 
    6913                 :            : static void
    6914                 :       1785 : table_mod__(struct oftable *oftable,
    6915                 :            :             const struct ofputil_table_mod *tm)
    6916                 :            : {
    6917         [ +  + ]:       1785 :     if (tm->miss == OFPUTIL_TABLE_MISS_DEFAULT) {
    6918                 :            :         /* This is how an OFPT_TABLE_MOD decodes if it doesn't specify any
    6919                 :            :          * table-miss configuration (because the protocol used doesn't have
    6920                 :            :          * such a concept), so there's nothing to do. */
    6921                 :            :     } else {
    6922                 :       1778 :         atomic_store_relaxed(&oftable->miss_config, tm->miss);
    6923                 :            :     }
    6924                 :            : 
    6925                 :       1785 :     unsigned int new_eviction = oftable->eviction;
    6926         [ +  + ]:       1785 :     if (tm->eviction == OFPUTIL_TABLE_EVICTION_ON) {
    6927                 :          2 :         new_eviction |= EVICTION_OPENFLOW;
    6928         [ +  + ]:       1783 :     } else if (tm->eviction == OFPUTIL_TABLE_EVICTION_OFF) {
    6929                 :          1 :         new_eviction &= ~EVICTION_OPENFLOW;
    6930                 :            :     }
    6931                 :            : 
    6932         [ +  + ]:       1785 :     if (new_eviction != oftable->eviction) {
    6933                 :          3 :         ovs_mutex_lock(&ofproto_mutex);
    6934                 :          3 :         oftable_configure_eviction(oftable, new_eviction,
    6935                 :          3 :                                    oftable->eviction_fields,
    6936                 :            :                                    oftable->n_eviction_fields);
    6937                 :          3 :         ovs_mutex_unlock(&ofproto_mutex);
    6938                 :            :     }
    6939                 :            : 
    6940         [ +  + ]:       1785 :     if (tm->vacancy != OFPUTIL_TABLE_VACANCY_DEFAULT) {
    6941                 :          7 :         ovs_mutex_lock(&ofproto_mutex);
    6942                 :          7 :         oftable->vacancy_down = tm->table_vacancy.vacancy_down;
    6943                 :          7 :         oftable->vacancy_up = tm->table_vacancy.vacancy_up;
    6944         [ +  + ]:          7 :         if (tm->vacancy == OFPUTIL_TABLE_VACANCY_OFF) {
    6945                 :          4 :             oftable->vacancy_event = 0;
    6946         [ +  - ]:          3 :         } else if (!oftable->vacancy_event) {
    6947                 :          3 :             uint8_t vacancy = oftable_vacancy(oftable);
    6948         [ +  + ]:          3 :             oftable->vacancy_event = (vacancy < oftable->vacancy_up
    6949                 :            :                                       ? OFPTR_VACANCY_UP
    6950                 :            :                                       : OFPTR_VACANCY_DOWN);
    6951                 :            :         }
    6952                 :          7 :         ovs_mutex_unlock(&ofproto_mutex);
    6953                 :            :     }
    6954                 :       1785 : }
    6955                 :            : 
    6956                 :            : static enum ofperr
    6957                 :         14 : table_mod(struct ofproto *ofproto, const struct ofputil_table_mod *tm)
    6958                 :            : {
    6959         [ -  + ]:         14 :     if (!check_table_id(ofproto, tm->table_id)) {
    6960                 :          0 :         return OFPERR_OFPTMFC_BAD_TABLE;
    6961                 :            :     }
    6962                 :            : 
    6963                 :            :     /* Don't allow the eviction flags to be changed (except to the only fixed
    6964                 :            :      * value that OVS supports).  OF1.4 says this is normal: "The
    6965                 :            :      * OFPTMPT_EVICTION property usually cannot be modified using a
    6966                 :            :      * OFP_TABLE_MOD request, because the eviction mechanism is switch
    6967                 :            :      * defined". */
    6968         [ -  + ]:         14 :     if (tm->eviction_flags != UINT32_MAX
    6969         [ #  # ]:          0 :         && tm->eviction_flags != OFPROTO_EVICTION_FLAGS) {
    6970                 :          0 :         return OFPERR_OFPTMFC_BAD_CONFIG;
    6971                 :            :     }
    6972                 :            : 
    6973         [ +  + ]:         14 :     if (tm->table_id == OFPTT_ALL) {
    6974                 :            :         struct oftable *oftable;
    6975         [ +  + ]:       1792 :         OFPROTO_FOR_EACH_TABLE (oftable, ofproto) {
    6976         [ +  + ]:       1785 :             if (!(oftable->flags & (OFTABLE_HIDDEN | OFTABLE_READONLY))) {
    6977                 :       1778 :                 table_mod__(oftable, tm);
    6978                 :            :             }
    6979                 :            :         }
    6980                 :            :     } else {
    6981                 :          7 :         struct oftable *oftable = &ofproto->tables[tm->table_id];
    6982         [ -  + ]:          7 :         if (oftable->flags & OFTABLE_READONLY) {
    6983                 :          0 :             return OFPERR_OFPTMFC_EPERM;
    6984                 :            :         }
    6985                 :          7 :         table_mod__(oftable, tm);
    6986                 :            :     }
    6987                 :            : 
    6988                 :         14 :     return 0;
    6989                 :            : }
    6990                 :            : 
    6991                 :            : static enum ofperr
    6992                 :         14 : handle_table_mod(struct ofconn *ofconn, const struct ofp_header *oh)
    6993                 :            : {
    6994                 :         14 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
    6995                 :            :     struct ofputil_table_mod tm;
    6996                 :            :     enum ofperr error;
    6997                 :            : 
    6998                 :         14 :     error = reject_slave_controller(ofconn);
    6999         [ -  + ]:         14 :     if (error) {
    7000                 :          0 :         return error;
    7001                 :            :     }
    7002                 :            : 
    7003                 :         14 :     error = ofputil_decode_table_mod(oh, &tm);
    7004         [ -  + ]:         14 :     if (error) {
    7005                 :          0 :         return error;
    7006                 :            :     }
    7007                 :            : 
    7008                 :         14 :     return table_mod(ofproto, &tm);
    7009                 :            : }
    7010                 :            : 
    7011                 :            : /* Free resources that may be allocated by ofproto_flow_mod_init(). */
    7012                 :            : void
    7013                 :      39578 : ofproto_flow_mod_uninit(struct ofproto_flow_mod *ofm)
    7014                 :            : {
    7015         [ +  + ]:      39578 :     if (ofm->temp_rule) {
    7016                 :         31 :         ofproto_rule_unref(ofm->temp_rule);
    7017                 :         31 :         ofm->temp_rule = NULL;
    7018                 :            :     }
    7019         [ +  + ]:      39578 :     if (ofm->criteria.version != OVS_VERSION_NOT_REMOVED) {
    7020                 :       7465 :         rule_criteria_destroy(&ofm->criteria);
    7021                 :            :     }
    7022         [ +  + ]:      39578 :     if (ofm->conjs) {
    7023                 :         36 :         free(ofm->conjs);
    7024                 :         36 :         ofm->conjs = NULL;
    7025                 :         36 :         ofm->n_conjs = 0;
    7026                 :            :     }
    7027                 :      39578 : }
    7028                 :            : 
    7029                 :            : static enum ofperr
    7030                 :      38929 : ofproto_flow_mod_init(struct ofproto *ofproto, struct ofproto_flow_mod *ofm,
    7031                 :            :                       const struct ofputil_flow_mod *fm)
    7032                 :            :     OVS_EXCLUDED(ofproto_mutex)
    7033                 :            : {
    7034                 :            :     enum ofperr error;
    7035                 :            : 
    7036                 :            :     /* Forward flow mod fields we need later. */
    7037                 :      38929 :     ofm->command = fm->command;
    7038                 :      38929 :     ofm->modify_cookie = fm->modify_cookie;
    7039                 :            : 
    7040                 :      77858 :     ofm->modify_may_add_flow = (fm->new_cookie != OVS_BE64_MAX
    7041 [ +  + ][ +  + ]:      38929 :                                 && fm->cookie_mask == htonll(0));
    7042                 :            : 
    7043                 :            :     /* Initialize state needed by ofproto_flow_mod_uninit(). */
    7044                 :      38929 :     ofm->temp_rule = NULL;
    7045                 :      38929 :     ofm->criteria.version = OVS_VERSION_NOT_REMOVED;
    7046                 :      38929 :     ofm->conjs = NULL;
    7047                 :      38929 :     ofm->n_conjs = 0;
    7048                 :            : 
    7049                 :      38929 :     bool check_buffer_id = false;
    7050                 :            : 
    7051   [ +  +  +  +  :      38929 :     switch (ofm->command) {
                   +  - ]
    7052                 :            :     case OFPFC_ADD:
    7053                 :      31464 :         check_buffer_id = true;
    7054                 :      31464 :         error = add_flow_init(ofproto, ofm, fm);
    7055                 :      31464 :         break;
    7056                 :            :     case OFPFC_MODIFY:
    7057                 :         39 :         check_buffer_id = true;
    7058                 :         39 :         error = modify_flows_init_loose(ofproto, ofm, fm);
    7059                 :         39 :         break;
    7060                 :            :     case OFPFC_MODIFY_STRICT:
    7061                 :        509 :         check_buffer_id = true;
    7062                 :        509 :         error = modify_flow_init_strict(ofproto, ofm, fm);
    7063                 :        509 :         break;
    7064                 :            :     case OFPFC_DELETE:
    7065                 :        730 :         error = delete_flows_init_loose(ofproto, ofm, fm);
    7066                 :        730 :         break;
    7067                 :            :     case OFPFC_DELETE_STRICT:
    7068                 :       6187 :         error = delete_flows_init_strict(ofproto, ofm, fm);
    7069                 :       6187 :         break;
    7070                 :            :     default:
    7071                 :          0 :         error = OFPERR_OFPFMFC_BAD_COMMAND;
    7072                 :          0 :         break;
    7073                 :            :     }
    7074 [ +  + ][ +  + ]:      38929 :     if (!error && check_buffer_id && fm->buffer_id != UINT32_MAX) {
                 [ -  + ]
    7075                 :          0 :         error = OFPERR_OFPBRC_BUFFER_UNKNOWN;
    7076                 :            :     }
    7077                 :            : 
    7078         [ +  + ]:      38929 :     if (error) {
    7079                 :        560 :         ofproto_flow_mod_uninit(ofm);
    7080                 :            :     }
    7081                 :      38929 :     return error;
    7082                 :            : }
    7083                 :            : 
    7084                 :            : static enum ofperr
    7085                 :      38349 : ofproto_flow_mod_start(struct ofproto *ofproto, struct ofproto_flow_mod *ofm)
    7086                 :            :     OVS_REQUIRES(ofproto_mutex)
    7087                 :            : {
    7088                 :            :     enum ofperr error;
    7089                 :            : 
    7090                 :      38349 :     rule_collection_init(&ofm->old_rules);
    7091                 :      38349 :     rule_collection_init(&ofm->new_rules);
    7092                 :            : 
    7093   [ +  +  +  +  :      38349 :     switch (ofm->command) {
                   +  - ]
    7094                 :            :     case OFPFC_ADD:
    7095                 :      30890 :         error = add_flow_start(ofproto, ofm);
    7096                 :      30890 :         break;
    7097                 :            :     case OFPFC_MODIFY:
    7098                 :         37 :         error = modify_flows_start_loose(ofproto, ofm);
    7099                 :         37 :         break;
    7100                 :            :     case OFPFC_MODIFY_STRICT:
    7101                 :        509 :         error = modify_flow_start_strict(ofproto, ofm);
    7102                 :        509 :         break;
    7103                 :            :     case OFPFC_DELETE:
    7104                 :        726 :         error = delete_flows_start_loose(ofproto, ofm);
    7105                 :        726 :         break;
    7106                 :            :     case OFPFC_DELETE_STRICT:
    7107                 :       6187 :         error = delete_flow_start_strict(ofproto, ofm);
    7108                 :       6187 :         break;
    7109                 :            :     default:
    7110                 :          0 :         OVS_NOT_REACHED();
    7111                 :            :     }
    7112                 :            :     /* Release resources not needed after start. */
    7113                 :      38349 :     ofproto_flow_mod_uninit(ofm);
    7114                 :            : 
    7115         [ +  + ]:      38349 :     if (error) {
    7116                 :         10 :         rule_collection_destroy(&ofm->old_rules);
    7117                 :         10 :         rule_collection_destroy(&ofm->new_rules);
    7118                 :            :     }
    7119                 :      38349 :     return error;
    7120                 :            : }
    7121                 :            : 
    7122                 :            : static void
    7123                 :          1 : ofproto_flow_mod_revert(struct ofproto *ofproto, struct ofproto_flow_mod *ofm)
    7124                 :            :     OVS_REQUIRES(ofproto_mutex)
    7125                 :            : {
    7126   [ +  -  -  - ]:          1 :     switch (ofm->command) {
    7127                 :            :     case OFPFC_ADD:
    7128                 :          1 :         add_flow_revert(ofproto, ofm);
    7129                 :          1 :         break;
    7130                 :            : 
    7131                 :            :     case OFPFC_MODIFY:
    7132                 :            :     case OFPFC_MODIFY_STRICT:
    7133                 :          0 :         modify_flows_revert(ofproto, ofm);
    7134                 :          0 :         break;
    7135                 :            : 
    7136                 :            :     case OFPFC_DELETE:
    7137                 :            :     case OFPFC_DELETE_STRICT:
    7138                 :          0 :         delete_flows_revert(ofproto, ofm);
    7139                 :          0 :         break;
    7140                 :            : 
    7141                 :            :     default:
    7142                 :          0 :         break;
    7143                 :            :     }
    7144                 :          1 :     rule_collection_destroy(&ofm->old_rules);
    7145                 :          1 :     rule_collection_destroy(&ofm->new_rules);
    7146                 :          1 : }
    7147                 :            : 
    7148                 :            : static void
    7149                 :      38338 : ofproto_flow_mod_finish(struct ofproto *ofproto,
    7150                 :            :                         struct ofproto_flow_mod *ofm,
    7151                 :            :                         const struct openflow_mod_requester *req)
    7152                 :            :     OVS_REQUIRES(ofproto_mutex)
    7153                 :            : {
    7154   [ +  +  +  - ]:      38338 :     switch (ofm->command) {
    7155                 :            :     case OFPFC_ADD:
    7156                 :      30881 :         add_flow_finish(ofproto, ofm, req);
    7157                 :      30881 :         break;
    7158                 :            : 
    7159                 :            :     case OFPFC_MODIFY:
    7160                 :            :     case OFPFC_MODIFY_STRICT:
    7161                 :        544 :         modify_flows_finish(ofproto, ofm, req);
    7162                 :        544 :         break;
    7163                 :            : 
    7164                 :            :     case OFPFC_DELETE:
    7165                 :            :     case OFPFC_DELETE_STRICT:
    7166                 :       6913 :         delete_flows_finish(ofproto, ofm, req);
    7167                 :       6913 :         break;
    7168                 :            : 
    7169                 :            :     default:
    7170                 :          0 :         break;
    7171                 :            :     }
    7172                 :            : 
    7173                 :      38338 :     rule_collection_destroy(&ofm->old_rules);
    7174                 :      38338 :     rule_collection_destroy(&ofm->new_rules);
    7175                 :            : 
    7176         [ +  + ]:      38338 :     if (req) {
    7177                 :      32869 :         ofconn_report_flow_mod(req->ofconn, ofm->command);
    7178                 :            :     }
    7179                 :      38338 : }
    7180                 :            : 
    7181                 :            : /* Commit phases (all while locking ofproto_mutex):
    7182                 :            :  *
    7183                 :            :  * 1. Begin: Gather resources and make changes visible in the next version.
    7184                 :            :  *           - Mark affected rules for removal in the next version.
    7185                 :            :  *           - Create new replacement rules, make visible in the next
    7186                 :            :  *             version.
    7187                 :            :  *           - Do not send any events or notifications.
    7188                 :            :  *
    7189                 :            :  * 2. Revert: Fail if any errors are found.  After this point no errors are
    7190                 :            :  * possible.  No visible changes were made, so rollback is minimal (remove
    7191                 :            :  * added invisible rules, restore visibility of rules marked for removal).
    7192                 :            :  *
    7193                 :            :  * 3. Finish: Make the changes visible for lookups. Insert replacement rules to
    7194                 :            :  * the ofproto provider. Remove replaced and deleted rules from ofproto data
    7195                 :            :  * structures, and Schedule postponed removal of deleted rules from the
    7196                 :            :  * classifier.  Send notifications, buffered packets, etc.
    7197                 :            :  */
    7198                 :            : static enum ofperr
    7199                 :        118 : do_bundle_commit(struct ofconn *ofconn, uint32_t id, uint16_t flags)
    7200                 :            : {
    7201                 :        118 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
    7202                 :        118 :     ovs_version_t version = ofproto->tables_version + 1;
    7203                 :            :     struct ofp_bundle *bundle;
    7204                 :            :     struct ofp_bundle_entry *be;
    7205                 :            :     enum ofperr error;
    7206                 :            : 
    7207                 :        118 :     bundle = ofconn_get_bundle(ofconn, id);
    7208                 :            : 
    7209         [ +  + ]:        118 :     if (!bundle) {
    7210                 :          2 :         return OFPERR_OFPBFC_BAD_ID;
    7211                 :            :     }
    7212         [ +  + ]:        116 :     if (bundle->flags != flags) {
    7213                 :          2 :         error = OFPERR_OFPBFC_BAD_FLAGS;
    7214                 :            :     } else {
    7215                 :        114 :         bool prev_is_port_mod = false;
    7216                 :            : 
    7217                 :        114 :         error = 0;
    7218                 :        114 :         ovs_mutex_lock(&ofproto_mutex);
    7219                 :            : 
    7220                 :            :         /* 1. Begin. */
    7221         [ +  + ]:        797 :         LIST_FOR_EACH (be, node, &bundle->msg_list) {
    7222         [ -  + ]:        688 :             if (be->type == OFPTYPE_PORT_MOD) {
    7223                 :            :                 /* Our port mods are not atomic. */
    7224         [ #  # ]:          0 :                 if (flags & OFPBF_ATOMIC) {
    7225                 :          0 :                     error = OFPERR_OFPBFC_MSG_FAILED;
    7226                 :            :                 } else {
    7227                 :          0 :                     prev_is_port_mod = true;
    7228                 :          0 :                     error = port_mod_start(ofconn, &be->opm.pm, &be->opm.port);
    7229                 :            :                 }
    7230                 :            :             } else {
    7231                 :            :                 /* Flow & group mods between port mods are applied as a single
    7232                 :            :                  * version, but the versions are published only after we know
    7233                 :            :                  * the commit is successful. */
    7234         [ -  + ]:        688 :                 if (prev_is_port_mod) {
    7235                 :          0 :                     prev_is_port_mod = false;
    7236                 :          0 :                     ++version;
    7237                 :            :                 }
    7238         [ +  + ]:        688 :                 if (be->type == OFPTYPE_FLOW_MOD) {
    7239                 :            :                     /* Store the version in which the changes should take
    7240                 :            :                      * effect. */
    7241                 :        647 :                     be->ofm.version = version;
    7242                 :        647 :                     error = ofproto_flow_mod_start(ofproto, &be->ofm);
    7243         [ +  - ]:         41 :                 } else if (be->type == OFPTYPE_GROUP_MOD) {
    7244                 :            :                     /* Store the version in which the changes should take
    7245                 :            :                      * effect. */
    7246                 :         41 :                     be->ogm.version = version;
    7247                 :         41 :                     error = ofproto_group_mod_start(ofproto, &be->ogm);
    7248                 :            :                 } else {
    7249                 :          0 :                     OVS_NOT_REACHED();
    7250                 :            :                 }
    7251                 :            :             }
    7252         [ +  + ]:        688 :             if (error) {
    7253                 :          5 :                 break;
    7254                 :            :             }
    7255                 :            :         }
    7256                 :            : 
    7257         [ +  + ]:        114 :         if (error) {
    7258                 :            :             /* Send error referring to the original message. */
    7259         [ +  - ]:          5 :             if (error) {
    7260                 :          5 :                 ofconn_send_error(ofconn, be->ofp_msg, error);
    7261                 :          5 :                 error = OFPERR_OFPBFC_MSG_FAILED;
    7262                 :            :             }
    7263                 :            : 
    7264                 :            :             /* 2. Revert.  Undo all the changes made above. */
    7265         [ +  + ]:          7 :             LIST_FOR_EACH_REVERSE_CONTINUE(be, node, &bundle->msg_list) {
    7266         [ +  + ]:          2 :                 if (be->type == OFPTYPE_FLOW_MOD) {
    7267                 :          1 :                     ofproto_flow_mod_revert(ofproto, &be->ofm);
    7268         [ +  - ]:          1 :                 } else if (be->type == OFPTYPE_GROUP_MOD) {
    7269                 :          1 :                     ofproto_group_mod_revert(ofproto, &be->ogm);
    7270                 :            :                 }
    7271                 :            : 
    7272                 :            :                 /* Nothing needs to be reverted for a port mod. */
    7273                 :            :             }
    7274                 :            :         } else {
    7275                 :            :             /* 4. Finish. */
    7276         [ +  + ]:        790 :             LIST_FOR_EACH (be, node, &bundle->msg_list) {
    7277         [ -  + ]:        681 :                 if (be->type == OFPTYPE_PORT_MOD) {
    7278                 :            :                     /* Perform the actual port mod. This is not atomic, i.e.,
    7279                 :            :                      * the effects will be immediately seen by upcall
    7280                 :            :                      * processing regardless of the lookup version.  It should
    7281                 :            :                      * be noted that port configuration changes can originate
    7282                 :            :                      * also from OVSDB changes asynchronously to all upcall
    7283                 :            :                      * processing. */
    7284                 :          0 :                     port_mod_finish(ofconn, &be->opm.pm, be->opm.port);
    7285                 :            :                 } else {
    7286                 :       1362 :                     struct openflow_mod_requester req = { ofconn,
    7287                 :        681 :                                                           be->ofp_msg };
    7288         [ +  + ]:        681 :                     if (be->type == OFPTYPE_FLOW_MOD) {
    7289                 :            :                         /* Bump the lookup version to the one of the current
    7290                 :            :                          * message.  This makes all the changes in the bundle
    7291                 :            :                          * at this version visible to lookups at once. */
    7292         [ +  + ]:        644 :                         if (ofproto->tables_version < be->ofm.version) {
    7293                 :         78 :                             ofproto->tables_version = be->ofm.version;
    7294                 :         78 :                             ofproto->ofproto_class->set_tables_version(
    7295                 :            :                                 ofproto, ofproto->tables_version);
    7296                 :            :                         }
    7297                 :            : 
    7298                 :        644 :                         ofproto_flow_mod_finish(ofproto, &be->ofm, &req);
    7299         [ +  - ]:         37 :                     } else if (be->type == OFPTYPE_GROUP_MOD) {
    7300                 :            :                         /* Bump the lookup version to the one of the current
    7301                 :            :                          * message.  This makes all the changes in the bundle
    7302                 :            :                          * at this version visible to lookups at once. */
    7303         [ +  + ]:         37 :                         if (ofproto->tables_version < be->ogm.version) {
    7304                 :         31 :                             ofproto->tables_version = be->ogm.version;
    7305                 :         31 :                             ofproto->ofproto_class->set_tables_version(
    7306                 :            :                                 ofproto, ofproto->tables_version);
    7307                 :            :                         }
    7308                 :            : 
    7309                 :        681 :                         ofproto_group_mod_finish(ofproto, &be->ogm, &req);
    7310                 :            :                     }
    7311                 :            :                 }
    7312                 :            :             }
    7313                 :            :         }
    7314                 :            : 
    7315                 :        114 :         ofmonitor_flush(ofproto->connmgr);
    7316                 :        114 :         ovs_mutex_unlock(&ofproto_mutex);
    7317                 :            :     }
    7318                 :            : 
    7319                 :            :     /* The bundle is discarded regardless the outcome. */
    7320                 :        116 :     ofp_bundle_remove__(ofconn, bundle, !error);
    7321                 :        116 :     return error;
    7322                 :            : }
    7323                 :            : 
    7324                 :            : static enum ofperr
    7325                 :        260 : handle_bundle_control(struct ofconn *ofconn, const struct ofp_header *oh)
    7326                 :            : {
    7327                 :            :     struct ofputil_bundle_ctrl_msg bctrl;
    7328                 :            :     struct ofputil_bundle_ctrl_msg reply;
    7329                 :            :     struct ofpbuf *buf;
    7330                 :            :     enum ofperr error;
    7331                 :            : 
    7332                 :        260 :     error = reject_slave_controller(ofconn);
    7333         [ -  + ]:        260 :     if (error) {
    7334                 :          0 :         return error;
    7335                 :            :     }
    7336                 :            : 
    7337                 :        260 :     error = ofputil_decode_bundle_ctrl(oh, &bctrl);
    7338         [ -  + ]:        260 :     if (error) {
    7339                 :          0 :         return error;
    7340                 :            :     }
    7341                 :        260 :     reply.flags = 0;
    7342                 :        260 :     reply.bundle_id = bctrl.bundle_id;
    7343                 :            : 
    7344   [ +  +  +  +  :        260 :     switch (bctrl.type) {
                   -  - ]
    7345                 :            :         case OFPBCT_OPEN_REQUEST:
    7346                 :        129 :         error = ofp_bundle_open(ofconn, bctrl.bundle_id, bctrl.flags);
    7347                 :        129 :         reply.type = OFPBCT_OPEN_REPLY;
    7348                 :        129 :         break;
    7349                 :            :     case OFPBCT_CLOSE_REQUEST:
    7350                 :          8 :         error = ofp_bundle_close(ofconn, bctrl.bundle_id, bctrl.flags);
    7351                 :          8 :         reply.type = OFPBCT_CLOSE_REPLY;
    7352                 :          8 :         break;
    7353                 :            :     case OFPBCT_COMMIT_REQUEST:
    7354                 :        118 :         error = do_bundle_commit(ofconn, bctrl.bundle_id, bctrl.flags);
    7355                 :        118 :         reply.type = OFPBCT_COMMIT_REPLY;
    7356                 :        118 :         break;
    7357                 :            :     case OFPBCT_DISCARD_REQUEST:
    7358                 :          5 :         error = ofp_bundle_discard(ofconn, bctrl.bundle_id);
    7359                 :          5 :         reply.type = OFPBCT_DISCARD_REPLY;
    7360                 :          5 :         break;
    7361                 :            : 
    7362                 :            :     case OFPBCT_OPEN_REPLY:
    7363                 :            :     case OFPBCT_CLOSE_REPLY:
    7364                 :            :     case OFPBCT_COMMIT_REPLY:
    7365                 :            :     case OFPBCT_DISCARD_REPLY:
    7366                 :          0 :         return OFPERR_OFPBFC_BAD_TYPE;
    7367                 :            :         break;
    7368                 :            :     }
    7369                 :            : 
    7370         [ +  + ]:        260 :     if (!error) {
    7371                 :        241 :         buf = ofputil_encode_bundle_ctrl_reply(oh, &reply);
    7372                 :        241 :         ofconn_send_reply(ofconn, buf);
    7373                 :            :     }
    7374                 :        260 :     return error;
    7375                 :            : }
    7376                 :            : 
    7377                 :            : static enum ofperr
    7378                 :        711 : handle_bundle_add(struct ofconn *ofconn, const struct ofp_header *oh)
    7379                 :            :     OVS_EXCLUDED(ofproto_mutex)
    7380                 :            : {
    7381                 :        711 :     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
    7382                 :            :     enum ofperr error;
    7383                 :            :     struct ofputil_bundle_add_msg badd;
    7384                 :            :     struct ofp_bundle_entry *bmsg;
    7385                 :            :     enum ofptype type;
    7386                 :            : 
    7387                 :        711 :     error = reject_slave_controller(ofconn);
    7388         [ -  + ]:        711 :     if (error) {
    7389                 :          0 :         return error;
    7390                 :            :     }
    7391                 :            : 
    7392                 :        711 :     error = ofputil_decode_bundle_add(oh, &badd, &type);
    7393         [ -  + ]:        711 :     if (error) {
    7394                 :          0 :         return error;
    7395                 :            :     }
    7396                 :            : 
    7397                 :        711 :     bmsg = ofp_bundle_entry_alloc(type, badd.msg);
    7398                 :            : 
    7399         [ -  + ]:        711 :     if (type == OFPTYPE_PORT_MOD) {
    7400                 :          0 :         error = ofputil_decode_port_mod(badd.msg, &bmsg->opm.pm, false);
    7401         [ +  + ]:        711 :     } else if (type == OFPTYPE_FLOW_MOD) {
    7402                 :            :         struct ofputil_flow_mod fm;
    7403                 :            :         struct ofpbuf ofpacts;
    7404                 :            :         uint64_t ofpacts_stub[1024 / 8];
    7405                 :            : 
    7406                 :        669 :         ofpbuf_use_stub(&ofpacts, ofpacts_stub, sizeof ofpacts_stub);
    7407                 :        669 :         error = ofputil_decode_flow_mod(&fm, badd.msg,
    7408                 :            :                                         ofconn_get_protocol(ofconn),
    7409                 :            :                                         &ofpacts,
    7410                 :        669 :                                         u16_to_ofp(ofproto->max_ports),
    7411                 :        669 :                                         ofproto->n_tables);
    7412         [ +  - ]:        669 :         if (!error) {
    7413                 :        669 :             error = ofproto_flow_mod_init(ofproto, &bmsg->ofm, &fm);
    7414                 :            :         }
    7415                 :        669 :         ofpbuf_uninit(&ofpacts);
    7416         [ +  - ]:         42 :     } else if (type == OFPTYPE_GROUP_MOD) {
    7417                 :         42 :         error = ofputil_decode_group_mod(badd.msg, &bmsg->ogm.gm);
    7418                 :            :     } else {
    7419                 :          0 :         OVS_NOT_REACHED();
    7420                 :            :     }
    7421                 :            : 
    7422         [ +  + ]:        711 :     if (!error) {
    7423                 :        708 :         error = ofp_bundle_add_message(ofconn, badd.bundle_id, badd.flags,
    7424                 :            :                                        bmsg);
    7425                 :            :     }
    7426                 :            : 
    7427         [ +  + ]:        711 :     if (error) {
    7428                 :          3 :         ofp_bundle_entry_free(bmsg);
    7429                 :            :     }
    7430                 :            : 
    7431                 :        711 :     return error;
    7432                 :            : }
    7433                 :            : 
    7434                 :            : static enum ofperr
    7435                 :         59 : handle_tlv_table_mod(struct ofconn *ofconn, const struct ofp_header *oh)
    7436                 :            : {
    7437                 :            :     struct ofputil_tlv_table_mod ttm;
    7438                 :            :     enum ofperr error;
    7439                 :            : 
    7440                 :         59 :     error = reject_slave_controller(ofconn);
    7441         [ -  + ]:         59 :     if (error) {
    7442                 :          0 :         return error;
    7443                 :            :     }
    7444                 :            : 
    7445                 :         59 :     error = ofputil_decode_tlv_table_mod(oh, &ttm);
    7446         [ -  + ]:         59 :     if (error) {
    7447                 :          0 :         return error;
    7448                 :            :     }
    7449                 :            : 
    7450                 :         59 :     error = tun_metadata_table_mod(&ttm);
    7451                 :            : 
    7452                 :         59 :     ofputil_uninit_tlv_table(&ttm.mappings);
    7453                 :         59 :     return error;
    7454                 :            : }
    7455                 :            : 
    7456                 :            : static enum ofperr
    7457                 :         46 : handle_tlv_table_request(struct ofconn *ofconn, const struct ofp_header *oh)
    7458                 :            : {
    7459                 :            :     struct ofputil_tlv_table_reply ttr;
    7460                 :            :     struct ofpbuf *b;
    7461                 :            : 
    7462                 :         46 :     tun_metadata_table_request(&ttr);
    7463                 :         46 :     b = ofputil_encode_tlv_table_reply(oh, &ttr);
    7464                 :         46 :     ofputil_uninit_tlv_table(&ttr.mappings);
    7465                 :            : 
    7466                 :         46 :     ofconn_send_reply(ofconn, b);
    7467                 :         46 :     return 0;
    7468                 :            : }
    7469                 :            : 
    7470                 :            : static enum ofperr
    7471                 :      52719 : handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
    7472                 :            :     OVS_EXCLUDED(ofproto_mutex)
    7473                 :            : {
    7474                 :      52719 :     const struct ofp_header *oh = msg->data;
    7475                 :            :     enum ofptype type;
    7476                 :            :     enum ofperr error;
    7477                 :            : 
    7478                 :      52719 :     error = ofptype_decode(&type, oh);
    7479         [ -  + ]:      52719 :     if (error) {
    7480                 :          0 :         return error;
    7481                 :            :     }
    7482 [ +  + ][ +  + ]:      52719 :     if (oh->version >= OFP13_VERSION && ofpmsg_is_stat_request(oh)
    7483         [ -  + ]:        165 :         && ofpmp_more(oh)) {
    7484                 :            :         /* We have no buffer implementation for multipart requests.
    7485                 :            :          * Report overflow for requests which consists of multiple
    7486                 :            :          * messages. */
    7487                 :          0 :         return OFPERR_OFPBRC_MULTIPART_BUFFER_OVERFLOW;
    7488                 :            :     }
    7489                 :            : 
    7490   [ +  +  +  +  :      52719 :     switch (type) {
          +  +  +  +  +  
          -  +  +  +  +  
          +  +  +  -  -  
          +  +  +  -  +  
          +  +  +  +  +  
          +  +  +  -  -  
          +  +  +  +  +  
          +  +  +  +  +  
                      - ]
    7491                 :            :         /* OpenFlow requests. */
    7492                 :            :     case OFPTYPE_ECHO_REQUEST:
    7493                 :          1 :         return handle_echo_request(ofconn, oh);
    7494                 :            : 
    7495                 :            :     case OFPTYPE_FEATURES_REQUEST:
    7496                 :         70 :         return handle_features_request(ofconn, oh);
    7497                 :            : 
    7498                 :            :     case OFPTYPE_GET_CONFIG_REQUEST:
    7499                 :        282 :         return handle_get_config_request(ofconn, oh);
    7500                 :            : 
    7501                 :            :     case OFPTYPE_SET_CONFIG:
    7502                 :        215 :         return handle_set_config(ofconn, oh);
    7503                 :            : 
    7504                 :            :     case OFPTYPE_PACKET_OUT:
    7505                 :       1562 :         return handle_packet_out(ofconn, oh);
    7506                 :            : 
    7507                 :            :     case OFPTYPE_PORT_MOD:
    7508                 :         39 :         return handle_port_mod(ofconn, oh);
    7509                 :            : 
    7510                 :            :     case OFPTYPE_FLOW_MOD:
    7511                 :      32791 :         return handle_flow_mod(ofconn, oh);
    7512                 :            : 
    7513                 :            :     case OFPTYPE_GROUP_MOD:
    7514                 :        143 :         return handle_group_mod(ofconn, oh);
    7515                 :            : 
    7516                 :            :     case OFPTYPE_TABLE_MOD:
    7517                 :         14 :         return handle_table_mod(ofconn, oh);
    7518                 :            : 
    7519                 :            :     case OFPTYPE_METER_MOD:
    7520                 :          0 :         return handle_meter_mod(ofconn, oh);
    7521                 :            : 
    7522                 :            :     case OFPTYPE_BARRIER_REQUEST:
    7523                 :      15031 :         return handle_barrier_request(ofconn, oh);
    7524                 :            : 
    7525                 :            :     case OFPTYPE_ROLE_REQUEST:
    7526                 :         24 :         return handle_role_request(ofconn, oh);
    7527                 :            : 
    7528                 :            :         /* OpenFlow replies. */
    7529                 :            :     case OFPTYPE_ECHO_REPLY:
    7530                 :         13 :         return 0;
    7531                 :            : 
    7532                 :            :         /* Nicira extension requests. */
    7533                 :            :     case OFPTYPE_FLOW_MOD_TABLE_ID:
    7534                 :         99 :         return handle_nxt_flow_mod_table_id(ofconn, oh);
    7535                 :            : 
    7536                 :            :     case OFPTYPE_SET_FLOW_FORMAT:
    7537                 :        347 :         return handle_nxt_set_flow_format(ofconn, oh);
    7538                 :            : 
    7539                 :            :     case OFPTYPE_SET_PACKET_IN_FORMAT:
    7540                 :        211 :         return handle_nxt_set_packet_in_format(ofconn, oh);
    7541                 :            : 
    7542                 :            :     case OFPTYPE_SET_CONTROLLER_ID:
    7543                 :          8 :         return handle_nxt_set_controller_id(ofconn, oh);
    7544                 :            : 
    7545                 :            :     case OFPTYPE_FLOW_AGE:
    7546                 :            :         /* Nothing to do. */
    7547                 :          0 :         return 0;
    7548                 :            : 
    7549                 :            :     case OFPTYPE_FLOW_MONITOR_CANCEL:
    7550                 :          0 :         return handle_flow_monitor_cancel(ofconn, oh);
    7551                 :            : 
    7552                 :            :     case OFPTYPE_SET_ASYNC_CONFIG:
    7553                 :          8 :         return handle_nxt_set_async_config(ofconn, oh);
    7554                 :            : 
    7555                 :            :     case OFPTYPE_GET_ASYNC_REQUEST:
    7556                 :          1 :         return handle_nxt_get_async_request(ofconn, oh);
    7557                 :            : 
    7558                 :            :     case OFPTYPE_NXT_RESUME:
    7559                 :        199 :         return handle_nxt_resume(ofconn, oh);
    7560                 :            : 
    7561                 :            :         /* Statistics requests. */
    7562                 :            :     case OFPTYPE_DESC_STATS_REQUEST:
    7563                 :          0 :         return handle_desc_stats_request(ofconn, oh);
    7564                 :            : 
    7565                 :            :     case OFPTYPE_FLOW_STATS_REQUEST:
    7566                 :        384 :         return handle_flow_stats_request(ofconn, oh);
    7567                 :            : 
    7568                 :            :     case OFPTYPE_AGGREGATE_STATS_REQUEST:
    7569                 :          5 :         return handle_aggregate_stats_request(ofconn, oh);
    7570                 :            : 
    7571                 :            :     case OFPTYPE_TABLE_STATS_REQUEST:
    7572                 :         10 :         return handle_table_stats_request(ofconn, oh);
    7573                 :            : 
    7574                 :            :     case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
    7575                 :          2 :         return handle_table_features_request(ofconn, oh);
    7576                 :            : 
    7577                 :            :     case OFPTYPE_TABLE_DESC_REQUEST:
    7578                 :         10 :         return handle_table_desc_request(ofconn, oh);
    7579                 :            : 
    7580                 :            :     case OFPTYPE_PORT_STATS_REQUEST:
    7581                 :         19 :         return handle_port_stats_request(ofconn, oh);
    7582                 :            : 
    7583                 :            :     case OFPTYPE_QUEUE_STATS_REQUEST:
    7584                 :         35 :         return handle_queue_stats_request(ofconn, oh);
    7585                 :            : 
    7586                 :            :     case OFPTYPE_PORT_DESC_STATS_REQUEST:
    7587                 :         36 :         return handle_port_desc_stats_request(ofconn, oh);
    7588                 :            : 
    7589                 :            :     case OFPTYPE_FLOW_MONITOR_STATS_REQUEST:
    7590                 :          4 :         return handle_flow_monitor_request(ofconn, oh);
    7591                 :            : 
    7592                 :            :     case OFPTYPE_METER_STATS_REQUEST:
    7593                 :            :     case OFPTYPE_METER_CONFIG_STATS_REQUEST:
    7594                 :          0 :         return handle_meter_request(ofconn, oh, type);
    7595                 :            : 
    7596                 :            :     case OFPTYPE_METER_FEATURES_STATS_REQUEST:
    7597                 :          0 :         return handle_meter_features_request(ofconn, oh);
    7598                 :            : 
    7599                 :            :     case OFPTYPE_GROUP_STATS_REQUEST:
    7600                 :          8 :         return handle_group_stats_request(ofconn, oh);
    7601                 :            : 
    7602                 :            :     case OFPTYPE_GROUP_DESC_STATS_REQUEST:
    7603                 :         52 :         return handle_group_desc_stats_request(ofconn, oh);
    7604                 :            : 
    7605                 :            :     case OFPTYPE_GROUP_FEATURES_STATS_REQUEST:
    7606                 :          1 :         return handle_group_features_stats_request(ofconn, oh);
    7607                 :            : 
    7608                 :            :     case OFPTYPE_QUEUE_GET_CONFIG_REQUEST:
    7609                 :         13 :         return handle_queue_get_config_request(ofconn, oh);
    7610                 :            : 
    7611                 :            :     case OFPTYPE_BUNDLE_CONTROL:
    7612                 :        260 :         return handle_bundle_control(ofconn, oh);
    7613                 :            : 
    7614                 :            :     case OFPTYPE_BUNDLE_ADD_MESSAGE:
    7615                 :        711 :         return handle_bundle_add(ofconn, oh);
    7616                 :            : 
    7617                 :            :     case OFPTYPE_NXT_TLV_TABLE_MOD:
    7618                 :         59 :         return handle_tlv_table_mod(ofconn, oh);
    7619                 :            : 
    7620                 :            :     case OFPTYPE_NXT_TLV_TABLE_REQUEST:
    7621                 :         46 :         return handle_tlv_table_request(ofconn, oh);
    7622                 :            : 
    7623                 :            :     case OFPTYPE_IPFIX_BRIDGE_STATS_REQUEST:
    7624                 :          3 :         return handle_ipfix_bridge_stats_request(ofconn, oh);
    7625                 :            : 
    7626                 :            :     case OFPTYPE_IPFIX_FLOW_STATS_REQUEST:
    7627                 :          3 :         return handle_ipfix_flow_stats_request(ofconn, oh);
    7628                 :            : 
    7629                 :            :     case OFPTYPE_HELLO:
    7630                 :            :     case OFPTYPE_ERROR:
    7631                 :            :     case OFPTYPE_FEATURES_REPLY:
    7632                 :            :     case OFPTYPE_GET_CONFIG_REPLY:
    7633                 :            :     case OFPTYPE_PACKET_IN:
    7634                 :            :     case OFPTYPE_FLOW_REMOVED:
    7635                 :            :     case OFPTYPE_PORT_STATUS:
    7636                 :            :     case OFPTYPE_BARRIER_REPLY:
    7637                 :            :     case OFPTYPE_QUEUE_GET_CONFIG_REPLY:
    7638                 :            :     case OFPTYPE_DESC_STATS_REPLY:
    7639                 :            :     case OFPTYPE_FLOW_STATS_REPLY:
    7640                 :            :     case OFPTYPE_QUEUE_STATS_REPLY:
    7641                 :            :     case OFPTYPE_PORT_STATS_REPLY:
    7642                 :            :     case OFPTYPE_TABLE_STATS_REPLY:
    7643                 :            :     case OFPTYPE_AGGREGATE_STATS_REPLY:
    7644                 :            :     case OFPTYPE_PORT_DESC_STATS_REPLY:
    7645                 :            :     case OFPTYPE_ROLE_REPLY:
    7646                 :            :     case OFPTYPE_FLOW_MONITOR_PAUSED:
    7647                 :            :     case OFPTYPE_FLOW_MONITOR_RESUMED:
    7648                 :            :     case OFPTYPE_FLOW_MONITOR_STATS_REPLY:
    7649                 :            :     case OFPTYPE_GET_ASYNC_REPLY:
    7650                 :            :     case OFPTYPE_GROUP_STATS_REPLY:
    7651                 :            :     case OFPTYPE_GROUP_DESC_STATS_REPLY:
    7652                 :            :     case OFPTYPE_GROUP_FEATURES_STATS_REPLY:
    7653                 :            :     case OFPTYPE_METER_STATS_REPLY:
    7654                 :            :     case OFPTYPE_METER_CONFIG_STATS_REPLY:
    7655                 :            :     case OFPTYPE_METER_FEATURES_STATS_REPLY:
    7656                 :            :     case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
    7657                 :            :     case OFPTYPE_TABLE_DESC_REPLY:
    7658                 :            :     case OFPTYPE_ROLE_STATUS:
    7659                 :            :     case OFPTYPE_REQUESTFORWARD:
    7660                 :            :     case OFPTYPE_TABLE_STATUS:
    7661                 :            :     case OFPTYPE_NXT_TLV_TABLE_REPLY:
    7662                 :            :     case OFPTYPE_IPFIX_BRIDGE_STATS_REPLY:
    7663                 :            :     case OFPTYPE_IPFIX_FLOW_STATS_REPLY:
    7664                 :            :     default:
    7665         [ #  # ]:          0 :         if (ofpmsg_is_stat_request(oh)) {
    7666                 :          0 :             return OFPERR_OFPBRC_BAD_STAT;
    7667                 :            :         } else {
    7668                 :      52719 :             return OFPERR_OFPBRC_BAD_TYPE;
    7669                 :            :         }
    7670                 :            :     }
    7671                 :            : }
    7672                 :            : 
    7673                 :            : static void
    7674                 :      52719 : handle_openflow(struct ofconn *ofconn, const struct ofpbuf *ofp_msg)
    7675                 :            :     OVS_EXCLUDED(ofproto_mutex)
    7676                 :            : {
    7677                 :      52719 :     enum ofperr error = handle_openflow__(ofconn, ofp_msg);
    7678                 :            : 
    7679         [ +  + ]:      52719 :     if (error) {
    7680                 :        619 :         ofconn_send_error(ofconn, ofp_msg->data, error);
    7681                 :            :     }
    7682                 :      52719 :     COVERAGE_INC(ofproto_recv_openflow);
    7683                 :      52719 : }
    7684                 :            : 
    7685                 :            : static uint64_t
    7686                 :        749 : pick_datapath_id(const struct ofproto *ofproto)
    7687                 :            : {
    7688                 :            :     const struct ofport *port;
    7689                 :            : 
    7690                 :        749 :     port = ofproto_get_port(ofproto, OFPP_LOCAL);
    7691         [ -  + ]:        749 :     if (port) {
    7692                 :            :         struct eth_addr ea;
    7693                 :            :         int error;
    7694                 :            : 
    7695                 :          0 :         error = netdev_get_etheraddr(port->netdev, &ea);
    7696         [ #  # ]:          0 :         if (!error) {
    7697                 :          0 :             return eth_addr_to_uint64(ea);
    7698                 :            :         }
    7699         [ #  # ]:          0 :         VLOG_WARN("%s: could not get MAC address for %s (%s)",
    7700                 :            :                   ofproto->name, netdev_get_name(port->netdev),
    7701                 :            :                   ovs_strerror(error));
    7702                 :            :     }
    7703                 :        749 :     return ofproto->fallback_dpid;
    7704                 :            : }
    7705                 :            : 
    7706                 :            : static uint64_t
    7707                 :        749 : pick_fallback_dpid(void)
    7708                 :            : {
    7709                 :            :     struct eth_addr ea;
    7710                 :        749 :     eth_addr_nicira_random(&ea);
    7711                 :        749 :     return eth_addr_to_uint64(ea);
    7712                 :            : }
    7713                 :            : 
    7714                 :            : /* Table overflow policy. */
    7715                 :            : 
    7716                 :            : /* Chooses and updates 'rulep' with a rule to evict from 'table'.  Sets 'rulep'
    7717                 :            :  * to NULL if the table is not configured to evict rules or if the table
    7718                 :            :  * contains no evictable rules.  (Rules with a readlock on their evict rwlock,
    7719                 :            :  * or with no timeouts are not evictable.) */
    7720                 :            : static bool
    7721                 :         26 : choose_rule_to_evict(struct oftable *table, struct rule **rulep)
    7722                 :            :     OVS_REQUIRES(ofproto_mutex)
    7723                 :            : {
    7724                 :            :     struct eviction_group *evg;
    7725                 :            : 
    7726                 :         26 :     *rulep = NULL;
    7727         [ +  + ]:         26 :     if (!table->eviction) {
    7728                 :          5 :         return false;
    7729                 :            :     }
    7730                 :            : 
    7731                 :            :     /* In the common case, the outer and inner loops here will each be entered
    7732                 :            :      * exactly once:
    7733                 :            :      *
    7734                 :            :      *   - The inner loop normally "return"s in its first iteration.  If the
    7735                 :            :      *     eviction group has any evictable rules, then it always returns in
    7736                 :            :      *     some iteration.
    7737                 :            :      *
    7738                 :            :      *   - The outer loop only iterates more than once if the largest eviction
    7739                 :            :      *     group has no evictable rules.
    7740                 :            :      *
    7741                 :            :      *   - The outer loop can exit only if table's 'max_flows' is all filled up
    7742                 :            :      *     by unevictable rules. */
    7743 [ +  + ][ #  # ]:         21 :     HEAP_FOR_EACH (evg, size_node, &table->eviction_groups_by_size) {
                 [ +  + ]
    7744                 :            :         struct rule *rule;
    7745                 :            : 
    7746 [ +  - ][ +  - ]:         19 :         HEAP_FOR_EACH (rule, evg_node, &evg->rules) {
    7747                 :         19 :             *rulep = rule;
    7748                 :         19 :             return true;
    7749                 :            :         }
    7750                 :            :     }
    7751                 :            : 
    7752                 :          2 :     return false;
    7753                 :            : }
    7754                 :            : 
    7755                 :            : /* Eviction groups. */
    7756                 :            : 
    7757                 :            : /* Returns the priority to use for an eviction_group that contains 'n_rules'
    7758                 :            :  * rules.  The priority contains low-order random bits to ensure that eviction
    7759                 :            :  * groups with the same number of rules are prioritized randomly. */
    7760                 :            : static uint32_t
    7761                 :         87 : eviction_group_priority(size_t n_rules)
    7762                 :            : {
    7763                 :         87 :     uint16_t size = MIN(UINT16_MAX, n_rules);
    7764                 :         87 :     return (size << 16) | random_uint16();
    7765                 :            : }
    7766                 :            : 
    7767                 :            : /* Updates 'evg', an eviction_group within 'table', following a change that
    7768                 :            :  * adds or removes rules in 'evg'. */
    7769                 :            : static void
    7770                 :         75 : eviction_group_resized(struct oftable *table, struct eviction_group *evg)
    7771                 :            :     OVS_REQUIRES(ofproto_mutex)
    7772                 :            : {
    7773                 :         75 :     heap_change(&table->eviction_groups_by_size, &evg->size_node,
    7774                 :         75 :                 eviction_group_priority(heap_count(&evg->rules)));
    7775                 :         75 : }
    7776                 :            : 
    7777                 :            : /* Destroys 'evg', an eviction_group within 'table':
    7778                 :            :  *
    7779                 :            :  *   - Removes all the rules, if any, from 'evg'.  (It doesn't destroy the
    7780                 :            :  *     rules themselves, just removes them from the eviction group.)
    7781                 :            :  *
    7782                 :            :  *   - Removes 'evg' from 'table'.
    7783                 :            :  *
    7784                 :            :  *   - Frees 'evg'. */
    7785                 :            : static void
    7786                 :         12 : eviction_group_destroy(struct oftable *table, struct eviction_group *evg)
    7787                 :            :     OVS_REQUIRES(ofproto_mutex)
    7788                 :            : {
    7789         [ +  + ]:         22 :     while (!heap_is_empty(&evg->rules)) {
    7790                 :            :         struct rule *rule;
    7791                 :            : 
    7792                 :         10 :         rule = CONTAINER_OF(heap_pop(&evg->rules), struct rule, evg_node);
    7793                 :         10 :         rule->eviction_group = NULL;
    7794                 :            :     }
    7795                 :         12 :     hmap_remove(&table->eviction_groups_by_id, &evg->id_node);
    7796                 :         12 :     heap_remove(&table->eviction_groups_by_size, &evg->size_node);
    7797                 :         12 :     heap_destroy(&evg->rules);
    7798                 :         12 :     free(evg);
    7799                 :         12 : }
    7800                 :            : 
    7801                 :            : /* Removes 'rule' from its eviction group, if any. */
    7802                 :            : static void
    7803                 :      31450 : eviction_group_remove_rule(struct rule *rule)
    7804                 :            :     OVS_REQUIRES(ofproto_mutex)
    7805                 :            : {
    7806         [ +  + ]:      31450 :     if (rule->eviction_group) {
    7807                 :         36 :         struct oftable *table = &rule->ofproto->tables[rule->table_id];
    7808                 :         36 :         struct eviction_group *evg = rule->eviction_group;
    7809                 :            : 
    7810                 :         36 :         rule->eviction_group = NULL;
    7811                 :         36 :         heap_remove(&evg->rules, &rule->evg_node);
    7812         [ +  + ]:         36 :         if (heap_is_empty(&evg->rules)) {
    7813                 :          7 :             eviction_group_destroy(table, evg);
    7814                 :            :         } else {
    7815                 :         29 :             eviction_group_resized(table, evg);
    7816                 :            :         }
    7817                 :            :     }
    7818                 :      31450 : }
    7819                 :            : 
    7820                 :            : /* Hashes the 'rule''s values for the eviction_fields of 'rule''s table, and
    7821                 :            :  * returns the hash value. */
    7822                 :            : static uint32_t
    7823                 :         46 : eviction_group_hash_rule(struct rule *rule)
    7824                 :            :     OVS_REQUIRES(ofproto_mutex)
    7825                 :            : {
    7826                 :         46 :     struct oftable *table = &rule->ofproto->tables[rule->table_id];
    7827                 :            :     const struct mf_subfield *sf;
    7828                 :            :     struct flow flow;
    7829                 :            :     uint32_t hash;
    7830                 :            : 
    7831                 :         46 :     hash = table->eviction_group_id_basis;
    7832                 :         46 :     miniflow_expand(rule->cr.match.flow, &flow);
    7833         [ +  + ]:         54 :     for (sf = table->eviction_fields;
    7834                 :         54 :          sf < &table->eviction_fields[table->n_eviction_fields];
    7835                 :          8 :          sf++)
    7836                 :            :     {
    7837         [ +  - ]:          8 :         if (mf_are_prereqs_ok(sf->field, &flow, NULL)) {
    7838                 :            :             union mf_value value;
    7839                 :            : 
    7840                 :          8 :             mf_get_value(sf->field, &flow, &value);
    7841         [ -  + ]:          8 :             if (sf->ofs) {
    7842                 :          0 :                 bitwise_zero(&value, sf->field->n_bytes, 0, sf->ofs);
    7843                 :            :             }
    7844         [ -  + ]:          8 :             if (sf->ofs + sf->n_bits < sf->field->n_bytes * 8) {
    7845                 :          0 :                 unsigned int start = sf->ofs + sf->n_bits;
    7846                 :          0 :                 bitwise_zero(&value, sf->field->n_bytes, start,
    7847                 :          0 :                              sf->field->n_bytes * 8 - start);
    7848                 :            :             }
    7849                 :          8 :             hash = hash_bytes(&value, sf->field->n_bytes, hash);
    7850                 :            :         } else {
    7851                 :          0 :             hash = hash_int(hash, 0);
    7852                 :            :         }
    7853                 :            :     }
    7854                 :            : 
    7855                 :         46 :     return hash;
    7856                 :            : }
    7857                 :            : 
    7858                 :            : /* Returns an eviction group within 'table' with the given 'id', creating one
    7859                 :            :  * if necessary. */
    7860                 :            : static struct eviction_group *
    7861                 :         46 : eviction_group_find(struct oftable *table, uint32_t id)
    7862                 :            :     OVS_REQUIRES(ofproto_mutex)
    7863                 :            : {
    7864                 :            :     struct eviction_group *evg;
    7865                 :            : 
    7866 [ +  + ][ -  + ]:         46 :     HMAP_FOR_EACH_WITH_HASH (evg, id_node, id, &table->eviction_groups_by_id) {
    7867                 :         34 :         return evg;
    7868                 :            :     }
    7869                 :            : 
    7870                 :         12 :     evg = xmalloc(sizeof *evg);
    7871                 :         12 :     hmap_insert(&table->eviction_groups_by_id, &evg->id_node, id);
    7872                 :         12 :     heap_insert(&table->eviction_groups_by_size, &evg->size_node,
    7873                 :         12 :                 eviction_group_priority(0));
    7874                 :         12 :     heap_init(&evg->rules);
    7875                 :            : 
    7876                 :         12 :     return evg;
    7877                 :            : }
    7878                 :            : 
    7879                 :            : /* Returns an eviction priority for 'rule'.  The return value should be
    7880                 :            :  * interpreted so that higher priorities make a rule a more attractive
    7881                 :            :  * candidate for eviction. */
    7882                 :            : static uint64_t
    7883                 :         72 : rule_eviction_priority(struct ofproto *ofproto, struct rule *rule)
    7884                 :            :     OVS_REQUIRES(ofproto_mutex)
    7885                 :            : {
    7886                 :            :     /* Calculate absolute time when this flow will expire.  If it will never
    7887                 :            :      * expire, then return 0 to make it unevictable.  */
    7888                 :         72 :     long long int expiration = LLONG_MAX;
    7889         [ +  + ]:         72 :     if (rule->hard_timeout) {
    7890                 :            :         /* 'modified' needs protection even when we hold 'ofproto_mutex'. */
    7891                 :         22 :         ovs_mutex_lock(&rule->mutex);
    7892                 :         22 :         long long int modified = rule->modified;
    7893                 :         22 :         ovs_mutex_unlock(&rule->mutex);
    7894                 :            : 
    7895                 :         22 :         expiration = modified + rule->hard_timeout * 1000;
    7896                 :            :     }
    7897         [ +  + ]:         72 :     if (rule->idle_timeout) {
    7898                 :            :         uint64_t packets, bytes;
    7899                 :            :         long long int used;
    7900                 :            :         long long int idle_expiration;
    7901                 :            : 
    7902                 :         50 :         ofproto->ofproto_class->rule_get_stats(rule, &packets, &bytes, &used);
    7903                 :         50 :         idle_expiration = used + rule->idle_timeout * 1000;
    7904                 :         50 :         expiration = MIN(expiration, idle_expiration);
    7905                 :            :     }
    7906         [ -  + ]:         72 :     if (expiration == LLONG_MAX) {
    7907                 :          0 :         return 0;
    7908                 :            :     }
    7909                 :            : 
    7910                 :            :     /* Calculate the time of expiration as a number of (approximate) seconds
    7911                 :            :      * after program startup.
    7912                 :            :      *
    7913                 :            :      * This should work OK for program runs that last UINT32_MAX seconds or
    7914                 :            :      * less.  Therefore, please restart OVS at least once every 136 years. */
    7915                 :         72 :     uint32_t expiration_ofs = (expiration >> 10) - (time_boot_msec() >> 10);
    7916                 :            : 
    7917                 :            :     /* Combine expiration time with OpenFlow "importance" to form a single
    7918                 :            :      * priority value.  We want flows with relatively low "importance" to be
    7919                 :            :      * evicted before even considering expiration time, so put "importance" in
    7920                 :            :      * the most significant bits and expiration time in the least significant
    7921                 :            :      * bits.
    7922                 :            :      *
    7923                 :            :      * Small 'priority' should be evicted before those with large 'priority'.
    7924                 :            :      * The caller expects the opposite convention (a large return value being
    7925                 :            :      * more attractive for eviction) so we invert it before returning. */
    7926                 :         72 :     uint64_t priority = ((uint64_t) rule->importance << 32) + expiration_ofs;
    7927                 :         72 :     return UINT64_MAX - priority;
    7928                 :            : }
    7929                 :            : 
    7930                 :            : /* Adds 'rule' to an appropriate eviction group for its oftable's
    7931                 :            :  * configuration.  Does nothing if 'rule''s oftable doesn't have eviction
    7932                 :            :  * enabled, or if 'rule' is a permanent rule (one that will never expire on its
    7933                 :            :  * own).
    7934                 :            :  *
    7935                 :            :  * The caller must ensure that 'rule' is not already in an eviction group. */
    7936                 :            : static void
    7937                 :      31439 : eviction_group_add_rule(struct rule *rule)
    7938                 :            :     OVS_REQUIRES(ofproto_mutex)
    7939                 :            : {
    7940                 :      31439 :     struct ofproto *ofproto = rule->ofproto;
    7941                 :      31439 :     struct oftable *table = &ofproto->tables[rule->table_id];
    7942                 :            :     bool has_timeout;
    7943                 :            : 
    7944                 :            :     /* Timeouts may be modified only when holding 'ofproto_mutex'.  We have it
    7945                 :            :      * so no additional protection is needed. */
    7946 [ +  + ][ +  + ]:      31439 :     has_timeout = rule->hard_timeout || rule->idle_timeout;
    7947                 :            : 
    7948 [ +  + ][ +  + ]:      31439 :     if (table->eviction && has_timeout) {
    7949                 :            :         struct eviction_group *evg;
    7950                 :            : 
    7951                 :         46 :         evg = eviction_group_find(table, eviction_group_hash_rule(rule));
    7952                 :            : 
    7953                 :         46 :         rule->eviction_group = evg;
    7954                 :         46 :         heap_insert(&evg->rules, &rule->evg_node,
    7955                 :            :                     rule_eviction_priority(ofproto, rule));
    7956                 :         46 :         eviction_group_resized(table, evg);
    7957                 :            :     }
    7958                 :      31439 : }
    7959                 :            : 
    7960                 :            : /* oftables. */
    7961                 :            : 
    7962                 :            : /* Initializes 'table'. */
    7963                 :            : static void
    7964                 :     190995 : oftable_init(struct oftable *table)
    7965                 :            : {
    7966                 :     190995 :     memset(table, 0, sizeof *table);
    7967                 :     190995 :     classifier_init(&table->cls, flow_segment_u64s);
    7968                 :     190995 :     table->max_flows = UINT_MAX;
    7969                 :     190995 :     table->n_flows = 0;
    7970                 :     190995 :     hmap_init(&table->eviction_groups_by_id);
    7971                 :     190995 :     heap_init(&table->eviction_groups_by_size);
    7972                 :     190995 :     atomic_init(&table->miss_config, OFPUTIL_TABLE_MISS_DEFAULT);
    7973                 :            : 
    7974                 :     190995 :     classifier_set_prefix_fields(&table->cls, default_prefix_fields,
    7975                 :            :                                  ARRAY_SIZE(default_prefix_fields));
    7976                 :            : 
    7977                 :     190995 :     atomic_init(&table->n_matched, 0);
    7978                 :     190995 :     atomic_init(&table->n_missed, 0);
    7979                 :     190995 : }
    7980                 :            : 
    7981                 :            : /* Destroys 'table', including its classifier and eviction groups.
    7982                 :            :  *
    7983                 :            :  * The caller is responsible for freeing 'table' itself. */
    7984                 :            : static void
    7985                 :      31365 : oftable_destroy(struct oftable *table)
    7986                 :            : {
    7987         [ -  + ]:      31365 :     ovs_assert(classifier_is_empty(&table->cls));
    7988                 :            : 
    7989                 :      31365 :     ovs_mutex_lock(&ofproto_mutex);
    7990                 :      31365 :     oftable_configure_eviction(table, 0, NULL, 0);
    7991                 :      31365 :     ovs_mutex_unlock(&ofproto_mutex);
    7992                 :            : 
    7993                 :      31365 :     hmap_destroy(&table->eviction_groups_by_id);
    7994                 :      31365 :     heap_destroy(&table->eviction_groups_by_size);
    7995                 :      31365 :     classifier_destroy(&table->cls);
    7996                 :      31365 :     free(table->name);
    7997                 :      31365 : }
    7998                 :            : 
    7999                 :            : /* Changes the name of 'table' to 'name'.  If 'name' is NULL or the empty
    8000                 :            :  * string, then 'table' will use its default name.
    8001                 :            :  *
    8002                 :            :  * This only affects the name exposed for a table exposed through the OpenFlow
    8003                 :            :  * OFPST_TABLE (as printed by "ovs-ofctl dump-tables"). */
    8004                 :            : static void
    8005                 :    1198500 : oftable_set_name(struct oftable *table, const char *name)
    8006                 :            : {
    8007 [ +  + ][ +  - ]:    1198517 :     if (name && name[0]) {
    8008                 :         17 :         int len = strnlen(name, OFP_MAX_TABLE_NAME_LEN);
    8009 [ +  + ][ -  + ]:         17 :         if (!table->name || strncmp(name, table->name, len)) {
    8010                 :         10 :             free(table->name);
    8011                 :         10 :             table->name = xmemdup0(name, len);
    8012                 :            :         }
    8013                 :            :     } else {
    8014                 :    1198483 :         free(table->name);
    8015                 :    1198483 :         table->name = NULL;
    8016                 :            :     }
    8017                 :    1198500 : }
    8018                 :            : 
    8019                 :            : /* oftables support a choice of two policies when adding a rule would cause the
    8020                 :            :  * number of flows in the table to exceed the configured maximum number: either
    8021                 :            :  * they can refuse to add the new flow or they can evict some existing flow.
    8022                 :            :  * This function configures the latter policy on 'table', with fairness based
    8023                 :            :  * on the values of the 'n_fields' fields specified in 'fields'.  (Specifying
    8024                 :            :  * 'n_fields' as 0 disables fairness.) */
    8025                 :            : static void
    8026                 :    1225168 : oftable_configure_eviction(struct oftable *table, unsigned int eviction,
    8027                 :            :                            const struct mf_subfield *fields, size_t n_fields)
    8028                 :            :     OVS_REQUIRES(ofproto_mutex)
    8029                 :            : {
    8030                 :            :     struct rule *rule;
    8031                 :            : 
    8032         [ +  + ]:    1225168 :     if ((table->eviction != 0) == (eviction != 0)
    8033         [ +  + ]:    1225159 :         && n_fields == table->n_eviction_fields
    8034         [ -  + ]:    1225157 :         && (!n_fields
    8035         [ #  # ]:          0 :             || !memcmp(fields, table->eviction_fields,
    8036                 :            :                        n_fields * sizeof *fields))) {
    8037                 :            :         /* The set of eviction fields did not change.  If 'eviction' changed,
    8038                 :            :          * it remains nonzero, so that we can just update table->eviction
    8039                 :            :          * without fussing with the eviction groups. */
    8040                 :    1225157 :         table->eviction = eviction;
    8041                 :    1225157 :         return;
    8042                 :            :     }
    8043                 :            : 
    8044                 :            :     /* Destroy existing eviction groups, then destroy and recreate data
    8045                 :            :      * structures to recover memory. */
    8046                 :            :     struct eviction_group *evg, *next;
    8047 [ +  + ][ -  + ]:         16 :     HMAP_FOR_EACH_SAFE (evg, next, id_node, &table->eviction_groups_by_id) {
                 [ +  + ]
    8048                 :          5 :         eviction_group_destroy(table, evg);
    8049                 :            :     }
    8050                 :         11 :     hmap_destroy(&table->eviction_groups_by_id);
    8051                 :         11 :     hmap_init(&table->eviction_groups_by_id);
    8052                 :         11 :     heap_destroy(&table->eviction_groups_by_size);
    8053                 :         11 :     heap_init(&table->eviction_groups_by_size);
    8054                 :            : 
    8055                 :            :     /* Replace eviction groups by the new ones, if there is a change.  Free the
    8056                 :            :      * old fields only after allocating the new ones, because 'fields ==
    8057                 :            :      * table->eviction_fields' is possible. */
    8058                 :         11 :     struct mf_subfield *old_fields = table->eviction_fields;
    8059                 :         11 :     table->n_eviction_fields = n_fields;
    8060                 :         11 :     table->eviction_fields = (fields
    8061                 :          2 :                               ? xmemdup(fields, n_fields * sizeof *fields)
    8062         [ +  + ]:         11 :                               : NULL);
    8063                 :         11 :     free(old_fields);
    8064                 :            : 
    8065                 :            :     /* Add the new eviction groups, if enabled. */
    8066                 :         11 :     table->eviction = eviction;
    8067         [ +  + ]:         11 :     if (table->eviction) {
    8068                 :         10 :         table->eviction_group_id_basis = random_uint32();
    8069 [ +  + ][ +  + ]:         18 :         CLS_FOR_EACH (rule, cr, &table->cls) {
    8070                 :          8 :             eviction_group_add_rule(rule);
    8071                 :            :         }
    8072                 :            :     }
    8073                 :            : }
    8074                 :            : 
    8075                 :            : /* Inserts 'rule' from the ofproto data structures BEFORE caller has inserted
    8076                 :            :  * it to the classifier. */
    8077                 :            : static void
    8078                 :      31431 : ofproto_rule_insert__(struct ofproto *ofproto, struct rule *rule)
    8079                 :            :     OVS_REQUIRES(ofproto_mutex)
    8080                 :            : {
    8081                 :      31431 :     const struct rule_actions *actions = rule_get_actions(rule);
    8082                 :            : 
    8083         [ -  + ]:      31431 :     ovs_assert(rule->removed);
    8084                 :            : 
    8085 [ +  + ][ +  + ]:      31431 :     if (rule->hard_timeout || rule->idle_timeout) {
    8086                 :         87 :         ovs_list_insert(&ofproto->expirable, &rule->expirable);
    8087                 :            :     }
    8088                 :      31431 :     cookies_insert(ofproto, rule);
    8089                 :      31431 :     eviction_group_add_rule(rule);
    8090         [ -  + ]:      31431 :     if (actions->has_meter) {
    8091                 :          0 :         meter_insert_rule(rule);
    8092                 :            :     }
    8093         [ +  + ]:      31431 :     if (actions->has_groups) {
    8094                 :            :         const struct ofpact_group *a;
    8095         [ +  + ]:         78 :         OFPACT_FOR_EACH_TYPE_FLATTENED (a, GROUP, actions->ofpacts,
    8096                 :            :                                         actions->ofpacts_len) {
    8097                 :            :             struct ofgroup *group;
    8098                 :            : 
    8099                 :         39 :             group = ofproto_group_lookup(ofproto, a->group_id, OVS_VERSION_MAX,
    8100                 :            :                                          false);
    8101         [ -  + ]:         39 :             ovs_assert(group != NULL);
    8102                 :         39 :             group_add_rule(group, rule);
    8103                 :            :         }
    8104                 :            :     }
    8105                 :            : 
    8106                 :      31431 :     rule->removed = false;
    8107                 :      31431 : }
    8108                 :            : 
    8109                 :            : /* Removes 'rule' from the ofproto data structures.  Caller may have deferred
    8110                 :            :  * the removal from the classifier. */
    8111                 :            : static void
    8112                 :      31431 : ofproto_rule_remove__(struct ofproto *ofproto, struct rule *rule)
    8113                 :            :     OVS_REQUIRES(ofproto_mutex)
    8114                 :            : {
    8115         [ -  + ]:      31431 :     ovs_assert(!rule->removed);
    8116                 :            : 
    8117                 :      31431 :     cookies_remove(ofproto, rule);
    8118                 :            : 
    8119                 :      31431 :     eviction_group_remove_rule(rule);
    8120         [ +  + ]:      31431 :     if (!ovs_list_is_empty(&rule->expirable)) {
    8121                 :         87 :         ovs_list_remove(&rule->expirable);
    8122                 :            :     }
    8123         [ -  + ]:      31431 :     if (!ovs_list_is_empty(&rule->meter_list_node)) {
    8124                 :          0 :         ovs_list_remove(&rule->meter_list_node);
    8125                 :          0 :         ovs_list_init(&rule->meter_list_node);
    8126                 :            :     }
    8127                 :            : 
    8128                 :            :     /* Remove the rule from any groups, except from the group that is being
    8129                 :            :      * deleted, if any. */
    8130                 :      31431 :     const struct rule_actions *actions = rule_get_actions(rule);
    8131                 :            : 
    8132         [ +  + ]:      31431 :     if (actions->has_groups) {
    8133                 :            :         const struct ofpact_group *a;
    8134                 :            : 
    8135         [ +  + ]:         78 :         OFPACT_FOR_EACH_TYPE (a, GROUP, actions->ofpacts,
    8136                 :            :                                         actions->ofpacts_len) {
    8137                 :            :             struct ofgroup *group;
    8138                 :            : 
    8139                 :         39 :             group = ofproto_group_lookup(ofproto, a->group_id, OVS_VERSION_MAX,
    8140                 :            :                                          false);
    8141         [ -  + ]:         39 :             ovs_assert(group);
    8142                 :            : 
    8143                 :            :             /* Leave the rule for the group that is being deleted, if any,
    8144                 :            :              * as we still need the list of rules for clean-up. */
    8145         [ +  + ]:         39 :             if (!group->being_deleted) {
    8146                 :         23 :                 group_remove_rule(group, rule);
    8147                 :            :             }
    8148                 :            :         }
    8149                 :            :     }
    8150                 :            : 
    8151                 :      31431 :     rule->removed = true;
    8152                 :      31431 : }
    8153                 :            : 
    8154                 :            : /* unixctl commands. */
    8155                 :            : 
    8156                 :            : struct ofproto *
    8157                 :          0 : ofproto_lookup(const char *name)
    8158                 :            : {
    8159                 :            :     struct ofproto *ofproto;
    8160                 :            : 
    8161 [ #  # ][ #  # ]:          0 :     HMAP_FOR_EACH_WITH_HASH (ofproto, hmap_node, hash_string(name, 0),
    8162                 :            :                              &all_ofprotos) {
    8163         [ #  # ]:          0 :         if (!strcmp(ofproto->name, name)) {
    8164                 :          0 :             return ofproto;
    8165                 :            :         }
    8166                 :            :     }
    8167                 :          0 :     return NULL;
    8168                 :            : }
    8169                 :            : 
    8170                 :            : static void
    8171                 :          0 : ofproto_unixctl_list(struct unixctl_conn *conn, int argc OVS_UNUSED,
    8172                 :            :                      const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
    8173                 :            : {
    8174                 :            :     struct ofproto *ofproto;
    8175                 :            :     struct ds results;
    8176                 :            : 
    8177                 :          0 :     ds_init(&results);
    8178 [ #  # ][ #  # ]:          0 :     HMAP_FOR_EACH (ofproto, hmap_node, &all_ofprotos) {
    8179                 :          0 :         ds_put_format(&results, "%s\n", ofproto->name);
    8180                 :            :     }
    8181                 :          0 :     unixctl_command_reply(conn, ds_cstr(&results));
    8182                 :          0 :     ds_destroy(&results);
    8183                 :          0 : }
    8184                 :            : 
    8185                 :            : static void
    8186                 :        615 : ofproto_unixctl_init(void)
    8187                 :            : {
    8188                 :            :     static bool registered;
    8189         [ -  + ]:        615 :     if (registered) {
    8190                 :          0 :         return;
    8191                 :            :     }
    8192                 :        615 :     registered = true;
    8193                 :            : 
    8194                 :        615 :     unixctl_command_register("ofproto/list", "", 0, 0,
    8195                 :            :                              ofproto_unixctl_list, NULL);
    8196                 :            : }

Generated by: LCOV version 1.12