Skip to content

Commit 9bcb5a5

Browse files
committed
Merge branch 'net-l3mdev-Support-for-sockets-bound-to-enslaved-device'
David Ahern says: ==================== net: l3mdev: Support for sockets bound to enslaved device A missing piece to the VRF puzzle is the ability to bind sockets to devices enslaved to a VRF. This patch set adds the enslaved device index, sdif, to IPv4 and IPv6 socket lookups. The end result for users is the following scope options for services: 1. "global" services - sockets not bound to any device Allows 1 service to work across all network interfaces with connected sockets bound to the VRF the connection originates (Requires net.ipv4.tcp_l3mdev_accept=1 for TCP and net.ipv4.udp_l3mdev_accept=1 for UDP) 2. "VRF" local services - sockets bound to a VRF Sockets work across all network interfaces enslaved to a VRF but are limited to just the one VRF. 3. "device" services - sockets bound to a specific network interface Service works only through the one specific interface. v3 - convert __inet_lookup_established in dccp_v4_err; missed in v2 v2 - remove sk_lookup struct and add sdif as an argument to existing functions Changes since RFC: - no significant logic changes; mainly whitespace cleanups ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 46d4b68 + 5108ab4 commit 9bcb5a5

File tree

23 files changed

+228
-135
lines changed

23 files changed

+228
-135
lines changed

include/linux/igmp.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ extern int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
118118
struct ip_msfilter __user *optval, int __user *optlen);
119119
extern int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
120120
struct group_filter __user *optval, int __user *optlen);
121-
extern int ip_mc_sf_allow(struct sock *sk, __be32 local, __be32 rmt, int dif);
121+
extern int ip_mc_sf_allow(struct sock *sk, __be32 local, __be32 rmt,
122+
int dif, int sdif);
122123
extern void ip_mc_init_dev(struct in_device *);
123124
extern void ip_mc_destroy_dev(struct in_device *);
124125
extern void ip_mc_up(struct in_device *);

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/inet6_hashtables.h

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,17 @@ struct sock *__inet6_lookup_established(struct net *net,
4949
const struct in6_addr *saddr,
5050
const __be16 sport,
5151
const struct in6_addr *daddr,
52-
const u16 hnum, const int dif);
52+
const u16 hnum, const int dif,
53+
const int sdif);
5354

5455
struct sock *inet6_lookup_listener(struct net *net,
5556
struct inet_hashinfo *hashinfo,
5657
struct sk_buff *skb, int doff,
5758
const struct in6_addr *saddr,
5859
const __be16 sport,
5960
const struct in6_addr *daddr,
60-
const unsigned short hnum, const int dif);
61+
const unsigned short hnum,
62+
const int dif, const int sdif);
6163

6264
static inline struct sock *__inet6_lookup(struct net *net,
6365
struct inet_hashinfo *hashinfo,
@@ -66,24 +68,25 @@ static inline struct sock *__inet6_lookup(struct net *net,
6668
const __be16 sport,
6769
const struct in6_addr *daddr,
6870
const u16 hnum,
69-
const int dif,
71+
const int dif, const int sdif,
7072
bool *refcounted)
7173
{
7274
struct sock *sk = __inet6_lookup_established(net, hashinfo, saddr,
73-
sport, daddr, hnum, dif);
75+
sport, daddr, hnum,
76+
dif, sdif);
7477
*refcounted = true;
7578
if (sk)
7679
return sk;
7780
*refcounted = false;
7881
return inet6_lookup_listener(net, hashinfo, skb, doff, saddr, sport,
79-
daddr, hnum, dif);
82+
daddr, hnum, dif, sdif);
8083
}
8184

8285
static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo,
8386
struct sk_buff *skb, int doff,
8487
const __be16 sport,
8588
const __be16 dport,
86-
int iif,
89+
int iif, int sdif,
8790
bool *refcounted)
8891
{
8992
struct sock *sk = skb_steal_sock(skb);
@@ -95,7 +98,7 @@ static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo,
9598
return __inet6_lookup(dev_net(skb_dst(skb)->dev), hashinfo, skb,
9699
doff, &ipv6_hdr(skb)->saddr, sport,
97100
&ipv6_hdr(skb)->daddr, ntohs(dport),
98-
iif, refcounted);
101+
iif, sdif, refcounted);
99102
}
100103

