Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2014-2023 Broadcom
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include <math.h>
7 : : #include <sys/queue.h>
8 : :
9 : : #include <rte_log.h>
10 : : #include <rte_malloc.h>
11 : : #include <rte_flow.h>
12 : : #include <rte_flow_driver.h>
13 : : #include <rte_tailq.h>
14 : : #include <rte_alarm.h>
15 : : #include <rte_cycles.h>
16 : : #include <rte_mtr.h>
17 : : #include <rte_mtr_driver.h>
18 : :
19 : : #include "bnxt.h"
20 : : #include "bnxt_filter.h"
21 : : #include "bnxt_hwrm.h"
22 : : #include "bnxt_ring.h"
23 : : #include "bnxt_rxq.h"
24 : : #include "bnxt_rxr.h"
25 : : #include "bnxt_vnic.h"
26 : : #include "hsi_struct_def_dpdk.h"
27 : :
28 : : #include "tfp.h"
29 : : #include "bnxt_tf_common.h"
30 : : #include "ulp_rte_parser.h"
31 : : #include "ulp_matcher.h"
32 : : #include "ulp_flow_db.h"
33 : : #include "ulp_mapper.h"
34 : : #include "ulp_fc_mgr.h"
35 : : #include "ulp_port_db.h"
36 : : #include "ulp_ha_mgr.h"
37 : : #include "ulp_tun.h"
38 : :
39 : : /**
40 : : * Meter init status
41 : : */
42 : : int bnxt_meter_initialized;
43 : :
44 : : /**
45 : : * Internal api to config global config.
46 : : * returns 0 on success.
47 : : */
48 : : static int32_t
49 : 0 : bnxt_meter_global_cfg_update(struct bnxt *bp,
50 : : enum tf_dir dir,
51 : : enum tf_global_config_type type,
52 : : uint32_t offset,
53 : : uint32_t value,
54 : : uint32_t set_flag)
55 : : {
56 : 0 : uint32_t global_cfg = 0;
57 : 0 : struct tf_global_cfg_parms parms = { 0 };
58 : : struct tf *tfp;
59 : : int32_t rc = 0;
60 : :
61 : 0 : parms.dir = dir,
62 : 0 : parms.type = type,
63 : 0 : parms.offset = offset,
64 : 0 : parms.config = (uint8_t *)&global_cfg,
65 : 0 : parms.config_sz_in_bytes = sizeof(global_cfg);
66 : :
67 : 0 : tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT);
68 : 0 : rc = tf_get_global_cfg(tfp, &parms);
69 [ # # ]: 0 : if (rc) {
70 : 0 : BNXT_TF_DBG(ERR, "Failed to get global cfg 0x%x rc:%d\n",
71 : : type, rc);
72 : 0 : return rc;
73 : : }
74 : :
75 [ # # ]: 0 : if (set_flag)
76 : 0 : global_cfg |= value;
77 : : else
78 : 0 : global_cfg &= ~value;
79 : :
80 : 0 : rc = tf_set_global_cfg(tfp, &parms);
81 [ # # ]: 0 : if (rc) {
82 : 0 : BNXT_TF_DBG(ERR, "Failed to set global cfg 0x%x rc:%d\n",
83 : : type, rc);
84 : 0 : return rc;
85 : : }
86 : : return rc;
87 : : }
88 : :
89 : : /**
90 : : * When a port is initialized by dpdk. This functions is called
91 : : * to enable the meter and initializes the meter global configurations.
92 : : */
93 : : #define BNXT_THOR_FMTCR_NUM_MET_MET_1K (0x7UL << 20)
94 : : #define BNXT_THOR_FMTCR_CNTRS_ENABLE (0x1UL << 25)
95 : : #define BNXT_THOR_FMTCR_INTERVAL_1K (1024)
96 : : int32_t
97 : 0 : bnxt_flow_meter_init(struct bnxt *bp)
98 : : {
99 : : int rc = 0;
100 : :
101 : : /*
102 : : * Enable metering. Set the meter global configuration register.
103 : : * Set number of meter to 1K. Disable the drop counter for now.
104 : : */
105 : 0 : rc = bnxt_meter_global_cfg_update(bp, TF_DIR_RX, TF_METER_CFG,
106 : : 0,
107 : : BNXT_THOR_FMTCR_NUM_MET_MET_1K,
108 : : 1);
109 [ # # ]: 0 : if (rc) {
110 : 0 : BNXT_TF_DBG(ERR, "Failed to set rx meter configuration\n");
111 : 0 : goto jump_to_error;
112 : : }
113 : :
114 : 0 : rc = bnxt_meter_global_cfg_update(bp, TF_DIR_TX, TF_METER_CFG,
115 : : 0,
116 : : BNXT_THOR_FMTCR_NUM_MET_MET_1K,
117 : : 1);
118 [ # # ]: 0 : if (rc) {
119 : 0 : BNXT_TF_DBG(ERR, "Failed to set tx meter configuration\n");
120 : 0 : goto jump_to_error;
121 : : }
122 : :
123 : : /*
124 : : * Set meter refresh rate to 1024 clock cycle. This value works for
125 : : * most bit rates especially for high rates.
126 : : */
127 : 0 : rc = bnxt_meter_global_cfg_update(bp, TF_DIR_RX, TF_METER_INTERVAL_CFG,
128 : : 0,
129 : : BNXT_THOR_FMTCR_INTERVAL_1K,
130 : : 1);
131 [ # # ]: 0 : if (rc) {
132 : 0 : BNXT_TF_DBG(ERR, "Failed to set rx meter interval\n");
133 : 0 : goto jump_to_error;
134 : : }
135 : :
136 : 0 : rc = bnxt_meter_global_cfg_update(bp, TF_DIR_TX, TF_METER_INTERVAL_CFG,
137 : : 0,
138 : : BNXT_THOR_FMTCR_INTERVAL_1K,
139 : : 1);
140 [ # # ]: 0 : if (rc) {
141 : 0 : BNXT_TF_DBG(ERR, "Failed to set tx meter interval\n");
142 : 0 : goto jump_to_error;
143 : : }
144 : :
145 : 0 : bnxt_meter_initialized = 1;
146 : 0 : BNXT_TF_DBG(DEBUG, "Bnxt flow meter has been initialized\n");
147 : 0 : return rc;
148 : :
149 : : jump_to_error:
150 : : return rc;
151 : : }
152 : :
153 : : /**
154 : : * Get meter capabilities.
155 : : */
156 : : #define MAX_FLOW_PER_METER 1024
157 : : #define MAX_METER_RATE_100GBPS ((1ULL << 30) * 100 / 8)
158 : : static int
159 : 0 : bnxt_flow_mtr_cap_get(struct rte_eth_dev *dev,
160 : : struct rte_mtr_capabilities *cap,
161 : : struct rte_mtr_error *error)
162 : : {
163 : 0 : struct bnxt *bp = dev->data->dev_private;
164 : 0 : uint32_t ulp_dev_id = BNXT_ULP_DEVICE_ID_LAST;
165 : : struct tf_get_session_info_parms iparms;
166 : : struct tf *tfp;
167 : : int32_t rc = 0;
168 : :
169 [ # # ]: 0 : if (!bnxt_meter_initialized)
170 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
171 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
172 : : NULL,
173 : : "Bnxt meter is not initialized");
174 : :
175 : 0 : rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &ulp_dev_id);
176 [ # # ]: 0 : if (rc)
177 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
178 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
179 : : NULL,
180 : : "Unable to get device id from ulp");
181 : :
182 : : /* Get number of meter reserved for this session */
183 : : memset(&iparms, 0, sizeof(iparms));
184 : 0 : tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT);
185 : 0 : rc = tf_get_session_info(tfp, &iparms);
186 [ # # ]: 0 : if (rc != 0)
187 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
188 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
189 : : NULL,
190 : : "Failed to get session resource info");
191 : :
192 : : memset(cap, 0, sizeof(struct rte_mtr_capabilities));
193 : :
194 : 0 : cap->n_max = iparms.session_info.tbl[TF_DIR_RX].info[TF_TBL_TYPE_METER_INST].stride;
195 [ # # ]: 0 : if (!cap->n_max)
196 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
197 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
198 : : "Meter is not supported");
199 : :
200 : 0 : cap->srtcm_rfc2697_byte_mode_supported = 1;
201 : 0 : cap->n_shared_max = cap->n_max;
202 : : /* No meter is identical */
203 : 0 : cap->identical = 1;
204 : 0 : cap->shared_identical = 1;
205 : 0 : cap->shared_n_flows_per_mtr_max = MAX_FLOW_PER_METER;
206 : 0 : cap->chaining_n_mtrs_per_flow_max = 1; /* Chaining is not supported. */
207 : 0 : cap->meter_srtcm_rfc2697_n_max = cap->n_max;
208 : 0 : cap->meter_rate_max = MAX_METER_RATE_100GBPS;
209 : : /* No stats supported now */
210 : : cap->stats_mask = 0;
211 : :
212 : 0 : return 0;
213 : : }
214 : :
215 : : /**
216 : : * Calculate mantissa and exponent for cir / eir reg.
217 : : */
218 : : #define BNXT_CPU_CLOCK 800
219 : : #define MEGA 1000000
220 : : #define NUM_BIT_PER_BYTE 8
221 : : static inline void
222 : 0 : bnxt_ulp_flow_meter_xir_calc(int64_t xir, uint32_t *reg)
223 : : {
224 : : int64_t temp;
225 : : uint16_t m = 0;
226 : : uint16_t e = 0;
227 : : uint8_t *swap = 0;
228 : :
229 : : /* Special case xir == 0 ? both exp and matissa are 0. */
230 [ # # ]: 0 : if (xir == 0) {
231 : 0 : *reg = 0;
232 : 0 : return;
233 : : }
234 : :
235 : : /*
236 : : * e = floor(log2(cir)) + 27
237 : : * a (MBps) = xir (bps) / MEGA
238 : : * b (MBpc) = a (MBps) / CPU_CLOCK (Mcps)
239 : : * e = floor(log2(b)) + 27
240 : : */
241 : 0 : temp = xir * (1 << 24) / (BNXT_CPU_CLOCK >> 3) / MEGA;
242 : 0 : e = log2(temp);
243 : :
244 : : /*
245 : : * m = round(b/2^(e-27) - 1) * 2048
246 : : * = round(b*2^(27-e) - 1) * 2^11
247 : : * = round(b*2^(38-e) - 2^11)
248 : : *
249 : : */
250 : 0 : m = xir * (1 << (38 - e)) / BNXT_CPU_CLOCK / MEGA - (1 << 11);
251 : 0 : *reg = ((m & 0x7FF) << 6) | (e & 0x3F);
252 : : swap = (uint8_t *)reg;
253 : 0 : *reg = swap[0] << 16 | swap[1] << 8 | swap[2];
254 : : }
255 : :
256 : : /**
257 : : * Calculate mantissa and exponent for cbs / ebs reg.
258 : : */
259 : : static inline void
260 : 0 : bnxt_ulp_flow_meter_xbs_calc(int64_t xbs, uint16_t *reg)
261 : : {
262 : : uint16_t m = 0;
263 : : uint16_t e = 0;
264 : :
265 [ # # ]: 0 : if (xbs == 0) {
266 : 0 : *reg = 0;
267 : 0 : return;
268 : : }
269 : :
270 : : /*
271 : : * e = floor(log2(xbs)) + 1
272 : : */
273 : 0 : e = log2(xbs) + 1;
274 : :
275 : : /*
276 : : * m = round(xbs/2^(e-1) - 1) * 128
277 : : * = round(xbs*2^(1-e) - 1) * 2^7
278 : : * = round(xbs*2^(8-e) - 2^7)
279 : : *
280 : : */
281 : 0 : m = xbs / (1 << (e - 8)) - (1 << 7);
282 : 0 : *reg = ((m & 0x7F) << 5) | (e & 0x1F);
283 [ # # ]: 0 : *reg = rte_cpu_to_be_16(*reg);
284 : : }
285 : :
286 : : /**
287 : : * Parse the meter profile.
288 : : */
289 : : static inline int
290 : 0 : bnxt_ulp_meter_profile_parse(struct ulp_rte_act_prop *act_prop,
291 : : const struct rte_mtr_meter_profile *profile,
292 : : struct rte_mtr_error *error)
293 : : {
294 : : uint64_t cir, cbs, eir, ebs;
295 : : uint32_t cir_reg, eir_reg;
296 : : uint16_t cbs_reg, ebs_reg;
297 : 0 : bool alg_rfc2698 = false;
298 : 0 : bool pm = false;
299 : :
300 : : /* Profile must not be NULL. */
301 [ # # ]: 0 : if (profile == NULL)
302 : 0 : return -rte_mtr_error_set(error, EINVAL,
303 : : RTE_MTR_ERROR_TYPE_METER_PROFILE,
304 : : NULL, "Meter profile is null.");
305 : :
306 [ # # ]: 0 : if (profile->packet_mode)
307 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
308 : : RTE_MTR_ERROR_TYPE_METER_PROFILE,
309 : : NULL,
310 : : "Metering packet_mode is not supported");
311 : :
312 [ # # # # ]: 0 : switch (profile->alg) {
313 : 0 : case RTE_MTR_SRTCM_RFC2697:
314 : 0 : cir = profile->srtcm_rfc2697.cir;
315 : 0 : cbs = profile->srtcm_rfc2697.cbs;
316 : : eir = 0;
317 : 0 : ebs = profile->srtcm_rfc2697.ebs;
318 : 0 : break;
319 : 0 : case RTE_MTR_TRTCM_RFC2698:
320 : 0 : cir = profile->trtcm_rfc2698.cir;
321 : 0 : cbs = profile->trtcm_rfc2698.cbs;
322 : 0 : eir = profile->trtcm_rfc2698.pir;
323 : 0 : ebs = profile->trtcm_rfc2698.pbs;
324 : 0 : alg_rfc2698 = true;
325 : 0 : break;
326 : 0 : case RTE_MTR_TRTCM_RFC4115:
327 : 0 : cir = profile->trtcm_rfc4115.cir;
328 : 0 : cbs = profile->trtcm_rfc4115.cbs;
329 : 0 : eir = profile->trtcm_rfc4115.eir;
330 : 0 : ebs = profile->trtcm_rfc4115.ebs;
331 : 0 : alg_rfc2698 = true;
332 : 0 : break;
333 : : default:
334 : 0 : return -rte_mtr_error_set(error, EINVAL,
335 : : RTE_MTR_ERROR_TYPE_METER_PROFILE,
336 : : NULL,
337 : : "Metering algorithm type is invalid");
338 : : }
339 : :
340 : : /* The CBS and EBS must be configured so that at least one
341 : : * of them is larger than 0. It is recommended that when
342 : : * the value of the CBS or the EBS is larger than 0, it
343 : : * is larger than or equal to the size of the largest possible
344 : : * IP packet in the stream.
345 : : */
346 [ # # ]: 0 : if (cbs == 0 && ebs == 0)
347 : 0 : return -rte_mtr_error_set(error, EINVAL,
348 : : RTE_MTR_ERROR_TYPE_METER_PROFILE,
349 : : NULL,
350 : : "CBS & EBS cannot both be 0. One of"
351 : : " them should be larger than the MTU");
352 : :
353 [ # # ]: 0 : if (alg_rfc2698 && eir < cir)
354 : 0 : return -rte_mtr_error_set(error, EINVAL,
355 : : RTE_MTR_ERROR_TYPE_METER_PROFILE,
356 : : NULL,
357 : : "PIR must be equal to or greater than CIR");
358 : :
359 : 0 : bnxt_ulp_flow_meter_xir_calc(cir, &cir_reg);
360 : 0 : memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_PROF_CIR],
361 : : &cir_reg,
362 : : BNXT_ULP_ACT_PROP_SZ_METER_PROF_CIR);
363 : :
364 : 0 : bnxt_ulp_flow_meter_xir_calc(eir, &eir_reg);
365 : 0 : memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_PROF_EIR],
366 : : &eir_reg,
367 : : BNXT_ULP_ACT_PROP_SZ_METER_PROF_EIR);
368 : :
369 : 0 : bnxt_ulp_flow_meter_xbs_calc(cbs, &cbs_reg);
370 : 0 : memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_PROF_CBS],
371 : : &cbs_reg,
372 : : BNXT_ULP_ACT_PROP_SZ_METER_PROF_CBS);
373 : :
374 : 0 : bnxt_ulp_flow_meter_xbs_calc(ebs, &ebs_reg);
375 : 0 : memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_PROF_EBS],
376 : : &ebs_reg,
377 : : BNXT_ULP_ACT_PROP_SZ_METER_PROF_EBS);
378 : :
379 : 0 : memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_PROF_RFC2698],
380 : : &alg_rfc2698,
381 : : BNXT_ULP_ACT_PROP_SZ_METER_PROF_RFC2698);
382 : :
383 : 0 : memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_PROF_PM],
384 : : &pm,
385 : : BNXT_ULP_ACT_PROP_SZ_METER_PROF_PM);
386 : :
387 : 0 : return 0;
388 : : }
389 : :
390 : : /**
391 : : * Add MTR profile.
392 : : */
393 : : static int
394 : 0 : bnxt_flow_meter_profile_add(struct rte_eth_dev *dev,
395 : : uint32_t meter_profile_id,
396 : : struct rte_mtr_meter_profile *profile,
397 : : struct rte_mtr_error *error)
398 : : {
399 : : struct bnxt_ulp_context *ulp_ctx;
400 : : struct ulp_rte_parser_params params;
401 : : struct ulp_rte_act_prop *act_prop = ¶ms.act_prop;
402 : 0 : struct bnxt_ulp_mapper_create_parms mparms = { 0 };
403 : : uint32_t act_tid;
404 : : uint16_t func_id;
405 : : int ret;
406 : : uint32_t tmp_profile_id;
407 : :
408 [ # # ]: 0 : if (!bnxt_meter_initialized)
409 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
410 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
411 : : NULL,
412 : : "Bnxt meter is not initialized");
413 : :
414 : 0 : ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev);
415 [ # # ]: 0 : if (!ulp_ctx)
416 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
417 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
418 : : NULL,
419 : : "ULP context is not initialized");
420 : :
421 : : /* Initialize the parser params */
422 : : memset(¶ms, 0, sizeof(struct ulp_rte_parser_params));
423 : 0 : params.ulp_ctx = ulp_ctx;
424 : 0 : params.act_bitmap.bits = BNXT_ULP_ACT_BIT_METER_PROFILE;
425 : : /* not direction from rte_mtr. Set ingress by default */
426 : 0 : params.dir_attr |= BNXT_ULP_FLOW_ATTR_INGRESS;
427 : :
428 [ # # ]: 0 : tmp_profile_id = tfp_cpu_to_be_32(meter_profile_id);
429 : : memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_PROF_ID],
430 : : &tmp_profile_id,
431 : : BNXT_ULP_ACT_PROP_SZ_METER_PROF_ID);
432 : :
433 : 0 : ret = bnxt_ulp_meter_profile_parse(act_prop, profile, error);
434 [ # # ]: 0 : if (ret)
435 : 0 : goto parse_error;
436 : :
437 : 0 : ret = ulp_matcher_action_match(¶ms, &act_tid);
438 [ # # ]: 0 : if (ret != BNXT_TF_RC_SUCCESS)
439 : 0 : goto act_error;
440 : :
441 : 0 : bnxt_ulp_init_mapper_params(&mparms, ¶ms,
442 : : BNXT_ULP_FDB_TYPE_REGULAR);
443 : 0 : mparms.act_tid = act_tid;
444 : :
445 : : /* Get the function id */
446 [ # # ]: 0 : if (ulp_port_db_port_func_id_get(ulp_ctx,
447 : 0 : dev->data->port_id,
448 : : &func_id)) {
449 : 0 : BNXT_TF_DBG(ERR, "conversion of port to func id failed\n");
450 : 0 : goto act_error;
451 : : }
452 : :
453 : : /* Protect flow creation */
454 [ # # ]: 0 : if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
455 : 0 : BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
456 : 0 : goto act_error;
457 : : }
458 : :
459 : 0 : ret = ulp_mapper_flow_create(params.ulp_ctx, &mparms);
460 : 0 : bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
461 : :
462 [ # # ]: 0 : if (ret)
463 : 0 : goto act_error;
464 : :
465 : : return 0;
466 : : parse_error:
467 : 0 : return ret;
468 [ # # ]: 0 : act_error:
469 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
470 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
471 : : NULL,
472 : : "Failed to add meter profile.");
473 : : }
474 : :
475 : : /**
476 : : * Delete meter profile.
477 : : */
478 : : static int
479 : 0 : bnxt_flow_meter_profile_delete(struct rte_eth_dev *dev,
480 : : uint32_t meter_profile_id,
481 : : struct rte_mtr_error *error)
482 : : {
483 : : struct bnxt_ulp_context *ulp_ctx;
484 : : struct ulp_rte_parser_params params;
485 : : struct ulp_rte_act_prop *act_prop = ¶ms.act_prop;
486 : 0 : struct bnxt_ulp_mapper_create_parms mparms = { 0 };
487 : : uint32_t act_tid;
488 : : uint16_t func_id;
489 : : int ret;
490 : : uint32_t tmp_profile_id;
491 : :
492 [ # # ]: 0 : if (!bnxt_meter_initialized)
493 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
494 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
495 : : NULL,
496 : : "Bnxt meter is not initialized");
497 : :
498 : 0 : ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev);
499 [ # # ]: 0 : if (!ulp_ctx)
500 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
501 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
502 : : NULL,
503 : : "ULP context is not initialized");
504 : :
505 : : /* Initialize the parser params */
506 : : memset(¶ms, 0, sizeof(struct ulp_rte_parser_params));
507 : 0 : params.ulp_ctx = ulp_ctx;
508 : : params.act_bitmap.bits = BNXT_ULP_ACT_BIT_METER_PROFILE;
509 : 0 : params.act_bitmap.bits |= BNXT_ULP_ACT_BIT_DELETE;
510 : : /* not direction from rte_mtr. Set ingress by default */
511 : 0 : params.dir_attr |= BNXT_ULP_FLOW_ATTR_INGRESS;
512 : :
513 [ # # ]: 0 : tmp_profile_id = tfp_cpu_to_be_32(meter_profile_id);
514 : : memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_PROF_ID],
515 : : &tmp_profile_id,
516 : : BNXT_ULP_ACT_PROP_SZ_METER_PROF_ID);
517 : :
518 : 0 : ret = ulp_matcher_action_match(¶ms, &act_tid);
519 [ # # ]: 0 : if (ret != BNXT_TF_RC_SUCCESS)
520 : 0 : goto parse_error;
521 : :
522 : 0 : bnxt_ulp_init_mapper_params(&mparms, ¶ms,
523 : : BNXT_ULP_FDB_TYPE_REGULAR);
524 : 0 : mparms.act_tid = act_tid;
525 : :
526 : : /* Get the function id */
527 [ # # ]: 0 : if (ulp_port_db_port_func_id_get(ulp_ctx,
528 : 0 : dev->data->port_id,
529 : : &func_id)) {
530 : 0 : BNXT_TF_DBG(ERR, "conversion of port to func id failed\n");
531 : 0 : goto parse_error;
532 : : }
533 : :
534 : : /* Protect flow creation */
535 [ # # ]: 0 : if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
536 : 0 : BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
537 : 0 : goto parse_error;
538 : : }
539 : :
540 : 0 : ret = ulp_mapper_flow_create(params.ulp_ctx, &mparms);
541 : 0 : bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
542 : :
543 [ # # ]: 0 : if (ret)
544 : 0 : goto parse_error;
545 : :
546 : 0 : BNXT_TF_DBG(DEBUG, "Bnxt flow meter profile %d deleted\n",
547 : : meter_profile_id);
548 : :
549 : 0 : return 0;
550 : :
551 [ # # ]: 0 : parse_error:
552 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
553 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
554 : : NULL,
555 : : "Failed to delete meter profile.");
556 : : }
557 : :
558 : : /**
559 : : * Create meter.
560 : : */
561 : : static int
562 : 0 : bnxt_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
563 : : struct rte_mtr_params *params, int shared __rte_unused,
564 : : struct rte_mtr_error *error)
565 : : {
566 : : struct bnxt_ulp_context *ulp_ctx;
567 : : struct ulp_rte_parser_params pparams;
568 : : struct ulp_rte_act_prop *act_prop = &pparams.act_prop;
569 : 0 : struct bnxt_ulp_mapper_create_parms mparms = { 0 };
570 : : uint32_t act_tid;
571 : : uint16_t func_id;
572 : 0 : bool meter_en = params->meter_enable ? true : false;
573 : : int ret;
574 : : uint32_t tmp_meter_id, tmp_profile_id;
575 : :
576 [ # # ]: 0 : if (!bnxt_meter_initialized)
577 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
578 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
579 : : NULL,
580 : : "Bnxt meter is not initialized");
581 : :
582 : 0 : ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev);
583 [ # # ]: 0 : if (!ulp_ctx)
584 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
585 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
586 : : NULL,
587 : : "ULP context is not initialized");
588 : :
589 : : /* Initialize the parser params */
590 : : memset(&pparams, 0, sizeof(struct ulp_rte_parser_params));
591 : 0 : pparams.ulp_ctx = ulp_ctx;
592 : 0 : pparams.act_bitmap.bits = BNXT_ULP_ACT_BIT_SHARED_METER;
593 : : /* not direction from rte_mtr. Set ingress by default */
594 : 0 : pparams.dir_attr |= BNXT_ULP_FLOW_ATTR_INGRESS;
595 : :
596 [ # # ]: 0 : tmp_meter_id = tfp_cpu_to_be_32(meter_id);
597 : : memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_INST_ID],
598 : : &tmp_meter_id,
599 : : BNXT_ULP_ACT_PROP_SZ_METER_INST_ID);
600 : :
601 [ # # ]: 0 : tmp_profile_id = tfp_cpu_to_be_32(params->meter_profile_id);
602 : : memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_PROF_ID],
603 : : &tmp_profile_id,
604 : : BNXT_ULP_ACT_PROP_SZ_METER_PROF_ID);
605 : :
606 : : memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_INST_MTR_VAL],
607 : : &meter_en,
608 : : BNXT_ULP_ACT_PROP_SZ_METER_INST_MTR_VAL);
609 : :
610 : 0 : ret = ulp_matcher_action_match(&pparams, &act_tid);
611 [ # # ]: 0 : if (ret != BNXT_TF_RC_SUCCESS)
612 : 0 : goto parse_error;
613 : :
614 : 0 : bnxt_ulp_init_mapper_params(&mparms, &pparams,
615 : : BNXT_ULP_FDB_TYPE_REGULAR);
616 : 0 : mparms.act_tid = act_tid;
617 : :
618 : : /* Get the function id */
619 [ # # ]: 0 : if (ulp_port_db_port_func_id_get(ulp_ctx,
620 : 0 : dev->data->port_id,
621 : : &func_id)) {
622 : 0 : BNXT_TF_DBG(ERR, "conversion of port to func id failed\n");
623 : 0 : goto parse_error;
624 : : }
625 : :
626 : : /* Protect flow creation */
627 [ # # ]: 0 : if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
628 : 0 : BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
629 : 0 : goto parse_error;
630 : : }
631 : :
632 : 0 : ret = ulp_mapper_flow_create(pparams.ulp_ctx, &mparms);
633 : 0 : bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
634 : :
635 [ # # ]: 0 : if (ret)
636 : 0 : goto parse_error;
637 : :
638 : 0 : BNXT_TF_DBG(DEBUG, "Bnxt flow meter %d is created\n", meter_id);
639 : :
640 : 0 : return 0;
641 [ # # ]: 0 : parse_error:
642 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
643 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
644 : : NULL,
645 : : "Failed to add meter.");
646 : : }
647 : :
648 : : /**
649 : : * Destroy meter.
650 : : */
651 : : static int
652 : 0 : bnxt_flow_meter_destroy(struct rte_eth_dev *dev,
653 : : uint32_t meter_id,
654 : : struct rte_mtr_error *error)
655 : : {
656 : : struct bnxt_ulp_context *ulp_ctx;
657 : : struct ulp_rte_parser_params pparams;
658 : : struct ulp_rte_act_prop *act_prop = &pparams.act_prop;
659 : 0 : struct bnxt_ulp_mapper_create_parms mparms = { 0 };
660 : : uint32_t act_tid;
661 : : uint16_t func_id;
662 : : int ret;
663 : : uint32_t tmp_meter_id;
664 : :
665 [ # # ]: 0 : if (!bnxt_meter_initialized)
666 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
667 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
668 : : NULL,
669 : : "Bnxt meter is not initialized");
670 : :
671 : 0 : ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev);
672 [ # # ]: 0 : if (!ulp_ctx)
673 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
674 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
675 : : NULL,
676 : : "ULP context is not initialized");
677 : :
678 : : /* Initialize the parser params */
679 : : memset(&pparams, 0, sizeof(struct ulp_rte_parser_params));
680 : 0 : pparams.ulp_ctx = ulp_ctx;
681 : : pparams.act_bitmap.bits = BNXT_ULP_ACT_BIT_SHARED_METER;
682 : 0 : pparams.act_bitmap.bits |= BNXT_ULP_ACT_BIT_DELETE;
683 : : /* not direction from rte_mtr. Set ingress by default */
684 : 0 : pparams.dir_attr |= BNXT_ULP_FLOW_ATTR_INGRESS;
685 : :
686 [ # # ]: 0 : tmp_meter_id = tfp_cpu_to_be_32(meter_id);
687 : : memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_INST_ID],
688 : : &tmp_meter_id,
689 : : BNXT_ULP_ACT_PROP_SZ_METER_INST_ID);
690 : :
691 : 0 : ret = ulp_matcher_action_match(&pparams, &act_tid);
692 [ # # ]: 0 : if (ret != BNXT_TF_RC_SUCCESS)
693 : 0 : goto parse_error;
694 : :
695 : 0 : bnxt_ulp_init_mapper_params(&mparms, &pparams,
696 : : BNXT_ULP_FDB_TYPE_REGULAR);
697 : 0 : mparms.act_tid = act_tid;
698 : :
699 : : /* Get the function id */
700 [ # # ]: 0 : if (ulp_port_db_port_func_id_get(ulp_ctx,
701 : 0 : dev->data->port_id,
702 : : &func_id)) {
703 : 0 : BNXT_TF_DBG(ERR, "conversion of port to func id failed\n");
704 : 0 : goto parse_error;
705 : : }
706 : :
707 : : /* Protect flow creation */
708 [ # # ]: 0 : if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
709 : 0 : BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
710 : 0 : goto parse_error;
711 : : }
712 : :
713 : 0 : ret = ulp_mapper_flow_create(pparams.ulp_ctx, &mparms);
714 : 0 : bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
715 : :
716 [ # # ]: 0 : if (ret)
717 : 0 : goto parse_error;
718 : :
719 : 0 : BNXT_TF_DBG(DEBUG, "Bnxt flow meter %d is deleted\n", meter_id);
720 : :
721 : 0 : return 0;
722 [ # # ]: 0 : parse_error:
723 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
724 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
725 : : NULL,
726 : : "Failed to delete meter.");
727 : : }
728 : :
729 : : /**
730 : : * Set meter valid/invalid.
731 : : */
732 : : static int
733 : 0 : bnxt_flow_meter_enable_set(struct rte_eth_dev *dev,
734 : : uint32_t meter_id,
735 : : uint8_t val,
736 : : struct rte_mtr_error *error)
737 : : {
738 : : struct bnxt_ulp_context *ulp_ctx;
739 : : struct ulp_rte_parser_params pparams;
740 : : struct ulp_rte_act_prop *act_prop = &pparams.act_prop;
741 : 0 : struct bnxt_ulp_mapper_create_parms mparms = { 0 };
742 : : uint32_t act_tid;
743 : : uint16_t func_id;
744 : : int ret;
745 : : uint32_t tmp_meter_id;
746 : :
747 [ # # ]: 0 : if (!bnxt_meter_initialized)
748 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
749 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
750 : : NULL,
751 : : "Bnxt meter is not initialized");
752 : :
753 : 0 : ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev);
754 [ # # ]: 0 : if (!ulp_ctx)
755 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
756 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
757 : : NULL,
758 : : "ULP context is not initialized");
759 : :
760 : : /* Initialize the parser params */
761 : : memset(&pparams, 0, sizeof(struct ulp_rte_parser_params));
762 : 0 : pparams.ulp_ctx = ulp_ctx;
763 : : pparams.act_bitmap.bits = BNXT_ULP_ACT_BIT_SHARED_METER;
764 : 0 : pparams.act_bitmap.bits |= BNXT_ULP_ACT_BIT_UPDATE;
765 : : /* not direction from rte_mtr. Set ingress by default */
766 : 0 : pparams.dir_attr |= BNXT_ULP_FLOW_ATTR_INGRESS;
767 : :
768 [ # # ]: 0 : tmp_meter_id = tfp_cpu_to_be_32(meter_id);
769 : : memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_INST_ID],
770 : : &tmp_meter_id,
771 : : BNXT_ULP_ACT_PROP_SZ_METER_INST_ID);
772 : 0 : act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_INST_MTR_VAL_UPDATE] = 1;
773 : 0 : act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_INST_MTR_VAL] = val;
774 : :
775 : 0 : ret = ulp_matcher_action_match(&pparams, &act_tid);
776 [ # # ]: 0 : if (ret != BNXT_TF_RC_SUCCESS)
777 : 0 : goto parse_error;
778 : :
779 : 0 : bnxt_ulp_init_mapper_params(&mparms, &pparams,
780 : : BNXT_ULP_FDB_TYPE_REGULAR);
781 : 0 : mparms.act_tid = act_tid;
782 : :
783 : : /* Get the function id */
784 [ # # ]: 0 : if (ulp_port_db_port_func_id_get(ulp_ctx,
785 : 0 : dev->data->port_id,
786 : : &func_id)) {
787 : 0 : BNXT_TF_DBG(ERR, "conversion of port to func id failed\n");
788 : 0 : goto parse_error;
789 : : }
790 : :
791 : : /* Protect flow creation */
792 [ # # ]: 0 : if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
793 : 0 : BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
794 : 0 : goto parse_error;
795 : : }
796 : :
797 : 0 : ret = ulp_mapper_flow_create(pparams.ulp_ctx, &mparms);
798 : 0 : bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
799 : :
800 [ # # ]: 0 : if (ret)
801 : 0 : goto parse_error;
802 : :
803 [ # # ]: 0 : BNXT_TF_DBG(DEBUG, "Bnxt flow meter %d is %s\n",
804 : : meter_id, val ? "enabled" : "disabled");
805 : :
806 : 0 : return 0;
807 [ # # ]: 0 : parse_error:
808 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
809 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
810 : : NULL,
811 : : "Failed to enable/disable meter.");
812 : : }
813 : :
814 : : /**
815 : : * Enable flow meter.
816 : : */
817 : : static int
818 : 0 : bnxt_flow_meter_enable(struct rte_eth_dev *dev,
819 : : uint32_t meter_id,
820 : : struct rte_mtr_error *error)
821 : : {
822 : 0 : return bnxt_flow_meter_enable_set(dev, meter_id, 1, error);
823 : : }
824 : :
825 : : /**
826 : : * Disable flow meter.
827 : : */
828 : : static int
829 : 0 : bnxt_flow_meter_disable(struct rte_eth_dev *dev,
830 : : uint32_t meter_id,
831 : : struct rte_mtr_error *error)
832 : : {
833 : 0 : return bnxt_flow_meter_enable_set(dev, meter_id, 0, error);
834 : : }
835 : :
836 : : /**
837 : : * Update meter profile.
838 : : */
839 : : static int
840 [ # # ]: 0 : bnxt_flow_meter_profile_update(struct rte_eth_dev *dev __rte_unused,
841 : : uint32_t meter_id __rte_unused,
842 : : uint32_t meter_profile_id __rte_unused,
843 : : struct rte_mtr_error *error)
844 : : {
845 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
846 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
847 : : NULL,
848 : : "Meter_profile_update not supported");
849 : : }
850 : :
851 : : /**
852 : : * Udate meter stats mask.
853 : : */
854 : : static int
855 [ # # ]: 0 : bnxt_flow_meter_stats_update(struct rte_eth_dev *dev __rte_unused,
856 : : uint32_t meter_id __rte_unused,
857 : : uint64_t stats_mask __rte_unused,
858 : : struct rte_mtr_error *error)
859 : : {
860 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
861 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
862 : : NULL,
863 : : "Meter_stats_update not supported");
864 : : }
865 : :
866 : : /**
867 : : * Read meter statistics.
868 : : */
869 : : static int
870 [ # # ]: 0 : bnxt_flow_meter_stats_read(struct rte_eth_dev *dev __rte_unused,
871 : : uint32_t meter_id __rte_unused,
872 : : struct rte_mtr_stats *stats __rte_unused,
873 : : uint64_t *stats_mask __rte_unused,
874 : : int clear __rte_unused,
875 : : struct rte_mtr_error *error)
876 : : {
877 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
878 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
879 : : NULL,
880 : : "Meter_stats_read not supported yet");
881 : : }
882 : :
883 : : static const struct rte_mtr_ops bnxt_flow_mtr_ops = {
884 : : .capabilities_get = bnxt_flow_mtr_cap_get,
885 : : .meter_profile_add = bnxt_flow_meter_profile_add,
886 : : .meter_profile_delete = bnxt_flow_meter_profile_delete,
887 : : .meter_policy_validate = NULL,
888 : : .meter_policy_add = NULL,
889 : : .meter_policy_delete = NULL,
890 : : .create = bnxt_flow_meter_create,
891 : : .destroy = bnxt_flow_meter_destroy,
892 : : .meter_enable = bnxt_flow_meter_enable,
893 : : .meter_disable = bnxt_flow_meter_disable,
894 : : .meter_profile_update = bnxt_flow_meter_profile_update,
895 : : .meter_dscp_table_update = NULL,
896 : : .stats_update = bnxt_flow_meter_stats_update,
897 : : .stats_read = bnxt_flow_meter_stats_read,
898 : : };
899 : :
900 : : /**
901 : : * Get meter operations.
902 : : */
903 : : int
904 : 0 : bnxt_flow_meter_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
905 : : {
906 : 0 : *(const struct rte_mtr_ops **)arg = &bnxt_flow_mtr_ops;
907 : 0 : return 0;
908 : : }
|