datapath: Use "OVS_*" as opposed to "ODP_*" for user<->kernel interactions.
[openvswitch] / ofproto / ofproto-dpif.c
index a865d21ca73641a4ca22bf09cc76d31104b989d5..f09c230d3c7b574149d287ddd014d363b5c0a4c5 100644 (file)
@@ -60,7 +60,7 @@ COVERAGE_DEFINE(facet_invalidated);
 COVERAGE_DEFINE(facet_revalidate);
 COVERAGE_DEFINE(facet_unexpected);
 
-/* Maximum depth of flow table recursion (due to NXAST_RESUBMIT actions) in a
+/* Maximum depth of flow table recursion (due to resubmit actions) in a
  * flow translation. */
 #define MAX_RESUBMIT_RECURSION 16
 
@@ -96,8 +96,8 @@ static struct rule_dpif *rule_dpif_cast(const struct rule *rule)
     return rule ? CONTAINER_OF(rule, struct rule_dpif, up) : NULL;
 }
 
-static struct rule_dpif *rule_dpif_lookup(struct ofproto_dpif *ofproto,
-                                          const struct flow *flow);
+static struct rule_dpif *rule_dpif_lookup(struct ofproto_dpif *,
+                                          const struct flow *, uint8_t table);
 
 #define MAX_MIRRORS 32
 typedef uint32_t mirror_mask_t;