101104
struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo,
@@ -107,13 +110,14 @@ struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo,
107110
int inet6_hash(struct sock *sk);
108111
#endif /* IS_ENABLED(CONFIG_IPV6) */
109112

110-
#define INET6_MATCH(__sk, __net, __saddr, __daddr, __ports, __dif) \
113+
#define INET6_MATCH(__sk, __net, __saddr, __daddr, __ports, __dif, __sdif) \
111114
(((__sk)->sk_portpair == (__ports)) && \
112115
((__sk)->sk_family == AF_INET6) && \
113116
ipv6_addr_equal(&(__sk)->sk_v6_daddr, (__saddr)) && \
114117
ipv6_addr_equal(&(__sk)->sk_v6_rcv_saddr, (__daddr)) && \
115118
(!(__sk)->sk_bound_dev_if || \
116-
((__sk)->sk_bound_dev_if == (__dif))) && \
119+
((__sk)->sk_bound_dev_if == (__dif)) || \
120+
((__sk)->sk_bound_dev_if == (__sdif))) && \
117121
net_eq(sock_net(__sk), (__net)))
118122

119123
#endif /* _INET6_HASHTABLES_H */

include/net/inet_hashtables.h

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -221,16 +221,16 @@ struct sock *__inet_lookup_listener(struct net *net,
221221
const __be32 saddr, const __be16 sport,
222222
const __be32 daddr,
223223
const unsigned short hnum,
224-
const int dif);
224+
const int dif, const int sdif);
225225

226226
static inline struct sock *inet_lookup_listener(struct net *net,
227227
struct inet_hashinfo *hashinfo,
228228
struct sk_buff *skb, int doff,
229229
__be32 saddr, __be16 sport,
230-
__be32 daddr, __be16 dport, int dif)
230+
__be32 daddr, __be16 dport, int dif, int sdif)
231231
{
232232
return __inet_lookup_listener(net, hashinfo, skb, doff, saddr, sport,
233-
daddr, ntohs(dport), dif);
233+
daddr, ntohs(dport), dif, sdif);
234234
}
235235

236236
/* Socket demux engine toys. */
@@ -262,22 +262,24 @@ static inline struct sock *inet_lookup_listener(struct net *net,
262262
(((__force __u64)(__be32)(__daddr)) << 32) | \
263263
((__force __u64)(__be32)(__saddr)))
264264
#endif /* __BIG_ENDIAN */
265-
#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif) \
265+
#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif, __sdif) \
266266
(((__sk)->sk_portpair == (__ports)) && \
267267
((__sk)->sk_addrpair == (__cookie)) && \
268268
(!(__sk)->sk_bound_dev_if || \
269-
((__sk)->sk_bound_dev_if == (__dif))) && \
269+
((__sk)->sk_bound_dev_if == (__dif)) || \
270+
((__sk)->sk_bound_dev_if == (__sdif))) && \
270271
net_eq(sock_net(__sk), (__net)))
271272
#else /* 32-bit arch */
272273
#define INET_ADDR_COOKIE(__name, __saddr, __daddr) \
273274
const int __name __deprecated __attribute__((unused))
274275

275-
#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif) \
276+
#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif, __sdif) \
276277
(((__sk)->sk_portpair == (__ports)) && \
277278
((__sk)->sk_daddr == (__saddr)) && \
278279
((__sk)->sk_rcv_saddr == (__daddr)) && \
279280
(!(__sk)->sk_bound_dev_if || \
280-
((__sk)->sk_bound_dev_if == (__dif))) && \
281+
((__sk)->sk_bound_dev_if == (__dif)) || \
282+
((__sk)->sk_bound_dev_if == (__sdif))) && \
281283
net_eq(sock_net(__sk), (__net)))
282284
#endif /* 64-bit arch */
283285

@@ -288,7 +290,7 @@ struct sock *__inet_lookup_established(struct net *net,
288290
struct inet_hashinfo *hashinfo,
289291
const __be32 saddr, const __be16 sport,
290292
const __be32 daddr, const u16 hnum,
291-
const int dif);
293+
const int dif, const int sdif);
292294

293295
static inline struct sock *
294296
inet_lookup_established(struct net *net, struct inet_hashinfo *hashinfo,
@@ -297,28 +299,28 @@ static inline struct sock *
297299
const int dif)
298300
{
299301
return __inet_lookup_established(net, hashinfo, saddr, sport, daddr,
300-
ntohs(dport), dif);
302+
ntohs(dport), dif, 0);
301303
}
302304

