meta-flow: New "subfield" data structure.
[sliver-openvswitch.git] / ofproto / ofproto-dpif.c
index 471ba64..a0c7b28 100644 (file)
@@ -34,6 +34,7 @@
 #include "lacp.h"
 #include "learn.h"
 #include "mac-learning.h"
+#include "meta-flow.h"
 #include "multipath.h"
 #include "netdev.h"
 #include "netlink.h"
@@ -1193,7 +1194,7 @@ update_stp_port_state(struct ofport_dpif *ofport)
         if (stp_learn_in_state(ofport->stp_state)
                 != stp_learn_in_state(state)) {
             /* xxx Learning action flows should also be flushed. */
-            mac_learning_flush(ofproto->ml);
+            mac_learning_flush(ofproto->ml, &ofproto->revalidate_set);
         }
         fwd_change = stp_forward_in_state(ofport->stp_state)
                         != stp_forward_in_state(state);
@@ -1296,6 +1297,10 @@ stp_run(struct ofproto_dpif *ofproto)
                 update_stp_port_state(ofport);
             }
         }
+
+        if (stp_check_and_reset_fdb_flush(ofproto->stp)) {
+            mac_learning_flush(ofproto->ml, &ofproto->revalidate_set);
+        }
     }
 }
 
@@ -2064,7 +2069,7 @@ mirror_set(struct ofproto *ofproto_, void *aux,
     }
 
     ofproto->need_revalidate = true;
-    mac_learning_flush(ofproto->ml);
+    mac_learning_flush(ofproto->ml, &ofproto->revalidate_set);
     mirror_update_dups(ofproto);
 
     return 0;
@@ -2083,7 +2088,7 @@ mirror_destroy(struct ofmirror *mirror)
 
     ofproto = mirror->ofproto;
     ofproto->need_revalidate = true;
-    mac_learning_flush(ofproto->ml);
+    mac_learning_flush(ofproto->ml, &ofproto->revalidate_set);
 
     mirror_bit = MIRROR_MASK_C(1) << mirror->idx;
     HMAP_FOR_EACH (bundle, hmap_node, &ofproto->bundles) {
@@ -2126,8 +2131,7 @@ set_flood_vlans(struct ofproto *ofproto_, unsigned long *flood_vlans)
 {
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
     if (mac_learning_set_flood_vlans(ofproto->ml, flood_vlans)) {
-        ofproto->need_revalidate = true;
-        mac_learning_flush(ofproto->ml);
+        mac_learning_flush(ofproto->ml, &ofproto->revalidate_set);
     }
     return 0;
 }
@@ -2421,7 +2425,7 @@ struct flow_miss_op {
  * OpenFlow controller as necessary according to their individual
  * configurations. */
 static void
-send_packet_in_miss(struct ofproto_dpif *ofproto, struct ofpbuf *packet,
+send_packet_in_miss(struct ofproto_dpif *ofproto, const struct ofpbuf *packet,
                     const struct flow *flow)
 {
     struct ofputil_packet_in pin;
@@ -2576,7 +2580,6 @@ handle_flow_miss(struct ofproto_dpif *ofproto, struct flow_miss *miss,
             continue;
         }
 
-        list_remove(&packet->list_node);
         if (flow->vlan_tci != subfacet->initial_tci) {
             /* This packet was received on a VLAN splinter port.  We added
              * a VLAN to the packet to make the packet resemble the flow,
@@ -2739,14 +2742,10 @@ handle_miss_upcalls(struct ofproto_dpif *ofproto, struct dpif_upcall *upcalls,
     /* Process each element in the to-do list, constructing the set of
      * operations to batch. */
     n_ops = 0;
-    HMAP_FOR_EACH_SAFE (miss, next_miss, hmap_node, &todo) {
+    HMAP_FOR_EACH (miss, hmap_node, &todo) {
         handle_flow_miss(ofproto, miss, flow_miss_ops, &n_ops);
-        ofpbuf_list_delete(&miss->packets);
-        hmap_remove(&todo, &miss->hmap_node);
-        free(miss);
     }
     assert(n_ops <= ARRAY_SIZE(flow_miss_ops));
-    hmap_destroy(&todo);
 
     /* Execute batch. */
     for (i = 0; i < n_ops; i++) {
@@ -2765,7 +2764,6 @@ handle_miss_upcalls(struct ofproto_dpif *ofproto, struct dpif_upcall *upcalls,
             if (op->subfacet->actions != execute->actions) {
                 free((struct nlattr *) execute->actions);
             }
-            ofpbuf_delete((struct ofpbuf *) execute->packet);
             break;
 
         case DPIF_OP_FLOW_PUT:
@@ -2775,6 +2773,12 @@ handle_miss_upcalls(struct ofproto_dpif *ofproto, struct dpif_upcall *upcalls,
             break;
         }
     }
+    HMAP_FOR_EACH_SAFE (miss, next_miss, hmap_node, &todo) {
+        ofpbuf_list_delete(&miss->packets);
+        hmap_remove(&todo, &miss->hmap_node);
+        free(miss);
+    }
+    hmap_destroy(&todo);
 }
 
 static void
@@ -4565,9 +4569,11 @@ static void
 xlate_output_reg_action(struct action_xlate_ctx *ctx,
                         const struct nx_action_output_reg *naor)
 {
+    struct mf_subfield src;
     uint64_t ofp_port;
 
-    ofp_port = nxm_read_field_bits(naor->src, naor->ofs_nbits, &ctx->flow);
+    nxm_decode(&src, naor->src, naor->ofs_nbits);
+    ofp_port = mf_get_subfield(&src, &ctx->flow);
 
     if (ofp_port <= UINT16_MAX) {
         xlate_output_action__(ctx, ofp_port, ntohs(naor->max_len));
@@ -5812,18 +5818,23 @@ ofproto_dpif_lookup(const char *name)
 }
 
 static void
-ofproto_unixctl_fdb_flush(struct unixctl_conn *conn, int argc OVS_UNUSED,
+ofproto_unixctl_fdb_flush(struct unixctl_conn *conn, int argc,
                           const char *argv[], void *aux OVS_UNUSED)
 {
     struct ofproto_dpif *ofproto;
 
-    ofproto = ofproto_dpif_lookup(argv[1]);
-    if (!ofproto) {
-        unixctl_command_reply(conn, 501, "no such bridge");
-        return;
+    if (argc > 1) {
+        ofproto = ofproto_dpif_lookup(argv[1]);
+        if (!ofproto) {
+            unixctl_command_reply(conn, 501, "no such bridge");
+            return;
+        }
+        mac_learning_flush(ofproto->ml, &ofproto->revalidate_set);
+    } else {
+        HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
+            mac_learning_flush(ofproto->ml, &ofproto->revalidate_set);
+        }
     }
-    mac_learning_flush(ofproto->ml);
-    ofproto->need_revalidate = true;
 
     unixctl_command_reply(conn, 200, "table successfully flushed");
 }
@@ -6124,7 +6135,7 @@ ofproto_dpif_unixctl_init(void)
         "ofproto/trace",
         "bridge {tun_id in_port packet | odp_flow [-generate]}",
         2, 5, ofproto_unixctl_trace, NULL);
-    unixctl_command_register("fdb/flush", "bridge", 1, 1,
+    unixctl_command_register("fdb/flush", "[bridge]", 0, 1,
                              ofproto_unixctl_fdb_flush, NULL);
     unixctl_command_register("fdb/show", "bridge", 1, 1,
                              ofproto_unixctl_fdb_show, NULL);