#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>
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)
{
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,
};
* 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
*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;
+}
\f
void
dpif_init(struct dpif *dpif, const struct dpif_class *dpif_class,
#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"
}
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 {
}
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;
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);
}
}
}
+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
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);
/* 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);