303305
static inline struct sock *__inet_lookup(struct net *net,
304306
struct inet_hashinfo *hashinfo,
305307
struct sk_buff *skb, int doff,
306308
const __be32 saddr, const __be16 sport,
307309
const __be32 daddr, const __be16 dport,
308-
const int dif,
310+
const int dif, const int sdif,
309311
bool *refcounted)
310312
{
311313
u16 hnum = ntohs(dport);
312314
struct sock *sk;
313315

314316
sk = __inet_lookup_established(net, hashinfo, saddr, sport,
315-
daddr, hnum, dif);
317+
daddr, hnum, dif, sdif);
316318
*refcounted = true;
317319
if (sk)
318320
return sk;
319321
*refcounted = false;
320322
return __inet_lookup_listener(net, hashinfo, skb, doff, saddr,
321-
sport, daddr, hnum, dif);
323+
sport, daddr, hnum, dif, sdif);
322324
}
323325

324326
static inline struct sock *inet_lookup(struct net *net,
@@ -332,7 +334,7 @@ static inline struct sock *inet_lookup(struct net *net,
332334
bool refcounted;
333335

334336
sk = __inet_lookup(net, hashinfo, skb, doff, saddr, sport, daddr,
335-
dport, dif, &refcounted);
337+
dport, dif, 0, &refcounted);
336338

337339
if (sk && !refcounted && !refcount_inc_not_zero(&sk->sk_refcnt))
338340
sk = NULL;
@@ -344,6 +346,7 @@ static inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo,
344346
int doff,
345347
const __be16 sport,
346348
const __be16 dport,
349+
const int sdif,
347350
bool *refcounted)
348351
{
349352
struct sock *sk = skb_steal_sock(skb);
@@ -355,7 +358,7 @@ static inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo,
355358

356359
return __inet_lookup(dev_net(skb_dst(skb)->dev), hashinfo, skb,
357360
doff, iph->saddr, sport,
358-
iph->daddr, dport, inet_iif(skb),
361+
iph->daddr, dport, inet_iif(skb), sdif,
359362
refcounted);
360363
}
361364

include/net/ip.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,16 @@ struct ipcm_cookie {
7878
#define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
7979
#define PKTINFO_SKB_CB(skb) ((struct in_pktinfo *)((skb)->cb))
8080

81+
/* return enslaved device index if relevant */
82+
static inline int inet_sdif(struct sk_buff *skb)
83+
{
84+
#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
85+
if (skb && ipv4_l3mdev_skb(IPCB(skb)->flags))
86+
return IPCB(skb)->iif;
87+
#endif
88+
return 0;
89+
}
90+
8191
struct ip_ra_chain {
8292
struct ip_ra_chain __rcu *next;
8393
struct sock *sk;

include/net/raw.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ extern struct proto raw_prot;
2626
extern struct raw_hashinfo raw_v4_hashinfo;
2727
struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
2828
unsigned short num, __be32 raddr,
29-
__be32 laddr, int dif);
29+
__be32 laddr, int dif, int sdif);
3030

3131
int raw_abort(struct sock *sk, int err);
3232
void raw_icmp_error(struct sk_buff *, int, u32);

include/net/rawv6.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
extern struct raw_hashinfo raw_v6_hashinfo;
77
struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
88
unsigned short num, const struct in6_addr *loc_addr,
9-
const struct in6_addr *rmt_addr, int dif);
9+
const struct in6_addr *rmt_addr, int dif, int sdif);
1010

1111
int raw_abort(struct sock *sk, int err);
1212

include/net/tcp.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,16 @@ static inline int tcp_v6_iif(const struct sk_buff *skb)
827827

828828
return l3_slave ? skb->skb_iif : TCP_SKB_CB(skb)->header.h6.iif;
829829
}
830+
831+
/* TCP_SKB_CB reference means this can not be used from early demux */
832+
static inline int tcp_v6_sdif(const struct sk_buff *skb)
833+
{
834+
#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
835+
if (skb && ipv6_l3mdev_skb(TCP_SKB_CB(skb)->header.h6.flags))
836+
return TCP_SKB_CB(skb)->header.h6.iif;
837+
#endif
838+
return 0;
839+
}
830840
#endif
831841

