[PATCH net-next 5/5] net: track xfrm_state refcnt with obj_cnt
STALE1763d
From: Xin Long <lucien.xin@gmail.com>
Date: 2021-12-07 04:02:20
Subsystem:
library code, networking [general], networking [ipsec], the rest · Maintainers:
Andrew Morton, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Steffen Klassert, Herbert Xu, Linus Torvalds
Two types are added into obj_cnt to count xfrm_state_hold and
xfrm_state_put*, and all it does is put obj_cnt_track_by_index()
into these two functions.
Here is a example to track the refcnt of a xfrm_state whose spi
is 0x100:
# sysctl -w obj_cnt.control="clear" # clear the old result
# sysctl -w obj_cnt.type=0xc0 # enable xfrm_state_hold/put track
# sysctl -w obj_cnt.index=0x100 # count xfrm_state_hold/put(state)
# sysctl -w obj_cnt.nr_entries=4 # save 4 frames' call trace
# ip link add dummy0 type dummy
# ip link set dummy0 up
# ip addr add 1.1.1.1/24 dev dummy0
# ip xfrm state add src 1.1.1.1 dst 1.1.1.2 spi 0x100 proto esp enc aes \
0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f \
mode tunnel sel src 1.1.1.1 dst 1.1.1.2
# ip xfrm policy add dir out src 1.1.1.1 dst 1.1.1.2 tmpl src 1.1.1.1 \
dst 1.1.1.2 proto esp mode tunnel
# ping 1.1.1.2 -c 1
# ip link set dummy0 down
# ip link del dummy0
# sysctl -w obj_cnt.control="scan" # print the new result
# dmesg
OBJ_CNT: obj_cnt_dump: obj: ffff8ca629cb0f00, type: xfrm_state_hold, cnt: 1,:
xfrm_add_sa+0x476/0x5f0
xfrm_user_rcv_msg+0x13c/0x250
netlink_rcv_skb+0x50/0x100
xfrm_netlink_rcv+0x30/0x40
OBJ_CNT: obj_cnt_dump: obj: ffff8ca629cb0f00, type: xfrm_state_put, cnt: 2,:
xfrm4_dst_destroy+0x110/0x130
dst_destroy+0x37/0xe0
rcu_do_batch+0x164/0x4b0
rcu_core+0x249/0x350
OBJ_CNT: obj_cnt_dump: obj: ffff8ca629cb0f00, type: xfrm_state_put, cnt: 1,:
xfrm_add_sa+0x497/0x5f0
xfrm_user_rcv_msg+0x13c/0x250
netlink_rcv_skb+0x50/0x100
xfrm_netlink_rcv+0x30/0x40
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
include/linux/obj_cnt.h | 2 ++
include/net/xfrm.h | 11 +++++++++++
lib/obj_cnt.c | 4 +++-
3 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/include/linux/obj_cnt.h b/include/linux/obj_cnt.h
index f014b2e613d9..42611aa321c7 100644
--- a/include/linux/obj_cnt.h
+++ b/include/linux/obj_cnt.h@@ -9,6 +9,8 @@ enum { OBJ_CNT_DST_PUT, OBJ_CNT_IN6_DEV_HOLD, OBJ_CNT_IN6_DEV_PUT, + OBJ_CNT_XFRM_STATE_HOLD, + OBJ_CNT_XFRM_STATE_PUT, OBJ_CNT_TYPE_MAX };
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 2308210793a0..543840fba068 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h@@ -772,25 +772,36 @@ static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols) void __xfrm_state_destroy(struct xfrm_state *, bool); +static inline void obj_cnt_track_by_index(void *obj, int index, int type) +{ +#ifdef CONFIG_OBJ_CNT + obj_cnt_track(type, index, NULL, obj); +#endif +} + static inline void __xfrm_state_put(struct xfrm_state *x) { + obj_cnt_track_by_index(x, ntohl(x->id.spi), OBJ_CNT_XFRM_STATE_PUT); refcount_dec(&x->refcnt); } static inline void xfrm_state_put(struct xfrm_state *x) { + obj_cnt_track_by_index(x, ntohl(x->id.spi), OBJ_CNT_XFRM_STATE_PUT); if (refcount_dec_and_test(&x->refcnt)) __xfrm_state_destroy(x, false); } static inline void xfrm_state_put_sync(struct xfrm_state *x) { + obj_cnt_track_by_index(x, ntohl(x->id.spi), OBJ_CNT_XFRM_STATE_PUT); if (refcount_dec_and_test(&x->refcnt)) __xfrm_state_destroy(x, true); } static inline void xfrm_state_hold(struct xfrm_state *x) { + obj_cnt_track_by_index(x, ntohl(x->id.spi), OBJ_CNT_XFRM_STATE_HOLD); refcount_inc(&x->refcnt); }
diff --git a/lib/obj_cnt.c b/lib/obj_cnt.c
index 8756efc005ed..f054455abe8d 100644
--- a/lib/obj_cnt.c
+++ b/lib/obj_cnt.c@@ -20,7 +20,9 @@ static char *obj_cnt_str[OBJ_CNT_TYPE_MAX] = { "dst_hold", "dst_put", "in6_dev_hold", - "in6_dev_put" + "in6_dev_put", + "xfrm_state_hold", + "xfrm_state_put" }; struct obj_cnt {
--
2.27.0