1 From: Felix Fietkau <nbd@nbd.name>
2 Subject: net: add an optimization for dealing with raw sockets
4 lede-commit: 4898039703d7315f0f3431c860123338ec3be0f6
5 Signed-off-by: Felix Fietkau <nbd@nbd.name>
7 include/uapi/linux/if_packet.h | 3 +++
8 net/packet/af_packet.c | 34 +++++++++++++++++++++++++++-------
9 net/packet/internal.h | 1 +
10 3 files changed, 31 insertions(+), 7 deletions(-)
12 diff --git a/include/uapi/linux/if_packet.h b/include/uapi/linux/if_packet.h
13 index 9e7edfd8141e..40fdf8907900 100644
14 --- a/include/uapi/linux/if_packet.h
15 +++ b/include/uapi/linux/if_packet.h
16 @@ -31,6 +31,8 @@ struct sockaddr_ll {
17 #define PACKET_KERNEL 7 /* To kernel space */
18 /* Unused, PACKET_FASTROUTE and PACKET_LOOPBACK are invisible to user space */
19 #define PACKET_FASTROUTE 6 /* Fastrouted frame */
20 +#define PACKET_MASK_ANY 0xffffffff /* mask for packet type bits */
23 /* Packet socket options */
25 @@ -56,6 +58,7 @@ struct sockaddr_ll {
26 #define PACKET_QDISC_BYPASS 20
27 #define PACKET_ROLLOVER_STATS 21
28 #define PACKET_FANOUT_DATA 22
29 +#define PACKET_RECV_TYPE 23
31 #define PACKET_FANOUT_HASH 0
32 #define PACKET_FANOUT_LB 1
33 diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
34 index 6a563e6e24de..e412c5a4f6d4 100644
35 --- a/net/packet/af_packet.c
36 +++ b/net/packet/af_packet.c
37 @@ -1772,6 +1772,7 @@ static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev,
40 struct sockaddr_pkt *spkt;
41 + struct packet_sock *po;
44 * When we registered the protocol we saved the socket in the data
45 @@ -1779,6 +1780,7 @@ static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev,
48 sk = pt->af_packet_priv;
52 * Yank back the headers [hope the device set this
53 @@ -1791,7 +1793,7 @@ static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev,
54 * so that this procedure is noop.
57 - if (skb->pkt_type == PACKET_LOOPBACK)
58 + if (!(po->pkt_type & (1 << skb->pkt_type)))
61 if (!net_eq(dev_net(dev), sock_net(sk)))
62 @@ -2029,12 +2031,12 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
63 unsigned int snaplen, res;
64 bool is_drop_n_account = false;
66 - if (skb->pkt_type == PACKET_LOOPBACK)
69 sk = pt->af_packet_priv;
72 + if (!(po->pkt_type & (1 << skb->pkt_type)))
75 if (!net_eq(dev_net(dev), sock_net(sk)))
78 @@ -2159,12 +2161,12 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
79 BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h2)) != 32);
80 BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h3)) != 48);
82 - if (skb->pkt_type == PACKET_LOOPBACK)
85 sk = pt->af_packet_priv;
88 + if (!(po->pkt_type & (1 << skb->pkt_type)))
91 if (!net_eq(dev_net(dev), sock_net(sk)))
94 @@ -3234,6 +3236,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
95 mutex_init(&po->pg_vec_lock);
97 po->prot_hook.func = packet_rcv;
98 + po->pkt_type = PACKET_MASK_ANY & ~(1 << PACKET_LOOPBACK);
100 if (sock->type == SOCK_PACKET)
101 po->prot_hook.func = packet_rcv_spkt;
102 @@ -3815,6 +3818,16 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
103 po->xmit = val ? packet_direct_xmit : dev_queue_xmit;
106 + case PACKET_RECV_TYPE:
109 + if (optlen != sizeof(val))
111 + if (copy_from_user(&val, optval, sizeof(val)))
113 + po->pkt_type = val & ~BIT(PACKET_LOOPBACK);
119 @@ -3867,6 +3880,13 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
120 case PACKET_VNET_HDR:
121 val = po->has_vnet_hdr;
123 + case PACKET_RECV_TYPE:
124 + if (len > sizeof(unsigned int))
125 + len = sizeof(unsigned int);
126 + val = po->pkt_type;
131 val = po->tp_version;
133 diff --git a/net/packet/internal.h b/net/packet/internal.h
134 index 9ee46314b7d7..76c895fcf22f 100644
135 --- a/net/packet/internal.h
136 +++ b/net/packet/internal.h
137 @@ -129,6 +129,7 @@ struct packet_sock {
138 struct net_device __rcu *cached_dev;
139 int (*xmit)(struct sk_buff *skb);
140 struct packet_type prot_hook ____cacheline_aligned_in_smp;
141 + unsigned int pkt_type;
144 static struct packet_sock *pkt_sk(struct sock *sk)