ofproto: Optionally flush all learning tables with appctl.
[sliver-openvswitch.git] / ofproto / ofproto-dpif.c
index f5280ff..9b06df0 100644 (file)
@@ -4634,8 +4634,11 @@ do_xlate_actions(const union ofp_action *in, size_t n_in,
             break;
 
         case OFPUTIL_OFPAT_SET_NW_TOS:
-            ctx->flow.nw_tos &= ~IP_DSCP_MASK;
-            ctx->flow.nw_tos |= ia->nw_tos.nw_tos & IP_DSCP_MASK;
+            /* OpenFlow 1.0 only supports IPv4. */
+            if (ctx->flow.dl_type == htons(ETH_TYPE_IP)) {
+                ctx->flow.nw_tos &= ~IP_DSCP_MASK;
+                ctx->flow.nw_tos |= ia->nw_tos.nw_tos & IP_DSCP_MASK;
+            }
             break;
 
         case OFPUTIL_OFPAT_SET_TP_SRC:
@@ -5534,15 +5537,24 @@ packet_out(struct ofproto *ofproto_, struct ofpbuf *packet,
                              ofproto->max_ports);
     if (!error) {
         struct odputil_keybuf keybuf;
-        struct action_xlate_ctx ctx;
         struct ofpbuf *odp_actions;
+        struct ofproto_push push;
         struct ofpbuf key;
 
         ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
         odp_flow_key_from_flow(&key, flow);
 
-        action_xlate_ctx_init(&ctx, ofproto, flow, flow->vlan_tci, 0, packet);
-        odp_actions = xlate_actions(&ctx, ofp_actions, n_ofp_actions);
+        action_xlate_ctx_init(&push.ctx, ofproto, flow, flow->vlan_tci, 0,
+                              packet);
+
+        /* Ensure that resubmits in 'ofp_actions' get accounted to their
+         * matching rules. */
+        push.packets = 1;
+        push.bytes = packet->size;
+        push.used = time_msec();
+        push.ctx.resubmit_hook = push_resubmit;
+
+        odp_actions = xlate_actions(&push.ctx, ofp_actions, n_ofp_actions);
         dpif_execute(ofproto->dpif, key.data, key.size,
                      odp_actions->data, odp_actions->size, packet);
         ofpbuf_delete(odp_actions);
@@ -5630,17 +5642,25 @@ 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)
 {
-    const struct ofproto_dpif *ofproto;
+    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->need_revalidate = true;
+    } else {
+        HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
+            mac_learning_flush(ofproto->ml);
+            ofproto->need_revalidate = true;
+        }
     }
-    mac_learning_flush(ofproto->ml);
 
     unixctl_command_reply(conn, 200, "table successfully flushed");
 }
@@ -5889,8 +5909,8 @@ ofproto_dpif_unixctl_init(void)
     unixctl_command_register(
         "ofproto/trace",
         "bridge {tun_id in_port packet | odp_flow [-generate]}",
-        2, 4, ofproto_unixctl_trace, NULL);
-    unixctl_command_register("fdb/flush", "bridge", 1, 1,
+        2, 5, ofproto_unixctl_trace, NULL);
+    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);