@@ -2994,6 +2994,7 @@ int skb_vlan_pop(struct sk_buff *skb);
int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci);
struct sk_buff *pskb_extract(struct sk_buff *skb, int off, int to_copy,
gfp_t gfp);
+int skb_vlan_deaccel(struct sk_buff *skb);
static inline int memcpy_from_msg(void *data, struct msghdr *msg, int len)
{
@@ -4516,30 +4516,44 @@ int skb_vlan_pop(struct sk_buff *skb)
}
EXPORT_SYMBOL(skb_vlan_pop);
-int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci)
+int skb_vlan_deaccel(struct sk_buff *skb)
{
- if (skb_vlan_tag_present(skb)) {
- unsigned int offset = skb->data - skb_mac_header(skb);
- int err;
+ unsigned int offset;
+ int err;
- /* __vlan_insert_tag expect skb->data pointing to mac header.
- * So change skb->data before calling it and change back to
- * original position later
- */
- __skb_push(skb, offset);
- err = __vlan_insert_tag(skb, skb->vlan_proto,
- skb_vlan_tag_get(skb));
- if (err) {
- __skb_pull(skb, offset);
- return err;
- }
+ if (!skb_vlan_tag_present(skb))
+ return 0;
- skb->protocol = skb->vlan_proto;
- skb->mac_len += VLAN_HLEN;
+ offset = skb->data - skb_mac_header(skb);
- skb_postpush_rcsum(skb, skb->data + (2 * ETH_ALEN), VLAN_HLEN);
+ /* __vlan_insert_tag expect skb->data pointing to mac header.
+ * So change skb->data before calling it and change back to
+ * original position later
+ */
+ __skb_push(skb, offset);
+ err = __vlan_insert_tag(skb, skb->vlan_proto, skb_vlan_tag_get(skb));
+ if (err) {
__skb_pull(skb, offset);
+ return err;
}
+
+ skb->protocol = skb->vlan_proto;
+ skb->mac_len += VLAN_HLEN;
+
+ skb_postpush_rcsum(skb, skb->data + (2 * ETH_ALEN), VLAN_HLEN);
+ __skb_pull(skb, offset);
+
+ return 0;
+}
+EXPORT_SYMBOL(skb_vlan_deaccel);
+
+int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci)
+{
+ int err;
+
+ err = skb_vlan_deaccel(skb);
+ if (err)
+ return err;
__vlan_hwaccel_put_tag(skb, vlan_proto, vlan_tci);
return 0;
}
This breaks out the bulk of skb_vlan_push into a separate helper. This new helper moves any vlan tag present in metadata into packet data. The existing skb_vlan_push uses this new helper and then pushes a new vlan tag (into metadata). The motivation is to allow deaccelerating VLAN tags without adding a new one. This is in preparation for a push ethernet header support in Open vSwitch. Signed-off-by: Simon Horman <simon.horman@netronome.com> --- v9 [Simon Horman] * New patch --- include/linux/skbuff.h | 1 + net/core/skbuff.c | 50 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 33 insertions(+), 18 deletions(-)