diff options
author | Ben Greear <greearb@candelatech.com> | 2011-02-11 09:35:18 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-02-11 21:26:32 -0800 |
commit | 57f89bfa21403d902ee176ef988136b75d9ab30b (patch) | |
tree | 3ebee83312498997fdd4630acfe0cfccec84835c /net/packet | |
parent | ab889e6607f6e3d52a76c5a43c8c4ad1d354da36 (diff) | |
download | lwn-57f89bfa21403d902ee176ef988136b75d9ab30b.tar.gz lwn-57f89bfa21403d902ee176ef988136b75d9ab30b.zip |
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')
-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: */ err = -EMSGSIZE; - if (len > dev->mtu + dev->hard_header_len) + if (len > dev->mtu + dev->hard_header_len + VLAN_HLEN) goto out_unlock; if (!skb) { @@ -496,6 +496,19 @@ retry: goto retry; } + if (len > (dev->mtu + dev->hard_header_len)) { + /* Earlier code assumed this would be a VLAN pkt, + * double-check this now that we have the actual + * packet in hand. + */ + struct ethhdr *ehdr; + skb_reset_mac_header(skb); + ehdr = eth_hdr(skb); + if (ehdr->h_proto != htons(ETH_P_8021Q)) { + err = -EMSGSIZE; + goto out_unlock; + } + } skb->protocol = proto; skb->dev = dev; @@ -1199,7 +1212,7 @@ static int packet_snd(struct socket *sock, } err = -EMSGSIZE; - if (!gso_type && (len > dev->mtu+reserve)) + if (!gso_type && (len > dev->mtu + reserve + VLAN_HLEN)) goto out_unlock; err = -ENOBUFS; @@ -1224,6 +1237,20 @@ static int packet_snd(struct socket *sock, if (err < 0) goto out_free; + if (!gso_type && (len > dev->mtu + reserve)) { + /* Earlier code assumed this would be a VLAN pkt, + * double-check this now that we have the actual + * packet in hand. + */ + struct ethhdr *ehdr; + skb_reset_mac_header(skb); + ehdr = eth_hdr(skb); + if (ehdr->h_proto != htons(ETH_P_8021Q)) { + err = -EMSGSIZE; + goto out_free; + } + } + skb->protocol = proto; skb->dev = dev; skb->priority = sk->sk_priority; |