aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_policy.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm/xfrm_policy.c')
-rw-r--r--net/xfrm/xfrm_policy.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index e6ff7b4046ea..55bcb8604bc6 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -566,6 +566,86 @@ static void xfrm_hash_resize(struct work_struct *work)
566 mutex_unlock(&hash_resize_mutex); 566 mutex_unlock(&hash_resize_mutex);
567} 567}
568 568
569static void xfrm_hash_rebuild(struct work_struct *work)
570{
571 struct net *net = container_of(work, struct net,
572 xfrm.policy_hthresh.work);
573 unsigned int hmask;
574 struct xfrm_policy *pol;
575 struct xfrm_policy *policy;
576 struct hlist_head *chain;
577 struct hlist_head *odst;
578 struct hlist_node *newpos;
579 int i;
580 int dir;
581 unsigned seq;
582 u8 lbits4, rbits4, lbits6, rbits6;
583
584 mutex_lock(&hash_resize_mutex);
585
586 /* read selector prefixlen thresholds */
587 do {
588 seq = read_seqbegin(&net->xfrm.policy_hthresh.lock);
589
590 lbits4 = net->xfrm.policy_hthresh.lbits4;
591 rbits4 = net->xfrm.policy_hthresh.rbits4;
592 lbits6 = net->xfrm.policy_hthresh.lbits6;
593 rbits6 = net->xfrm.policy_hthresh.rbits6;
594 } while (read_seqretry(&net->xfrm.policy_hthresh.lock, seq));
595
596 write_lock_bh(&net->xfrm.xfrm_policy_lock);
597
598 /* reset the bydst and inexact table in all directions */
599 for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) {
600 INIT_HLIST_HEAD(&net->xfrm.policy_inexact[dir]);
601 hmask = net->xfrm.policy_bydst[dir].hmask;
602 odst = net->xfrm.policy_bydst[dir].table;
603 for (i = hmask; i >= 0; i--)
604 INIT_HLIST_HEAD(odst + i);
605 if ((dir & XFRM_POLICY_MASK) == XFRM_POLICY_OUT) {
606 /* dir out => dst = remote, src = local */
607 net->xfrm.policy_bydst[dir].dbits4 = rbits4;
608 net->xfrm.policy_bydst[dir].sbits4 = lbits4;
609 net->xfrm.policy_bydst[dir].dbits6 = rbits6;
610 net->xfrm.policy_bydst[dir].sbits6 = lbits6;
611 } else {
612 /* dir in/fwd => dst = local, src = remote */
613 net->xfrm.policy_bydst[dir].dbits4 = lbits4;
614 net->xfrm.policy_bydst[dir].sbits4 = rbits4;
615 net->xfrm.policy_bydst[dir].dbits6 = lbits6;
616 net->xfrm.policy_bydst[dir].sbits6 = rbits6;
617 }
618 }
619
620 /* re-insert all policies by order of creation */
621 list_for_each_entry_reverse(policy, &net->xfrm.policy_all, walk.all) {
622 newpos = NULL;
623 chain = policy_hash_bysel(net, &policy->selector,
624 policy->family,
625 xfrm_policy_id2dir(policy->index));
626 hlist_for_each_entry(pol, chain, bydst) {
627 if (policy->priority >= pol->priority)
628 newpos = &pol->bydst;
629 else
630 break;
631 }
632 if (newpos)
633 hlist_add_behind(&policy->bydst, newpos);
634 else
635 hlist_add_head(&policy->bydst, chain);
636 }
637
638 write_unlock_bh(&net->xfrm.xfrm_policy_lock);
639
640 mutex_unlock(&hash_resize_mutex);
641}
642
643void xfrm_policy_hash_rebuild(struct net *net)
644{
645 schedule_work(&net->xfrm.policy_hthresh.work);
646}
647EXPORT_SYMBOL(xfrm_policy_hash_rebuild);
648
569/* Generate new index... KAME seems to generate them ordered by cost 649/* Generate new index... KAME seems to generate them ordered by cost
570 * of an absolute inpredictability of ordering of rules. This will not pass. */ 650 * of an absolute inpredictability of ordering of rules. This will not pass. */
571static u32 xfrm_gen_index(struct net *net, int dir, u32 index) 651static u32 xfrm_gen_index(struct net *net, int dir, u32 index)
@@ -2872,9 +2952,16 @@ static int __net_init xfrm_policy_init(struct net *net)
2872 htab->dbits6 = 128; 2952 htab->dbits6 = 128;
2873 htab->sbits6 = 128; 2953 htab->sbits6 = 128;
2874 } 2954 }
2955 net->xfrm.policy_hthresh.lbits4 = 32;
2956 net->xfrm.policy_hthresh.rbits4 = 32;
2957 net->xfrm.policy_hthresh.lbits6 = 128;
2958 net->xfrm.policy_hthresh.rbits6 = 128;
2959
2960 seqlock_init(&net->xfrm.policy_hthresh.lock);
2875 2961
2876 INIT_LIST_HEAD(&net->xfrm.policy_all); 2962 INIT_LIST_HEAD(&net->xfrm.policy_all);
2877 INIT_WORK(&net->xfrm.policy_hash_work, xfrm_hash_resize); 2963 INIT_WORK(&net->xfrm.policy_hash_work, xfrm_hash_resize);
2964 INIT_WORK(&net->xfrm.policy_hthresh.work, xfrm_hash_rebuild);
2878 if (net_eq(net, &init_net)) 2965 if (net_eq(net, &init_net))
2879 register_netdevice_notifier(&xfrm_dev_notifier); 2966 register_netdevice_notifier(&xfrm_dev_notifier);
2880 return 0; 2967 return 0;