diff options
author | Patrick McHardy <kaber@trash.net> | 2008-07-18 21:05:19 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-07-18 21:05:19 -0400 |
commit | 8913336a7e8d56e984109a3137d6c0e3362596a4 (patch) | |
tree | 16e2ad819112b59a759daff79651955e9bfab1dd /net/packet/af_packet.c | |
parent | 3ca4095f246c21c285d9e4be2ea4d3ee7fbacebd (diff) |
packet: add PACKET_RESERVE sockopt
Add new sockopt to reserve some headroom in the mmaped ring frames in
front of the packet payload. This can be used f.i. when the VLAN header
needs to be (re)constructed to avoid moving the entire payload.
Signed-off-by: Patrick McHardy <kaber@trash.net>
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 | 29 |
1 files changed, 26 insertions, 3 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index db792e02a37f..de73bcb5235a 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -188,6 +188,7 @@ struct packet_sock { | |||
188 | unsigned int pg_vec_len; | 188 | unsigned int pg_vec_len; |
189 | enum tpacket_versions tp_version; | 189 | enum tpacket_versions tp_version; |
190 | unsigned int tp_hdrlen; | 190 | unsigned int tp_hdrlen; |
191 | unsigned int tp_reserve; | ||
191 | #endif | 192 | #endif |
192 | }; | 193 | }; |
193 | 194 | ||
@@ -635,11 +636,13 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe | |||
635 | snaplen = res; | 636 | snaplen = res; |
636 | 637 | ||
637 | if (sk->sk_type == SOCK_DGRAM) { | 638 | if (sk->sk_type == SOCK_DGRAM) { |
638 | macoff = netoff = TPACKET_ALIGN(po->tp_hdrlen) + 16; | 639 | macoff = netoff = TPACKET_ALIGN(po->tp_hdrlen) + 16 + |
640 | po->tp_reserve; | ||
639 | } else { | 641 | } else { |
640 | unsigned maclen = skb_network_offset(skb); | 642 | unsigned maclen = skb_network_offset(skb); |
641 | netoff = TPACKET_ALIGN(po->tp_hdrlen + | 643 | netoff = TPACKET_ALIGN(po->tp_hdrlen + |
642 | (maclen < 16 ? 16 : maclen)); | 644 | (maclen < 16 ? 16 : maclen)) + |
645 | po->tp_reserve; | ||
643 | macoff = netoff - maclen; | 646 | macoff = netoff - maclen; |
644 | } | 647 | } |
645 | 648 | ||
@@ -1448,6 +1451,19 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv | |||
1448 | return -EINVAL; | 1451 | return -EINVAL; |
1449 | } | 1452 | } |
1450 | } | 1453 | } |
1454 | case PACKET_RESERVE: | ||
1455 | { | ||
1456 | unsigned int val; | ||
1457 | |||
1458 | if (optlen != sizeof(val)) | ||
1459 | return -EINVAL; | ||
1460 | if (po->pg_vec) | ||
1461 | return -EBUSY; | ||
1462 | if (copy_from_user(&val, optval, sizeof(val))) | ||
1463 | return -EFAULT; | ||
1464 | po->tp_reserve = val; | ||
1465 | return 0; | ||
1466 | } | ||
1451 | #endif | 1467 | #endif |
1452 | case PACKET_AUXDATA: | 1468 | case PACKET_AUXDATA: |
1453 | { | 1469 | { |
@@ -1547,6 +1563,12 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, | |||
1547 | } | 1563 | } |
1548 | data = &val; | 1564 | data = &val; |
1549 | break; | 1565 | break; |
1566 | case PACKET_RESERVE: | ||
1567 | if (len > sizeof(unsigned int)) | ||
1568 | len = sizeof(unsigned int); | ||
1569 | val = po->tp_reserve; | ||
1570 | data = &val; | ||
1571 | break; | ||
1550 | #endif | 1572 | #endif |
1551 | default: | 1573 | default: |
1552 | return -ENOPROTOOPT; | 1574 | return -ENOPROTOOPT; |
@@ -1790,7 +1812,8 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing | |||
1790 | return -EINVAL; | 1812 | return -EINVAL; |
1791 | if (unlikely(req->tp_block_size & (PAGE_SIZE - 1))) | 1813 | if (unlikely(req->tp_block_size & (PAGE_SIZE - 1))) |
1792 | return -EINVAL; | 1814 | return -EINVAL; |
1793 | if (unlikely(req->tp_frame_size < po->tp_hdrlen)) | 1815 | if (unlikely(req->tp_frame_size < po->tp_hdrlen + |
1816 | po->tp_reserve)) | ||
1794 | return -EINVAL; | 1817 | return -EINVAL; |
1795 | if (unlikely(req->tp_frame_size & (TPACKET_ALIGNMENT - 1))) | 1818 | if (unlikely(req->tp_frame_size & (TPACKET_ALIGNMENT - 1))) |
1796 | return -EINVAL; | 1819 | return -EINVAL; |