On 2019-04-26 8:13 a.m., Edward Cree wrote:
Sure; this block is (still slightly abridged)
if (a->ops && a->ops->stats_update) {
struct efx_tc_counter_index *ctr;
ctr = efx_tc_flower_get_counter_by_index(efx, a->tcfa_index);
if (IS_ERR(ctr)) {
rc = PTR_ERR(ctr);
goto release;
}
act->count = ctr;
act->count_action_idx = i;
efx_tc_calculate_count_delta(act);
}
and we have
struct efx_tc_counter_index {
u32 tcfa_index;
struct rhash_head linkage;
refcount_t ref;
u32 fw_id;
};
const static struct rhashtable_params efx_tc_counter_ht_params = {
.key_len = offsetof(struct efx_tc_counter_index, linkage),
.key_offset = 0,
.head_offset = offsetof(struct efx_tc_counter_index, linkage),
};
static struct efx_tc_counter_index *efx_tc_flower_get_counter_by_index(
struct efx_nic *efx, u32 idx)
{
struct efx_tc_counter_index *ctr, *old;
long rc;
ctr = kzalloc(sizeof(*ctr), GFP_USER);
if (!ctr)
return ERR_PTR(-ENOMEM);
ctr->tcfa_index = idx;
old = rhashtable_lookup_get_insert_fast(&efx->tc->counter_ht,
&ctr->linkage,
efx_tc_counter_ht_params);
if (old) {
/* don't need our new entry */
kfree(ctr);
if (!refcount_inc_not_zero(&old->ref))
return ERR_PTR(-EAGAIN);
/* existing entry found */
ctr = old;
} else {
rc = efx_tc_flower_allocate_counter(efx);
if (rc < 0) {
rhashtable_remove_fast(&efx->tc->counter_ht,
&ctr->linkage,
efx_tc_counter_ht_params);
kfree(ctr);
return ERR_PTR(rc);
}
ctr->fw_id = rc;
refcount_inc(&ctr->ref);
}
return ctr;
}
Thus if (and only if) two TC actions have the same tcfa_index, they will
share a single counter in the HW.
I gathered from a previous conversation with Jamal[1] that that was the
correct behaviour:
Yes, this is expected behavior. Meters/policers as well used indices to
indicate sharing.
cheers,
jamal