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