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:
@@ -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);
|
||||||
|
@@ -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)
|
||||||
|
@@ -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);
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
@@ -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) \
|
||||||
|
@@ -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);
|
||||||
|
14
lib/flow.c
14
lib/flow.c
@@ -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),
|
||||||
|
@@ -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;
|
||||||
|
@@ -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,
|
||||||
|
@@ -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);
|
||||||
|
@@ -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);
|
||||||
|
@@ -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}),
|
||||||
|
@@ -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);
|
||||||
|
@@ -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
|
||||||
|
@@ -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 },
|
||||||
|
Reference in New Issue
Block a user