Skip to content

Commit

Permalink
packet: add PACKET_RESERVE sockopt
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Patrick McHardy authored and David S. Miller committed Jul 19, 2008
1 parent 3ca4095 commit 8913336
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 3 deletions.
1 change: 1 addition & 0 deletions include/linux/if_packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ struct sockaddr_ll
#define PACKET_ORIGDEV 9
#define PACKET_VERSION 10
#define PACKET_HDRLEN 11
#define PACKET_RESERVE 12

struct tpacket_stats
{
Expand Down
29 changes: 26 additions & 3 deletions net/packet/af_packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ struct packet_sock {
unsigned int pg_vec_len;
enum tpacket_versions tp_version;
unsigned int tp_hdrlen;
unsigned int tp_reserve;
#endif
};

Expand Down Expand Up @@ -635,11 +636,13 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
snaplen = res;

if (sk->sk_type == SOCK_DGRAM) {
macoff = netoff = TPACKET_ALIGN(po->tp_hdrlen) + 16;
macoff = netoff = TPACKET_ALIGN(po->tp_hdrlen) + 16 +
po->tp_reserve;
} else {
unsigned maclen = skb_network_offset(skb);
netoff = TPACKET_ALIGN(po->tp_hdrlen +
(maclen < 16 ? 16 : maclen));
(maclen < 16 ? 16 : maclen)) +
po->tp_reserve;
macoff = netoff - maclen;
}

Expand Down Expand Up @@ -1448,6 +1451,19 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
return -EINVAL;
}
}
case PACKET_RESERVE:
{
unsigned int val;

if (optlen != sizeof(val))
return -EINVAL;
if (po->pg_vec)
return -EBUSY;
if (copy_from_user(&val, optval, sizeof(val)))
return -EFAULT;
po->tp_reserve = val;
return 0;
}
#endif
case PACKET_AUXDATA:
{
Expand Down Expand Up @@ -1547,6 +1563,12 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
}
data = &val;
break;
case PACKET_RESERVE:
if (len > sizeof(unsigned int))
len = sizeof(unsigned int);
val = po->tp_reserve;
data = &val;
break;
#endif
default:
return -ENOPROTOOPT;
Expand Down Expand Up @@ -1790,7 +1812,8 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing
return -EINVAL;
if (unlikely(req->tp_block_size & (PAGE_SIZE - 1)))
return -EINVAL;
if (unlikely(req->tp_frame_size < po->tp_hdrlen))
if (unlikely(req->tp_frame_size < po->tp_hdrlen +
po->tp_reserve))
return -EINVAL;
if (unlikely(req->tp_frame_size & (TPACKET_ALIGNMENT - 1)))
return -EINVAL;
Expand Down

0 comments on commit 8913336

Please sign in to comment.