OpenFlow 1.0 adds support for matching on IP ToS/DSCP bits.
NOTE: OVS at this point is not wire-compatible with OpenFlow 1.0 until
the final commit in this OpenFlow 1.0 set.
error = -EFAULT;
if (copy_from_user(&uf, ufp, sizeof(struct odp_flow_put)))
goto error;
+ memset(uf.flow.key.reserved, 0, sizeof uf.flow.key.reserved);
table = rcu_dereference(dp->table);
flow = dp_table_lookup(table, &uf.flow.key);
error = -EFAULT;
if (copy_from_user(&uf, ufp, sizeof uf))
goto error;
+ memset(uf.key.reserved, 0, sizeof uf.key.reserved);
flow = dp_table_lookup(table, &uf.key);
error = -ENOENT;
if (__copy_from_user(&uf, ufp, sizeof uf))
return -EFAULT;
+ memset(uf.key.reserved, 0, sizeof uf.key.reserved);
flow = dp_table_lookup(table, &uf.key);
if (!flow)
/*
* Distributed under the terms of the GNU GPL version 2.
- * Copyright (c) 2007, 2008, 2009 Nicira Networks.
+ * Copyright (c) 2007, 2008, 2009, 2010 Nicira Networks.
*
* Significant portions of this file may be copied from parts of the Linux
* kernel, by Linus Torvalds and others.
int th_ofs = nh_ofs + nh->ihl * 4;
key->nw_src = nh->saddr;
key->nw_dst = nh->daddr;
+ key->nw_tos = nh->tos & 0xfc;
key->nw_proto = nh->protocol;
skb_set_transport_header(skb, th_ofs);
OFPAT_SET_DL_DST, /* Ethernet destination address. */
OFPAT_SET_NW_SRC, /* IP source address. */
OFPAT_SET_NW_DST, /* IP destination address. */
- OFPAT_SET_NW_TOS, /* IP ToS/DSCP field (6 bits). */
+ OFPAT_SET_NW_TOS, /* IP ToS (DSCP field, 6 bits). */
OFPAT_SET_TP_SRC, /* TCP/UDP source port. */
OFPAT_SET_TP_DST, /* TCP/UDP destination port. */
OFPAT_VENDOR = 0xffff
struct ofp_action_nw_tos {
uint16_t type; /* OFPAT_SET_TW_TOS. */
uint16_t len; /* Length is 8. */
- uint8_t nw_tos; /* IP ToS/DSCP (6 bits). */
+ uint8_t nw_tos; /* IP TOS (DSCP field, 6 bits). */
uint8_t pad[3];
};
OFP_ASSERT(sizeof(struct ofp_action_nw_tos) == 8);
OFPFW_NW_DST_ALL = 32 << OFPFW_NW_DST_SHIFT,
OFPFW_DL_VLAN_PCP = 1 << 20, /* VLAN priority. */
+ OFPFW_NW_TOS = 1 << 21, /* IP ToS (DSCP field, 6 bits). */
/* Wildcard all fields. */
- OFPFW_ALL = ((1 << 21) - 1)
+ OFPFW_ALL = ((1 << 22) - 1)
};
/* The wildcards for ICMP type and code fields use the transport source
uint8_t dl_vlan_pcp; /* Input VLAN priority. */
uint8_t pad1[1]; /* Align to 64-bits. */
uint16_t dl_type; /* Ethernet frame type. */
+ uint8_t nw_tos; /* IP ToS (DSCP field, 6 bits). */
uint8_t nw_proto; /* IP protocol or lower 8 bits of
ARP opcode. */
- uint8_t pad2[3]; /* Align to 64-bits. */
+ uint8_t pad2[2]; /* Align to 64-bits. */
uint32_t nw_src; /* IP source address. */
uint32_t nw_dst; /* IP destination address. */
uint16_t tp_src; /* TCP/UDP source port. */
__u8 nw_proto; /* IP protocol or lower 8 bits of
ARP opcode. */
__u8 dl_vlan_pcp; /* Input VLAN priority. */
+ __u8 nw_tos; /* IP ToS (DSCP field, 6 bits). */
+ __u8 reserved[3]; /* Align to 32-bits...must be zeroed. */
};
/* Flags for ODP_FLOW. */
cls_rule_from_flow(struct cls_rule *rule, const flow_t *flow,
uint32_t wildcards, unsigned int priority)
{
+ assert(!flow->reserved[0] && !flow->reserved[1] && !flow->reserved[2]);
rule->flow = *flow;
flow_wildcards_init(&rule->wc, wildcards);
rule->priority = priority;
/*
- * Copyright (c) 2009 Nicira Networks.
+ * Copyright (c) 2009, 2010 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
CLS_FIELD(OFPFW_NW_SRC_MASK, nw_src, NW_SRC) \
CLS_FIELD(OFPFW_NW_DST_MASK, nw_dst, NW_DST) \
CLS_FIELD(OFPFW_NW_PROTO, nw_proto, NW_PROTO) \
+ CLS_FIELD(OFPFW_NW_TOS, nw_tos, NW_TOS) \
CLS_FIELD(OFPFW_TP_SRC, tp_src, TP_SRC) \
CLS_FIELD(OFPFW_TP_DST, tp_dst, TP_DST)
{
struct dp_netdev_flow *flow;
+ assert(!key->reserved[0] && !key->reserved[1] && !key->reserved[2]);
HMAP_FOR_EACH_WITH_HASH (flow, struct dp_netdev_flow, node,
flow_hash(key, 0), &dp->flow_table) {
if (flow_equal(&flow->key, key)) {
flow = xzalloc(sizeof *flow);
flow->key = odp_flow->key;
+ memset(flow->key.reserved, 0, sizeof flow->key.reserved);
error = set_flow_actions(flow, odp_flow);
if (error) {
if (nh) {
flow->nw_src = nh->ip_src;
flow->nw_dst = nh->ip_dst;
+ flow->nw_tos = nh->ip_tos & 0xfc;
flow->nw_proto = nh->ip_proto;
packet->l4 = b.data;
if (!IP_IS_FRAGMENT(nh->ip_frag_off)) {
match->dl_type = flow->dl_type;
match->nw_src = flow->nw_src;
match->nw_dst = flow->nw_dst;
+ match->nw_tos = flow->nw_tos;
match->nw_proto = flow->nw_proto;
match->tp_src = flow->tp_src;
match->tp_dst = flow->tp_dst;
flow->tp_dst = match->tp_dst;
memcpy(flow->dl_src, match->dl_src, ETH_ADDR_LEN);
memcpy(flow->dl_dst, match->dl_dst, ETH_ADDR_LEN);
+ flow->nw_tos = match->nw_tos;
flow->nw_proto = match->nw_proto;
+ memset(flow->reserved, 0, sizeof flow->reserved);
}
char *
flow_format(struct ds *ds, const flow_t *flow)
{
ds_put_format(ds, "in_port%04x:vlan%d:pcp%d mac"ETH_ADDR_FMT
- "->"ETH_ADDR_FMT" type%04x proto%"PRId8" ip"IP_FMT
- "->"IP_FMT" port%d->%d",
+ "->"ETH_ADDR_FMT" type%04x proto%"PRId8" tos%"PRIu8
+ " ip"IP_FMT"->"IP_FMT" port%d->%d",
flow->in_port, ntohs(flow->dl_vlan), flow->dl_vlan_pcp,
ETH_ADDR_ARGS(flow->dl_src), ETH_ADDR_ARGS(flow->dl_dst),
- ntohs(flow->dl_type), flow->nw_proto,
+ ntohs(flow->dl_type), flow->nw_proto, flow->nw_tos,
IP_ARGS(&flow->nw_src), IP_ARGS(&flow->nw_dst),
ntohs(flow->tp_src), ntohs(flow->tp_dst));
}
} else {
print_wild(&f, "nw_proto=", w & OFPFW_NW_PROTO, verbosity,
"%u", om->nw_proto);
+ print_wild(&f, "nw_tos=", w & OFPFW_NW_TOS, verbosity,
+ "%u", om->nw_tos);
}
}
if (om->nw_proto == IP_TYPE_ICMP) {
ofm->match.nw_src = flow->nw_src;
ofm->match.nw_dst = flow->nw_dst;
ofm->match.nw_proto = flow->nw_proto;
+ ofm->match.nw_tos = flow->nw_tos;
ofm->match.tp_src = flow->tp_src;
ofm->match.tp_dst = flow->tp_dst;
ofm->command = htons(command);
#! /usr/bin/perl
-# Copyright (c) 2009 Nicira Networks.
+# Copyright (c) 2009, 2010 Nicira Networks.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
$flow{DL_SRC} = "00:02:e3:0f:80:a4";
$flow{DL_DST} = "00:1a:92:40:ac:05";
$flow{NW_PROTO} = 0;
+ $flow{NW_TOS} = 0;
$flow{NW_SRC} = '0.0.0.0';
$flow{NW_DST} = '0.0.0.0';
$flow{TP_SRC} = 0;
$flow{DL_TYPE} = 0x0800; # ETH_TYPE_IP
$flow{NW_SRC} = '10.0.2.15';
$flow{NW_DST} = '192.168.1.20';
+ $flow{NW_TOS} = 44;
if ($attrs{TP_PROTO} eq 'other') {
$flow{NW_PROTO} = 42;
} elsif ($attrs{TP_PROTO} eq 'TCP' ||
if ($attrs{DL_TYPE} eq 'ip') {
my $ip = pack('CCnnnCCnNN',
(4 << 4) | 5, # version, hdrlen
- 0, # type of service
+ $flow{NW_TOS}, # type of service
0, # total length (filled in later)
65432, # id
0, # frag offset
1); # in_port
print FLOWS pack_ethaddr($flow{DL_SRC});
print FLOWS pack_ethaddr($flow{DL_DST});
- print FLOWS pack('nCxnCxxxNNnn',
+ print FLOWS pack('nCxnCCxxNNnn',
$flow{DL_VLAN},
0, # DL_VLAN_PCP
$flow{DL_TYPE},
+ $flow{NW_TOS},
$flow{NW_PROTO},
inet_aton($flow{NW_SRC}),
inet_aton($flow{NW_DST}),
static uint8_t dl_dst_values[][6] = { { 0x4a, 0x27, 0x71, 0xae, 0x64, 0xc1 },
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
static uint8_t nw_proto_values[] = { IP_TYPE_TCP, IP_TYPE_ICMP };
+static uint8_t nw_tos_values[] = { 49, 0 };
static void *values[CLS_N_FIELDS][2];
values[CLS_F_IDX_NW_PROTO][0] = &nw_proto_values[0];
values[CLS_F_IDX_NW_PROTO][1] = &nw_proto_values[1];
+ values[CLS_F_IDX_NW_TOS][0] = &nw_tos_values[0];
+ values[CLS_F_IDX_NW_TOS][1] = &nw_tos_values[1];
+
values[CLS_F_IDX_TP_SRC][0] = &tp_src_values[0];
values[CLS_F_IDX_TP_SRC][1] = &tp_src_values[1];
#define N_DL_SRC_VALUES ARRAY_SIZE(dl_src_values)
#define N_DL_DST_VALUES ARRAY_SIZE(dl_dst_values)
#define N_NW_PROTO_VALUES ARRAY_SIZE(nw_proto_values)
+#define N_NW_TOS_VALUES ARRAY_SIZE(nw_tos_values)
#define N_FLOW_VALUES (N_NW_SRC_VALUES * \
N_NW_DST_VALUES * \
N_TP_DST_VALUES * \
N_DL_SRC_VALUES * \
N_DL_DST_VALUES * \
- N_NW_PROTO_VALUES)
+ N_NW_PROTO_VALUES * \
+ N_NW_TOS_VALUES)
static unsigned int
get_value(unsigned int *x, unsigned n_values)
memcpy(flow.dl_dst, dl_dst_values[get_value(&x, N_DL_DST_VALUES)],
ETH_ADDR_LEN);
flow.nw_proto = nw_proto_values[get_value(&x, N_NW_PROTO_VALUES)];
+ flow.nw_tos = nw_tos_values[get_value(&x, N_NW_TOS_VALUES)];
+ memset(flow.reserved, 0, sizeof flow.reserved);
for (include = 1; include <= 3; include++) {
cr0 = lookup_with_include_bits(cls, &flow, include);
-.TH ovs\-ofctl 8 "June 2009" "Open vSwitch" "Open vSwitch Manual"
+.TH ovs\-ofctl 8 "January 2010" "Open vSwitch" "Open vSwitch Manual"
.ds PN ovs\-ofctl
.SH NAME
Matches IP protocol type \fIproto\fR, which is specified as a decimal
number between 0 and 255, inclusive (e.g. 6 to match TCP packets).
+.IP \fBnw_tos=\fItos\fR
+Matches IP ToS/DSCP field \fItos\fR, which is specified as a decimal
+number between 0 and 255, inclusive. Note that the two lower reserved
+bits are ignored for matching purposes.
+
.IP \fBtp_src=\fIport\fR
Matches UDP or TCP source port \fIport\fR, which is specified as a decimal
number between 0 and 65535, inclusive (e.g. 80 to match packets originating
{ "nw_dst", OFPFW_NW_DST_MASK, F_IP,
F_OFS(nw_dst), OFPFW_NW_DST_SHIFT },
{ "nw_proto", OFPFW_NW_PROTO, F_U8, F_OFS(nw_proto), 0 },
+ { "nw_tos", OFPFW_NW_TOS, F_U8, F_OFS(nw_tos), 0 },
{ "tp_src", OFPFW_TP_SRC, F_U16, F_OFS(tp_src), 0 },
{ "tp_dst", OFPFW_TP_DST, F_U16, F_OFS(tp_dst), 0 },
{ "icmp_type", OFPFW_ICMP_TYPE, F_U16, F_OFS(icmp_type), 0 },