3434
3535#define xfrm_state_deref_prot (table , net ) \
3636 rcu_dereference_protected((table), lockdep_is_held(&(net)->xfrm.xfrm_state_lock))
37+ #define xfrm_state_deref_check (table , net ) \
38+ rcu_dereference_check((table), lockdep_is_held(&(net)->xfrm.xfrm_state_lock))
3739
3840static void xfrm_state_gc_task (struct work_struct * work );
3941
@@ -62,6 +64,8 @@ static inline unsigned int xfrm_dst_hash(struct net *net,
6264 u32 reqid ,
6365 unsigned short family )
6466{
67+ lockdep_assert_held (& net -> xfrm .xfrm_state_lock );
68+
6569 return __xfrm_dst_hash (daddr , saddr , reqid , family , net -> xfrm .state_hmask );
6670}
6771
@@ -70,18 +74,24 @@ static inline unsigned int xfrm_src_hash(struct net *net,
7074 const xfrm_address_t * saddr ,
7175 unsigned short family )
7276{
77+ lockdep_assert_held (& net -> xfrm .xfrm_state_lock );
78+
7379 return __xfrm_src_hash (daddr , saddr , family , net -> xfrm .state_hmask );
7480}
7581
7682static inline unsigned int
7783xfrm_spi_hash (struct net * net , const xfrm_address_t * daddr ,
7884 __be32 spi , u8 proto , unsigned short family )
7985{
86+ lockdep_assert_held (& net -> xfrm .xfrm_state_lock );
87+
8088 return __xfrm_spi_hash (daddr , spi , proto , family , net -> xfrm .state_hmask );
8189}
8290
8391static unsigned int xfrm_seq_hash (struct net * net , u32 seq )
8492{
93+ lockdep_assert_held (& net -> xfrm .xfrm_state_lock );
94+
8595 return __xfrm_seq_hash (seq , net -> xfrm .state_hmask );
8696}
8797
@@ -1108,16 +1118,38 @@ xfrm_init_tempstate(struct xfrm_state *x, const struct flowi *fl,
11081118 x -> props .family = tmpl -> encap_family ;
11091119}
11101120
1111- static struct xfrm_state * __xfrm_state_lookup_all (struct net * net , u32 mark ,
1121+ struct xfrm_hash_state_ptrs {
1122+ const struct hlist_head * bydst ;
1123+ const struct hlist_head * bysrc ;
1124+ const struct hlist_head * byspi ;
1125+ unsigned int hmask ;
1126+ };
1127+
1128+ static void xfrm_hash_ptrs_get (const struct net * net , struct xfrm_hash_state_ptrs * ptrs )
1129+ {
1130+ unsigned int sequence ;
1131+
1132+ do {
1133+ sequence = read_seqcount_begin (& net -> xfrm .xfrm_state_hash_generation );
1134+
1135+ ptrs -> bydst = xfrm_state_deref_check (net -> xfrm .state_bydst , net );
1136+ ptrs -> bysrc = xfrm_state_deref_check (net -> xfrm .state_bysrc , net );
1137+ ptrs -> byspi = xfrm_state_deref_check (net -> xfrm .state_byspi , net );
1138+ ptrs -> hmask = net -> xfrm .state_hmask ;
1139+ } while (read_seqcount_retry (& net -> xfrm .xfrm_state_hash_generation , sequence ));
1140+ }
1141+
1142+ static struct xfrm_state * __xfrm_state_lookup_all (const struct xfrm_hash_state_ptrs * state_ptrs ,
1143+ u32 mark ,
11121144 const xfrm_address_t * daddr ,
11131145 __be32 spi , u8 proto ,
11141146 unsigned short family ,
11151147 struct xfrm_dev_offload * xdo )
11161148{
1117- unsigned int h = xfrm_spi_hash ( net , daddr , spi , proto , family );
1149+ unsigned int h = __xfrm_spi_hash ( daddr , spi , proto , family , state_ptrs -> hmask );
11181150 struct xfrm_state * x ;
11191151
1120- hlist_for_each_entry_rcu (x , net -> xfrm . state_byspi + h , byspi ) {
1152+ hlist_for_each_entry_rcu (x , state_ptrs -> byspi + h , byspi ) {
11211153#ifdef CONFIG_XFRM_OFFLOAD
11221154 if (xdo -> type == XFRM_DEV_OFFLOAD_PACKET ) {
11231155 if (x -> xso .type != XFRM_DEV_OFFLOAD_PACKET )
@@ -1151,15 +1183,16 @@ static struct xfrm_state *__xfrm_state_lookup_all(struct net *net, u32 mark,
11511183 return NULL ;
11521184}
11531185
1154- static struct xfrm_state * __xfrm_state_lookup (struct net * net , u32 mark ,
1186+ static struct xfrm_state * __xfrm_state_lookup (const struct xfrm_hash_state_ptrs * state_ptrs ,
1187+ u32 mark ,
11551188 const xfrm_address_t * daddr ,
11561189 __be32 spi , u8 proto ,
11571190 unsigned short family )
11581191{
1159- unsigned int h = xfrm_spi_hash ( net , daddr , spi , proto , family );
1192+ unsigned int h = __xfrm_spi_hash ( daddr , spi , proto , family , state_ptrs -> hmask );
11601193 struct xfrm_state * x ;
11611194
1162- hlist_for_each_entry_rcu (x , net -> xfrm . state_byspi + h , byspi ) {
1195+ hlist_for_each_entry_rcu (x , state_ptrs -> byspi + h , byspi ) {
11631196 if (x -> props .family != family ||
11641197 x -> id .spi != spi ||
11651198 x -> id .proto != proto ||
@@ -1181,11 +1214,11 @@ struct xfrm_state *xfrm_input_state_lookup(struct net *net, u32 mark,
11811214 __be32 spi , u8 proto ,
11821215 unsigned short family )
11831216{
1217+ struct xfrm_hash_state_ptrs state_ptrs ;
11841218 struct hlist_head * state_cache_input ;
11851219 struct xfrm_state * x = NULL ;
1186- int cpu = get_cpu ();
11871220
1188- state_cache_input = per_cpu_ptr (net -> xfrm .state_cache_input , cpu );
1221+ state_cache_input = raw_cpu_ptr (net -> xfrm .state_cache_input );
11891222
11901223 rcu_read_lock ();
11911224 hlist_for_each_entry_rcu (x , state_cache_input , state_cache_input ) {
@@ -1202,7 +1235,9 @@ struct xfrm_state *xfrm_input_state_lookup(struct net *net, u32 mark,
12021235 goto out ;
12031236 }
12041237
1205- x = __xfrm_state_lookup (net , mark , daddr , spi , proto , family );
1238+ xfrm_hash_ptrs_get (net , & state_ptrs );
1239+
1240+ x = __xfrm_state_lookup (& state_ptrs , mark , daddr , spi , proto , family );
12061241
12071242 if (x && x -> km .state == XFRM_STATE_VALID ) {
12081243 spin_lock_bh (& net -> xfrm .xfrm_state_lock );
@@ -1217,20 +1252,20 @@ struct xfrm_state *xfrm_input_state_lookup(struct net *net, u32 mark,
12171252
12181253out :
12191254 rcu_read_unlock ();
1220- put_cpu ();
12211255 return x ;
12221256}
12231257EXPORT_SYMBOL (xfrm_input_state_lookup );
12241258
1225- static struct xfrm_state * __xfrm_state_lookup_byaddr (struct net * net , u32 mark ,
1259+ static struct xfrm_state * __xfrm_state_lookup_byaddr (const struct xfrm_hash_state_ptrs * state_ptrs ,
1260+ u32 mark ,
12261261 const xfrm_address_t * daddr ,
12271262 const xfrm_address_t * saddr ,
12281263 u8 proto , unsigned short family )
12291264{
1230- unsigned int h = xfrm_src_hash ( net , daddr , saddr , family );
1265+ unsigned int h = __xfrm_src_hash ( daddr , saddr , family , state_ptrs -> hmask );
12311266 struct xfrm_state * x ;
12321267
1233- hlist_for_each_entry_rcu (x , net -> xfrm . state_bysrc + h , bysrc ) {
1268+ hlist_for_each_entry_rcu (x , state_ptrs -> bysrc + h , bysrc ) {
12341269 if (x -> props .family != family ||
12351270 x -> id .proto != proto ||
12361271 !xfrm_addr_equal (& x -> id .daddr , daddr , family ) ||
@@ -1250,14 +1285,17 @@ static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, u32 mark,
12501285static inline struct xfrm_state *
12511286__xfrm_state_locate (struct xfrm_state * x , int use_spi , int family )
12521287{
1288+ struct xfrm_hash_state_ptrs state_ptrs ;
12531289 struct net * net = xs_net (x );
12541290 u32 mark = x -> mark .v & x -> mark .m ;
12551291
1292+ xfrm_hash_ptrs_get (net , & state_ptrs );
1293+
12561294 if (use_spi )
1257- return __xfrm_state_lookup (net , mark , & x -> id .daddr ,
1295+ return __xfrm_state_lookup (& state_ptrs , mark , & x -> id .daddr ,
12581296 x -> id .spi , x -> id .proto , family );
12591297 else
1260- return __xfrm_state_lookup_byaddr (net , mark ,
1298+ return __xfrm_state_lookup_byaddr (& state_ptrs , mark ,
12611299 & x -> id .daddr ,
12621300 & x -> props .saddr ,
12631301 x -> id .proto , family );
@@ -1331,6 +1369,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
13311369 unsigned short family , u32 if_id )
13321370{
13331371 static xfrm_address_t saddr_wildcard = { };
1372+ struct xfrm_hash_state_ptrs state_ptrs ;
13341373 struct net * net = xp_net (pol );
13351374 unsigned int h , h_wildcard ;
13361375 struct xfrm_state * x , * x0 , * to_put ;
@@ -1395,8 +1434,10 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
13951434 else if (acquire_in_progress ) /* XXX: acquire_in_progress should not happen */
13961435 WARN_ON (1 );
13971436
1398- h = xfrm_dst_hash (net , daddr , saddr , tmpl -> reqid , encap_family );
1399- hlist_for_each_entry_rcu (x , net -> xfrm .state_bydst + h , bydst ) {
1437+ xfrm_hash_ptrs_get (net , & state_ptrs );
1438+
1439+ h = __xfrm_dst_hash (daddr , saddr , tmpl -> reqid , encap_family , state_ptrs .hmask );
1440+ hlist_for_each_entry_rcu (x , state_ptrs .bydst + h , bydst ) {
14001441#ifdef CONFIG_XFRM_OFFLOAD
14011442 if (pol -> xdo .type == XFRM_DEV_OFFLOAD_PACKET ) {
14021443 if (x -> xso .type != XFRM_DEV_OFFLOAD_PACKET )
@@ -1429,8 +1470,9 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
14291470 if (best || acquire_in_progress )
14301471 goto found ;
14311472
1432- h_wildcard = xfrm_dst_hash (net , daddr , & saddr_wildcard , tmpl -> reqid , encap_family );
1433- hlist_for_each_entry_rcu (x , net -> xfrm .state_bydst + h_wildcard , bydst ) {
1473+ h_wildcard = __xfrm_dst_hash (daddr , & saddr_wildcard , tmpl -> reqid ,
1474+ encap_family , state_ptrs .hmask );
1475+ hlist_for_each_entry_rcu (x , state_ptrs .bydst + h_wildcard , bydst ) {
14341476#ifdef CONFIG_XFRM_OFFLOAD
14351477 if (pol -> xdo .type == XFRM_DEV_OFFLOAD_PACKET ) {
14361478 if (x -> xso .type != XFRM_DEV_OFFLOAD_PACKET )
@@ -1468,7 +1510,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
14681510
14691511 if (!x && !error && !acquire_in_progress ) {
14701512 if (tmpl -> id .spi &&
1471- (x0 = __xfrm_state_lookup_all (net , mark , daddr ,
1513+ (x0 = __xfrm_state_lookup_all (& state_ptrs , mark , daddr ,
14721514 tmpl -> id .spi , tmpl -> id .proto ,
14731515 encap_family ,
14741516 & pol -> xdo )) != NULL ) {
@@ -2253,10 +2295,13 @@ struct xfrm_state *
22532295xfrm_state_lookup (struct net * net , u32 mark , const xfrm_address_t * daddr , __be32 spi ,
22542296 u8 proto , unsigned short family )
22552297{
2298+ struct xfrm_hash_state_ptrs state_ptrs ;
22562299 struct xfrm_state * x ;
22572300
22582301 rcu_read_lock ();
2259- x = __xfrm_state_lookup (net , mark , daddr , spi , proto , family );
2302+ xfrm_hash_ptrs_get (net , & state_ptrs );
2303+
2304+ x = __xfrm_state_lookup (& state_ptrs , mark , daddr , spi , proto , family );
22602305 rcu_read_unlock ();
22612306 return x ;
22622307}
@@ -2267,10 +2312,14 @@ xfrm_state_lookup_byaddr(struct net *net, u32 mark,
22672312 const xfrm_address_t * daddr , const xfrm_address_t * saddr ,
22682313 u8 proto , unsigned short family )
22692314{
2315+ struct xfrm_hash_state_ptrs state_ptrs ;
22702316 struct xfrm_state * x ;
22712317
22722318 spin_lock_bh (& net -> xfrm .xfrm_state_lock );
2273- x = __xfrm_state_lookup_byaddr (net , mark , daddr , saddr , proto , family );
2319+
2320+ xfrm_hash_ptrs_get (net , & state_ptrs );
2321+
2322+ x = __xfrm_state_lookup_byaddr (& state_ptrs , mark , daddr , saddr , proto , family );
22742323 spin_unlock_bh (& net -> xfrm .xfrm_state_lock );
22752324 return x ;
22762325}
0 commit comments