@@ -665,6 +665,7 @@ struct xfrm_state *xfrm_state_alloc(struct net *net)
665665 refcount_set (& x -> refcnt , 1 );
666666 atomic_set (& x -> tunnel_users , 0 );
667667 INIT_LIST_HEAD (& x -> km .all );
668+ INIT_HLIST_NODE (& x -> state_cache );
668669 INIT_HLIST_NODE (& x -> bydst );
669670 INIT_HLIST_NODE (& x -> bysrc );
670671 INIT_HLIST_NODE (& x -> byspi );
@@ -744,12 +745,15 @@ int __xfrm_state_delete(struct xfrm_state *x)
744745
745746 if (x -> km .state != XFRM_STATE_DEAD ) {
746747 x -> km .state = XFRM_STATE_DEAD ;
748+
747749 spin_lock (& net -> xfrm .xfrm_state_lock );
748750 list_del (& x -> km .all );
749751 hlist_del_rcu (& x -> bydst );
750752 hlist_del_rcu (& x -> bysrc );
751753 if (x -> km .seq )
752754 hlist_del_rcu (& x -> byseq );
755+ if (!hlist_unhashed (& x -> state_cache ))
756+ hlist_del_rcu (& x -> state_cache );
753757 if (x -> id .spi )
754758 hlist_del_rcu (& x -> byspi );
755759 net -> xfrm .state_num -- ;
@@ -1222,6 +1226,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
12221226 unsigned int sequence ;
12231227 struct km_event c ;
12241228 unsigned int pcpu_id ;
1229+ bool cached = false;
12251230
12261231 /* We need the cpu id just as a lookup key,
12271232 * we don't require it to be stable.
@@ -1234,6 +1239,46 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
12341239 sequence = read_seqcount_begin (& net -> xfrm .xfrm_state_hash_generation );
12351240
12361241 rcu_read_lock ();
1242+ hlist_for_each_entry_rcu (x , & pol -> state_cache_list , state_cache ) {
1243+ if (x -> props .family == encap_family &&
1244+ x -> props .reqid == tmpl -> reqid &&
1245+ (mark & x -> mark .m ) == x -> mark .v &&
1246+ x -> if_id == if_id &&
1247+ !(x -> props .flags & XFRM_STATE_WILDRECV ) &&
1248+ xfrm_state_addr_check (x , daddr , saddr , encap_family ) &&
1249+ tmpl -> mode == x -> props .mode &&
1250+ tmpl -> id .proto == x -> id .proto &&
1251+ (tmpl -> id .spi == x -> id .spi || !tmpl -> id .spi ))
1252+ xfrm_state_look_at (pol , x , fl , encap_family ,
1253+ & best , & acquire_in_progress , & error );
1254+ }
1255+
1256+ if (best )
1257+ goto cached ;
1258+
1259+ hlist_for_each_entry_rcu (x , & pol -> state_cache_list , state_cache ) {
1260+ if (x -> props .family == encap_family &&
1261+ x -> props .reqid == tmpl -> reqid &&
1262+ (mark & x -> mark .m ) == x -> mark .v &&
1263+ x -> if_id == if_id &&
1264+ !(x -> props .flags & XFRM_STATE_WILDRECV ) &&
1265+ xfrm_addr_equal (& x -> id .daddr , daddr , encap_family ) &&
1266+ tmpl -> mode == x -> props .mode &&
1267+ tmpl -> id .proto == x -> id .proto &&
1268+ (tmpl -> id .spi == x -> id .spi || !tmpl -> id .spi ))
1269+ xfrm_state_look_at (pol , x , fl , family ,
1270+ & best , & acquire_in_progress , & error );
1271+ }
1272+
1273+ cached :
1274+ cached = true;
1275+ if (best )
1276+ goto found ;
1277+ else if (error )
1278+ best = NULL ;
1279+ else if (acquire_in_progress ) /* XXX: acquire_in_progress should not happen */
1280+ WARN_ON (1 );
1281+
12371282 h = xfrm_dst_hash (net , daddr , saddr , tmpl -> reqid , encap_family );
12381283 hlist_for_each_entry_rcu (x , net -> xfrm .state_bydst + h , bydst ) {
12391284#ifdef CONFIG_XFRM_OFFLOAD
@@ -1383,6 +1428,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
13831428 XFRM_STATE_INSERT (bysrc , & x -> bysrc ,
13841429 net -> xfrm .state_bysrc + h ,
13851430 x -> xso .type );
1431+ INIT_HLIST_NODE (& x -> state_cache );
13861432 if (x -> id .spi ) {
13871433 h = xfrm_spi_hash (net , & x -> id .daddr , x -> id .spi , x -> id .proto , encap_family );
13881434 XFRM_STATE_INSERT (byspi , & x -> byspi ,
@@ -1431,6 +1477,15 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
14311477 } else {
14321478 * err = acquire_in_progress ? - EAGAIN : error ;
14331479 }
1480+
1481+ if (x && x -> km .state == XFRM_STATE_VALID && !cached &&
1482+ (!(pol -> flags & XFRM_POLICY_CPU_ACQUIRE ) || x -> pcpu_num == pcpu_id )) {
1483+ spin_lock_bh (& net -> xfrm .xfrm_state_lock );
1484+ if (hlist_unhashed (& x -> state_cache ))
1485+ hlist_add_head_rcu (& x -> state_cache , & pol -> state_cache_list );
1486+ spin_unlock_bh (& net -> xfrm .xfrm_state_lock );
1487+ }
1488+
14341489 rcu_read_unlock ();
14351490 if (to_put )
14361491 xfrm_state_put (to_put );
0 commit comments