From aae51f53358dc7946f7f09a88b1e0dd40306a99a Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 20 Jul 2010 11:23:21 -0700 Subject: [PATCH] dpif: Abstract translation from OpenFlow queue ID into ODP priority value. 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 af6eee4161c..87f29f84f5e 100644 --- a/lib/dpif-linux.c +++ b/lib/dpif-linux.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -457,6 +458,18 @@ dpif_linux_set_sflow_probability(struct dpif *dpif_, uint32_t probability) return do_ioctl(dpif_, ODP_SET_SFLOW_PROBABILITY, &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) { @@ -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 fa47d39e356..fc117d20623 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -1366,6 +1366,7 @@ const struct dpif_class dpif_netdev_class = { dpif_netdev_recv_set_mask, NULL, /* get_sflow_probability */ NULL, /* set_sflow_probability */ + NULL, /* queue_to_priority */ dpif_netdev_recv, dpif_netdev_recv_wait, }; diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h index 5cbefebc644..b2f9d4bd1bf 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 8286da402ae..ef28ea9fa18 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 47892844644..a6397254536 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 eb62fe8c0bc..cf491395c2d 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -59,9 +59,6 @@ #include "vconn.h" #include "xtoxll.h" -#include /* XXX */ -#include /* 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);