832842
/* TCP_SKB_CB reference means this can not be used from early demux */
@@ -840,6 +850,16 @@ static inline bool inet_exact_dif_match(struct net *net, struct sk_buff *skb)
840850
return false;
841851
}
842852

853+
/* TCP_SKB_CB reference means this can not be used from early demux */
854+
static inline int tcp_v4_sdif(struct sk_buff *skb)
855+
{
856+
#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
857+
if (skb && ipv4_l3mdev_skb(TCP_SKB_CB(skb)->header.h4.flags))
858+
return TCP_SKB_CB(skb)->header.h4.iif;
859+
#endif
860+
return 0;
861+
}
862+
843863
/* Due to TSO, an SKB can be composed of multiple actual
844864
* packets. To keep these tracked properly, we use this.
845865
*/

include/net/udp.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
287287
struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
288288
__be32 daddr, __be16 dport, int dif);
289289
struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
290-
__be32 daddr, __be16 dport, int dif,
290+
__be32 daddr, __be16 dport, int dif, int sdif,
291291
struct udp_table *tbl, struct sk_buff *skb);
292292
struct sock *udp4_lib_lookup_skb(struct sk_buff *skb,
293293
__be16 sport, __be16 dport);
@@ -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/dccp/ipv4.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
256256
sk = __inet_lookup_established(net, &dccp_hashinfo,
257257
iph->daddr, dh->dccph_dport,
258258
iph->saddr, ntohs(dh->dccph_sport),
259-
inet_iif(skb));
259+
inet_iif(skb), 0);
260260
if (!sk) {
261261
__ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
262262
return;
@@ -804,7 +804,7 @@ static int dccp_v4_rcv(struct sk_buff *skb)
804804

805805
lookup:
806806
sk = __inet_lookup_skb(&dccp_hashinfo, skb, __dccp_hdr_len(dh),
807-
dh->dccph_sport, dh->dccph_dport, &refcounted);
807+
dh->dccph_sport, dh->dccph_dport, 0, &refcounted);
808808
if (!sk) {
809809
dccp_pr_debug("failed to look up flow ID in table and "
810810
"get corresponding socket\n");

net/dccp/ipv6.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
8989
sk = __inet6_lookup_established(net, &dccp_hashinfo,
9090
&hdr->daddr, dh->dccph_dport,
9191
&hdr->saddr, ntohs(dh->dccph_sport),
92-
inet6_iif(skb));
92+
inet6_iif(skb), 0);
9393

9494
if (!sk) {
9595
__ICMP6_INC_STATS(net, __in6_dev_get(skb->dev),
@@ -687,7 +687,7 @@ static int dccp_v6_rcv(struct sk_buff *skb)
687687
lookup:
688688
sk = __inet6_lookup_skb(&dccp_hashinfo, skb, __dccp_hdr_len(dh),
689689
dh->dccph_sport, dh->dccph_dport,
690-
inet6_iif(skb), &refcounted);
690+
inet6_iif(skb), 0, &refcounted);
691691
if (!sk) {
692692
dccp_pr_debug("failed to look up flow ID in table and "
693693
"get corresponding socket\n");

net/ipv4/igmp.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2549,7 +2549,8 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
25492549
/*
25502550
* check if a multicast source filter allows delivery for a given <src,dst,intf>
25512551
*/
2552-
int ip_mc_sf_allow(struct sock *sk, __be32 loc_addr, __be32 rmt_addr, int dif)
2552+
int ip_mc_sf_allow(struct sock *sk, __be32 loc_addr, __be32 rmt_addr,
2553+
int dif, int sdif)
25532554
{
25542555
struct inet_sock *inet = inet_sk(sk);
25552556
struct ip_mc_socklist *pmc;
@@ -2564,7 +2565,8 @@ int ip_mc_sf_allow(struct sock *sk, __be32 loc_addr, __be32 rmt_addr, int dif)
25642565
rcu_read_lock();
25652566
for_each_pmc_rcu(inet, pmc) {
25662567
if (pmc->multi.imr_multiaddr.s_addr == loc_addr &&
2567-
pmc->multi.imr_ifindex == dif)
2568+
(pmc->multi.imr_ifindex == dif ||
2569+
(sdif && pmc->multi.imr_ifindex == sdif)))
25682570
break;
25692571
}
25702572
ret = inet->mc_all;

0 commit comments

Comments
 (0)