2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-31 22:35:15 +00:00

Add Nicira extension for modifying queue without transmitting

The OpenFlow OFPAT_ENQUEUE action sets a queue id and outputs the packet
in one shot.  There are times in which the queue should be set, but the
output port is not yet known.  This commit adds the NXAST_SET_QUEUE and
NXAST_POP_QUEUE Nicira extension actions to modify the queue
configuration without requiring a port argument.

CC: Jeremy Stribling <strib@nicira.com>
CC: Keith Amidon <keith@nicira.com>
This commit is contained in:
Justin Pettit
2010-10-02 00:27:23 -07:00
parent 9ebc44ae8c
commit eedc0097f4
7 changed files with 91 additions and 2 deletions

View File

@@ -142,7 +142,17 @@ enum nx_action_subtype {
* This is useful because OpenFlow does not provide a way to match on the
* Ethernet addresses inside ARP packets, so there is no other way to drop
* spoofed ARPs other than sending every ARP packet to a controller. */
NXAST_DROP_SPOOFED_ARP
NXAST_DROP_SPOOFED_ARP,
/* Set the queue that should be used when packets are output. This
* is similar to the OpenFlow OFPAT_ENQUEUE action, but does not
* take the output port as an argument. This allows the queue
* to be defined before the port is known. */
NXAST_SET_QUEUE,
/* Restore the queue to the value it was before any NXAST_SET_QUEUE
* actions were used. */
NXAST_POP_QUEUE
};
/* Action structure for NXAST_RESUBMIT. */
@@ -167,6 +177,17 @@ struct nx_action_set_tunnel {
};
OFP_ASSERT(sizeof(struct nx_action_set_tunnel) == 16);
/* Action structure for NXAST_SET_QUEUE. */
struct nx_action_set_queue {
uint16_t type; /* OFPAT_VENDOR. */
uint16_t len; /* Length is 16. */
uint32_t vendor; /* NX_VENDOR_ID. */
uint16_t subtype; /* NXAST_SET_QUEUE. */
uint8_t pad[2];
uint32_t queue_id; /* Where to enqueue packets. */
};
OFP_ASSERT(sizeof(struct nx_action_set_queue) == 16);
/* Header for Nicira-defined actions. */
struct nx_action_header {
uint16_t type; /* OFPAT_VENDOR. */

View File

@@ -267,6 +267,17 @@ str_to_action(char *str, struct ofpbuf *b)
nah = put_action(b, sizeof *nah, OFPAT_VENDOR);
nah->vendor = htonl(NX_VENDOR_ID);
nah->subtype = htons(NXAST_DROP_SPOOFED_ARP);
} else if (!strcasecmp(act, "set_queue")) {
struct nx_action_set_queue *nasq;
nasq = put_action(b, sizeof *nasq, OFPAT_VENDOR);
nasq->vendor = htonl(NX_VENDOR_ID);
nasq->subtype = htons(NXAST_SET_QUEUE);
nasq->queue_id = htonl(str_to_u32(arg));
} else if (!strcasecmp(act, "pop_queue")) {
struct nx_action_header *nah;
nah = put_action(b, sizeof *nah, OFPAT_VENDOR);
nah->vendor = htonl(NX_VENDOR_ID);
nah->subtype = htons(NXAST_POP_QUEUE);
} else if (!strcasecmp(act, "output")) {
put_output_action(b, str_to_u32(arg));
} else if (!strcasecmp(act, "enqueue")) {

View File

@@ -205,6 +205,17 @@ ofp_print_nx_action(struct ds *string, const struct nx_action_header *nah)
ds_put_cstr(string, "drop_spoofed_arp");
break;
case NXAST_SET_QUEUE: {
const struct nx_action_set_queue *nasq =
(struct nx_action_set_queue *)nah;
ds_put_format(string, "set_queue:%u", ntohl(nasq->queue_id));
break;
}
case NXAST_POP_QUEUE:
ds_put_cstr(string, "pop_queue");
break;
default:
ds_put_format(string, "***unknown Nicira action:%d***",
ntohs(nah->subtype));

View File

@@ -565,6 +565,8 @@ check_nicira_action(const union ofp_action *a, unsigned int len)
case NXAST_RESUBMIT:
case NXAST_SET_TUNNEL:
case NXAST_DROP_SPOOFED_ARP:
case NXAST_SET_QUEUE:
case NXAST_POP_QUEUE:
return check_action_exact_len(a, len, 16);
default:
return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_VENDOR_TYPE);

