These are 1-bit saturating counters which can only be useful
to tell whether a given flow rule has offloaded some packets
since the last query. Byte count is never provided for these.

Signed-off-by: Ivan Malov <ivan.ma...@arknetworks.am>
Reviewed-by: Andy Moreton <amore...@xilinx.com>
---
 drivers/net/sfc/sfc_flow.h        |   2 +
 drivers/net/sfc/sfc_mae.c         | 119 ++++++++++++++++++++++--------
 drivers/net/sfc/sfc_mae.h         |   2 +
 drivers/net/sfc/sfc_mae_counter.c |  30 ++++++++
 4 files changed, 124 insertions(+), 29 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index af94d0654a..601f93e540 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -86,6 +86,8 @@ struct sfc_flow_spec_mae {
        /* Conntrack (CT) assistance table entry key and response */
        sfc_mae_conntrack_response_t    ct_resp;
        sfc_mae_conntrack_key_t         ct_key;
+       /* Conntrack (CT) assistance counter */
+       struct sfc_mae_counter          *ct_counter;
 };
 
 /* PMD-specific definition of the opaque type from rte_flow.h */
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 7353d04af8..ab315853d5 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -65,7 +65,8 @@ sfc_mae_assign_entity_mport(struct sfc_adapter *sa,
 
 static int
 sfc_mae_counter_registry_init(struct sfc_mae_counter_registry *registry,
-                             uint32_t nb_action_counters_max)
+                             uint32_t nb_action_counters_max,
+                             uint32_t nb_conntrack_counters_max)
 {
        int ret;
 
@@ -76,12 +77,20 @@ sfc_mae_counter_registry_init(struct 
sfc_mae_counter_registry *registry,
 
        registry->action_counters.type = EFX_COUNTER_TYPE_ACTION;
 
+       ret = sfc_mae_counters_init(&registry->conntrack_counters,
+                                   nb_conntrack_counters_max);
+       if (ret != 0)
+               return ret;
+
+       registry->conntrack_counters.type = EFX_COUNTER_TYPE_CONNTRACK;
+
        return 0;
 }
 
 static void
 sfc_mae_counter_registry_fini(struct sfc_mae_counter_registry *registry)
 {
+       sfc_mae_counters_fini(&registry->conntrack_counters);
        sfc_mae_counters_fini(&registry->action_counters);
 }
 
@@ -162,10 +171,13 @@ sfc_mae_attach(struct sfc_adapter *sa)
 
                sfc_log_init(sa, "init MAE counter record registry");
                rc = sfc_mae_counter_registry_init(&mae->counter_registry,
-                                       limits.eml_max_n_action_counters);
+                                       limits.eml_max_n_action_counters,
+                                       limits.eml_max_n_conntrack_counters);
                if (rc != 0) {
-                       sfc_err(sa, "failed to init record registry for %u AR 
counters: %s",
-                               limits.eml_max_n_action_counters, 
rte_strerror(rc));
+                       sfc_err(sa, "failed to init record registry for %u AR 
and %u CT counters: %s",
+                               limits.eml_max_n_action_counters,
+                               limits.eml_max_n_conntrack_counters,
+                               rte_strerror(rc));
                        goto fail_counter_registry_init;
                }
        }
@@ -1471,6 +1483,8 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
        }
 
        sfc_mae_action_rule_del(sa, spec_mae->action_rule);
+
+       sfc_mae_counter_del(sa, spec_mae->ct_counter);
 }
 
 static int
