aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/cls_api.c
diff options
context:
space:
mode:
authorJiri Pirko <jiri@mellanox.com>2018-07-27 03:45:05 -0400
committerDavid S. Miller <davem@davemloft.net>2018-07-27 12:38:46 -0400
commit1f3ed383fb9a073ae2e408cd7a0717b04c7c3a21 (patch)
tree823f398d9c83214306a5cfb09a12c032fe3b91c6 /net/sched/cls_api.c
parent7a49d3d4ea42fe15db0d36e042df14a645d1fdce (diff)
net: sched: don't dump chains only held by actions
In case a chain is empty and not explicitly created by a user, such chain should not exist. The only exception is if there is an action "goto chain" pointing to it. In that case, don't show the chain in the dump. Track the chain references held by actions and use them to find out if a chain should or should not be shown in chain dump. Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/cls_api.c')
-rw-r--r--net/sched/cls_api.c70
1 files changed, 58 insertions, 12 deletions
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 75cce2819de9..e20aad1987b8 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -262,6 +262,25 @@ static void tcf_chain_hold(struct tcf_chain *chain)
262 ++chain->refcnt; 262 ++chain->refcnt;
263} 263}
264 264
265static void tcf_chain_hold_by_act(struct tcf_chain *chain)
266{
267 ++chain->action_refcnt;
268}
269
270static void tcf_chain_release_by_act(struct tcf_chain *chain)
271{
272 --chain->action_refcnt;
273}
274
275static bool tcf_chain_is_zombie(struct tcf_chain *chain)
276{
277 /* In case all the references are action references, this
278 * chain is a zombie and should not be listed in the chain
279 * dump list.
280 */
281 return chain->refcnt == chain->action_refcnt;
282}
283
265static struct tcf_chain *tcf_chain_lookup(struct tcf_block *block, 284static struct tcf_chain *tcf_chain_lookup(struct tcf_block *block,
266 u32 chain_index) 285 u32 chain_index)
267{ 286{
@@ -298,6 +317,15 @@ struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index,
298} 317}
299EXPORT_SYMBOL(tcf_chain_get); 318EXPORT_SYMBOL(tcf_chain_get);
300 319
320struct tcf_chain *tcf_chain_get_by_act(struct tcf_block *block, u32 chain_index)
321{
322 struct tcf_chain *chain = tcf_chain_get(block, chain_index, true);
323
324 tcf_chain_hold_by_act(chain);
325 return chain;
326}
327EXPORT_SYMBOL(tcf_chain_get_by_act);
328
301static void tc_chain_tmplt_del(struct tcf_chain *chain); 329static void tc_chain_tmplt_del(struct tcf_chain *chain);
302 330
303void tcf_chain_put(struct tcf_chain *chain) 331void tcf_chain_put(struct tcf_chain *chain)
@@ -310,6 +338,13 @@ void tcf_chain_put(struct tcf_chain *chain)
310} 338}
311EXPORT_SYMBOL(tcf_chain_put); 339EXPORT_SYMBOL(tcf_chain_put);
312 340
341void tcf_chain_put_by_act(struct tcf_chain *chain)
342{
343 tcf_chain_release_by_act(chain);
344 tcf_chain_put(chain);
345}
346EXPORT_SYMBOL(tcf_chain_put_by_act);
347
313static void tcf_chain_put_explicitly_created(struct tcf_chain *chain) 348static void tcf_chain_put_explicitly_created(struct tcf_chain *chain)
314{ 349{
315 if (chain->explicitly_created) 350 if (chain->explicitly_created)
@@ -1803,20 +1838,29 @@ replay:
1803 chain = tcf_chain_lookup(block, chain_index); 1838 chain = tcf_chain_lookup(block, chain_index);
1804 if (n->nlmsg_type == RTM_NEWCHAIN) { 1839 if (n->nlmsg_type == RTM_NEWCHAIN) {
1805 if (chain) { 1840 if (chain) {
1806 NL_SET_ERR_MSG(extack, "Filter chain already exists"); 1841 if (tcf_chain_is_zombie(chain)) {
1807 return -EEXIST; 1842 /* The chain exists only because there is
1808 } 1843 * some action referencing it, meaning it
1809 if (!(n->nlmsg_flags & NLM_F_CREATE)) { 1844 * is a zombie.
1810 NL_SET_ERR_MSG(extack, "Need both RTM_NEWCHAIN and NLM_F_CREATE to create a new chain"); 1845 */
1811 return -ENOENT; 1846 tcf_chain_hold(chain);
1812 } 1847 } else {
1813 chain = tcf_chain_create(block, chain_index); 1848 NL_SET_ERR_MSG(extack, "Filter chain already exists");
1814 if (!chain) { 1849 return -EEXIST;
1815 NL_SET_ERR_MSG(extack, "Failed to create filter chain"); 1850 }
1816 return -ENOMEM; 1851 } else {
1852 if (!(n->nlmsg_flags & NLM_F_CREATE)) {
1853 NL_SET_ERR_MSG(extack, "Need both RTM_NEWCHAIN and NLM_F_CREATE to create a new chain");
1854 return -ENOENT;
1855 }
1856 chain = tcf_chain_create(block, chain_index);
1857 if (!chain) {
1858 NL_SET_ERR_MSG(extack, "Failed to create filter chain");
1859 return -ENOMEM;
1860 }
1817 } 1861 }
1818 } else { 1862 } else {
1819 if (!chain) { 1863 if (!chain || tcf_chain_is_zombie(chain)) {
1820 NL_SET_ERR_MSG(extack, "Cannot find specified filter chain"); 1864 NL_SET_ERR_MSG(extack, "Cannot find specified filter chain");
1821 return -EINVAL; 1865 return -EINVAL;
1822 } 1866 }
@@ -1944,6 +1988,8 @@ static int tc_dump_chain(struct sk_buff *skb, struct netlink_callback *cb)
1944 index++; 1988 index++;
1945 continue; 1989 continue;
1946 } 1990 }
1991 if (tcf_chain_is_zombie(chain))
1992 continue;
1947 err = tc_chain_fill_node(chain, net, skb, block, 1993 err = tc_chain_fill_node(chain, net, skb, block,
1948 NETLINK_CB(cb->skb).portid, 1994 NETLINK_CB(cb->skb).portid,
1949 cb->nlh->nlmsg_seq, NLM_F_MULTI, 1995 cb->nlh->nlmsg_seq, NLM_F_MULTI,