1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2024-09-19 02:29:53 +03:00
openwrt-xburst/target/linux/generic-2.6/patches-2.6.32/240-packet_socket_type.patch

133 lines
2.9 KiB
Diff
Raw Normal View History

This patch allows the user to specify desired packet types (outgoing,
broadcast, unicast, etc.) on packet sockets via setsockopt.
This can reduce the load in situations where only a limited number
of packet types are necessary
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
--- a/include/linux/if_packet.h
+++ b/include/linux/if_packet.h
@@ -31,6 +31,8 @@
/* These ones are invisible by user level */
#define PACKET_LOOPBACK 5 /* MC/BRD frame looped back */
#define PACKET_FASTROUTE 6 /* Fastrouted frame */
+#define PACKET_MASK_ANY 0xffffffff /* mask for packet type bits */
+
/* Packet socket options */
@@ -48,6 +50,7 @@
#define PACKET_RESERVE 12
#define PACKET_TX_RING 13
#define PACKET_LOSS 14
+#define PACKET_RECV_TYPE 15
struct tpacket_stats
{
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -204,6 +204,7 @@
unsigned int tp_reserve;
unsigned int tp_loss:1;
#endif
+ unsigned int pkt_type;
};
struct packet_skb_cb {
@@ -342,6 +343,7 @@
{
struct sock *sk;
struct sockaddr_pkt *spkt;
+ struct packet_sock *po;
/*
* When we registered the protocol we saved the socket in the data
@@ -349,6 +351,7 @@
*/
sk = pt->af_packet_priv;
+ po = pkt_sk(sk);
/*
* Yank back the headers [hope the device set this
@@ -361,7 +364,7 @@
* so that this procedure is noop.
*/
- if (skb->pkt_type == PACKET_LOOPBACK)
+ if (!(po->pkt_type & (1 << skb->pkt_type)))
goto out;
if (dev_net(dev) != sock_net(sk))
@@ -545,12 +548,12 @@
int skb_len = skb->len;
unsigned int snaplen, res;
- if (skb->pkt_type == PACKET_LOOPBACK)
- goto drop;
-
sk = pt->af_packet_priv;
po = pkt_sk(sk);
+ if (!(po->pkt_type & (1 << skb->pkt_type)))
+ goto drop;
+
if (dev_net(dev) != sock_net(sk))
goto drop;
@@ -667,12 +670,12 @@
struct timeval tv;
struct timespec ts;
- if (skb->pkt_type == PACKET_LOOPBACK)
- goto drop;
-
sk = pt->af_packet_priv;
po = pkt_sk(sk);
+ if (!(po->pkt_type & (1 << skb->pkt_type)))
+ goto drop;
+
if (dev_net(dev) != sock_net(sk))
goto drop;
@@ -1390,6 +1393,7 @@
spin_lock_init(&po->bind_lock);
mutex_init(&po->pg_vec_lock);
po->prot_hook.func = packet_rcv;
+ po->pkt_type = PACKET_MASK_ANY & ~(1 << PACKET_LOOPBACK);
if (sock->type == SOCK_PACKET)
po->prot_hook.func = packet_rcv_spkt;
@@ -1737,6 +1741,16 @@
ret = packet_mc_drop(sk, &mreq);
return ret;
}
+ case PACKET_RECV_TYPE:
+ {
+ unsigned int val;
+ if (optlen != sizeof(val))
+ return -EINVAL;
+ if (copy_from_user(&val, optval, sizeof(val)))
+ return -EFAULT;
+ po->pkt_type = val & ~PACKET_LOOPBACK;
+ return 0;
+ }
#ifdef CONFIG_PACKET_MMAP
case PACKET_RX_RING:
@@ -1882,6 +1896,13 @@
data = &val;
break;
+ case PACKET_RECV_TYPE:
+ if (len > sizeof(unsigned int))
+ len = sizeof(unsigned int);
+ val = po->pkt_type;
+
+ data = &val;
+ break;
#ifdef CONFIG_PACKET_MMAP
case PACKET_VERSION:
if (len > sizeof(int))