57
57
#include <net/sctp/checksum.h>
58
58
#include <net/net_namespace.h>
59
59
#include <linux/rhashtable.h>
60
+ #include <net/sock_reuseport.h>
60
61
61
62
/* Forward declarations for internal helpers. */
62
63
static int sctp_rcv_ootb (struct sk_buff * );
@@ -65,8 +66,10 @@ static struct sctp_association *__sctp_rcv_lookup(struct net *net,
65
66
const union sctp_addr * paddr ,
66
67
const union sctp_addr * laddr ,
67
68
struct sctp_transport * * transportp );
68
- static struct sctp_endpoint * __sctp_rcv_lookup_endpoint (struct net * net ,
69
- const union sctp_addr * laddr );
69
+ static struct sctp_endpoint * __sctp_rcv_lookup_endpoint (
70
+ struct net * net , struct sk_buff * skb ,
71
+ const union sctp_addr * laddr ,
72
+ const union sctp_addr * daddr );
70
73
static struct sctp_association * __sctp_lookup_association (
71
74
struct net * net ,
72
75
const union sctp_addr * local ,
@@ -171,7 +174,7 @@ int sctp_rcv(struct sk_buff *skb)
171
174
asoc = __sctp_rcv_lookup (net , skb , & src , & dest , & transport );
172
175
173
176
if (!asoc )
174
- ep = __sctp_rcv_lookup_endpoint (net , & dest );
177
+ ep = __sctp_rcv_lookup_endpoint (net , skb , & dest , & src );
175
178
176
179
/* Retrieve the common input handling substructure. */
177
180
rcvr = asoc ? & asoc -> base : & ep -> base ;
@@ -771,16 +774,35 @@ void sctp_unhash_endpoint(struct sctp_endpoint *ep)
771
774
local_bh_enable ();
772
775
}
773
776
777
+ static inline __u32 sctp_hashfn (const struct net * net , __be16 lport ,
778
+ const union sctp_addr * paddr , __u32 seed )
779
+ {
780
+ __u32 addr ;
781
+
782
+ if (paddr -> sa .sa_family == AF_INET6 )
783
+ addr = jhash (& paddr -> v6 .sin6_addr , 16 , seed );
784
+ else
785
+ addr = (__force __u32 )paddr -> v4 .sin_addr .s_addr ;
786
+
787
+ return jhash_3words (addr , ((__force __u32 )paddr -> v4 .sin_port ) << 16 |
788
+ (__force __u32 )lport , net_hash_mix (net ), seed );
789
+ }
790
+
774
791
/* Look up an endpoint. */
775
- static struct sctp_endpoint * __sctp_rcv_lookup_endpoint (struct net * net ,
776
- const union sctp_addr * laddr )
792
+ static struct sctp_endpoint * __sctp_rcv_lookup_endpoint (
793
+ struct net * net , struct sk_buff * skb ,
794
+ const union sctp_addr * laddr ,
795
+ const union sctp_addr * paddr )
777
796
{
778
797
struct sctp_hashbucket * head ;
779
798
struct sctp_ep_common * epb ;
780
799
struct sctp_endpoint * ep ;
800
+ struct sock * sk ;
801
+ __be16 lport ;
781
802
int hash ;
782
803
783
- hash = sctp_ep_hashfn (net , ntohs (laddr -> v4 .sin_port ));
804
+ lport = laddr -> v4 .sin_port ;
805
+ hash = sctp_ep_hashfn (net , ntohs (lport ));
784
806
head = & sctp_ep_hashtable [hash ];
785
807
read_lock (& head -> lock );
786
808
sctp_for_each_hentry (epb , & head -> chain ) {
@@ -792,6 +814,15 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
792
814
ep = sctp_sk (net -> sctp .ctl_sock )-> ep ;
793
815
794
816
hit :
817
+ sk = ep -> base .sk ;
818
+ if (sk -> sk_reuseport ) {
819
+ __u32 phash = sctp_hashfn (net , lport , paddr , 0 );
820
+
821
+ sk = reuseport_select_sock (sk , phash , skb ,
822
+ sizeof (struct sctphdr ));
823
+ if (sk )
824
+ ep = sctp_sk (sk )-> ep ;
825
+ }
795
826
sctp_endpoint_hold (ep );
796
827
read_unlock (& head -> lock );
797
828
return ep ;
@@ -830,35 +861,17 @@ static inline int sctp_hash_cmp(struct rhashtable_compare_arg *arg,
830
861
static inline __u32 sctp_hash_obj (const void * data , u32 len , u32 seed )
831
862
{
832
863
const struct sctp_transport * t = data ;
833
- const union sctp_addr * paddr = & t -> ipaddr ;
834
- const struct net * net = sock_net (t -> asoc -> base .sk );
835
- __be16 lport = htons (t -> asoc -> base .bind_addr .port );
836
- __u32 addr ;
837
-
838
- if (paddr -> sa .sa_family == AF_INET6 )
839
- addr = jhash (& paddr -> v6 .sin6_addr , 16 , seed );
840
- else
841
- addr = (__force __u32 )paddr -> v4 .sin_addr .s_addr ;
842
864
843
- return jhash_3words (addr , ((__force __u32 )paddr -> v4 .sin_port ) << 16 |
844
- (__force __u32 )lport , net_hash_mix (net ), seed );
865
+ return sctp_hashfn (sock_net (t -> asoc -> base .sk ),
866
+ htons (t -> asoc -> base .bind_addr .port ),
867
+ & t -> ipaddr , seed );
845
868
}
846
869
847
870
static inline __u32 sctp_hash_key (const void * data , u32 len , u32 seed )
848
871
{
849
872
const struct sctp_hash_cmp_arg * x = data ;
850
- const union sctp_addr * paddr = x -> paddr ;
851
- const struct net * net = x -> net ;
852
- __be16 lport = x -> lport ;
853
- __u32 addr ;
854
-
855
- if (paddr -> sa .sa_family == AF_INET6 )
856
- addr = jhash (& paddr -> v6 .sin6_addr , 16 , seed );
857
- else
858
- addr = (__force __u32 )paddr -> v4 .sin_addr .s_addr ;
859
873
860
- return jhash_3words (addr , ((__force __u32 )paddr -> v4 .sin_port ) << 16 |
861
- (__force __u32 )lport , net_hash_mix (net ), seed );
874
+ return sctp_hashfn (x -> net , x -> lport , x -> paddr , seed );
862
875
}
863
876
864
877
static const struct rhashtable_params sctp_hash_params = {
0 commit comments