From: pravin <[email protected]>
following patch changes OVS VLAN actions from MODIFY and STRIP to more
generic PUSH and POP.
As this patch replaces MODIFY with PUSH semantic , userapce is fixed
accordingly.
---
datapath/actions.c | 63 +++++++++++++++++++++---------
datapath/datapath.c | 8 ++--
include/openvswitch/datapath-protocol.h | 4 +-
lib/dpif-netdev.c | 8 ++--
lib/odp-util.c | 12 +++---
ofproto/ofproto-dpif-sflow.c | 2 +-
ofproto/ofproto-dpif.c | 17 +++++---
7 files changed, 72 insertions(+), 42 deletions(-)
diff --git a/datapath/actions.c b/datapath/actions.c
index ed61039..a91eca5 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -39,19 +39,12 @@ static int make_writable(struct sk_buff *skb, int write_len)
return pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
}
-static int strip_vlan(struct sk_buff *skb)
+static int __pop_vlan_tci(struct sk_buff *skb, __be16 *current_tci)
{
struct ethhdr *eh;
+ struct vlan_ethhdr *veth;
int err;
- if (vlan_tx_tag_present(skb)) {
- vlan_set_tci(skb, 0);
- return 0;
- }
-
- if (unlikely(skb->protocol != htons(ETH_P_8021Q) ||
- skb->len < VLAN_ETH_HLEN))
- return 0;
err = make_writable(skb, VLAN_ETH_HLEN);
if (unlikely(err))
@@ -61,6 +54,9 @@ static int strip_vlan(struct sk_buff *skb)
skb->csum = csum_sub(skb->csum, csum_partial(skb->data
+ ETH_HLEN, VLAN_HLEN, 0));
+ veth = (struct vlan_ethhdr *) skb->data;
+ *current_tci = veth->h_vlan_TCI;
+
memmove(skb->data + VLAN_HLEN, skb->data, 2 * ETH_ALEN);
eh = (struct ethhdr *)skb_pull(skb, VLAN_HLEN);
@@ -71,21 +67,48 @@ static int strip_vlan(struct sk_buff *skb)
return 0;
}
-static int modify_vlan_tci(struct sk_buff *skb, __be16 tci)
+static int pop_vlan_tci(struct sk_buff *skb)
{
- if (!vlan_tx_tag_present(skb) && skb->protocol == htons(ETH_P_8021Q)) {
- int err;
+ __be16 tci;
+ int err;
- if (unlikely(skb->len < VLAN_ETH_HLEN))
+ if (vlan_tx_tag_present(skb)) {
+ vlan_set_tci(skb, 0);
+ } else {
+ if (unlikely(skb->protocol != htons(ETH_P_8021Q) ||
+ skb->len < VLAN_ETH_HLEN))
return 0;
- err = strip_vlan(skb);
- if (unlikely(err))
+ err = __pop_vlan_tci(skb, &tci);
+ if (err)
return err;
}
+ /* move next vlan tag to hw accel tag*/
+
+ if (likely(skb->protocol != htons(ETH_P_8021Q) ||
+ skb->len < VLAN_ETH_HLEN))
+ return 0;
+
+ err = __pop_vlan_tci(skb, &tci);
+ if (err)
+ return err;
+
__vlan_hwaccel_put_tag(skb, ntohs(tci));
+ return 0;
+}
+
+static int push_vlan_tci(struct sk_buff *skb, __be16 new_tci)
+{
+ if (vlan_tx_tag_present(skb)) {
+ u16 current_tag;
+
+ current_tag = vlan_tx_tag_get(skb);
+ if (!__vlan_put_tag(skb, current_tag))
+ return -ENOMEM;
+ }
+ __vlan_hwaccel_put_tag(skb, ntohs(new_tci));
return 0;
}
@@ -270,12 +293,14 @@ static int do_execute_actions(struct datapath *dp, struct
sk_buff *skb,
OVS_CB(skb)->tun_id = nla_get_be64(a);
break;
- case ODP_ACTION_ATTR_SET_DL_TCI:
- err = modify_vlan_tci(skb, nla_get_be16(a));
+ case ODP_ACTION_ATTR_PUSH_VLAN_TCI:
+ err = push_vlan_tci(skb, nla_get_be16(a));
+ if (unlikely(err)) /* skb already freed */
+ return err;
break;
- case ODP_ACTION_ATTR_STRIP_VLAN:
- err = strip_vlan(skb);
+ case ODP_ACTION_ATTR_POP_VLAN_TCI:
+ err = pop_vlan_tci(skb);
break;
case ODP_ACTION_ATTR_SET_DL_SRC:
diff --git a/datapath/datapath.c b/datapath/datapath.c
index d149344..9c9b70d 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -553,8 +553,8 @@ static int validate_actions(const struct nlattr *attr)
static const u32 action_lens[ODP_ACTION_ATTR_MAX + 1] = {
[ODP_ACTION_ATTR_OUTPUT] = 4,
[ODP_ACTION_ATTR_CONTROLLER] = 8,
- [ODP_ACTION_ATTR_SET_DL_TCI] = 2,
- [ODP_ACTION_ATTR_STRIP_VLAN] = 0,
+ [ODP_ACTION_ATTR_PUSH_VLAN_TCI] = 2,
+ [ODP_ACTION_ATTR_POP_VLAN_TCI] = 0,
[ODP_ACTION_ATTR_SET_DL_SRC] = ETH_ALEN,
[ODP_ACTION_ATTR_SET_DL_DST] = ETH_ALEN,
[ODP_ACTION_ATTR_SET_NW_SRC] = 4,
@@ -576,7 +576,7 @@ static int validate_actions(const struct nlattr *attr)
return -EINVAL;
case ODP_ACTION_ATTR_CONTROLLER:
- case ODP_ACTION_ATTR_STRIP_VLAN:
+ case ODP_ACTION_ATTR_POP_VLAN_TCI:
case ODP_ACTION_ATTR_SET_DL_SRC:
case ODP_ACTION_ATTR_SET_DL_DST:
case ODP_ACTION_ATTR_SET_NW_SRC:
@@ -594,7 +594,7 @@ static int validate_actions(const struct nlattr *attr)
return -EINVAL;
break;
- case ODP_ACTION_ATTR_SET_DL_TCI:
+ case ODP_ACTION_ATTR_PUSH_VLAN_TCI:
if (nla_get_be16(a) & htons(VLAN_CFI_MASK))
return -EINVAL;
break;
diff --git a/include/openvswitch/datapath-protocol.h
b/include/openvswitch/datapath-protocol.h
index e7708ef..d972a25 100644
--- a/include/openvswitch/datapath-protocol.h
+++ b/include/openvswitch/datapath-protocol.h
@@ -410,8 +410,8 @@ enum odp_action_type {
ODP_ACTION_ATTR_UNSPEC,
ODP_ACTION_ATTR_OUTPUT, /* Output to switch port. */
ODP_ACTION_ATTR_CONTROLLER, /* Send copy to controller. */
- ODP_ACTION_ATTR_SET_DL_TCI, /* Set the 802.1q TCI value. */
- ODP_ACTION_ATTR_STRIP_VLAN, /* Strip the 802.1q header. */
+ ODP_ACTION_ATTR_PUSH_VLAN_TCI, /* push 802.1q header with new TCI
value. */
+ ODP_ACTION_ATTR_POP_VLAN_TCI, /* pop the 802.1q header. */
ODP_ACTION_ATTR_SET_DL_SRC, /* Ethernet source address. */
ODP_ACTION_ATTR_SET_DL_DST, /* Ethernet destination address. */
ODP_ACTION_ATTR_SET_NW_SRC, /* IPv4 source address. */
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 3b93a4c..5c52ea6 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -710,7 +710,7 @@ dpif_netdev_validate_actions(const struct nlattr *actions,
case ODP_ACTION_ATTR_CONTROLLER:
break;
- case ODP_ACTION_ATTR_SET_DL_TCI:
+ case ODP_ACTION_ATTR_PUSH_VLAN_TCI:
*mutates = true;
if (nl_attr_get_be16(a) & htons(VLAN_CFI)) {
return EINVAL;
@@ -724,7 +724,7 @@ dpif_netdev_validate_actions(const struct nlattr *actions,
}
break;
- case ODP_ACTION_ATTR_STRIP_VLAN:
+ case ODP_ACTION_ATTR_POP_VLAN_TCI:
case ODP_ACTION_ATTR_SET_DL_SRC:
case ODP_ACTION_ATTR_SET_DL_DST:
case ODP_ACTION_ATTR_SET_NW_SRC:
@@ -1304,11 +1304,11 @@ dp_netdev_execute_actions(struct dp_netdev *dp,
key, nl_attr_get_u64(a));
break;
- case ODP_ACTION_ATTR_SET_DL_TCI:
+ case ODP_ACTION_ATTR_PUSH_VLAN_TCI:
eth_set_vlan_tci(packet, nl_attr_get_be16(a));
break;
- case ODP_ACTION_ATTR_STRIP_VLAN:
+ case ODP_ACTION_ATTR_POP_VLAN_TCI:
dp_netdev_strip_vlan(packet);
break;
diff --git a/lib/odp-util.c b/lib/odp-util.c
index d7a3118..32fb722 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -42,8 +42,8 @@ odp_action_len(uint16_t type)
switch ((enum odp_action_type) type) {
case ODP_ACTION_ATTR_OUTPUT: return 4;
case ODP_ACTION_ATTR_CONTROLLER: return 8;
- case ODP_ACTION_ATTR_SET_DL_TCI: return 2;
- case ODP_ACTION_ATTR_STRIP_VLAN: return 0;
+ case ODP_ACTION_ATTR_PUSH_VLAN_TCI: return 2;
+ case ODP_ACTION_ATTR_POP_VLAN_TCI: return 0;
case ODP_ACTION_ATTR_SET_DL_SRC: return ETH_ADDR_LEN;
case ODP_ACTION_ATTR_SET_DL_DST: return ETH_ADDR_LEN;
case ODP_ACTION_ATTR_SET_NW_SRC: return 4;
@@ -106,13 +106,13 @@ format_odp_action(struct ds *ds, const struct nlattr *a)
ds_put_format(ds, "set_tunnel(%#"PRIx64")",
ntohll(nl_attr_get_be64(a)));
break;
- case ODP_ACTION_ATTR_SET_DL_TCI:
- ds_put_format(ds, "set_tci(vid=%"PRIu16",pcp=%d)",
+ case ODP_ACTION_ATTR_PUSH_VLAN_TCI:
+ ds_put_format(ds, "push_tci(vid=%"PRIu16",pcp=%d)",
vlan_tci_to_vid(nl_attr_get_be16(a)),
vlan_tci_to_pcp(nl_attr_get_be16(a)));
break;
- case ODP_ACTION_ATTR_STRIP_VLAN:
- ds_put_format(ds, "strip_vlan");
+ case ODP_ACTION_ATTR_POP_VLAN_TCI:
+ ds_put_format(ds, "pop_vlan");
break;
case ODP_ACTION_ATTR_SET_DL_SRC:
eth = nl_attr_get_unspec(a, ETH_ADDR_LEN);
diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c
index d2da42b..e9dc756 100644
--- a/ofproto/ofproto-dpif-sflow.c
+++ b/ofproto/ofproto-dpif-sflow.c
@@ -538,7 +538,7 @@ dpif_sflow_received(struct dpif_sflow *ds, const struct
dpif_upcall *upcall,
n_outputs++;
break;
- case ODP_ACTION_ATTR_SET_DL_TCI:
+ case ODP_ACTION_ATTR_PUSH_VLAN_TCI:
tci = nl_attr_get_be16(a);
switchElem.flowType.sw.dst_vlan = vlan_tci_to_vid(tci);
switchElem.flowType.sw.dst_priority = vlan_tci_to_pcp(tci);
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 7264355..1bcd81f 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -2241,11 +2241,11 @@ facet_account(struct ofproto_dpif *ofproto,
}
break;
- case ODP_ACTION_ATTR_STRIP_VLAN:
+ case ODP_ACTION_ATTR_POP_VLAN_TCI:
vlan_tci = htons(0);
break;
- case ODP_ACTION_ATTR_SET_DL_TCI:
+ case ODP_ACTION_ATTR_PUSH_VLAN_TCI:
vlan_tci = nl_attr_get_be16(a);
break;
}
@@ -2790,9 +2790,11 @@ commit_odp_actions(struct action_xlate_ctx *ctx)
if (base->vlan_tci != flow->vlan_tci) {
if (!(flow->vlan_tci & htons(VLAN_CFI))) {
- nl_msg_put_flag(odp_actions, ODP_ACTION_ATTR_STRIP_VLAN);
+ nl_msg_put_flag(odp_actions, ODP_ACTION_ATTR_POP_VLAN_TCI);
} else {
- nl_msg_put_be16(odp_actions, ODP_ACTION_ATTR_SET_DL_TCI,
+ if (base->vlan_tci & htons(VLAN_CFI))
+ nl_msg_put_flag(odp_actions, ODP_ACTION_ATTR_POP_VLAN_TCI);
+ nl_msg_put_be16(odp_actions, ODP_ACTION_ATTR_PUSH_VLAN_TCI,
flow->vlan_tci & ~htons(VLAN_CFI));
}
base->vlan_tci = flow->vlan_tci;
@@ -3461,13 +3463,16 @@ compose_actions(struct action_xlate_ctx *ctx, uint16_t
vlan,
}
if (dst->vlan != cur_vlan) {
if (dst->vlan == OFP_VLAN_NONE) {
- nl_msg_put_flag(ctx->odp_actions, ODP_ACTION_ATTR_STRIP_VLAN);
+ nl_msg_put_flag(ctx->odp_actions,
ODP_ACTION_ATTR_POP_VLAN_TCI);
} else {
ovs_be16 tci;
+
+ if (cur_vlan & htons(VLAN_CFI))
+ nl_msg_put_flag(ctx->odp_actions,
ODP_ACTION_ATTR_POP_VLAN_TCI);
tci = htons(dst->vlan & VLAN_VID_MASK);
tci |= ctx->flow.vlan_tci & htons(VLAN_PCP_MASK);
nl_msg_put_be16(ctx->odp_actions,
- ODP_ACTION_ATTR_SET_DL_TCI, tci);
+ ODP_ACTION_ATTR_PUSH_VLAN_TCI, tci);
}
cur_vlan = dst->vlan;
}
--
1.7.1
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev