bpf: Add ingress_ifindex to bpf_sk_lookup
authorMark Pashmfouroush <markpash@cloudflare.com>
Wed, 10 Nov 2021 11:10:15 +0000 (11:10 +0000)
committerAlexei Starovoitov <ast@kernel.org>
Thu, 11 Nov 2021 00:29:58 +0000 (16:29 -0800)
It may be helpful to have access to the ifindex during bpf socket
lookup. An example may be to scope certain socket lookup logic to
specific interfaces, i.e. an interface may be made exempt from custom
lookup code.

Add the ifindex of the arriving connection to the bpf_sk_lookup API.

Signed-off-by: Mark Pashmfouroush <markpash@cloudflare.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20211110111016.5670-2-markpash@cloudflare.com
include/linux/filter.h
include/uapi/linux/bpf.h
net/core/filter.c
net/ipv4/inet_hashtables.c
net/ipv4/udp.c
net/ipv6/inet6_hashtables.c
net/ipv6/udp.c
tools/include/uapi/linux/bpf.h

index 24b7ed2677afd26b0ffd1ce80f34469adc7129b0..b6a216eb217aceabdc24b20e9ebb6ad8b140f73c 100644 (file)
@@ -1374,6 +1374,7 @@ struct bpf_sk_lookup_kern {
                const struct in6_addr *daddr;
        } v6;
        struct sock     *selected_sk;
+       u32             ingress_ifindex;
        bool            no_reuseport;
 };
 
