diff options
author | Jamal Hadi Salim <hadi@cyberus.ca> | 2007-04-26 03:10:29 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2007-04-26 03:10:29 -0400 |
commit | 28d8909bc790d936ce33f4402adf7577533bbd4b (patch) | |
tree | 8de479d6660aba23bc99fa555c150852548df58d | |
parent | 98486fa2f4894e2b01e325c659635596bdec1614 (diff) |
[XFRM]: Export SAD info.
On a system with a lot of SAs, counting SAD entries chews useful
CPU time since you need to dump the whole SAD to user space;
i.e something like ip xfrm state ls | grep -i src | wc -l
I have seen taking literally minutes on a 40K SAs when the system
is swapping.
With this patch, some of the SAD info (that was already being tracked)
is exposed to user space. i.e you do:
ip xfrm state count
And you get the count; you can also pass -s to the command line and
get the hash info.
Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/xfrm.h | 25 | ||||
-rw-r--r-- | include/net/xfrm.h | 8 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 10 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 56 |
4 files changed, 99 insertions, 0 deletions
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index 15ca89e9961b..9c656a5cf842 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h | |||
@@ -181,6 +181,10 @@ enum { | |||
181 | XFRM_MSG_MIGRATE, | 181 | XFRM_MSG_MIGRATE, |
182 | #define XFRM_MSG_MIGRATE XFRM_MSG_MIGRATE | 182 | #define XFRM_MSG_MIGRATE XFRM_MSG_MIGRATE |
183 | 183 | ||
184 | XFRM_MSG_NEWSADINFO, | ||
185 | #define XFRM_MSG_NEWSADINFO XFRM_MSG_NEWSADINFO | ||
186 | XFRM_MSG_GETSADINFO, | ||
187 | #define XFRM_MSG_GETSADINFO XFRM_MSG_GETSADINFO | ||
184 | __XFRM_MSG_MAX | 188 | __XFRM_MSG_MAX |
185 | }; | 189 | }; |
186 | #define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1) | 190 | #define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1) |
@@ -234,6 +238,17 @@ enum xfrm_ae_ftype_t { | |||
234 | #define XFRM_AE_MAX (__XFRM_AE_MAX - 1) | 238 | #define XFRM_AE_MAX (__XFRM_AE_MAX - 1) |
235 | }; | 239 | }; |
236 | 240 | ||
241 | /* SAD Table filter flags */ | ||
242 | enum xfrm_sad_ftype_t { | ||
243 | XFRM_SAD_UNSPEC, | ||
244 | XFRM_SAD_HMASK=1, | ||
245 | XFRM_SAD_HMAX=2, | ||
246 | XFRM_SAD_CNT=4, | ||
247 | __XFRM_SAD_MAX | ||
248 | |||
249 | #define XFRM_SAD_MAX (__XFRM_SAD_MAX - 1) | ||
250 | }; | ||
251 | |||
237 | struct xfrm_userpolicy_type { | 252 | struct xfrm_userpolicy_type { |
238 | __u8 type; | 253 | __u8 type; |
239 | __u16 reserved1; | 254 | __u16 reserved1; |
@@ -265,6 +280,16 @@ enum xfrm_attr_type_t { | |||
265 | #define XFRMA_MAX (__XFRMA_MAX - 1) | 280 | #define XFRMA_MAX (__XFRMA_MAX - 1) |
266 | }; | 281 | }; |
267 | 282 | ||
283 | enum xfrm_sadattr_type_t { | ||
284 | XFRMA_SAD_UNSPEC, | ||
285 | XFRMA_SADHMASK, | ||
286 | XFRMA_SADHMAX, | ||
287 | XFRMA_SADCNT, | ||
288 | __XFRMA_SAD_MAX | ||
289 | |||
290 | #define XFRMA_SAD_MAX (__XFRMA_SAD_MAX - 1) | ||
291 | }; | ||
292 | |||
268 | struct xfrm_usersa_info { | 293 | struct xfrm_usersa_info { |
269 | struct xfrm_selector sel; | 294 | struct xfrm_selector sel; |
270 | struct xfrm_id id; | 295 | struct xfrm_id id; |
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index e144a25814bd..8287081d77f2 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
@@ -416,6 +416,13 @@ struct xfrm_audit | |||
416 | u32 secid; | 416 | u32 secid; |
417 | }; | 417 | }; |
418 | 418 | ||
419 | /* SAD metadata, add more later */ | ||
420 | struct xfrm_sadinfo | ||
421 | { | ||
422 | u32 sadhcnt; /* current hash bkts */ | ||
423 | u32 sadhmcnt; /* max allowed hash bkts */ | ||
424 | u32 sadcnt; /* current running count */ | ||
425 | }; | ||
419 | #ifdef CONFIG_AUDITSYSCALL | 426 | #ifdef CONFIG_AUDITSYSCALL |
420 | extern void xfrm_audit_log(uid_t auid, u32 secid, int type, int result, | 427 | extern void xfrm_audit_log(uid_t auid, u32 secid, int type, int result, |
421 | struct xfrm_policy *xp, struct xfrm_state *x); | 428 | struct xfrm_policy *xp, struct xfrm_state *x); |
@@ -938,6 +945,7 @@ static inline int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **s | |||
938 | extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq); | 945 | extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq); |
939 | extern int xfrm_state_delete(struct xfrm_state *x); | 946 | extern int xfrm_state_delete(struct xfrm_state *x); |
940 | extern void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info); | 947 | extern void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info); |
948 | extern void xfrm_sad_getinfo(struct xfrm_sadinfo *si); | ||
941 | extern int xfrm_replay_check(struct xfrm_state *x, __be32 seq); | 949 | extern int xfrm_replay_check(struct xfrm_state *x, __be32 seq); |
942 | extern void xfrm_replay_advance(struct xfrm_state *x, __be32 seq); | 950 | extern void xfrm_replay_advance(struct xfrm_state *x, __be32 seq); |
943 | extern void xfrm_replay_notify(struct xfrm_state *x, int event); | 951 | extern void xfrm_replay_notify(struct xfrm_state *x, int event); |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 743f07e7f698..f3a61ebd8d65 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -421,6 +421,16 @@ restart: | |||
421 | } | 421 | } |
422 | EXPORT_SYMBOL(xfrm_state_flush); | 422 | EXPORT_SYMBOL(xfrm_state_flush); |
423 | 423 | ||
424 | void xfrm_sad_getinfo(struct xfrm_sadinfo *si) | ||
425 | { | ||
426 | spin_lock_bh(&xfrm_state_lock); | ||
427 | si->sadcnt = xfrm_state_num; | ||
428 | si->sadhcnt = xfrm_state_hmask; | ||
429 | si->sadhmcnt = xfrm_state_hashmax; | ||
430 | spin_unlock_bh(&xfrm_state_lock); | ||
431 | } | ||
432 | EXPORT_SYMBOL(xfrm_sad_getinfo); | ||
433 | |||
424 | static int | 434 | static int |
425 | xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl, | 435 | xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl, |
426 | struct xfrm_tmpl *tmpl, | 436 | struct xfrm_tmpl *tmpl, |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index f91521d5f2ab..cb4cc1bde5d1 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -672,6 +672,61 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb, | |||
672 | return skb; | 672 | return skb; |
673 | } | 673 | } |
674 | 674 | ||
675 | static int build_sadinfo(struct sk_buff *skb, u32 pid, u32 seq, u32 flags) | ||
676 | { | ||
677 | struct xfrm_sadinfo si; | ||
678 | struct nlmsghdr *nlh; | ||
679 | u32 *f; | ||
680 | |||
681 | nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSADINFO, sizeof(u32), 0); | ||
682 | if (nlh == NULL) /* shouldnt really happen ... */ | ||
683 | return -EMSGSIZE; | ||
684 | |||
685 | f = nlmsg_data(nlh); | ||
686 | *f = flags; | ||
687 | xfrm_sad_getinfo(&si); | ||
688 | |||
689 | if (flags & XFRM_SAD_HMASK) | ||
690 | NLA_PUT_U32(skb, XFRMA_SADHMASK, si.sadhcnt); | ||
691 | if (flags & XFRM_SAD_HMAX) | ||
692 | NLA_PUT_U32(skb, XFRMA_SADHMAX, si.sadhmcnt); | ||
693 | if (flags & XFRM_SAD_CNT) | ||
694 | NLA_PUT_U32(skb, XFRMA_SADCNT, si.sadcnt); | ||
695 | |||
696 | return nlmsg_end(skb, nlh); | ||
697 | |||
698 | nla_put_failure: | ||
699 | nlmsg_cancel(skb, nlh); | ||
700 | return -EMSGSIZE; | ||
701 | } | ||
702 | |||
703 | static int xfrm_get_sadinfo(struct sk_buff *skb, struct nlmsghdr *nlh, | ||
704 | struct rtattr **xfrma) | ||
705 | { | ||
706 | struct sk_buff *r_skb; | ||
707 | u32 *flags = NLMSG_DATA(nlh); | ||
708 | u32 spid = NETLINK_CB(skb).pid; | ||
709 | u32 seq = nlh->nlmsg_seq; | ||
710 | int len = NLMSG_LENGTH(sizeof(u32)); | ||
711 | |||
712 | if (*flags & XFRM_SAD_HMASK) | ||
713 | len += RTA_SPACE(sizeof(u32)); | ||
714 | if (*flags & XFRM_SAD_HMAX) | ||
715 | len += RTA_SPACE(sizeof(u32)); | ||
716 | if (*flags & XFRM_SAD_CNT) | ||
717 | len += RTA_SPACE(sizeof(u32)); | ||
718 | |||
719 | r_skb = alloc_skb(len, GFP_ATOMIC); | ||
720 | |||
721 | if (r_skb == NULL) | ||
722 | return -ENOMEM; | ||
723 | |||
724 | if (build_sadinfo(r_skb, spid, seq, *flags) < 0) | ||
725 | BUG(); | ||
726 | |||
727 | return nlmsg_unicast(xfrm_nl, r_skb, spid); | ||
728 | } | ||
729 | |||
675 | static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh, | 730 | static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh, |
676 | struct rtattr **xfrma) | 731 | struct rtattr **xfrma) |
677 | { | 732 | { |
@@ -1850,6 +1905,7 @@ static struct xfrm_link { | |||
1850 | [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = { .doit = xfrm_new_ae }, | 1905 | [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = { .doit = xfrm_new_ae }, |
1851 | [XFRM_MSG_GETAE - XFRM_MSG_BASE] = { .doit = xfrm_get_ae }, | 1906 | [XFRM_MSG_GETAE - XFRM_MSG_BASE] = { .doit = xfrm_get_ae }, |
1852 | [XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = { .doit = xfrm_do_migrate }, | 1907 | [XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = { .doit = xfrm_do_migrate }, |
1908 | [XFRM_MSG_GETSADINFO - XFRM_MSG_BASE] = { .doit = xfrm_get_sadinfo }, | ||
1853 | }; | 1909 | }; |
1854 | 1910 | ||
1855 | static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | 1911 | static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) |