@@ -1361,36 +1361,29 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, const struct flowi *fl,
1361
1361
struct net * net = xp_net (policy );
1362
1362
int nx ;
1363
1363
int i , error ;
1364
- xfrm_address_t * daddr = xfrm_flowi_daddr (fl , family );
1365
- xfrm_address_t * saddr = xfrm_flowi_saddr (fl , family );
1366
1364
xfrm_address_t tmp ;
1367
1365
1368
1366
for (nx = 0 , i = 0 ; i < policy -> xfrm_nr ; i ++ ) {
1369
1367
struct xfrm_state * x ;
1370
- xfrm_address_t * remote = daddr ;
1371
- xfrm_address_t * local = saddr ;
1368
+ xfrm_address_t * local ;
1369
+ xfrm_address_t * remote ;
1372
1370
struct xfrm_tmpl * tmpl = & policy -> xfrm_vec [i ];
1373
1371
1374
- if (tmpl -> mode == XFRM_MODE_TUNNEL ||
1375
- tmpl -> mode == XFRM_MODE_BEET ) {
1376
- remote = & tmpl -> id .daddr ;
1377
- local = & tmpl -> saddr ;
1378
- if (xfrm_addr_any (local , tmpl -> encap_family )) {
1379
- error = xfrm_get_saddr (net , fl -> flowi_oif ,
1380
- & tmp , remote ,
1381
- tmpl -> encap_family , 0 );
1382
- if (error )
1383
- goto fail ;
1384
- local = & tmp ;
1385
- }
1372
+ remote = & tmpl -> id .daddr ;
1373
+ local = & tmpl -> saddr ;
1374
+ if (xfrm_addr_any (local , tmpl -> encap_family )) {
1375
+ error = xfrm_get_saddr (net , fl -> flowi_oif ,
1376
+ & tmp , remote ,
1377
+ tmpl -> encap_family , 0 );
1378
+ if (error )
1379
+ goto fail ;
1380
+ local = & tmp ;
1386
1381
}
1387
1382
1388
1383
x = xfrm_state_find (remote , local , fl , tmpl , policy , & error , family );
1389
1384
1390
1385
if (x && x -> km .state == XFRM_STATE_VALID ) {
1391
1386
xfrm [nx ++ ] = x ;
1392
- daddr = remote ;
1393
- saddr = local ;
1394
1387
continue ;
1395
1388
}
1396
1389
if (x ) {
@@ -1787,19 +1780,23 @@ void xfrm_policy_cache_flush(void)
1787
1780
put_online_cpus ();
1788
1781
}
1789
1782
1790
- static bool xfrm_pol_dead (struct xfrm_dst * xdst )
1783
+ static bool xfrm_xdst_can_reuse (struct xfrm_dst * xdst ,
1784
+ struct xfrm_state * const xfrm [],
1785
+ int num )
1791
1786
{
1792
- unsigned int num_pols = xdst -> num_pols ;
1793
- unsigned int pol_dead = 0 , i ;
1787
+ const struct dst_entry * dst = & xdst -> u . dst ;
1788
+ int i ;
1794
1789
1795
- for ( i = 0 ; i < num_pols ; i ++ )
1796
- pol_dead |= xdst -> pols [ i ] -> walk . dead ;
1790
+ if ( xdst -> num_xfrms != num )
1791
+ return false ;
1797
1792
1798
- /* Mark DST_OBSOLETE_DEAD to fail the next xfrm_dst_check() */
1799
- if (pol_dead )
1800
- xdst -> u .dst .obsolete = DST_OBSOLETE_DEAD ;
1793
+ for (i = 0 ; i < num ; i ++ ) {
1794
+ if (!dst || dst -> xfrm != xfrm [i ])
1795
+ return false;
1796
+ dst = dst -> child ;
1797
+ }
1801
1798
1802
- return pol_dead ;
1799
+ return xfrm_bundle_ok ( xdst ) ;
1803
1800
}
1804
1801
1805
1802
static struct xfrm_dst *
@@ -1813,26 +1810,28 @@ xfrm_resolve_and_create_bundle(struct xfrm_policy **pols, int num_pols,
1813
1810
struct dst_entry * dst ;
1814
1811
int err ;
1815
1812
1813
+ /* Try to instantiate a bundle */
1814
+ err = xfrm_tmpl_resolve (pols , num_pols , fl , xfrm , family );
1815
+ if (err <= 0 ) {
1816
+ if (err != 0 && err != - EAGAIN )
1817
+ XFRM_INC_STATS (net , LINUX_MIB_XFRMOUTPOLERROR );
1818
+ return ERR_PTR (err );
1819
+ }
1820
+
1816
1821
xdst = this_cpu_read (xfrm_last_dst );
1817
1822
if (xdst &&
1818
1823
xdst -> u .dst .dev == dst_orig -> dev &&
1819
1824
xdst -> num_pols == num_pols &&
1820
- !xfrm_pol_dead (xdst ) &&
1821
1825
memcmp (xdst -> pols , pols ,
1822
1826
sizeof (struct xfrm_policy * ) * num_pols ) == 0 &&
1823
- xfrm_bundle_ok (xdst )) {
1827
+ xfrm_xdst_can_reuse (xdst , xfrm , err )) {
1824
1828
dst_hold (& xdst -> u .dst );
1829
+ while (err > 0 )
1830
+ xfrm_state_put (xfrm [-- err ]);
1825
1831
return xdst ;
1826
1832
}
1827
1833
1828
1834
old = xdst ;
1829
- /* Try to instantiate a bundle */
1830
- err = xfrm_tmpl_resolve (pols , num_pols , fl , xfrm , family );
1831
- if (err <= 0 ) {
1832
- if (err != 0 && err != - EAGAIN )
1833
- XFRM_INC_STATS (net , LINUX_MIB_XFRMOUTPOLERROR );
1834
- return ERR_PTR (err );
1835
- }
1836
1835
1837
1836
dst = xfrm_bundle_create (pols [0 ], xfrm , err , fl , dst_orig );
1838
1837
if (IS_ERR (dst )) {
0 commit comments