aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_state.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm/xfrm_state.c')
-rw-r--r--net/xfrm/xfrm_state.c139
1 files changed, 82 insertions, 57 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index f2f7c638083e..add77ecb8ac4 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -21,6 +21,10 @@
21#include <linux/cache.h> 21#include <linux/cache.h>
22#include <linux/audit.h> 22#include <linux/audit.h>
23#include <asm/uaccess.h> 23#include <asm/uaccess.h>
24#include <linux/ktime.h>
25#include <linux/slab.h>
26#include <linux/interrupt.h>
27#include <linux/kernel.h>
24 28
25#include "xfrm_hash.h" 29#include "xfrm_hash.h"
26 30
@@ -352,7 +356,7 @@ static void xfrm_put_mode(struct xfrm_mode *mode)
352 356
353static void xfrm_state_gc_destroy(struct xfrm_state *x) 357static void xfrm_state_gc_destroy(struct xfrm_state *x)
354{ 358{
355 del_timer_sync(&x->timer); 359 tasklet_hrtimer_cancel(&x->mtimer);
356 del_timer_sync(&x->rtimer); 360 del_timer_sync(&x->rtimer);
357 kfree(x->aalg); 361 kfree(x->aalg);
358 kfree(x->ealg); 362 kfree(x->ealg);
@@ -398,9 +402,10 @@ static inline unsigned long make_jiffies(long secs)
398 return secs*HZ; 402 return secs*HZ;
399} 403}
400 404
401static void xfrm_timer_handler(unsigned long data) 405static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me)
402{ 406{
403 struct xfrm_state *x = (struct xfrm_state*)data; 407 struct tasklet_hrtimer *thr = container_of(me, struct tasklet_hrtimer, timer);
408 struct xfrm_state *x = container_of(thr, struct xfrm_state, mtimer);
404 struct net *net = xs_net(x); 409 struct net *net = xs_net(x);
405 unsigned long now = get_seconds(); 410 unsigned long now = get_seconds();
406 long next = LONG_MAX; 411 long next = LONG_MAX;
@@ -451,8 +456,9 @@ static void xfrm_timer_handler(unsigned long data)
451 if (warn) 456 if (warn)
452 km_state_expired(x, 0, 0); 457 km_state_expired(x, 0, 0);
453resched: 458resched:
454 if (next != LONG_MAX) 459 if (next != LONG_MAX){
455 mod_timer(&x->timer, jiffies + make_jiffies(next)); 460 tasklet_hrtimer_start(&x->mtimer, ktime_set(next, 0), HRTIMER_MODE_REL);
461 }
456 462
457 goto out; 463 goto out;
458 464
@@ -474,6 +480,7 @@ expired:
474 480
475out: 481out:
476 spin_unlock(&x->lock); 482 spin_unlock(&x->lock);
483 return HRTIMER_NORESTART;
477} 484}
478 485
479static void xfrm_replay_timer_handler(unsigned long data); 486static void xfrm_replay_timer_handler(unsigned long data);
@@ -492,7 +499,7 @@ struct xfrm_state *xfrm_state_alloc(struct net *net)
492 INIT_HLIST_NODE(&x->bydst); 499 INIT_HLIST_NODE(&x->bydst);
493 INIT_HLIST_NODE(&x->bysrc); 500 INIT_HLIST_NODE(&x->bysrc);
494 INIT_HLIST_NODE(&x->byspi); 501 INIT_HLIST_NODE(&x->byspi);
495 setup_timer(&x->timer, xfrm_timer_handler, (unsigned long)x); 502 tasklet_hrtimer_init(&x->mtimer, xfrm_timer_handler, CLOCK_REALTIME, HRTIMER_MODE_ABS);
496 setup_timer(&x->rtimer, xfrm_replay_timer_handler, 503 setup_timer(&x->rtimer, xfrm_replay_timer_handler,
497 (unsigned long)x); 504 (unsigned long)x);
498 x->curlft.add_time = get_seconds(); 505 x->curlft.add_time = get_seconds();
@@ -597,13 +604,14 @@ xfrm_state_flush_secctx_check(struct net *net, u8 proto, struct xfrm_audit *audi
597 604
598int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info) 605int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info)
599{ 606{
600 int i, err = 0; 607 int i, err = 0, cnt = 0;
601 608
602 spin_lock_bh(&xfrm_state_lock); 609 spin_lock_bh(&xfrm_state_lock);
603 err = xfrm_state_flush_secctx_check(net, proto, audit_info); 610 err = xfrm_state_flush_secctx_check(net, proto, audit_info);
604 if (err) 611 if (err)
605 goto out; 612 goto out;
606 613
614 err = -ESRCH;
607 for (i = 0; i <= net->xfrm.state_hmask; i++) { 615 for (i = 0; i <= net->xfrm.state_hmask; i++) {
608 struct hlist_node *entry; 616 struct hlist_node *entry;
609 struct xfrm_state *x; 617 struct xfrm_state *x;
@@ -620,13 +628,16 @@ restart:
620 audit_info->sessionid, 628 audit_info->sessionid,
621 audit_info->secid); 629 audit_info->secid);
622 xfrm_state_put(x); 630 xfrm_state_put(x);
631 if (!err)
632 cnt++;
623 633
624 spin_lock_bh(&xfrm_state_lock); 634 spin_lock_bh(&xfrm_state_lock);
625 goto restart; 635 goto restart;
626 } 636 }
627 } 637 }
628 } 638 }
629 err = 0; 639 if (cnt)
640 err = 0;
630 641
631out: 642out:
632 spin_unlock_bh(&xfrm_state_lock); 643 spin_unlock_bh(&xfrm_state_lock);
@@ -635,11 +646,11 @@ out:
635} 646}
636EXPORT_SYMBOL(xfrm_state_flush); 647EXPORT_SYMBOL(xfrm_state_flush);
637 648
638void xfrm_sad_getinfo(struct xfrmk_sadinfo *si) 649void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si)
639{ 650{
640 spin_lock_bh(&xfrm_state_lock); 651 spin_lock_bh(&xfrm_state_lock);
641 si->sadcnt = init_net.xfrm.state_num; 652 si->sadcnt = net->xfrm.state_num;
642 si->sadhcnt = init_net.xfrm.state_hmask; 653 si->sadhcnt = net->xfrm.state_hmask;
643 si->sadhmcnt = xfrm_state_hashmax; 654 si->sadhmcnt = xfrm_state_hashmax;
644 spin_unlock_bh(&xfrm_state_lock); 655 spin_unlock_bh(&xfrm_state_lock);
645} 656}
@@ -659,7 +670,7 @@ xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl,
659 return 0; 670 return 0;
660} 671}
661 672
662static struct xfrm_state *__xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family) 673static struct xfrm_state *__xfrm_state_lookup(struct net *net, u32 mark, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family)
663{ 674{
664 unsigned int h = xfrm_spi_hash(net, daddr, spi, proto, family); 675 unsigned int h = xfrm_spi_hash(net, daddr, spi, proto, family);
665 struct xfrm_state *x; 676 struct xfrm_state *x;
@@ -672,6 +683,8 @@ static struct xfrm_state *__xfrm_state_lookup(struct net *net, xfrm_address_t *d
672 xfrm_addr_cmp(&x->id.daddr, daddr, family)) 683 xfrm_addr_cmp(&x->id.daddr, daddr, family))
673 continue; 684 continue;
674 685
686 if ((mark & x->mark.m) != x->mark.v)
687 continue;
675 xfrm_state_hold(x); 688 xfrm_state_hold(x);
676 return x; 689 return x;
677 } 690 }
@@ -679,7 +692,7 @@ static struct xfrm_state *__xfrm_state_lookup(struct net *net, xfrm_address_t *d
679 return NULL; 692 return NULL;
680} 693}
681 694
682static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) 695static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, u32 mark, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family)
683{ 696{
684 unsigned int h = xfrm_src_hash(net, daddr, saddr, family); 697 unsigned int h = xfrm_src_hash(net, daddr, saddr, family);
685 struct xfrm_state *x; 698 struct xfrm_state *x;
@@ -692,6 +705,8 @@ static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, xfrm_addre
692 xfrm_addr_cmp(&x->props.saddr, saddr, family)) 705 xfrm_addr_cmp(&x->props.saddr, saddr, family))
693 continue; 706 continue;
694 707
708 if ((mark & x->mark.m) != x->mark.v)
709 continue;
695 xfrm_state_hold(x); 710 xfrm_state_hold(x);
696 return x; 711 return x;
697 } 712 }
@@ -703,12 +718,14 @@ static inline struct xfrm_state *
703__xfrm_state_locate(struct xfrm_state *x, int use_spi, int family) 718__xfrm_state_locate(struct xfrm_state *x, int use_spi, int family)
704{ 719{
705 struct net *net = xs_net(x); 720 struct net *net = xs_net(x);
721 u32 mark = x->mark.v & x->mark.m;
706 722
707 if (use_spi) 723 if (use_spi)
708 return __xfrm_state_lookup(net, &x->id.daddr, x->id.spi, 724 return __xfrm_state_lookup(net, mark, &x->id.daddr,
709 x->id.proto, family); 725 x->id.spi, x->id.proto, family);
710 else 726 else
711 return __xfrm_state_lookup_byaddr(net, &x->id.daddr, 727 return __xfrm_state_lookup_byaddr(net, mark,
728 &x->id.daddr,
712 &x->props.saddr, 729 &x->props.saddr,
713 x->id.proto, family); 730 x->id.proto, family);
714} 731}
@@ -773,6 +790,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
773 int acquire_in_progress = 0; 790 int acquire_in_progress = 0;
774 int error = 0; 791 int error = 0;
775 struct xfrm_state *best = NULL; 792 struct xfrm_state *best = NULL;
793 u32 mark = pol->mark.v & pol->mark.m;
776 794
777 to_put = NULL; 795 to_put = NULL;
778 796
@@ -781,6 +799,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
781 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { 799 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) {
782 if (x->props.family == family && 800 if (x->props.family == family &&
783 x->props.reqid == tmpl->reqid && 801 x->props.reqid == tmpl->reqid &&
802 (mark & x->mark.m) == x->mark.v &&
784 !(x->props.flags & XFRM_STATE_WILDRECV) && 803 !(x->props.flags & XFRM_STATE_WILDRECV) &&
785 xfrm_state_addr_check(x, daddr, saddr, family) && 804 xfrm_state_addr_check(x, daddr, saddr, family) &&
786 tmpl->mode == x->props.mode && 805 tmpl->mode == x->props.mode &&
@@ -796,6 +815,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
796 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h_wildcard, bydst) { 815 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h_wildcard, bydst) {
797 if (x->props.family == family && 816 if (x->props.family == family &&
798 x->props.reqid == tmpl->reqid && 817 x->props.reqid == tmpl->reqid &&
818 (mark & x->mark.m) == x->mark.v &&
799 !(x->props.flags & XFRM_STATE_WILDRECV) && 819 !(x->props.flags & XFRM_STATE_WILDRECV) &&
800 xfrm_state_addr_check(x, daddr, saddr, family) && 820 xfrm_state_addr_check(x, daddr, saddr, family) &&
801 tmpl->mode == x->props.mode && 821 tmpl->mode == x->props.mode &&
@@ -809,7 +829,7 @@ found:
809 x = best; 829 x = best;
810 if (!x && !error && !acquire_in_progress) { 830 if (!x && !error && !acquire_in_progress) {
811 if (tmpl->id.spi && 831 if (tmpl->id.spi &&
812 (x0 = __xfrm_state_lookup(net, daddr, tmpl->id.spi, 832 (x0 = __xfrm_state_lookup(net, mark, daddr, tmpl->id.spi,
813 tmpl->id.proto, family)) != NULL) { 833 tmpl->id.proto, family)) != NULL) {
814 to_put = x0; 834 to_put = x0;
815 error = -EEXIST; 835 error = -EEXIST;
@@ -823,6 +843,7 @@ found:
823 /* Initialize temporary selector matching only 843 /* Initialize temporary selector matching only
824 * to current session. */ 844 * to current session. */
825 xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family); 845 xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family);
846 memcpy(&x->mark, &pol->mark, sizeof(x->mark));
826 847
827 error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid); 848 error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid);
828 if (error) { 849 if (error) {
@@ -843,8 +864,7 @@ found:
843 hlist_add_head(&x->byspi, net->xfrm.state_byspi+h); 864 hlist_add_head(&x->byspi, net->xfrm.state_byspi+h);
844 } 865 }
845 x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; 866 x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires;
846 x->timer.expires = jiffies + net->xfrm.sysctl_acq_expires*HZ; 867 tasklet_hrtimer_start(&x->mtimer, ktime_set(net->xfrm.sysctl_acq_expires, 0), HRTIMER_MODE_REL);
847 add_timer(&x->timer);
848 net->xfrm.state_num++; 868 net->xfrm.state_num++;
849 xfrm_hash_grow_check(net, x->bydst.next != NULL); 869 xfrm_hash_grow_check(net, x->bydst.next != NULL);
850 } else { 870 } else {
@@ -866,7 +886,7 @@ out:
866} 886}
867 887
868struct xfrm_state * 888struct xfrm_state *
869xfrm_stateonly_find(struct net *net, 889xfrm_stateonly_find(struct net *net, u32 mark,
870 xfrm_address_t *daddr, xfrm_address_t *saddr, 890 xfrm_address_t *daddr, xfrm_address_t *saddr,
871 unsigned short family, u8 mode, u8 proto, u32 reqid) 891 unsigned short family, u8 mode, u8 proto, u32 reqid)
872{ 892{
@@ -879,6 +899,7 @@ xfrm_stateonly_find(struct net *net,
879 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { 899 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) {
880 if (x->props.family == family && 900 if (x->props.family == family &&
881 x->props.reqid == reqid && 901 x->props.reqid == reqid &&
902 (mark & x->mark.m) == x->mark.v &&
882 !(x->props.flags & XFRM_STATE_WILDRECV) && 903 !(x->props.flags & XFRM_STATE_WILDRECV) &&
883 xfrm_state_addr_check(x, daddr, saddr, family) && 904 xfrm_state_addr_check(x, daddr, saddr, family) &&
884 mode == x->props.mode && 905 mode == x->props.mode &&
@@ -921,7 +942,7 @@ static void __xfrm_state_insert(struct xfrm_state *x)
921 hlist_add_head(&x->byspi, net->xfrm.state_byspi+h); 942 hlist_add_head(&x->byspi, net->xfrm.state_byspi+h);
922 } 943 }
923 944
924 mod_timer(&x->timer, jiffies + HZ); 945 tasklet_hrtimer_start(&x->mtimer, ktime_set(1, 0), HRTIMER_MODE_REL);
925 if (x->replay_maxage) 946 if (x->replay_maxage)
926 mod_timer(&x->rtimer, jiffies + x->replay_maxage); 947 mod_timer(&x->rtimer, jiffies + x->replay_maxage);
927 948
@@ -941,11 +962,13 @@ static void __xfrm_state_bump_genids(struct xfrm_state *xnew)
941 struct xfrm_state *x; 962 struct xfrm_state *x;
942 struct hlist_node *entry; 963 struct hlist_node *entry;
943 unsigned int h; 964 unsigned int h;
965 u32 mark = xnew->mark.v & xnew->mark.m;
944 966
945 h = xfrm_dst_hash(net, &xnew->id.daddr, &xnew->props.saddr, reqid, family); 967 h = xfrm_dst_hash(net, &xnew->id.daddr, &xnew->props.saddr, reqid, family);
946 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { 968 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) {
947 if (x->props.family == family && 969 if (x->props.family == family &&
948 x->props.reqid == reqid && 970 x->props.reqid == reqid &&
971 (mark & x->mark.m) == x->mark.v &&
949 !xfrm_addr_cmp(&x->id.daddr, &xnew->id.daddr, family) && 972 !xfrm_addr_cmp(&x->id.daddr, &xnew->id.daddr, family) &&
950 !xfrm_addr_cmp(&x->props.saddr, &xnew->props.saddr, family)) 973 !xfrm_addr_cmp(&x->props.saddr, &xnew->props.saddr, family))
951 x->genid = xfrm_state_genid; 974 x->genid = xfrm_state_genid;
@@ -962,11 +985,12 @@ void xfrm_state_insert(struct xfrm_state *x)
962EXPORT_SYMBOL(xfrm_state_insert); 985EXPORT_SYMBOL(xfrm_state_insert);
963 986
964/* xfrm_state_lock is held */ 987/* xfrm_state_lock is held */
965static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create) 988static struct xfrm_state *__find_acq_core(struct net *net, struct xfrm_mark *m, unsigned short family, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create)
966{ 989{
967 unsigned int h = xfrm_dst_hash(net, daddr, saddr, reqid, family); 990 unsigned int h = xfrm_dst_hash(net, daddr, saddr, reqid, family);
968 struct hlist_node *entry; 991 struct hlist_node *entry;
969 struct xfrm_state *x; 992 struct xfrm_state *x;
993 u32 mark = m->v & m->m;
970 994
971 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { 995 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) {
972 if (x->props.reqid != reqid || 996 if (x->props.reqid != reqid ||
@@ -975,6 +999,7 @@ static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family
975 x->km.state != XFRM_STATE_ACQ || 999 x->km.state != XFRM_STATE_ACQ ||
976 x->id.spi != 0 || 1000 x->id.spi != 0 ||
977 x->id.proto != proto || 1001 x->id.proto != proto ||
1002 (mark & x->mark.m) != x->mark.v ||
978 xfrm_addr_cmp(&x->id.daddr, daddr, family) || 1003 xfrm_addr_cmp(&x->id.daddr, daddr, family) ||
979 xfrm_addr_cmp(&x->props.saddr, saddr, family)) 1004 xfrm_addr_cmp(&x->props.saddr, saddr, family))
980 continue; 1005 continue;
@@ -1017,10 +1042,11 @@ static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family
1017 x->props.family = family; 1042 x->props.family = family;
1018 x->props.mode = mode; 1043 x->props.mode = mode;
1019 x->props.reqid = reqid; 1044 x->props.reqid = reqid;
1045 x->mark.v = m->v;
1046 x->mark.m = m->m;
1020 x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; 1047 x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires;
1021 xfrm_state_hold(x); 1048 xfrm_state_hold(x);
1022 x->timer.expires = jiffies + net->xfrm.sysctl_acq_expires*HZ; 1049 tasklet_hrtimer_start(&x->mtimer, ktime_set(net->xfrm.sysctl_acq_expires, 0), HRTIMER_MODE_REL);
1023 add_timer(&x->timer);
1024 list_add(&x->km.all, &net->xfrm.state_all); 1050 list_add(&x->km.all, &net->xfrm.state_all);
1025 hlist_add_head(&x->bydst, net->xfrm.state_bydst+h); 1051 hlist_add_head(&x->bydst, net->xfrm.state_bydst+h);
1026 h = xfrm_src_hash(net, daddr, saddr, family); 1052 h = xfrm_src_hash(net, daddr, saddr, family);
@@ -1034,7 +1060,7 @@ static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family
1034 return x; 1060 return x;
1035} 1061}
1036 1062
1037static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq); 1063static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq);
1038 1064
1039int xfrm_state_add(struct xfrm_state *x) 1065int xfrm_state_add(struct xfrm_state *x)
1040{ 1066{
@@ -1042,6 +1068,7 @@ int xfrm_state_add(struct xfrm_state *x)
1042 struct xfrm_state *x1, *to_put; 1068 struct xfrm_state *x1, *to_put;
1043 int family; 1069 int family;
1044 int err; 1070 int err;
1071 u32 mark = x->mark.v & x->mark.m;
1045 int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY); 1072 int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY);
1046 1073
1047 family = x->props.family; 1074 family = x->props.family;
@@ -1059,7 +1086,7 @@ int xfrm_state_add(struct xfrm_state *x)
1059 } 1086 }
1060 1087
1061 if (use_spi && x->km.seq) { 1088 if (use_spi && x->km.seq) {
1062 x1 = __xfrm_find_acq_byseq(net, x->km.seq); 1089 x1 = __xfrm_find_acq_byseq(net, mark, x->km.seq);
1063 if (x1 && ((x1->id.proto != x->id.proto) || 1090 if (x1 && ((x1->id.proto != x->id.proto) ||
1064 xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) { 1091 xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) {
1065 to_put = x1; 1092 to_put = x1;
@@ -1068,8 +1095,8 @@ int xfrm_state_add(struct xfrm_state *x)
1068 } 1095 }
1069 1096
1070 if (use_spi && !x1) 1097 if (use_spi && !x1)
1071 x1 = __find_acq_core(net, family, x->props.mode, x->props.reqid, 1098 x1 = __find_acq_core(net, &x->mark, family, x->props.mode,
1072 x->id.proto, 1099 x->props.reqid, x->id.proto,
1073 &x->id.daddr, &x->props.saddr, 0); 1100 &x->id.daddr, &x->props.saddr, 0);
1074 1101
1075 __xfrm_state_bump_genids(x); 1102 __xfrm_state_bump_genids(x);
@@ -1098,7 +1125,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
1098 int err = -ENOMEM; 1125 int err = -ENOMEM;
1099 struct xfrm_state *x = xfrm_state_alloc(net); 1126 struct xfrm_state *x = xfrm_state_alloc(net);
1100 if (!x) 1127 if (!x)
1101 goto error; 1128 goto out;
1102 1129
1103 memcpy(&x->id, &orig->id, sizeof(x->id)); 1130 memcpy(&x->id, &orig->id, sizeof(x->id));
1104 memcpy(&x->sel, &orig->sel, sizeof(x->sel)); 1131 memcpy(&x->sel, &orig->sel, sizeof(x->sel));
@@ -1110,7 +1137,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
1110 x->props.saddr = orig->props.saddr; 1137 x->props.saddr = orig->props.saddr;
1111 1138
1112 if (orig->aalg) { 1139 if (orig->aalg) {
1113 x->aalg = xfrm_algo_clone(orig->aalg); 1140 x->aalg = xfrm_algo_auth_clone(orig->aalg);
1114 if (!x->aalg) 1141 if (!x->aalg)
1115 goto error; 1142 goto error;
1116 } 1143 }
@@ -1143,6 +1170,8 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
1143 goto error; 1170 goto error;
1144 } 1171 }
1145 1172
1173 memcpy(&x->mark, &orig->mark, sizeof(x->mark));
1174
1146 err = xfrm_init_state(x); 1175 err = xfrm_init_state(x);
1147 if (err) 1176 if (err)
1148 goto error; 1177 goto error;
@@ -1156,16 +1185,10 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
1156 return x; 1185 return x;
1157 1186
1158 error: 1187 error:
1188 xfrm_state_put(x);
1189out:
1159 if (errp) 1190 if (errp)
1160 *errp = err; 1191 *errp = err;
1161 if (x) {
1162 kfree(x->aalg);
1163 kfree(x->ealg);
1164 kfree(x->calg);
1165 kfree(x->encap);
1166 kfree(x->coaddr);
1167 }
1168 kfree(x);
1169 return NULL; 1192 return NULL;
1170} 1193}
1171 1194
@@ -1300,7 +1323,7 @@ out:
1300 memcpy(&x1->lft, &x->lft, sizeof(x1->lft)); 1323 memcpy(&x1->lft, &x->lft, sizeof(x1->lft));
1301 x1->km.dying = 0; 1324 x1->km.dying = 0;
1302 1325
1303 mod_timer(&x1->timer, jiffies + HZ); 1326 tasklet_hrtimer_start(&x1->mtimer, ktime_set(1, 0), HRTIMER_MODE_REL);
1304 if (x1->curlft.use_time) 1327 if (x1->curlft.use_time)
1305 xfrm_state_check_expire(x1); 1328 xfrm_state_check_expire(x1);
1306 1329
@@ -1325,7 +1348,7 @@ int xfrm_state_check_expire(struct xfrm_state *x)
1325 if (x->curlft.bytes >= x->lft.hard_byte_limit || 1348 if (x->curlft.bytes >= x->lft.hard_byte_limit ||
1326 x->curlft.packets >= x->lft.hard_packet_limit) { 1349 x->curlft.packets >= x->lft.hard_packet_limit) {
1327 x->km.state = XFRM_STATE_EXPIRED; 1350 x->km.state = XFRM_STATE_EXPIRED;
1328 mod_timer(&x->timer, jiffies); 1351 tasklet_hrtimer_start(&x->mtimer, ktime_set(0,0), HRTIMER_MODE_REL);
1329 return -EINVAL; 1352 return -EINVAL;
1330 } 1353 }
1331 1354
@@ -1340,41 +1363,41 @@ int xfrm_state_check_expire(struct xfrm_state *x)
1340EXPORT_SYMBOL(xfrm_state_check_expire); 1363EXPORT_SYMBOL(xfrm_state_check_expire);
1341 1364
1342struct xfrm_state * 1365struct xfrm_state *
1343xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, 1366xfrm_state_lookup(struct net *net, u32 mark, xfrm_address_t *daddr, __be32 spi,
1344 unsigned short family) 1367 u8 proto, unsigned short family)
1345{ 1368{
1346 struct xfrm_state *x; 1369 struct xfrm_state *x;
1347 1370
1348 spin_lock_bh(&xfrm_state_lock); 1371 spin_lock_bh(&xfrm_state_lock);
1349 x = __xfrm_state_lookup(net, daddr, spi, proto, family); 1372 x = __xfrm_state_lookup(net, mark, daddr, spi, proto, family);
1350 spin_unlock_bh(&xfrm_state_lock); 1373 spin_unlock_bh(&xfrm_state_lock);
1351 return x; 1374 return x;
1352} 1375}
1353EXPORT_SYMBOL(xfrm_state_lookup); 1376EXPORT_SYMBOL(xfrm_state_lookup);
1354 1377
1355struct xfrm_state * 1378struct xfrm_state *
1356xfrm_state_lookup_byaddr(struct net *net, 1379xfrm_state_lookup_byaddr(struct net *net, u32 mark,
1357 xfrm_address_t *daddr, xfrm_address_t *saddr, 1380 xfrm_address_t *daddr, xfrm_address_t *saddr,
1358 u8 proto, unsigned short family) 1381 u8 proto, unsigned short family)
1359{ 1382{
1360 struct xfrm_state *x; 1383 struct xfrm_state *x;
1361 1384
1362 spin_lock_bh(&xfrm_state_lock); 1385 spin_lock_bh(&xfrm_state_lock);
1363 x = __xfrm_state_lookup_byaddr(net, daddr, saddr, proto, family); 1386 x = __xfrm_state_lookup_byaddr(net, mark, daddr, saddr, proto, family);
1364 spin_unlock_bh(&xfrm_state_lock); 1387 spin_unlock_bh(&xfrm_state_lock);
1365 return x; 1388 return x;
1366} 1389}
1367EXPORT_SYMBOL(xfrm_state_lookup_byaddr); 1390EXPORT_SYMBOL(xfrm_state_lookup_byaddr);
1368 1391
1369struct xfrm_state * 1392struct xfrm_state *
1370xfrm_find_acq(struct net *net, u8 mode, u32 reqid, u8 proto, 1393xfrm_find_acq(struct net *net, struct xfrm_mark *mark, u8 mode, u32 reqid, u8 proto,
1371 xfrm_address_t *daddr, xfrm_address_t *saddr, 1394 xfrm_address_t *daddr, xfrm_address_t *saddr,
1372 int create, unsigned short family) 1395 int create, unsigned short family)
1373{ 1396{
1374 struct xfrm_state *x; 1397 struct xfrm_state *x;
1375 1398
1376 spin_lock_bh(&xfrm_state_lock); 1399 spin_lock_bh(&xfrm_state_lock);
1377 x = __find_acq_core(net, family, mode, reqid, proto, daddr, saddr, create); 1400 x = __find_acq_core(net, mark, family, mode, reqid, proto, daddr, saddr, create);
1378 spin_unlock_bh(&xfrm_state_lock); 1401 spin_unlock_bh(&xfrm_state_lock);
1379 1402
1380 return x; 1403 return x;
@@ -1421,7 +1444,7 @@ EXPORT_SYMBOL(xfrm_state_sort);
1421 1444
1422/* Silly enough, but I'm lazy to build resolution list */ 1445/* Silly enough, but I'm lazy to build resolution list */
1423 1446
1424static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq) 1447static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq)
1425{ 1448{
1426 int i; 1449 int i;
1427 1450
@@ -1431,6 +1454,7 @@ static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq)
1431 1454
1432 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+i, bydst) { 1455 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+i, bydst) {
1433 if (x->km.seq == seq && 1456 if (x->km.seq == seq &&
1457 (mark & x->mark.m) == x->mark.v &&
1434 x->km.state == XFRM_STATE_ACQ) { 1458 x->km.state == XFRM_STATE_ACQ) {
1435 xfrm_state_hold(x); 1459 xfrm_state_hold(x);
1436 return x; 1460 return x;
@@ -1440,12 +1464,12 @@ static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq)
1440 return NULL; 1464 return NULL;
1441} 1465}
1442 1466
1443struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 seq) 1467struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq)
1444{ 1468{
1445 struct xfrm_state *x; 1469 struct xfrm_state *x;
1446 1470
1447 spin_lock_bh(&xfrm_state_lock); 1471 spin_lock_bh(&xfrm_state_lock);
1448 x = __xfrm_find_acq_byseq(net, seq); 1472 x = __xfrm_find_acq_byseq(net, mark, seq);
1449 spin_unlock_bh(&xfrm_state_lock); 1473 spin_unlock_bh(&xfrm_state_lock);
1450 return x; 1474 return x;
1451} 1475}
@@ -1454,12 +1478,12 @@ EXPORT_SYMBOL(xfrm_find_acq_byseq);
1454u32 xfrm_get_acqseq(void) 1478u32 xfrm_get_acqseq(void)
1455{ 1479{
1456 u32 res; 1480 u32 res;
1457 static u32 acqseq; 1481 static atomic_t acqseq;
1458 static DEFINE_SPINLOCK(acqseq_lock); 1482
1483 do {
1484 res = atomic_inc_return(&acqseq);
1485 } while (!res);
1459 1486
1460 spin_lock_bh(&acqseq_lock);
1461 res = (++acqseq ? : ++acqseq);
1462 spin_unlock_bh(&acqseq_lock);
1463 return res; 1487 return res;
1464} 1488}
1465EXPORT_SYMBOL(xfrm_get_acqseq); 1489EXPORT_SYMBOL(xfrm_get_acqseq);
@@ -1472,6 +1496,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
1472 int err = -ENOENT; 1496 int err = -ENOENT;
1473 __be32 minspi = htonl(low); 1497 __be32 minspi = htonl(low);
1474 __be32 maxspi = htonl(high); 1498 __be32 maxspi = htonl(high);
1499 u32 mark = x->mark.v & x->mark.m;
1475 1500
1476 spin_lock_bh(&x->lock); 1501 spin_lock_bh(&x->lock);
1477 if (x->km.state == XFRM_STATE_DEAD) 1502 if (x->km.state == XFRM_STATE_DEAD)
@@ -1484,7 +1509,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
1484 err = -ENOENT; 1509 err = -ENOENT;
1485 1510
1486 if (minspi == maxspi) { 1511 if (minspi == maxspi) {
1487 x0 = xfrm_state_lookup(net, &x->id.daddr, minspi, x->id.proto, x->props.family); 1512 x0 = xfrm_state_lookup(net, mark, &x->id.daddr, minspi, x->id.proto, x->props.family);
1488 if (x0) { 1513 if (x0) {
1489 xfrm_state_put(x0); 1514 xfrm_state_put(x0);
1490 goto unlock; 1515 goto unlock;
@@ -1494,7 +1519,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
1494 u32 spi = 0; 1519 u32 spi = 0;
1495 for (h=0; h<high-low+1; h++) { 1520 for (h=0; h<high-low+1; h++) {
1496 spi = low + net_random()%(high-low+1); 1521 spi = low + net_random()%(high-low+1);
1497 x0 = xfrm_state_lookup(net, &x->id.daddr, htonl(spi), x->id.proto, x->props.family); 1522 x0 = xfrm_state_lookup(net, mark, &x->id.daddr, htonl(spi), x->id.proto, x->props.family);
1498 if (x0 == NULL) { 1523 if (x0 == NULL) {
1499 x->id.spi = htonl(spi); 1524 x->id.spi = htonl(spi);
1500 break; 1525 break;