1*c0db99c5SDenis Pryazhennikov /* SPDX-License-Identifier: BSD-3-Clause
2*c0db99c5SDenis Pryazhennikov *
3*c0db99c5SDenis Pryazhennikov * Copyright (c) 2023 Advanced Micro Devices, Inc.
4*c0db99c5SDenis Pryazhennikov */
5*c0db99c5SDenis Pryazhennikov
6*c0db99c5SDenis Pryazhennikov #include "sfc.h"
7*c0db99c5SDenis Pryazhennikov #include "sfc_mae_ct.h"
8*c0db99c5SDenis Pryazhennikov
9*c0db99c5SDenis Pryazhennikov /* SF-123102-TC-1A § 10.6.3: Conntrack_Table key */
10*c0db99c5SDenis Pryazhennikov 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)11*c0db99c5SDenis Pryazhennikov sfc_mae_ct_key_to_mcdi_key(const sfc_mae_conntrack_key_t *key,
12*c0db99c5SDenis Pryazhennikov const efx_table_field_descriptor_t *fields,
13*c0db99c5SDenis Pryazhennikov unsigned int n_fields, uint32_t *mcdi_key,
14*c0db99c5SDenis Pryazhennikov unsigned int key_size)
15*c0db99c5SDenis Pryazhennikov {
16*c0db99c5SDenis Pryazhennikov unsigned int i;
17*c0db99c5SDenis Pryazhennikov
18*c0db99c5SDenis Pryazhennikov for (i = 0; i < n_fields; i++) {
19*c0db99c5SDenis Pryazhennikov const efx_table_field_descriptor_t *desc = &fields[i];
20*c0db99c5SDenis Pryazhennikov
21*c0db99c5SDenis Pryazhennikov if (desc->mask_type == EFX_TABLE_FIELD_MASK_NEVER)
22*c0db99c5SDenis Pryazhennikov continue;
23*c0db99c5SDenis Pryazhennikov
24*c0db99c5SDenis Pryazhennikov switch (desc->field_id) {
25*c0db99c5SDenis Pryazhennikov case EFX_TABLE_FIELD_ID_IP_PROTO:
26*c0db99c5SDenis Pryazhennikov sfc_tbls_field_set_u8(mcdi_key, key_size, desc->lbn,
27*c0db99c5SDenis Pryazhennikov desc->width, key->ip_proto);
28*c0db99c5SDenis Pryazhennikov break;
29*c0db99c5SDenis Pryazhennikov case EFX_TABLE_FIELD_ID_ETHER_TYPE:
30*c0db99c5SDenis Pryazhennikov sfc_tbls_field_set_u16(mcdi_key, key_size, desc->lbn,
31*c0db99c5SDenis Pryazhennikov desc->width, key->ether_type_le);
32*c0db99c5SDenis Pryazhennikov break;
33*c0db99c5SDenis Pryazhennikov case EFX_TABLE_FIELD_ID_SRC_PORT:
34*c0db99c5SDenis Pryazhennikov sfc_tbls_field_set_u16(mcdi_key, key_size, desc->lbn,
35*c0db99c5SDenis Pryazhennikov desc->width, key->src_port_le);
36*c0db99c5SDenis Pryazhennikov break;
37*c0db99c5SDenis Pryazhennikov case EFX_TABLE_FIELD_ID_DST_PORT:
38*c0db99c5SDenis Pryazhennikov sfc_tbls_field_set_u16(mcdi_key, key_size, desc->lbn,
39*c0db99c5SDenis Pryazhennikov desc->width, key->dst_port_le);
40*c0db99c5SDenis Pryazhennikov break;
41*c0db99c5SDenis Pryazhennikov case EFX_TABLE_FIELD_ID_SRC_IP:
42*c0db99c5SDenis Pryazhennikov sfc_tbls_field_set_ip(mcdi_key, key_size, desc->lbn,
43*c0db99c5SDenis Pryazhennikov desc->width,
44*c0db99c5SDenis Pryazhennikov (const uint32_t *)key->src_addr_le);
45*c0db99c5SDenis Pryazhennikov break;
46*c0db99c5SDenis Pryazhennikov case EFX_TABLE_FIELD_ID_DST_IP:
47*c0db99c5SDenis Pryazhennikov sfc_tbls_field_set_ip(mcdi_key, key_size, desc->lbn,
48*c0db99c5SDenis Pryazhennikov desc->width,
49*c0db99c5SDenis Pryazhennikov (const uint32_t *)key->dst_addr_le);
50*c0db99c5SDenis Pryazhennikov break;
51*c0db99c5SDenis Pryazhennikov
52*c0db99c5SDenis Pryazhennikov default:
53*c0db99c5SDenis Pryazhennikov break;
54*c0db99c5SDenis Pryazhennikov }
55*c0db99c5SDenis Pryazhennikov }
56*c0db99c5SDenis Pryazhennikov }
57*c0db99c5SDenis Pryazhennikov
58*c0db99c5SDenis Pryazhennikov /* SF-123102-TC-1A § 10.6.4: Conntrack_Table response */
59*c0db99c5SDenis Pryazhennikov 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)60*c0db99c5SDenis Pryazhennikov sfc_mae_ct_response_to_mcdi_response(const sfc_mae_conntrack_response_t *response,
61*c0db99c5SDenis Pryazhennikov const efx_table_field_descriptor_t *fields,
62*c0db99c5SDenis Pryazhennikov unsigned int n_fields, uint32_t *mcdi_resp,
63*c0db99c5SDenis Pryazhennikov unsigned int resp_size)
64*c0db99c5SDenis Pryazhennikov {
65*c0db99c5SDenis Pryazhennikov unsigned int i;
66*c0db99c5SDenis Pryazhennikov
67*c0db99c5SDenis Pryazhennikov for (i = 0; i < n_fields; i++) {
68*c0db99c5SDenis Pryazhennikov const efx_table_field_descriptor_t *desc = &fields[i];
69*c0db99c5SDenis Pryazhennikov
70*c0db99c5SDenis Pryazhennikov if (desc->mask_type == EFX_TABLE_FIELD_MASK_NEVER)
71*c0db99c5SDenis Pryazhennikov continue;
72*c0db99c5SDenis Pryazhennikov
73*c0db99c5SDenis Pryazhennikov /* Fields of responses are always reported with the EXACT type. */
74*c0db99c5SDenis Pryazhennikov SFC_ASSERT(desc->mask_type == EFX_TABLE_FIELD_MASK_EXACT);
75*c0db99c5SDenis Pryazhennikov
76*c0db99c5SDenis Pryazhennikov switch (desc->field_id) {
77*c0db99c5SDenis Pryazhennikov case EFX_TABLE_FIELD_ID_CT_MARK:
78*c0db99c5SDenis Pryazhennikov sfc_tbls_field_set_u32(mcdi_resp, resp_size, desc->lbn,
79*c0db99c5SDenis Pryazhennikov desc->width, response->ct_mark);
80*c0db99c5SDenis Pryazhennikov break;
81*c0db99c5SDenis Pryazhennikov case EFX_TABLE_FIELD_ID_COUNTER_ID:
82*c0db99c5SDenis Pryazhennikov sfc_tbls_field_set_u32(mcdi_resp, resp_size, desc->lbn,
83*c0db99c5SDenis Pryazhennikov desc->width, response->counter_id);
84*c0db99c5SDenis Pryazhennikov break;
85*c0db99c5SDenis Pryazhennikov case EFX_TABLE_FIELD_ID_NAT_DIR:
86*c0db99c5SDenis Pryazhennikov sfc_tbls_field_set_u8(mcdi_resp, resp_size, desc->lbn,
87*c0db99c5SDenis Pryazhennikov desc->width, response->nat.dir_is_dst);
88*c0db99c5SDenis Pryazhennikov break;
89*c0db99c5SDenis Pryazhennikov case EFX_TABLE_FIELD_ID_NAT_IP:
90*c0db99c5SDenis Pryazhennikov sfc_tbls_field_set_u32(mcdi_resp, resp_size, desc->lbn,
91*c0db99c5SDenis Pryazhennikov desc->width, response->nat.ip_le);
92*c0db99c5SDenis Pryazhennikov break;
93*c0db99c5SDenis Pryazhennikov case EFX_TABLE_FIELD_ID_NAT_PORT:
94*c0db99c5SDenis Pryazhennikov sfc_tbls_field_set_u16(mcdi_resp, resp_size, desc->lbn,
95*c0db99c5SDenis Pryazhennikov desc->width, response->nat.port_le);
96*c0db99c5SDenis Pryazhennikov break;
97*c0db99c5SDenis Pryazhennikov
98*c0db99c5SDenis Pryazhennikov default:
99*c0db99c5SDenis Pryazhennikov break;
100*c0db99c5SDenis Pryazhennikov }
101*c0db99c5SDenis Pryazhennikov }
102*c0db99c5SDenis Pryazhennikov }
103*c0db99c5SDenis Pryazhennikov
104*c0db99c5SDenis Pryazhennikov int
sfc_mae_conntrack_insert(struct sfc_adapter * sa,const sfc_mae_conntrack_key_t * key,const sfc_mae_conntrack_response_t * response)105*c0db99c5SDenis Pryazhennikov sfc_mae_conntrack_insert(struct sfc_adapter *sa,
106*c0db99c5SDenis Pryazhennikov const sfc_mae_conntrack_key_t *key,
107*c0db99c5SDenis Pryazhennikov const sfc_mae_conntrack_response_t *response)
108*c0db99c5SDenis Pryazhennikov {
109*c0db99c5SDenis Pryazhennikov const struct sfc_tbls *tables = &sa->hw_tables;
110*c0db99c5SDenis Pryazhennikov uint8_t data[EFX_TABLE_ENTRY_LENGTH_MAX] = {0};
111*c0db99c5SDenis Pryazhennikov const struct sfc_tbl_meta *meta = NULL;
112*c0db99c5SDenis Pryazhennikov unsigned int response_size;
113*c0db99c5SDenis Pryazhennikov uint32_t *response_data;
114*c0db99c5SDenis Pryazhennikov unsigned int data_size;
115*c0db99c5SDenis Pryazhennikov unsigned int key_size;
116*c0db99c5SDenis Pryazhennikov uint32_t *start_data;
117*c0db99c5SDenis Pryazhennikov uint16_t resp_width;
118*c0db99c5SDenis Pryazhennikov uint16_t key_width;
119*c0db99c5SDenis Pryazhennikov uint32_t *key_data;
120*c0db99c5SDenis Pryazhennikov uint32_t *end_data;
121*c0db99c5SDenis Pryazhennikov int rc = 0;
122*c0db99c5SDenis Pryazhennikov
123*c0db99c5SDenis Pryazhennikov if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
124*c0db99c5SDenis Pryazhennikov return -ENOTSUP;
125*c0db99c5SDenis Pryazhennikov
126*c0db99c5SDenis Pryazhennikov if (!sfc_mae_conntrack_is_supported(sa))
127*c0db99c5SDenis Pryazhennikov return -ENOTSUP;
128*c0db99c5SDenis Pryazhennikov
129*c0db99c5SDenis Pryazhennikov meta = sfc_mae_conntrack_meta_lookup(sa);
130*c0db99c5SDenis Pryazhennikov if (meta == NULL)
131*c0db99c5SDenis Pryazhennikov return -ENOENT;
132*c0db99c5SDenis Pryazhennikov
133*c0db99c5SDenis Pryazhennikov key_width = meta->descriptor.key_width;
134*c0db99c5SDenis Pryazhennikov resp_width = meta->descriptor.resp_width;
135*c0db99c5SDenis Pryazhennikov
136*c0db99c5SDenis Pryazhennikov start_data = (uint32_t *)data;
137*c0db99c5SDenis Pryazhennikov key_data = start_data;
138*c0db99c5SDenis Pryazhennikov response_data = sfc_tbls_next_req_fields(key_data, key_width);
139*c0db99c5SDenis Pryazhennikov end_data = sfc_tbls_next_req_fields(response_data, resp_width);
140*c0db99c5SDenis Pryazhennikov
141*c0db99c5SDenis Pryazhennikov key_size = RTE_PTR_DIFF(response_data, key_data);
142*c0db99c5SDenis Pryazhennikov response_size = RTE_PTR_DIFF(end_data, response_data);
143*c0db99c5SDenis Pryazhennikov data_size = RTE_PTR_DIFF(end_data, start_data);
144*c0db99c5SDenis Pryazhennikov SFC_ASSERT(data_size <= sizeof(data));
145*c0db99c5SDenis Pryazhennikov
146*c0db99c5SDenis Pryazhennikov sfc_mae_ct_key_to_mcdi_key(key, meta->keys,
147*c0db99c5SDenis Pryazhennikov meta->descriptor.n_key_fields, key_data,
148*c0db99c5SDenis Pryazhennikov key_size);
149*c0db99c5SDenis Pryazhennikov sfc_mae_ct_response_to_mcdi_response(response, meta->responses,
150*c0db99c5SDenis Pryazhennikov meta->descriptor.n_resp_fields,
151*c0db99c5SDenis Pryazhennikov response_data, response_size);
152*c0db99c5SDenis Pryazhennikov
153*c0db99c5SDenis Pryazhennikov rc = sfc_tbls_bcam_entry_insert(sa->nic, EFX_TABLE_ID_CONNTRACK,
154*c0db99c5SDenis Pryazhennikov key_width, resp_width, data,
155*c0db99c5SDenis Pryazhennikov data_size);
156*c0db99c5SDenis Pryazhennikov
157*c0db99c5SDenis Pryazhennikov return rc;
158*c0db99c5SDenis Pryazhennikov }
159*c0db99c5SDenis Pryazhennikov
160*c0db99c5SDenis Pryazhennikov int
sfc_mae_conntrack_delete(struct sfc_adapter * sa,const sfc_mae_conntrack_key_t * key)161*c0db99c5SDenis Pryazhennikov sfc_mae_conntrack_delete(struct sfc_adapter *sa,
162*c0db99c5SDenis Pryazhennikov const sfc_mae_conntrack_key_t *key)
163*c0db99c5SDenis Pryazhennikov {
164*c0db99c5SDenis Pryazhennikov const struct sfc_tbls *tables = &sa->hw_tables;
165*c0db99c5SDenis Pryazhennikov uint8_t data[EFX_TABLE_ENTRY_LENGTH_MAX] = {0};
166*c0db99c5SDenis Pryazhennikov const struct sfc_tbl_meta *meta = NULL;
167*c0db99c5SDenis Pryazhennikov unsigned int data_size;
168*c0db99c5SDenis Pryazhennikov uint32_t *start_data;
169*c0db99c5SDenis Pryazhennikov uint16_t key_width;
170*c0db99c5SDenis Pryazhennikov uint32_t *key_data;
171*c0db99c5SDenis Pryazhennikov uint32_t *end_data;
172*c0db99c5SDenis Pryazhennikov int rc = 0;
173*c0db99c5SDenis Pryazhennikov
174*c0db99c5SDenis Pryazhennikov if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
175*c0db99c5SDenis Pryazhennikov return -ENOTSUP;
176*c0db99c5SDenis Pryazhennikov
177*c0db99c5SDenis Pryazhennikov if (!sfc_mae_conntrack_is_supported(sa))
178*c0db99c5SDenis Pryazhennikov return -ENOTSUP;
179*c0db99c5SDenis Pryazhennikov
180*c0db99c5SDenis Pryazhennikov meta = sfc_mae_conntrack_meta_lookup(sa);
181*c0db99c5SDenis Pryazhennikov if (meta == NULL)
182*c0db99c5SDenis Pryazhennikov return -ENOENT;
183*c0db99c5SDenis Pryazhennikov
184*c0db99c5SDenis Pryazhennikov key_width = meta->descriptor.key_width;
185*c0db99c5SDenis Pryazhennikov
186*c0db99c5SDenis Pryazhennikov start_data = (uint32_t *)data;
187*c0db99c5SDenis Pryazhennikov key_data = start_data;
188*c0db99c5SDenis Pryazhennikov end_data = sfc_tbls_next_req_fields(key_data, key_width);
189*c0db99c5SDenis Pryazhennikov
190*c0db99c5SDenis Pryazhennikov data_size = RTE_PTR_DIFF(end_data, start_data);
191*c0db99c5SDenis Pryazhennikov SFC_ASSERT(data_size <= sizeof(data));
192*c0db99c5SDenis Pryazhennikov
193*c0db99c5SDenis Pryazhennikov sfc_mae_ct_key_to_mcdi_key(key, meta->keys,
194*c0db99c5SDenis Pryazhennikov meta->descriptor.n_key_fields,
195*c0db99c5SDenis Pryazhennikov key_data, data_size);
196*c0db99c5SDenis Pryazhennikov
197*c0db99c5SDenis Pryazhennikov rc = sfc_tbls_bcam_entry_delete(sa->nic, EFX_TABLE_ID_CONNTRACK,
198*c0db99c5SDenis Pryazhennikov key_width, data, data_size);
199*c0db99c5SDenis Pryazhennikov
200*c0db99c5SDenis Pryazhennikov return rc;
201*c0db99c5SDenis Pryazhennikov }
202