View File

@@ -2661,12 +2661,33 @@ xlate_enqueue_action(struct action_xlate_ctx *ctx,
}
}
static void
xlate_set_queue_action(struct action_xlate_ctx *ctx,
const struct nx_action_set_queue *nasq)
{
uint32_t priority;
int error;
error = dpif_queue_to_priority(ctx->ofproto->dpif, ntohl(nasq->queue_id),
&priority);
if (error) {
/* Couldn't translate queue to a priority, so ignore. A warning
* has already been logged. */
return;
}
remove_pop_action(ctx);
odp_actions_add(ctx->out, ODPAT_SET_PRIORITY)->priority.priority
= priority;
}
static void
xlate_nicira_action(struct action_xlate_ctx *ctx,
const struct nx_action_header *nah)
{
const struct nx_action_resubmit *nar;
const struct nx_action_set_tunnel *nast;
const struct nx_action_set_queue *nasq;
union odp_action *oa;
int subtype = ntohs(nah->subtype);
@@ -2689,6 +2710,15 @@ xlate_nicira_action(struct action_xlate_ctx *ctx,
}
break;
case NXAST_SET_QUEUE:
nasq = (const struct nx_action_set_queue *) nah;
xlate_set_queue_action(ctx, nasq);
break;
case NXAST_POP_QUEUE:
odp_actions_add(ctx->out, ODPAT_POP_PRIORITY);
break;
/* If you add a new action here that modifies flow data, don't forget to
* update the flow key in ctx->flow at the same time. */

View File

@@ -5,8 +5,10 @@ AT_DATA([flows.txt], [
# comment
tcp,tp_src=123,actions=flood
in_port=LOCAL dl_vlan=9 dl_src=00:0A:E4:25:6B:B0 actions=drop
arp,nw_src=192.168.0.1,actions=drop_spoofed_arp,NORMAL
arp,nw_src=192.168.0.1 actions=drop_spoofed_arp,NORMAL
udp dl_vlan_pcp=7 idle_timeout=5 actions=strip_vlan output:0
tcp,nw_src=192.168.0.3,tp_dst=80 actions=set_queue:37,output:1
udp,nw_src=192.168.0.3,tp_dst=53 actions=pop_queue,output:1
cookie=0x123456789abcdef hard_timeout=10 priority=60000 actions=controller
actions=drop
])
@@ -16,6 +18,8 @@ flow_mod: tcp,tp_src=123, ADD: actions=FLOOD
flow_mod: in_port=65534,dl_vlan=9,dl_src=00:0a:e4:25:6b:b0, ADD: actions=drop
flow_mod: arp,nw_src=192.168.0.1, ADD: actions=drop_spoofed_arp,NORMAL
flow_mod: udp,dl_vlan_pcp=7, ADD: idle:5 actions=strip_vlan,output:0
flow_mod: tcp,nw_src=192.168.0.3,tp_dst=80, ADD: actions=set_queue:37,output:1
flow_mod: udp,nw_src=192.168.0.3,tp_dst=53, ADD: actions=pop_queue,output:1
flow_mod: ADD: cookie:0x123456789abcdef hard:10 pri:60000 actions=CONTROLLER:65535
flow_mod: ADD: actions=drop
])

View File

@@ -469,6 +469,16 @@ Ethernet header.
This is useful because OpenFlow does not provide a way to match on the
Ethernet addresses inside ARP packets, so there is no other way to
drop spoofed ARPs other than sending every ARP packet to a controller.
.
.IP \fBset_queue\fB:\fIqueue\fR
Sets the queue that should be used to \fIqueue\fR when packets are
output. The number of supported queues depends on the switch; some
OpenFlow implementations do not support queuing at all.
.
.IP \fBpop_queue\fR
Restores the queue to the value it was before any \fBset_queue\fR
actions were applied.
.
.RE
.
.IP