@@ -1436,7 +1437,7 @@ extern struct static_key_false bpf_sk_lookup_enabled;
 static inline bool bpf_sk_lookup_run_v4(struct net *net, int protocol,
                                        const __be32 saddr, const __be16 sport,
                                        const __be32 daddr, const u16 dport,
-                                       struct sock **psk)
+                                       const int ifindex, struct sock **psk)
 {
        struct bpf_prog_array *run_array;
        struct sock *selected_sk = NULL;
@@ -1452,6 +1453,7 @@ static inline bool bpf_sk_lookup_run_v4(struct net *net, int protocol,
                        .v4.daddr       = daddr,
                        .sport          = sport,
                        .dport          = dport,
+                       .ingress_ifindex        = ifindex,
                };
                u32 act;
 
@@ -1474,7 +1476,7 @@ static inline bool bpf_sk_lookup_run_v6(struct net *net, int protocol,
                                        const __be16 sport,
                                        const struct in6_addr *daddr,
                                        const u16 dport,
-                                       struct sock **psk)
+                                       const int ifindex, struct sock **psk)
 {
        struct bpf_prog_array *run_array;
        struct sock *selected_sk = NULL;
@@ -1490,6 +1492,7 @@ static inline bool bpf_sk_lookup_run_v6(struct net *net, int protocol,
                        .v6.daddr       = daddr,
                        .sport          = sport,
                        .dport          = dport,
+                       .ingress_ifindex        = ifindex,
                };
                u32 act;
 
index 509eee5f0393ddaebb817b79de6937cef866f999..6297eafdc40fa412e7f9e0a657cee24d5ba4c8e7 100644 (file)
@@ -6316,6 +6316,7 @@ struct bpf_sk_lookup {
        __u32 local_ip4;        /* Network byte order */
        __u32 local_ip6[4];     /* Network byte order */
        __u32 local_port;       /* Host byte order */
+       __u32 ingress_ifindex;          /* The arriving interface. Determined by inet_iif. */
 };
 
 /*
index 8e8d3b49c2976725cd37baa9cbecd2d4e6f66019..315a58466fc93dfea11347c98ee11e3e61e22754 100644 (file)
@@ -10491,6 +10491,7 @@ static bool sk_lookup_is_valid_access(int off, int size,
        case bpf_ctx_range_till(struct bpf_sk_lookup, local_ip6[0], local_ip6[3]):
        case bpf_ctx_range(struct bpf_sk_lookup, remote_port):
        case bpf_ctx_range(struct bpf_sk_lookup, local_port):
+       case bpf_ctx_range(struct bpf_sk_lookup, ingress_ifindex):
                bpf_ctx_record_field_size(info, sizeof(__u32));
                return bpf_ctx_narrow_access_ok(off, size, sizeof(__u32));
 
@@ -10580,6 +10581,12 @@ static u32 sk_lookup_convert_ctx_access(enum bpf_access_type type,
                                      bpf_target_off(struct bpf_sk_lookup_kern,
                                                     dport, 2, target_size));
                break;
+
+       case offsetof(struct bpf_sk_lookup, ingress_ifindex):
+               *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
+                                     bpf_target_off(struct bpf_sk_lookup_kern,
+                                                    ingress_ifindex, 4, target_size));
+               break;
        }
 
        return insn - insn_buf;
index 75737267746f85a5be82fbe04bbfb429914334c1..30ab717ff1b816506f47e4c14f47a7d12cfbdac4 100644 (file)
@@ -307,7 +307,7 @@ static inline struct sock *inet_lookup_run_bpf(struct net *net,
                                               struct inet_hashinfo *hashinfo,
                                               struct sk_buff *skb, int doff,
                                               __be32 saddr, __be16 sport,
-                                              __be32 daddr, u16 hnum)
+                                              __be32 daddr, u16 hnum, const int dif)
 {
        struct sock *sk, *reuse_sk;
        bool no_reuseport;
@@ -315,8 +315,8 @@ static inline struct sock *inet_lookup_run_bpf(struct net *net,
        if (hashinfo != &tcp_hashinfo)
                return NULL; /* only TCP is supported */
 
-       no_reuseport = bpf_sk_lookup_run_v4(net, IPPROTO_TCP,
-                                           saddr, sport, daddr, hnum, &sk);
+       no_reuseport = bpf_sk_lookup_run_v4(net, IPPROTO_TCP, saddr, sport,
+                                           daddr, hnum, dif, &sk);
        if (no_reuseport || IS_ERR_OR_NULL(sk))
                return sk;
 
@@ -340,7 +340,7 @@ struct sock *__inet_lookup_listener(struct net *net,
        /* Lookup redirect from BPF */
        if (static_branch_unlikely(&bpf_sk_lookup_enabled)) {
                result = inet_lookup_run_bpf(net, hashinfo, skb, doff,
-                                            saddr, sport, daddr, hnum);
+                                            saddr, sport, daddr, hnum, dif);
                if (result)
                        goto done;
        }
index 2fffcf2b54f3f304c6643d04d2c066d4ea6f5de4..5fceee3de65dd08b3ca301f878b4a4e06c8c4b7e 100644 (file)
@@ -460,7 +460,7 @@ static struct sock *udp4_lookup_run_bpf(struct net *net,
                                        struct udp_table *udptable,
                                        struct sk_buff *skb,
                                        __be32 saddr, __be16 sport,
-                                       __be32 daddr, u16 hnum)
+                                       __be32 daddr, u16 hnum, const int dif)
 {
        struct sock *sk, *reuse_sk;
        bool no_reuseport;
@@ -468,8 +468,8 @@ static struct sock *udp4_lookup_run_bpf(struct net *net,
        if (udptable != &udp_table)
                return NULL; /* only UDP is supported */
 
-       no_reuseport = bpf_sk_lookup_run_v4(net, IPPROTO_UDP,
-                                           saddr, sport, daddr, hnum, &sk);
+       no_reuseport = bpf_sk_lookup_run_v4(net, IPPROTO_UDP, saddr, sport,
+                                           daddr, hnum, dif, &sk);
        if (no_reuseport || IS_ERR_OR_NULL(sk))
                return sk;
 
@@ -505,7 +505,7 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
        /* Lookup redirect from BPF */
        if (static_branch_unlikely(&bpf_sk_lookup_enabled)) {
                sk = udp4_lookup_run_bpf(net, udptable, skb,
-                                        saddr, sport, daddr, hnum);
+                                        saddr, sport, daddr, hnum, dif);
                if (sk) {
                        result = sk;
                        goto done;
index 67c9114835c84864a3353c6f1c16853ea62a21c5..4514444e96c8dafed50d65172b6b23d9958c83ab 100644 (file)
@@ -165,7 +165,7 @@ static inline struct sock *inet6_lookup_run_bpf(struct net *net,
                                                const struct in6_addr *saddr,
                                                const __be16 sport,
                                                const struct in6_addr *daddr,
-                                               const u16 hnum)
+                                               const u16 hnum, const int dif)
 {
        struct sock *sk, *reuse_sk;
        bool no_reuseport;
@@ -173,8 +173,8 @@ static inline struct sock *inet6_lookup_run_bpf(struct net *net,
        if (hashinfo != &tcp_hashinfo)
                return NULL; /* only TCP is supported */
 
-       no_reuseport = bpf_sk_lookup_run_v6(net, IPPROTO_TCP,
-                                           saddr, sport, daddr, hnum, &sk);
+       no_reuseport = bpf_sk_lookup_run_v6(net, IPPROTO_TCP, saddr, sport,
+                                           daddr, hnum, dif, &sk);
        if (no_reuseport || IS_ERR_OR_NULL(sk))
                return sk;
 
@@ -198,7 +198,7 @@ struct sock *inet6_lookup_listener(struct net *net,
        /* Lookup redirect from BPF */
        if (static_branch_unlikely(&bpf_sk_lookup_enabled)) {
                result = inet6_lookup_run_bpf(net, hashinfo, skb, doff,
-                                             saddr, sport, daddr, hnum);
+                                             saddr, sport, daddr, hnum, dif);
                if (result)
                        goto done;
        }
index 12c12619ee357d4010045e1802c37f13a10d770c..ea4ea525f94abe2c158e302f9e1f76889fc2d17f 100644 (file)
@@ -195,7 +195,7 @@ static inline struct sock *udp6_lookup_run_bpf(struct net *net,
                                               const struct in6_addr *saddr,
                                               __be16 sport,
                                               const struct in6_addr *daddr,
-                                              u16 hnum)
+                                              u16 hnum, const int dif)
 {
        struct sock *sk, *reuse_sk;
        bool no_reuseport;
@@ -203,8 +203,8 @@ static inline struct sock *udp6_lookup_run_bpf(struct net *net,
        if (udptable != &udp_table)
                return NULL; /* only UDP is supported */
 
-       no_reuseport = bpf_sk_lookup_run_v6(net, IPPROTO_UDP,
-                                           saddr, sport, daddr, hnum, &sk);
+       no_reuseport = bpf_sk_lookup_run_v6(net, IPPROTO_UDP, saddr, sport,
+                                           daddr, hnum, dif, &sk);
        if (no_reuseport || IS_ERR_OR_NULL(sk))
                return sk;
 
@@ -240,7 +240,7 @@ struct sock *__udp6_lib_lookup(struct net *net,
        /* Lookup redirect from BPF */
        if (static_branch_unlikely(&bpf_sk_lookup_enabled)) {
                sk = udp6_lookup_run_bpf(net, udptable, skb,
-                                        saddr, sport, daddr, hnum);
+                                        saddr, sport, daddr, hnum, dif);
                if (sk) {
                        result = sk;
                        goto done;
index 509eee5f0393ddaebb817b79de6937cef866f999..6297eafdc40fa412e7f9e0a657cee24d5ba4c8e7 100644 (file)
@@ -6316,6 +6316,7 @@ struct bpf_sk_lookup {
        __u32 local_ip4;        /* Network byte order */
        __u32 local_ip6[4];     /* Network byte order */
        __u32 local_port;       /* Host byte order */
+       __u32 ingress_ifindex;          /* The arriving interface. Determined by inet_iif. */
 };
 
 /*