aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/xfrm/xfrm_policy.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 47219f98053f..9fc4c315f6cd 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -331,15 +331,31 @@ static void xfrm_dst_hash_transfer(struct hlist_head *list,
331 struct hlist_head *ndsttable, 331 struct hlist_head *ndsttable,
332 unsigned int nhashmask) 332 unsigned int nhashmask)
333{ 333{
334 struct hlist_node *entry, *tmp; 334 struct hlist_node *entry, *tmp, *entry0 = NULL;
335 struct xfrm_policy *pol; 335 struct xfrm_policy *pol;
336 unsigned int h0 = 0;
336 337
338redo:
337 hlist_for_each_entry_safe(pol, entry, tmp, list, bydst) { 339 hlist_for_each_entry_safe(pol, entry, tmp, list, bydst) {
338 unsigned int h; 340 unsigned int h;
339 341
340 h = __addr_hash(&pol->selector.daddr, &pol->selector.saddr, 342 h = __addr_hash(&pol->selector.daddr, &pol->selector.saddr,
341 pol->family, nhashmask); 343 pol->family, nhashmask);
342 hlist_add_head(&pol->bydst, ndsttable+h); 344 if (!entry0) {
345 hlist_del(entry);
346 hlist_add_head(&pol->bydst, ndsttable+h);
347 h0 = h;
348 } else {
349 if (h != h0)
350 continue;
351 hlist_del(entry);
352 hlist_add_after(entry0, &pol->bydst);
353 }
354 entry0 = entry;
355 }
356 if (!hlist_empty(list)) {
357 entry0 = NULL;
358 goto redo;
343 } 359 }
344} 360}
345 361