kernel: Update kernel 4.9 to 4.9.70
[openwrt/openwrt.git] / target / linux / generic / pending-4.9 / 630-packet_socket_type.patch
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 @@ -31,6 +31,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 @@ -56,6 +58,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 @@ -1773,6 +1773,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 @@ -1780,6 +1781,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 @@ -1792,7 +1794,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 @@ -2030,12 +2032,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 @@ -2161,12 +2163,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
90 @@ -3251,6 +3253,7 @@ static int packet_create(struct net *net
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;
98 @@ -3837,6 +3840,16 @@ packet_setsockopt(struct socket *sock, i
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 }
115 @@ -3889,6 +3902,13 @@ static int packet_getsockopt(struct sock
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 @@ -128,6 +128,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)