2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-03 07:45:30 +00:00

ofproto: Match VLAN PCP and rewrite ToS bits (OpenFlow 0.9)

Starting in OpenFlow 0.9, it is possible to match on the VLAN PCP
(priority) field and rewrite the IP ToS/DSCP bits.  This check-in
provides that support and bumps the wire protocol number to 0x98.

NOTE: The wire changes come together over the set of OpenFlow 0.9 commits,
so OVS will not be OpenFlow-compatible with any official release between
this commit and the one that completes the set.
This commit is contained in:
Justin Pettit
2009-11-11 14:59:49 -08:00
parent 2f6d344525
commit 959a2ecdc8
17 changed files with 156 additions and 35 deletions

View File

@@ -285,6 +285,30 @@ static struct sk_buff *set_nw_addr(struct sk_buff *skb,
return skb; return skb;
} }
static struct sk_buff *set_nw_tos(struct sk_buff *skb,
struct odp_flow_key *key,
const struct odp_action_nw_tos *a,
gfp_t gfp)
{
if (key->dl_type != htons(ETH_P_IP))
return skb;
skb = make_writable(skb, 0, gfp);
if (skb) {
struct iphdr *nh = ip_hdr(skb);
u8 *f = &nh->tos;
u8 old = *f;
/* We only set the lower 6 bits. */
u8 new = (a->nw_tos & 0x3f) | (nh->tos & 0xc0);
update_csum(&nh->check, skb, htons((uint16_t)old),
htons((uint16_t)new), 0);
*f = new;
}
return skb;
}
static struct sk_buff * static struct sk_buff *
set_tp_port(struct sk_buff *skb, struct odp_flow_key *key, set_tp_port(struct sk_buff *skb, struct odp_flow_key *key,
const struct odp_action_tp_port *a, const struct odp_action_tp_port *a,
@@ -491,6 +515,10 @@ int execute_actions(struct datapath *dp, struct sk_buff *skb,
skb = set_nw_addr(skb, key, &a->nw_addr, gfp); skb = set_nw_addr(skb, key, &a->nw_addr, gfp);
break; break;
case ODPAT_SET_NW_TOS:
skb = set_nw_tos(skb, key, &a->nw_tos, gfp);
break;
case ODPAT_SET_TP_SRC: case ODPAT_SET_TP_SRC:
case ODPAT_SET_TP_DST: case ODPAT_SET_TP_DST:
skb = set_tp_port(skb, key, &a->tp_port, gfp); skb = set_tp_port(skb, key, &a->tp_port, gfp);

View File

@@ -940,7 +940,6 @@ static int put_flow(struct datapath *dp, struct odp_flow_put __user *ufp)
error = -EFAULT; error = -EFAULT;
if (copy_from_user(&uf, ufp, sizeof(struct odp_flow_put))) if (copy_from_user(&uf, ufp, sizeof(struct odp_flow_put)))
goto error; goto error;
uf.flow.key.reserved = 0;
table = rcu_dereference(dp->table); table = rcu_dereference(dp->table);
flow = dp_table_lookup(table, &uf.flow.key); flow = dp_table_lookup(table, &uf.flow.key);
@@ -1085,7 +1084,6 @@ static int del_flow(struct datapath *dp, struct odp_flow __user *ufp)
error = -EFAULT; error = -EFAULT;
if (copy_from_user(&uf, ufp, sizeof uf)) if (copy_from_user(&uf, ufp, sizeof uf))
goto error; goto error;
uf.key.reserved = 0;
flow = dp_table_lookup(table, &uf.key); flow = dp_table_lookup(table, &uf.key);
error = -ENOENT; error = -ENOENT;
@@ -1121,7 +1119,6 @@ static int query_flows(struct datapath *dp, const struct odp_flowvec *flowvec)
if (__copy_from_user(&uf, ufp, sizeof uf)) if (__copy_from_user(&uf, ufp, sizeof uf))
return -EFAULT; return -EFAULT;
uf.key.reserved = 0;
flow = dp_table_lookup(table, &uf.key); flow = dp_table_lookup(table, &uf.key);
if (!flow) if (!flow)

View File

@@ -231,6 +231,7 @@ int flow_extract(struct sk_buff *skb, u16 in_port, struct odp_flow_key *key)
struct vlan_hdr *vh = (struct vlan_hdr*)(skb->data + nh_ofs); struct vlan_hdr *vh = (struct vlan_hdr*)(skb->data + nh_ofs);
key->dl_type = vh->h_vlan_encapsulated_proto; key->dl_type = vh->h_vlan_encapsulated_proto;
key->dl_vlan = vh->h_vlan_TCI & htons(VLAN_VID_MASK); key->dl_vlan = vh->h_vlan_TCI & htons(VLAN_VID_MASK);
key->dl_vlan_pcp = (ntohs(vh->h_vlan_TCI) & 0xe000) >> 13;
nh_ofs += sizeof(struct vlan_hdr); nh_ofs += sizeof(struct vlan_hdr);
} }
memcpy(key->dl_src, eth->h_source, ETH_ALEN); memcpy(key->dl_src, eth->h_source, ETH_ALEN);

View File

@@ -46,7 +46,7 @@
/* The most significant bit being set in the version field indicates an /* The most significant bit being set in the version field indicates an
* experimental OpenFlow version. * experimental OpenFlow version.
*/ */
#define OFP_VERSION 0x97 #define OFP_VERSION 0x98
#define OFP_MAX_TABLE_NAME_LEN 32 #define OFP_MAX_TABLE_NAME_LEN 32
#define OFP_MAX_PORT_NAME_LEN 16 #define OFP_MAX_PORT_NAME_LEN 16
@@ -313,6 +313,7 @@ enum ofp_action_type {
OFPAT_SET_DL_DST, /* Ethernet destination address. */ OFPAT_SET_DL_DST, /* Ethernet destination address. */
OFPAT_SET_NW_SRC, /* IP source address. */ OFPAT_SET_NW_SRC, /* IP source address. */
OFPAT_SET_NW_DST, /* IP destination address. */ OFPAT_SET_NW_DST, /* IP destination address. */
OFPAT_SET_NW_TOS, /* IP ToS/DSCP field (6 bits). */
OFPAT_SET_TP_SRC, /* TCP/UDP source port. */ OFPAT_SET_TP_SRC, /* TCP/UDP source port. */
OFPAT_SET_TP_DST, /* TCP/UDP destination port. */ OFPAT_SET_TP_DST, /* TCP/UDP destination port. */
OFPAT_VENDOR = 0xffff OFPAT_VENDOR = 0xffff
@@ -370,6 +371,15 @@ struct ofp_action_nw_addr {
}; };
OFP_ASSERT(sizeof(struct ofp_action_nw_addr) == 8); OFP_ASSERT(sizeof(struct ofp_action_nw_addr) == 8);
/* Action structure for OFPAT_SET_NW_TOS. */
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 pad[3];
};
OFP_ASSERT(sizeof(struct ofp_action_nw_tos) == 8);
/* Action structure for OFPAT_SET_TP_SRC/DST. */ /* Action structure for OFPAT_SET_TP_SRC/DST. */
struct ofp_action_tp_port { struct ofp_action_tp_port {
uint16_t type; /* OFPAT_SET_TP_SRC/DST. */ uint16_t type; /* OFPAT_SET_TP_SRC/DST. */
@@ -409,6 +419,7 @@ union ofp_action {
struct ofp_action_vlan_vid vlan_vid; struct ofp_action_vlan_vid vlan_vid;
struct ofp_action_vlan_pcp vlan_pcp; struct ofp_action_vlan_pcp vlan_pcp;
struct ofp_action_nw_addr nw_addr; struct ofp_action_nw_addr nw_addr;
struct ofp_action_nw_tos nw_tos;
struct ofp_action_tp_port tp_port; struct ofp_action_tp_port tp_port;
}; };
OFP_ASSERT(sizeof(union ofp_action) == 8); OFP_ASSERT(sizeof(union ofp_action) == 8);
@@ -436,14 +447,14 @@ enum ofp_flow_mod_command {
/* Flow wildcards. */ /* Flow wildcards. */
enum ofp_flow_wildcards { enum ofp_flow_wildcards {
OFPFW_IN_PORT = 1 << 0, /* Switch input port. */ OFPFW_IN_PORT = 1 << 0, /* Switch input port. */
OFPFW_DL_VLAN = 1 << 1, /* VLAN. */ OFPFW_DL_VLAN = 1 << 1, /* VLAN. */
OFPFW_DL_SRC = 1 << 2, /* Ethernet source address. */ OFPFW_DL_SRC = 1 << 2, /* Ethernet source address. */
OFPFW_DL_DST = 1 << 3, /* Ethernet destination address. */ OFPFW_DL_DST = 1 << 3, /* Ethernet destination address. */
OFPFW_DL_TYPE = 1 << 4, /* Ethernet frame type. */ OFPFW_DL_TYPE = 1 << 4, /* Ethernet frame type. */
OFPFW_NW_PROTO = 1 << 5, /* IP protocol. */ OFPFW_NW_PROTO = 1 << 5, /* IP protocol. */
OFPFW_TP_SRC = 1 << 6, /* TCP/UDP source port. */ OFPFW_TP_SRC = 1 << 6, /* TCP/UDP source port. */
OFPFW_TP_DST = 1 << 7, /* TCP/UDP destination port. */ OFPFW_TP_DST = 1 << 7, /* TCP/UDP destination port. */
/* IP source address wildcard bit count. 0 is exact match, 1 ignores the /* IP source address wildcard bit count. 0 is exact match, 1 ignores the
* LSB, 2 ignores the 2 least-significant bits, ..., 32 and higher wildcard * LSB, 2 ignores the 2 least-significant bits, ..., 32 and higher wildcard
@@ -460,8 +471,10 @@ enum ofp_flow_wildcards {
OFPFW_NW_DST_MASK = ((1 << OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT, OFPFW_NW_DST_MASK = ((1 << OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT,
OFPFW_NW_DST_ALL = 32 << OFPFW_NW_DST_SHIFT, OFPFW_NW_DST_ALL = 32 << OFPFW_NW_DST_SHIFT,
OFPFW_DL_VLAN_PCP = 1 << 20, /* VLAN priority. */
/* Wildcard all fields. */ /* Wildcard all fields. */
OFPFW_ALL = ((1 << 20) - 1) OFPFW_ALL = ((1 << 21) - 1)
}; };
/* The wildcards for ICMP type and code fields use the transport source /* The wildcards for ICMP type and code fields use the transport source
@@ -492,15 +505,17 @@ struct ofp_match {
uint8_t dl_src[OFP_ETH_ALEN]; /* Ethernet source address. */ uint8_t dl_src[OFP_ETH_ALEN]; /* Ethernet source address. */
uint8_t dl_dst[OFP_ETH_ALEN]; /* Ethernet destination address. */ uint8_t dl_dst[OFP_ETH_ALEN]; /* Ethernet destination address. */
uint16_t dl_vlan; /* Input VLAN. */ uint16_t dl_vlan; /* Input VLAN. */
uint8_t dl_vlan_pcp; /* Input VLAN priority. */
uint8_t pad1[1]; /* Align to 64-bits. */
uint16_t dl_type; /* Ethernet frame type. */ uint16_t dl_type; /* Ethernet frame type. */
uint8_t nw_proto; /* IP protocol. */ uint8_t nw_proto; /* IP protocol. */
uint8_t pad; /* Align to 32-bits. */ uint8_t pad2[3]; /* Align to 64-bits. */
uint32_t nw_src; /* IP source address. */ uint32_t nw_src; /* IP source address. */
uint32_t nw_dst; /* IP destination address. */ uint32_t nw_dst; /* IP destination address. */
uint16_t tp_src; /* TCP/UDP source port. */ uint16_t tp_src; /* TCP/UDP source port. */
uint16_t tp_dst; /* TCP/UDP destination port. */ uint16_t tp_dst; /* TCP/UDP destination port. */
}; };
OFP_ASSERT(sizeof(struct ofp_match) == 36); OFP_ASSERT(sizeof(struct ofp_match) == 40);
/* The match fields for ICMP type and code use the transport source and /* The match fields for ICMP type and code use the transport source and
* destination port fields, respectively. */ * destination port fields, respectively. */
@@ -536,7 +551,7 @@ struct ofp_flow_mod {
from the length field in the from the length field in the
header. */ header. */
}; };
OFP_ASSERT(sizeof(struct ofp_flow_mod) == 64); OFP_ASSERT(sizeof(struct ofp_flow_mod) == 68);
/* Why did this flow expire? */ /* Why did this flow expire? */
enum ofp_flow_expired_reason { enum ofp_flow_expired_reason {
@@ -558,7 +573,7 @@ struct ofp_flow_expired {
uint64_t packet_count; uint64_t packet_count;
uint64_t byte_count; uint64_t byte_count;
}; };
OFP_ASSERT(sizeof(struct ofp_flow_expired) == 72); OFP_ASSERT(sizeof(struct ofp_flow_expired) == 76);
/* Values for 'type' in ofp_error_message. These values are immutable: they /* Values for 'type' in ofp_error_message. These values are immutable: they
* will not change in future versions of the protocol (although new values may * will not change in future versions of the protocol (although new values may
@@ -703,7 +718,7 @@ struct ofp_flow_stats_request {
as an output port. A value of OFPP_NONE as an output port. A value of OFPP_NONE
indicates no restriction. */ indicates no restriction. */
}; };
OFP_ASSERT(sizeof(struct ofp_flow_stats_request) == 40); OFP_ASSERT(sizeof(struct ofp_flow_stats_request) == 44);
/* Body of reply to OFPST_FLOW request. */ /* Body of reply to OFPST_FLOW request. */
struct ofp_flow_stats { struct ofp_flow_stats {
@@ -716,7 +731,7 @@ struct ofp_flow_stats {
when this is not an exact-match entry. */ when this is not an exact-match entry. */
uint16_t idle_timeout; /* Number of seconds idle before expiration. */ uint16_t idle_timeout; /* Number of seconds idle before expiration. */
uint16_t hard_timeout; /* Number of seconds before expiration. */ uint16_t hard_timeout; /* Number of seconds before expiration. */
uint16_t pad2[3]; /* Pad to 64 bits. */ uint16_t pad2; /* Pad to 64 bits. */
uint64_t packet_count; /* Number of packets in flow. */ uint64_t packet_count; /* Number of packets in flow. */
uint64_t byte_count; /* Number of bytes in flow. */ uint64_t byte_count; /* Number of bytes in flow. */
struct ofp_action_header actions[0]; /* Actions. */ struct ofp_action_header actions[0]; /* Actions. */
@@ -733,7 +748,7 @@ struct ofp_aggregate_stats_request {
as an output port. A value of OFPP_NONE as an output port. A value of OFPP_NONE
indicates no restriction. */ indicates no restriction. */
}; };
OFP_ASSERT(sizeof(struct ofp_aggregate_stats_request) == 40); OFP_ASSERT(sizeof(struct ofp_aggregate_stats_request) == 44);
/* Body of reply to OFPST_AGGREGATE request. */ /* Body of reply to OFPST_AGGREGATE request. */
struct ofp_aggregate_stats_reply { struct ofp_aggregate_stats_reply {

View File

@@ -201,7 +201,7 @@ struct odp_flow_key {
__u8 dl_dst[ETH_ALEN]; /* Ethernet destination address. */ __u8 dl_dst[ETH_ALEN]; /* Ethernet destination address. */
__u8 nw_proto; /* IP protocol or lower 8 bits of __u8 nw_proto; /* IP protocol or lower 8 bits of
ARP opcode. */ ARP opcode. */
__u8 reserved; /* Pad to 64 bits. */ __u8 dl_vlan_pcp; /* Input VLAN priority. */
}; };
/* Flags for ODP_FLOW. */ /* Flags for ODP_FLOW. */
@@ -247,9 +247,10 @@ struct odp_flowvec {
#define ODPAT_SET_DL_DST 7 /* Ethernet destination address. */ #define ODPAT_SET_DL_DST 7 /* Ethernet destination address. */
#define ODPAT_SET_NW_SRC 8 /* IP source address. */ #define ODPAT_SET_NW_SRC 8 /* IP source address. */
#define ODPAT_SET_NW_DST 9 /* IP destination address. */ #define ODPAT_SET_NW_DST 9 /* IP destination address. */
#define ODPAT_SET_TP_SRC 10 /* TCP/UDP source port. */ #define ODPAT_SET_NW_TOS 10 /* IP ToS/DSCP field (6 bits). */
#define ODPAT_SET_TP_DST 11 /* TCP/UDP destination port. */ #define ODPAT_SET_TP_SRC 11 /* TCP/UDP source port. */
#define ODPAT_N_ACTIONS 12 #define ODPAT_SET_TP_DST 12 /* TCP/UDP destination port. */
#define ODPAT_N_ACTIONS 13
struct odp_action_output { struct odp_action_output {
__u16 type; /* ODPAT_OUTPUT. */ __u16 type; /* ODPAT_OUTPUT. */
@@ -301,6 +302,14 @@ struct odp_action_nw_addr {
__be32 nw_addr; /* IP address. */ __be32 nw_addr; /* IP address. */
}; };
struct odp_action_nw_tos {
__u16 type; /* ODPAT_SET_NW_TOS. */
__u8 nw_tos; /* IP ToS/DSCP field (6 bits). */
__u8 reserved1;
__u16 reserved2;
__u16 reserved3;
};
/* Action structure for ODPAT_SET_TP_SRC/DST. */ /* Action structure for ODPAT_SET_TP_SRC/DST. */
struct odp_action_tp_port { struct odp_action_tp_port {
__u16 type; /* ODPAT_SET_TP_SRC/DST. */ __u16 type; /* ODPAT_SET_TP_SRC/DST. */
@@ -318,6 +327,7 @@ union odp_action {
struct odp_action_vlan_pcp vlan_pcp; struct odp_action_vlan_pcp vlan_pcp;
struct odp_action_dl_addr dl_addr; struct odp_action_dl_addr dl_addr;
struct odp_action_nw_addr nw_addr; struct odp_action_nw_addr nw_addr;
struct odp_action_nw_tos nw_tos;
struct odp_action_tp_port tp_port; struct odp_action_tp_port tp_port;
}; };

View File

@@ -55,7 +55,6 @@ void
cls_rule_from_flow(struct cls_rule *rule, const flow_t *flow, cls_rule_from_flow(struct cls_rule *rule, const flow_t *flow,
uint32_t wildcards, unsigned int priority) uint32_t wildcards, unsigned int priority)
{ {
assert(flow->reserved == 0);
rule->flow = *flow; rule->flow = *flow;
flow_wildcards_init(&rule->wc, wildcards); flow_wildcards_init(&rule->wc, wildcards);
rule->priority = priority; rule->priority = priority;

View File

@@ -60,6 +60,7 @@
/* ----------------- ----------- -------- */ \ /* ----------------- ----------- -------- */ \
CLS_FIELD(OFPFW_IN_PORT, in_port, IN_PORT) \ CLS_FIELD(OFPFW_IN_PORT, in_port, IN_PORT) \
CLS_FIELD(OFPFW_DL_VLAN, dl_vlan, DL_VLAN) \ CLS_FIELD(OFPFW_DL_VLAN, dl_vlan, DL_VLAN) \
CLS_FIELD(OFPFW_DL_VLAN_PCP, dl_vlan_pcp, DL_VLAN_PCP) \
CLS_FIELD(OFPFW_DL_SRC, dl_src, DL_SRC) \ CLS_FIELD(OFPFW_DL_SRC, dl_src, DL_SRC) \
CLS_FIELD(OFPFW_DL_DST, dl_dst, DL_DST) \ CLS_FIELD(OFPFW_DL_DST, dl_dst, DL_DST) \
CLS_FIELD(OFPFW_DL_TYPE, dl_type, DL_TYPE) \ CLS_FIELD(OFPFW_DL_TYPE, dl_type, DL_TYPE) \

View File

@@ -663,7 +663,6 @@ dp_netdev_lookup_flow(const struct dp_netdev *dp, const flow_t *key)
{ {
struct dp_netdev_flow *flow; struct dp_netdev_flow *flow;
assert(key->reserved == 0);
HMAP_FOR_EACH_WITH_HASH (flow, struct dp_netdev_flow, node, HMAP_FOR_EACH_WITH_HASH (flow, struct dp_netdev_flow, node,
flow_hash(key, 0), &dp->flow_table) { flow_hash(key, 0), &dp->flow_table) {
if (flow_equal(&flow->key, key)) { if (flow_equal(&flow->key, key)) {
@@ -761,6 +760,7 @@ dpif_netdev_validate_actions(const union odp_action *actions, int n_actions,
case ODPAT_SET_DL_DST: case ODPAT_SET_DL_DST:
case ODPAT_SET_NW_SRC: case ODPAT_SET_NW_SRC:
case ODPAT_SET_NW_DST: case ODPAT_SET_NW_DST:
case ODPAT_SET_NW_TOS:
case ODPAT_SET_TP_SRC: case ODPAT_SET_TP_SRC:
case ODPAT_SET_TP_DST: case ODPAT_SET_TP_DST:
*mutates = true; *mutates = true;
@@ -805,7 +805,6 @@ add_flow(struct dpif *dpif, struct odp_flow *odp_flow)
flow = xzalloc(sizeof *flow); flow = xzalloc(sizeof *flow);
flow->key = odp_flow->key; flow->key = odp_flow->key;
flow->key.reserved = 0;
error = set_flow_actions(flow, odp_flow); error = set_flow_actions(flow, odp_flow);
if (error) { if (error) {
@@ -1170,6 +1169,23 @@ dp_netdev_set_nw_addr(struct ofpbuf *packet, flow_t *key,
} }
} }
static void
dp_netdev_set_nw_tos(struct ofpbuf *packet, flow_t *key,
const struct odp_action_nw_tos *a)
{
if (key->dl_type == htons(ETH_TYPE_IP)) {
struct ip_header *nh = packet->l3;
uint8_t *field = &nh->ip_tos;
/* We only set the lower 6 bits. */
uint8_t new = (a->nw_tos & 0x3f) | (nh->ip_tos & 0xc0);
nh->ip_csum = recalc_csum16(nh->ip_csum, htons((uint16_t)*field),
htons((uint16_t)a->nw_tos));
*field = new;
}
}
static void static void
dp_netdev_set_tp_port(struct ofpbuf *packet, flow_t *key, dp_netdev_set_tp_port(struct ofpbuf *packet, flow_t *key,
const struct odp_action_tp_port *a) const struct odp_action_tp_port *a)
@@ -1293,6 +1309,10 @@ dp_netdev_execute_actions(struct dp_netdev *dp,
dp_netdev_set_nw_addr(packet, key, &a->nw_addr); dp_netdev_set_nw_addr(packet, key, &a->nw_addr);
break; break;
case ODPAT_SET_NW_TOS:
dp_netdev_set_nw_tos(packet, key, &a->nw_tos);
break;
case ODPAT_SET_TP_SRC: case ODPAT_SET_TP_SRC:
case ODPAT_SET_TP_DST: case ODPAT_SET_TP_DST:
dp_netdev_set_tp_port(packet, key, &a->tp_port); dp_netdev_set_tp_port(packet, key, &a->tp_port);

View File

@@ -139,6 +139,7 @@ flow_extract(struct ofpbuf *packet, uint16_t in_port, flow_t *flow)
if (vh) { if (vh) {
flow->dl_type = vh->vlan_next_type; flow->dl_type = vh->vlan_next_type;
flow->dl_vlan = vh->vlan_tci & htons(VLAN_VID_MASK); flow->dl_vlan = vh->vlan_tci & htons(VLAN_VID_MASK);
flow->dl_vlan_pcp = (ntohs(vh->vlan_tci) & 0xe000) >> 13;
} }
} }
memcpy(flow->dl_src, eth->eth_src, ETH_ADDR_LEN); memcpy(flow->dl_src, eth->eth_src, ETH_ADDR_LEN);
@@ -246,6 +247,7 @@ flow_to_ovs_match(const flow_t *flow, uint32_t wildcards,
match->in_port = htons(flow->in_port == ODPP_LOCAL ? OFPP_LOCAL match->in_port = htons(flow->in_port == ODPP_LOCAL ? OFPP_LOCAL
: flow->in_port); : flow->in_port);
match->dl_vlan = flow->dl_vlan; match->dl_vlan = flow->dl_vlan;
match->dl_vlan_pcp = flow->dl_vlan_pcp;
memcpy(match->dl_src, flow->dl_src, ETH_ADDR_LEN); memcpy(match->dl_src, flow->dl_src, ETH_ADDR_LEN);
memcpy(match->dl_dst, flow->dl_dst, ETH_ADDR_LEN); memcpy(match->dl_dst, flow->dl_dst, ETH_ADDR_LEN);
match->dl_type = flow->dl_type; match->dl_type = flow->dl_type;
@@ -254,7 +256,8 @@ flow_to_ovs_match(const flow_t *flow, uint32_t wildcards,
match->nw_proto = flow->nw_proto; match->nw_proto = flow->nw_proto;
match->tp_src = flow->tp_src; match->tp_src = flow->tp_src;
match->tp_dst = flow->tp_dst; match->tp_dst = flow->tp_dst;
match->pad = 0; memset(match->pad1, '\0', sizeof match->pad1);
memset(match->pad2, '\0', sizeof match->pad2);
} }
/* Extract 'flow' with 'wildcards' into the OpenFlow match structure /* Extract 'flow' with 'wildcards' into the OpenFlow match structure
@@ -298,13 +301,13 @@ flow_from_match(flow_t *flow, uint32_t *wildcards,
flow->in_port = (match->in_port == htons(OFPP_LOCAL) ? ODPP_LOCAL flow->in_port = (match->in_port == htons(OFPP_LOCAL) ? ODPP_LOCAL
: ntohs(match->in_port)); : ntohs(match->in_port));
flow->dl_vlan = match->dl_vlan; flow->dl_vlan = match->dl_vlan;
flow->dl_vlan_pcp = match->dl_vlan_pcp;
flow->dl_type = match->dl_type; flow->dl_type = match->dl_type;
flow->tp_src = match->tp_src; flow->tp_src = match->tp_src;
flow->tp_dst = match->tp_dst; flow->tp_dst = match->tp_dst;
memcpy(flow->dl_src, match->dl_src, ETH_ADDR_LEN); memcpy(flow->dl_src, match->dl_src, ETH_ADDR_LEN);
memcpy(flow->dl_dst, match->dl_dst, ETH_ADDR_LEN); memcpy(flow->dl_dst, match->dl_dst, ETH_ADDR_LEN);
flow->nw_proto = match->nw_proto; flow->nw_proto = match->nw_proto;
flow->reserved = 0;
} }
char * char *
@@ -318,9 +321,10 @@ flow_to_string(const flow_t *flow)
void void
flow_format(struct ds *ds, const flow_t *flow) flow_format(struct ds *ds, const flow_t *flow)
{ {
ds_put_format(ds, "in_port%04x:vlan%d mac"ETH_ADDR_FMT"->"ETH_ADDR_FMT" " ds_put_format(ds, "in_port%04x:vlan%d:pcp%d mac"ETH_ADDR_FMT
"type%04x proto%"PRId8" ip"IP_FMT"->"IP_FMT" port%d->%d", "->"ETH_ADDR_FMT" type%04x proto%"PRId8" ip"IP_FMT
flow->in_port, ntohs(flow->dl_vlan), "->"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), 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,
IP_ARGS(&flow->nw_src), IP_ARGS(&flow->nw_dst), IP_ARGS(&flow->nw_src), IP_ARGS(&flow->nw_dst),

View File

@@ -80,6 +80,9 @@ format_odp_action(struct ds *ds, const union odp_action *a)
ds_put_format(ds, "set_nw_dst("IP_FMT")", ds_put_format(ds, "set_nw_dst("IP_FMT")",
IP_ARGS(&a->nw_addr.nw_addr)); IP_ARGS(&a->nw_addr.nw_addr));
break; break;
case ODPAT_SET_NW_TOS:
ds_put_format(ds, "set_nw_tos(%"PRIu8")", a->nw_tos.nw_tos);
break;
case ODPAT_SET_TP_SRC: case ODPAT_SET_TP_SRC:
ds_put_format(ds, "set_tp_src(%"PRIu16")", ntohs(a->tp_port.tp_port)); ds_put_format(ds, "set_tp_src(%"PRIu16")", ntohs(a->tp_port.tp_port));
break; break;

View File

@@ -243,6 +243,10 @@ ofp_print_action(struct ds *string, const struct ofp_action_header *ah,
sizeof(struct ofp_action_nw_addr), sizeof(struct ofp_action_nw_addr),
sizeof(struct ofp_action_nw_addr), sizeof(struct ofp_action_nw_addr),
}, },
[OFPAT_SET_NW_TOS] = {
sizeof(struct ofp_action_nw_tos),
sizeof(struct ofp_action_nw_tos),
},
[OFPAT_SET_TP_SRC] = { [OFPAT_SET_TP_SRC] = {
sizeof(struct ofp_action_tp_port), sizeof(struct ofp_action_tp_port),
sizeof(struct ofp_action_tp_port), sizeof(struct ofp_action_tp_port),
@@ -343,6 +347,12 @@ ofp_print_action(struct ds *string, const struct ofp_action_header *ah,
break; break;
} }
case OFPAT_SET_NW_TOS: {
struct ofp_action_nw_tos *nt = (struct ofp_action_nw_tos *)ah;
ds_put_format(string, "mod_nw_tos:%d", nt->nw_tos);
break;
}
case OFPAT_SET_TP_SRC: { case OFPAT_SET_TP_SRC: {
struct ofp_action_tp_port *ta = (struct ofp_action_tp_port *)ah; struct ofp_action_tp_port *ta = (struct ofp_action_tp_port *)ah;
ds_put_format(string, "mod_tp_src:%d", ntohs(ta->tp_port)); ds_put_format(string, "mod_tp_src:%d", ntohs(ta->tp_port));
@@ -669,6 +679,8 @@ ofp_match_to_string(const struct ofp_match *om, int verbosity)
"%d", ntohs(om->in_port)); "%d", ntohs(om->in_port));
print_wild(&f, "dl_vlan=", w & OFPFW_DL_VLAN, verbosity, print_wild(&f, "dl_vlan=", w & OFPFW_DL_VLAN, verbosity,
"0x%04x", ntohs(om->dl_vlan)); "0x%04x", ntohs(om->dl_vlan));
print_wild(&f, "dl_vlan_pcp=", w & OFPFW_DL_VLAN_PCP, verbosity,
"%d", om->dl_vlan_pcp);
print_wild(&f, "dl_src=", w & OFPFW_DL_SRC, verbosity, print_wild(&f, "dl_src=", w & OFPFW_DL_SRC, verbosity,
ETH_ADDR_FMT, ETH_ADDR_ARGS(om->dl_src)); ETH_ADDR_FMT, ETH_ADDR_ARGS(om->dl_src));
print_wild(&f, "dl_dst=", w & OFPFW_DL_DST, verbosity, print_wild(&f, "dl_dst=", w & OFPFW_DL_DST, verbosity,

View File

@@ -892,6 +892,7 @@ make_flow_mod(uint16_t command, const flow_t *flow, size_t actions_len)
memcpy(ofm->match.dl_src, flow->dl_src, sizeof ofm->match.dl_src); memcpy(ofm->match.dl_src, flow->dl_src, sizeof ofm->match.dl_src);
memcpy(ofm->match.dl_dst, flow->dl_dst, sizeof ofm->match.dl_dst); memcpy(ofm->match.dl_dst, flow->dl_dst, sizeof ofm->match.dl_dst);
ofm->match.dl_vlan = flow->dl_vlan; ofm->match.dl_vlan = flow->dl_vlan;
ofm->match.dl_vlan_pcp = flow->dl_vlan_pcp;
ofm->match.dl_type = flow->dl_type; ofm->match.dl_type = flow->dl_type;
ofm->match.nw_src = flow->nw_src; ofm->match.nw_src = flow->nw_src;
ofm->match.nw_dst = flow->nw_dst; ofm->match.nw_dst = flow->nw_dst;
@@ -1292,6 +1293,7 @@ check_action(const union ofp_action *a, unsigned int len, int max_ports)
case OFPAT_STRIP_VLAN: case OFPAT_STRIP_VLAN:
case OFPAT_SET_NW_SRC: case OFPAT_SET_NW_SRC:
case OFPAT_SET_NW_DST: case OFPAT_SET_NW_DST:
case OFPAT_SET_NW_TOS:
case OFPAT_SET_TP_SRC: case OFPAT_SET_TP_SRC:
case OFPAT_SET_TP_DST: case OFPAT_SET_TP_DST:
return check_action_exact_len(a, len, 8); return check_action_exact_len(a, len, 8);

View File

@@ -1853,6 +1853,7 @@ handle_features_request(struct ofproto *p, struct ofconn *ofconn,
(1u << OFPAT_SET_DL_DST) | (1u << OFPAT_SET_DL_DST) |
(1u << OFPAT_SET_NW_SRC) | (1u << OFPAT_SET_NW_SRC) |
(1u << OFPAT_SET_NW_DST) | (1u << OFPAT_SET_NW_DST) |
(1u << OFPAT_SET_NW_TOS) |
(1u << OFPAT_SET_TP_SRC) | (1u << OFPAT_SET_TP_SRC) |
(1u << OFPAT_SET_TP_DST)); (1u << OFPAT_SET_TP_DST));
@@ -2170,6 +2171,10 @@ do_xlate_actions(const union ofp_action *in, size_t n_in,
case OFPAT_SET_NW_DST: case OFPAT_SET_NW_DST:
oa = odp_actions_add(ctx->out, ODPAT_SET_NW_DST); oa = odp_actions_add(ctx->out, ODPAT_SET_NW_DST);
oa->nw_addr.nw_addr = ia->nw_addr.nw_addr; oa->nw_addr.nw_addr = ia->nw_addr.nw_addr;
case OFPAT_SET_NW_TOS:
oa = odp_actions_add(ctx->out, ODPAT_SET_NW_TOS);
oa->nw_tos.nw_tos = ia->nw_tos.nw_tos;
break; break;
case OFPAT_SET_TP_SRC: case OFPAT_SET_TP_SRC:
@@ -2554,7 +2559,7 @@ flow_stats_cb(struct cls_rule *rule_, void *cbdata_)
ofs->priority = htons(rule->cr.priority); ofs->priority = htons(rule->cr.priority);
ofs->idle_timeout = htons(rule->idle_timeout); ofs->idle_timeout = htons(rule->idle_timeout);
ofs->hard_timeout = htons(rule->hard_timeout); ofs->hard_timeout = htons(rule->hard_timeout);
memset(ofs->pad2, 0, sizeof ofs->pad2); ofs->pad2 = 0;
ofs->packet_count = htonll(packet_count); ofs->packet_count = htonll(packet_count);
ofs->byte_count = htonll(byte_count); ofs->byte_count = htonll(byte_count);
memcpy(ofs->actions, rule->actions, act_len); memcpy(ofs->actions, rule->actions, act_len);

View File

@@ -203,8 +203,9 @@ sub output {
1); # in_port 1); # in_port
print FLOWS pack_ethaddr($flow{DL_SRC}); print FLOWS pack_ethaddr($flow{DL_SRC});
print FLOWS pack_ethaddr($flow{DL_DST}); print FLOWS pack_ethaddr($flow{DL_DST});
print FLOWS pack('nnCxNNnn', print FLOWS pack('nCxnCxxxNNnn',
$flow{DL_VLAN}, $flow{DL_VLAN},
0, # DL_VLAN_PCP
$flow{DL_TYPE}, $flow{DL_TYPE},
$flow{NW_PROTO}, $flow{NW_PROTO},
inet_aton($flow{NW_SRC}), inet_aton($flow{NW_SRC}),

View File

@@ -240,6 +240,7 @@ static uint32_t nw_dst_values[] = { T_HTONL(0xc0a80002),
T_HTONL(0xc0a04455) }; T_HTONL(0xc0a04455) };
static uint16_t in_port_values[] = { T_HTONS(1), T_HTONS(OFPP_LOCAL) }; static uint16_t in_port_values[] = { T_HTONS(1), T_HTONS(OFPP_LOCAL) };
static uint16_t dl_vlan_values[] = { T_HTONS(101), T_HTONS(0) }; static uint16_t dl_vlan_values[] = { T_HTONS(101), T_HTONS(0) };
static uint8_t dl_vlan_pcp_values[] = { 7, 0 };
static uint16_t dl_type_values[] static uint16_t dl_type_values[]
= { T_HTONS(ETH_TYPE_IP), T_HTONS(ETH_TYPE_ARP) }; = { T_HTONS(ETH_TYPE_IP), T_HTONS(ETH_TYPE_ARP) };
static uint16_t tp_src_values[] = { T_HTONS(49362), T_HTONS(80) }; static uint16_t tp_src_values[] = { T_HTONS(49362), T_HTONS(80) };
@@ -261,6 +262,9 @@ init_values(void)
values[CLS_F_IDX_DL_VLAN][0] = &dl_vlan_values[0]; values[CLS_F_IDX_DL_VLAN][0] = &dl_vlan_values[0];
values[CLS_F_IDX_DL_VLAN][1] = &dl_vlan_values[1]; values[CLS_F_IDX_DL_VLAN][1] = &dl_vlan_values[1];
values[CLS_F_IDX_DL_VLAN_PCP][0] = &dl_vlan_pcp_values[0];
values[CLS_F_IDX_DL_VLAN_PCP][1] = &dl_vlan_pcp_values[1];
values[CLS_F_IDX_DL_SRC][0] = dl_src_values[0]; values[CLS_F_IDX_DL_SRC][0] = dl_src_values[0];
values[CLS_F_IDX_DL_SRC][1] = dl_src_values[1]; values[CLS_F_IDX_DL_SRC][1] = dl_src_values[1];
@@ -290,6 +294,7 @@ init_values(void)
#define N_NW_DST_VALUES ARRAY_SIZE(nw_dst_values) #define N_NW_DST_VALUES ARRAY_SIZE(nw_dst_values)
#define N_IN_PORT_VALUES ARRAY_SIZE(in_port_values) #define N_IN_PORT_VALUES ARRAY_SIZE(in_port_values)
#define N_DL_VLAN_VALUES ARRAY_SIZE(dl_vlan_values) #define N_DL_VLAN_VALUES ARRAY_SIZE(dl_vlan_values)
#define N_DL_VLAN_PCP_VALUES ARRAY_SIZE(dl_vlan_pcp_values)
#define N_DL_TYPE_VALUES ARRAY_SIZE(dl_type_values) #define N_DL_TYPE_VALUES ARRAY_SIZE(dl_type_values)
#define N_TP_SRC_VALUES ARRAY_SIZE(tp_src_values) #define N_TP_SRC_VALUES ARRAY_SIZE(tp_src_values)
#define N_TP_DST_VALUES ARRAY_SIZE(tp_dst_values) #define N_TP_DST_VALUES ARRAY_SIZE(tp_dst_values)
@@ -301,6 +306,7 @@ init_values(void)
N_NW_DST_VALUES * \ N_NW_DST_VALUES * \
N_IN_PORT_VALUES * \ N_IN_PORT_VALUES * \
N_DL_VLAN_VALUES * \ N_DL_VLAN_VALUES * \
N_DL_VLAN_PCP_VALUES * \
N_DL_TYPE_VALUES * \ N_DL_TYPE_VALUES * \
N_TP_SRC_VALUES * \ N_TP_SRC_VALUES * \
N_TP_DST_VALUES * \ N_TP_DST_VALUES * \
@@ -350,6 +356,8 @@ compare_classifiers(struct classifier *cls, struct tcls *tcls)
flow.nw_dst = nw_dst_values[get_value(&x, N_NW_DST_VALUES)]; flow.nw_dst = nw_dst_values[get_value(&x, N_NW_DST_VALUES)];
flow.in_port = in_port_values[get_value(&x, N_IN_PORT_VALUES)]; flow.in_port = in_port_values[get_value(&x, N_IN_PORT_VALUES)];
flow.dl_vlan = dl_vlan_values[get_value(&x, N_DL_VLAN_VALUES)]; flow.dl_vlan = dl_vlan_values[get_value(&x, N_DL_VLAN_VALUES)];
flow.dl_vlan_pcp = dl_vlan_pcp_values[get_value(&x,
N_DL_VLAN_PCP_VALUES)];
flow.dl_type = dl_type_values[get_value(&x, N_DL_TYPE_VALUES)]; flow.dl_type = dl_type_values[get_value(&x, N_DL_TYPE_VALUES)];
flow.tp_src = tp_src_values[get_value(&x, N_TP_SRC_VALUES)]; flow.tp_src = tp_src_values[get_value(&x, N_TP_SRC_VALUES)];
flow.tp_dst = tp_dst_values[get_value(&x, N_TP_DST_VALUES)]; flow.tp_dst = tp_dst_values[get_value(&x, N_TP_DST_VALUES)];
@@ -358,7 +366,6 @@ compare_classifiers(struct classifier *cls, struct tcls *tcls)
memcpy(flow.dl_dst, dl_dst_values[get_value(&x, N_DL_DST_VALUES)], memcpy(flow.dl_dst, dl_dst_values[get_value(&x, N_DL_DST_VALUES)],
ETH_ADDR_LEN); ETH_ADDR_LEN);
flow.nw_proto = nw_proto_values[get_value(&x, N_NW_PROTO_VALUES)]; flow.nw_proto = nw_proto_values[get_value(&x, N_NW_PROTO_VALUES)];
flow.reserved = 0;
for (include = 1; include <= 3; include++) { for (include = 1; include <= 3; include++) {
cr0 = lookup_with_include_bits(cls, &flow, include); cr0 = lookup_with_include_bits(cls, &flow, include);

View File

@@ -212,6 +212,11 @@ as \fIvlan\fR to match packets that are not tagged with a Virtual LAN;
otherwise, specify a number between 0 and 4095, inclusive, as the otherwise, specify a number between 0 and 4095, inclusive, as the
12-bit VLAN ID to match. 12-bit VLAN ID to match.
.IP \fBdl_vlan_pcp=\fIpriority\fR
Matches IEEE 802.1q Priority Code Point (PCP) \fIpriority\fR, which is
specified as a value between 0 and 7, inclusive. A higher value
indicates a higher frame priority level.
.IP \fBdl_src=\fImac\fR .IP \fBdl_src=\fImac\fR
Matches Ethernet source address \fImac\fR, which is specified as 6 pairs Matches Ethernet source address \fImac\fR, which is specified as 6 pairs
of hexadecimal digits delimited by colons (e.g. \fB00:0A:E4:25:6B:B0\fR). of hexadecimal digits delimited by colons (e.g. \fB00:0A:E4:25:6B:B0\fR).
@@ -348,6 +353,12 @@ Sets the TCP or UDP source port to \fIport\fR.
.IP \fBmod_tp_dst\fB:\fIport\fR .IP \fBmod_tp_dst\fB:\fIport\fR
Sets the TCP or UDP destination port to \fIport\fR. Sets the TCP or UDP destination port to \fIport\fR.
.IP \fBmod_nw_tos\fB:\fItos\fR
Sets the IP ToS/DSCP field to \fItos\fR. Valid values are between 0 and
255, inclusive. Note that the two lower reserved bits are never
modified.
.RE .RE
.IP .IP

View File

@@ -580,6 +580,10 @@ str_to_action(char *str, struct ofpbuf *b)
struct ofp_action_tp_port *ta; struct ofp_action_tp_port *ta;
ta = put_action(b, sizeof *ta, OFPAT_SET_TP_DST); ta = put_action(b, sizeof *ta, OFPAT_SET_TP_DST);
ta->tp_port = htons(str_to_u32(arg)); ta->tp_port = htons(str_to_u32(arg));
} else if (!strcasecmp(act, "mod_nw_tos")) {
struct ofp_action_nw_tos *nt;
nt = put_action(b, sizeof *nt, OFPAT_SET_NW_TOS);
nt->nw_tos = str_to_u32(arg);
} else if (!strcasecmp(act, "output")) { } else if (!strcasecmp(act, "output")) {
put_output_action(b, str_to_u32(arg)); put_output_action(b, str_to_u32(arg));
} else if (!strcasecmp(act, "drop")) { } else if (!strcasecmp(act, "drop")) {
@@ -653,6 +657,7 @@ parse_field(const char *name, const struct field **f_out)
static const struct field fields[] = { static const struct field fields[] = {
{ "in_port", OFPFW_IN_PORT, F_U16, F_OFS(in_port), 0 }, { "in_port", OFPFW_IN_PORT, F_U16, F_OFS(in_port), 0 },
{ "dl_vlan", OFPFW_DL_VLAN, F_U16, F_OFS(dl_vlan), 0 }, { "dl_vlan", OFPFW_DL_VLAN, F_U16, F_OFS(dl_vlan), 0 },
{ "dl_vlan_pcp", OFPFW_DL_VLAN_PCP, F_U8, F_OFS(dl_vlan_pcp), 0 },
{ "dl_src", OFPFW_DL_SRC, F_MAC, F_OFS(dl_src), 0 }, { "dl_src", OFPFW_DL_SRC, F_MAC, F_OFS(dl_src), 0 },
{ "dl_dst", OFPFW_DL_DST, F_MAC, F_OFS(dl_dst), 0 }, { "dl_dst", OFPFW_DL_DST, F_MAC, F_OFS(dl_dst), 0 },
{ "dl_type", OFPFW_DL_TYPE, F_U16, F_OFS(dl_type), 0 }, { "dl_type", OFPFW_DL_TYPE, F_U16, F_OFS(dl_type), 0 },