@@ -188,6 +188,7 @@ struct action_xlate_ctx {
     uint32_t priority;          /* Current flow priority. 0 if none. */
     struct flow base_flow;      /* Flow at the last commit. */
     uint32_t base_priority;     /* Priority at the last commit. */
+    uint8_t table_id;           /* OpenFlow table ID where flow was found. */
 };
 
 static void action_xlate_ctx_init(struct action_xlate_ctx *,
@@ -206,12 +207,8 @@ struct facet {
      *     dpif_execute().
      *
      *   - Do include packets and bytes that were obtained from the datapath
-     *     when a flow was deleted (e.g. dpif_flow_del()) or when its
-     *     statistics were reset (e.g. dpif_flow_put() with
+     *     when its statistics were reset (e.g. dpif_flow_put() with
      *     DPIF_FP_ZERO_STATS).
-     *
-     *   - Do not include any packets or bytes that can currently be obtained
-     *     from the datapath by, e.g., dpif_flow_get().
      */
     uint64_t packet_count;       /* Number of packets received. */
     uint64_t byte_count;         /* Number of bytes received. */
@@ -223,10 +220,7 @@ struct facet {
     uint64_t rs_byte_count;      /* Bytes pushed to resubmit children. */
     long long int rs_used;       /* Used time pushed to resubmit children. */
 
-    /* Number of bytes passed to account_cb.  This may include bytes that can
-     * currently obtained from the datapath (thus, it can be greater than
-     * byte_count). */
-    uint64_t accounted_bytes;
+    uint64_t accounted_bytes;    /* Bytes processed by facet_account(). */
 
     struct hmap_node hmap_node;  /* In owning ofproto's 'facets' hmap. */
     struct list list_node;       /* In owning rule's 'facets' list. */
@@ -268,10 +262,10 @@ static void facet_update_time(struct ofproto_dpif *, struct facet *,
                               long long int used);
 static void facet_update_stats(struct ofproto_dpif *, struct facet *,
                                const struct dpif_flow_stats *);
+static void facet_reset_counters(struct facet *);
 static void facet_reset_dp_stats(struct facet *, struct dpif_flow_stats *);
 static void facet_push_stats(struct facet *);
-static void facet_account(struct ofproto_dpif *, struct facet *,
-                          uint64_t extra_bytes);
+static void facet_account(struct ofproto_dpif *, struct facet *);
 
 static bool facet_is_controller_flow(struct facet *);
 
@@ -565,6 +559,8 @@ run(struct ofproto *ofproto_)
         bundle_run(bundle);
     }
 
+    mac_learning_run(ofproto->ml, &ofproto->revalidate_set);
+
     /* Now revalidate if there's anything to do. */
     if (ofproto->need_revalidate
         || !tag_set_is_empty(&ofproto->revalidate_set)) {
@@ -612,6 +608,7 @@ wait(struct ofproto *ofproto_)
     HMAP_FOR_EACH (bundle, hmap_node, &ofproto->bundles) {
         bundle_wait(bundle);
     }
+    mac_learning_wait(ofproto->ml);
     if (ofproto->need_revalidate) {
         /* Shouldn't happen, but if it does just go around again. */
         VLOG_DBG_RL(&rl, "need revalidate in ofproto_wait_cb()");
@@ -663,7 +660,7 @@ static void
 get_tables(struct ofproto *ofproto_, struct ofp_table_stats *ots)
 {
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
-    struct odp_stats s;
+    struct ovs_dp_stats s;
 
     strcpy(ots->name, "classifier");
 
@@ -1394,6 +1391,14 @@ is_mirror_output_bundle(struct ofproto *ofproto_, void *aux)
     struct ofbundle *bundle = bundle_lookup(ofproto, aux);
     return bundle && bundle->mirror_out != 0;
 }
+
+static void
+forward_bpdu_changed(struct ofproto *ofproto_)
+{
+    struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
+    /* Revalidate cached flows whenever forward_bpdu option changes. */
+    ofproto->need_revalidate = true;
+}
 \f
 /* Ports. */
 
@@ -1649,12 +1654,12 @@ handle_miss_upcall(struct ofproto_dpif *ofproto, struct dpif_upcall *upcall)
     /* Check with in-band control to see if this packet should be sent
      * to the local port regardless of the flow table. */
     if (connmgr_msg_in_hook(ofproto->up.connmgr, &flow, upcall->packet)) {
-        send_packet(ofproto, ODPP_LOCAL, upcall->packet);
+        send_packet(ofproto, OVSP_LOCAL, upcall->packet);
     }
 
     facet = facet_lookup_valid(ofproto, &flow);
     if (!facet) {
-        struct rule_dpif *rule = rule_dpif_lookup(ofproto, &flow);
+        struct rule_dpif *rule = rule_dpif_lookup(ofproto, &flow, 0);
         if (!rule) {
             /* Don't send a packet-in if OFPPC_NO_PACKET_IN asserted. */
             struct ofport_dpif *port = get_ofp_port(ofproto, flow.in_port);
@@ -1812,7 +1817,7 @@ update_stats(struct ofproto_dpif *p)
 
             ds_init(&s);
             odp_flow_key_format(key, key_len, &s);
-            VLOG_WARN_RL(&rl, "failed to convert ODP flow key to flow: %s",
+            VLOG_WARN_RL(&rl, "failed to convert datapath flow key to flow: %s",
                          ds_cstr(&s));
             ds_destroy(&s);
 
@@ -1839,7 +1844,7 @@ update_stats(struct ofproto_dpif *p)
             facet->dp_byte_count = stats->n_bytes;
 
             facet_update_time(p, facet, stats->used);
-            facet_account(p, facet, stats->n_bytes);
+            facet_account(p, facet);
             facet_push_stats(facet);
         } else {
             /* There's a flow in the datapath that we know nothing about.
@@ -2054,7 +2059,7 @@ execute_odp_actions(struct ofproto_dpif *ofproto, const struct flow *flow,
                     struct ofpbuf *packet)
 {
     if (actions_len == NLA_ALIGN(NLA_HDRLEN + sizeof(uint64_t))
-        && odp_actions->nla_type == ODP_ACTION_ATTR_USERSPACE) {
+        && odp_actions->nla_type == OVS_ACTION_ATTR_USERSPACE) {
         /* As an optimization, avoid a round-trip from userspace to kernel to
          * userspace.  This also avoids possibly filling up kernel packet
          * buffers along the way. */
@@ -2096,8 +2101,8 @@ execute_odp_actions(struct ofproto_dpif *ofproto, const struct flow *flow,
  * applying flow_extract() to 'packet' would yield the same flow as
  * 'facet->flow'.
  *
- * 'facet' must have accurately composed ODP actions; that is, it must not be
- * in need of revalidation.
+ * 'facet' must have accurately composed datapath actions; that is, it must
+ * not be in need of revalidation.
  *
  * Takes ownership of 'packet'. */
 static void
@@ -2133,7 +2138,7 @@ facet_remove(struct ofproto_dpif *ofproto, struct facet *facet)
     facet_free(facet);
 }
 
-/* Composes the ODP actions for 'facet' based on its rule's actions. */
+/* Composes the datapath actions for 'facet' based on its rule's actions. */
 static void
 facet_make_actions(struct ofproto_dpif *p, struct facet *facet,
                    const struct ofpbuf *packet)
@@ -2214,10 +2219,9 @@ vlan_tci_to_openflow_vlan(ovs_be16 vlan_tci)
 }
 
 static void
-facet_account(struct ofproto_dpif *ofproto,
-              struct facet *facet, uint64_t extra_bytes)
+facet_account(struct ofproto_dpif *ofproto, struct facet *facet)
 {
-    uint64_t total_bytes, n_bytes;
+    uint64_t n_bytes;
     struct ofbundle *in_bundle;
     const struct nlattr *a;
     tag_type dummy = 0;
@@ -2225,12 +2229,11 @@ facet_account(struct ofproto_dpif *ofproto,
     ovs_be16 vlan_tci;
     int vlan;
 
-    total_bytes = facet->byte_count + extra_bytes;
-    if (total_bytes <= facet->accounted_bytes) {
+    if (facet->byte_count <= facet->accounted_bytes) {
         return;
     }
-    n_bytes = total_bytes - facet->accounted_bytes;
-    facet->accounted_bytes = total_bytes;
+    n_bytes = facet->byte_count - facet->accounted_bytes;
+    facet->accounted_bytes = facet->byte_count;
 
     /* Test that 'tags' is nonzero to ensure that only flows that include an
      * OFPP_NORMAL action are used for learning and bond slave rebalancing.
@@ -2261,7 +2264,7 @@ facet_account(struct ofproto_dpif *ofproto,
         struct ofport_dpif *port;
 
         switch (nl_attr_type(a)) {
-        case ODP_ACTION_ATTR_OUTPUT:
+        case OVS_ACTION_ATTR_OUTPUT:
             port = get_odp_port(ofproto, nl_attr_get_u32(a));
             if (port && port->bundle && port->bundle->bond) {
                 bond_account(port->bundle->bond, &facet->flow,
@@ -2269,11 +2272,11 @@ facet_account(struct ofproto_dpif *ofproto,
             }
             break;
 
-        case ODP_ACTION_ATTR_STRIP_VLAN:
+        case OVS_ACTION_ATTR_STRIP_VLAN:
             vlan_tci = htons(0);
             break;
 
-        case ODP_ACTION_ATTR_SET_DL_TCI:
+        case OVS_ACTION_ATTR_SET_DL_TCI:
             vlan_tci = nl_attr_get_be16(a);
             break;
         }
@@ -2346,7 +2349,7 @@ facet_flush_stats(struct ofproto_dpif *ofproto, struct facet *facet)
     assert(!facet->dp_packet_count);
 
     facet_push_stats(facet);
-    facet_account(ofproto, facet, 0);
+    facet_account(ofproto, facet);
 
     if (ofproto->netflow && !facet_is_controller_flow(facet)) {
         struct ofexpired expired;
@@ -2362,11 +2365,7 @@ facet_flush_stats(struct ofproto_dpif *ofproto, struct facet *facet)
 
     /* Reset counters to prevent double counting if 'facet' ever gets
      * reinstalled. */
-    facet->packet_count = 0;
-    facet->byte_count = 0;
-    facet->rs_packet_count = 0;
-    facet->rs_byte_count = 0;
-    facet->accounted_bytes = 0;
+    facet_reset_counters(facet);
 
     netflow_flow_clear(&facet->nf_flow);
 }
@@ -2434,14 +2433,14 @@ facet_revalidate(struct ofproto_dpif *ofproto, struct facet *facet)
     COVERAGE_INC(facet_revalidate);
 
     /* Determine the new rule. */
-    new_rule = rule_dpif_lookup(ofproto, &facet->flow);
+    new_rule = rule_dpif_lookup(ofproto, &facet->flow, 0);
     if (!new_rule) {
         /* No new rule, so delete the facet. */
         facet_remove(ofproto, facet);
         return false;
     }
 
-    /* Calculate new ODP actions.
+    /* Calculate new datapath actions.
      *
      * We do not modify any 'facet' state yet, because we might need to, e.g.,
      * emit a NetFlow expiration and, if so, we need to have the old state
@@ -2453,8 +2452,8 @@ facet_revalidate(struct ofproto_dpif *ofproto, struct facet *facet)
                        || memcmp(facet->actions, odp_actions->data,
                                  facet->actions_len));
 
-    /* If the ODP actions changed or the installability changed, then we need
-     * to talk to the datapath. */
+    /* If the datapath actions changed or the installability changed,
+     * then we need to talk to the datapath. */
     if (actions_changed || ctx.may_set_up_flow != facet->installed) {
         if (ctx.may_set_up_flow) {
             struct dpif_flow_stats stats;
@@ -2528,6 +2527,16 @@ facet_update_stats(struct ofproto_dpif *ofproto, struct facet *facet,
     }
 }
 
+static void
+facet_reset_counters(struct facet *facet)
+{
+    facet->packet_count = 0;
+    facet->byte_count = 0;
+    facet->rs_packet_count = 0;
+    facet->rs_byte_count = 0;
+    facet->accounted_bytes = 0;
+}
+
 static void
 facet_push_stats(struct facet *facet)
 {
@@ -2592,10 +2601,11 @@ flow_push_stats(const struct rule_dpif *rule,
 /* Rules. */
 
 static struct rule_dpif *
-rule_dpif_lookup(struct ofproto_dpif *ofproto, const struct flow *flow)
+rule_dpif_lookup(struct ofproto_dpif *ofproto, const struct flow *flow,
+                 uint8_t table_id)
 {
     return rule_dpif_cast(rule_from_cls_rule(
-                              classifier_lookup(&ofproto->up.tables[0],
+                              classifier_lookup(&ofproto->up.tables[table_id],
                                                 flow)));
 }
 
@@ -2653,6 +2663,13 @@ rule_construct(struct rule *rule_)
         rule->facets = victim->facets;
         list_moved(&rule->facets);
         LIST_FOR_EACH (facet, list_node, &rule->facets) {
+            /* XXX: We're only clearing our local counters here.  It's possible
+             * that quite a few packets are unaccounted for in the datapath
+             * statistics.  These will be accounted to the new rule instead of
+             * cleared as required.  This could be fixed by clearing out the
+             * datapath statistics for this facet, but currently it doesn't
+             * seem worth it. */
+            facet_reset_counters(facet);
             facet->rule = rule;
         }
     } else {
@@ -2717,7 +2734,7 @@ rule_execute(struct rule *rule_, struct flow *flow, struct ofpbuf *packet)
 
     /* Otherwise, if 'rule' is in fact the correct rule for 'packet', then
      * create a new facet for it and use that. */
-    if (rule_dpif_lookup(ofproto, flow) == rule) {
+    if (rule_dpif_lookup(ofproto, flow, 0) == rule) {
         facet = facet_create(rule, flow, packet);
         facet_execute(ofproto, facet, packet);
         facet_install(ofproto, facet, true);
@@ -2774,7 +2791,7 @@ send_packet(struct ofproto_dpif *ofproto, uint32_t odp_port,
     odp_flow_key_from_flow(&key, &flow);
 
     ofpbuf_init(&odp_actions, 32);
-    nl_msg_put_u32(&odp_actions, ODP_ACTION_ATTR_OUTPUT, odp_port);
+    nl_msg_put_u32(&odp_actions, OVS_ACTION_ATTR_OUTPUT, odp_port);
     error = dpif_execute(ofproto->dpif,
                          key.data, key.size,
                          odp_actions.data, odp_actions.size,
@@ -2788,7 +2805,7 @@ send_packet(struct ofproto_dpif *ofproto, uint32_t odp_port,
     return error;
 }
 \f
-/* OpenFlow to ODP action translation. */
+/* OpenFlow to datapath action translation. */
 
 static void do_xlate_actions(const union ofp_action *in, size_t n_in,
                              struct action_xlate_ctx *ctx);
@@ -2802,63 +2819,63 @@ commit_odp_actions(struct action_xlate_ctx *ctx)
     struct ofpbuf *odp_actions = ctx->odp_actions;
 
     if (base->tun_id != flow->tun_id) {
-        nl_msg_put_be64(odp_actions, ODP_ACTION_ATTR_SET_TUNNEL, flow->tun_id);
+        nl_msg_put_be64(odp_actions, OVS_ACTION_ATTR_SET_TUNNEL, flow->tun_id);
         base->tun_id = flow->tun_id;
     }
 
     if (base->nw_src != flow->nw_src) {
-        nl_msg_put_be32(odp_actions, ODP_ACTION_ATTR_SET_NW_SRC, flow->nw_src);
+        nl_msg_put_be32(odp_actions, OVS_ACTION_ATTR_SET_NW_SRC, flow->nw_src);
         base->nw_src = flow->nw_src;
     }
 
     if (base->nw_dst != flow->nw_dst) {
-        nl_msg_put_be32(odp_actions, ODP_ACTION_ATTR_SET_NW_DST, flow->nw_dst);
+        nl_msg_put_be32(odp_actions, OVS_ACTION_ATTR_SET_NW_DST, flow->nw_dst);
         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);
+        nl_msg_put_u8(odp_actions, OVS_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);
+            nl_msg_put_flag(odp_actions, OVS_ACTION_ATTR_STRIP_VLAN);
         } else {
-            nl_msg_put_be16(odp_actions, ODP_ACTION_ATTR_SET_DL_TCI,
+            nl_msg_put_be16(odp_actions, OVS_ACTION_ATTR_SET_DL_TCI,
                             flow->vlan_tci & ~htons(VLAN_CFI));
         }
         base->vlan_tci = flow->vlan_tci;
     }
 
     if (base->tp_src != flow->tp_src) {
-        nl_msg_put_be16(odp_actions, ODP_ACTION_ATTR_SET_TP_SRC, flow->tp_src);
+        nl_msg_put_be16(odp_actions, OVS_ACTION_ATTR_SET_TP_SRC, flow->tp_src);
         base->tp_src = flow->tp_src;
     }
 
     if (base->tp_dst != flow->tp_dst) {
-        nl_msg_put_be16(odp_actions, ODP_ACTION_ATTR_SET_TP_DST, flow->tp_dst);
+        nl_msg_put_be16(odp_actions, OVS_ACTION_ATTR_SET_TP_DST, flow->tp_dst);
         base->tp_dst = flow->tp_dst;
     }
 
     if (!eth_addr_equals(base->dl_src, flow->dl_src)) {
-        nl_msg_put_unspec(odp_actions, ODP_ACTION_ATTR_SET_DL_SRC,
+        nl_msg_put_unspec(odp_actions, OVS_ACTION_ATTR_SET_DL_SRC,
                           flow->dl_src, ETH_ADDR_LEN);
         memcpy(base->dl_src, flow->dl_src, ETH_ADDR_LEN);
     }
 
     if (!eth_addr_equals(base->dl_dst, flow->dl_dst)) {
-        nl_msg_put_unspec(odp_actions, ODP_ACTION_ATTR_SET_DL_DST,
+        nl_msg_put_unspec(odp_actions, OVS_ACTION_ATTR_SET_DL_DST,
                           flow->dl_dst, ETH_ADDR_LEN);
         memcpy(base->dl_dst, flow->dl_dst, ETH_ADDR_LEN);
     }
 
     if (ctx->base_priority != ctx->priority) {
         if (ctx->priority) {
-            nl_msg_put_u32(odp_actions, ODP_ACTION_ATTR_SET_PRIORITY,
+            nl_msg_put_u32(odp_actions, OVS_ACTION_ATTR_SET_PRIORITY,
                            ctx->priority);
         } else {
-            nl_msg_put_flag(odp_actions, ODP_ACTION_ATTR_POP_PRIORITY);
+            nl_msg_put_flag(odp_actions, OVS_ACTION_ATTR_POP_PRIORITY);
         }
         ctx->base_priority = ctx->priority;
     }
@@ -2884,23 +2901,28 @@ add_output_action(struct action_xlate_ctx *ctx, uint16_t ofp_port)
     }
 
     commit_odp_actions(ctx);
-    nl_msg_put_u32(ctx->odp_actions, ODP_ACTION_ATTR_OUTPUT, odp_port);
+    nl_msg_put_u32(ctx->odp_actions, OVS_ACTION_ATTR_OUTPUT, odp_port);
     ctx->nf_output_iface = ofp_port;
 }
 
 static void
-xlate_table_action(struct action_xlate_ctx *ctx, uint16_t in_port)
+xlate_table_action(struct action_xlate_ctx *ctx,
+                   uint16_t in_port, uint8_t table_id)
 {
     if (ctx->recurse < MAX_RESUBMIT_RECURSION) {
         struct rule_dpif *rule;
         uint16_t old_in_port;
+        uint8_t old_table_id;
+
+        old_table_id = ctx->table_id;
+        ctx->table_id = table_id;
 
         /* Look up a flow with 'in_port' as the input port.  Then restore the
          * original input port (otherwise OFPP_NORMAL and OFPP_IN_PORT will
          * have surprising behavior). */
         old_in_port = ctx->flow.in_port;
         ctx->flow.in_port = in_port;
-        rule = rule_dpif_lookup(ctx->ofproto, &ctx->flow);
+        rule = rule_dpif_lookup(ctx->ofproto, &ctx->flow, table_id);
         ctx->flow.in_port = old_in_port;
 
         if (ctx->resubmit_hook) {
@@ -2912,14 +2934,31 @@ xlate_table_action(struct action_xlate_ctx *ctx, uint16_t in_port)
             do_xlate_actions(rule->up.actions, rule->up.n_actions, ctx);
             ctx->recurse--;
         }
+
+        ctx->table_id = old_table_id;
     } else {
         static struct vlog_rate_limit recurse_rl = VLOG_RATE_LIMIT_INIT(1, 1);
 
-        VLOG_ERR_RL(&recurse_rl, "NXAST_RESUBMIT recursed over %d times",
+        VLOG_ERR_RL(&recurse_rl, "resubmit actions recursed over %d times",
                     MAX_RESUBMIT_RECURSION);
     }
 }
 
+static void
+xlate_resubmit_table(struct action_xlate_ctx *ctx,
+                     const struct nx_action_resubmit *nar)
+{
+    uint16_t in_port;
+    uint8_t table_id;
+
+    in_port = (nar->in_port == htons(OFPP_IN_PORT)
+               ? ctx->flow.in_port
+               : ntohs(nar->in_port));
+    table_id = nar->table == 255 ? ctx->table_id : nar->table;
+
+    xlate_table_action(ctx, in_port, table_id);
+}
+
 static void
 flood_packets(struct action_xlate_ctx *ctx, ovs_be32 mask)
 {
@@ -2929,7 +2968,7 @@ flood_packets(struct action_xlate_ctx *ctx, ovs_be32 mask)
     HMAP_FOR_EACH (ofport, up.hmap_node, &ctx->ofproto->up.ports) {
         uint16_t ofp_port = ofport->up.ofp_port;
         if (ofp_port != ctx->flow.in_port && !(ofport->up.opp.config & mask)) {
-            nl_msg_put_u32(ctx->odp_actions, ODP_ACTION_ATTR_OUTPUT,
+            nl_msg_put_u32(ctx->odp_actions, OVS_ACTION_ATTR_OUTPUT,
                            ofport->odp_port);
         }
     }
@@ -2950,7 +2989,7 @@ xlate_output_action__(struct action_xlate_ctx *ctx,
         add_output_action(ctx, ctx->flow.in_port);
         break;
     case OFPP_TABLE:
-        xlate_table_action(ctx, ctx->flow.in_port);
+        xlate_table_action(ctx, ctx->flow.in_port, ctx->table_id);
         break;
     case OFPP_NORMAL:
         xlate_normal(ctx);
@@ -2963,7 +3002,7 @@ xlate_output_action__(struct action_xlate_ctx *ctx,
         break;
     case OFPP_CONTROLLER:
         commit_odp_actions(ctx);
-        nl_msg_put_u64(ctx->odp_actions, ODP_ACTION_ATTR_USERSPACE, max_len);
+        nl_msg_put_u64(ctx->odp_actions, OVS_ACTION_ATTR_USERSPACE, max_len);
         break;
     case OFPP_LOCAL:
         add_output_action(ctx, OFPP_LOCAL);
@@ -2987,6 +3026,19 @@ xlate_output_action__(struct action_xlate_ctx *ctx,
     }
 }
 
+static void
+xlate_output_reg_action(struct action_xlate_ctx *ctx,
+                        const struct nx_action_output_reg *naor)
+{
+    uint64_t ofp_port;
+
+    ofp_port = nxm_read_field_bits(naor->src, naor->ofs_nbits, &ctx->flow);
+
+    if (ofp_port <= UINT16_MAX) {
+        xlate_output_action__(ctx, ofp_port, ntohs(naor->max_len));
+    }
+}
+
 static void
 xlate_output_action(struct action_xlate_ctx *ctx,
                     const struct ofp_action_output *oao)
@@ -3010,14 +3062,14 @@ xlate_enqueue_action(struct action_xlate_ctx *ctx,
         return;
     }
 
-    /* Figure out ODP output port. */
+    /* Figure out datapath output port. */
     ofp_port = ntohs(oae->port);
     if (ofp_port == OFPP_IN_PORT) {
         ofp_port = ctx->flow.in_port;
     }
     odp_port = ofp_port_to_odp_port(ofp_port);
 
-    /* Add ODP actions. */
+    /* Add datapath actions. */
     ctx_priority = ctx->priority;
     ctx->priority = priority;
     add_output_action(ctx, odp_port);
@@ -3122,6 +3174,7 @@ do_xlate_actions(const union ofp_action *in, size_t n_in,
         const struct nx_action_multipath *nam;
         const struct nx_action_autopath *naa;
         const struct nx_action_bundle *nab;
+        const struct nx_action_output_reg *naor;
         enum ofputil_action_code code;
         ovs_be64 tun_id;
 
@@ -3182,7 +3235,11 @@ do_xlate_actions(const union ofp_action *in, size_t n_in,
 
         case OFPUTIL_NXAST_RESUBMIT:
             nar = (const struct nx_action_resubmit *) ia;
-            xlate_table_action(ctx, ntohs(nar->in_port));
+            xlate_table_action(ctx, ntohs(nar->in_port), ctx->table_id);
+            break;
+
+        case OFPUTIL_NXAST_RESUBMIT_TABLE:
+            xlate_resubmit_table(ctx, (const struct nx_action_resubmit *) ia);
             break;
 
         case OFPUTIL_NXAST_SET_TUNNEL:
@@ -3243,6 +3300,11 @@ do_xlate_actions(const union ofp_action *in, size_t n_in,
             bundle_execute_load(nab, &ctx->flow, slave_enabled_cb,
                                 ctx->ofproto);
             break;
+
+        case OFPUTIL_NXAST_OUTPUT_REG:
+            naor = (const struct nx_action_output_reg *) ia;
+            xlate_output_reg_action(ctx, naor);
+            break;
         }
     }
 }
@@ -3272,6 +3334,7 @@ xlate_actions(struct action_xlate_ctx *ctx,
     ctx->priority = 0;
     ctx->base_priority = 0;
     ctx->base_flow = ctx->flow;
+    ctx->table_id = 0;
 
     if (process_special(ctx->ofproto, &ctx->flow, ctx->packet)) {
         ctx->may_set_up_flow = false;
@@ -3565,7 +3628,7 @@ compose_actions(struct action_xlate_ctx *ctx, uint16_t vlan,
             continue;
         }
         nl_msg_put_u32(ctx->odp_actions,
-                       ODP_ACTION_ATTR_OUTPUT, dst->port->odp_port);
+                       OVS_ACTION_ATTR_OUTPUT, dst->port->odp_port);
     }
 
     /* Then output the rest. */
@@ -3576,18 +3639,18 @@ compose_actions(struct action_xlate_ctx *ctx, uint16_t vlan,
         }
         if (dst->vlan != cur_vlan) {
             if (dst->vlan == OFP_VLAN_NONE) {
-                nl_msg_put_flag(ctx->odp_actions, ODP_ACTION_ATTR_STRIP_VLAN);
+                nl_msg_put_flag(ctx->odp_actions, OVS_ACTION_ATTR_STRIP_VLAN);
             } else {
                 ovs_be16 tci;
                 tci = htons(dst->vlan & VLAN_VID_MASK);
                 tci |= ctx->flow.vlan_tci & htons(VLAN_PCP_MASK);
                 nl_msg_put_be16(ctx->odp_actions,
-                                ODP_ACTION_ATTR_SET_DL_TCI, tci);
+                                OVS_ACTION_ATTR_SET_DL_TCI, tci);
             }
             cur_vlan = dst->vlan;
         }
         nl_msg_put_u32(ctx->odp_actions,
-                       ODP_ACTION_ATTR_OUTPUT, dst->port->odp_port);
+                       OVS_ACTION_ATTR_OUTPUT, dst->port->odp_port);
     }
 
     dst_set_free(&set);
@@ -3740,8 +3803,10 @@ is_admissible(struct ofproto_dpif *ofproto, const struct flow *flow,
         return false;
     }
 
-    /* Drop frames for reserved multicast addresses. */
-    if (eth_addr_is_reserved(flow->dl_dst)) {
+    /* Drop frames for reserved multicast addresses
+     * only if forward_bpdu option is absent. */
+    if (eth_addr_is_reserved(flow->dl_dst) &&
+        !ofproto->up.forward_bpdu) {
         return false;
     }
 
@@ -3925,7 +3990,8 @@ struct ofproto_trace {
 };
 
 static void
-trace_format_rule(struct ds *result, int level, const struct rule_dpif *rule)
+trace_format_rule(struct ds *result, uint8_t table_id, int level,
+                  const struct rule_dpif *rule)
 {
     ds_put_char_multiple(result, '\t', level);
     if (!rule) {
@@ -3933,8 +3999,8 @@ trace_format_rule(struct ds *result, int level, const struct rule_dpif *rule)
         return;
     }
 
-    ds_put_format(result, "Rule: cookie=%#"PRIx64" ",
-                  ntohll(rule->up.flow_cookie));
+    ds_put_format(result, "Rule: table=%"PRIu8" cookie=%#"PRIx64" ",
+                  table_id, ntohll(rule->up.flow_cookie));
     cls_rule_format(&rule->up.cr, result);
     ds_put_char(result, '\n');
 
@@ -3959,6 +4025,20 @@ trace_format_flow(struct ds *result, int level, const char *title,
     ds_put_char(result, '\n');
 }
 
+static void
+trace_format_regs(struct ds *result, int level, const char *title,
+                  struct ofproto_trace *trace)
+{
+    size_t i;
+
+    ds_put_char_multiple(result, '\t', level);
+    ds_put_format(result, "%s:", title);
+    for (i = 0; i < FLOW_N_REGS; i++) {
+        ds_put_format(result, " reg%zu=0x%"PRIx32, i, trace->flow.regs[i]);
+    }
+    ds_put_char(result, '\n');
+}
+
 static void
 trace_resubmit(struct action_xlate_ctx *ctx, struct rule_dpif *rule)
 {
@@ -3967,7 +4047,8 @@ trace_resubmit(struct action_xlate_ctx *ctx, struct rule_dpif *rule)
 
     ds_put_char(result, '\n');
     trace_format_flow(result, ctx->recurse + 1, "Resubmitted flow", trace);
-    trace_format_rule(result, ctx->recurse + 1, rule);
+    trace_format_regs(result, ctx->recurse + 1, "Resubmitted regs", trace);
+    trace_format_rule(result, ctx->table_id, ctx->recurse + 1, rule);
 }
 
 static void
@@ -3997,7 +4078,7 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, const char *args_,
         /* ofproto/trace dpname flow */
         int error;
 
-        /* Convert string to ODP key. */
+        /* Convert string to datapath key. */
         ofpbuf_init(&odp_key, 0);
         error = odp_flow_key_from_string(arg1, &odp_key);
         if (error) {
@@ -4054,8 +4135,8 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, const char *args_,
     flow_format(&result, &flow);
     ds_put_char(&result, '\n');
 
-    rule = rule_dpif_lookup(ofproto, &flow);
-    trace_format_rule(&result, 0, rule);
+    rule = rule_dpif_lookup(ofproto, &flow, 0);
+    trace_format_rule(&result, 0, 0, rule);
     if (rule) {
         struct ofproto_trace trace;
         struct ofpbuf *odp_actions;
@@ -4173,4 +4254,5 @@ const struct ofproto_class ofproto_dpif_class = {
     mirror_set,
     set_flood_vlans,
     is_mirror_output_bundle,
+    forward_bpdu_changed,
 };