Message ID | 1482264424-15439-2-git-send-email-jbacik@fb.com |
---|---|
State | RFC, archived |
Delegated to: | David Miller |
Headers | show |
On Tue, 2016-12-20 at 15:07 -0500, Josef Bacik wrote: > The only difference between inet6_csk_bind_conflict and inet_csk_bind_conflict > is how they check the rcv_saddr. Since we want to be able to check the saddr in > other places just drop the protocol specific ->bind_conflict and replace it with > ->rcv_saddr_equal, then make inet_csk_bind_conflict the one true bind conflict > function. > > Signed-off-by: Josef Bacik <jbacik@fb.com> > > --- > include/net/inet6_connection_sock.h | 5 ----- > include/net/inet_connection_sock.h | 9 +++------ > net/dccp/ipv4.c | 3 ++- > net/dccp/ipv6.c | 2 +- > net/ipv4/inet_connection_sock.c | 22 +++++++------------- > net/ipv4/tcp_ipv4.c | 3 ++- > net/ipv4/udp.c | 1 + > net/ipv6/inet6_connection_sock.c | 40 ------------------------------------- > net/ipv6/tcp_ipv6.c | 4 ++-- > 9 files changed, 18 insertions(+), 71 deletions(-) > > diff --git a/include/net/inet6_connection_sock.h b/include/net/inet6_connection_sock.h > index 3212b39..8ec87b6 100644 > --- a/include/net/inet6_connection_sock.h > +++ b/include/net/inet6_connection_sock.h > @@ -15,16 +15,11 @@ > > #include <linux/types.h> > > -struct inet_bind_bucket; > struct request_sock; > struct sk_buff; > struct sock; > struct sockaddr; > > -int inet6_csk_bind_conflict(const struct sock *sk, > - const struct inet_bind_bucket *tb, bool relax, > - bool soreuseport_ok); > - > struct dst_entry *inet6_csk_route_req(const struct sock *sk, struct flowi6 *fl6, > const struct request_sock *req, u8 proto); > > diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h > index ec0479a..9cd43c5 100644 > --- a/include/net/inet_connection_sock.h > +++ b/include/net/inet_connection_sock.h > @@ -62,9 +62,9 @@ struct inet_connection_sock_af_ops { > char __user *optval, int __user *optlen); > #endif > void (*addr2sockaddr)(struct sock *sk, struct sockaddr *); > - int (*bind_conflict)(const struct sock *sk, > - const struct inet_bind_bucket *tb, > - bool relax, bool soreuseport_ok); > + int (*rcv_saddr_equal)(const struct sock *sk1, > + const struct sock *sk2, > + bool match_wildcard); > void (*mtu_reduced)(struct sock *sk); > }; > > The patch looks as a nice code cleanup already! Have you looked if we can simply have one rcv_saddr_equal for both ipv4 and ipv6 that e.g. uses sk->sk_family instead of function pointers? This could give us even more possibilities to remove some indirect functions calls and thus might relieve some cycles? Thanks, Hannes
On Wed, Dec 21, 2016 at 10:06 AM, Hannes Frederic Sowa <hannes@stressinduktion.org> wrote: > On Tue, 2016-12-20 at 15:07 -0500, Josef Bacik wrote: >> The only difference between inet6_csk_bind_conflict and >> inet_csk_bind_conflict >> is how they check the rcv_saddr. Since we want to be able to check >> the saddr in >> other places just drop the protocol specific ->bind_conflict and >> replace it with >> ->rcv_saddr_equal, then make inet_csk_bind_conflict the one true >> bind conflict >> function. >> >> Signed-off-by: Josef Bacik <jbacik@fb.com> >> > > > >> --- >> include/net/inet6_connection_sock.h | 5 ----- >> include/net/inet_connection_sock.h | 9 +++------ >> net/dccp/ipv4.c | 3 ++- >> net/dccp/ipv6.c | 2 +- >> net/ipv4/inet_connection_sock.c | 22 +++++++------------- >> net/ipv4/tcp_ipv4.c | 3 ++- >> net/ipv4/udp.c | 1 + >> net/ipv6/inet6_connection_sock.c | 40 >> ------------------------------------- >> net/ipv6/tcp_ipv6.c | 4 ++-- >> 9 files changed, 18 insertions(+), 71 deletions(-) >> >> diff --git a/include/net/inet6_connection_sock.h >> b/include/net/inet6_connection_sock.h >> index 3212b39..8ec87b6 100644 >> --- a/include/net/inet6_connection_sock.h >> +++ b/include/net/inet6_connection_sock.h >> @@ -15,16 +15,11 @@ >> >> #include <linux/types.h> >> >> -struct inet_bind_bucket; >> struct request_sock; >> struct sk_buff; >> struct sock; >> struct sockaddr; >> >> -int inet6_csk_bind_conflict(const struct sock *sk, >> - const struct inet_bind_bucket *tb, bool relax, >> - bool soreuseport_ok); >> - >> struct dst_entry *inet6_csk_route_req(const struct sock *sk, >> struct flowi6 *fl6, >> const struct request_sock *req, u8 proto); >> >> diff --git a/include/net/inet_connection_sock.h >> b/include/net/inet_connection_sock.h >> index ec0479a..9cd43c5 100644 >> --- a/include/net/inet_connection_sock.h >> +++ b/include/net/inet_connection_sock.h >> @@ -62,9 +62,9 @@ struct inet_connection_sock_af_ops { >> char __user *optval, int __user *optlen); >> #endif >> void (*addr2sockaddr)(struct sock *sk, struct sockaddr *); >> - int (*bind_conflict)(const struct sock *sk, >> - const struct inet_bind_bucket *tb, >> - bool relax, bool soreuseport_ok); >> + int (*rcv_saddr_equal)(const struct sock *sk1, >> + const struct sock *sk2, >> + bool match_wildcard); >> void (*mtu_reduced)(struct sock *sk); >> }; >> >> > > The patch looks as a nice code cleanup already! > > Have you looked if we can simply have one rcv_saddr_equal for both > ipv4 > and ipv6 that e.g. uses sk->sk_family instead of function pointers? > This could give us even more possibilities to remove some indirect > functions calls and thus might relieve some cycles? I was going to do that but I'm not familiar enough with how sockets work to be comfortable. My main concern is we have the ipv6_only() check on a socket, which seems to indicate to me that you can have a socket that can do both ipv4/ipv6, so what if we're specifically going through the ipv6 code, but we aren't ipv6_only() and we end up doing the ipv4 address compare when we really need to do the ipv6 address compare? If this can't happen (and honestly as I type it out it sounds crazier than it did in my head) then yeah I'll totally do that as well and we can just have a global function without the protocol specific callbacks, but I need you or somebody to tell me I'm crazy and that it would be ok to have it all in one function. Thanks, Josef
On Tue, 2016-12-20 at 15:07 -0500, Josef Bacik wrote: > --- a/net/dccp/ipv6.c > +++ b/net/dccp/ipv6.c > @@ -926,7 +926,7 @@ static const struct inet_connection_sock_af_ops dccp_ipv6_af_ops = { > .getsockopt = ipv6_getsockopt, > .addr2sockaddr = inet6_csk_addr2sockaddr, > .sockaddr_len = sizeof(struct sockaddr_in6), > - .bind_conflict = inet6_csk_bind_conflict, > + .rcv_saddr_equal = ipv6_rcv_saddr_equal, > #ifdef CONFIG_COMPAT > .compat_setsockopt = compat_ipv6_setsockopt, > .compat_getsockopt = compat_ipv6_getsockopt, > Btw, small nit, you forgot the corresponding changes in dccp_ipv6_mapped, thus causing this compiler error: net/dccp/ipv6.c:961:2: error: unknown field ‘bind_conflict’ specified in initializer .bind_conflict = inet6_csk_bind_conflict, ^ net/dccp/ipv6.c:961:22: error: ‘inet6_csk_bind_conflict’ undeclared here (not in a function) .bind_conflict = inet6_csk_bind_conflict, ^~~~~~~~~~~~~~~~~~~~~~~ scripts/Makefile.build:293: recipe for target 'net/dccp/ipv6.o' failed Bye, Hannes
On Wed, Dec 21, 2016 at 10:23 AM, Hannes Frederic Sowa <hannes@stressinduktion.org> wrote: > On Tue, 2016-12-20 at 15:07 -0500, Josef Bacik wrote: >> --- a/net/dccp/ipv6.c >> +++ b/net/dccp/ipv6.c >> @@ -926,7 +926,7 @@ static const struct inet_connection_sock_af_ops >> dccp_ipv6_af_ops = { >> .getsockopt = ipv6_getsockopt, >> .addr2sockaddr = inet6_csk_addr2sockaddr, >> .sockaddr_len = sizeof(struct sockaddr_in6), >> - .bind_conflict = inet6_csk_bind_conflict, >> + .rcv_saddr_equal = ipv6_rcv_saddr_equal, >> #ifdef CONFIG_COMPAT >> .compat_setsockopt = compat_ipv6_setsockopt, >> .compat_getsockopt = compat_ipv6_getsockopt, >> > > Btw, small nit, you forgot the corresponding changes in > dccp_ipv6_mapped, thus causing this compiler error: > > net/dccp/ipv6.c:961:2: error: unknown field ‘bind_conflict’ > specified in initializer > .bind_conflict = inet6_csk_bind_conflict, > ^ > net/dccp/ipv6.c:961:22: error: ‘inet6_csk_bind_conflict’ > undeclared here (not in a function) > .bind_conflict = inet6_csk_bind_conflict, > ^~~~~~~~~~~~~~~~~~~~~~~ > scripts/Makefile.build:293: recipe for target 'net/dccp/ipv6.o' failed Yeah kbuild caught that yesterday and I have it fixed up in my git tree already, thanks, Josef
From: Josef Bacik <jbacik@fb.com> Date: Tue, 20 Dec 2016 15:07:00 -0500 > The only difference between inet6_csk_bind_conflict and inet_csk_bind_conflict > is how they check the rcv_saddr. Since we want to be able to check the saddr in > other places just drop the protocol specific ->bind_conflict and replace it with > ->rcv_saddr_equal, then make inet_csk_bind_conflict the one true bind conflict > function. > > Signed-off-by: Josef Bacik <jbacik@fb.com> This may be a nice cleanup and all, but realize that if we do actually have to traverse a lot of sockets this code has become significantly slower. We now have to execute a hard to predict indirect call for every socket we process on the list. This is almost certainly why we had two seperate functions expanded rather than having an AF-specific helper execute in the inner loop of a generic function.
On 21.12.2016 16:16, Josef Bacik wrote: > On Wed, Dec 21, 2016 at 10:06 AM, Hannes Frederic Sowa > <hannes@stressinduktion.org> wrote: >> On Tue, 2016-12-20 at 15:07 -0500, Josef Bacik wrote: >>> The only difference between inet6_csk_bind_conflict and >>> inet_csk_bind_conflict >>> is how they check the rcv_saddr. Since we want to be able to check >>> the saddr in >>> other places just drop the protocol specific ->bind_conflict and >>> replace it with >>> ->rcv_saddr_equal, then make inet_csk_bind_conflict the one true >>> bind conflict >>> function. >>> >>> Signed-off-by: Josef Bacik <jbacik@fb.com> >>> >> >> >> >>> --- >>> include/net/inet6_connection_sock.h | 5 ----- >>> include/net/inet_connection_sock.h | 9 +++------ >>> net/dccp/ipv4.c | 3 ++- >>> net/dccp/ipv6.c | 2 +- >>> net/ipv4/inet_connection_sock.c | 22 +++++++------------- >>> net/ipv4/tcp_ipv4.c | 3 ++- >>> net/ipv4/udp.c | 1 + >>> net/ipv6/inet6_connection_sock.c | 40 >>> ------------------------------------- >>> net/ipv6/tcp_ipv6.c | 4 ++-- >>> 9 files changed, 18 insertions(+), 71 deletions(-) >>> >>> diff --git a/include/net/inet6_connection_sock.h >>> b/include/net/inet6_connection_sock.h >>> index 3212b39..8ec87b6 100644 >>> --- a/include/net/inet6_connection_sock.h >>> +++ b/include/net/inet6_connection_sock.h >>> @@ -15,16 +15,11 @@ >>> >>> #include <linux/types.h> >>> >>> -struct inet_bind_bucket; >>> struct request_sock; >>> struct sk_buff; >>> struct sock; >>> struct sockaddr; >>> >>> -int inet6_csk_bind_conflict(const struct sock *sk, >>> - const struct inet_bind_bucket *tb, bool relax, >>> - bool soreuseport_ok); >>> - >>> struct dst_entry *inet6_csk_route_req(const struct sock *sk, struct >>> flowi6 *fl6, >>> const struct request_sock *req, u8 proto); >>> >>> diff --git a/include/net/inet_connection_sock.h >>> b/include/net/inet_connection_sock.h >>> index ec0479a..9cd43c5 100644 >>> --- a/include/net/inet_connection_sock.h >>> +++ b/include/net/inet_connection_sock.h >>> @@ -62,9 +62,9 @@ struct inet_connection_sock_af_ops { >>> char __user *optval, int __user *optlen); >>> #endif >>> void (*addr2sockaddr)(struct sock *sk, struct sockaddr *); >>> - int (*bind_conflict)(const struct sock *sk, >>> - const struct inet_bind_bucket *tb, >>> - bool relax, bool soreuseport_ok); >>> + int (*rcv_saddr_equal)(const struct sock *sk1, >>> + const struct sock *sk2, >>> + bool match_wildcard); >>> void (*mtu_reduced)(struct sock *sk); >>> }; >>> >>> >> >> The patch looks as a nice code cleanup already! >> >> Have you looked if we can simply have one rcv_saddr_equal for both ipv4 >> and ipv6 that e.g. uses sk->sk_family instead of function pointers? >> This could give us even more possibilities to remove some indirect >> functions calls and thus might relieve some cycles? > > I was going to do that but I'm not familiar enough with how sockets work > to be comfortable. My main concern is we have the ipv6_only() check on > a socket, which seems to indicate to me that you can have a socket that > can do both ipv4/ipv6, so what if we're specifically going through the > ipv6 code, but we aren't ipv6_only() and we end up doing the ipv4 > address compare when we really need to do the ipv6 address compare? If > this can't happen (and honestly as I type it out it sounds crazier than > it did in my head) then yeah I'll totally do that as well and we can > just have a global function without the protocol specific callbacks, but > I need you or somebody to tell me I'm crazy and that it would be ok to > have it all in one function. Thanks, IPv6 sockets can do IPv4 via mapped addresses. The other way around doesn't work, there are no IPv4 sockets that can speak IPv6. The ipv6_only flags in IPv4 sockets should always stay 0 but they need to be evaluated from there side for possible port conflicts. My idea is to use sk->sk_family, which is in sync with icsk->icsk_af_ops, which you use for the function pointer lookup, to switch between those functions. Looking through a lot of callback, I don't see this assumption violated so far. This would also solve the problem which David described, your search would be free of those indirect jumps. Bye, Hannes
diff --git a/include/net/inet6_connection_sock.h b/include/net/inet6_connection_sock.h index 3212b39..8ec87b6 100644 --- a/include/net/inet6_connection_sock.h +++ b/include/net/inet6_connection_sock.h @@ -15,16 +15,11 @@ #include <linux/types.h> -struct inet_bind_bucket; struct request_sock; struct sk_buff; struct sock; struct sockaddr; -int inet6_csk_bind_conflict(const struct sock *sk, - const struct inet_bind_bucket *tb, bool relax, - bool soreuseport_ok); - struct dst_entry *inet6_csk_route_req(const struct sock *sk, struct flowi6 *fl6, const struct request_sock *req, u8 proto); diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index ec0479a..9cd43c5 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -62,9 +62,9 @@ struct inet_connection_sock_af_ops { char __user *optval, int __user *optlen); #endif void (*addr2sockaddr)(struct sock *sk, struct sockaddr *); - int (*bind_conflict)(const struct sock *sk, - const struct inet_bind_bucket *tb, - bool relax, bool soreuseport_ok); + int (*rcv_saddr_equal)(const struct sock *sk1, + const struct sock *sk2, + bool match_wildcard); void (*mtu_reduced)(struct sock *sk); }; @@ -261,9 +261,6 @@ inet_csk_rto_backoff(const struct inet_connection_sock *icsk, struct sock *inet_csk_accept(struct sock *sk, int flags, int *err); -int inet_csk_bind_conflict(const struct sock *sk, - const struct inet_bind_bucket *tb, bool relax, - bool soreuseport_ok); int inet_csk_get_port(struct sock *sk, unsigned short snum); struct dst_entry *inet_csk_route_req(const struct sock *sk, struct flowi4 *fl4, diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 9c67a96..1931324 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -17,6 +17,7 @@ #include <linux/skbuff.h> #include <linux/random.h> +#include <net/addrconf.h> #include <net/icmp.h> #include <net/inet_common.h> #include <net/inet_hashtables.h> @@ -901,7 +902,7 @@ static const struct inet_connection_sock_af_ops dccp_ipv4_af_ops = { .getsockopt = ip_getsockopt, .addr2sockaddr = inet_csk_addr2sockaddr, .sockaddr_len = sizeof(struct sockaddr_in), - .bind_conflict = inet_csk_bind_conflict, + .rcv_saddr_equal = ipv4_rcv_saddr_equal, #ifdef CONFIG_COMPAT .compat_setsockopt = compat_ip_setsockopt, .compat_getsockopt = compat_ip_getsockopt, diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 4663a01..45242b8 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -926,7 +926,7 @@ static const struct inet_connection_sock_af_ops dccp_ipv6_af_ops = { .getsockopt = ipv6_getsockopt, .addr2sockaddr = inet6_csk_addr2sockaddr, .sockaddr_len = sizeof(struct sockaddr_in6), - .bind_conflict = inet6_csk_bind_conflict, + .rcv_saddr_equal = ipv6_rcv_saddr_equal, #ifdef CONFIG_COMPAT .compat_setsockopt = compat_ipv6_setsockopt, .compat_getsockopt = compat_ipv6_getsockopt, diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 5f44fa1..74f6a57 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -44,9 +44,9 @@ void inet_get_local_port_range(struct net *net, int *low, int *high) } EXPORT_SYMBOL(inet_get_local_port_range); -int inet_csk_bind_conflict(const struct sock *sk, - const struct inet_bind_bucket *tb, bool relax, - bool reuseport_ok) +static int inet_csk_bind_conflict(const struct sock *sk, + const struct inet_bind_bucket *tb, + bool relax, bool reuseport_ok) { struct sock *sk2; bool reuse = sk->sk_reuse; @@ -62,7 +62,6 @@ int inet_csk_bind_conflict(const struct sock *sk, sk_for_each_bound(sk2, &tb->owners) { if (sk != sk2 && - !inet_v6_ipv6only(sk2) && (!sk->sk_bound_dev_if || !sk2->sk_bound_dev_if || sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) { @@ -72,23 +71,18 @@ int inet_csk_bind_conflict(const struct sock *sk, rcu_access_pointer(sk->sk_reuseport_cb) || (sk2->sk_state != TCP_TIME_WAIT && !uid_eq(uid, sock_i_uid(sk2))))) { - - if (!sk2->sk_rcv_saddr || !sk->sk_rcv_saddr || - sk2->sk_rcv_saddr == sk->sk_rcv_saddr) + if (inet_csk(sk)->icsk_af_ops->rcv_saddr_equal(sk, sk2, true)) break; } if (!relax && reuse && sk2->sk_reuse && sk2->sk_state != TCP_LISTEN) { - - if (!sk2->sk_rcv_saddr || !sk->sk_rcv_saddr || - sk2->sk_rcv_saddr == sk->sk_rcv_saddr) + if (inet_csk(sk)->icsk_af_ops->rcv_saddr_equal(sk, sk2, true)) break; } } } return sk2 != NULL; } -EXPORT_SYMBOL_GPL(inet_csk_bind_conflict); /* Obtain a reference to a local port for the given sock, * if snum is zero it means select any available local port. @@ -167,8 +161,7 @@ other_parity_scan: smallest_size = tb->num_owners; smallest_port = port; } - if (!inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb, false, - reuseport_ok)) + if (!inet_csk_bind_conflict(sk, tb, false, reuseport_ok)) goto tb_found; goto next_port; } @@ -209,8 +202,7 @@ tb_found: sk->sk_reuseport && uid_eq(tb->fastuid, uid))) && smallest_size == -1) goto success; - if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb, true, - reuseport_ok)) { + if (inet_csk_bind_conflict(sk, tb, true, reuseport_ok)) { if ((reuse || (tb->fastreuseport > 0 && sk->sk_reuseport && diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 029708f..7608012 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -63,6 +63,7 @@ #include <linux/times.h> #include <linux/slab.h> +#include <net/addrconf.h> #include <net/net_namespace.h> #include <net/icmp.h> #include <net/inet_hashtables.h> @@ -1781,7 +1782,7 @@ const struct inet_connection_sock_af_ops ipv4_specific = { .getsockopt = ip_getsockopt, .addr2sockaddr = inet_csk_addr2sockaddr, .sockaddr_len = sizeof(struct sockaddr_in), - .bind_conflict = inet_csk_bind_conflict, + .rcv_saddr_equal = ipv4_rcv_saddr_equal, #ifdef CONFIG_COMPAT .compat_setsockopt = compat_ip_setsockopt, .compat_getsockopt = compat_ip_getsockopt, diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 2a70c05..6089ea8 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -374,6 +374,7 @@ int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2, } return 0; } +EXPORT_SYMBOL(ipv4_rcv_saddr_equal); static u32 udp4_portaddr_hash(const struct net *net, __be32 saddr, unsigned int port) diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 71939a2..7538715 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c @@ -28,46 +28,6 @@ #include <net/inet6_connection_sock.h> #include <net/sock_reuseport.h> -int inet6_csk_bind_conflict(const struct sock *sk, - const struct inet_bind_bucket *tb, bool relax, - bool reuseport_ok) -{ - const struct sock *sk2; - bool reuse = !!sk->sk_reuse; - bool reuseport = !!sk->sk_reuseport && reuseport_ok; - kuid_t uid = sock_i_uid((struct sock *)sk); - - /* We must walk the whole port owner list in this case. -DaveM */ - /* - * See comment in inet_csk_bind_conflict about sock lookup - * vs net namespaces issues. - */ - sk_for_each_bound(sk2, &tb->owners) { - if (sk != sk2 && - (!sk->sk_bound_dev_if || - !sk2->sk_bound_dev_if || - sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) { - if ((!reuse || !sk2->sk_reuse || - sk2->sk_state == TCP_LISTEN) && - (!reuseport || !sk2->sk_reuseport || - rcu_access_pointer(sk->sk_reuseport_cb) || - (sk2->sk_state != TCP_TIME_WAIT && - !uid_eq(uid, - sock_i_uid((struct sock *)sk2))))) { - if (ipv6_rcv_saddr_equal(sk, sk2, true)) - break; - } - if (!relax && reuse && sk2->sk_reuse && - sk2->sk_state != TCP_LISTEN && - ipv6_rcv_saddr_equal(sk, sk2, true)) - break; - } - } - - return sk2 != NULL; -} -EXPORT_SYMBOL_GPL(inet6_csk_bind_conflict); - struct dst_entry *inet6_csk_route_req(const struct sock *sk, struct flowi6 *fl6, const struct request_sock *req, diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index bee59a6..2f40b98 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1603,7 +1603,7 @@ static const struct inet_connection_sock_af_ops ipv6_specific = { .getsockopt = ipv6_getsockopt, .addr2sockaddr = inet6_csk_addr2sockaddr, .sockaddr_len = sizeof(struct sockaddr_in6), - .bind_conflict = inet6_csk_bind_conflict, + .rcv_saddr_equal = ipv6_rcv_saddr_equal, #ifdef CONFIG_COMPAT .compat_setsockopt = compat_ipv6_setsockopt, .compat_getsockopt = compat_ipv6_getsockopt, @@ -1634,7 +1634,7 @@ static const struct inet_connection_sock_af_ops ipv6_mapped = { .getsockopt = ipv6_getsockopt, .addr2sockaddr = inet6_csk_addr2sockaddr, .sockaddr_len = sizeof(struct sockaddr_in6), - .bind_conflict = inet6_csk_bind_conflict, + .rcv_saddr_equal = ipv6_rcv_saddr_equal, #ifdef CONFIG_COMPAT .compat_setsockopt = compat_ipv6_setsockopt, .compat_getsockopt = compat_ipv6_getsockopt,
The only difference between inet6_csk_bind_conflict and inet_csk_bind_conflict is how they check the rcv_saddr. Since we want to be able to check the saddr in other places just drop the protocol specific ->bind_conflict and replace it with ->rcv_saddr_equal, then make inet_csk_bind_conflict the one true bind conflict function. Signed-off-by: Josef Bacik <jbacik@fb.com> --- include/net/inet6_connection_sock.h | 5 ----- include/net/inet_connection_sock.h | 9 +++------ net/dccp/ipv4.c | 3 ++- net/dccp/ipv6.c | 2 +- net/ipv4/inet_connection_sock.c | 22 +++++++------------- net/ipv4/tcp_ipv4.c | 3 ++- net/ipv4/udp.c | 1 + net/ipv6/inet6_connection_sock.c | 40 ------------------------------------- net/ipv6/tcp_ipv6.c | 4 ++-- 9 files changed, 18 insertions(+), 71 deletions(-)