[ovs-dev] [QoS fixes 07/10] dpif: Abstract translation from OpenFlow queue ID into ODP priority value.

Ben Pfaff blp at nicira.com
Fri Jul 16 22:52:50 UTC 2010


When the QoS code was integrated, I didn't yet know how to abstract the
translation from a queue ID in an OpenFlow OFPAT_ENQUEUE action into a
priority value for an ODP ODPAT_SET_PRIORITY action.  This commit is a
first attempt that works OK for Linux, so far.  It's possible that in fact
this translation needs the 'netdev' as an argument too, but it's not needed
yet.
---
 lib/dpif-linux.c    |   14 ++++++++++++++
 lib/dpif-netdev.c   |    1 +
 lib/dpif-provider.h |    6 ++++++
 lib/dpif.c          |   19 +++++++++++++++++++
 lib/dpif.h          |    3 +++
 ofproto/ofproto.c   |   37 +++++++++++++++++++++++++------------
 6 files changed, 68 insertions(+), 12 deletions(-)

diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c
index af6eee4..87f29f8 100644
--- a/lib/dpif-linux.c
+++ b/lib/dpif-linux.c
@@ -25,6 +25,7 @@
 #include <net/if.h>
 #include <linux/types.h>
 #include <linux/ethtool.h>
+#include <linux/pkt_sched.h>
 #include <linux/rtnetlink.h>
 #include <linux/sockios.h>
 #include <stdlib.h>
@@ -458,6 +459,18 @@ dpif_linux_set_sflow_probability(struct dpif *dpif_, uint32_t probability)
 }
 
 static int
+dpif_linux_queue_to_priority(const struct dpif *dpif OVS_UNUSED,
+                             uint32_t queue_id, uint32_t *priority)
+{
+    if (queue_id < 0xf000) {
+        *priority = TC_H_MAKE(1, queue_id);
+        return 0;
+    } else {
+        return EINVAL;
+    }
+}
+
+static int
 dpif_linux_recv(struct dpif *dpif_, struct ofpbuf **bufp)
 {
     struct dpif_linux *dpif = dpif_linux_cast(dpif_);
@@ -539,6 +552,7 @@ const struct dpif_class dpif_linux_class = {
     dpif_linux_recv_set_mask,
     dpif_linux_get_sflow_probability,
     dpif_linux_set_sflow_probability,
+    dpif_linux_queue_to_priority,
     dpif_linux_recv,
     dpif_linux_recv_wait,
 };
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index fa47d39..010388f 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -1364,6 +1364,7 @@ const struct dpif_class dpif_netdev_class = {
     dpif_netdev_execute,
     dpif_netdev_recv_get_mask,
     dpif_netdev_recv_set_mask,
+    NULL,                       /* queue_to_priority */
     NULL,                       /* get_sflow_probability */
     NULL,                       /* set_sflow_probability */
     dpif_netdev_recv,
diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h
index 5cbefeb..b2f9d4b 100644
--- a/lib/dpif-provider.h
+++ b/lib/dpif-provider.h
@@ -302,6 +302,12 @@ struct dpif_class {
      * packet. */
     int (*set_sflow_probability)(struct dpif *dpif, uint32_t probability);
 
+    /* Translates OpenFlow queue ID 'queue_id' (in host byte order) into a
+     * priority value for use in the ODPAT_SET_PRIORITY action in
+     * '*priority'. */
+    int (*queue_to_priority)(const struct dpif *dpif, uint32_t queue_id,
+                             uint32_t *priority);
+
     /* Attempts to receive a message from 'dpif'.  If successful, stores the
      * message into '*packetp'.  The message, if one is received, must begin
      * with 'struct odp_msg' as a header, and must have at least
diff --git a/lib/dpif.c b/lib/dpif.c
index 8286da4..ef28ea9 100644
--- a/lib/dpif.c
+++ b/lib/dpif.c
@@ -1096,6 +1096,25 @@ dpif_get_netflow_ids(const struct dpif *dpif,
     *engine_type = dpif->netflow_engine_type;
     *engine_id = dpif->netflow_engine_id;
 }
+
+/* Translates OpenFlow queue ID 'queue_id' (in host byte order) into a priority
+ * value for use in the ODPAT_SET_PRIORITY action.  On success, returns 0 and
+ * stores the priority into '*priority'.  On failure, returns a positive errno
+ * value and stores 0 into '*priority'. */
+int
+dpif_queue_to_priority(const struct dpif *dpif, uint32_t queue_id,
+                       uint32_t *priority)
+{
+    int error = (dpif->dpif_class->queue_to_priority
+                 ? dpif->dpif_class->queue_to_priority(dpif, queue_id,
+                                                       priority)
+                 : EOPNOTSUPP);
+    if (error) {
+        *priority = 0;
+    }
+    log_operation(dpif, "queue_to_priority", error);
+    return error;
+}
 
 void
 dpif_init(struct dpif *dpif, const struct dpif_class *dpif_class,
diff --git a/lib/dpif.h b/lib/dpif.h
index 4789284..a639725 100644
--- a/lib/dpif.h
+++ b/lib/dpif.h
@@ -101,6 +101,9 @@ void dpif_recv_wait(struct dpif *);
 void dpif_get_netflow_ids(const struct dpif *,
                           uint8_t *engine_type, uint8_t *engine_id);
 
+int dpif_queue_to_priority(const struct dpif *, uint32_t queue_id,
+                           uint32_t *priority);
+
 #ifdef  __cplusplus
 }
 #endif
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index eb62fe8..cf49139 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -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"
 
@@ -2280,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 {
@@ -2376,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;
@@ -2408,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);
         }
@@ -2431,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
@@ -2449,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);
@@ -2461,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);
 
-- 
1.7.1





More information about the dev mailing list