mirror of
https://github.com/openvswitch/ovs
synced 2025-08-31 06:15:47 +00:00
tc: Support new terse dump kernel API
When dumping flows in terse mode set TCA_DUMP_FLAGS attribute to TCA_DUMP_FLAGS_TERSE flag to prevent unnecessary copying of data between kernel and user spaces. Only expect kernel to provide cookie, stats and flags when dumping filters in terse mode. Signed-off-by: Vlad Buslov <vladbu@mellanox.com> Reviewed-by: Roi Dayan <roid@mellanox.com> Signed-off-by: Simon Horman <simon.horman@netronome.com>
This commit is contained in:
committed by
Simon Horman
parent
191536574e
commit
5db012c4ac
59
lib/tc.c
59
lib/tc.c
@@ -51,9 +51,14 @@
|
||||
#define TCM_IFINDEX_MAGIC_BLOCK (0xFFFFFFFFU)
|
||||
#endif
|
||||
|
||||
#if TCA_MAX < 14
|
||||
#ifndef TCA_DUMP_FLAGS_TERSE
|
||||
#define TCA_DUMP_FLAGS_TERSE (1 << 0)
|
||||
#endif
|
||||
|
||||
#if TCA_MAX < 15
|
||||
#define TCA_CHAIN 11
|
||||
#define TCA_INGRESS_BLOCK 13
|
||||
#define TCA_DUMP_FLAGS 15
|
||||
#endif
|
||||
|
||||
VLOG_DEFINE_THIS_MODULE(tc);
|
||||
@@ -417,6 +422,11 @@ static const struct nl_policy tca_flower_policy[] = {
|
||||
.optional = true, },
|
||||
};
|
||||
|
||||
static const struct nl_policy tca_flower_terse_policy[] = {
|
||||
[TCA_FLOWER_FLAGS] = { .type = NL_A_U32, .optional = false, },
|
||||
[TCA_FLOWER_ACT] = { .type = NL_A_NESTED, .optional = false, },
|
||||
};
|
||||
|
||||
static void
|
||||
nl_parse_flower_eth(struct nlattr **attrs, struct tc_flower *flower)
|
||||
{
|
||||
@@ -1595,7 +1605,7 @@ nl_parse_act_csum(struct nlattr *options, struct tc_flower *flower)
|
||||
static const struct nl_policy act_policy[] = {
|
||||
[TCA_ACT_KIND] = { .type = NL_A_STRING, .optional = false, },
|
||||
[TCA_ACT_COOKIE] = { .type = NL_A_UNSPEC, .optional = true, },
|
||||
[TCA_ACT_OPTIONS] = { .type = NL_A_NESTED, .optional = false, },
|
||||
[TCA_ACT_OPTIONS] = { .type = NL_A_NESTED, .optional = true, },
|
||||
[TCA_ACT_STATS] = { .type = NL_A_NESTED, .optional = false, },
|
||||
};
|
||||
|
||||
@@ -1606,7 +1616,8 @@ static const struct nl_policy stats_policy[] = {
|
||||
};
|
||||
|
||||
static int
|
||||
nl_parse_single_action(struct nlattr *action, struct tc_flower *flower)
|
||||
nl_parse_single_action(struct nlattr *action, struct tc_flower *flower,
|
||||
bool terse)
|
||||
{
|
||||
struct nlattr *act_options;
|
||||
struct nlattr *act_stats;
|
||||
@@ -1619,7 +1630,8 @@ nl_parse_single_action(struct nlattr *action, struct tc_flower *flower)
|
||||
int err = 0;
|
||||
|
||||
if (!nl_parse_nested(action, act_policy, action_attrs,
|
||||
ARRAY_SIZE(act_policy))) {
|
||||
ARRAY_SIZE(act_policy)) ||
|
||||
(!terse && !action_attrs[TCA_ACT_OPTIONS])) {
|
||||
VLOG_ERR_RL(&error_rl, "failed to parse single action options");
|
||||
return EPROTO;
|
||||
}
|
||||
@@ -1628,7 +1640,9 @@ nl_parse_single_action(struct nlattr *action, struct tc_flower *flower)
|
||||
act_options = action_attrs[TCA_ACT_OPTIONS];
|
||||
act_cookie = action_attrs[TCA_ACT_COOKIE];
|
||||
|
||||
if (!strcmp(act_kind, "gact")) {
|
||||
if (terse) {
|
||||
/* Terse dump doesn't provide act options attribute. */
|
||||
} else if (!strcmp(act_kind, "gact")) {
|
||||
err = nl_parse_act_gact(act_options, flower);
|
||||
} else if (!strcmp(act_kind, "mirred")) {
|
||||
err = nl_parse_act_mirred(act_options, flower);
|
||||
@@ -1678,7 +1692,8 @@ nl_parse_single_action(struct nlattr *action, struct tc_flower *flower)
|
||||
#define TCA_ACT_MIN_PRIO 1
|
||||
|
||||
static int
|
||||
nl_parse_flower_actions(struct nlattr **attrs, struct tc_flower *flower)
|
||||
nl_parse_flower_actions(struct nlattr **attrs, struct tc_flower *flower,
|
||||
bool terse)
|
||||
{
|
||||
const struct nlattr *actions = attrs[TCA_FLOWER_ACT];
|
||||
static struct nl_policy actions_orders_policy[TCA_ACT_MAX_NUM + 1] = {};
|
||||
@@ -1704,7 +1719,7 @@ nl_parse_flower_actions(struct nlattr **attrs, struct tc_flower *flower)
|
||||
VLOG_DBG_RL(&error_rl, "Can only support %d actions", TCA_ACT_MAX_NUM);
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
err = nl_parse_single_action(actions_orders[i], flower);
|
||||
err = nl_parse_single_action(actions_orders[i], flower, terse);
|
||||
|
||||
if (err) {
|
||||
return err;
|
||||
@@ -1723,11 +1738,21 @@ nl_parse_flower_actions(struct nlattr **attrs, struct tc_flower *flower)
|
||||
}
|
||||
|
||||
static int
|
||||
nl_parse_flower_options(struct nlattr *nl_options, struct tc_flower *flower)
|
||||
nl_parse_flower_options(struct nlattr *nl_options, struct tc_flower *flower,
|
||||
bool terse)
|
||||
{
|
||||
struct nlattr *attrs[ARRAY_SIZE(tca_flower_policy)];
|
||||
int err;
|
||||
|
||||
if (terse) {
|
||||
if (!nl_parse_nested(nl_options, tca_flower_terse_policy,
|
||||
attrs, ARRAY_SIZE(tca_flower_terse_policy))) {
|
||||
VLOG_ERR_RL(&error_rl, "failed to parse flower classifier terse options");
|
||||
return EPROTO;
|
||||
}
|
||||
goto skip_flower_opts;
|
||||
}
|
||||
|
||||
if (!nl_parse_nested(nl_options, tca_flower_policy,
|
||||
attrs, ARRAY_SIZE(tca_flower_policy))) {
|
||||
VLOG_ERR_RL(&error_rl, "failed to parse flower classifier options");
|
||||
@@ -1743,13 +1768,14 @@ nl_parse_flower_options(struct nlattr *nl_options, struct tc_flower *flower)
|
||||
return err;
|
||||
}
|
||||
|
||||
skip_flower_opts:
|
||||
nl_parse_flower_flags(attrs, flower);
|
||||
return nl_parse_flower_actions(attrs, flower);
|
||||
return nl_parse_flower_actions(attrs, flower, terse);
|
||||
}
|
||||
|
||||
int
|
||||
parse_netlink_to_tc_flower(struct ofpbuf *reply, struct tcf_id *id,
|
||||
struct tc_flower *flower)
|
||||
struct tc_flower *flower, bool terse)
|
||||
{
|
||||
struct tcmsg *tc;
|
||||
struct nlattr *ta[ARRAY_SIZE(tca_policy)];
|
||||
@@ -1792,15 +1818,22 @@ parse_netlink_to_tc_flower(struct ofpbuf *reply, struct tcf_id *id,
|
||||
return EPROTO;
|
||||
}
|
||||
|
||||
return nl_parse_flower_options(ta[TCA_OPTIONS], flower);
|
||||
return nl_parse_flower_options(ta[TCA_OPTIONS], flower, terse);
|
||||
}
|
||||
|
||||
int
|
||||
tc_dump_flower_start(struct tcf_id *id, struct nl_dump *dump)
|
||||
tc_dump_flower_start(struct tcf_id *id, struct nl_dump *dump, bool terse)
|
||||
{
|
||||
struct ofpbuf request;
|
||||
|
||||
request_from_tcf_id(id, 0, RTM_GETTFILTER, NLM_F_DUMP, &request);
|
||||
if (terse) {
|
||||
struct nla_bitfield32 dump_flags = { TCA_DUMP_FLAGS_TERSE,
|
||||
TCA_DUMP_FLAGS_TERSE };
|
||||
|
||||
nl_msg_put_unspec(&request, TCA_DUMP_FLAGS, &dump_flags,
|
||||
sizeof dump_flags);
|
||||
}
|
||||
nl_dump_start(dump, NETLINK_ROUTE, &request);
|
||||
ofpbuf_uninit(&request);
|
||||
|
||||
@@ -1829,7 +1862,7 @@ tc_get_flower(struct tcf_id *id, struct tc_flower *flower)
|
||||
return error;
|
||||
}
|
||||
|
||||
error = parse_netlink_to_tc_flower(reply, id, flower);
|
||||
error = parse_netlink_to_tc_flower(reply, id, flower, false);
|
||||
ofpbuf_delete(reply);
|
||||
return error;
|
||||
}
|
||||
|
Reference in New Issue
Block a user