2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-22 09:58:01 +00:00

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.
This commit is contained in:
Ben Pfaff 2010-07-20 11:23:21 -07:00
parent c4d279ab34
commit aae51f5335
6 changed files with 68 additions and 12 deletions

View File

@ -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>
@ -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,
};

View File

@ -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,
};

View File

@ -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

View File

@ -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,

View File

@ -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

View 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"
@ -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);