Skip to content

Commit

Permalink
Merge branch 'vlan_action'
Browse files Browse the repository at this point in the history
Jiri Pirko says:

====================
sched: introduce vlan action

Please see the individual patches for info
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Nov 21, 2014
2 parents fe15912 + c7e2b96 commit df6ce47
Show file tree
Hide file tree
Showing 22 changed files with 522 additions and 214 deletions.
17 changes: 4 additions & 13 deletions drivers/net/bonding/bond_alb.c
Original file line number Diff line number Diff line change
Expand Up @@ -475,12 +475,8 @@ static void rlb_update_client(struct rlb_client_info *client_info)
skb->dev = client_info->slave->dev;

if (client_info->vlan_id) {
skb = vlan_put_tag(skb, htons(ETH_P_8021Q), client_info->vlan_id);
if (!skb) {
netdev_err(client_info->slave->bond->dev,
"failed to insert VLAN tag\n");
continue;
}
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
client_info->vlan_id);
}

arp_xmit(skb);
Expand Down Expand Up @@ -951,13 +947,8 @@ static void alb_send_lp_vid(struct slave *slave, u8 mac_addr[],
skb->priority = TC_PRIO_CONTROL;
skb->dev = slave->dev;

if (vid) {
skb = vlan_put_tag(skb, vlan_proto, vid);
if (!skb) {
netdev_err(slave->bond->dev, "failed to insert VLAN tag\n");
return;
}
}
if (vid)
__vlan_hwaccel_put_tag(skb, vlan_proto, vid);

dev_queue_xmit(skb);
}
Expand Down
12 changes: 4 additions & 8 deletions drivers/net/bonding/bond_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2146,8 +2146,8 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op,

netdev_dbg(slave_dev, "inner tag: proto %X vid %X\n",
ntohs(outer_tag->vlan_proto), tags->vlan_id);
skb = __vlan_put_tag(skb, tags->vlan_proto,
tags->vlan_id);
skb = vlan_insert_tag_set_proto(skb, tags->vlan_proto,
tags->vlan_id);
if (!skb) {
net_err_ratelimited("failed to insert inner VLAN tag\n");
return;
Expand All @@ -2159,12 +2159,8 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op,
if (outer_tag->vlan_id) {
netdev_dbg(slave_dev, "outer tag: proto %X vid %X\n",
ntohs(outer_tag->vlan_proto), outer_tag->vlan_id);
skb = vlan_put_tag(skb, outer_tag->vlan_proto,
outer_tag->vlan_id);
if (!skb) {
net_err_ratelimited("failed to insert outer VLAN tag\n");
return;
}
__vlan_hwaccel_put_tag(skb, outer_tag->vlan_proto,
outer_tag->vlan_id);
}

xmit:
Expand Down
6 changes: 4 additions & 2 deletions drivers/net/ethernet/emulex/benet/be_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -887,7 +887,8 @@ static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter,
}

if (vlan_tag) {
skb = __vlan_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
skb = vlan_insert_tag_set_proto(skb, htons(ETH_P_8021Q),
vlan_tag);
if (unlikely(!skb))
return skb;
skb->vlan_tci = 0;
Expand All @@ -896,7 +897,8 @@ static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter,
/* Insert the outer VLAN, if any */
if (adapter->qnq_vid) {
vlan_tag = adapter->qnq_vid;
skb = __vlan_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
skb = vlan_insert_tag_set_proto(skb, htons(ETH_P_8021Q),
vlan_tag);
if (unlikely(!skb))
return skb;
if (skip_hw_vlan)
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/usb/cdc_mbim.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_

/* map MBIM session to VLAN */
if (tci)
vlan_put_tag(skb, htons(ETH_P_8021Q), tci);
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), tci);
err:
return skb;
}
Expand Down
22 changes: 6 additions & 16 deletions drivers/net/vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -1599,14 +1599,9 @@ static int vxlan6_xmit_skb(struct vxlan_sock *vs,
if (unlikely(err))
return err;

if (vlan_tx_tag_present(skb)) {
if (WARN_ON(!__vlan_put_tag(skb,
skb->vlan_proto,
vlan_tx_tag_get(skb))))
return -ENOMEM;

skb->vlan_tci = 0;
}
skb = vlan_hwaccel_push_inside(skb);
if (WARN_ON(!skb))
return -ENOMEM;

vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh));
vxh->vx_flags = htonl(VXLAN_FLAGS);
Expand Down Expand Up @@ -1643,14 +1638,9 @@ int vxlan_xmit_skb(struct vxlan_sock *vs,
if (unlikely(err))
return err;

if (vlan_tx_tag_present(skb)) {
if (WARN_ON(!__vlan_put_tag(skb,
skb->vlan_proto,
vlan_tx_tag_get(skb))))
return -ENOMEM;

skb->vlan_tci = 0;
}
skb = vlan_hwaccel_push_inside(skb);
if (WARN_ON(!skb))
return -ENOMEM;

vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh));
vxh->vx_flags = htonl(VXLAN_FLAGS);
Expand Down
6 changes: 2 additions & 4 deletions drivers/scsi/fcoe/fcoe.c
Original file line number Diff line number Diff line change
Expand Up @@ -1669,10 +1669,8 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
fcoe->realdev->features & NETIF_F_HW_VLAN_CTAG_TX) {
/* must set skb->dev before calling vlan_put_tag */
skb->dev = fcoe->realdev;
skb = __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
vlan_dev_vlan_id(fcoe->netdev));
if (!skb)
return -ENOMEM;
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
vlan_dev_vlan_id(fcoe->netdev));
} else
skb->dev = fcoe->netdev;

