ofproto-dpif: Add helper function to retrieve a subfacet from a facet.
[sliver-openvswitch.git] / ofproto / ofproto-dpif.c
index 79088db..56b55f6 100644 (file)
@@ -487,7 +487,9 @@ struct facet {
 
     /* Storage for a single subfacet, to reduce malloc() time and space
      * overhead.  (A facet always has at least one subfacet and in the common
-     * case has exactly one subfacet.) */
+     * case has exactly one subfacet.  However, 'one_subfacet' may not
+     * always be valid, since it could have been removed after newer
+     * subfacets were pushed onto the 'subfacets' list.) */
     struct subfacet one_subfacet;
 };
 
@@ -511,6 +513,8 @@ static void facet_push_stats(struct facet *);
 static void facet_learn(struct facet *);
 static void facet_account(struct facet *);
 
+static struct subfacet *facet_get_subfacet(struct facet *);
+
 static bool facet_is_controller_flow(struct facet *);
 
 struct ofport_dpif {
@@ -4439,7 +4443,7 @@ static void
 facet_account(struct facet *facet)
 {
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(facet->rule->up.ofproto);
-    struct subfacet *subfacet;
+    struct subfacet *subfacet = facet_get_subfacet(facet);
     const struct nlattr *a;
     unsigned int left;
     ovs_be16 vlan_tci;
@@ -4458,8 +4462,6 @@ facet_account(struct facet *facet)
      *
      * We use the actions from an arbitrary subfacet because they should all
      * be equally valid for our purpose. */
-    subfacet = CONTAINER_OF(list_front(&facet->subfacets),
-                            struct subfacet, list_node);
     vlan_tci = facet->flow.vlan_tci;
     NL_ATTR_FOR_EACH_UNSAFE (a, left,
                              subfacet->actions, subfacet->actions_len) {
@@ -4596,6 +4598,14 @@ facet_lookup_valid(struct ofproto_dpif *ofproto, const struct flow *flow,
     return facet;
 }
 
+/* Return a subfacet from 'facet'.  A facet consists of one or more
+ * subfacets, and this function returns one of them. */
+static struct subfacet *facet_get_subfacet(struct facet *facet)
+{
+    return CONTAINER_OF(list_front(&facet->subfacets), struct subfacet,
+                        list_node);
+}
+
 static const char *
 subfacet_path_to_string(enum subfacet_path path)
 {
@@ -4935,8 +4945,7 @@ flow_push_stats(struct facet *facet, const struct dpif_flow_stats *stats)
 {
     struct rule_dpif *rule = facet->rule;
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto);
-    struct subfacet *subfacet = CONTAINER_OF(list_front(&facet->subfacets),
-                                             struct subfacet, list_node);
+    struct subfacet *subfacet = facet_get_subfacet(facet);
     struct action_xlate_ctx ctx;
 
     ofproto_rule_update_used(&rule->up, stats->used);
@@ -6087,7 +6096,7 @@ execute_dec_mpls_ttl_action(struct action_xlate_ctx *ctx)
         return false;
     }
 
-    if (ttl > 0) {
+    if (ttl > 1) {
         ttl--;
         set_mpls_lse_ttl(&ctx->flow.mpls_lse, ttl);
         return false;
@@ -6321,11 +6330,15 @@ static bool
 tunnel_ecn_ok(struct action_xlate_ctx *ctx)
 {
     if (is_ip_any(&ctx->base_flow)
-        && (ctx->base_flow.tunnel.ip_tos & IP_ECN_MASK) == IP_ECN_CE
-        && (ctx->base_flow.nw_tos & IP_ECN_MASK) == IP_ECN_NOT_ECT) {
-        VLOG_WARN_RL(&rl, "dropping tunnel packet marked ECN CE but is not ECN"
-                     " capable");
-        return false;
+        && (ctx->base_flow.tunnel.ip_tos & IP_ECN_MASK) == IP_ECN_CE) {
+        if ((ctx->base_flow.nw_tos & IP_ECN_MASK) == IP_ECN_NOT_ECT) {
+            VLOG_WARN_RL(&rl, "dropping tunnel packet marked ECN CE"
+                         " but is not ECN capable");
+            return false;
+        } else {
+            /* Set the ECN CE value in the tunneled packet. */
+            ctx->flow.nw_tos |= IP_ECN_CE;
+        }
     }
 
     return true;