Fix misspellings in comments and docs.
[sliver-openvswitch.git] / ofproto / ofproto-dpif.c
index 08d7c0c..2307577 100644 (file)
@@ -398,13 +398,6 @@ struct subfacet {
     uint64_t dp_byte_count;     /* Last known byte count in the datapath. */
 
     enum subfacet_path path;    /* Installed in datapath? */
-
-    /* Datapath port the packet arrived on.  This is needed to remove
-     * flows for ports that are no longer part of the bridge.  Since the
-     * flow definition only has the OpenFlow port number and the port is
-     * no longer part of the bridge, we can't determine the datapath port
-     * number needed to delete the flow from the datapath. */
-    uint32_t odp_in_port;
 };
 
 #define SUBFACET_DESTROY_MAX_BATCH 50
@@ -570,8 +563,9 @@ struct vlan_splinter {
     int vid;
 };
 
-static uint32_t vsp_realdev_to_vlandev(const struct ofproto_dpif *,
-                                       uint32_t realdev, ovs_be16 vlan_tci);
+static uint16_t vsp_realdev_to_vlandev(const struct ofproto_dpif *,
+                                       uint16_t realdev_ofp_port,
+                                       ovs_be16 vlan_tci);
 static bool vsp_adjust_flow(const struct ofproto_dpif *, struct flow *);
 static void vsp_remove(struct ofport_dpif *);
 static void vsp_add(struct ofport_dpif *, uint16_t realdev_ofp_port, int vid);
@@ -656,6 +650,7 @@ struct dpif_backer {
     struct tag_set revalidate_set; /* Revalidate only matching facets. */
 
     struct hmap drop_keys; /* Set of dropped odp keys. */
+    bool recv_set_enable; /* Enables or disables receiving packets. */
 };
 
 /* All existing ofproto_backer instances, indexed by ofproto->up.type. */
@@ -665,8 +660,6 @@ static void drop_key_clear(struct dpif_backer *);
 static struct ofport_dpif *
 odp_port_to_ofport(const struct dpif_backer *, uint32_t odp_port);
 
-static void dpif_stats_update_hit_count(struct ofproto_dpif *ofproto,
-                                        uint64_t delta);
 struct avg_subfacet_rates {
     double add_rate;     /* Moving average of new flows created per minute. */
     double del_rate;     /* Moving average of flows deleted per minute. */
@@ -766,8 +759,6 @@ static unsigned long long int avg_subfacet_life_span(
                                         const struct ofproto_dpif *);
 static double avg_subfacet_count(const struct ofproto_dpif *ofproto);
 static void update_moving_averages(struct ofproto_dpif *ofproto);
-static void dpif_stats_update_hit_count(struct ofproto_dpif *ofproto,
-                                        uint64_t delta);
 static void update_max_subfacet_count(struct ofproto_dpif *ofproto);
 
 /* Defer flow mod completion until "ovs-appctl ofproto/unclog"?  (Useful only
@@ -929,6 +920,21 @@ type_run(const char *type)
         push_all_stats();
     }
 
+    /* If vswitchd started with other_config:flow_restore_wait set as "true",
+     * and the configuration has now changed to "false", enable receiving
+     * packets from the datapath. */
+    if (!backer->recv_set_enable && !ofproto_get_flow_restore_wait()) {
+        backer->recv_set_enable = true;
+
+        error = dpif_recv_set(backer->dpif, backer->recv_set_enable);
+        if (error) {
+            VLOG_ERR("Failed to enable receiving packets in dpif.");
+            return error;
+        }
+        dpif_flow_flush(backer->dpif);
+        backer->need_revalidate = REV_RECONFIGURE;
+    }
+
     if (backer->need_revalidate
         || !tag_set_is_empty(&backer->revalidate_set)) {
         struct tag_set revalidate_set = backer->revalidate_set;
@@ -1022,7 +1028,10 @@ type_run(const char *type)
         }
     }
 
