@@ -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 */
@@ -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(®istry->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(®istry->conntrack_counters);
sfc_mae_counters_fini(®istry->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,
@@ -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 */
@@ -91,6 +91,9 @@ sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
case EFX_COUNTER_TYPE_ACTION:
counters = ®->action_counters;
break;
+ case EFX_COUNTER_TYPE_CONNTRACK:
+ counters = ®->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 = ®->action_counters;
break;
+ case EFX_COUNTER_TYPE_CONNTRACK:
+ counters = ®->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;
}