Skip to content

Commit a583636

Browse files
kraigatgoogdavem330
authored andcommitted
inet: refactor inet[6]_lookup functions to take skb
This is a preliminary step to allow fast socket lookup of SO_REUSEPORT groups. Doing so with a BPF filter will require access to the skb in question. This change plumbs the skb (and offset to payload data) through the call stack to the listening socket lookup implementations where it will be used in a following patch. Signed-off-by: Craig Gallek <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d9b3fca commit a583636

File tree

12 files changed

+85
-42
lines changed

12 files changed

+85
-42
lines changed

include/net/addrconf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr,
8787
u32 banned_flags);
8888
int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
8989
u32 banned_flags);
90+
int ipv4_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2,
91+
bool match_wildcard);
9092
int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2,
9193
bool match_wildcard);
9294
void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr);

include/net/inet6_hashtables.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,15 @@ struct sock *__inet6_lookup_established(struct net *net,
5353

5454
struct sock *inet6_lookup_listener(struct net *net,
5555
struct inet_hashinfo *hashinfo,
56+
struct sk_buff *skb, int doff,
5657
const struct in6_addr *saddr,
5758
const __be16 sport,
5859
const struct in6_addr *daddr,
5960
const unsigned short hnum, const int dif);
6061

6162
static inline struct sock *__inet6_lookup(struct net *net,
6263
struct inet_hashinfo *hashinfo,
64+
struct sk_buff *skb, int doff,
6365
const struct in6_addr *saddr,
6466
const __be16 sport,
6567
const struct in6_addr *daddr,
@@ -71,12 +73,12 @@ static inline struct sock *__inet6_lookup(struct net *net,
7173
if (sk)
7274
return sk;
7375

74-
return inet6_lookup_listener(net, hashinfo, saddr, sport,
76+
return inet6_lookup_listener(net, hashinfo, skb, doff, saddr, sport,
7577
daddr, hnum, dif);
7678
}
7779

7880
static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo,
79-
struct sk_buff *skb,
81+
struct sk_buff *skb, int doff,
8082
const __be16 sport,
8183
const __be16 dport,
8284
int iif)
@@ -86,13 +88,14 @@ static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo,
8688
if (sk)
8789
return sk;
8890

89-
return __inet6_lookup(dev_net(skb_dst(skb)->dev), hashinfo,
90-
&ipv6_hdr(skb)->saddr, sport,
91+
return __inet6_lookup(dev_net(skb_dst(skb)->dev), hashinfo, skb,
92+
doff, &ipv6_hdr(skb)->saddr, sport,
9193
&ipv6_hdr(skb)->daddr, ntohs(dport),
9294
iif);
9395
}
9496

9597
struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo,
98+
struct sk_buff *skb, int doff,
9699
const struct in6_addr *saddr, const __be16 sport,
97100
const struct in6_addr *daddr, const __be16 dport,
98101
const int dif);

include/net/inet_hashtables.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,17 +213,19 @@ void inet_unhash(struct sock *sk);
213213

214214
struct sock *__inet_lookup_listener(struct net *net,
215215
struct inet_hashinfo *hashinfo,
216+
struct sk_buff *skb, int doff,
216217
const __be32 saddr, const __be16 sport,
217218
const __be32 daddr,
218219
const unsigned short hnum,
219220
const int dif);
220221

221222
static inline struct sock *inet_lookup_listener(struct net *net,
222223
struct inet_hashinfo *hashinfo,
224+
struct sk_buff *skb, int doff,
223225
__be32 saddr, __be16 sport,
224226
__be32 daddr, __be16 dport, int dif)
225227
{
226-
return __inet_lookup_listener(net, hashinfo, saddr, sport,
228+
return __inet_lookup_listener(net, hashinfo, skb, doff, saddr, sport,
227229
daddr, ntohs(dport), dif);
228230
}
229231

@@ -299,6 +301,7 @@ static inline struct sock *
299301

300302
static inline struct sock *__inet_lookup(struct net *net,
301303
struct inet_hashinfo *hashinfo,
304+
struct sk_buff *skb, int doff,
302305
const __be32 saddr, const __be16 sport,
303306
const __be32 daddr, const __be16 dport,
304307
const int dif)
@@ -307,27 +310,30 @@ static inline struct sock *__inet_lookup(struct net *net,
307310
struct sock *sk = __inet_lookup_established(net, hashinfo,
308311
saddr, sport, daddr, hnum, dif);
309312

310-
return sk ? : __inet_lookup_listener(net, hashinfo, saddr, sport,
311-
daddr, hnum, dif);
313+
return sk ? : __inet_lookup_listener(net, hashinfo, skb, doff, saddr,
314+
sport, daddr, hnum, dif);
312315
}
313316

314317
static inline struct sock *inet_lookup(struct net *net,
315318
struct inet_hashinfo *hashinfo,
319+
struct sk_buff *skb, int doff,
316320
const __be32 saddr, const __be16 sport,
317321
const __be32 daddr, const __be16 dport,
318322
const int dif)
319323
{
320324
struct sock *sk;
321325

322326
local_bh_disable();
323-
sk = __inet_lookup(net, hashinfo, saddr, sport, daddr, dport, dif);
327+
sk = __inet_lookup(net, hashinfo, skb, doff, saddr, sport, daddr,
328+
dport, dif);
324329
local_bh_enable();
325330

326331
return sk;
327332
}
328333

329334
static inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo,
330335
struct sk_buff *skb,
336+
int doff,
331337
const __be16 sport,
332338
const __be16 dport)
333339
{
@@ -337,8 +343,8 @@ static inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo,
337343
if (sk)
338344
return sk;
339345
else
340-
return __inet_lookup(dev_net(skb_dst(skb)->dev), hashinfo,
341-
iph->saddr, sport,
346+
return __inet_lookup(dev_net(skb_dst(skb)->dev), hashinfo, skb,
347+
doff, iph->saddr, sport,
342348
iph->daddr, dport, inet_iif(skb));
343349
}
344350

net/dccp/ipv4.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -802,7 +802,7 @@ static int dccp_v4_rcv(struct sk_buff *skb)
802802
}
803803

804804
lookup:
805-
sk = __inet_lookup_skb(&dccp_hashinfo, skb,
805+
sk = __inet_lookup_skb(&dccp_hashinfo, skb, __dccp_hdr_len(dh),
806806
dh->dccph_sport, dh->dccph_dport);
807807
if (!sk) {
808808
dccp_pr_debug("failed to look up flow ID in table and "

net/dccp/ipv6.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ static int dccp_v6_rcv(struct sk_buff *skb)
668668
DCCP_SKB_CB(skb)->dccpd_ack_seq = dccp_hdr_ack_seq(skb);
669669

670670
lookup:
671-
sk = __inet6_lookup_skb(&dccp_hashinfo, skb,
671+
sk = __inet6_lookup_skb(&dccp_hashinfo, skb, __dccp_hdr_len(dh),
672672
dh->dccph_sport, dh->dccph_dport,
673673
inet6_iif(skb));
674674
if (!sk) {

net/ipv4/inet_diag.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -357,18 +357,18 @@ struct sock *inet_diag_find_one_icsk(struct net *net,
357357
struct sock *sk;
358358

359359
if (req->sdiag_family == AF_INET)
360-
sk = inet_lookup(net, hashinfo, req->id.idiag_dst[0],
360+
sk = inet_lookup(net, hashinfo, NULL, 0, req->id.idiag_dst[0],
361361
req->id.idiag_dport, req->id.idiag_src[0],
362362
req->id.idiag_sport, req->id.idiag_if);
363363
#if IS_ENABLED(CONFIG_IPV6)
364364
else if (req->sdiag_family == AF_INET6) {
365365
if (ipv6_addr_v4mapped((struct in6_addr *)req->id.idiag_dst) &&
366366
ipv6_addr_v4mapped((struct in6_addr *)req->id.idiag_src))
367-
sk = inet_lookup(net, hashinfo, req->id.idiag_dst[3],
367+
sk = inet_lookup(net, hashinfo, NULL, 0, req->id.idiag_dst[3],
368368
req->id.idiag_dport, req->id.idiag_src[3],
369369
req->id.idiag_sport, req->id.idiag_if);
370370
else
371-
sk = inet6_lookup(net, hashinfo,
371+
sk = inet6_lookup(net, hashinfo, NULL, 0,
372372
(struct in6_addr *)req->id.idiag_dst,
373373
req->id.idiag_dport,
374374
(struct in6_addr *)req->id.idiag_src,

net/ipv4/inet_hashtables.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ static inline int compute_score(struct sock *sk, struct net *net,
205205

206206
struct sock *__inet_lookup_listener(struct net *net,
207207
struct inet_hashinfo *hashinfo,
208+
struct sk_buff *skb, int doff,
208209
const __be32 saddr, __be16 sport,
209210
const __be32 daddr, const unsigned short hnum,
210211
const int dif)

net/ipv4/tcp_ipv4.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -637,8 +637,8 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb)
637637
* Incoming packet is checked with md5 hash with finding key,
638638
* no RST generated if md5 hash doesn't match.
639639
*/
640-
sk1 = __inet_lookup_listener(net,
641-
&tcp_hashinfo, ip_hdr(skb)->saddr,
640+
sk1 = __inet_lookup_listener(net, &tcp_hashinfo, NULL, 0,
641+
ip_hdr(skb)->saddr,
642642
th->source, ip_hdr(skb)->daddr,
643643
ntohs(th->source), inet_iif(skb));
644644
/* don't send rst if it can't find key */
@@ -1581,7 +1581,8 @@ int tcp_v4_rcv(struct sk_buff *skb)
15811581
TCP_SKB_CB(skb)->sacked = 0;
15821582

15831583
lookup:
1584-
sk = __inet_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest);
1584+
sk = __inet_lookup_skb(&tcp_hashinfo, skb, __tcp_hdrlen(th), th->source,
1585+
th->dest);
15851586
if (!sk)
15861587
goto no_tcp_socket;
15871588

@@ -1695,7 +1696,8 @@ int tcp_v4_rcv(struct sk_buff *skb)
16951696
switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
16961697
case TCP_TW_SYN: {
16971698
struct sock *sk2 = inet_lookup_listener(dev_net(skb->dev),
1698-
&tcp_hashinfo,
1699+
&tcp_hashinfo, skb,
1700+
__tcp_hdrlen(th),
16991701
iph->saddr, th->source,
17001702
iph->daddr, th->dest,
17011703
inet_iif(skb));

net/ipv6/inet6_hashtables.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,9 @@ static inline int compute_score(struct sock *sk, struct net *net,
121121
}
122122

123123
struct sock *inet6_lookup_listener(struct net *net,
124-
struct inet_hashinfo *hashinfo, const struct in6_addr *saddr,
124+
struct inet_hashinfo *hashinfo,
125+
struct sk_buff *skb, int doff,
126+
const struct in6_addr *saddr,
125127
const __be16 sport, const struct in6_addr *daddr,
126128
const unsigned short hnum, const int dif)
127129
{
@@ -177,14 +179,16 @@ struct sock *inet6_lookup_listener(struct net *net,
177179
EXPORT_SYMBOL_GPL(inet6_lookup_listener);
178180

179181
struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo,
182+
struct sk_buff *skb, int doff,
180183
const struct in6_addr *saddr, const __be16 sport,
181184
const struct in6_addr *daddr, const __be16 dport,
182185
const int dif)
183186
{
184187
struct sock *sk;
185188

186189
local_bh_disable();
187-
sk = __inet6_lookup(net, hashinfo, saddr, sport, daddr, ntohs(dport), dif);
190+
sk = __inet6_lookup(net, hashinfo, skb, doff, saddr, sport, daddr,
191+
ntohs(dport), dif);
188192
local_bh_enable();
189193

190194
return sk;

net/ipv6/tcp_ipv6.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -866,7 +866,8 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
866866
* no RST generated if md5 hash doesn't match.
867867
*/
868868
sk1 = inet6_lookup_listener(dev_net(skb_dst(skb)->dev),
869-
&tcp_hashinfo, &ipv6h->saddr,
869+
&tcp_hashinfo, NULL, 0,
870+
&ipv6h->saddr,
870871
th->source, &ipv6h->daddr,
871872
ntohs(th->source), tcp_v6_iif(skb));
872873
if (!sk1)
@@ -1375,8 +1376,8 @@ static int tcp_v6_rcv(struct sk_buff *skb)
13751376
hdr = ipv6_hdr(skb);
13761377

13771378
lookup:
1378-
sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest,
1379-
inet6_iif(skb));
1379+
sk = __inet6_lookup_skb(&tcp_hashinfo, skb, __tcp_hdrlen(th),
1380+
th->source, th->dest, inet6_iif(skb));
13801381
if (!sk)
13811382
goto no_tcp_socket;
13821383

@@ -1500,6 +1501,7 @@ static int tcp_v6_rcv(struct sk_buff *skb)
15001501
struct sock *sk2;
15011502

15021503
sk2 = inet6_lookup_listener(dev_net(skb->dev), &tcp_hashinfo,
1504+
skb, __tcp_hdrlen(th),
15031505
&ipv6_hdr(skb)->saddr, th->source,
15041506
&ipv6_hdr(skb)->daddr,
15051507
ntohs(th->dest), tcp_v6_iif(skb));

net/netfilter/xt_TPROXY.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -105,19 +105,24 @@ tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, __be32 daddr)
105105
* belonging to established connections going through that one.
106106
*/
107107
static inline struct sock *
108-
nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
108+
nf_tproxy_get_sock_v4(struct net *net, struct sk_buff *skb, void *hp,
109+
const u8 protocol,
109110
const __be32 saddr, const __be32 daddr,
110111
const __be16 sport, const __be16 dport,
111112
const struct net_device *in,
112113
const enum nf_tproxy_lookup_t lookup_type)
113114
{
114115
struct sock *sk;
116+
struct tcphdr *tcph;
115117

116118
switch (protocol) {
117119
case IPPROTO_TCP:
118120
switch (lookup_type) {
119121
case NFT_LOOKUP_LISTENER:
120-
sk = inet_lookup_listener(net, &tcp_hashinfo,
122+
tcph = hp;
123+
sk = inet_lookup_listener(net, &tcp_hashinfo, skb,
124+
ip_hdrlen(skb) +
125+
__tcp_hdrlen(tcph),
121126
saddr, sport,
122127
daddr, dport,
123128
in->ifindex);
@@ -169,19 +174,23 @@ nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
169174

170175
#ifdef XT_TPROXY_HAVE_IPV6
171176
static inline struct sock *
172-
nf_tproxy_get_sock_v6(struct net *net, const u8 protocol,
177+
nf_tproxy_get_sock_v6(struct net *net, struct sk_buff *skb, int thoff, void *hp,
178+
const u8 protocol,
173179
const struct in6_addr *saddr, const struct in6_addr *daddr,
174180
const __be16 sport, const __be16 dport,
175181
const struct net_device *in,
176182
const enum nf_tproxy_lookup_t lookup_type)
177183
{
178184
struct sock *sk;
185+
struct tcphdr *tcph;
179186

180187
switch (protocol) {
181188
case IPPROTO_TCP:
182189
switch (lookup_type) {
183190
case NFT_LOOKUP_LISTENER:
184-
sk = inet6_lookup_listener(net, &tcp_hashinfo,
191+
tcph = hp;
192+
sk = inet6_lookup_listener(net, &tcp_hashinfo, skb,
193+
thoff + __tcp_hdrlen(tcph),
185194
saddr, sport,
186195
daddr, ntohs(dport),
187196
in->ifindex);
@@ -267,7 +276,7 @@ tproxy_handle_time_wait4(struct net *net, struct sk_buff *skb,
267276
* to a listener socket if there's one */
268277
struct sock *sk2;
269278

270-
sk2 = nf_tproxy_get_sock_v4(net, iph->protocol,
279+
sk2 = nf_tproxy_get_sock_v4(net, skb, hp, iph->protocol,
271280
iph->saddr, laddr ? laddr : iph->daddr,
272281
hp->source, lport ? lport : hp->dest,
273282
skb->dev, NFT_LOOKUP_LISTENER);
@@ -305,7 +314,7 @@ tproxy_tg4(struct net *net, struct sk_buff *skb, __be32 laddr, __be16 lport,
305314
* addresses, this happens if the redirect already happened
306315
* and the current packet belongs to an already established
307316
* connection */
308-
sk = nf_tproxy_get_sock_v4(net, iph->protocol,
317+
sk = nf_tproxy_get_sock_v4(net, skb, hp, iph->protocol,
309318
iph->saddr, iph->daddr,
310319
hp->source, hp->dest,
311320
skb->dev, NFT_LOOKUP_ESTABLISHED);
@@ -321,7 +330,7 @@ tproxy_tg4(struct net *net, struct sk_buff *skb, __be32 laddr, __be16 lport,
321330
else if (!sk)
322331
/* no, there's no established connection, check if
323332
* there's a listener on the redirected addr/port */
324-
sk = nf_tproxy_get_sock_v4(net, iph->protocol,
333+
sk = nf_tproxy_get_sock_v4(net, skb, hp, iph->protocol,
325334
iph->saddr, laddr,
326335
hp->source, lport,
327336
skb->dev, NFT_LOOKUP_LISTENER);
@@ -429,7 +438,7 @@ tproxy_handle_time_wait6(struct sk_buff *skb, int tproto, int thoff,
429438
* to a listener socket if there's one */
430439
struct sock *sk2;
431440

432-
sk2 = nf_tproxy_get_sock_v6(par->net, tproto,
441+
sk2 = nf_tproxy_get_sock_v6(par->net, skb, thoff, hp, tproto,
433442
&iph->saddr,
434443
tproxy_laddr6(skb, &tgi->laddr.in6, &iph->daddr),
435444
hp->source,
@@ -472,7 +481,7 @@ tproxy_tg6_v1(struct sk_buff *skb, const struct xt_action_param *par)
472481
* addresses, this happens if the redirect already happened
473482
* and the current packet belongs to an already established
474483
* connection */
475-
sk = nf_tproxy_get_sock_v6(par->net, tproto,
484+
sk = nf_tproxy_get_sock_v6(par->net, skb, thoff, hp, tproto,
476485
&iph->saddr, &iph->daddr,
477486
hp->source, hp->dest,
478487
par->in, NFT_LOOKUP_ESTABLISHED);
@@ -487,8 +496,8 @@ tproxy_tg6_v1(struct sk_buff *skb, const struct xt_action_param *par)
487496
else if (!sk)
488497
/* no there's no established connection, check if
489498
* there's a listener on the redirected addr/port */
490-
sk = nf_tproxy_get_sock_v6(par->net, tproto,
491-
&iph->saddr, laddr,
499+
sk = nf_tproxy_get_sock_v6(par->net, skb, thoff, hp,
500+
tproto, &iph->saddr, laddr,
492501
hp->source, lport,
493502
par->in, NFT_LOOKUP_LISTENER);
494503

0 commit comments

Comments
 (0)