dpif: Abstract translation from OpenFlow queue ID into ODP priority value.
[openvswitch] / ofproto / ofproto.c
index 4c4df9493f5c90b44e923d797d149d84a0377e4d..cf491395c2d1d2eccb4078bcb7b73b19b8463648 100644 (file)
@@ -59,9 +59,6 @@
 #include "vconn.h"
 #include "xtoxll.h"
 
-#include <linux/types.h>        /* XXX */
-#include <linux/pkt_sched.h>    /* XXX */
-
 #define THIS_MODULE VLM_ofproto
 #include "vlog.h"
 
@@ -414,15 +411,11 @@ ofproto_set_datapath_id(struct ofproto *p, uint64_t datapath_id)
     uint64_t old_dpid = p->datapath_id;
     p->datapath_id = datapath_id ? datapath_id : pick_datapath_id(p);
     if (p->datapath_id != old_dpid) {
-        struct ofconn *ofconn;
-
         VLOG_INFO("datapath ID changed to %016"PRIx64, p->datapath_id);
 
         /* Force all active connections to reconnect, since there is no way to
          * notify a controller that the datapath ID has changed. */
-        LIST_FOR_EACH (ofconn, struct ofconn, node, &p->all_conns) {
-            rconn_reconnect(ofconn->rconn);
-        }
+        ofproto_reconnect_controllers(p);
     }
 }
 
@@ -667,6 +660,18 @@ ofproto_set_controllers(struct ofproto *p,
     }
 }
 
+/* Drops the connections between 'ofproto' and all of its controllers, forcing
+ * them to reconnect. */
+void
+ofproto_reconnect_controllers(struct ofproto *ofproto)
+{
+    struct ofconn *ofconn;
+
+    LIST_FOR_EACH (ofconn, struct ofconn, node, &ofproto->all_conns) {
+        rconn_reconnect(ofconn->rconn);
+    }
+}
+
 static bool
 any_extras_changed(const struct ofproto *ofproto,
                    const struct sockaddr_in *extras, size_t n)
@@ -2272,11 +2277,10 @@ add_output_group_action(struct odp_actions *actions, uint16_t group,
 }
 
 static void
-add_controller_action(struct odp_actions *actions,
-                      const struct ofp_action_output *oao)
+add_controller_action(struct odp_actions *actions, uint16_t max_len)
 {
     union odp_action *a = odp_actions_add(actions, ODPAT_CONTROLLER);
-    a->controller.arg = ntohs(oao->max_len);
+    a->controller.arg = max_len;
 }
 
 struct action_xlate_ctx {
@@ -2368,15 +2372,15 @@ xlate_table_action(struct action_xlate_ctx *ctx, uint16_t in_port)
 }
 
 static void
-xlate_output_action(struct action_xlate_ctx *ctx,
-                    const struct ofp_action_output *oao)
+xlate_output_action__(struct action_xlate_ctx *ctx,
+                      uint16_t port, uint16_t max_len)
 {
     uint16_t odp_port;
     uint16_t prev_nf_output_iface = ctx->nf_output_iface;
 
     ctx->nf_output_iface = NF_OUT_DROP;
 
-    switch (ntohs(oao->port)) {
+    switch (port) {
     case OFPP_IN_PORT:
         add_output_action(ctx, ctx->flow.in_port);
         break;
@@ -2400,13 +2404,13 @@ xlate_output_action(struct action_xlate_ctx *ctx,
         add_output_group_action(ctx->out, DP_GROUP_ALL, &ctx->nf_output_iface);
         break;
     case OFPP_CONTROLLER:
-        add_controller_action(ctx->out, oao);
+        add_controller_action(ctx->out, max_len);
         break;
     case OFPP_LOCAL:
         add_output_action(ctx, ODPP_LOCAL);
         break;
     default:
-        odp_port = ofp_port_to_odp_port(ntohs(oao->port));
+        odp_port = ofp_port_to_odp_port(port);
         if (odp_port != ctx->flow.in_port) {
             add_output_action(ctx, odp_port);
         }
@@ -2423,6 +2427,13 @@ xlate_output_action(struct action_xlate_ctx *ctx,
     }
 }
 
+static void
+xlate_output_action(struct action_xlate_ctx *ctx,
+                    const struct ofp_action_output *oao)
+{
+    xlate_output_action__(ctx, ntohs(oao->port), ntohs(oao->max_len));
+}
+
 /* If the final ODP action in 'ctx' is "pop priority", drop it, as an
  * optimization, because we're going to add another action that sets the
  * priority immediately after, or because there are no actions following the
@@ -2441,6 +2452,16 @@ xlate_enqueue_action(struct action_xlate_ctx *ctx,
                      const struct ofp_action_enqueue *oae)
 {
     uint16_t ofp_port, odp_port;
+    uint32_t priority;
+    int error;
+
+    error = dpif_queue_to_priority(ctx->ofproto->dpif, ntohl(oae->queue_id),
+                                   &priority);
+    if (error) {
+        /* Fall back to ordinary output action. */
+        xlate_output_action__(ctx, ntohs(oae->port), 0);
+        return;
+    }
 
     /* Figure out ODP output port. */
     ofp_port = ntohs(oae->port);
@@ -2453,7 +2474,7 @@ xlate_enqueue_action(struct action_xlate_ctx *ctx,
     /* Add ODP actions. */
     remove_pop_action(ctx);
     odp_actions_add(ctx->out, ODPAT_SET_PRIORITY)->priority.priority
-        = TC_H_MAKE(1, ntohl(oae->queue_id)); /* XXX */
+        = priority;
     add_output_action(ctx, odp_port);
     odp_actions_add(ctx->out, ODPAT_POP_PRIORITY);
 
@@ -3631,6 +3652,7 @@ static int
 handle_flow_mod(struct ofproto *p, struct ofconn *ofconn,
                 struct ofp_flow_mod *ofm)
 {
+    struct ofp_match orig_match;
     size_t n_actions;
     int error;
 
@@ -3652,7 +3674,25 @@ handle_flow_mod(struct ofproto *p, struct ofconn *ofconn,
         return ofp_mkerr(OFPET_FLOW_MOD_FAILED, OFPFMFC_ALL_TABLES_FULL);
     }
 
+    /* Normalize ofp->match.  If normalization actually changes anything, then
+     * log the differences. */
+    ofm->match.pad1[0] = ofm->match.pad2[0] = 0;
+    orig_match = ofm->match;
     normalize_match(&ofm->match);
+    if (memcmp(&ofm->match, &orig_match, sizeof orig_match)) {
+        static struct vlog_rate_limit normal_rl = VLOG_RATE_LIMIT_INIT(1, 1);
+        if (!VLOG_DROP_INFO(&normal_rl)) {
+            char *old = ofp_match_to_literal_string(&orig_match);
+            char *new = ofp_match_to_literal_string(&ofm->match);
+            VLOG_INFO("%s: normalization changed ofp_match, details:",
+                      rconn_get_name(ofconn->rconn));
+            VLOG_INFO(" pre: %s", old);
+            VLOG_INFO("post: %s", new);
+            free(old);
+            free(new);
+        }
+    }
+
     if (!ofm->match.wildcards) {
         ofm->priority = htons(UINT16_MAX);
     }