[ovs-dev] [netlink 07/16] datapath: Combine dl_vlan and dl_vlan_pcp.
Ben Pfaff
blp at nicira.com
Fri Sep 10 15:55:07 PDT 2010
This allows eliminating padding from odp_flow_key, although actually doing
that is postponed until the next commit.
Signed-off-by: Ben Pfaff <blp at nicira.com>
---
datapath/actions.c | 21 ++------
datapath/datapath.c | 15 +++---
datapath/flow.c | 4 +-
.../linux-2.6/compat-2.6/include/linux/if_vlan.h | 10 ++++
include/openvswitch/datapath-protocol.h | 52 ++++++++------------
lib/dpif-netdev.c | 44 +++++++----------
lib/odp-util.c | 39 ++++++++++-----
lib/packets.h | 20 ++++++++
ofproto/ofproto-sflow.c | 14 +++--
ofproto/ofproto.c | 11 +++--
vswitchd/bridge.c | 5 +-
11 files changed, 127 insertions(+), 108 deletions(-)
diff --git a/datapath/actions.c b/datapath/actions.c
index c0b3040..961a0dc 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -75,15 +75,8 @@ static struct sk_buff *modify_vlan_tci(struct datapath *dp, struct sk_buff *skb,
const union odp_action *a, int n_actions,
gfp_t gfp)
{
- u16 tci, mask;
-
- if (a->type == ODPAT_SET_VLAN_VID) {
- tci = ntohs(a->vlan_vid.vlan_vid);
- mask = VLAN_VID_MASK;
- } else {
- tci = a->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT;
- mask = VLAN_PCP_MASK;
- }
+ __be16 mask = a->dl_tci.mask;
+ __be16 tci = a->dl_tci.tci;
skb = make_writable(skb, VLAN_HLEN, gfp);
if (!skb)
@@ -100,7 +93,7 @@ static struct sk_buff *modify_vlan_tci(struct datapath *dp, struct sk_buff *skb,
vh = vlan_eth_hdr(skb);
old_tci = vh->h_vlan_TCI;
- vh->h_vlan_TCI = htons((ntohs(vh->h_vlan_TCI) & ~mask) | tci);
+ vh->h_vlan_TCI = (vh->h_vlan_TCI & ~mask) | tci;
if (OVS_CB(skb)->ip_summed == OVS_CSUM_COMPLETE) {
__be16 diff[] = { ~old_tci, vh->h_vlan_TCI };
@@ -156,7 +149,7 @@ static struct sk_buff *modify_vlan_tci(struct datapath *dp, struct sk_buff *skb,
/* GSO can change the checksum type so update.*/
compute_ip_summed(segs, true);
- segs = __vlan_put_tag(segs, tci);
+ segs = __vlan_put_tag(segs, ntohs(tci));
err = -ENOMEM;
if (segs) {
err = execute_actions(dp, segs,
@@ -186,7 +179,7 @@ static struct sk_buff *modify_vlan_tci(struct datapath *dp, struct sk_buff *skb,
* e.g. vconfig(8)), so call the software-only version
* __vlan_put_tag() directly instead.
*/
- skb = __vlan_put_tag(skb, tci);
+ skb = __vlan_put_tag(skb, ntohs(tci));
if (!skb)
return ERR_PTR(-ENOMEM);
@@ -205,7 +198,6 @@ static struct sk_buff *strip_vlan(struct sk_buff *skb, gfp_t gfp)
skb = make_writable(skb, 0, gfp);
if (skb)
vlan_pull_tag(skb);
-
return skb;
}
@@ -478,8 +470,7 @@ int execute_actions(struct datapath *dp, struct sk_buff *skb,
OVS_CB(skb)->tun_id = a->tunnel.tun_id;
break;
- case ODPAT_SET_VLAN_VID:
- case ODPAT_SET_VLAN_PCP:
+ case ODPAT_SET_DL_TCI:
skb = modify_vlan_tci(dp, skb, key, a, n_actions, gfp);
if (IS_ERR(skb))
return PTR_ERR(skb);
diff --git a/datapath/datapath.c b/datapath/datapath.c
index 3ab302a..5941d26 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -858,6 +858,8 @@ static int validate_actions(const struct sw_flow_actions *actions)
for (i = 0; i < actions->n_actions; i++) {
const union odp_action *a = &actions->actions[i];
+ __be16 mask;
+
switch (a->type) {
case ODPAT_CONTROLLER:
case ODPAT_STRIP_VLAN:
@@ -879,14 +881,13 @@ static int validate_actions(const struct sw_flow_actions *actions)
return -EINVAL;
break;
- case ODPAT_SET_VLAN_VID:
- if (a->vlan_vid.vlan_vid & htons(~VLAN_VID_MASK))
+ case ODPAT_SET_DL_TCI:
+ mask = a->dl_tci.mask;
+ if (mask != htons(VLAN_VID_MASK) &&
+ mask != htons(VLAN_PCP_MASK) &&
+ mask != htons(VLAN_VID_MASK | VLAN_PCP_MASK))
return -EINVAL;
- break;
-
- case ODPAT_SET_VLAN_PCP:
- if (a->vlan_pcp.vlan_pcp
- & ~(VLAN_PCP_MASK >> VLAN_PCP_SHIFT))
+ if (a->dl_tci.tci & ~mask)
return -EINVAL;
break;
diff --git a/datapath/flow.c b/datapath/flow.c
index dbfe5dd..06a2ce3 100644
--- a/datapath/flow.c
+++ b/datapath/flow.c
@@ -177,8 +177,7 @@ static void parse_vlan(struct sk_buff *skb, struct odp_flow_key *key)
return;
qp = (struct qtag_prefix *) skb->data;
- key->dl_vlan = qp->tci & htons(VLAN_VID_MASK);
- key->dl_vlan_pcp = (ntohs(qp->tci) & VLAN_PCP_MASK) >> VLAN_PCP_SHIFT;
+ key->dl_tci = qp->tci | htons(ODP_TCI_PRESENT);
__skb_pull(skb, sizeof(struct qtag_prefix));
}
@@ -246,7 +245,6 @@ int flow_extract(struct sk_buff *skb, u16 in_port, struct odp_flow_key *key)
memset(key, 0, sizeof *key);
key->tun_id = OVS_CB(skb)->tun_id;
key->in_port = in_port;
- key->dl_vlan = htons(ODP_VLAN_NONE);
OVS_CB(skb)->is_frag = false;
/*
diff --git a/datapath/linux-2.6/compat-2.6/include/linux/if_vlan.h b/datapath/linux-2.6/compat-2.6/include/linux/if_vlan.h
index 8bc4ac5..f418407 100644
--- a/datapath/linux-2.6/compat-2.6/include/linux/if_vlan.h
+++ b/datapath/linux-2.6/compat-2.6/include/linux/if_vlan.h
@@ -44,4 +44,14 @@ static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, u16 vlan_tci)
return skb;
}
+
+/* All of these were introduced in a single commit preceding 2.6.33, so
+ * presumably all of them or none of them are present. */
+#ifndef VLAN_PRIO_MASK
+#define VLAN_PRIO_MASK 0xe000 /* Priority Code Point */
+#define VLAN_PRIO_SHIFT 13
+#define VLAN_CFI_MASK 0x1000 /* Canonical Format Indicator */
+#define VLAN_TAG_PRESENT VLAN_CFI_MASK
+#endif
+
#endif /* linux/if_vlan.h wrapper */
diff --git a/include/openvswitch/datapath-protocol.h b/include/openvswitch/datapath-protocol.h
index 2186562..3e5bf28 100644
--- a/include/openvswitch/datapath-protocol.h
+++ b/include/openvswitch/datapath-protocol.h
@@ -204,12 +204,21 @@ struct odp_flow_stats {
uint16_t error; /* Used by ODP_FLOW_GET. */
};
+/*
+ * The datapath protocol adopts the Linux convention for TCI fields: if an
+ * 802.1Q header is present then its TCI value is used verbatim except that the
+ * CFI bit (0x1000) is always set to 1, and all-bits-zero indicates no 802.1Q
+ * header.
+ */
+#define ODP_TCI_PRESENT 0x1000 /* CFI bit */
+
struct odp_flow_key {
ovs_be32 tun_id; /* Encapsulating tunnel ID. */
ovs_be32 nw_src; /* IP source address. */
ovs_be32 nw_dst; /* IP destination address. */
uint16_t in_port; /* Input switch port. */
- ovs_be16 dl_vlan; /* Input VLAN. */
+ ovs_be16 dl_tci; /* All zeros if 802.1Q header absent,
+ * ODP_TCI_PRESENT set if present. */
ovs_be16 dl_type; /* Ethernet frame type. */
ovs_be16 tp_src; /* TCP/UDP source port. */
ovs_be16 tp_dst; /* TCP/UDP destination port. */
@@ -217,9 +226,8 @@ struct odp_flow_key {
uint8_t dl_dst[6]; /* Ethernet destination address. */
uint8_t nw_proto; /* IP protocol or lower 8 bits of
ARP opcode. */
- uint8_t dl_vlan_pcp; /* Input VLAN priority. */
uint8_t nw_tos; /* IP ToS (DSCP field, 6 bits). */
- uint8_t reserved[3]; /* Align to 32-bits...must be zeroed. */
+ uint32_t reserved[1]; /* Reserved for later use. */
};
/* Flags for ODP_FLOW. */
@@ -249,16 +257,10 @@ struct odp_flowvec {
uint32_t n_flows;
};
-/* The VLAN id is 12 bits, so we can use the entire 16 bits to indicate
- * special conditions. All ones is used to match that no VLAN id was
- * set. */
-#define ODP_VLAN_NONE 0xffff
-
/* Action types. */
#define ODPAT_OUTPUT 0 /* Output to switch port. */
#define ODPAT_CONTROLLER 2 /* Send copy to controller. */
-#define ODPAT_SET_VLAN_VID 3 /* Set the 802.1q VLAN id. */
-#define ODPAT_SET_VLAN_PCP 4 /* Set the 802.1q priority. */
+#define ODPAT_SET_DL_TCI 3 /* Set the 802.1q VLAN VID and/or PCP. */
#define ODPAT_STRIP_VLAN 5 /* Strip the 802.1q header. */
#define ODPAT_SET_DL_SRC 6 /* Ethernet source address. */
#define ODPAT_SET_DL_DST 7 /* Ethernet destination address. */
@@ -292,21 +294,13 @@ struct odp_action_tunnel {
ovs_be32 tun_id; /* Tunnel ID. */
};
-/* Action structure for ODPAT_SET_VLAN_VID. */
-struct odp_action_vlan_vid {
- uint16_t type; /* ODPAT_SET_VLAN_VID. */
- ovs_be16 vlan_vid; /* VLAN id. */
- uint16_t reserved1;
- uint16_t reserved2;
-};
-
-/* Action structure for ODPAT_SET_VLAN_PCP. */
-struct odp_action_vlan_pcp {
- uint16_t type; /* ODPAT_SET_VLAN_PCP. */
- uint8_t vlan_pcp; /* VLAN priority. */
- uint8_t reserved1;
- uint16_t reserved2;
- uint16_t reserved3;
+/* Action structure for ODPAT_SET_DL_TCI. */
+struct odp_action_dl_tci {
+ uint16_t type; /* ODPAT_SET_DL_TCI. */
+ ovs_be16 tci; /* New TCI. Bits not in mask must be zero. */
+ ovs_be16 mask; /* 0x0fff to set VID, 0xe000 to set PCP,
+ * or 0xefff to set both. */
+ uint16_t reserved;
};
/* Action structure for ODPAT_SET_DL_SRC/DST. */
@@ -350,8 +344,7 @@ union odp_action {
struct odp_action_output output;
struct odp_action_controller controller;
struct odp_action_tunnel tunnel;
- struct odp_action_vlan_vid vlan_vid;
- struct odp_action_vlan_pcp vlan_pcp;
+ struct odp_action_dl_tci dl_tci;
struct odp_action_dl_addr dl_addr;
struct odp_action_nw_addr nw_addr;
struct odp_action_nw_tos nw_tos;
@@ -408,9 +401,4 @@ struct odp_vport_mtu {
*/
#define ODP_DL_TYPE_NOT_ETH_TYPE 0x05ff
-/* The VLAN id is 12-bits, so we can use the entire 16 bits to indicate
- * special conditions. All ones indicates that no VLAN id was set.
- */
-#define ODP_VLAN_NONE 0xffff
-
#endif /* openvswitch/datapath-protocol.h */
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index bbc590f..d848995 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -609,6 +609,8 @@ dp_netdev_lookup_flow(const struct dp_netdev *dp,
{
struct dp_netdev_flow *flow;
+ BUILD_ASSERT_DECL(ARRAY_SIZE(key->reserved) == 1);
+ assert(!key->reserved[0]);
HMAP_FOR_EACH_WITH_HASH (flow, struct dp_netdev_flow, node,
odp_flow_key_hash(key, 0), &dp->flow_table) {
if (odp_flow_key_equal(&flow->key, key)) {
@@ -680,16 +682,14 @@ dpif_netdev_validate_actions(const union odp_action *actions, int n_actions,
case ODPAT_CONTROLLER:
break;
- case ODPAT_SET_VLAN_VID:
+ case ODPAT_SET_DL_TCI:
*mutates = true;
- if (a->vlan_vid.vlan_vid & htons(~VLAN_VID_MASK)) {
+ if (a->dl_tci.mask != htons(VLAN_VID_MASK)
+ && a->dl_tci.mask != htons(VLAN_PCP_MASK)
+ && a->dl_tci.mask != htons(VLAN_VID_MASK | VLAN_PCP_MASK)) {
return EINVAL;
}
- break;
-
- case ODPAT_SET_VLAN_PCP:
- *mutates = true;
- if (a->vlan_pcp.vlan_pcp & ~(VLAN_PCP_MASK >> VLAN_PCP_SHIFT)) {
+ if (a->dl_tci.tci & ~a->dl_tci.mask){
return EINVAL;
}
break;
@@ -1027,16 +1027,16 @@ dp_netdev_wait(void)
}
-/* Modify the TCI field of 'packet'. If a VLAN tag is not present, one
- * is added with the TCI field set to 'tci'. If a VLAN tag is present,
- * then 'mask' bits are cleared before 'tci' is logically OR'd into the
- * TCI field.
+/* Modify the TCI field of 'packet'. If a VLAN tag is not present, one is
+ * added with the TCI field set to 'a->tci'. If a VLAN tag is present, then
+ * 'a->mask' bits are cleared before 'a->tci' is logically OR'd into the TCI
+ * field.
*
- * Note that the function does not ensure that 'tci' does not affect
- * bits outside of 'mask'.
+ * Note that the function does not ensure that 'a->tci' does not affect bits
+ * outside of 'a->mask'.
*/
static void
-dp_netdev_modify_vlan_tci(struct ofpbuf *packet, uint16_t tci, uint16_t mask)
+dp_netdev_set_dl_tci(struct ofpbuf *packet, const struct odp_action_dl_tci *a)
{
struct vlan_eth_header *veh;
struct eth_header *eh;
@@ -1046,8 +1046,7 @@ dp_netdev_modify_vlan_tci(struct ofpbuf *packet, uint16_t tci, uint16_t mask)
&& eh->eth_type == htons(ETH_TYPE_VLAN)) {
/* Clear 'mask' bits, but maintain other TCI bits. */
veh = packet->l2;
- veh->veth_tci &= ~htons(mask);
- veh->veth_tci |= htons(tci);
+ veh->veth_tci = (veh->veth_tci & ~a->mask) | a->tci;
} else {
/* Insert new 802.1Q header. */
struct eth_header *eh = packet->l2;
@@ -1055,7 +1054,7 @@ dp_netdev_modify_vlan_tci(struct ofpbuf *packet, uint16_t tci, uint16_t mask)
memcpy(tmp.veth_dst, eh->eth_dst, ETH_ADDR_LEN);
memcpy(tmp.veth_src, eh->eth_src, ETH_ADDR_LEN);
tmp.veth_type = htons(ETH_TYPE_VLAN);
- tmp.veth_tci = htons(tci);
+ tmp.veth_tci = htons(a->tci);
tmp.veth_next_type = eh->eth_type;
veh = ofpbuf_push_uninit(packet, VLAN_HEADER_LEN);
@@ -1252,15 +1251,8 @@ dp_netdev_execute_actions(struct dp_netdev *dp,
key->in_port, a->controller.arg);
break;
- case ODPAT_SET_VLAN_VID:
- dp_netdev_modify_vlan_tci(packet, ntohs(a->vlan_vid.vlan_vid),
- VLAN_VID_MASK);
- break;
-
- case ODPAT_SET_VLAN_PCP:
- dp_netdev_modify_vlan_tci(packet,
- a->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT,
- VLAN_PCP_MASK);
+ case ODPAT_SET_DL_TCI:
+ dp_netdev_set_dl_tci(packet, &a->dl_tci);
break;
case ODPAT_STRIP_VLAN:
diff --git a/lib/odp-util.c b/lib/odp-util.c
index b980611..512a305 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -42,10 +42,14 @@ odp_actions_add(struct odp_actions *actions, uint16_t type)
void
format_odp_flow_key(struct ds *ds, const struct odp_flow_key *key)
{
- ds_put_format(ds, "in_port%04x:vlan%d:pcp%d mac"ETH_ADDR_FMT
- "->"ETH_ADDR_FMT" type%04x proto%"PRId8" tos%"PRIu8
- " ip"IP_FMT"->"IP_FMT" port%d->%d",
- key->in_port, ntohs(key->dl_vlan), key->dl_vlan_pcp,
+ ds_put_format(ds, "in_port%04x", key->in_port);
+ if (key->dl_tci) {
+ ds_put_format(ds, ":vlan%"PRIu16":pcp%d",
+ vlan_tci_to_vid(key->dl_tci),
+ vlan_tci_to_pcp(key->dl_tci));
+ }
+ ds_put_format(ds, " mac"ETH_ADDR_FMT"->"ETH_ADDR_FMT" type%04x "
+ "proto%"PRId8" tos%"PRIu8" ip"IP_FMT"->"IP_FMT" port%d->%d",
ETH_ADDR_ARGS(key->dl_src), ETH_ADDR_ARGS(key->dl_dst),
ntohs(key->dl_type), key->nw_proto, key->nw_tos,
IP_ARGS(&key->nw_src), IP_ARGS(&key->nw_dst),
@@ -65,11 +69,9 @@ format_odp_action(struct ds *ds, const union odp_action *a)
case ODPAT_SET_TUNNEL:
ds_put_format(ds, "set_tunnel(0x%08"PRIx32")", ntohl(a->tunnel.tun_id));
break;
- case ODPAT_SET_VLAN_VID:
- ds_put_format(ds, "set_vlan(%"PRIu16")", ntohs(a->vlan_vid.vlan_vid));
- break;
- case ODPAT_SET_VLAN_PCP:
- ds_put_format(ds, "set_vlan_pcp(%"PRIu8")", a->vlan_pcp.vlan_pcp);
+ case ODPAT_SET_DL_TCI:
+ ds_put_format(ds, "set_tci(%04"PRIx16",mask=%04"PRIx16")",
+ ntohs(a->dl_tci.tci), ntohs(a->dl_tci.mask));
break;
case ODPAT_STRIP_VLAN:
ds_put_format(ds, "strip_vlan");
@@ -157,14 +159,20 @@ odp_flow_key_from_flow(struct odp_flow_key *key, const struct flow *flow)
key->nw_src = flow->nw_src;
key->nw_dst = flow->nw_dst;
key->in_port = flow->in_port;
- key->dl_vlan = flow->dl_vlan;
+ if (flow->dl_vlan == htons(OFP_VLAN_NONE)) {
+ key->dl_tci = htons(0);
+ } else {
+ uint16_t vid = flow->dl_vlan & htons(VLAN_VID_MASK);
+ uint16_t pcp = htons((flow->dl_vlan_pcp << VLAN_PCP_SHIFT)
+ & VLAN_PCP_MASK);
+ key->dl_tci = vid | pcp | htons(ODP_TCI_PRESENT);
+ }
key->dl_type = flow->dl_type;
key->tp_src = flow->tp_src;
key->tp_dst = flow->tp_dst;
memcpy(key->dl_src, flow->dl_src, ETH_ADDR_LEN);
memcpy(key->dl_dst, flow->dl_dst, ETH_ADDR_LEN);
key->nw_proto = flow->nw_proto;
- key->dl_vlan_pcp = flow->dl_vlan_pcp;
key->nw_tos = flow->nw_tos;
memset(key->reserved, 0, sizeof key->reserved);
}
@@ -175,13 +183,18 @@ odp_flow_key_to_flow(const struct odp_flow_key *key, struct flow *flow)
flow->nw_src = key->nw_src;
flow->nw_dst = key->nw_dst;
flow->in_port = key->in_port;
- flow->dl_vlan = key->dl_vlan;
+ if (key->dl_tci) {
+ flow->dl_vlan = htons(vlan_tci_to_vid(key->dl_tci));
+ flow->dl_vlan_pcp = vlan_tci_to_pcp(key->dl_tci);
+ } else {
+ flow->dl_vlan = htons(OFP_VLAN_NONE);
+ flow->dl_vlan_pcp = 0;
+ }
flow->dl_type = key->dl_type;
flow->tp_src = key->tp_src;
flow->tp_dst = key->tp_dst;
memcpy(flow->dl_src, key->dl_src, ETH_ADDR_LEN);
memcpy(flow->dl_dst, key->dl_dst, ETH_ADDR_LEN);
flow->nw_proto = key->nw_proto;
- flow->dl_vlan_pcp = key->dl_vlan_pcp;
flow->nw_tos = key->nw_tos;
}
diff --git a/lib/packets.h b/lib/packets.h
index fb04407..af028eb 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -18,6 +18,8 @@
#define PACKETS_H 1
#include <inttypes.h>
+#include <sys/types.h>
+#include <netinet/in.h>
#include <stdint.h>
#include <string.h>
#include "compiler.h"
@@ -198,6 +200,24 @@ BUILD_ASSERT_DECL(LLC_SNAP_HEADER_LEN == sizeof(struct llc_snap_header));
#define VLAN_PCP_MASK 0xe000
#define VLAN_PCP_SHIFT 13
+#define VLAN_CFI 0x1000
+
+/* Given the vlan_tci field from an 802.1Q header, in network byte order,
+ * returns the VLAN ID in host byte order. */
+static inline uint16_t
+vlan_tci_to_vid(uint16_t vlan_tci)
+{
+ return (ntohs(vlan_tci) & VLAN_VID_MASK) >> VLAN_VID_SHIFT;
+}
+
+/* Given the vlan_tci field from an 802.1Q header, in network byte order,
+ * returns the priority code point (PCP) in host byte order. */
+static inline int
+vlan_tci_to_pcp(uint16_t vlan_tci)
+{
+ return (ntohs(vlan_tci) & VLAN_PCP_MASK) >> VLAN_PCP_SHIFT;
+}
+
#define VLAN_HEADER_LEN 4
struct vlan_header {
uint16_t vlan_tci; /* Lowest 12 bits are VLAN ID. */
diff --git a/ofproto/ofproto-sflow.c b/ofproto/ofproto-sflow.c
index f8ff496..0fb26a6 100644
--- a/ofproto/ofproto-sflow.c
+++ b/ofproto/ofproto-sflow.c
@@ -25,6 +25,7 @@
#include "netdev.h"
#include "ofpbuf.h"
#include "ofproto.h"
+#include "packets.h"
#include "poll-loop.h"
#include "port-array.h"
#include "sflow_api.h"
@@ -547,12 +548,13 @@ ofproto_sflow_received(struct ofproto_sflow *os, struct odp_msg *msg)
n_outputs++;
break;
- case ODPAT_SET_VLAN_VID:
- switchElem.flowType.sw.dst_vlan = ntohs(a->vlan_vid.vlan_vid);
- break;
-
- case ODPAT_SET_VLAN_PCP:
- switchElem.flowType.sw.dst_priority = a->vlan_pcp.vlan_pcp;
+ case ODPAT_SET_DL_TCI:
+ if (a->dl_tci.mask & htons(VLAN_VID_MASK)) {
+ switchElem.flowType.sw.dst_vlan = vlan_tci_to_vid(a->dl_tci.tci);
+ }
+ if (a->dl_tci.mask & htons(VLAN_PCP_MASK)) {
+ switchElem.flowType.sw.dst_priority = vlan_tci_to_pcp(a->dl_tci.tci);
+ }
break;
default:
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 4e209f0..6b4f4a0 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -2681,13 +2681,16 @@ do_xlate_actions(const union ofp_action *in, size_t n_in,
break;
case OFPAT_SET_VLAN_VID:
- oa = odp_actions_add(ctx->out, ODPAT_SET_VLAN_VID);
- ctx->flow.dl_vlan = oa->vlan_vid.vlan_vid = ia->vlan_vid.vlan_vid;
+ oa = odp_actions_add(ctx->out, ODPAT_SET_DL_TCI);
+ oa->dl_tci.tci = ia->vlan_vid.vlan_vid & htons(VLAN_VID_MASK);
+ oa->dl_tci.mask = htons(VLAN_VID_MASK);
break;
case OFPAT_SET_VLAN_PCP:
- oa = odp_actions_add(ctx->out, ODPAT_SET_VLAN_PCP);
- ctx->flow.dl_vlan_pcp = oa->vlan_pcp.vlan_pcp = ia->vlan_pcp.vlan_pcp;
+ oa = odp_actions_add(ctx->out, ODPAT_SET_DL_TCI);
+ oa->dl_tci.tci = htons((ia->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT)
+ & VLAN_PCP_MASK);
+ oa->dl_tci.mask = htons(VLAN_PCP_MASK);
break;
case OFPAT_STRIP_VLAN:
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index 9a3be00..f1721e5 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -2226,8 +2226,9 @@ compose_actions(struct bridge *br, const struct flow *flow, uint16_t vlan,
if (p->vlan == OFP_VLAN_NONE) {
odp_actions_add(actions, ODPAT_STRIP_VLAN);
} else {
- a = odp_actions_add(actions, ODPAT_SET_VLAN_VID);
- a->vlan_vid.vlan_vid = htons(p->vlan);
+ a = odp_actions_add(actions, ODPAT_SET_DL_TCI);
+ a->dl_tci.tci = htons(p->vlan & VLAN_VID_MASK);
+ a->dl_tci.mask = htons(VLAN_VID_MASK);
}
cur_vlan = p->vlan;
}
--
1.7.1
More information about the dev
mailing list