OpenWrt – Blame information for rev 3
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | From: Felix Fietkau <nbd@nbd.name> |
2 | Subject: net: add an optimization for dealing with raw sockets |
||
3 | |||
4 | lede-commit: 4898039703d7315f0f3431c860123338ec3be0f6 |
||
5 | Signed-off-by: Felix Fietkau <nbd@nbd.name> |
||
6 | --- |
||
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(-) |
||
11 | |||
12 | --- a/include/uapi/linux/if_packet.h |
||
13 | +++ b/include/uapi/linux/if_packet.h |
||
14 | @@ -32,6 +32,8 @@ struct sockaddr_ll { |
||
15 | #define PACKET_KERNEL 7 /* To kernel space */ |
||
16 | /* Unused, PACKET_FASTROUTE and PACKET_LOOPBACK are invisible to user space */ |
||
17 | #define PACKET_FASTROUTE 6 /* Fastrouted frame */ |
||
18 | +#define PACKET_MASK_ANY 0xffffffff /* mask for packet type bits */ |
||
19 | + |
||
20 | |||
21 | /* Packet socket options */ |
||
22 | |||
23 | @@ -57,6 +59,7 @@ struct sockaddr_ll { |
||
24 | #define PACKET_QDISC_BYPASS 20 |
||
25 | #define PACKET_ROLLOVER_STATS 21 |
||
26 | #define PACKET_FANOUT_DATA 22 |
||
27 | +#define PACKET_RECV_TYPE 23 |
||
28 | |||
29 | #define PACKET_FANOUT_HASH 0 |
||
30 | #define PACKET_FANOUT_LB 1 |
||
31 | --- a/net/packet/af_packet.c |
||
32 | +++ b/net/packet/af_packet.c |
||
33 | @@ -1829,6 +1829,7 @@ static int packet_rcv_spkt(struct sk_buf |
||
34 | { |
||
35 | struct sock *sk; |
||
36 | struct sockaddr_pkt *spkt; |
||
37 | + struct packet_sock *po; |
||
38 | |||
39 | /* |
||
40 | * When we registered the protocol we saved the socket in the data |
||
41 | @@ -1836,6 +1837,7 @@ static int packet_rcv_spkt(struct sk_buf |
||
42 | */ |
||
43 | |||
44 | sk = pt->af_packet_priv; |
||
45 | + po = pkt_sk(sk); |
||
46 | |||
47 | /* |
||
48 | * Yank back the headers [hope the device set this |
||
49 | @@ -1848,7 +1850,7 @@ static int packet_rcv_spkt(struct sk_buf |
||
50 | * so that this procedure is noop. |
||
51 | */ |
||
52 | |||
53 | - if (skb->pkt_type == PACKET_LOOPBACK) |
||
54 | + if (!(po->pkt_type & (1 << skb->pkt_type))) |
||
55 | goto out; |
||
56 | |||
57 | if (!net_eq(dev_net(dev), sock_net(sk))) |
||
58 | @@ -2075,12 +2077,12 @@ static int packet_rcv(struct sk_buff *sk |
||
59 | unsigned int snaplen, res; |
||
60 | bool is_drop_n_account = false; |
||
61 | |||
62 | - if (skb->pkt_type == PACKET_LOOPBACK) |
||
63 | - goto drop; |
||
64 | - |
||
65 | sk = pt->af_packet_priv; |
||
66 | po = pkt_sk(sk); |
||
67 | |||
68 | + if (!(po->pkt_type & (1 << skb->pkt_type))) |
||
69 | + goto drop; |
||
70 | + |
||
71 | if (!net_eq(dev_net(dev), sock_net(sk))) |
||
72 | goto drop; |
||
73 | |||
74 | @@ -2206,12 +2208,12 @@ static int tpacket_rcv(struct sk_buff *s |
||
75 | BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h2)) != 32); |
||
76 | BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h3)) != 48); |
||
77 | |||
78 | - if (skb->pkt_type == PACKET_LOOPBACK) |
||
79 | - goto drop; |
||
80 | - |
||
81 | sk = pt->af_packet_priv; |
||
82 | po = pkt_sk(sk); |
||
83 | |||
84 | + if (!(po->pkt_type & (1 << skb->pkt_type))) |
||
85 | + goto drop; |
||
86 | + |
||
87 | if (!net_eq(dev_net(dev), sock_net(sk))) |
||
88 | goto drop; |
||
89 | |||
3 | office | 90 | @@ -3260,6 +3262,7 @@ static int packet_create(struct net *net |
1 | office | 91 | mutex_init(&po->pg_vec_lock); |
92 | po->rollover = NULL; |
||
93 | po->prot_hook.func = packet_rcv; |
||
94 | + po->pkt_type = PACKET_MASK_ANY & ~(1 << PACKET_LOOPBACK); |
||
95 | |||
96 | if (sock->type == SOCK_PACKET) |
||
97 | po->prot_hook.func = packet_rcv_spkt; |
||
3 | office | 98 | @@ -3873,6 +3876,16 @@ packet_setsockopt(struct socket *sock, i |
1 | office | 99 | po->xmit = val ? packet_direct_xmit : dev_queue_xmit; |
100 | return 0; |
||
101 | } |
||
102 | + case PACKET_RECV_TYPE: |
||
103 | + { |
||
104 | + unsigned int val; |
||
105 | + if (optlen != sizeof(val)) |
||
106 | + return -EINVAL; |
||
107 | + if (copy_from_user(&val, optval, sizeof(val))) |
||
108 | + return -EFAULT; |
||
109 | + po->pkt_type = val & ~BIT(PACKET_LOOPBACK); |
||
110 | + return 0; |
||
111 | + } |
||
112 | default: |
||
113 | return -ENOPROTOOPT; |
||
114 | } |
||
3 | office | 115 | @@ -3925,6 +3938,13 @@ static int packet_getsockopt(struct sock |
1 | office | 116 | case PACKET_VNET_HDR: |
117 | val = po->has_vnet_hdr; |
||
118 | break; |
||
119 | + case PACKET_RECV_TYPE: |
||
120 | + if (len > sizeof(unsigned int)) |
||
121 | + len = sizeof(unsigned int); |
||
122 | + val = po->pkt_type; |
||
123 | + |
||
124 | + data = &val; |
||
125 | + break; |
||
126 | case PACKET_VERSION: |
||
127 | val = po->tp_version; |
||
128 | break; |
||
129 | --- a/net/packet/internal.h |
||
130 | +++ b/net/packet/internal.h |
||
131 | @@ -131,6 +131,7 @@ struct packet_sock { |
||
132 | struct net_device __rcu *cached_dev; |
||
133 | int (*xmit)(struct sk_buff *skb); |
||
134 | struct packet_type prot_hook ____cacheline_aligned_in_smp; |
||
135 | + unsigned int pkt_type; |
||
136 | }; |
||
137 | |||
138 | static struct packet_sock *pkt_sk(struct sock *sk) |