Skip to content

Commit

Permalink
Merge branch 'net-sched-offload-failure-error-reporting'
Browse files Browse the repository at this point in the history
Ido Schimmel says:

====================
net/sched: Better error reporting for offload failures

This patchset improves error reporting to user space when offload fails
during the flow action setup phase. That is, when failures occur in the
actions themselves, even before calling device drivers. Requested /
reported in [1].

This is done by passing extack to the offload_act_setup() callback and
making use of it in the various actions.

Patches #1-#2 change matchall and flower to log error messages to user
space in accordance with the verbose flag.

Patch #3 passes extack to the offload_act_setup() callback from the
various call sites, including matchall and flower.

Patches #4-#11 make use of extack in the various actions to report
offload failures.

Patch #12 adds an error message when the action does not support offload
at all.

Patches #13-#14 change matchall and flower to stop overwriting more
specific error messages.

[1] https://lore.kernel.org/netdev/20220317185249.5mff5u2x624pjewv@skbuf/
====================

Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Apr 8, 2022
2 parents 4a778f3 + fd23e0e commit 85b15c2
Show file tree
Hide file tree
Showing 20 changed files with 128 additions and 48 deletions.
3 changes: 2 additions & 1 deletion include/net/act_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ struct tc_action_ops {
(*get_psample_group)(const struct tc_action *a,
tc_action_priv_destructor *destructor);
int (*offload_act_setup)(struct tc_action *act, void *entry_data,
u32 *index_inc, bool bind);
u32 *index_inc, bool bind,
struct netlink_ext_ack *extack);
};

struct tc_action_net {
Expand Down
6 changes: 4 additions & 2 deletions include/net/pkt_cls.h
Original file line number Diff line number Diff line change
Expand Up @@ -547,10 +547,12 @@ tcf_match_indev(struct sk_buff *skb, int ifindex)
}

int tc_setup_offload_action(struct flow_action *flow_action,
const struct tcf_exts *exts);
const struct tcf_exts *exts,
struct netlink_ext_ack *extack);
void tc_cleanup_offload_action(struct flow_action *flow_action);
int tc_setup_action(struct flow_action *flow_action,
struct tc_action *actions[]);
struct tc_action *actions[],
struct netlink_ext_ack *extack);

int tc_setup_cb_call(struct tcf_block *block, enum tc_setup_type type,
void *type_data, bool err_stop, bool rtnl_held);
Expand Down
15 changes: 15 additions & 0 deletions include/net/tc_act/tc_gact.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,19 @@ static inline u32 tcf_gact_goto_chain_index(const struct tc_action *a)
return READ_ONCE(a->tcfa_action) & TC_ACT_EXT_VAL_MASK;
}

static inline bool is_tcf_gact_continue(const struct tc_action *a)
{
return __is_tcf_gact_act(a, TC_ACT_UNSPEC, false);
}

static inline bool is_tcf_gact_reclassify(const struct tc_action *a)
{
return __is_tcf_gact_act(a, TC_ACT_RECLASSIFY, false);
}

static inline bool is_tcf_gact_pipe(const struct tc_action *a)
{
return __is_tcf_gact_act(a, TC_ACT_PIPE, false);
}

#endif /* __NET_TC_GACT_H */
12 changes: 12 additions & 0 deletions include/net/tc_act/tc_skbedit.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,16 @@ static inline u32 tcf_skbedit_priority(const struct tc_action *a)
return priority;
}

/* Return true iff action is queue_mapping */
static inline bool is_tcf_skbedit_queue_mapping(const struct tc_action *a)
{
return is_tcf_skbedit_with_flag(a, SKBEDIT_F_QUEUE_MAPPING);
}

/* Return true iff action is inheritdsfield */
static inline bool is_tcf_skbedit_inheritdsfield(const struct tc_action *a)
{
return is_tcf_skbedit_with_flag(a, SKBEDIT_F_INHERITDSFIELD);
}