@@ -4223,7 +4237,7 @@ static const char * const action_names[] = {
 static int
 sfc_mae_rule_parse_action(struct sfc_adapter *sa,
                          const struct rte_flow_action *action,
-                         struct rte_flow *flow,
+                         struct rte_flow *flow, bool ct,
                          struct sfc_mae_actions_bundle *bundle,
                          struct sfc_mae_aset_ctx *ctx,
                          struct rte_flow_error *error)
@@ -4239,6 +4253,12 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
        bool custom_error = B_FALSE;
        int rc = 0;
 
+       if (ct) {
+               mae_counter_type = EFX_COUNTER_TYPE_CONNTRACK;
+               counterp = &spec_mae->ct_counter;
+               spec_ptr = NULL;
+       }
+
        switch (action->type) {
        case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
                SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VXLAN_DECAP,
@@ -4526,7 +4546,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
                if (rc != 0)
                        goto fail_rule_parse_action;
 
-               rc = sfc_mae_rule_parse_action(sa, action, flow,
+               rc = sfc_mae_rule_parse_action(sa, action, flow, ct,
                                               &bundle, &ctx, error);
                if (rc != 0)
                        goto fail_rule_parse_action;
@@ -4561,8 +4581,15 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
                 */
                efx_mae_action_set_populate_mark_reset(ctx.spec);
 
-               (ctx.counter)->ft_switch_hit_counter =
-                       &spec_mae->ft_ctx->switch_hit_counter;
+               if (ctx.counter != NULL) {
+                       (ctx.counter)->ft_switch_hit_counter =
+                               &spec_mae->ft_ctx->switch_hit_counter;
+               } else if (sfc_mae_counter_stream_enabled(sa)) {
+                       SFC_ASSERT(ct);
+
+                       spec_mae->ct_counter->ft_switch_hit_counter =
+                               &spec_mae->ft_ctx->switch_hit_counter;
+               }
                break;
        default:
                SFC_ASSERT(B_FALSE);
@@ -4843,12 +4870,34 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
                return rc;
 
        if (spec_mae->action_rule->ct_mark != 0) {
+               struct sfc_mae_counter *counter = spec_mae->ct_counter;
+
+               rc = sfc_mae_counter_enable(sa, counter, NULL);
+               if (rc != 0) {
+                       sfc_mae_action_rule_disable(sa, action_rule);
+                       return rc;
+               }
+
+               if (counter != NULL) {
+                       struct sfc_mae_fw_rsrc *fw_rsrc = &counter->fw_rsrc;
+
+                       spec_mae->ct_resp.counter_id = fw_rsrc->counter_id.id;
+
+                       rc = sfc_mae_counter_start(sa);
+                       if (rc != 0) {
+                               sfc_mae_action_rule_disable(sa, action_rule);
+                               return rc;
+                       }
+               } else {
+                       spec_mae->ct_resp.counter_id = EFX_MAE_RSRC_ID_INVALID;
+               }
+
                spec_mae->ct_resp.ct_mark = spec_mae->action_rule->ct_mark;
-               spec_mae->ct_resp.counter_id = EFX_MAE_RSRC_ID_INVALID;
 
                rc = sfc_mae_conntrack_insert(sa, &spec_mae->ct_key,
                                              &spec_mae->ct_resp);
                if (rc != 0) {
+                       sfc_mae_counter_disable(sa, counter);
                        sfc_mae_action_rule_disable(sa, action_rule);
                        return rc;
                }
@@ -4871,6 +4920,8 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,
        if (action_rule->ct_mark != 0)
                (void)sfc_mae_conntrack_delete(sa, &spec_mae->ct_key);
 
+       sfc_mae_counter_disable(sa, spec_mae->ct_counter);
+
        sfc_mae_action_rule_disable(sa, action_rule);
 
        return 0;
@@ -4885,31 +4936,41 @@ sfc_mae_query_counter(struct sfc_adapter *sa,
 {
        const struct sfc_mae_action_rule *action_rule = spec->action_rule;
        const struct rte_flow_action_count *conf = action->conf;
-       struct sfc_mae_action_set *action_set;
-       struct sfc_mae_counter *counter;
+       struct sfc_mae_counter *counters[1 /* action rule counter */ +
+                                        1 /* conntrack counter */];
+       unsigned int i;
        int rc;
 
-       if (action_rule == NULL || action_rule->action_set == NULL ||
-           action_rule->action_set->counter == NULL ||
-           action_rule->action_set->counter->indirect) {
-               return rte_flow_error_set(error, EINVAL,
-                       RTE_FLOW_ERROR_TYPE_ACTION, action,
-                       "Queried flow rule does not have count actions");
-       }
+       /*
+        * The check for counter unavailability is done based
+        * on counter traversal results. See error set below.
+        */
+       if (action_rule != NULL && action_rule->action_set != NULL &&
+           action_rule->action_set->counter != NULL &&
+           !action_rule->action_set->counter->indirect)
+               counters[0] = action_rule->action_set->counter;
+       else
+               counters[0] = NULL;
 
-       action_set = action_rule->action_set;
-       counter = action_set->counter;
+       counters[1] = spec->ct_counter;
 
-       if (conf == NULL ||
-           (counter->rte_id_valid && conf->id == counter->rte_id)) {
-               rc = sfc_mae_counter_get(sa, counter, data);
-               if (rc != 0) {
-                       return rte_flow_error_set(error, EINVAL,
-                               RTE_FLOW_ERROR_TYPE_ACTION, action,
-                               "Queried flow rule counter action is invalid");
-               }
+       for (i = 0; i < RTE_DIM(counters); ++i) {
+               struct sfc_mae_counter *counter = counters[i];
 
-               return 0;
+               if (counter == NULL)
+                       continue;
+
+               if (conf == NULL ||
+                   (counter->rte_id_valid && conf->id == counter->rte_id)) {
+                       rc = sfc_mae_counter_get(sa, counter, data);
+                       if (rc != 0) {
+                               return rte_flow_error_set(error, EINVAL,
+                                       RTE_FLOW_ERROR_TYPE_ACTION, action,
+                                       "Queried flow rule counter action is 
invalid");
+                       }
+
+                       return 0;
+               }
        }
 
        return rte_flow_error_set(error, ENOENT,
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 3a3a5225fd..80585c0e93 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -173,6 +173,8 @@ struct sfc_mae_counter_registry {
        /* Common counter information */
        /** Action rule counter record collection */
        struct sfc_mae_counter_records  action_counters;
+       /** Conntrack counter record collection */
+       struct sfc_mae_counter_records  conntrack_counters;
 
        /* Information used by counter update service */
        /** Callback to get packets from RxQ */
diff --git a/drivers/net/sfc/sfc_mae_counter.c 
b/drivers/net/sfc/sfc_mae_counter.c
index 47448cba15..79043ff7d7 100644
--- a/drivers/net/sfc/sfc_mae_counter.c
+++ b/drivers/net/sfc/sfc_mae_counter.c
@@ -91,6 +91,9 @@ sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
        case EFX_COUNTER_TYPE_ACTION:
                counters = &reg->action_counters;
                break;
+       case EFX_COUNTER_TYPE_CONNTRACK:
+               counters = &reg->conntrack_counters;
+               break;
        default:
                rc = EINVAL;
                goto fail_counter_type_check;
@@ -172,6 +175,9 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
        case EFX_COUNTER_TYPE_ACTION:
                counters = &reg->action_counters;
                break;
+       case EFX_COUNTER_TYPE_CONNTRACK:
+               counters = &reg->conntrack_counters;
+               break;
        default:
                return EINVAL;
        }
@@ -319,6 +325,9 @@ sfc_mae_parse_counter_packet(struct sfc_adapter *sa,
        case ERF_SC_PACKETISER_HEADER_IDENTIFIER_AR:
                counters = &counter_registry->action_counters;
                break;
+       case ERF_SC_PACKETISER_HEADER_IDENTIFIER_CT:
+               counters = &counter_registry->conntrack_counters;
+               break;
        default:
                sfc_err(sa, "unexpected MAE counters source identifier %u", id);
                return;
@@ -392,6 +401,23 @@ sfc_mae_parse_counter_packet(struct sfc_adapter *sa,
                byte_count_hi =
                        EFX_OWORD_FIELD32(counters_data[i],
                                ERF_SC_PACKETISER_PAYLOAD_BYTE_COUNT_HI);
+
+               if (id == ERF_SC_PACKETISER_HEADER_IDENTIFIER_CT) {
+                       /*
+                        * FIXME:
+                        *
+                        * CT counters are 1-bit saturating counters.
+                        * There is no way to express this in DPDK
+                        * currently, so increment the hit count
+                        * by one to let the application know
+                        * that the flow is still effective.
+                        */
+                       packet_count_lo = 1;
+                       packet_count_hi = 0;
+                       byte_count_lo = 0;
+                       byte_count_hi = 0;
+               }
+
                sfc_mae_counter_increment(sa,
                        counters,
                        EFX_OWORD_FIELD32(counters_data[i],
@@ -983,6 +1009,10 @@ sfc_mae_counter_get(struct sfc_adapter *sa,
                counters = &sa->mae.counter_registry.action_counters;
                need_byte_count = true;
                break;
+       case EFX_COUNTER_TYPE_CONNTRACK:
+               counters = &sa->mae.counter_registry.conntrack_counters;
+               need_byte_count = false;
+               break;
        default:
                return EINVAL;
        }
-- 
2.30.2

Reply via email to