Commit ca44b738 authored by Vlad Buslov's avatar Vlad Buslov Committed by David S. Miller

net: sched: implement terse dump support in act

Extend tcf_action_dump() with boolean argument 'terse' that is used to
request terse-mode action dump. In terse mode only essential data needed to
identify particular action (action kind, cookie, etc.) and its stats is put
to resulting skb and everything else is omitted. Implement
tcf_exts_terse_dump() helper in cls API that is intended to be used to
request terse dump of all exts (actions) attached to the filter.
Signed-off-by: default avatarVlad Buslov <vladbu@mellanox.com>
Reviewed-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f8ab1807
...@@ -193,7 +193,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, ...@@ -193,7 +193,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
bool rtnl_held, bool rtnl_held,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
int tcf_action_dump(struct sk_buff *skb, struct tc_action *actions[], int bind, int tcf_action_dump(struct sk_buff *skb, struct tc_action *actions[], int bind,
int ref); int ref, bool terse);
int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int); int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int); int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
......
...@@ -325,6 +325,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, ...@@ -325,6 +325,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp,
void tcf_exts_destroy(struct tcf_exts *exts); void tcf_exts_destroy(struct tcf_exts *exts);
void tcf_exts_change(struct tcf_exts *dst, struct tcf_exts *src); void tcf_exts_change(struct tcf_exts *dst, struct tcf_exts *src);
int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts); int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts);
int tcf_exts_terse_dump(struct sk_buff *skb, struct tcf_exts *exts);
int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts); int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts);
/** /**
......
...@@ -766,12 +766,10 @@ tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int bind, int ref) ...@@ -766,12 +766,10 @@ tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
return a->ops->dump(skb, a, bind, ref); return a->ops->dump(skb, a, bind, ref);
} }
int static int
tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref) tcf_action_dump_terse(struct sk_buff *skb, struct tc_action *a)
{ {
int err = -EINVAL;
unsigned char *b = skb_tail_pointer(skb); unsigned char *b = skb_tail_pointer(skb);
struct nlattr *nest;
struct tc_cookie *cookie; struct tc_cookie *cookie;
if (nla_put_string(skb, TCA_KIND, a->ops->kind)) if (nla_put_string(skb, TCA_KIND, a->ops->kind))
...@@ -789,6 +787,23 @@ tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref) ...@@ -789,6 +787,23 @@ tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
} }
rcu_read_unlock(); rcu_read_unlock();
return 0;
nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
int
tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
{
int err = -EINVAL;
unsigned char *b = skb_tail_pointer(skb);
struct nlattr *nest;
if (tcf_action_dump_terse(skb, a))
goto nla_put_failure;
if (a->hw_stats != TCA_ACT_HW_STATS_ANY && if (a->hw_stats != TCA_ACT_HW_STATS_ANY &&
nla_put_bitfield32(skb, TCA_ACT_HW_STATS, nla_put_bitfield32(skb, TCA_ACT_HW_STATS,
a->hw_stats, TCA_ACT_HW_STATS_ANY)) a->hw_stats, TCA_ACT_HW_STATS_ANY))
...@@ -820,7 +835,7 @@ tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref) ...@@ -820,7 +835,7 @@ tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
EXPORT_SYMBOL(tcf_action_dump_1); EXPORT_SYMBOL(tcf_action_dump_1);
int tcf_action_dump(struct sk_buff *skb, struct tc_action *actions[], int tcf_action_dump(struct sk_buff *skb, struct tc_action *actions[],
int bind, int ref) int bind, int ref, bool terse)
{ {
struct tc_action *a; struct tc_action *a;
int err = -EINVAL, i; int err = -EINVAL, i;
...@@ -831,7 +846,8 @@ int tcf_action_dump(struct sk_buff *skb, struct tc_action *actions[], ...@@ -831,7 +846,8 @@ int tcf_action_dump(struct sk_buff *skb, struct tc_action *actions[],
nest = nla_nest_start_noflag(skb, i + 1); nest = nla_nest_start_noflag(skb, i + 1);
if (nest == NULL) if (nest == NULL)
goto nla_put_failure; goto nla_put_failure;
err = tcf_action_dump_1(skb, a, bind, ref); err = terse ? tcf_action_dump_terse(skb, a) :
tcf_action_dump_1(skb, a, bind, ref);
if (err < 0) if (err < 0)
goto errout; goto errout;
nla_nest_end(skb, nest); nla_nest_end(skb, nest);
...@@ -1133,7 +1149,7 @@ static int tca_get_fill(struct sk_buff *skb, struct tc_action *actions[], ...@@ -1133,7 +1149,7 @@ static int tca_get_fill(struct sk_buff *skb, struct tc_action *actions[],
if (!nest) if (!nest)
goto out_nlmsg_trim; goto out_nlmsg_trim;
if (tcf_action_dump(skb, actions, bind, ref) < 0) if (tcf_action_dump(skb, actions, bind, ref, false) < 0)
goto out_nlmsg_trim; goto out_nlmsg_trim;
nla_nest_end(skb, nest); nla_nest_end(skb, nest);
......
...@@ -3179,7 +3179,8 @@ int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts) ...@@ -3179,7 +3179,8 @@ int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts)
if (nest == NULL) if (nest == NULL)
goto nla_put_failure; goto nla_put_failure;
if (tcf_action_dump(skb, exts->actions, 0, 0) < 0) if (tcf_action_dump(skb, exts->actions, 0, 0, false)
< 0)
goto nla_put_failure; goto nla_put_failure;
nla_nest_end(skb, nest); nla_nest_end(skb, nest);
} else if (exts->police) { } else if (exts->police) {
...@@ -3203,6 +3204,31 @@ int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts) ...@@ -3203,6 +3204,31 @@ int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts)
} }
EXPORT_SYMBOL(tcf_exts_dump); EXPORT_SYMBOL(tcf_exts_dump);
int tcf_exts_terse_dump(struct sk_buff *skb, struct tcf_exts *exts)
{
#ifdef CONFIG_NET_CLS_ACT
struct nlattr *nest;
if (!exts->action || !tcf_exts_has_actions(exts))
return 0;
nest = nla_nest_start_noflag(skb, exts->action);
if (!nest)
goto nla_put_failure;
if (tcf_action_dump(skb, exts->actions, 0, 0, true) < 0)
goto nla_put_failure;
nla_nest_end(skb, nest);
return 0;
nla_put_failure:
nla_nest_cancel(skb, nest);
return -1;
#else
return 0;
#endif
}
EXPORT_SYMBOL(tcf_exts_terse_dump);
int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts) int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment