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:
parent
c4d279ab34
commit
aae51f5335
@ -25,6 +25,7 @@
|
|||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/ethtool.h>
|
#include <linux/ethtool.h>
|
||||||
|
#include <linux/pkt_sched.h>
|
||||||
#include <linux/rtnetlink.h>
|
#include <linux/rtnetlink.h>
|
||||||
#include <linux/sockios.h>
|
#include <linux/sockios.h>
|
||||||
#include <stdlib.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);
|
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
|
static int
|
||||||
dpif_linux_recv(struct dpif *dpif_, struct ofpbuf **bufp)
|
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_recv_set_mask,
|
||||||
dpif_linux_get_sflow_probability,
|
dpif_linux_get_sflow_probability,
|
||||||
dpif_linux_set_sflow_probability,
|
dpif_linux_set_sflow_probability,
|
||||||
|
dpif_linux_queue_to_priority,
|
||||||
dpif_linux_recv,
|
dpif_linux_recv,
|
||||||
dpif_linux_recv_wait,
|
dpif_linux_recv_wait,
|
||||||
};
|
};
|
||||||
|
@ -1366,6 +1366,7 @@ const struct dpif_class dpif_netdev_class = {
|
|||||||
dpif_netdev_recv_set_mask,
|
dpif_netdev_recv_set_mask,
|
||||||
NULL, /* get_sflow_probability */
|
NULL, /* get_sflow_probability */
|
||||||
NULL, /* set_sflow_probability */
|
NULL, /* set_sflow_probability */
|
||||||
|
NULL, /* queue_to_priority */
|
||||||
dpif_netdev_recv,
|
dpif_netdev_recv,
|
||||||
dpif_netdev_recv_wait,
|
dpif_netdev_recv_wait,
|
||||||
};
|
};
|
||||||
|
@ -302,6 +302,12 @@ struct dpif_class {
|
|||||||
* packet. */
|
* packet. */
|
||||||
int (*set_sflow_probability)(struct dpif *dpif, uint32_t probability);
|
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
|
/* Attempts to receive a message from 'dpif'. If successful, stores the
|
||||||
* message into '*packetp'. The message, if one is received, must begin
|
* message into '*packetp'. The message, if one is received, must begin
|
||||||
* with 'struct odp_msg' as a header, and must have at least
|
* with 'struct odp_msg' as a header, and must have at least
|
||||||
|
19
lib/dpif.c
19
lib/dpif.c
@ -1096,6 +1096,25 @@ dpif_get_netflow_ids(const struct dpif *dpif,
|
|||||||
*engine_type = dpif->netflow_engine_type;
|
*engine_type = dpif->netflow_engine_type;
|
||||||
*engine_id = dpif->netflow_engine_id;
|
*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
|
void
|
||||||
dpif_init(struct dpif *dpif, const struct dpif_class *dpif_class,
|
dpif_init(struct dpif *dpif, const struct dpif_class *dpif_class,
|
||||||
|
@ -101,6 +101,9 @@ void dpif_recv_wait(struct dpif *);
|
|||||||
void dpif_get_netflow_ids(const struct dpif *,
|
void dpif_get_netflow_ids(const struct dpif *,
|
||||||
uint8_t *engine_type, uint8_t *engine_id);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -59,9 +59,6 @@
|
|||||||
#include "vconn.h"
|
#include "vconn.h"
|
||||||
#include "xtoxll.h"
|
#include "xtoxll.h"
|
||||||
|
|
||||||
#include <linux/types.h> /* XXX */
|
|
||||||
#include <linux/pkt_sched.h> /* XXX */
|
|
||||||
|
|
||||||
#define THIS_MODULE VLM_ofproto
|
#define THIS_MODULE VLM_ofproto
|
||||||
#include "vlog.h"
|
#include "vlog.h"
|
||||||
|
|
||||||
@ -2280,11 +2277,10 @@ add_output_group_action(struct odp_actions *actions, uint16_t group,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_controller_action(struct odp_actions *actions,
|
add_controller_action(struct odp_actions *actions, uint16_t max_len)
|
||||||
const struct ofp_action_output *oao)
|
|
||||||
{
|
{
|
||||||
union odp_action *a = odp_actions_add(actions, ODPAT_CONTROLLER);
|
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 {
|
struct action_xlate_ctx {
|
||||||
@ -2376,15 +2372,15 @@ xlate_table_action(struct action_xlate_ctx *ctx, uint16_t in_port)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xlate_output_action(struct action_xlate_ctx *ctx,
|
xlate_output_action__(struct action_xlate_ctx *ctx,
|
||||||
const struct ofp_action_output *oao)
|
uint16_t port, uint16_t max_len)
|
||||||
{
|
{
|
||||||
uint16_t odp_port;
|
uint16_t odp_port;
|
||||||
uint16_t prev_nf_output_iface = ctx->nf_output_iface;
|
uint16_t prev_nf_output_iface = ctx->nf_output_iface;
|
||||||
|
|
||||||
ctx->nf_output_iface = NF_OUT_DROP;
|
ctx->nf_output_iface = NF_OUT_DROP;
|
||||||
|
|
||||||
switch (ntohs(oao->port)) {
|
switch (port) {
|
||||||
case OFPP_IN_PORT:
|
case OFPP_IN_PORT:
|
||||||
add_output_action(ctx, ctx->flow.in_port);
|
add_output_action(ctx, ctx->flow.in_port);
|
||||||
break;
|
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);
|
add_output_group_action(ctx->out, DP_GROUP_ALL, &ctx->nf_output_iface);
|
||||||
break;
|
break;
|
||||||
case OFPP_CONTROLLER:
|
case OFPP_CONTROLLER:
|
||||||
add_controller_action(ctx->out, oao);
|
add_controller_action(ctx->out, max_len);
|
||||||
break;
|
break;
|
||||||
case OFPP_LOCAL:
|
case OFPP_LOCAL:
|
||||||
add_output_action(ctx, ODPP_LOCAL);
|
add_output_action(ctx, ODPP_LOCAL);
|
||||||
break;
|
break;
|
||||||
default:
|
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) {
|
if (odp_port != ctx->flow.in_port) {
|
||||||
add_output_action(ctx, odp_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
|
/* 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
|
* optimization, because we're going to add another action that sets the
|
||||||
* priority immediately after, or because there are no actions following 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)
|
const struct ofp_action_enqueue *oae)
|
||||||
{
|
{
|
||||||
uint16_t ofp_port, odp_port;
|
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. */
|
/* Figure out ODP output port. */
|
||||||
ofp_port = ntohs(oae->port);
|
ofp_port = ntohs(oae->port);
|
||||||
@ -2461,7 +2474,7 @@ xlate_enqueue_action(struct action_xlate_ctx *ctx,
|
|||||||
/* Add ODP actions. */
|
/* Add ODP actions. */
|
||||||
remove_pop_action(ctx);
|
remove_pop_action(ctx);
|
||||||
odp_actions_add(ctx->out, ODPAT_SET_PRIORITY)->priority.priority
|
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);
|
add_output_action(ctx, odp_port);
|
||||||
odp_actions_add(ctx->out, ODPAT_POP_PRIORITY);
|
odp_actions_add(ctx->out, ODPAT_POP_PRIORITY);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user