Hello Jianbo, On Thu, Feb 24, 2022 at 10:29:07AM +0000, Jianbo Liu wrote: > The current police offload action entry is missing exceed/notexceed > actions and parameters that can be configured by tc police action. > Add the missing parameters as a pre-step for offloading police actions > to hardware. > > Signed-off-by: Jianbo Liu <jianbol@xxxxxxxxxx> > Signed-off-by: Roi Dayan <roid@xxxxxxxxxx> > Reviewed-by: Ido Schimmel <idosch@xxxxxxxxxx> > --- > include/net/flow_offload.h | 9 +++++++ > include/net/tc_act/tc_police.h | 30 ++++++++++++++++++++++ > net/sched/act_police.c | 46 ++++++++++++++++++++++++++++++++++ > 3 files changed, 85 insertions(+) > > diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h > index 5b8c54eb7a6b..74f44d44abe3 100644 > --- a/include/net/flow_offload.h > +++ b/include/net/flow_offload.h > @@ -148,6 +148,8 @@ enum flow_action_id { > FLOW_ACTION_MPLS_MANGLE, > FLOW_ACTION_GATE, > FLOW_ACTION_PPPOE_PUSH, > + FLOW_ACTION_JUMP, > + FLOW_ACTION_PIPE, > NUM_FLOW_ACTIONS, > }; > > @@ -235,9 +237,16 @@ struct flow_action_entry { > struct { /* FLOW_ACTION_POLICE */ > u32 burst; > u64 rate_bytes_ps; > + u64 peakrate_bytes_ps; > + u32 avrate; > + u16 overhead; > u64 burst_pkt; > u64 rate_pkt_ps; > u32 mtu; > + struct { > + enum flow_action_id act_id; > + u32 extval; > + } exceed, notexceed; > } police; > struct { /* FLOW_ACTION_CT */ > int action; > diff --git a/include/net/tc_act/tc_police.h b/include/net/tc_act/tc_police.h > index 72649512dcdd..283bde711a42 100644 > --- a/include/net/tc_act/tc_police.h > +++ b/include/net/tc_act/tc_police.h > @@ -159,4 +159,34 @@ static inline u32 tcf_police_tcfp_mtu(const struct tc_action *act) > return params->tcfp_mtu; > } > > +static inline u64 tcf_police_peakrate_bytes_ps(const struct tc_action *act) > +{ > + struct tcf_police *police = to_police(act); > + struct tcf_police_params *params; > + > + params = rcu_dereference_protected(police->params, > + lockdep_is_held(&police->tcf_lock)); > + return params->peak.rate_bytes_ps; > +} > + > +static inline u32 tcf_police_tcfp_ewma_rate(const struct tc_action *act) > +{ > + struct tcf_police *police = to_police(act); > + struct tcf_police_params *params; > + > + params = rcu_dereference_protected(police->params, > + lockdep_is_held(&police->tcf_lock)); > + return params->tcfp_ewma_rate; > +} > + > +static inline u16 tcf_police_rate_overhead(const struct tc_action *act) > +{ > + struct tcf_police *police = to_police(act); > + struct tcf_police_params *params; > + > + params = rcu_dereference_protected(police->params, > + lockdep_is_held(&police->tcf_lock)); > + return params->rate.overhead; > +} > + > #endif /* __NET_TC_POLICE_H */ > diff --git a/net/sched/act_police.c b/net/sched/act_police.c > index 0923aa2b8f8a..a2275eef6877 100644 > --- a/net/sched/act_police.c > +++ b/net/sched/act_police.c > @@ -405,20 +405,66 @@ 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) > +{ > + int act_id = -EOPNOTSUPP; > + > + if (!TC_ACT_EXT_OPCODE(tc_act)) { > + if (tc_act == TC_ACT_OK) > + act_id = FLOW_ACTION_ACCEPT; > + else if (tc_act == TC_ACT_SHOT) > + act_id = FLOW_ACTION_DROP; > + else if (tc_act == TC_ACT_PIPE) > + act_id = FLOW_ACTION_PIPE; > + } 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; > + } > + > + return act_id; > +} > + > static int tcf_police_offload_act_setup(struct tc_action *act, void *entry_data, > u32 *index_inc, bool bind) > { > if (bind) { > struct flow_action_entry *entry = entry_data; > + struct tcf_police *police = to_police(act); > + struct tcf_police_params *p; > + int act_id; > + > + p = rcu_dereference_protected(police->params, > + lockdep_is_held(&police->tcf_lock)); > > entry->id = FLOW_ACTION_POLICE; > entry->police.burst = tcf_police_burst(act); > entry->police.rate_bytes_ps = > tcf_police_rate_bytes_ps(act); > + entry->police.peakrate_bytes_ps = tcf_police_peakrate_bytes_ps(act); > + entry->police.avrate = tcf_police_tcfp_ewma_rate(act); > + entry->police.overhead = tcf_police_rate_overhead(act); > entry->police.burst_pkt = tcf_police_burst_pkt(act); > entry->police.rate_pkt_ps = > tcf_police_rate_pkt_ps(act); > entry->police.mtu = tcf_police_tcfp_mtu(act); > + > + act_id = tcf_police_act_to_flow_act(police->tcf_action, > + &entry->police.exceed.extval); I don't know why just now, but I observed an apparent regression here with these commands: root@debian:~# tc qdisc add dev swp3 clsact root@debian:~# tc filter add dev swp3 ingress protocol ip flower skip_sw ip_proto icmp action police rate 100Mbit burst 10000 [ 45.767900] tcf_police_act_to_flow_act: 434: tc_act 1 [ 45.773100] tcf_police_offload_act_setup: 475, act_id -95 Error: cls_flower: Failed to setup flow action. We have an error talking to the kernel, -1 The reason why I'm not sure is because I don't know if this should have worked as intended or not. I am remarking just now in "man tc-police" that the default conform-exceed action is "reclassify". So if I specify "conform-exceed drop", things are as expected, but with the default (implicitly "conform-exceed reclassify") things fail with -EOPNOTSUPP because tcf_police_act_to_flow_act() doesn't handle a police->tcf_action of TC_ACT_RECLASSIFY. Should it? > + 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); > + if (act_id < 0) > + return act_id; > + > + entry->police.notexceed.act_id = act_id; > + > *index_inc = 1; > } else { > struct flow_offload_action *fl_action = entry_data; > -- > 2.26.2 >