Expand Down
107 changes: 73 additions & 34 deletions include/linux/if_vlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,28 +282,24 @@ static inline bool vlan_hw_offload_capable(netdev_features_t features,
}

/**
* vlan_insert_tag - regular VLAN tag inserting
* __vlan_insert_tag - regular VLAN tag inserting
* @skb: skbuff to tag
* @vlan_proto: VLAN encapsulation protocol
* @vlan_tci: VLAN TCI to insert
*
* Inserts the VLAN tag into @skb as part of the payload
* Returns a VLAN tagged skb. If a new skb is created, @skb is freed.
*
* Following the skb_unshare() example, in case of error, the calling function
* doesn't have to worry about freeing the original skb.
* Returns error if skb_cow_head failes.
*
* Does not change skb->protocol so this function can be used during receive.
*/
static inline struct sk_buff *vlan_insert_tag(struct sk_buff *skb,
__be16 vlan_proto, u16 vlan_tci)
static inline int __vlan_insert_tag(struct sk_buff *skb,
__be16 vlan_proto, u16 vlan_tci)
{
struct vlan_ethhdr *veth;

if (skb_cow_head(skb, VLAN_HLEN) < 0) {
dev_kfree_skb_any(skb);
return NULL;
}
if (skb_cow_head(skb, VLAN_HLEN) < 0)
return -ENOMEM;

veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN);

/* Move the mac addresses to the beginning of the new header. */
Expand All @@ -316,12 +312,40 @@ static inline struct sk_buff *vlan_insert_tag(struct sk_buff *skb,
/* now, the TCI */
veth->h_vlan_TCI = htons(vlan_tci);

return 0;
}

/**
* vlan_insert_tag - regular VLAN tag inserting
* @skb: skbuff to tag
* @vlan_proto: VLAN encapsulation protocol
* @vlan_tci: VLAN TCI to insert
*
* Inserts the VLAN tag into @skb as part of the payload
* Returns a VLAN tagged skb. If a new skb is created, @skb is freed.
*
* Following the skb_unshare() example, in case of error, the calling function
* doesn't have to worry about freeing the original skb.
*
* Does not change skb->protocol so this function can be used during receive.
*/
static inline struct sk_buff *vlan_insert_tag(struct sk_buff *skb,
__be16 vlan_proto, u16 vlan_tci)
{
int err;

err = __vlan_insert_tag(skb, vlan_proto, vlan_tci);
if (err) {
dev_kfree_skb_any(skb);
return NULL;
}
return skb;
}

/**
* __vlan_put_tag - regular VLAN tag inserting
* vlan_insert_tag_set_proto - regular VLAN tag inserting
* @skb: skbuff to tag
* @vlan_proto: VLAN encapsulation protocol
* @vlan_tci: VLAN TCI to insert
*
* Inserts the VLAN tag into @skb as part of the payload
Expand All @@ -330,48 +354,63 @@ static inline struct sk_buff *vlan_insert_tag(struct sk_buff *skb,
* Following the skb_unshare() example, in case of error, the calling function
* doesn't have to worry about freeing the original skb.
*/
static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb,
__be16 vlan_proto, u16 vlan_tci)
static inline struct sk_buff *vlan_insert_tag_set_proto(struct sk_buff *skb,
__be16 vlan_proto,
u16 vlan_tci)
{
skb = vlan_insert_tag(skb, vlan_proto, vlan_tci);
if (skb)
skb->protocol = vlan_proto;
return skb;
}

/**
* __vlan_hwaccel_put_tag - hardware accelerated VLAN inserting
/*
* __vlan_hwaccel_push_inside - pushes vlan tag to the payload
* @skb: skbuff to tag
* @vlan_proto: VLAN encapsulation protocol
* @vlan_tci: VLAN TCI to insert
*
* Puts the VLAN TCI in @skb->vlan_tci and lets the device do the rest
* Pushes the VLAN tag from @skb->vlan_tci inside to the payload.
*
* Following the skb_unshare() example, in case of error, the calling function
* doesn't have to worry about freeing the original skb.
*/
static inline struct sk_buff *__vlan_hwaccel_put_tag(struct sk_buff *skb,
__be16 vlan_proto,
u16 vlan_tci)
static inline struct sk_buff *__vlan_hwaccel_push_inside(struct sk_buff *skb)
{
skb->vlan_proto = vlan_proto;
skb->vlan_tci = VLAN_TAG_PRESENT | vlan_tci;
skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto,
vlan_tx_tag_get(skb));
if (likely(skb))
skb->vlan_tci = 0;
return skb;
}
/*
* vlan_hwaccel_push_inside - pushes vlan tag to the payload
* @skb: skbuff to tag
*
* Checks is tag is present in @skb->vlan_tci and if it is, it pushes the
* VLAN tag from @skb->vlan_tci inside to the payload.
*
* Following the skb_unshare() example, in case of error, the calling function
* doesn't have to worry about freeing the original skb.
*/
static inline struct sk_buff *vlan_hwaccel_push_inside(struct sk_buff *skb)
{
if (vlan_tx_tag_present(skb))
skb = __vlan_hwaccel_push_inside(skb);
return skb;
}

/**
* vlan_put_tag - inserts VLAN tag according to device features
* __vlan_hwaccel_put_tag - hardware accelerated VLAN inserting
* @skb: skbuff to tag
* @vlan_proto: VLAN encapsulation protocol
* @vlan_tci: VLAN TCI to insert
*
* Assumes skb->dev is the target that will xmit this frame.
* Returns a VLAN tagged skb.
* Puts the VLAN TCI in @skb->vlan_tci and lets the device do the rest
*/
static inline struct sk_buff *vlan_put_tag(struct sk_buff *skb,
__be16 vlan_proto, u16 vlan_tci)
static inline void __vlan_hwaccel_put_tag(struct sk_buff *skb,
__be16 vlan_proto, u16 vlan_tci)
{
if (vlan_hw_offload_capable(skb->dev->features, vlan_proto)) {
return __vlan_hwaccel_put_tag(skb, vlan_proto, vlan_tci);
} else {
return __vlan_put_tag(skb, vlan_proto, vlan_tci);
}
skb->vlan_proto = vlan_proto;
skb->vlan_tci = VLAN_TAG_PRESENT | vlan_tci;
}

/**
Expand Down
3 changes: 3 additions & 0 deletions include/linux/skbuff.h
Original file line number Diff line number Diff line change
Expand Up @@ -2678,6 +2678,9 @@ void skb_scrub_packet(struct sk_buff *skb, bool xnet);
unsigned int skb_gso_transport_seglen(const struct sk_buff *skb);
struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features);
struct sk_buff *skb_vlan_untag(struct sk_buff *skb);
int skb_ensure_writable(struct sk_buff *skb, int write_len);
int skb_vlan_pop(struct sk_buff *skb);
int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci);

struct skb_checksum_ops {
__wsum (*update)(const void *mem, int len, __wsum wsum);
Expand Down
27 changes: 27 additions & 0 deletions include/net/tc_act/tc_vlan.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2014 Jiri Pirko <jiri@resnulli.us>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/

#ifndef __NET_TC_VLAN_H
#define __NET_TC_VLAN_H

#include <net/act_api.h>

#define VLAN_F_POP 0x1
#define VLAN_F_PUSH 0x2

struct tcf_vlan {
struct tcf_common common;
int tcfv_action;
__be16 tcfv_push_vid;
__be16 tcfv_push_proto;
};
#define to_vlan(a) \
container_of(a->priv, struct tcf_vlan, common)

#endif /* __NET_TC_VLAN_H */
35 changes: 35 additions & 0 deletions include/uapi/linux/tc_act/tc_vlan.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2014 Jiri Pirko <jiri@resnulli.us>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/

#ifndef __LINUX_TC_VLAN_H
#define __LINUX_TC_VLAN_H

#include <linux/pkt_cls.h>

#define TCA_ACT_VLAN 12

#define TCA_VLAN_ACT_POP 1
#define TCA_VLAN_ACT_PUSH 2

struct tc_vlan {
tc_gen;
int v_action;
};

enum {
TCA_VLAN_UNSPEC,
TCA_VLAN_TM,
TCA_VLAN_PARMS,
TCA_VLAN_PUSH_VLAN_ID,
TCA_VLAN_PUSH_VLAN_PROTOCOL,
__TCA_VLAN_MAX,
};
#define TCA_VLAN_MAX (__TCA_VLAN_MAX - 1)

#endif
2 changes: 1 addition & 1 deletion net/8021q/vlan_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb,
u16 vlan_tci;
vlan_tci = vlan->vlan_id;
vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb->priority);
skb = __vlan_hwaccel_put_tag(skb, vlan->vlan_proto, vlan_tci);
__vlan_hwaccel_put_tag(skb, vlan->vlan_proto, vlan_tci);
}

skb->dev = vlan->real_dev;
Expand Down
4 changes: 2 additions & 2 deletions net/bridge/br_vlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,8 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
if (skb->vlan_proto != proto) {
/* Protocol-mismatch, empty out vlan_tci for new tag */
skb_push(skb, ETH_HLEN);
skb = __vlan_put_tag(skb, skb->vlan_proto,
vlan_tx_tag_get(skb));
skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto,
vlan_tx_tag_get(skb));
if (unlikely(!skb))
return false;

Expand Down
Loading

0 comments on commit df6ce47

Please sign in to comment.