ofproto-dpif: Restore former NORMAL action behavior when revalidating.
[sliver-openvswitch.git] / ofproto / ofproto-dpif.c
index 42138b9..a700d5e 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "autopath.h"
 #include "bond.h"
+#include "bundle.h"
 #include "byte-order.h"
 #include "connmgr.h"
 #include "coverage.h"
@@ -332,6 +333,8 @@ struct ofproto_dpif {
 
     /* Support for debugging async flow mods. */
     struct list completions;
+
+    bool has_bundle_action; /* True when the first bundle action appears. */
 };
 
 /* Defer flow mod completion until "ovs-appctl ofproto/unclog"?  (Useful only
@@ -467,6 +470,8 @@ construct(struct ofproto *ofproto_)
 
     ofproto_dpif_unixctl_init();
 
+    ofproto->has_bundle_action = false;
+
     return 0;
 }
 
@@ -709,6 +714,7 @@ port_construct(struct ofport *port_)
     port->bundle = NULL;
     port->cfm = NULL;
     port->tag = tag_create_random();
+    port->may_enable = true;
 
     if (ofproto->sflow) {
         dpif_sflow_add_port(ofproto->sflow, port->odp_port,
@@ -1436,6 +1442,14 @@ port_run(struct ofport_dpif *ofport)
         enable = enable && lacp_slave_may_enable(ofport->bundle->lacp, ofport);
     }
 
+    if (ofport->may_enable != enable) {
+        struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
+
+        if (ofproto->has_bundle_action) {
+            ofproto->need_revalidate = true;
+        }
+    }
+
     ofport->may_enable = enable;
 }
 
@@ -2770,7 +2784,7 @@ send_packet(struct ofproto_dpif *ofproto, uint32_t odp_port,
 
 static void do_xlate_actions(const union ofp_action *in, size_t n_in,
                              struct action_xlate_ctx *ctx);
-static bool xlate_normal(struct action_xlate_ctx *);
+static void xlate_normal(struct action_xlate_ctx *);
 
 static void
 commit_odp_actions(struct action_xlate_ctx *ctx)
@@ -2794,6 +2808,11 @@ commit_odp_actions(struct action_xlate_ctx *ctx)
         base->nw_dst = flow->nw_dst;
     }
 
+    if (base->nw_tos != flow->nw_tos) {
+        nl_msg_put_u8(odp_actions, ODP_ACTION_ATTR_SET_NW_TOS, flow->nw_tos);
+        base->nw_tos = flow->nw_tos;
+    }
+
     if (base->vlan_tci != flow->vlan_tci) {
         if (!(flow->vlan_tci & htons(VLAN_CFI))) {
             nl_msg_put_flag(odp_actions, ODP_ACTION_ATTR_STRIP_VLAN);
@@ -3047,6 +3066,28 @@ xlate_autopath(struct action_xlate_ctx *ctx,
     autopath_execute(naa, &ctx->flow, ofp_port);
 }
 
+static bool
+slave_enabled_cb(uint16_t ofp_port, void *ofproto_)
+{
+    struct ofproto_dpif *ofproto = ofproto_;
+    struct ofport_dpif *port;
+
+    switch (ofp_port) {
+    case OFPP_IN_PORT:
+    case OFPP_TABLE:
+    case OFPP_NORMAL:
+    case OFPP_FLOOD:
+    case OFPP_ALL:
+    case OFPP_LOCAL:
+        return true;
+    case OFPP_CONTROLLER: /* Not supported by the bundle action. */
+        return false;
+    default:
+        port = get_ofp_port(ofproto, ofp_port);
+        return port ? port->may_enable : false;
+    }
+}
+
 static void
 do_xlate_actions(const union ofp_action *in, size_t n_in,
                  struct action_xlate_ctx *ctx)
@@ -3072,6 +3113,7 @@ do_xlate_actions(const union ofp_action *in, size_t n_in,
         const struct nx_action_set_queue *nasq;
         const struct nx_action_multipath *nam;
         const struct nx_action_autopath *naa;
+        const struct nx_action_bundle *nab;
         enum ofputil_action_code code;
         ovs_be64 tun_id;
 
@@ -3115,7 +3157,7 @@ do_xlate_actions(const union ofp_action *in, size_t n_in,
             break;
 
         case OFPUTIL_OFPAT_SET_NW_TOS:
-            ctx->flow.nw_tos = ia->nw_tos.nw_tos;
+            ctx->flow.nw_tos = ia->nw_tos.nw_tos & IP_DSCP_MASK;
             break;
 
         case OFPUTIL_OFPAT_SET_TP_SRC:
@@ -3178,6 +3220,21 @@ do_xlate_actions(const union ofp_action *in, size_t n_in,
             naa = (const struct nx_action_autopath *) ia;
             xlate_autopath(ctx, naa);
             break;
+
+        case OFPUTIL_NXAST_BUNDLE:
+            ctx->ofproto->has_bundle_action = true;
+            nab = (const struct nx_action_bundle *) ia;
+            xlate_output_action__(ctx, bundle_execute(nab, &ctx->flow,
+                                                      slave_enabled_cb,
+                                                      ctx->ofproto), 0);
+            break;
+
+        case OFPUTIL_NXAST_BUNDLE_LOAD:
+            ctx->ofproto->has_bundle_action = true;
+            nab = (const struct nx_action_bundle *) ia;
+            bundle_execute_load(nab, &ctx->flow, slave_enabled_cb,
+                                ctx->ofproto);
+            break;
         }
     }
 }
@@ -3319,7 +3376,8 @@ dst_is_duplicate(const struct dst_set *set, const struct dst *test)
 static bool
 ofbundle_trunks_vlan(const struct ofbundle *bundle, uint16_t vlan)
 {
-    return bundle->vlan < 0 && vlan_bitmap_contains(bundle->trunks, vlan);
+    return (bundle->vlan < 0
+            && (!bundle->trunks || bitmap_is_set(bundle->trunks, vlan)));
 }
 
 static bool
@@ -3365,7 +3423,7 @@ compose_dsts(struct action_xlate_ctx *ctx, uint16_t vlan,
 static bool
 vlan_is_mirrored(const struct ofmirror *m, int vlan)
 {
-    return vlan_bitmap_contains(m->vlans, vlan);
+    return !m->vlans || bitmap_is_set(m->vlans, vlan);
 }
 
 /* Returns true if a packet with Ethernet destination MAC 'dst' may be mirrored
@@ -3715,10 +3773,7 @@ is_admissible(struct ofproto_dpif *ofproto, const struct flow *flow,
     return true;
 }
 
-/* If the composed actions may be applied to any packet in the given 'flow',
- * returns true.  Otherwise, the actions should only be applied to 'packet', or
- * not at all, if 'packet' was NULL. */
-static bool
+static void
 xlate_normal(struct action_xlate_ctx *ctx)
 {
     struct ofbundle *in_bundle;
@@ -3749,7 +3804,8 @@ xlate_normal(struct action_xlate_ctx *ctx)
          * of time where we could learn from a packet reflected on a bond and
          * blackhole packets before the learning table is updated to reflect
          * the correct port. */
-        return false;
+        ctx->may_set_up_flow = false;
+        return;
     } else {
         out_bundle = OFBUNDLE_FLOOD;
     }
@@ -3763,8 +3819,6 @@ done:
     if (in_bundle) {
         compose_actions(ctx, vlan, in_bundle, out_bundle);
     }
-
-    return true;
 }
 \f
 static bool