[PATCH v2] act: grab a reference when adding an action to a filter

Cong Wang xiyou.wangcong at gmail.com
Wed Apr 23 17:28:29 PDT 2014


When we add an action to a filter, its lifetime becomes
same with the filter. So in case user frees it before
us, we could just grab a reference here.

Signed-off-by: Cong Wang <xiyou.wangcong at gmail.com>
---
 include/netlink/route/action.h | 1 +
 include/netlink/utils.h        | 7 +++++++
 lib/route/act.c                | 5 +++++
 lib/route/cls/basic.c          | 8 +++++++-
 lib/route/cls/u32.c            | 8 +++++++-
 lib/utils.c                    | 2 +-
 6 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/include/netlink/route/action.h b/include/netlink/route/action.h
index e904432..054bdd8 100644
--- a/include/netlink/route/action.h
+++ b/include/netlink/route/action.h
@@ -22,6 +22,7 @@ extern "C" {
 #endif
 
 extern struct rtnl_act *rtnl_act_alloc(void);
+extern void		rtnl_act_get(struct rtnl_act *);
 extern void		rtnl_act_put(struct rtnl_act *);
 extern int		rtnl_act_build_add_request(struct rtnl_act *, int,
 						   struct nl_msg **);
diff --git a/include/netlink/utils.h b/include/netlink/utils.h
index 6c4cb52..1e0e4ce 100644
--- a/include/netlink/utils.h
+++ b/include/netlink/utils.h
@@ -97,6 +97,13 @@ enum {
 	 */
 #define NL_CAPABILITY_ROUTE_LINK_VETH_GET_PEER_OWN_REFERENCE NL_CAPABILITY_ROUTE_LINK_VETH_GET_PEER_OWN_REFERENCE
 
+	/**
+	 * rtnl_u32_add_action() and rtnl_basic_add_action() now grab a reference to act
+	 * caller are free to release its own
+	 */
+	NL_CAPABILITY_ROUTE_LINK_CLS_ADD_ACT_OWN_REFERENCE = 3,
+#define NL_CAPABILITY_ROUTE_LINK_CLS_ADD_ACT_OWN_REFERENCE NL_CAPABILITY_ROUTE_LINK_CLS_ADD_ACT_OWN_REFERENCE
+
 	__NL_CAPABILITY_MAX
 #define NL_CAPABILITY_MAX                               (__NL_CAPABILITY_MAX - 1)
 };
diff --git a/lib/route/act.c b/lib/route/act.c
index a2ca335..ef63eba 100644
--- a/lib/route/act.c
+++ b/lib/route/act.c
@@ -178,6 +178,11 @@ struct rtnl_act *rtnl_act_alloc(void)
 	return (struct rtnl_act *) tc;
 }
 
+void rtnl_act_get(struct rtnl_act *act)
+{
+	nl_object_get(OBJ_CAST(act));
+}
+
 void rtnl_act_put(struct rtnl_act *act)
 {
 	nl_object_put((struct nl_object *) act);
diff --git a/lib/route/cls/basic.c b/lib/route/cls/basic.c
index 5a67fae..6af3844 100644
--- a/lib/route/cls/basic.c
+++ b/lib/route/cls/basic.c
@@ -228,6 +228,8 @@ int rtnl_basic_add_action(struct rtnl_cls *cls, struct rtnl_act *act)
 		return -NLE_NOMEM;
 
 	b->b_mask |= BASIC_ATTR_ACTION;
+	/* In case user frees it */
+	rtnl_act_get(act);
 	return rtnl_act_append(&b->b_act, act);
 }
 
@@ -245,9 +247,13 @@ int rtnl_basic_del_action(struct rtnl_cls *cls, struct rtnl_act *act)
 	if (!(b->b_mask & BASIC_ATTR_ACTION))
 		return -NLE_INVAL;
 	ret = rtnl_act_remove(&b->b_act, act);
+	if (ret)
+		return ret;
+
 	if (!b->b_act)
 		b->b_mask &= ~BASIC_ATTR_ACTION;
-	return ret;
+	rtnl_act_put(act);
+	return 0;
 }
 /** @} */
 
diff --git a/lib/route/cls/u32.c b/lib/route/cls/u32.c
index 52ab263..e91c39a 100644
--- a/lib/route/cls/u32.c
+++ b/lib/route/cls/u32.c
@@ -470,6 +470,8 @@ int rtnl_u32_add_action(struct rtnl_cls *cls, struct rtnl_act *act)
 		return -NLE_NOMEM;
 
 	u->cu_mask |= U32_ATTR_ACTION;
+	/* In case user frees it */
+	rtnl_act_get(act);
 	return rtnl_act_append(&u->cu_act, act);
 }
 
@@ -488,9 +490,13 @@ int rtnl_u32_del_action(struct rtnl_cls *cls, struct rtnl_act *act)
 		return -NLE_INVAL;
 
 	ret = rtnl_act_remove(&u->cu_act, act);
+	if (ret)
+		return ret;
+
 	if (!u->cu_act)
 		u->cu_mask &= ~U32_ATTR_ACTION;
-	return ret;
+	rtnl_act_put(act);
+	return 0;
 }
 /** @} */
 
diff --git a/lib/utils.c b/lib/utils.c
index ac36493..e2294e6 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -1146,7 +1146,7 @@ int nl_has_capability (int capability)
 		_NL_SET(0,
 			NL_CAPABILITY_ROUTE_BUILD_MSG_SET_SCOPE,
 			NL_CAPABILITY_ROUTE_LINK_VETH_GET_PEER_OWN_REFERENCE,
-			0,
+			NL_CAPABILITY_ROUTE_LINK_CLS_ADD_ACT_OWN_REFERENCE,
 			0,
 			0,
 			0,
-- 
1.8.3.1




More information about the libnl mailing list