diff options
-rw-r--r-- | include/net/netns/xfrm.h | 10 | ||||
-rw-r--r-- | include/net/xfrm.h | 1 | ||||
-rw-r--r-- | include/uapi/linux/xfrm.h | 7 | ||||
-rw-r--r-- | net/xfrm/xfrm_policy.c | 87 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 80 |
5 files changed, 182 insertions, 3 deletions
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h index 41902a8103bd..9da798256f0e 100644 --- a/include/net/netns/xfrm.h +++ b/include/net/netns/xfrm.h | |||
@@ -19,6 +19,15 @@ struct xfrm_policy_hash { | |||
19 | u8 sbits6; | 19 | u8 sbits6; |
20 | }; | 20 | }; |
21 | 21 | ||
22 | struct xfrm_policy_hthresh { | ||
23 | struct work_struct work; | ||
24 | seqlock_t lock; | ||
25 | u8 lbits4; | ||
26 | u8 rbits4; | ||
27 | u8 lbits6; | ||
28 | u8 rbits6; | ||
29 | }; | ||
30 | |||
22 | struct netns_xfrm { | 31 | struct netns_xfrm { |
23 | struct list_head state_all; | 32 | struct list_head state_all; |
24 | /* | 33 | /* |
@@ -45,6 +54,7 @@ struct netns_xfrm { | |||
45 | struct xfrm_policy_hash policy_bydst[XFRM_POLICY_MAX * 2]; | 54 | struct xfrm_policy_hash policy_bydst[XFRM_POLICY_MAX * 2]; |
46 | unsigned int policy_count[XFRM_POLICY_MAX * 2]; | 55 | unsigned int policy_count[XFRM_POLICY_MAX * 2]; |
47 | struct work_struct policy_hash_work; | 56 | struct work_struct policy_hash_work; |
57 | struct xfrm_policy_hthresh policy_hthresh; | ||
48 | 58 | ||
49 | 59 | ||
50 | struct sock *nlsk; | 60 | struct sock *nlsk; |
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 721e9c3b11bd..dc4865e90fe4 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
@@ -1591,6 +1591,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, | |||
1591 | struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8, int dir, | 1591 | struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8, int dir, |
1592 | u32 id, int delete, int *err); | 1592 | u32 id, int delete, int *err); |
1593 | int xfrm_policy_flush(struct net *net, u8 type, bool task_valid); | 1593 | int xfrm_policy_flush(struct net *net, u8 type, bool task_valid); |
1594 | void xfrm_policy_hash_rebuild(struct net *net); | ||
1594 | u32 xfrm_get_acqseq(void); | 1595 | u32 xfrm_get_acqseq(void); |
1595 | int verify_spi_info(u8 proto, u32 min, u32 max); | 1596 | int verify_spi_info(u8 proto, u32 min, u32 max); |
1596 | int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi); | 1597 | int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi); |
diff --git a/include/uapi/linux/xfrm.h b/include/uapi/linux/xfrm.h index 25e5dd916ba4..02d5125a5ee8 100644 --- a/include/uapi/linux/xfrm.h +++ b/include/uapi/linux/xfrm.h | |||
@@ -328,6 +328,8 @@ enum xfrm_spdattr_type_t { | |||
328 | XFRMA_SPD_UNSPEC, | 328 | XFRMA_SPD_UNSPEC, |
329 | XFRMA_SPD_INFO, | 329 | XFRMA_SPD_INFO, |
330 | XFRMA_SPD_HINFO, | 330 | XFRMA_SPD_HINFO, |
331 | XFRMA_SPD_IPV4_HTHRESH, | ||
332 | XFRMA_SPD_IPV6_HTHRESH, | ||
331 | __XFRMA_SPD_MAX | 333 | __XFRMA_SPD_MAX |
332 | 334 | ||
333 | #define XFRMA_SPD_MAX (__XFRMA_SPD_MAX - 1) | 335 | #define XFRMA_SPD_MAX (__XFRMA_SPD_MAX - 1) |
@@ -347,6 +349,11 @@ struct xfrmu_spdhinfo { | |||
347 | __u32 spdhmcnt; | 349 | __u32 spdhmcnt; |
348 | }; | 350 | }; |
349 | 351 | ||
352 | struct xfrmu_spdhthresh { | ||
353 | __u8 lbits; | ||
354 | __u8 rbits; | ||
355 | }; | ||
356 | |||
350 | struct xfrm_usersa_info { | 357 | struct xfrm_usersa_info { |
351 | struct xfrm_selector sel; | 358 | struct xfrm_selector sel; |
352 | struct xfrm_id id; | 359 | struct xfrm_id id; |
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 | ||
569 | static 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 | |||
643 | void xfrm_policy_hash_rebuild(struct net *net) | ||
644 | { | ||
645 | schedule_work(&net->xfrm.policy_hthresh.work); | ||
646 | } | ||
647 | EXPORT_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. */ |
571 | static u32 xfrm_gen_index(struct net *net, int dir, u32 index) | 651 | static 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; |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index d4db6ebb089d..eaf8a8f1cbe8 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -964,7 +964,9 @@ static inline size_t xfrm_spdinfo_msgsize(void) | |||
964 | { | 964 | { |
965 | return NLMSG_ALIGN(4) | 965 | return NLMSG_ALIGN(4) |
966 | + nla_total_size(sizeof(struct xfrmu_spdinfo)) | 966 | + nla_total_size(sizeof(struct xfrmu_spdinfo)) |
967 | + nla_total_size(sizeof(struct xfrmu_spdhinfo)); | 967 | + nla_total_size(sizeof(struct xfrmu_spdhinfo)) |
968 | + nla_total_size(sizeof(struct xfrmu_spdhthresh)) | ||
969 | + nla_total_size(sizeof(struct xfrmu_spdhthresh)); | ||
968 | } | 970 | } |
969 | 971 | ||
970 | static int build_spdinfo(struct sk_buff *skb, struct net *net, | 972 | static int build_spdinfo(struct sk_buff *skb, struct net *net, |
@@ -973,9 +975,11 @@ static int build_spdinfo(struct sk_buff *skb, struct net *net, | |||
973 | struct xfrmk_spdinfo si; | 975 | struct xfrmk_spdinfo si; |
974 | struct xfrmu_spdinfo spc; | 976 | struct xfrmu_spdinfo spc; |
975 | struct xfrmu_spdhinfo sph; | 977 | struct xfrmu_spdhinfo sph; |
978 | struct xfrmu_spdhthresh spt4, spt6; | ||
976 | struct nlmsghdr *nlh; | 979 | struct nlmsghdr *nlh; |
977 | int err; | 980 | int err; |
978 | u32 *f; | 981 | u32 *f; |
982 | unsigned lseq; | ||
979 | 983 | ||
980 | nlh = nlmsg_put(skb, portid, seq, XFRM_MSG_NEWSPDINFO, sizeof(u32), 0); | 984 | nlh = nlmsg_put(skb, portid, seq, XFRM_MSG_NEWSPDINFO, sizeof(u32), 0); |
981 | if (nlh == NULL) /* shouldn't really happen ... */ | 985 | if (nlh == NULL) /* shouldn't really happen ... */ |
@@ -993,9 +997,22 @@ static int build_spdinfo(struct sk_buff *skb, struct net *net, | |||
993 | sph.spdhcnt = si.spdhcnt; | 997 | sph.spdhcnt = si.spdhcnt; |
994 | sph.spdhmcnt = si.spdhmcnt; | 998 | sph.spdhmcnt = si.spdhmcnt; |
995 | 999 | ||
1000 | do { | ||
1001 | lseq = read_seqbegin(&net->xfrm.policy_hthresh.lock); | ||
1002 | |||
1003 | spt4.lbits = net->xfrm.policy_hthresh.lbits4; | ||
1004 | spt4.rbits = net->xfrm.policy_hthresh.rbits4; | ||
1005 | spt6.lbits = net->xfrm.policy_hthresh.lbits6; | ||
1006 | spt6.rbits = net->xfrm.policy_hthresh.rbits6; | ||
1007 | } while (read_seqretry(&net->xfrm.policy_hthresh.lock, lseq)); | ||
1008 | |||
996 | err = nla_put(skb, XFRMA_SPD_INFO, sizeof(spc), &spc); | 1009 | err = nla_put(skb, XFRMA_SPD_INFO, sizeof(spc), &spc); |
997 | if (!err) | 1010 | if (!err) |
998 | err = nla_put(skb, XFRMA_SPD_HINFO, sizeof(sph), &sph); | 1011 | err = nla_put(skb, XFRMA_SPD_HINFO, sizeof(sph), &sph); |
1012 | if (!err) | ||
1013 | err = nla_put(skb, XFRMA_SPD_IPV4_HTHRESH, sizeof(spt4), &spt4); | ||
1014 | if (!err) | ||
1015 | err = nla_put(skb, XFRMA_SPD_IPV6_HTHRESH, sizeof(spt6), &spt6); | ||
999 | if (err) { | 1016 | if (err) { |
1000 | nlmsg_cancel(skb, nlh); | 1017 | nlmsg_cancel(skb, nlh); |
1001 | return err; | 1018 | return err; |
@@ -1004,6 +1021,51 @@ static int build_spdinfo(struct sk_buff *skb, struct net *net, | |||
1004 | return nlmsg_end(skb, nlh); | 1021 | return nlmsg_end(skb, nlh); |
1005 | } | 1022 | } |
1006 | 1023 | ||
1024 | static int xfrm_set_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh, | ||
1025 | struct nlattr **attrs) | ||
1026 | { | ||
1027 | struct net *net = sock_net(skb->sk); | ||
1028 | struct xfrmu_spdhthresh *thresh4 = NULL; | ||
1029 | struct xfrmu_spdhthresh *thresh6 = NULL; | ||
1030 | |||
1031 | /* selector prefixlen thresholds to hash policies */ | ||
1032 | if (attrs[XFRMA_SPD_IPV4_HTHRESH]) { | ||
1033 | struct nlattr *rta = attrs[XFRMA_SPD_IPV4_HTHRESH]; | ||
1034 | |||
1035 | if (nla_len(rta) < sizeof(*thresh4)) | ||
1036 | return -EINVAL; | ||
1037 | thresh4 = nla_data(rta); | ||
1038 | if (thresh4->lbits > 32 || thresh4->rbits > 32) | ||
1039 | return -EINVAL; | ||
1040 | } | ||
1041 | if (attrs[XFRMA_SPD_IPV6_HTHRESH]) { | ||
1042 | struct nlattr *rta = attrs[XFRMA_SPD_IPV6_HTHRESH]; | ||
1043 | |||
1044 | if (nla_len(rta) < sizeof(*thresh6)) | ||
1045 | return -EINVAL; | ||
1046 | thresh6 = nla_data(rta); | ||
1047 | if (thresh6->lbits > 128 || thresh6->rbits > 128) | ||
1048 | return -EINVAL; | ||
1049 | } | ||
1050 | |||
1051 | if (thresh4 || thresh6) { | ||
1052 | write_seqlock(&net->xfrm.policy_hthresh.lock); | ||
1053 | if (thresh4) { | ||
1054 | net->xfrm.policy_hthresh.lbits4 = thresh4->lbits; | ||
1055 | net->xfrm.policy_hthresh.rbits4 = thresh4->rbits; | ||
1056 | } | ||
1057 | if (thresh6) { | ||
1058 | net->xfrm.policy_hthresh.lbits6 = thresh6->lbits; | ||
1059 | net->xfrm.policy_hthresh.rbits6 = thresh6->rbits; | ||
1060 | } | ||
1061 | write_sequnlock(&net->xfrm.policy_hthresh.lock); | ||
1062 | |||
1063 | xfrm_policy_hash_rebuild(net); | ||
1064 | } | ||
1065 | |||
1066 | return 0; | ||
1067 | } | ||
1068 | |||
1007 | static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh, | 1069 | static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh, |
1008 | struct nlattr **attrs) | 1070 | struct nlattr **attrs) |
1009 | { | 1071 | { |
@@ -2274,6 +2336,7 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { | |||
2274 | [XFRM_MSG_REPORT - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_report), | 2336 | [XFRM_MSG_REPORT - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_report), |
2275 | [XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), | 2337 | [XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), |
2276 | [XFRM_MSG_GETSADINFO - XFRM_MSG_BASE] = sizeof(u32), | 2338 | [XFRM_MSG_GETSADINFO - XFRM_MSG_BASE] = sizeof(u32), |
2339 | [XFRM_MSG_NEWSPDINFO - XFRM_MSG_BASE] = sizeof(u32), | ||
2277 | [XFRM_MSG_GETSPDINFO - XFRM_MSG_BASE] = sizeof(u32), | 2340 | [XFRM_MSG_GETSPDINFO - XFRM_MSG_BASE] = sizeof(u32), |
2278 | }; | 2341 | }; |
2279 | 2342 | ||
@@ -2308,10 +2371,17 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { | |||
2308 | [XFRMA_ADDRESS_FILTER] = { .len = sizeof(struct xfrm_address_filter) }, | 2371 | [XFRMA_ADDRESS_FILTER] = { .len = sizeof(struct xfrm_address_filter) }, |
2309 | }; | 2372 | }; |
2310 | 2373 | ||
2374 | static const struct nla_policy xfrma_spd_policy[XFRMA_SPD_MAX+1] = { | ||
2375 | [XFRMA_SPD_IPV4_HTHRESH] = { .len = sizeof(struct xfrmu_spdhthresh) }, | ||
2376 | [XFRMA_SPD_IPV6_HTHRESH] = { .len = sizeof(struct xfrmu_spdhthresh) }, | ||
2377 | }; | ||
2378 | |||
2311 | static const struct xfrm_link { | 2379 | static const struct xfrm_link { |
2312 | int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **); | 2380 | int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **); |
2313 | int (*dump)(struct sk_buff *, struct netlink_callback *); | 2381 | int (*dump)(struct sk_buff *, struct netlink_callback *); |
2314 | int (*done)(struct netlink_callback *); | 2382 | int (*done)(struct netlink_callback *); |
2383 | const struct nla_policy *nla_pol; | ||
2384 | int nla_max; | ||
2315 | } xfrm_dispatch[XFRM_NR_MSGTYPES] = { | 2385 | } xfrm_dispatch[XFRM_NR_MSGTYPES] = { |
2316 | [XFRM_MSG_NEWSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa }, | 2386 | [XFRM_MSG_NEWSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa }, |
2317 | [XFRM_MSG_DELSA - XFRM_MSG_BASE] = { .doit = xfrm_del_sa }, | 2387 | [XFRM_MSG_DELSA - XFRM_MSG_BASE] = { .doit = xfrm_del_sa }, |
@@ -2335,6 +2405,9 @@ static const struct xfrm_link { | |||
2335 | [XFRM_MSG_GETAE - XFRM_MSG_BASE] = { .doit = xfrm_get_ae }, | 2405 | [XFRM_MSG_GETAE - XFRM_MSG_BASE] = { .doit = xfrm_get_ae }, |
2336 | [XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = { .doit = xfrm_do_migrate }, | 2406 | [XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = { .doit = xfrm_do_migrate }, |
2337 | [XFRM_MSG_GETSADINFO - XFRM_MSG_BASE] = { .doit = xfrm_get_sadinfo }, | 2407 | [XFRM_MSG_GETSADINFO - XFRM_MSG_BASE] = { .doit = xfrm_get_sadinfo }, |
2408 | [XFRM_MSG_NEWSPDINFO - XFRM_MSG_BASE] = { .doit = xfrm_set_spdinfo, | ||
2409 | .nla_pol = xfrma_spd_policy, | ||
2410 | .nla_max = XFRMA_SPD_MAX }, | ||
2338 | [XFRM_MSG_GETSPDINFO - XFRM_MSG_BASE] = { .doit = xfrm_get_spdinfo }, | 2411 | [XFRM_MSG_GETSPDINFO - XFRM_MSG_BASE] = { .doit = xfrm_get_spdinfo }, |
2339 | }; | 2412 | }; |
2340 | 2413 | ||
@@ -2371,8 +2444,9 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
2371 | } | 2444 | } |
2372 | } | 2445 | } |
2373 | 2446 | ||
2374 | err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs, XFRMA_MAX, | 2447 | err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs, |
2375 | xfrma_policy); | 2448 | link->nla_max ? : XFRMA_MAX, |
2449 | link->nla_pol ? : xfrma_policy); | ||
2376 | if (err < 0) | 2450 | if (err < 0) |
2377 | return err; | 2451 | return err; |
2378 | 2452 | ||