Skip to content

Commit 1801b57

Browse files
dsaherndavem330
authored andcommitted
net: ipv6: add second dif to udp socket lookups
Add a second device index, sdif, to udp socket lookups. sdif is the index for ingress devices enslaved to an l3mdev. It allows the lookups to consider the enslaved device as well as the L3 domain when searching for a socket. Early demux lookups are handled in the next patch as part of INET_MATCH changes. Signed-off-by: David Ahern <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 60d9b03 commit 1801b57

File tree

4 files changed

+35
-21
lines changed

4 files changed

+35
-21
lines changed

include/linux/ipv6.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,16 @@ static inline bool inet6_is_jumbogram(const struct sk_buff *skb)
158158
return !!(IP6CB(skb)->flags & IP6SKB_JUMBOGRAM);
159159
}
160160

161+
/* can not be used in TCP layer after tcp_v6_fill_cb */
162+
static inline int inet6_sdif(const struct sk_buff *skb)
163+
{
164+
#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
165+
if (skb && ipv6_l3mdev_skb(IP6CB(skb)->flags))
166+
return IP6CB(skb)->iif;
167+
#endif
168+
return 0;
169+
}
170+
161171
/* can not be used in TCP layer after tcp_v6_fill_cb */
162172
static inline bool inet6_exact_dif_match(struct net *net, struct sk_buff *skb)
163173
{

include/net/udp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ struct sock *udp6_lib_lookup(struct net *net,
298298
struct sock *__udp6_lib_lookup(struct net *net,
299299
const struct in6_addr *saddr, __be16 sport,
300300
const struct in6_addr *daddr, __be16 dport,
301-
int dif, struct udp_table *tbl,
301+
int dif, int sdif, struct udp_table *tbl,
302302
struct sk_buff *skb);
303303
struct sock *udp6_lib_lookup_skb(struct sk_buff *skb,
304304
__be16 sport, __be16 dport);

net/ipv4/udp_diag.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
5353
req->id.idiag_sport,
5454
(struct in6_addr *)req->id.idiag_dst,
5555
req->id.idiag_dport,
56-
req->id.idiag_if, tbl, NULL);
56+
req->id.idiag_if, 0, tbl, NULL);
5757
#endif
5858
if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
5959
sk = NULL;
@@ -198,7 +198,7 @@ static int __udp_diag_destroy(struct sk_buff *in_skb,
198198
req->id.idiag_dport,
199199
(struct in6_addr *)req->id.idiag_src,
200200
req->id.idiag_sport,
201-
req->id.idiag_if, tbl, NULL);
201+
req->id.idiag_if, 0, tbl, NULL);
202202
}
203203
#endif
204204
else {

net/ipv6/udp.c

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ static void udp_v6_rehash(struct sock *sk)
129129
static int compute_score(struct sock *sk, struct net *net,
130130
const struct in6_addr *saddr, __be16 sport,
131131
const struct in6_addr *daddr, unsigned short hnum,
132-
int dif, bool exact_dif)
132+
int dif, int sdif, bool exact_dif)
133133
{
134134
int score;
135135
struct inet_sock *inet;
@@ -161,9 +161,13 @@ static int compute_score(struct sock *sk, struct net *net,
161161
}
162162

163163
if (sk->sk_bound_dev_if || exact_dif) {
164-
if (sk->sk_bound_dev_if != dif)
164+
bool dev_match = (sk->sk_bound_dev_if == dif ||
165+
sk->sk_bound_dev_if == sdif);
166+
167+
if (exact_dif && !dev_match)
165168
return -1;
166-
score++;
169+
if (sk->sk_bound_dev_if && dev_match)
170+
score++;
167171
}
168172

169173
if (sk->sk_incoming_cpu == raw_smp_processor_id())
@@ -175,9 +179,9 @@ static int compute_score(struct sock *sk, struct net *net,
175179
/* called with rcu_read_lock() */
176180
static struct sock *udp6_lib_lookup2(struct net *net,
177181
const struct in6_addr *saddr, __be16 sport,
178-
const struct in6_addr *daddr, unsigned int hnum, int dif,
179-
bool exact_dif, struct udp_hslot *hslot2,
180-
struct sk_buff *skb)
182+
const struct in6_addr *daddr, unsigned int hnum,
183+
int dif, int sdif, bool exact_dif,
184+
struct udp_hslot *hslot2, struct sk_buff *skb)
181185
{
182186
struct sock *sk, *result;
183187
int score, badness, matches = 0, reuseport = 0;
@@ -187,7 +191,7 @@ static struct sock *udp6_lib_lookup2(struct net *net,
187191
badness = -1;
188192
udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) {
189193
score = compute_score(sk, net, saddr, sport,
190-
daddr, hnum, dif, exact_dif);
194+
daddr, hnum, dif, sdif, exact_dif);
191195
if (score > badness) {
192196
reuseport = sk->sk_reuseport;
193197
if (reuseport) {
@@ -214,10 +218,10 @@ static struct sock *udp6_lib_lookup2(struct net *net,
214218

215219
/* rcu_read_lock() must be held */
216220
struct sock *__udp6_lib_lookup(struct net *net,
217-
const struct in6_addr *saddr, __be16 sport,
218-
const struct in6_addr *daddr, __be16 dport,
219-
int dif, struct udp_table *udptable,
220-
struct sk_buff *skb)
221+
const struct in6_addr *saddr, __be16 sport,
222+
const struct in6_addr *daddr, __be16 dport,
223+
int dif, int sdif, struct udp_table *udptable,
224+
struct sk_buff *skb)
221225
{
222226
struct sock *sk, *result;
223227
unsigned short hnum = ntohs(dport);
@@ -235,7 +239,7 @@ struct sock *__udp6_lib_lookup(struct net *net,
235239
goto begin;
236240

237241
result = udp6_lib_lookup2(net, saddr, sport,
238-
daddr, hnum, dif, exact_dif,
242+
daddr, hnum, dif, sdif, exact_dif,
239243
hslot2, skb);
240244
if (!result) {
241245
unsigned int old_slot2 = slot2;
@@ -250,7 +254,7 @@ struct sock *__udp6_lib_lookup(struct net *net,
250254
goto begin;
251255

252256
result = udp6_lib_lookup2(net, saddr, sport,
253-
daddr, hnum, dif,
257+
daddr, hnum, dif, sdif,
254258
exact_dif, hslot2,
255259
skb);
256260
}
@@ -261,7 +265,7 @@ struct sock *__udp6_lib_lookup(struct net *net,
261265
badness = -1;
262266
sk_for_each_rcu(sk, &hslot->head) {
263267
score = compute_score(sk, net, saddr, sport, daddr, hnum, dif,
264-
exact_dif);
268+
sdif, exact_dif);
265269
if (score > badness) {
266270
reuseport = sk->sk_reuseport;
267271
if (reuseport) {
@@ -294,7 +298,7 @@ static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb,
294298

295299
return __udp6_lib_lookup(dev_net(skb->dev), &iph->saddr, sport,
296300
&iph->daddr, dport, inet6_iif(skb),
297-
udptable, skb);
301+
inet6_sdif(skb), udptable, skb);
298302
}
299303

300304
struct sock *udp6_lib_lookup_skb(struct sk_buff *skb,
@@ -304,7 +308,7 @@ struct sock *udp6_lib_lookup_skb(struct sk_buff *skb,
304308

305309
return __udp6_lib_lookup(dev_net(skb->dev), &iph->saddr, sport,
306310
&iph->daddr, dport, inet6_iif(skb),
307-
&udp_table, skb);
311+
inet6_sdif(skb), &udp_table, skb);
308312
}
309313
EXPORT_SYMBOL_GPL(udp6_lib_lookup_skb);
310314

@@ -320,7 +324,7 @@ struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be
320324
struct sock *sk;
321325

322326
sk = __udp6_lib_lookup(net, saddr, sport, daddr, dport,
323-
dif, &udp_table, NULL);
327+
dif, 0, &udp_table, NULL);
324328
if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
325329
sk = NULL;
326330
return sk;
@@ -501,7 +505,7 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
501505
struct net *net = dev_net(skb->dev);
502506

503507
sk = __udp6_lib_lookup(net, daddr, uh->dest, saddr, uh->source,
504-
inet6_iif(skb), udptable, skb);
508+
inet6_iif(skb), 0, udptable, skb);
505509
if (!sk) {
506510
__ICMP6_INC_STATS(net, __in6_dev_get(skb->dev),
507511
ICMP6_MIB_INERRORS);

0 commit comments

Comments
 (0)