unsigned int used_keys;
};
-struct sparx5_tc_rule_pkt_cnt {
- u64 cookie;
- u32 pkts;
-};
-
/* These protocols have dedicated keysets in IS2 and a TC dissector
* ETH_P_ARP does not have a TC dissector
*/
return err;
}
-/* Collect packet counts from all rules with the same cookie */
-static int sparx5_tc_rule_counter_cb(void *arg, struct vcap_rule *rule)
-{
- struct sparx5_tc_rule_pkt_cnt *rinfo = arg;
- struct vcap_counter counter;
- int err = 0;
-
- if (rule->cookie == rinfo->cookie) {
- err = vcap_rule_get_counter(rule, &counter);
- if (err)
- return err;
- rinfo->pkts += counter.value;
- /* Reset the rule counter */
- counter.value = 0;
- vcap_rule_set_counter(rule, &counter);
- }
- return err;
-}
-
static int sparx5_tc_flower_stats(struct net_device *ndev,
struct flow_cls_offload *fco,
struct vcap_admin *admin)
{
struct sparx5_port *port = netdev_priv(ndev);
- struct sparx5_tc_rule_pkt_cnt rinfo = {};
+ struct vcap_counter ctr = {};
struct vcap_control *vctrl;
ulong lastused = 0;
- u64 drops = 0;
- u32 pkts = 0;
int err;
- rinfo.cookie = fco->cookie;
vctrl = port->sparx5->vcap_ctrl;
- err = vcap_rule_iter(vctrl, sparx5_tc_rule_counter_cb, &rinfo);
+ err = vcap_get_rule_count_by_cookie(vctrl, &ctr, fco->cookie);
if (err)
return err;
- pkts = rinfo.pkts;
- flow_stats_update(&fco->stats, 0x0, pkts, drops, lastused,
+ flow_stats_update(&fco->stats, 0x0, ctr.value, 0, lastused,
FLOW_ACTION_HW_STATS_IMMEDIATE);
return err;
}
}
EXPORT_SYMBOL_GPL(vcap_rule_set_counter_id);
-/* Provide all rules via a callback interface */
-int vcap_rule_iter(struct vcap_control *vctrl,
- int (*callback)(void *, struct vcap_rule *), void *arg)
-{
- struct vcap_rule_internal *ri;
- struct vcap_admin *admin;
- int ret;
-
- ret = vcap_api_check(vctrl);
- if (ret)
- return ret;
-
- /* Iterate all rules in each VCAP instance */
- list_for_each_entry(admin, &vctrl->list, list) {
- list_for_each_entry(ri, &admin->rules, list) {
- ret = callback(arg, &ri->data);
- if (ret)
- return ret;
- }
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(vcap_rule_iter);
-
int vcap_rule_set_counter(struct vcap_rule *rule, struct vcap_counter *ctr)
{
struct vcap_rule_internal *ri = to_intrule(rule);
return -EINVAL;
}
+/* Collect packet counts from all rules with the same cookie */
+int vcap_get_rule_count_by_cookie(struct vcap_control *vctrl,
+ struct vcap_counter *ctr, u64 cookie)
+{
+ struct vcap_rule_internal *ri;
+ struct vcap_counter temp = {};
+ struct vcap_admin *admin;
+ int err;
+
+ err = vcap_api_check(vctrl);
+ if (err)
+ return err;
+
+ /* Iterate all rules in each VCAP instance */
+ list_for_each_entry(admin, &vctrl->list, list) {
+ mutex_lock(&admin->lock);
+ list_for_each_entry(ri, &admin->rules, list) {
+ if (ri->data.cookie != cookie)
+ continue;
+
+ err = vcap_read_counter(ri, &temp);
+ if (err)
+ goto unlock;
+ ctr->value += temp.value;
+
+ /* Reset the rule counter */
+ temp.value = 0;
+ temp.sticky = 0;
+ err = vcap_write_counter(ri, &temp);
+ if (err)
+ goto unlock;
+ }
+ mutex_unlock(&admin->lock);
+ }
+ return err;
+
+unlock:
+ mutex_unlock(&admin->lock);
+ return err;
+}
+EXPORT_SYMBOL_GPL(vcap_get_rule_count_by_cookie);
+
static int vcap_rule_mod_key(struct vcap_rule *rule,
enum vcap_key_field key,
enum vcap_field_type ftype,