ofproto: Implement OpenFlow 1.3 meter table.
[sliver-openvswitch.git] / ofproto / ofproto-dpif.c
index a2a59e1..4293824 100644 (file)
@@ -1045,8 +1045,6 @@ construct(struct ofproto *ofproto_)
     ofproto_dpif_unixctl_init();
 
     ofproto->has_mirrors = false;
-    ofproto->has_bundle_action = false;
-
     hmap_init(&ofproto->vlandev_map);
     hmap_init(&ofproto->realdev_vid_map);
 
@@ -1195,9 +1193,9 @@ destruct(struct ofproto *ofproto_)
     }
 
     netflow_destroy(ofproto->netflow);
-    dpif_sflow_destroy(ofproto->sflow);
+    dpif_sflow_unref(ofproto->sflow);
     hmap_destroy(&ofproto->bundles);
-    mac_learning_destroy(ofproto->ml);
+    mac_learning_unref(ofproto->ml);
 
     classifier_destroy(&ofproto->facets);
 
@@ -1500,7 +1498,7 @@ port_construct(struct ofport *port_)
         }
 
         hmap_insert(&ofproto->backer->odp_to_ofport_map, &port->odp_port_node,
-                    hash_int(odp_to_u32(port->odp_port), 0));
+                    hash_odp_port(port->odp_port));
     }
     dpif_port_destroy(&dpif_port);
 
@@ -1520,6 +1518,8 @@ port_destruct(struct ofport *port_)
     char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
     const char *dp_port_name;
 
+    ofproto->backer->need_revalidate = REV_RECONFIGURE;
+
     dp_port_name = netdev_vport_get_dpif_port(port->up.netdev, namebuf,
                                               sizeof namebuf);
     if (dpif_port_exists(ofproto->backer->dpif, dp_port_name)) {
@@ -1530,7 +1530,6 @@ port_destruct(struct ofport *port_)
         if (!port->tnl_port) {
             dpif_port_del(ofproto->backer->dpif, port->odp_port);
         }
-        ofproto->backer->need_revalidate = REV_RECONFIGURE;
     }
 
     if (port->peer) {
@@ -1545,7 +1544,6 @@ port_destruct(struct ofport *port_)
     tnl_port_del(port->tnl_port);
     sset_find_and_delete(&ofproto->ports, devname);
     sset_find_and_delete(&ofproto->ghost_ports, devname);
-    ofproto->backer->need_revalidate = REV_RECONFIGURE;
     bundle_remove(port_);
     set_cfm(port_, NULL);
     set_bfd(port_, NULL);
@@ -1572,7 +1570,8 @@ port_modified(struct ofport *port_)
 
     if (port->tnl_port && tnl_port_reconfigure(&port->up, port->odp_port,
                                                &port->tnl_port)) {
-        ofproto_dpif_cast(port->up.ofproto)->backer->need_revalidate = true;
+        ofproto_dpif_cast(port->up.ofproto)->backer->need_revalidate =
+            REV_RECONFIGURE;
     }
 
     ofport_update_peer(port);
@@ -1616,7 +1615,7 @@ set_sflow(struct ofproto *ofproto_,
         dpif_sflow_set_options(ds, sflow_options);
     } else {
         if (ds) {
-            dpif_sflow_destroy(ds);
+            dpif_sflow_unref(ds);
             ofproto->backer->need_revalidate = REV_RECONFIGURE;
             ofproto->sflow = NULL;
         }
@@ -1643,7 +1642,7 @@ set_ipfix(
             n_flow_exporters_options);
     } else {
         if (di) {
-            dpif_ipfix_destroy(di);
+            dpif_ipfix_unref(di);
             ofproto->ipfix = NULL;
         }
     }
@@ -1673,7 +1672,7 @@ set_cfm(struct ofport *ofport_, const struct cfm_settings *s)
 
         error = EINVAL;
     }
-    cfm_destroy(ofport->cfm);
+    cfm_unref(ofport->cfm);
     ofport->cfm = NULL;
     return error;
 }
@@ -2244,8 +2243,8 @@ bundle_destroy(struct ofbundle *bundle)
     hmap_remove(&ofproto->bundles, &bundle->hmap_node);
     free(bundle->name);
     free(bundle->trunks);
-    lacp_destroy(bundle->lacp);
-    bond_destroy(bundle->bond);
+    lacp_unref(bundle->lacp);
+    bond_unref(bundle->bond);
     free(bundle);
 }
 
@@ -2308,7 +2307,7 @@ bundle_set(struct ofproto *ofproto_, void *aux,
         }
         lacp_configure(bundle->lacp, s->lacp);
     } else {
-        lacp_destroy(bundle->lacp);
+        lacp_unref(bundle->lacp);
         bundle->lacp = NULL;
     }
 
@@ -2419,7 +2418,7 @@ bundle_set(struct ofproto *ofproto_, void *aux,
             bond_slave_register(bundle->bond, port, port->up.netdev);
         }
     } else {
-        bond_destroy(bundle->bond);
+        bond_unref(bundle->bond);
         bundle->bond = NULL;
     }
 
