diff options
author | Ben Greear <greearb@candelatech.com> | 2011-02-11 04:35:18 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-02-12 00:26:32 -0500 |
commit | 57f89bfa21403d902ee176ef988136b75d9ab30b (patch) | |
tree | 3ebee83312498997fdd4630acfe0cfccec84835c /net/packet/af_packet.c | |
parent | ab889e6607f6e3d52a76c5a43c8c4ad1d354da36 (diff) |
network: Allow af_packet to transmit +4 bytes for VLAN packets.
This allows user-space to send a '1500' MTU VLAN packet on a
1500 MTU ethernet frame. The extra 4 bytes of a VLAN header is
not usually charged against the MTU when other parts of the
network stack is transmitting vlans...
Signed-off-by: Ben Greear <greearb@candelatech.com>
Reviewed-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/packet/af_packet.c')
-rw-r--r-- | net/packet/af_packet.c | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index c60649ec1193..5efef5b5879e 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -465,7 +465,7 @@ retry: | |||
465 | */ | 465 | */ |
466 | 466 | ||
467 | err = -EMSGSIZE; | 467 | err = -EMSGSIZE; |
468 | if (len > dev->mtu + dev->hard_header_len) | 468 | if (len > dev->mtu + dev->hard_header_len + VLAN_HLEN) |
469 | goto out_unlock; | 469 | goto out_unlock; |
470 | 470 | ||
471 | if (!skb) { | 471 | if (!skb) { |
@@ -496,6 +496,19 @@ retry: | |||
496 | goto retry; | 496 | goto retry; |
497 | } | 497 | } |
498 | 498 | ||
499 | if (len > (dev->mtu + dev->hard_header_len)) { | ||
500 | /* Earlier code assumed this would be a VLAN pkt, | ||
501 | * double-check this now that we have the actual | ||
502 | * packet in hand. | ||
503 | */ | ||
504 | struct ethhdr *ehdr; | ||
505 | skb_reset_mac_header(skb); | ||
506 | ehdr = eth_hdr(skb); | ||
507 | if (ehdr->h_proto != htons(ETH_P_8021Q)) { | ||
508 | err = -EMSGSIZE; | ||
509 | goto out_unlock; | ||
510 | } | ||
511 | } | ||
499 | 512 | ||
500 | skb->protocol = proto; | 513 | skb->protocol = proto; |
501 | skb->dev = dev; | 514 | skb->dev = dev; |
@@ -1199,7 +1212,7 @@ static int packet_snd(struct socket *sock, | |||
1199 | } | 1212 | } |
1200 | 1213 | ||
1201 | err = -EMSGSIZE; | 1214 | err = -EMSGSIZE; |
1202 | if (!gso_type && (len > dev->mtu+reserve)) | 1215 | if (!gso_type && (len > dev->mtu + reserve + VLAN_HLEN)) |
1203 | goto out_unlock; | 1216 | goto out_unlock; |
1204 | 1217 | ||
1205 | err = -ENOBUFS; | 1218 | err = -ENOBUFS; |
@@ -1224,6 +1237,20 @@ static int packet_snd(struct socket *sock, | |||
1224 | if (err < 0) | 1237 | if (err < 0) |
1225 | goto out_free; | 1238 | goto out_free; |
1226 | 1239 | ||
1240 | if (!gso_type && (len > dev->mtu + reserve)) { | ||
1241 | /* Earlier code assumed this would be a VLAN pkt, | ||
1242 | * double-check this now that we have the actual | ||
1243 | * packet in hand. | ||
1244 | */ | ||
1245 | struct ethhdr *ehdr; | ||
1246 | skb_reset_mac_header(skb); | ||
1247 | ehdr = eth_hdr(skb); | ||
1248 | if (ehdr->h_proto != htons(ETH_P_8021Q)) { | ||
1249 | err = -EMSGSIZE; | ||
1250 | goto out_free; | ||
1251 | } | ||
1252 | } | ||
1253 | |||
1227 | skb->protocol = proto; | 1254 | skb->protocol = proto; |
1228 | skb->dev = dev; | 1255 | skb->dev = dev; |
1229 | skb->priority = sk->sk_priority; | 1256 | skb->priority = sk->sk_priority; |