#endif /* __NET_TC_SKBEDIT_H */
4 changes: 2 additions & 2 deletions net/sched/act_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ static int offload_action_init(struct flow_offload_action *fl_action,
if (act->ops->offload_act_setup) {
spin_lock_bh(&act->tcfa_lock);
err = act->ops->offload_act_setup(act, fl_action, NULL,
false);
false, extack);
spin_unlock_bh(&act->tcfa_lock);
return err;
}
Expand Down Expand Up @@ -271,7 +271,7 @@ static int tcf_action_offload_add_ex(struct tc_action *action,
if (err)
goto fl_err;

err = tc_setup_action(&fl_action->action, actions);
err = tc_setup_action(&fl_action->action, actions, extack);
if (err) {
NL_SET_ERR_MSG_MOD(extack,
"Failed to setup tc actions for offload");
Expand Down
3 changes: 2 additions & 1 deletion net/sched/act_csum.c
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,8 @@ static size_t tcf_csum_get_fill_size(const struct tc_action *act)
}

static int tcf_csum_offload_act_setup(struct tc_action *act, void *entry_data,
u32 *index_inc, bool bind)
u32 *index_inc, bool bind,
struct netlink_ext_ack *extack)
{
if (bind) {
struct flow_action_entry *entry = entry_data;
Expand Down
3 changes: 2 additions & 1 deletion net/sched/act_ct.c
Original file line number Diff line number Diff line change
Expand Up @@ -1584,7 +1584,8 @@ static void tcf_stats_update(struct tc_action *a, u64 bytes, u64 packets,
}

static int tcf_ct_offload_act_setup(struct tc_action *act, void *entry_data,
u32 *index_inc, bool bind)
u32 *index_inc, bool bind,
struct netlink_ext_ack *extack)
{
if (bind) {
struct flow_action_entry *entry = entry_data;
Expand Down
13 changes: 12 additions & 1 deletion net/sched/act_gact.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,8 @@ static size_t tcf_gact_get_fill_size(const struct tc_action *act)
}

static int tcf_gact_offload_act_setup(struct tc_action *act, void *entry_data,
u32 *index_inc, bool bind)
u32 *index_inc, bool bind,
struct netlink_ext_ack *extack)
{
if (bind) {
struct flow_action_entry *entry = entry_data;
Expand All @@ -267,7 +268,17 @@ static int tcf_gact_offload_act_setup(struct tc_action *act, void *entry_data,
} else if (is_tcf_gact_goto_chain(act)) {
entry->id = FLOW_ACTION_GOTO;
entry->chain_index = tcf_gact_goto_chain_index(act);
} else if (is_tcf_gact_continue(act)) {
NL_SET_ERR_MSG_MOD(extack, "Offload of \"continue\" action is not supported");
return -EOPNOTSUPP;
} else if (is_tcf_gact_reclassify(act)) {
NL_SET_ERR_MSG_MOD(extack, "Offload of \"reclassify\" action is not supported");
return -EOPNOTSUPP;
} else if (is_tcf_gact_pipe(act)) {
NL_SET_ERR_MSG_MOD(extack, "Offload of \"pipe\" action is not supported");
return -EOPNOTSUPP;
} else {
NL_SET_ERR_MSG_MOD(extack, "Unsupported generic action offload");
return -EOPNOTSUPP;
}
*index_inc = 1;
Expand Down
3 changes: 2 additions & 1 deletion net/sched/act_gate.c
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,8 @@ static int tcf_gate_get_entries(struct flow_action_entry *entry,
}

static int tcf_gate_offload_act_setup(struct tc_action *act, void *entry_data,
u32 *index_inc, bool bind)
u32 *index_inc, bool bind,
struct netlink_ext_ack *extack)
{
int err;

Expand Down
4 changes: 3 additions & 1 deletion net/sched/act_mirred.c
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,8 @@ static void tcf_offload_mirred_get_dev(struct flow_action_entry *entry,
}

static int tcf_mirred_offload_act_setup(struct tc_action *act, void *entry_data,
u32 *index_inc, bool bind)
u32 *index_inc, bool bind,
struct netlink_ext_ack *extack)
{
if (bind) {
struct flow_action_entry *entry = entry_data;
Expand All @@ -478,6 +479,7 @@ static int tcf_mirred_offload_act_setup(struct tc_action *act, void *entry_data,
entry->id = FLOW_ACTION_MIRRED_INGRESS;
tcf_offload_mirred_get_dev(entry, act);
} else {
NL_SET_ERR_MSG_MOD(extack, "Unsupported mirred offload");
return -EOPNOTSUPP;
}
*index_inc = 1;
Expand Down
10 changes: 9 additions & 1 deletion net/sched/act_mpls.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,8 @@ static int tcf_mpls_search(struct net *net, struct tc_action **a, u32 index)
}

static int tcf_mpls_offload_act_setup(struct tc_action *act, void *entry_data,
u32 *index_inc, bool bind)
u32 *index_inc, bool bind,
struct netlink_ext_ack *extack)
{
if (bind) {
struct flow_action_entry *entry = entry_data;
Expand All @@ -410,7 +411,14 @@ static int tcf_mpls_offload_act_setup(struct tc_action *act, void *entry_data,
entry->mpls_mangle.bos = tcf_mpls_bos(act);
entry->mpls_mangle.ttl = tcf_mpls_ttl(act);
break;
case TCA_MPLS_ACT_DEC_TTL:
NL_SET_ERR_MSG_MOD(extack, "Offload not supported when \"dec_ttl\" option is used");
return -EOPNOTSUPP;
case TCA_MPLS_ACT_MAC_PUSH:
NL_SET_ERR_MSG_MOD(extack, "Offload not supported when \"mac_push\" option is used");
return -EOPNOTSUPP;
default:
NL_SET_ERR_MSG_MOD(extack, "Unsupported MPLS mode offload");
return -EOPNOTSUPP;
}
*index_inc = 1;
Expand Down
4 changes: 3 additions & 1 deletion net/sched/act_pedit.c
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,8 @@ static int tcf_pedit_search(struct net *net, struct tc_action **a, u32 index)
}

static int tcf_pedit_offload_act_setup(struct tc_action *act, void *entry_data,
u32 *index_inc, bool bind)
u32 *index_inc, bool bind,
struct netlink_ext_ack *extack)
{
if (bind) {
struct flow_action_entry *entry = entry_data;
Expand All @@ -503,6 +504,7 @@ static int tcf_pedit_offload_act_setup(struct tc_action *act, void *entry_data,
entry->id = FLOW_ACTION_ADD;
break;
default:
NL_SET_ERR_MSG_MOD(extack, "Unsupported pedit command offload");
return -EOPNOTSUPP;
}
entry->mangle.htype = tcf_pedit_htype(act, k);
Expand Down
20 changes: 16 additions & 4 deletions net/sched/act_police.c
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,8 @@ static int tcf_police_search(struct net *net, struct tc_action **a, u32 index)
return tcf_idr_search(tn, a, index);
}

static int tcf_police_act_to_flow_act(int tc_act, u32 *extval)
static int tcf_police_act_to_flow_act(int tc_act, u32 *extval,
struct netlink_ext_ack *extack)
{
int act_id = -EOPNOTSUPP;

Expand All @@ -430,19 +431,28 @@ static int tcf_police_act_to_flow_act(int tc_act, u32 *extval)
act_id = FLOW_ACTION_DROP;
else if (tc_act == TC_ACT_PIPE)
act_id = FLOW_ACTION_PIPE;
else if (tc_act == TC_ACT_RECLASSIFY)
NL_SET_ERR_MSG_MOD(extack, "Offload not supported when conform/exceed action is \"reclassify\"");
else
NL_SET_ERR_MSG_MOD(extack, "Unsupported conform/exceed action offload");
} else if (TC_ACT_EXT_CMP(tc_act, TC_ACT_GOTO_CHAIN)) {
act_id = FLOW_ACTION_GOTO;
*extval = tc_act & TC_ACT_EXT_VAL_MASK;
} else if (TC_ACT_EXT_CMP(tc_act, TC_ACT_JUMP)) {
act_id = FLOW_ACTION_JUMP;
*extval = tc_act & TC_ACT_EXT_VAL_MASK;
} else if (tc_act == TC_ACT_UNSPEC) {
NL_SET_ERR_MSG_MOD(extack, "Offload not supported when conform/exceed action is \"continue\"");
} else {
NL_SET_ERR_MSG_MOD(extack, "Unsupported conform/exceed action offload");
}

return act_id;
}

static int tcf_police_offload_act_setup(struct tc_action *act, void *entry_data,
u32 *index_inc, bool bind)
u32 *index_inc, bool bind,
struct netlink_ext_ack *extack)
{
if (bind) {
struct flow_action_entry *entry = entry_data;
Expand All @@ -466,14 +476,16 @@ static int tcf_police_offload_act_setup(struct tc_action *act, void *entry_data,
entry->police.mtu = tcf_police_tcfp_mtu(act);

act_id = tcf_police_act_to_flow_act(police->tcf_action,
&entry->police.exceed.extval);
&entry->police.exceed.extval,
extack);
if (act_id < 0)
return act_id;

entry->police.exceed.act_id = act_id;

act_id = tcf_police_act_to_flow_act(p->tcfp_result,
&entry->police.notexceed.extval);
&entry->police.notexceed.extval,
extack);
if (act_id < 0)
return act_id;

Expand Down
3 changes: 2 additions & 1 deletion net/sched/act_sample.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,8 @@ static void tcf_offload_sample_get_group(struct flow_action_entry *entry,
}

static int tcf_sample_offload_act_setup(struct tc_action *act, void *entry_data,
u32 *index_inc, bool bind)
u32 *index_inc, bool bind,
struct netlink_ext_ack *extack)
{
if (bind) {
struct flow_action_entry *entry = entry_data;
Expand Down
10 changes: 9 additions & 1 deletion net/sched/act_skbedit.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,8 @@ static size_t tcf_skbedit_get_fill_size(const struct tc_action *act)
}

static int tcf_skbedit_offload_act_setup(struct tc_action *act, void *entry_data,
u32 *index_inc, bool bind)
u32 *index_inc, bool bind,
struct netlink_ext_ack *extack)
{
if (bind) {
struct flow_action_entry *entry = entry_data;
Expand All @@ -342,7 +343,14 @@ static int tcf_skbedit_offload_act_setup(struct tc_action *act, void *entry_data
} else if (is_tcf_skbedit_priority(act)) {
entry->id = FLOW_ACTION_PRIORITY;
entry->priority = tcf_skbedit_priority(act);
} else if (is_tcf_skbedit_queue_mapping(act)) {
NL_SET_ERR_MSG_MOD(extack, "Offload not supported when \"queue_mapping\" option is used");
return -EOPNOTSUPP;
} else if (is_tcf_skbedit_inheritdsfield(act)) {
NL_SET_ERR_MSG_MOD(extack, "Offload not supported when \"inheritdsfield\" option is used");
return -EOPNOTSUPP;
} else {
NL_SET_ERR_MSG_MOD(extack, "Unsupported skbedit option offload");
return -EOPNOTSUPP;
}
*index_inc = 1;
Expand Down
4 changes: 3 additions & 1 deletion net/sched/act_tunnel_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -808,7 +808,8 @@ static int tcf_tunnel_encap_get_tunnel(struct flow_action_entry *entry,
static int tcf_tunnel_key_offload_act_setup(struct tc_action *act,
void *entry_data,
u32 *index_inc,
bool bind)
bool bind,
struct netlink_ext_ack *extack)
{
int err;

Expand All @@ -823,6 +824,7 @@ static int tcf_tunnel_key_offload_act_setup(struct tc_action *act,
} else if (is_tcf_tunnel_release(act)) {
entry->id = FLOW_ACTION_TUNNEL_DECAP;
} else {
NL_SET_ERR_MSG_MOD(extack, "Unsupported tunnel key mode offload");
return -EOPNOTSUPP;
}
*index_inc = 1;
Expand Down
4 changes: 3 additions & 1 deletion net/sched/act_vlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,8 @@ static size_t tcf_vlan_get_fill_size(const struct tc_action *act)
}

static int tcf_vlan_offload_act_setup(struct tc_action *act, void *entry_data,
u32 *index_inc, bool bind)
u32 *index_inc, bool bind,
struct netlink_ext_ack *extack)
{
if (bind) {
struct flow_action_entry *entry = entry_data;
Expand Down Expand Up @@ -398,6 +399,7 @@ static int tcf_vlan_offload_act_setup(struct tc_action *act, void *entry_data,
tcf_vlan_push_eth(entry->vlan_push_eth.src, entry->vlan_push_eth.dst, act);
break;
default:
NL_SET_ERR_MSG_MOD(extack, "Unsupported vlan action mode offload");
return -EOPNOTSUPP;
}
*index_inc = 1;
Expand Down
22 changes: 14 additions & 8 deletions net/sched/cls_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -3513,20 +3513,25 @@ EXPORT_SYMBOL(tc_cleanup_offload_action);

static int tc_setup_offload_act(struct tc_action *act,
struct flow_action_entry *entry,
u32 *index_inc)
u32 *index_inc,
struct netlink_ext_ack *extack)
{
#ifdef CONFIG_NET_CLS_ACT
if (act->ops->offload_act_setup)
return act->ops->offload_act_setup(act, entry, index_inc, true);
else
if (act->ops->offload_act_setup) {
return act->ops->offload_act_setup(act, entry, index_inc, true,
extack);
} else {
NL_SET_ERR_MSG(extack, "Action does not support offload");
return -EOPNOTSUPP;
}
#else
return 0;
#endif
}

int tc_setup_action(struct flow_action *flow_action,
struct tc_action *actions[])
struct tc_action *actions[],
struct netlink_ext_ack *extack)
{
int i, j, index, err = 0;
struct tc_action *act;
Expand All @@ -3551,7 +3556,7 @@ int tc_setup_action(struct flow_action *flow_action,
entry->hw_stats = tc_act_hw_stats(act->hw_stats);
entry->hw_index = act->tcfa_index;
index = 0;
err = tc_setup_offload_act(act, entry, &index);
err = tc_setup_offload_act(act, entry, &index, extack);
if (!err)
j += index;
else
Expand All @@ -3570,13 +3575,14 @@ int tc_setup_action(struct flow_action *flow_action,
}

int tc_setup_offload_action(struct flow_action *flow_action,
const struct tcf_exts *exts)
const struct tcf_exts *exts,
struct netlink_ext_ack *extack)
{
#ifdef CONFIG_NET_CLS_ACT
if (!exts)
return 0;

return tc_setup_action(flow_action, exts->actions);
return tc_setup_action(flow_action, exts->actions, extack);
#else
return 0;
#endif
Expand Down
Loading

0 comments on commit 85b15c2

Please sign in to comment.