Re: [PATCH net-next 2/3] sctp: add sock_reuseport for the sock in __sctp_hash_endpoint
On Mon, Oct 22, 2018 at 11:15 PM Marcelo Ricardo Leitner wrote: > > On Sun, Oct 21, 2018 at 12:43:37PM +0800, Xin Long wrote: > > This is a part of sk_reuseport support for sctp. It defines a helper > > sctp_bind_addrs_check() to check if the bind_addrs in two socks are > > matched. It will add sock_reuseport if they are completely matched, > > and return err if they are partly matched, and alloc sock_reuseport > > if all socks are not matched at all. > > > > It will work until sk_reuseport support is added in > > sctp_get_port_local() in the next patch. > > > > Signed-off-by: Xin Long > > --- > > include/net/sctp/sctp.h| 2 +- > > include/net/sctp/structs.h | 2 ++ > > net/core/sock_reuseport.c | 1 + > > net/sctp/bind_addr.c | 28 ++ > > net/sctp/input.c | 60 > > +++--- > > net/sctp/socket.c | 3 +-- > > 6 files changed, 85 insertions(+), 11 deletions(-) > > > > diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h > > index 8c2caa3..b8cd58d 100644 > > --- a/include/net/sctp/sctp.h > > +++ b/include/net/sctp/sctp.h > > @@ -152,7 +152,7 @@ int sctp_primitive_RECONF(struct net *net, struct > > sctp_association *asoc, > > */ > > int sctp_rcv(struct sk_buff *skb); > > void sctp_v4_err(struct sk_buff *skb, u32 info); > > -void sctp_hash_endpoint(struct sctp_endpoint *); > > +int sctp_hash_endpoint(struct sctp_endpoint *ep); > > void sctp_unhash_endpoint(struct sctp_endpoint *); > > struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *, > >struct sctphdr *, struct sctp_association **, > > diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h > > index a11f937..15d017f 100644 > > --- a/include/net/sctp/structs.h > > +++ b/include/net/sctp/structs.h > > @@ -1190,6 +1190,8 @@ int sctp_bind_addr_conflict(struct sctp_bind_addr *, > > const union sctp_addr *, > >struct sctp_sock *, struct sctp_sock *); > > int sctp_bind_addr_state(const struct sctp_bind_addr *bp, > >const union sctp_addr *addr); > > +int sctp_bind_addrs_check(struct sctp_sock *sp, > > + struct sctp_sock *sp2, int cnt2); > > union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr*bp, > > const union sctp_addr *addrs, > > int addrcnt, > > diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c > > index ba5cba5..d8fe3e5 100644 > > --- a/net/core/sock_reuseport.c > > +++ b/net/core/sock_reuseport.c > > @@ -187,6 +187,7 @@ int reuseport_add_sock(struct sock *sk, struct sock > > *sk2, bool bind_inany) > > call_rcu(_reuse->rcu, reuseport_free_rcu); > > return 0; > > } > > +EXPORT_SYMBOL(reuseport_add_sock); > > > > void reuseport_detach_sock(struct sock *sk) > > { > > diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c > > index 7df3704..78d0d93 100644 > > --- a/net/sctp/bind_addr.c > > +++ b/net/sctp/bind_addr.c > > @@ -337,6 +337,34 @@ int sctp_bind_addr_match(struct sctp_bind_addr *bp, > > return match; > > } > > > > +int sctp_bind_addrs_check(struct sctp_sock *sp, > > + struct sctp_sock *sp2, int cnt2) > > +{ > > + struct sctp_bind_addr *bp2 = >ep->base.bind_addr; > > + struct sctp_bind_addr *bp = >ep->base.bind_addr; > > + struct sctp_sockaddr_entry *laddr, *laddr2; > > + bool exist = false; > > + int cnt = 0; > > + > > + rcu_read_lock(); > > + list_for_each_entry_rcu(laddr, >address_list, list) { > > + list_for_each_entry_rcu(laddr2, >address_list, list) { > > + if (sp->pf->af->cmp_addr(>a, >a) && > > + laddr->valid == laddr2->valid) { > > I think by here in the normal run laddr2->valid will always be true, > but as is it gives the impression that it accepts 0 == 0 too, which > would be bad. May be on a fast BINDX_REM/BINDX_ADD it could trigger > laddr2->valid = 0 in there, not sure. > > Anyway, may be '... laddr->valid && laddr2->valid' instead or you > really want to allow the 0 == 0 case? > will improve it in v2. thanks. > > + exist = true; > > + goto next; > > + } > > + } > > + cnt = 0; > > + break; > > +next: > > + cnt++; > > + } > > + rcu_read_unlock(); > > + > > + return (cnt == cnt2) ? 0 : (exist ? -EEXIST : 1); > > +} > > + > > /* Does the address 'addr' conflict with any addresses in > > * the bp. > > */ > > diff --git a/net/sctp/input.c b/net/sctp/input.c > > index 60ede89..6bfeb10 100644 > > --- a/net/sctp/input.c > > +++ b/net/sctp/input.c > > @@ -723,43 +723,87 @@ static int sctp_rcv_ootb(struct sk_buff *skb) > > } > > > > /* Insert endpoint into the hash table. */ > > -static void
Re: [PATCH net-next 2/3] sctp: add sock_reuseport for the sock in __sctp_hash_endpoint
On Sun, Oct 21, 2018 at 12:43:37PM +0800, Xin Long wrote: > This is a part of sk_reuseport support for sctp. It defines a helper > sctp_bind_addrs_check() to check if the bind_addrs in two socks are > matched. It will add sock_reuseport if they are completely matched, > and return err if they are partly matched, and alloc sock_reuseport > if all socks are not matched at all. > > It will work until sk_reuseport support is added in > sctp_get_port_local() in the next patch. > > Signed-off-by: Xin Long > --- > include/net/sctp/sctp.h| 2 +- > include/net/sctp/structs.h | 2 ++ > net/core/sock_reuseport.c | 1 + > net/sctp/bind_addr.c | 28 ++ > net/sctp/input.c | 60 > +++--- > net/sctp/socket.c | 3 +-- > 6 files changed, 85 insertions(+), 11 deletions(-) > > diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h > index 8c2caa3..b8cd58d 100644 > --- a/include/net/sctp/sctp.h > +++ b/include/net/sctp/sctp.h > @@ -152,7 +152,7 @@ int sctp_primitive_RECONF(struct net *net, struct > sctp_association *asoc, > */ > int sctp_rcv(struct sk_buff *skb); > void sctp_v4_err(struct sk_buff *skb, u32 info); > -void sctp_hash_endpoint(struct sctp_endpoint *); > +int sctp_hash_endpoint(struct sctp_endpoint *ep); > void sctp_unhash_endpoint(struct sctp_endpoint *); > struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *, >struct sctphdr *, struct sctp_association **, > diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h > index a11f937..15d017f 100644 > --- a/include/net/sctp/structs.h > +++ b/include/net/sctp/structs.h > @@ -1190,6 +1190,8 @@ int sctp_bind_addr_conflict(struct sctp_bind_addr *, > const union sctp_addr *, >struct sctp_sock *, struct sctp_sock *); > int sctp_bind_addr_state(const struct sctp_bind_addr *bp, >const union sctp_addr *addr); > +int sctp_bind_addrs_check(struct sctp_sock *sp, > + struct sctp_sock *sp2, int cnt2); > union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr*bp, > const union sctp_addr *addrs, > int addrcnt, > diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c > index ba5cba5..d8fe3e5 100644 > --- a/net/core/sock_reuseport.c > +++ b/net/core/sock_reuseport.c > @@ -187,6 +187,7 @@ int reuseport_add_sock(struct sock *sk, struct sock *sk2, > bool bind_inany) > call_rcu(_reuse->rcu, reuseport_free_rcu); > return 0; > } > +EXPORT_SYMBOL(reuseport_add_sock); > > void reuseport_detach_sock(struct sock *sk) > { > diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c > index 7df3704..78d0d93 100644 > --- a/net/sctp/bind_addr.c > +++ b/net/sctp/bind_addr.c > @@ -337,6 +337,34 @@ int sctp_bind_addr_match(struct sctp_bind_addr *bp, > return match; > } > > +int sctp_bind_addrs_check(struct sctp_sock *sp, > + struct sctp_sock *sp2, int cnt2) > +{ > + struct sctp_bind_addr *bp2 = >ep->base.bind_addr; > + struct sctp_bind_addr *bp = >ep->base.bind_addr; > + struct sctp_sockaddr_entry *laddr, *laddr2; > + bool exist = false; > + int cnt = 0; > + > + rcu_read_lock(); > + list_for_each_entry_rcu(laddr, >address_list, list) { > + list_for_each_entry_rcu(laddr2, >address_list, list) { > + if (sp->pf->af->cmp_addr(>a, >a) && > + laddr->valid == laddr2->valid) { I think by here in the normal run laddr2->valid will always be true, but as is it gives the impression that it accepts 0 == 0 too, which would be bad. May be on a fast BINDX_REM/BINDX_ADD it could trigger laddr2->valid = 0 in there, not sure. Anyway, may be '... laddr->valid && laddr2->valid' instead or you really want to allow the 0 == 0 case? > + exist = true; > + goto next; > + } > + } > + cnt = 0; > + break; > +next: > + cnt++; > + } > + rcu_read_unlock(); > + > + return (cnt == cnt2) ? 0 : (exist ? -EEXIST : 1); > +} > + > /* Does the address 'addr' conflict with any addresses in > * the bp. > */ > diff --git a/net/sctp/input.c b/net/sctp/input.c > index 60ede89..6bfeb10 100644 > --- a/net/sctp/input.c > +++ b/net/sctp/input.c > @@ -723,43 +723,87 @@ static int sctp_rcv_ootb(struct sk_buff *skb) > } > > /* Insert endpoint into the hash table. */ > -static void __sctp_hash_endpoint(struct sctp_endpoint *ep) > +static int __sctp_hash_endpoint(struct sctp_endpoint *ep) > { > - struct net *net = sock_net(ep->base.sk); > - struct sctp_ep_common *epb; > + struct sock *sk = ep->base.sk; > + struct net *net = sock_net(sk); > struct sctp_hashbucket *head; > +
[PATCH net-next 2/3] sctp: add sock_reuseport for the sock in __sctp_hash_endpoint
This is a part of sk_reuseport support for sctp. It defines a helper sctp_bind_addrs_check() to check if the bind_addrs in two socks are matched. It will add sock_reuseport if they are completely matched, and return err if they are partly matched, and alloc sock_reuseport if all socks are not matched at all. It will work until sk_reuseport support is added in sctp_get_port_local() in the next patch. Signed-off-by: Xin Long --- include/net/sctp/sctp.h| 2 +- include/net/sctp/structs.h | 2 ++ net/core/sock_reuseport.c | 1 + net/sctp/bind_addr.c | 28 ++ net/sctp/input.c | 60 +++--- net/sctp/socket.c | 3 +-- 6 files changed, 85 insertions(+), 11 deletions(-) diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 8c2caa3..b8cd58d 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -152,7 +152,7 @@ int sctp_primitive_RECONF(struct net *net, struct sctp_association *asoc, */ int sctp_rcv(struct sk_buff *skb); void sctp_v4_err(struct sk_buff *skb, u32 info); -void sctp_hash_endpoint(struct sctp_endpoint *); +int sctp_hash_endpoint(struct sctp_endpoint *ep); void sctp_unhash_endpoint(struct sctp_endpoint *); struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *, struct sctphdr *, struct sctp_association **, diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index a11f937..15d017f 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1190,6 +1190,8 @@ int sctp_bind_addr_conflict(struct sctp_bind_addr *, const union sctp_addr *, struct sctp_sock *, struct sctp_sock *); int sctp_bind_addr_state(const struct sctp_bind_addr *bp, const union sctp_addr *addr); +int sctp_bind_addrs_check(struct sctp_sock *sp, + struct sctp_sock *sp2, int cnt2); union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp, const union sctp_addr *addrs, int addrcnt, diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c index ba5cba5..d8fe3e5 100644 --- a/net/core/sock_reuseport.c +++ b/net/core/sock_reuseport.c @@ -187,6 +187,7 @@ int reuseport_add_sock(struct sock *sk, struct sock *sk2, bool bind_inany) call_rcu(_reuse->rcu, reuseport_free_rcu); return 0; } +EXPORT_SYMBOL(reuseport_add_sock); void reuseport_detach_sock(struct sock *sk) { diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 7df3704..78d0d93 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -337,6 +337,34 @@ int sctp_bind_addr_match(struct sctp_bind_addr *bp, return match; } +int sctp_bind_addrs_check(struct sctp_sock *sp, + struct sctp_sock *sp2, int cnt2) +{ + struct sctp_bind_addr *bp2 = >ep->base.bind_addr; + struct sctp_bind_addr *bp = >ep->base.bind_addr; + struct sctp_sockaddr_entry *laddr, *laddr2; + bool exist = false; + int cnt = 0; + + rcu_read_lock(); + list_for_each_entry_rcu(laddr, >address_list, list) { + list_for_each_entry_rcu(laddr2, >address_list, list) { + if (sp->pf->af->cmp_addr(>a, >a) && + laddr->valid == laddr2->valid) { + exist = true; + goto next; + } + } + cnt = 0; + break; +next: + cnt++; + } + rcu_read_unlock(); + + return (cnt == cnt2) ? 0 : (exist ? -EEXIST : 1); +} + /* Does the address 'addr' conflict with any addresses in * the bp. */ diff --git a/net/sctp/input.c b/net/sctp/input.c index 60ede89..6bfeb10 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -723,43 +723,87 @@ static int sctp_rcv_ootb(struct sk_buff *skb) } /* Insert endpoint into the hash table. */ -static void __sctp_hash_endpoint(struct sctp_endpoint *ep) +static int __sctp_hash_endpoint(struct sctp_endpoint *ep) { - struct net *net = sock_net(ep->base.sk); - struct sctp_ep_common *epb; + struct sock *sk = ep->base.sk; + struct net *net = sock_net(sk); struct sctp_hashbucket *head; + struct sctp_ep_common *epb; epb = >base; - epb->hashent = sctp_ep_hashfn(net, epb->bind_addr.port); head = _ep_hashtable[epb->hashent]; + if (sk->sk_reuseport) { + bool any = sctp_is_ep_boundall(sk); + struct sctp_ep_common *epb2; + struct list_head *list; + int cnt = 0, err = 1; + + list_for_each(list, >base.bind_addr.address_list) + cnt++; + + sctp_for_each_hentry(epb2, >chain) { + struct sock *sk2 = epb2->sk; + +