It has shown FLOW_ACTION_POLICE is not stable, and it's very likely that options were added at drivers' request. However, that also means .port_policer_add() would have to check the parameters themselves. Giving that struct dsa_mall_policer_tc_entry is not stable, adjusting the interface between the framework and drivers would be a pain. Introduce a helper to maximize forward compatibility. Drivers may use it to recognize the pattern of tc entry reliably, and ensure all newly-added options are set to 0 / their default values and do not break the semantics. Signed-off-by: David Yang --- include/net/dsa.h | 14 ++++++++++++++ net/dsa/dsa.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/include/net/dsa.h b/include/net/dsa.h index 4c177b168ec8..957439846fe5 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -1410,4 +1410,18 @@ netdev_tx_t dsa_enqueue_skb(struct sk_buff *skb, struct net_device *dev); void dsa_port_phylink_mac_change(struct dsa_switch *ds, int port, bool up); bool dsa_supports_eee(struct dsa_switch *ds, int port); +enum dsa_mall_policer_tc_type { + /* Pattern recognized, no surprising fields exist */ + DSA_MALL_POLICER_TC_KNOWN = BIT(0), + /* Unset: .burst and .rate_bytes_per_sec valid + * Set: .burst_pkt and .rate_pkt_ps valid + */ + DSA_MALL_POLICER_TC_PKT_MODE = BIT(1), + /* .mtu valid */ + DSA_MALL_POLICER_TC_MTU = BIT(2), +}; + +unsigned long +dsa_mall_policer_tc_entry_type(struct dsa_mall_policer_tc_entry *entry); + #endif diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 35ce3941fae3..c8102cea5ab3 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -1834,6 +1834,39 @@ int dsa_port_simple_hsr_leave(struct dsa_switch *ds, int port, } EXPORT_SYMBOL_GPL(dsa_port_simple_hsr_leave); +/* dsa_mall_policer_tc_entry_type - map tc_entry to some "known" types + * @entry: the tc entry + * + * A helper to check dsa_mall_policer_tc_entry against some known patterns, + * without having to know the exact struct layout. + * + * Returns: ORs of enum dsa_mall_policer_tc_type with DSA_MALL_POLICER_TC_KNOWN + * set if recognized, otherwise 0 + */ +unsigned long +dsa_mall_policer_tc_entry_type(struct dsa_mall_policer_tc_entry *entry) +{ + bool byte_mode = (entry->burst || entry->rate_bytes_per_sec); + bool pkt_mode = (entry->burst_pkt || entry->rate_pkt_ps); + unsigned long flags = DSA_MALL_POLICER_TC_KNOWN; + + if (byte_mode == pkt_mode) + return 0; + if (entry->peakrate_bytes_ps || entry->avrate || entry->overhead) + return 0; + if (entry->exceed.act_id != FLOW_ACTION_DROP || + entry->notexceed.act_id != FLOW_ACTION_ACCEPT) + return 0; + + if (pkt_mode) + flags |= DSA_MALL_POLICER_TC_PKT_MODE; + if (entry->mtu) + flags |= DSA_MALL_POLICER_TC_MTU; + + return flags; +} +EXPORT_SYMBOL_GPL(dsa_mall_policer_tc_entry_type); + static const struct dsa_stubs __dsa_stubs = { .conduit_hwtstamp_validate = __dsa_conduit_hwtstamp_validate, }; -- 2.51.0