From: Denis Pryazhennikov <denis.pryazhenni...@arknetworks.am>

The new API allows to manipulate entries in
the HW Conntrack table.
It uses a new Table Access API as a backend.

Signed-off-by: Denis Pryazhennikov <denis.pryazhenni...@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.ma...@arknetworks.am>
Reviewed-by: Andy Moreton <amore...@xilinx.com>
---
 drivers/net/sfc/meson.build  |   1 +
 drivers/net/sfc/sfc_mae_ct.c | 201 +++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae_ct.h |  68 ++++++++++++
 3 files changed, 270 insertions(+)
 create mode 100644 drivers/net/sfc/sfc_mae_ct.c
 create mode 100644 drivers/net/sfc/sfc_mae_ct.h

diff --git a/drivers/net/sfc/meson.build b/drivers/net/sfc/meson.build
index c9d4264674..5adde68517 100644
--- a/drivers/net/sfc/meson.build
+++ b/drivers/net/sfc/meson.build
@@ -92,6 +92,7 @@ sources = files(
         'sfc_tbl_meta_cache.c',
         'sfc_mae.c',
         'sfc_mae_counter.c',
+        'sfc_mae_ct.c',
         'sfc_flow.c',
         'sfc_flow_rss.c',
         'sfc_flow_tunnel.c',
diff --git a/drivers/net/sfc/sfc_mae_ct.c b/drivers/net/sfc/sfc_mae_ct.c
new file mode 100644
index 0000000000..fd6819c8a5
--- /dev/null
+++ b/drivers/net/sfc/sfc_mae_ct.c
@@ -0,0 +1,201 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#include "sfc.h"
+#include "sfc_mae_ct.h"
+
+/* SF-123102-TC-1A § 10.6.3: Conntrack_Table key */
+static void
+sfc_mae_ct_key_to_mcdi_key(const sfc_mae_conntrack_key_t *key,
+                          const efx_table_field_descriptor_t *fields,
+                          unsigned int n_fields, uint32_t *mcdi_key,
+                          unsigned int key_size)
+{
+       unsigned int i;
+
+       for (i = 0; i < n_fields; i++) {
+               const efx_table_field_descriptor_t *desc = &fields[i];
+
+               if (desc->mask_type == EFX_TABLE_FIELD_MASK_NEVER)
+                       continue;
+
+               switch (desc->field_id) {
+               case EFX_TABLE_FIELD_ID_IP_PROTO:
+                       sfc_tbls_field_set_u8(mcdi_key, key_size, desc->lbn,
+                                             desc->width, key->ip_proto);
+                       break;
+               case EFX_TABLE_FIELD_ID_ETHER_TYPE:
+                       sfc_tbls_field_set_u16(mcdi_key, key_size, desc->lbn,
+                                              desc->width, key->ether_type_le);
+                       break;
+               case EFX_TABLE_FIELD_ID_SRC_PORT:
+                       sfc_tbls_field_set_u16(mcdi_key, key_size, desc->lbn,
+                                              desc->width, key->src_port_le);
+                       break;
+               case EFX_TABLE_FIELD_ID_DST_PORT:
+                       sfc_tbls_field_set_u16(mcdi_key, key_size, desc->lbn,
+                                              desc->width, key->dst_port_le);
+                       break;
+               case EFX_TABLE_FIELD_ID_SRC_IP:
+                       sfc_tbls_field_set_ip(mcdi_key, key_size, desc->lbn,
+                                             desc->width,
+                                             (const uint32_t 
*)key->src_addr_le);
+                       break;
+               case EFX_TABLE_FIELD_ID_DST_IP:
+                       sfc_tbls_field_set_ip(mcdi_key, key_size, desc->lbn,
+                                             desc->width,
+                                             (const uint32_t 
*)key->dst_addr_le);
+                       break;
+
+               default:
+                       break;
+               }
+       }
+}
+
+/* SF-123102-TC-1A § 10.6.4: Conntrack_Table response */
+static void
+sfc_mae_ct_response_to_mcdi_response(const sfc_mae_conntrack_response_t 
*response,
+                                    const efx_table_field_descriptor_t *fields,
+                                    unsigned int n_fields, uint32_t *mcdi_resp,
+                                    unsigned int resp_size)
+{
+       unsigned int i;
+
+       for (i = 0; i < n_fields; i++) {
+               const efx_table_field_descriptor_t *desc = &fields[i];
+
+               if (desc->mask_type == EFX_TABLE_FIELD_MASK_NEVER)
+                       continue;
+
+               /* Fields of responses are always reported with the EXACT type. 
*/
+               SFC_ASSERT(desc->mask_type == EFX_TABLE_FIELD_MASK_EXACT);
+
+               switch (desc->field_id) {
+               case EFX_TABLE_FIELD_ID_CT_MARK:
+                       sfc_tbls_field_set_u32(mcdi_resp, resp_size, desc->lbn,
+                                              desc->width, response->ct_mark);
+                       break;
+               case EFX_TABLE_FIELD_ID_COUNTER_ID:
+                       sfc_tbls_field_set_u32(mcdi_resp, resp_size, desc->lbn,
+                                              desc->width, 
response->counter_id);
+                       break;
+               case EFX_TABLE_FIELD_ID_NAT_DIR:
+                       sfc_tbls_field_set_u8(mcdi_resp, resp_size, desc->lbn,
+                                             desc->width, 
response->nat.dir_is_dst);
+                       break;
+               case EFX_TABLE_FIELD_ID_NAT_IP:
+                       sfc_tbls_field_set_u32(mcdi_resp, resp_size, desc->lbn,
+                                              desc->width, 
response->nat.ip_le);
+                       break;
+               case EFX_TABLE_FIELD_ID_NAT_PORT:
+                       sfc_tbls_field_set_u16(mcdi_resp, resp_size, desc->lbn,
+                                              desc->width, 
response->nat.port_le);
+                       break;
+
+               default:
+                       break;
+               }
+       }
+}
+
+int
+sfc_mae_conntrack_insert(struct sfc_adapter *sa,
+                        const sfc_mae_conntrack_key_t *key,
+                        const sfc_mae_conntrack_response_t *response)
+{
+       const struct sfc_tbls *tables = &sa->hw_tables;
+       uint8_t data[EFX_TABLE_ENTRY_LENGTH_MAX] = {0};
+       const struct sfc_tbl_meta *meta = NULL;
+       unsigned int response_size;
+       uint32_t *response_data;
+       unsigned int data_size;
+       unsigned int key_size;
+       uint32_t *start_data;
+       uint16_t resp_width;
+       uint16_t key_width;
+       uint32_t *key_data;
+       uint32_t *end_data;
+       int rc = 0;
+
+       if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
+               return -ENOTSUP;
+
+       if (!sfc_mae_conntrack_is_supported(sa))
+               return -ENOTSUP;
+
+       meta = sfc_mae_conntrack_meta_lookup(sa);
+       if (meta == NULL)
+               return -ENOENT;
+
+       key_width = meta->descriptor.key_width;
+       resp_width = meta->descriptor.resp_width;
+
+       start_data = (uint32_t *)data;
+       key_data = start_data;
+       response_data = sfc_tbls_next_req_fields(key_data, key_width);
+       end_data = sfc_tbls_next_req_fields(response_data, resp_width);
+
+       key_size = RTE_PTR_DIFF(response_data, key_data);
+       response_size = RTE_PTR_DIFF(end_data, response_data);
+       data_size = RTE_PTR_DIFF(end_data, start_data);
+       SFC_ASSERT(data_size <= sizeof(data));
+
+       sfc_mae_ct_key_to_mcdi_key(key, meta->keys,
+                                  meta->descriptor.n_key_fields, key_data,
+                                  key_size);
+       sfc_mae_ct_response_to_mcdi_response(response, meta->responses,
+                                            meta->descriptor.n_resp_fields,
+                                            response_data, response_size);
+
+       rc = sfc_tbls_bcam_entry_insert(sa->nic, EFX_TABLE_ID_CONNTRACK,
+                                       key_width, resp_width, data,
+                                       data_size);
+
+       return rc;
+}
+
+int
+sfc_mae_conntrack_delete(struct sfc_adapter *sa,
+                        const sfc_mae_conntrack_key_t *key)
+{
+       const struct sfc_tbls *tables = &sa->hw_tables;
+       uint8_t data[EFX_TABLE_ENTRY_LENGTH_MAX] = {0};
+       const struct sfc_tbl_meta *meta = NULL;
+       unsigned int data_size;
+       uint32_t *start_data;
+       uint16_t key_width;
+       uint32_t *key_data;
+       uint32_t *end_data;
+       int rc = 0;
+
+       if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
+               return -ENOTSUP;
+
+       if (!sfc_mae_conntrack_is_supported(sa))
+               return -ENOTSUP;
+
+       meta = sfc_mae_conntrack_meta_lookup(sa);
+       if (meta == NULL)
+               return -ENOENT;
+
+       key_width = meta->descriptor.key_width;
+
+       start_data = (uint32_t *)data;
+       key_data = start_data;
+       end_data = sfc_tbls_next_req_fields(key_data, key_width);
+
+       data_size = RTE_PTR_DIFF(end_data, start_data);
+       SFC_ASSERT(data_size <= sizeof(data));
+
+       sfc_mae_ct_key_to_mcdi_key(key, meta->keys,
+                                  meta->descriptor.n_key_fields,
+                                  key_data, data_size);
+
+       rc = sfc_tbls_bcam_entry_delete(sa->nic, EFX_TABLE_ID_CONNTRACK,
+                                       key_width, data, data_size);
+
+       return rc;
+}
diff --git a/drivers/net/sfc/sfc_mae_ct.h b/drivers/net/sfc/sfc_mae_ct.h
new file mode 100644
index 0000000000..b5a3181cd3
--- /dev/null
+++ b/drivers/net/sfc/sfc_mae_ct.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _SFC_MAE_CONNTRACK_H
+#define _SFC_MAE_CONNTRACK_H
+
+#include <stdbool.h>
+
+#include <rte_ip.h>
+
+#include "efx.h"
+
+#include "sfc_tbls.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct sfc_mae_conntrack_key_s {
+       uint8_t         ip_proto;
+       uint16_t        ether_type_le;
+
+       uint16_t        src_port_le;
+       uint16_t        dst_port_le;
+
+       uint8_t         src_addr_le[RTE_SIZEOF_FIELD(struct rte_ipv6_hdr, 
src_addr)];
+       uint8_t         dst_addr_le[RTE_SIZEOF_FIELD(struct rte_ipv6_hdr, 
dst_addr)];
+} sfc_mae_conntrack_key_t;
+
+typedef struct sfc_mae_conntrack_nat_s {
+       uint32_t        ip_le;
+       uint16_t        port_le;
+       bool            dir_is_dst;
+} sfc_mae_conntrack_nat_t;
+
+typedef struct sfc_mae_conntrack_response_s {
+       uint32_t                ct_mark;
+       sfc_mae_conntrack_nat_t nat;
+       uint32_t                counter_id;
+} sfc_mae_conntrack_response_t;
+
+struct sfc_adapter;
+
+static inline bool
+sfc_mae_conntrack_is_supported(struct sfc_adapter *sa)
+{
+       return sfc_tbls_id_is_supported(sa, EFX_TABLE_ID_CONNTRACK);
+}
+
+static inline const struct sfc_tbl_meta *
+sfc_mae_conntrack_meta_lookup(struct sfc_adapter *sa)
+{
+       return sfc_tbl_meta_lookup(sa, EFX_TABLE_ID_CONNTRACK);
+}
+
+int sfc_mae_conntrack_insert(struct sfc_adapter *sa,
+                            const sfc_mae_conntrack_key_t *key,
+                            const sfc_mae_conntrack_response_t *response);
+
+int sfc_mae_conntrack_delete(struct sfc_adapter *sa,
+                            const sfc_mae_conntrack_key_t *key);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _SFC_MAE_CONNTRACK_H */
-- 
2.30.2

Reply via email to