Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2021-2023 Broadcom
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include <inttypes.h>
7 : : #include "hcapi_cfa_defs.h"
8 : : #include "tf_util.h"
9 : : #include "cfa_tcam_mgr.h"
10 : : #include "cfa_tcam_mgr_device.h"
11 : : #include "cfa_tcam_mgr_session.h"
12 : : #include "cfa_tcam_mgr_sbmp.h"
13 : : #include "tfp.h"
14 : : #include "cfa_tcam_mgr_p58.h"
15 : : #include "cfa_tcam_mgr_p4.h"
16 : :
17 : : struct cfa_tcam_mgr_session_data {
18 : : uint32_t session_id;
19 : : /* The following are per-session values */
20 : : uint16_t max_entries[TF_DIR_MAX][CFA_TCAM_MGR_TBL_TYPE_MAX];
21 : : uint16_t used_entries[TF_DIR_MAX][CFA_TCAM_MGR_TBL_TYPE_MAX];
22 : : };
23 : :
24 : : static struct cfa_tcam_mgr_session_data session_data[TF_TCAM_MAX_SESSIONS];
25 : :
26 : : static uint16_t last_entry_id;
27 : :
28 : : static struct sbmp *session_bmp[TF_TCAM_MAX_SESSIONS];
29 : :
30 : : int
31 : 0 : cfa_tcam_mgr_session_init(int sess_idx, enum cfa_tcam_mgr_device_type type)
32 : : {
33 : : int rc;
34 : :
35 [ # # # ]: 0 : switch (type) {
36 : 0 : case CFA_TCAM_MGR_DEVICE_TYPE_P4:
37 : : case CFA_TCAM_MGR_DEVICE_TYPE_SR:
38 : 0 : rc = cfa_tcam_mgr_sess_table_get_p4(sess_idx, &session_bmp[sess_idx]);
39 : 0 : break;
40 : 0 : case CFA_TCAM_MGR_DEVICE_TYPE_P5:
41 : 0 : rc = cfa_tcam_mgr_sess_table_get_p58(sess_idx, &session_bmp[sess_idx]);
42 : 0 : break;
43 : 0 : default:
44 : 0 : CFA_TCAM_MGR_LOG(ERR, "No such device %d\n", type);
45 : : rc = -CFA_TCAM_MGR_ERR_CODE(NODEV);
46 : : }
47 : :
48 : 0 : return rc;
49 : : }
50 : :
51 : : int
52 : 0 : cfa_tcam_mgr_get_session_from_context(struct cfa_tcam_mgr_context *context,
53 : : uint32_t *session_id)
54 : : {
55 [ # # ]: 0 : if (context == NULL) {
56 : 0 : CFA_TCAM_MGR_LOG_0(ERR, "context passed as NULL pointer.\n");
57 : 0 : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
58 : : }
59 : :
60 : 0 : *session_id = context->tfp->session->session_id.id;
61 : 0 : return 0;
62 : : }
63 : :
64 : : int
65 : 0 : cfa_tcam_mgr_session_find(unsigned int session_id)
66 : : {
67 : : unsigned int sess_idx;
68 : :
69 [ # # ]: 0 : for (sess_idx = 0; sess_idx < ARRAY_SIZE(session_data); sess_idx++) {
70 [ # # ]: 0 : if (session_data[sess_idx].session_id == session_id)
71 : 0 : return sess_idx;
72 : : }
73 : :
74 : : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
75 : : }
76 : :
77 : : int
78 : 0 : cfa_tcam_mgr_session_add(unsigned int session_id)
79 : : {
80 : : int sess_idx;
81 : :
82 : 0 : sess_idx = cfa_tcam_mgr_session_find(session_id);
83 [ # # ]: 0 : if (sess_idx >= 0) {
84 : 0 : CFA_TCAM_MGR_LOG_0(ERR, "Session is already bound.\n");
85 : 0 : return -CFA_TCAM_MGR_ERR_CODE(BUSY);
86 : : }
87 : :
88 : : /* Session not found in table, find first empty entry. */
89 : : for (sess_idx = 0;
90 [ # # ]: 0 : sess_idx < (signed int)ARRAY_SIZE(session_data);
91 : 0 : sess_idx++) {
92 [ # # ]: 0 : if (session_data[sess_idx].session_id == 0)
93 : : break;
94 : : }
95 : :
96 [ # # ]: 0 : if (sess_idx >= (signed int)ARRAY_SIZE(session_data)) {
97 : : /* No room in the session table */
98 : 0 : CFA_TCAM_MGR_LOG_0(ERR, "Session table is full.\n");
99 : 0 : return -CFA_TCAM_MGR_ERR_CODE(NOMEM);
100 : : }
101 : :
102 : 0 : session_data[sess_idx].session_id = session_id;
103 : :
104 : 0 : return sess_idx;
105 : : }
106 : :
107 : : int
108 : 0 : cfa_tcam_mgr_session_free(unsigned int session_id,
109 : : struct cfa_tcam_mgr_context *context)
110 : : {
111 : : struct cfa_tcam_mgr_free_parms free_parms;
112 : : int entry_id;
113 : 0 : int sess_idx = cfa_tcam_mgr_session_find(session_id);
114 : :
115 [ # # ]: 0 : if (sess_idx < 0)
116 : : return sess_idx;
117 : :
118 : : memset(&free_parms, 0, sizeof(free_parms));
119 : : /* Since we are freeing all pending TCAM entries (which is typically
120 : : * done during tcam_unbind), we don't know the type of each entry.
121 : : * So we set the type to MAX as a hint to cfa_tcam_mgr_free() to
122 : : * figure out the actual type. We need to set it through each
123 : : * iteration in the loop below; otherwise, the type determined for
124 : : * the first entry would be used for subsequent entries that may or
125 : : * may not be of the same type, resulting in errors.
126 : : */
127 [ # # ]: 0 : for (entry_id = 0; entry_id < cfa_tcam_mgr_max_entries[sess_idx]; entry_id++) {
128 [ # # ]: 0 : if (SBMP_MEMBER(session_bmp[sess_idx][entry_id], sess_idx)) {
129 : 0 : SBMP_SESSION_REMOVE(session_bmp[sess_idx][entry_id], sess_idx);
130 : :
131 : 0 : free_parms.id = entry_id;
132 : 0 : free_parms.type = CFA_TCAM_MGR_TBL_TYPE_MAX;
133 : 0 : cfa_tcam_mgr_free(context, &free_parms);
134 : : }
135 : : }
136 : :
137 : 0 : memset(&session_data[sess_idx], 0, sizeof(session_data[sess_idx]));
138 : 0 : return 0;
139 : : }
140 : :
141 : : int
142 : 0 : cfa_tcam_mgr_session_cfg(unsigned int session_id,
143 : : uint16_t tcam_cnt[][CFA_TCAM_MGR_TBL_TYPE_MAX])
144 : : {
145 : : struct cfa_tcam_mgr_table_data *table_data;
146 : : struct cfa_tcam_mgr_session_data *session_entry;
147 : : unsigned int dir, type;
148 : 0 : int sess_idx = cfa_tcam_mgr_session_find(session_id);
149 : : uint16_t requested_cnt;
150 : :
151 [ # # ]: 0 : if (sess_idx < 0)
152 : : return sess_idx;
153 : :
154 : : session_entry = &session_data[sess_idx];
155 : :
156 : : /* Validate session request */
157 [ # # ]: 0 : for (dir = 0; dir < ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx]); dir++) {
158 : : for (type = 0;
159 [ # # ]: 0 : type < ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx][dir]);
160 : 0 : type++) {
161 : : table_data = &cfa_tcam_mgr_tables[sess_idx][dir][type];
162 : 0 : requested_cnt = tcam_cnt[dir][type];
163 : : /*
164 : : * Only check if table supported (max_entries > 0).
165 : : */
166 [ # # # # ]: 0 : if (table_data->max_entries > 0 &&
167 : : requested_cnt > table_data->max_entries) {
168 : 0 : CFA_TCAM_MGR_LOG_DIR_TYPE(ERR, dir, type,
169 : : "Requested %d, available %d.\n",
170 : : requested_cnt,
171 : : table_data->max_entries);
172 : 0 : return -CFA_TCAM_MGR_ERR_CODE(NOSPC);
173 : : }
174 : : }
175 : : }
176 : :
177 : 0 : memcpy(session_entry->max_entries, tcam_cnt,
178 : : sizeof(session_entry->max_entries));
179 : 0 : return 0;
180 : : }
181 : :
182 : : void
183 : 0 : cfa_tcam_mgr_mv_session_used_entries_cnt(int sess_idx, enum tf_dir dir,
184 : : enum cfa_tcam_mgr_tbl_type dst_type,
185 : : enum cfa_tcam_mgr_tbl_type src_type)
186 : : {
187 : 0 : session_data[sess_idx].used_entries[dir][dst_type]++;
188 : 0 : session_data[sess_idx].used_entries[dir][src_type]--;
189 : 0 : }
190 : :
191 : : int
192 : 0 : cfa_tcam_mgr_session_entry_alloc(unsigned int session_id,
193 : : enum tf_dir dir,
194 : : enum cfa_tcam_mgr_tbl_type type)
195 : : {
196 : : int sess_idx;
197 : :
198 : 0 : sess_idx = cfa_tcam_mgr_session_find(session_id);
199 [ # # ]: 0 : if (sess_idx < 0) {
200 : 0 : CFA_TCAM_MGR_LOG_0(ERR, "Session not found.\n");
201 : 0 : return -CFA_TCAM_MGR_ERR_CODE(NODEV);
202 : : }
203 : :
204 : 0 : if (session_data[sess_idx].used_entries[dir][type] >=
205 [ # # ]: 0 : session_data[sess_idx].max_entries[dir][type]) {
206 : 0 : CFA_TCAM_MGR_LOG_0(ERR, "Table full (session).\n");
207 : 0 : return -CFA_TCAM_MGR_ERR_CODE(NOSPC);
208 : : }
209 : :
210 : : do {
211 : 0 : last_entry_id++;
212 [ # # ]: 0 : if (cfa_tcam_mgr_max_entries[sess_idx] <= last_entry_id)
213 : 0 : last_entry_id = 0;
214 [ # # ]: 0 : } while (!SBMP_IS_NULL(session_bmp[sess_idx][last_entry_id]));
215 : :
216 : 0 : SBMP_SESSION_ADD(session_bmp[sess_idx][last_entry_id], sess_idx);
217 : :
218 : 0 : session_data[sess_idx].used_entries[dir][type] += 1;
219 : :
220 : 0 : return last_entry_id;
221 : : }
222 : :
223 : : int
224 : 0 : cfa_tcam_mgr_session_entry_free(unsigned int session_id,
225 : : unsigned int entry_id,
226 : : enum tf_dir dir,
227 : : enum cfa_tcam_mgr_tbl_type type)
228 : : {
229 : : int sess_idx;
230 : :
231 : 0 : sess_idx = cfa_tcam_mgr_session_find(session_id);
232 [ # # ]: 0 : if (sess_idx < 0) {
233 : 0 : CFA_TCAM_MGR_LOG_0(ERR, "Session not found.\n");
234 : 0 : return -CFA_TCAM_MGR_ERR_CODE(NODEV);
235 : : }
236 : :
237 : 0 : SBMP_SESSION_REMOVE(session_bmp[sess_idx][entry_id], sess_idx);
238 : 0 : session_data[sess_idx].used_entries[dir][type] -= 1;
239 : :
240 : 0 : return 0;
241 : : }
242 : :
243 : : #if SBMP_WORD_WIDTH == 16
244 : : #define SBMP_FORMAT PRIX16
245 : : #define SBMP_PRECISION "4"
246 : : #elif SBMP_WORD_WIDTH == 32
247 : : #define SBMP_FORMAT PRIX32
248 : : #define SBMP_PRECISION "8"
249 : : #elif SBMP_WORD_WIDTH == 64
250 : : #define SBMP_FORMAT PRIX64
251 : : #define SBMP_PRECISION "16"
252 : : #else
253 : : #error "Invalid value for SBMP_WORD_WIDTH."
254 : : #endif
255 : :
256 : : static void
257 : 0 : cfa_tcam_mgr_session_bitmap_print(struct sbmp *session_bmp)
258 : : {
259 : : unsigned int i;
260 : :
261 : : printf("0x");
262 : 0 : for (i = 0;
263 [ # # ]: 0 : i < ARRAY_SIZE(session_bmp->bits);
264 : : i++) {
265 : 0 : printf("%0" SBMP_PRECISION SBMP_FORMAT,
266 : 0 : session_bmp->bits[i]);
267 : : }
268 : 0 : }
269 : :
270 : : #define SESSION_DUMP_HEADER_1 " RX TX\n"
271 : : #define SESSION_DUMP_HEADER_2 \
272 : : " Max Used Max Used\n"
273 : :
274 : : static void
275 : 0 : cfa_tcam_mgr_session_printf(struct cfa_tcam_mgr_session_data *session,
276 : : enum cfa_tcam_mgr_tbl_type tbl_type)
277 : : {
278 : 0 : printf("%-22s: %5u %5u %5u %5u\n",
279 : : cfa_tcam_mgr_tbl_2_str(tbl_type),
280 : 0 : session->max_entries[TF_DIR_RX][tbl_type],
281 : 0 : session->used_entries[TF_DIR_RX][tbl_type],
282 : 0 : session->max_entries[TF_DIR_TX][tbl_type],
283 : 0 : session->used_entries[TF_DIR_TX][tbl_type]);
284 : 0 : }
285 : :
286 : : void
287 : 0 : cfa_tcam_mgr_sessions_dump(void)
288 : : {
289 : : struct cfa_tcam_mgr_session_data *session;
290 : : unsigned int sess_idx;
291 : : bool sess_found = false;
292 : : enum cfa_tcam_mgr_tbl_type tbl_type;
293 : :
294 : : printf("\nTCAM Sessions Table:\n");
295 [ # # ]: 0 : for (sess_idx = 0; sess_idx < ARRAY_SIZE(session_data); sess_idx++) {
296 [ # # ]: 0 : if (session_data[sess_idx].session_id != 0) {
297 : 0 : session = &session_data[sess_idx];
298 [ # # ]: 0 : if (!sess_found) {
299 : : printf(SESSION_DUMP_HEADER_1);
300 : : printf(SESSION_DUMP_HEADER_2);
301 : : }
302 : 0 : printf("Session 0x%08x:\n",
303 : : session->session_id);
304 : 0 : for (tbl_type = CFA_TCAM_MGR_TBL_TYPE_START;
305 [ # # ]: 0 : tbl_type < CFA_TCAM_MGR_TBL_TYPE_MAX;
306 : 0 : tbl_type++) {
307 : 0 : cfa_tcam_mgr_session_printf(session, tbl_type);
308 : : }
309 : : sess_found = true;
310 : : }
311 : : }
312 : :
313 [ # # ]: 0 : if (!sess_found)
314 : : printf("No sessions found.\n");
315 : 0 : }
316 : :
317 : : /* This dumps all the sessions using an entry */
318 : : void
319 : 0 : cfa_tcam_mgr_entry_sessions_dump(int sess_idx, uint16_t id)
320 : : {
321 : : bool session_found = false;
322 : :
323 [ # # ]: 0 : if (id >= cfa_tcam_mgr_max_entries[sess_idx]) {
324 : 0 : printf("Entry ID %u out of range for sess_idx %d. Max ID %u.\n",
325 : : id, sess_idx, cfa_tcam_mgr_max_entries[sess_idx] - 1);
326 : 0 : return;
327 : : }
328 : :
329 [ # # ]: 0 : if (!SBMP_IS_NULL(session_bmp[sess_idx][id])) {
330 : : printf("Sessions using entry ID %u:\n", id);
331 [ # # ]: 0 : for (sess_idx = 0; sess_idx < SBMP_SESSION_MAX; sess_idx++)
332 [ # # ]: 0 : if (SBMP_MEMBER(session_bmp[sess_idx][id], (sess_idx))) {
333 [ # # ]: 0 : if (session_data[sess_idx].session_id != 0) {
334 : : printf("0x%08x (index %d)\n",
335 : : session_data[sess_idx].session_id,
336 : : sess_idx);
337 : : session_found = true;
338 : : } else {
339 : : printf("Error! Entry ID %u used by "
340 : : "session index %d which is not "
341 : : "in use.\n",
342 : : id, sess_idx);
343 : : }
344 : : }
345 [ # # ]: 0 : if (!session_found)
346 : : printf("No sessions using entry ID %u.\n", id);
347 : : } else {
348 : : printf("Entry ID %u not in use.\n",
349 : : id);
350 : 0 : return;
351 : : }
352 : : }
353 : :
354 : : /* This dumps all the entries in use by any session */
355 : : void
356 : 0 : cfa_tcam_mgr_session_entries_dump(int sess_idx)
357 : : {
358 : : bool entry_found = false;
359 : : uint16_t id;
360 : :
361 : 0 : printf("\nGlobal Maximum Entries for sess_idx %d: %d\n\n",
362 : : sess_idx, cfa_tcam_mgr_max_entries[sess_idx]);
363 : : printf("TCAM Session Entry Table:\n");
364 [ # # ]: 0 : for (id = 0; id < cfa_tcam_mgr_max_entries[sess_idx]; id++) {
365 [ # # ]: 0 : if (!SBMP_IS_NULL(session_bmp[sess_idx][id])) {
366 [ # # ]: 0 : if (!entry_found)
367 : : printf(" EID Session bitmap\n");
368 : : printf("%5u ", id);
369 : 0 : cfa_tcam_mgr_session_bitmap_print(&session_bmp[sess_idx][id]);
370 : : printf("\n");
371 : : entry_found = true;
372 : : }
373 : : }
374 : :
375 [ # # ]: 0 : if (!entry_found)
376 : : printf("No entries found.\n");
377 : 0 : }
|