-    if (timer_expired(&backer->next_expiration)) {
+    if (!backer->recv_set_enable) {
+        /* Wake up before a max of 1000ms. */
+        timer_set_duration(&backer->next_expiration, 1000);
+    } else if (timer_expired(&backer->next_expiration)) {
         int delay = expire(backer);
         timer_set_duration(&backer->next_expiration, delay);
     }
@@ -1088,6 +1097,11 @@ dpif_backer_run_fast(struct dpif_backer *backer, int max_batch)
 {
     unsigned int work;
 
+    /* If recv_set_enable is false, we should not handle upcalls. */
+    if (!backer->recv_set_enable) {
+        return 0;
+    }
+
     /* Handle one or more batches of upcalls, until there's nothing left to do
      * or until we do a fixed total amount of work.
      *
@@ -1287,9 +1301,12 @@ open_dpif_backer(const char *type, struct dpif_backer **backerp)
     backer->need_revalidate = 0;
     simap_init(&backer->tnl_backers);
     tag_set_init(&backer->revalidate_set);
+    backer->recv_set_enable = !ofproto_get_flow_restore_wait();
     *backerp = backer;
 
-    dpif_flow_flush(backer->dpif);
+    if (backer->recv_set_enable) {
+        dpif_flow_flush(backer->dpif);
+    }
 
     /* Loop through the ports already on the datapath and remove any
      * that we don't need anymore. */
@@ -1313,7 +1330,7 @@ open_dpif_backer(const char *type, struct dpif_backer **backerp)
 
     shash_add(&all_dpif_backers, type, backer);
 
-    error = dpif_recv_set(backer->dpif, true);
+    error = dpif_recv_set(backer->dpif, backer->recv_set_enable);
     if (error) {
         VLOG_ERR("failed to listen on datapath of type %s: %s",
                  type, strerror(error));
@@ -1549,6 +1566,12 @@ run_fast(struct ofproto *ofproto_)
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
     struct ofport_dpif *ofport;
 
+    /* Do not perform any periodic activity required by 'ofproto' while
+     * waiting for flow restore to complete. */
+    if (ofproto_get_flow_restore_wait()) {
+        return 0;
+    }
+
     HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
         port_run_fast(ofport);
     }
@@ -1568,6 +1591,12 @@ run(struct ofproto *ofproto_)
         complete_operations(ofproto);
     }
 
+    /* Do not perform any periodic activity below required by 'ofproto' while
+     * waiting for flow restore to complete. */
+    if (ofproto_get_flow_restore_wait()) {
+        return 0;
+    }
+
     error = run_fast(ofproto_);
     if (error) {
         return error;
@@ -1642,6 +1671,10 @@ wait(struct ofproto *ofproto_)
         poll_immediate_wake();
     }
 
+    if (ofproto_get_flow_restore_wait()) {
+        return;
+    }
+
     dpif_wait(ofproto->backer->dpif);
     dpif_recv_wait(ofproto->backer->dpif);
     if (ofproto->sflow) {
@@ -1871,6 +1904,10 @@ port_modified(struct ofport *port_)
     if (port->bundle && port->bundle->bond) {
         bond_slave_set_netdev(port->bundle->bond, port, port->up.netdev);
     }
+
+    if (port->cfm) {
+        cfm_set_netdev(port->cfm, port->up.netdev);
+    }
 }
 
 static void
@@ -3491,7 +3528,6 @@ struct flow_miss {
     struct initial_vals initial_vals;
     struct list packets;
     enum dpif_upcall_type upcall_type;
-    uint32_t odp_in_port;
 };
 
 struct flow_miss_op {
@@ -3783,7 +3819,7 @@ handle_flow_miss(struct flow_miss *miss, struct flow_miss_op *ops,
          * flow keys with fitness ODP_FIT_TO_LITTLE.  This breaks a fundamental
          * assumption used throughout the facet and subfacet handling code.
          * Since we have to handle these misses in userspace anyway, we simply
-         * skip facet creation, avoiding the problem alltogether. */
+         * skip facet creation, avoiding the problem altogether. */
         if (miss->key_fitness == ODP_FIT_TOO_LITTLE
             || !flow_miss_should_make_facet(ofproto, miss, hash)) {
             handle_flow_miss_without_facet(miss, ops, n_ops);
@@ -3982,14 +4018,14 @@ handle_miss_upcalls(struct dpif_backer *backer, struct dpif_upcall *upcalls,
         if (error == ENODEV) {
             struct drop_key *drop_key;
 
-            /* Received packet on port for which we couldn't associate
-             * an ofproto.  This can happen if a port is removed while
-             * traffic is being received.  Print a rate-limited message
+            /* Received packet on datapath port for which we couldn't
+             * associate an ofproto.  This can happen if a port is removed
+             * while traffic is being received.  Print a rate-limited message
              * in case it happens frequently.  Install a drop flow so
              * that future packets of the flow are inexpensively dropped
              * in the kernel. */
-            VLOG_INFO_RL(&rl, "received packet on unassociated port %"PRIu32,
-                         flow.in_port);
+            VLOG_INFO_RL(&rl, "received packet on unassociated datapath port "
+                              "%"PRIu32, odp_in_port);
 
             drop_key = drop_key_lookup(backer, upcall->key, upcall->key_len);
             if (!drop_key) {
@@ -4021,7 +4057,6 @@ handle_miss_upcalls(struct dpif_backer *backer, struct dpif_upcall *upcalls,
             miss->key = upcall->key;
             miss->key_len = upcall->key_len;
             miss->upcall_type = upcall->type;
-            miss->odp_in_port = odp_in_port;
             list_init(&miss->packets);
 
             n_misses++;
@@ -4308,6 +4343,7 @@ update_subfacet_stats(struct subfacet *subfacet,
                       const struct dpif_flow_stats *stats)
 {
     struct facet *facet = subfacet->facet;
+    struct ofproto_dpif *ofproto = ofproto_dpif_cast(facet->rule->up.ofproto);
     struct dpif_flow_stats diff;
 
     diff.tcp_flags = stats->tcp_flags;
@@ -4327,6 +4363,7 @@ update_subfacet_stats(struct subfacet *subfacet,
         diff.n_bytes = 0;
     }
 
+    ofproto->n_hit += diff.n_packets;
     subfacet->dp_packet_count = stats->n_packets;
     subfacet->dp_byte_count = stats->n_bytes;
     subfacet_update_stats(subfacet, &diff);
@@ -4400,12 +4437,6 @@ update_stats(struct dpif_backer *backer)
         subfacet = subfacet_find(ofproto, key, key_len, key_hash);
         switch (subfacet ? subfacet->path : SF_NOT_INSTALLED) {
         case SF_FAST_PATH:
-            /* Update ofproto_dpif's hit count. */
-            if (stats->n_packets > subfacet->dp_packet_count) {
-                uint64_t delta = stats->n_packets - subfacet->dp_packet_count;
-                dpif_stats_update_hit_count(ofproto, delta);
-            }
-
             update_subfacet_stats(subfacet, stats);
             break;
 
@@ -5203,7 +5234,6 @@ subfacet_create(struct facet *facet, struct flow_miss *miss,
     subfacet->dp_packet_count = 0;
     subfacet->dp_byte_count = 0;
     subfacet->path = SF_NOT_INSTALLED;
-    subfacet->odp_in_port = miss->odp_in_port;
 
     ofproto->subfacet_add_count++;
     return subfacet;
@@ -5973,10 +6003,14 @@ compose_output_action__(struct xlate_ctx *ctx, uint16_t ofp_port,
                                  &ctx->xout->odp_actions);
         ctx->xin->flow.tunnel = flow_tnl; /* Restore tunnel metadata */
     } else {
+        uint16_t vlandev_port;
         odp_port = ofport->odp_port;
-        out_port = vsp_realdev_to_vlandev(ctx->ofproto, odp_port,
-                                          ctx->xin->flow.vlan_tci);
-        if (out_port != odp_port) {
+        vlandev_port = vsp_realdev_to_vlandev(ctx->ofproto, ofp_port,
+                                              ctx->xin->flow.vlan_tci);
+        if (vlandev_port == ofp_port) {
+            out_port = odp_port;
+        } else {
+            out_port = ofp_port_to_odp_port(ctx->ofproto, vlandev_port);
             ctx->xin->flow.vlan_tci = htons(0);
         }
         ctx->xin->flow.skb_mark &= ~IPSEC_MARK;
@@ -8534,33 +8568,31 @@ hash_realdev_vid(uint16_t realdev_ofp_port, int vid)
     return hash_2words(realdev_ofp_port, vid);
 }
 
-/* Returns the ODP port number of the Linux VLAN device that corresponds to
- * 'vlan_tci' on the network device with port number 'realdev_odp_port' in
- * 'ofproto'.  For example, given 'realdev_odp_port' of eth0 and 'vlan_tci' 9,
- * it would return the port number of eth0.9.
+/* Returns the OFP port number of the Linux VLAN device that corresponds to
+ * 'vlan_tci' on the network device with port number 'realdev_ofp_port' in
+ * 'struct ofport_dpif'.  For example, given 'realdev_ofp_port' of eth0 and
+ * 'vlan_tci' 9, it would return the port number of eth0.9.
  *
- * Unless VLAN splinters are enabled for port 'realdev_odp_port', this
- * function just returns its 'realdev_odp_port' argument. */
-static uint32_t
+ * Unless VLAN splinters are enabled for port 'realdev_ofp_port', this
+ * function just returns its 'realdev_ofp_port' argument. */
+static uint16_t
 vsp_realdev_to_vlandev(const struct ofproto_dpif *ofproto,
-                       uint32_t realdev_odp_port, ovs_be16 vlan_tci)
+                       uint16_t realdev_ofp_port, ovs_be16 vlan_tci)
 {
     if (!hmap_is_empty(&ofproto->realdev_vid_map)) {
-        uint16_t realdev_ofp_port;
         int vid = vlan_tci_to_vid(vlan_tci);
         const struct vlan_splinter *vsp;
 
-        realdev_ofp_port = odp_port_to_ofp_port(ofproto, realdev_odp_port);
         HMAP_FOR_EACH_WITH_HASH (vsp, realdev_vid_node,
                                  hash_realdev_vid(realdev_ofp_port, vid),
                                  &ofproto->realdev_vid_map) {
             if (vsp->realdev_ofp_port == realdev_ofp_port
                 && vsp->vid == vid) {
-                return ofp_port_to_odp_port(ofproto, vsp->vlandev_ofp_port);
+                return vsp->vlandev_ofp_port;
             }
         }
     }
-    return realdev_odp_port;
+    return realdev_ofp_port;
 }
 
 static struct vlan_splinter *
@@ -8781,12 +8813,6 @@ update_moving_averages(struct ofproto_dpif *ofproto)
     }
 }
 
-static void
-dpif_stats_update_hit_count(struct ofproto_dpif *ofproto, uint64_t delta)
-{
-    ofproto->n_hit += delta;
-}
-
 const struct ofproto_class ofproto_dpif_class = {
     init,
     enumerate_types,