@@ -2443,7 +2442,7 @@ bundle_remove(struct ofport *port_)
         if (list_is_empty(&bundle->ports)) {
             bundle_destroy(bundle);
         } else if (list_is_short(&bundle->ports)) {
-            bond_destroy(bundle->bond);
+            bond_unref(bundle->bond);
             bundle->bond = NULL;
         }
     }
@@ -2859,7 +2858,7 @@ ofport_update_peer(struct ofport_dpif *ofport)
     }
 
     backer = ofproto_dpif_cast(ofport->up.ofproto)->backer;
-    backer->need_revalidate = true;
+    backer->need_revalidate = REV_RECONFIGURE;
 
     if (ofport->peer) {
         ofport->peer->peer = NULL;
@@ -2955,10 +2954,7 @@ port_run(struct ofport_dpif *ofport)
 
     if (ofport->may_enable != enable) {
         struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
-
-        if (ofproto->has_bundle_action) {
-            ofproto->backer->need_revalidate = REV_PORT_TOGGLED;
-        }
+        ofproto->backer->need_revalidate = REV_PORT_TOGGLED;
     }
 
     ofport->may_enable = enable;
@@ -3360,6 +3356,15 @@ flow_miss_should_make_facet(struct flow_miss *miss, struct flow_wildcards *wc)
     struct dpif_backer *backer = miss->ofproto->backer;
     uint32_t hash;
 
+    switch (flow_miss_model) {
+    case OFPROTO_HANDLE_MISS_AUTO:
+        break;
+    case OFPROTO_HANDLE_MISS_WITH_FACETS:
+        return true;
+    case OFPROTO_HANDLE_MISS_WITHOUT_FACETS:
+        return false;
+    }
+
     if (!backer->governor) {
         size_t n_subfacets;
 
@@ -5173,6 +5178,7 @@ rule_dpif_lookup_in_table(struct ofproto_dpif *ofproto,
     }
 
     if (wc) {
+        memset(&wc->masks.dl_type, 0xff, sizeof wc->masks.dl_type);
         wc->masks.nw_frag |= FLOW_NW_FRAG_MASK;
     }
 
@@ -5496,6 +5502,22 @@ update_mirror_stats(struct ofproto_dpif *ofproto, mirror_mask_t mirrors,
     }
 }
 
+tag_type
+calculate_flow_tag(struct ofproto_dpif *ofproto, const struct flow *flow,
+                   uint8_t table_id, struct rule_dpif *rule)
+{
+    if (table_id > 0 && table_id < N_TABLES) {
+        struct table_dpif *table = &ofproto->tables[table_id];
+        if (table->other_table) {
+            return (rule && rule->tag
+                    ? rule->tag
+                    : rule_calculate_tag(flow, &table->other_table->mask,
+                                         table->basis));
+        }
+    }
+
+    return 0;
+}
 \f
 /* Optimized flow revalidation.
  *
@@ -6556,7 +6578,7 @@ vlandev_find(const struct ofproto_dpif *ofproto, ofp_port_t vlandev_ofp_port)
     struct vlan_splinter *vsp;
 
     HMAP_FOR_EACH_WITH_HASH (vsp, vlandev_node,
-                             hash_int(ofp_to_u16(vlandev_ofp_port), 0),
+                             hash_ofp_port(vlandev_ofp_port),
                              &ofproto->vlandev_map) {
         if (vsp->vlandev_ofp_port == vlandev_ofp_port) {
             return vsp;
@@ -6647,7 +6669,7 @@ vsp_add(struct ofport_dpif *port, ofp_port_t realdev_ofp_port, int vid)
 
         vsp = xmalloc(sizeof *vsp);
         hmap_insert(&ofproto->vlandev_map, &vsp->vlandev_node,
-                    hash_int(ofp_to_u16(port->up.ofp_port), 0));
+                    hash_ofp_port(port->up.ofp_port));
         hmap_insert(&ofproto->realdev_vid_map, &vsp->realdev_vid_node,
                     hash_realdev_vid(realdev_ofp_port, vid));
         vsp->realdev_ofp_port = realdev_ofp_port;
@@ -6672,8 +6694,7 @@ odp_port_to_ofport(const struct dpif_backer *backer, odp_port_t odp_port)
 {
     struct ofport_dpif *port;
 
-    HMAP_FOR_EACH_IN_BUCKET (port, odp_port_node,
-                             hash_int(odp_to_u32(odp_port), 0),
+    HMAP_FOR_EACH_IN_BUCKET (port, odp_port_node, hash_odp_port(odp_port),
                              &backer->odp_to_ofport_map) {
         if (port->odp_port == odp_port) {
             return port;
@@ -6809,4 +6830,8 @@ const struct ofproto_class ofproto_dpif_class = {
     forward_bpdu_changed,
     set_mac_table_config,
     set_realdev,
+    NULL,                       /* meter_get_features */
+    NULL,                       /* meter_set */
+    NULL,                       /* meter_get */
+    NULL,                       /* meter_del */
 };