2
0
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:
Vlad Buslov
2020-06-04 13:47:01 +03:00
committed by Simon Horman
parent 191536574e
commit 5db012c4ac
3 changed files with 51 additions and 17 deletions

View File

@@ -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;
}