From: pravin <pshe...@nicira.com> 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 dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev