Skip to content

Commit 53d6471

Browse files
Vlad Yasevichdavem330
authored andcommitted
net: Account for all vlan headers in skb_mac_gso_segment
skb_network_protocol() already accounts for multiple vlan headers that may be present in the skb. However, skb_mac_gso_segment() doesn't know anything about it and assumes that skb->mac_len is set correctly to skip all mac headers. That may not always be the case. If we are simply forwarding the packet (via bridge or macvtap), all vlan headers may not be accounted for. A simple solution is to allow skb_network_protocol to return the vlan depth it has calculated. This way skb_mac_gso_segment will correctly skip all mac headers. Signed-off-by: Vlad Yasevich <vyasevic@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 898602a commit 53d6471

File tree

3 files changed

+12
-6
lines changed

3 files changed

+12
-6
lines changed

include/linux/netdevice.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3014,7 +3014,7 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, netdev_features_t features)
30143014
{
30153015
return __skb_gso_segment(skb, features, true);
30163016
}
3017-
__be16 skb_network_protocol(struct sk_buff *skb);
3017+
__be16 skb_network_protocol(struct sk_buff *skb, int *depth);
30183018

30193019
static inline bool can_checksum_protocol(netdev_features_t features,
30203020
__be16 protocol)

net/core/dev.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2286,7 +2286,7 @@ int skb_checksum_help(struct sk_buff *skb)
22862286
}
22872287
EXPORT_SYMBOL(skb_checksum_help);
22882288

2289-
__be16 skb_network_protocol(struct sk_buff *skb)
2289+
__be16 skb_network_protocol(struct sk_buff *skb, int *depth)
22902290
{
22912291
__be16 type = skb->protocol;
22922292
int vlan_depth = ETH_HLEN;
@@ -2313,6 +2313,8 @@ __be16 skb_network_protocol(struct sk_buff *skb)
23132313
vlan_depth += VLAN_HLEN;
23142314
}
23152315

2316+
*depth = vlan_depth;
2317+
23162318
return type;
23172319
}
23182320

@@ -2326,12 +2328,13 @@ struct sk_buff *skb_mac_gso_segment(struct sk_buff *skb,
23262328
{
23272329
struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
23282330
struct packet_offload *ptype;
2329-
__be16 type = skb_network_protocol(skb);
2331+
int vlan_depth = skb->mac_len;
2332+
__be16 type = skb_network_protocol(skb, &vlan_depth);
23302333

23312334
if (unlikely(!type))
23322335
return ERR_PTR(-EINVAL);
23332336

2334-
__skb_pull(skb, skb->mac_len);
2337+
__skb_pull(skb, vlan_depth);
23352338

23362339
rcu_read_lock();
23372340
list_for_each_entry_rcu(ptype, &offload_base, list) {
@@ -2498,8 +2501,10 @@ static netdev_features_t harmonize_features(struct sk_buff *skb,
24982501
const struct net_device *dev,
24992502
netdev_features_t features)
25002503
{
2504+
int tmp;
2505+
25012506
if (skb->ip_summed != CHECKSUM_NONE &&
2502-
!can_checksum_protocol(features, skb_network_protocol(skb))) {
2507+
!can_checksum_protocol(features, skb_network_protocol(skb, &tmp))) {
25032508
features &= ~NETIF_F_ALL_CSUM;
25042509
} else if (illegal_highdma(dev, skb)) {
25052510
features &= ~NETIF_F_SG;

net/core/skbuff.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2879,8 +2879,9 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
28792879
int err = -ENOMEM;
28802880
int i = 0;
28812881
int pos;
2882+
int dummy;
28822883

2883-
proto = skb_network_protocol(head_skb);
2884+
proto = skb_network_protocol(head_skb, &dummy);
28842885
if (unlikely(!proto))
28852886
return ERR_PTR(-EINVAL);
28862887

0 commit comments

Comments
 (0)