ofproto-dpif-monitor: Fix deadlock.
[sliver-openvswitch.git] / ofproto / ofproto-dpif-xlate.c
index 6a56a15..da538b7 100644 (file)
@@ -192,6 +192,10 @@ struct xlate_ctx {
     uint16_t user_cookie_offset;/* Used for user_action_cookie fixup. */
     bool exit;                  /* No further actions should be processed. */
 
+    bool use_recirc;            /* Should generate recirc? */
+    struct xlate_recirc recirc; /* Information used for generating
+                                 * recirculation actions */
+
     /* OpenFlow 1.1+ action set.
      *
      * 'action_set' accumulates "struct ofpact"s added by OFPACT_WRITE_ACTIONS.
@@ -770,8 +774,9 @@ xport_stp_listen_state(const struct xport *xport)
 static bool
 stp_should_process_flow(const struct flow *flow, struct flow_wildcards *wc)
 {
+    /* is_stp() also checks dl_type, but dl_type is always set in 'wc'. */
     memset(&wc->masks.dl_dst, 0xff, sizeof wc->masks.dl_dst);
-    return eth_addr_equals(flow->dl_dst, eth_addr_stp);
+    return is_stp(flow);
 }
 
 static void
@@ -970,9 +975,10 @@ lookup_input_bundle(const struct xbridge *xbridge, ofp_port_t in_port,
         return xport->xbundle;
     }
 
-    /* Special-case OFPP_NONE, which a controller may use as the ingress
-     * port for traffic that it is sourcing. */
-    if (in_port == OFPP_NONE) {
+    /* Special-case OFPP_NONE (OF1.0) and OFPP_CONTROLLER (OF1.1+),
+     * which a controller may use as the ingress port for traffic that
+     * it is sourcing. */
+    if (in_port == OFPP_CONTROLLER || in_port == OFPP_NONE) {
         return &ofpp_none_bundle;
     }
 
@@ -1207,19 +1213,19 @@ output_normal(struct xlate_ctx *ctx, const struct xbundle *out_xbundle,
         /* Partially configured bundle with no slaves.  Drop the packet. */
         return;
     } else if (!out_xbundle->bond) {
-        ctx->xout->use_recirc = false;
+        ctx->use_recirc = false;
         xport = CONTAINER_OF(list_front(&out_xbundle->xports), struct xport,
                              bundle_node);
     } else {
         struct ofport_dpif *ofport;
-        struct xlate_recirc *xr = &ctx->xout->recirc;
+        struct xlate_recirc *xr = &ctx->recirc;
         struct flow_wildcards *wc = &ctx->xout->wc;
 
         if (ctx->xbridge->enable_recirc) {
-            ctx->xout->use_recirc = bond_may_recirc(
+            ctx->use_recirc = bond_may_recirc(
                 out_xbundle->bond, &xr->recirc_id, &xr->hash_basis);
 
-            if (ctx->xout->use_recirc) {
+            if (ctx->use_recirc) {
                 /* Only TCP mode uses recirculation. */
                 xr->hash_alg = OVS_HASH_ALG_L4;
                 bond_update_post_recirc_rules(out_xbundle->bond, false);
@@ -1240,7 +1246,7 @@ output_normal(struct xlate_ctx *ctx, const struct xbundle *out_xbundle,
 
         /* If ctx->xout->use_recirc is set, the main thread will handle stats
          * accounting for this bond. */
-        if (!ctx->xout->use_recirc) {
+        if (!ctx->use_recirc) {
             if (ctx->xin->resubmit_stats) {
                 bond_account(out_xbundle->bond, &ctx->xin->flow, vid,
                              ctx->xin->resubmit_stats->n_bytes);
@@ -1772,11 +1778,7 @@ process_special(struct xlate_ctx *ctx, const struct flow *flow,
             bfd_process_packet(xport->bfd, flow, packet);
             /* If POLL received, immediately sends FINAL back. */
             if (bfd_should_send_packet(xport->bfd)) {
-                if (xport->peer) {
-                    ofproto_dpif_monitor_port_send_soon(xport->ofport);
-                } else {
-                    ofproto_dpif_monitor_port_send_soon_safe(xport->ofport);
-                }
+                ofproto_dpif_monitor_port_send_soon(xport->ofport);
             }
         }
         return SLOW_BFD;
@@ -1820,7 +1822,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
         xlate_report(ctx, "OFPPC_NO_FWD set, skipping output");
         return;
     } else if (check_stp) {
-        if (eth_addr_equals(ctx->base_flow.dl_dst, eth_addr_stp)) {
+        if (is_stp(&ctx->base_flow)) {
             if (!xport_stp_listen_state(xport)) {
                 xlate_report(ctx, "STP not in listening state, "
                              "skipping bpdu output");
@@ -1950,9 +1952,9 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
                                               &ctx->xout->odp_actions,
                                               &ctx->xout->wc);
 
-        if (ctx->xout->use_recirc) {
+        if (ctx->use_recirc) {
             struct ovs_action_hash *act_hash;
-            struct xlate_recirc *xr = &ctx->xout->recirc;
+            struct xlate_recirc *xr = &ctx->recirc;
 
             /* Hash action. */
             act_hash = nl_msg_put_unspec_uninit(&ctx->xout->odp_actions,
@@ -1991,7 +1993,7 @@ static void
 xlate_recursively(struct xlate_ctx *ctx, struct rule_dpif *rule)
 {
     struct rule_dpif *old_rule = ctx->rule;
-    struct rule_actions *actions;
+    const struct rule_actions *actions;
 
     if (ctx->xin->resubmit_stats) {
         rule_dpif_credit_stats(rule, ctx->xin->resubmit_stats);
@@ -2724,7 +2726,7 @@ xlate_sample_action(struct xlate_ctx *ctx,
 static bool
 may_receive(const struct xport *xport, struct xlate_ctx *ctx)
 {
-    if (xport->config & (eth_addr_equals(ctx->xin->flow.dl_dst, eth_addr_stp)
+    if (xport->config & (is_stp(&ctx->xin->flow)
                          ? OFPUTIL_PC_NO_RECV_STP
                          : OFPUTIL_PC_NO_RECV)) {
         return false;
@@ -3190,7 +3192,7 @@ xlate_actions__(struct xlate_in *xin, struct xlate_out *xout)
     struct flow *flow = &xin->flow;
     struct rule_dpif *rule = NULL;
 
-    struct rule_actions *actions = NULL;
+    const struct rule_actions *actions = NULL;
     enum slow_path_reason special;
     const struct ofpact *ofpacts;
     struct xport *in_port;
@@ -3266,6 +3268,7 @@ xlate_actions__(struct xlate_in *xin, struct xlate_out *xout)
     ctx.orig_skb_priority = flow->skb_priority;
     ctx.table_id = 0;
     ctx.exit = false;
+    ctx.use_recirc = false;
 
     if (!xin->ofpacts && !ctx.rule) {
         ctx.table_id = rule_dpif_lookup(ctx.xbridge->ofproto, flow,
@@ -3283,7 +3286,6 @@ xlate_actions__(struct xlate_in *xin, struct xlate_out *xout)
         ctx.rule = rule;
     }
     xout->fail_open = ctx.rule && rule_dpif_is_fail_open(ctx.rule);
-    xout->use_recirc = false;
 
     if (xin->ofpacts) {
         ofpacts = xin->ofpacts;