Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2024 ZTE Corporation
3 : : */
4 : :
5 : : #include <bus_pci_driver.h>
6 : : #include <rte_ethdev.h>
7 : : #include <rte_mtr_driver.h>
8 : : #include <rte_mempool.h>
9 : :
10 : : #include "zxdh_logs.h"
11 : : #include "zxdh_mtr.h"
12 : : #include "zxdh_msg.h"
13 : : #include "zxdh_ethdev.h"
14 : : #include "zxdh_tables.h"
15 : :
16 : : #define ZXDH_SHARE_FLOW_MAX 2048
17 : : #define ZXDH_HW_PROFILE_MAX 512
18 : : #define ZXDH_MAX_MTR_PROFILE_NUM ZXDH_HW_PROFILE_MAX
19 : : #define ZXDH_PORT_MTR_FID_BASE 8192
20 : :
21 : : /* Maximum value of srTCM metering parameters, unit_step: 64kb
22 : : * 61K~400000000(400G) bps, uint 64Kbps CBS/EBS/PBS max bucket depth 128MB
23 : : * PPS: 1pps~600Mpps
24 : : */
25 : : #define ZXDH_SRTCM_CIR_MIN_BPS (61 * (1ULL << 10))
26 : : #define ZXDH_SRTCM_CIR_MAX_BPS (400 * (1ULL << 30))
27 : : #define ZXDH_SRTCM_EBS_MAX_B (128 * (1ULL << 20))
28 : : #define ZXDH_SRTCM_CBS_MAX_B (128 * (1ULL << 20))
29 : : #define ZXDH_TRTCM_PBS_MAX_B (128 * (1ULL << 20))
30 : : #define ZXDH_TRTCM_PIR_MAX_BPS (400 * (1ULL << 30))
31 : : #define ZXDH_TRTCM_PIR_MIN_BPS (61 * (1ULL << 10))
32 : :
33 : : #define ZXDH_SRTCM_CIR_MIN_PPS (1)
34 : : #define ZXDH_SRTCM_CIR_MAX_PPS (200 * (1ULL << 20))
35 : : #define ZXDH_SRTCM_CBS_MAX_P (8192)
36 : : #define ZXDH_SRTCM_EBS_MAX_P (8192)
37 : : #define ZXDH_TRTCM_PBS_MAX_P (8192)
38 : : #define ZXDH_TRTCM_PIR_MIN_PPS (1)
39 : : #define ZXDH_TRTCM_PIR_MAX_PPS (200 * (1ULL << 20))
40 : :
41 : : #define ZXDH_MP_ALLOC_OBJ_FUNC(mp, obj) rte_mempool_get(mp, (void **)&(obj))
42 : : #define ZXDH_MP_FREE_OBJ_FUNC(mp, obj) rte_mempool_put(mp, obj)
43 : :
44 : : #define ZXDH_VFUNC_ACTIVE_BIT 11
45 : : #define ZXDH_VFUNC_NUM_MASK 0xff
46 : : #define ZXDH_GET_OWNER_PF_VPORT(vport) \
47 : : (((vport) & ~(ZXDH_VFUNC_NUM_MASK)) & (~(1 << ZXDH_VFUNC_ACTIVE_BIT)))
48 : :
49 : : enum ZXDH_PLCR_CD {
50 : : ZXDH_PLCR_CD_SRTCM = 0,
51 : : ZXDH_PLCR_CD_TRTCM,
52 : : ZXDH_PLCR_CD_MEF101,
53 : : };
54 : : enum ZXDH_PLCR_CM {
55 : : ZXDH_PLCR_CM_BLIND = 0,
56 : : ZXDH_PLCR_CM_AWARE,
57 : : };
58 : : enum ZXDH_PLCR_CF {
59 : : ZXDH_PLCR_CF_UNOVERFLOW = 0,
60 : : ZXDH_PLCR_CF_OVERFLOW,
61 : : };
62 : :
63 : : int
64 : 0 : zxdh_hw_profile_ref(uint16_t hw_profile_id)
65 : : {
66 [ # # ]: 0 : if (hw_profile_id >= HW_PROFILE_MAX)
67 : : return -1;
68 : :
69 : : rte_spinlock_lock(&g_mtr_res.hw_plcr_res_lock);
70 : 0 : g_mtr_res.hw_profile_refcnt[hw_profile_id]++;
71 : : rte_spinlock_unlock(&g_mtr_res.hw_plcr_res_lock);
72 : 0 : return 0;
73 : : }
74 : :
75 : : static struct zxdh_meter_policy
76 : : *zxdh_mtr_policy_find_by_id(struct zxdh_mtr_policy_list *mtr_policy_list,
77 : : uint16_t policy_id, uint16_t dpdk_portid)
78 : : {
79 : : struct zxdh_meter_policy *mtr_policy = NULL;
80 : :
81 [ # # # # : 0 : TAILQ_FOREACH(mtr_policy, mtr_policy_list, next) {
# # ]
82 [ # # # # : 0 : if (policy_id == mtr_policy->policy_id &&
# # ]
83 [ # # # # : 0 : dpdk_portid == mtr_policy->dpdk_port_id)
# # ]
84 : : return mtr_policy;
85 : : }
86 : : return NULL;
87 : : }
88 : :
89 : : static int
90 : : zxdh_policy_validate_actions(const struct rte_flow_action *actions[RTE_COLORS],
91 : : struct rte_mtr_error *error)
92 : : {
93 [ # # # # ]: 0 : if (!actions[RTE_COLOR_RED] || actions[RTE_COLOR_RED]->type != RTE_FLOW_ACTION_TYPE_DROP)
94 : : return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
95 : : "Red color only supports drop action.");
96 : : return 0;
97 : : }
98 : :
99 : : static int
100 : 0 : mtr_hw_stats_get(struct zxdh_hw *hw, uint8_t direction, struct zxdh_hw_mtr_stats *hw_mtr_stats)
101 : : {
102 : 0 : union zxdh_virport_num v_port = hw->vport;
103 : : uint32_t stat_baseaddr = (direction == ZXDH_EGRESS)
104 : : ? ZXDH_MTR_STATS_EGRESS_BASE
105 [ # # ]: 0 : : ZXDH_MTR_STATS_INGRESS_BASE;
106 : 0 : uint32_t idx = zxdh_vport_to_vfid(v_port) + stat_baseaddr;
107 : 0 : struct zxdh_dtb_shared_data *dtb_sd = &hw->dev_sd->dtb_sd;
108 : :
109 : 0 : int ret = zxdh_np_dtb_stats_get(hw->dev_id,
110 : 0 : dtb_sd->queueid, ZXDH_STAT_128_MODE,
111 : : idx, (uint32_t *)hw_mtr_stats);
112 : :
113 [ # # ]: 0 : if (ret) {
114 : 0 : PMD_DRV_LOG(ERR, "get vport 0x%x (vfid 0x%x) dir %u stats failed",
115 : : v_port.vport,
116 : : hw->vfid,
117 : : direction);
118 : 0 : return ret;
119 : : }
120 : 0 : PMD_DRV_LOG(INFO, "get vport 0x%x (vfid 0x%x) dir %u stats",
121 : : v_port.vport,
122 : : hw->vfid,
123 : : direction);
124 : 0 : return 0;
125 : : }
126 : :
127 : : static int
128 : 0 : zxdh_mtr_stats_get(struct rte_eth_dev *dev, int dir, struct zxdh_mtr_stats *mtr_stats)
129 : : {
130 : 0 : struct zxdh_hw_mtr_stats hw_mtr_stat = {0};
131 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
132 : 0 : int ret = mtr_hw_stats_get(hw, dir, &hw_mtr_stat);
133 : :
134 [ # # ]: 0 : if (ret) {
135 : 0 : PMD_DRV_LOG(ERR, "port %u dir %u get mtr stats failed", hw->vport.vport, dir);
136 : 0 : return ret;
137 : : }
138 : 0 : mtr_stats->n_bytes_dropped =
139 : 0 : (uint64_t)(rte_le_to_cpu_32(hw_mtr_stat.n_bytes_dropped_hi)) << 32 |
140 : 0 : rte_le_to_cpu_32(hw_mtr_stat.n_bytes_dropped_lo);
141 : 0 : mtr_stats->n_pkts_dropped =
142 : 0 : (uint64_t)(rte_le_to_cpu_32(hw_mtr_stat.n_pkts_dropped_hi)) << 32 |
143 : 0 : rte_le_to_cpu_32(hw_mtr_stat.n_pkts_dropped_lo);
144 : :
145 : 0 : return 0;
146 : : }
147 : :
148 : : static int
149 : 0 : zxdh_meter_cap_get(struct rte_eth_dev *dev __rte_unused,
150 : : struct rte_mtr_capabilities *cap,
151 : : struct rte_mtr_error *error __rte_unused)
152 : : {
153 : : struct rte_mtr_capabilities capa = {
154 : : .n_max = ZXDH_MAX_MTR_NUM,
155 : : .n_shared_max = ZXDH_SHARE_FLOW_MAX,
156 : : .meter_srtcm_rfc2697_n_max = ZXDH_MAX_MTR_PROFILE_NUM,
157 : : .meter_trtcm_rfc2698_n_max = ZXDH_MAX_MTR_PROFILE_NUM,
158 : : .color_aware_srtcm_rfc2697_supported = 1,
159 : : .color_aware_trtcm_rfc2698_supported = 1,
160 : : .meter_rate_max = ZXDH_SRTCM_CIR_MAX_BPS,
161 : : .meter_policy_n_max = ZXDH_MAX_POLICY_NUM,
162 : : .srtcm_rfc2697_byte_mode_supported = 1,
163 : : .srtcm_rfc2697_packet_mode_supported = 1,
164 : : .trtcm_rfc2698_byte_mode_supported = 1,
165 : : .trtcm_rfc2698_packet_mode_supported = 1,
166 : : .stats_mask = RTE_MTR_STATS_N_PKTS_DROPPED | RTE_MTR_STATS_N_BYTES_DROPPED,
167 : : };
168 : :
169 : 0 : *cap = capa;
170 : 0 : return 0;
171 : : }
172 : :
173 : : static int
174 : 0 : zxdh_mtr_profile_validate(uint32_t meter_profile_id,
175 : : struct rte_mtr_meter_profile *profile,
176 : : struct rte_mtr_error *error)
177 : : {
178 : : uint64_t cir_min, cir_max, cbs_max, ebs_max, pir_min, pir_max, pbs_max;
179 : :
180 [ # # ]: 0 : if (profile == NULL || meter_profile_id >= ZXDH_MAX_MTR_PROFILE_NUM) {
181 : 0 : return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
182 : : "Meter profile param id invalid or null");
183 : : }
184 : :
185 [ # # ]: 0 : if (profile->packet_mode == 0) {
186 : : cir_min = ZXDH_SRTCM_CIR_MIN_BPS / 8;
187 : : cir_max = ZXDH_SRTCM_CIR_MAX_BPS / 8;
188 : : cbs_max = ZXDH_SRTCM_CBS_MAX_B;
189 : : ebs_max = ZXDH_SRTCM_EBS_MAX_B;
190 : : pir_min = ZXDH_TRTCM_PIR_MIN_BPS / 8;
191 : : pir_max = ZXDH_TRTCM_PIR_MAX_BPS / 8;
192 : : pbs_max = ZXDH_TRTCM_PBS_MAX_B;
193 : : } else {
194 : : cir_min = ZXDH_SRTCM_CIR_MIN_PPS;
195 : : cir_max = ZXDH_SRTCM_CIR_MAX_PPS;
196 : : cbs_max = ZXDH_SRTCM_CBS_MAX_P;
197 : : ebs_max = ZXDH_SRTCM_EBS_MAX_P;
198 : : pir_min = ZXDH_TRTCM_PIR_MIN_PPS;
199 : : pir_max = ZXDH_TRTCM_PIR_MAX_PPS;
200 : : pbs_max = ZXDH_TRTCM_PBS_MAX_P;
201 : : }
202 [ # # ]: 0 : if (profile->alg == RTE_MTR_SRTCM_RFC2697) {
203 [ # # # # ]: 0 : if (profile->srtcm_rfc2697.cir >= cir_min &&
204 : 0 : profile->srtcm_rfc2697.cir < cir_max &&
205 [ # # # # ]: 0 : profile->srtcm_rfc2697.cbs < cbs_max &&
206 : 0 : profile->srtcm_rfc2697.cbs > 0 &&
207 [ # # # # ]: 0 : profile->srtcm_rfc2697.ebs > 0 &&
208 : : profile->srtcm_rfc2697.ebs < ebs_max) {
209 : 0 : goto check_exist;
210 : : } else {
211 : 0 : return -rte_mtr_error_set
212 : : (error, ENOTSUP,
213 : : RTE_MTR_ERROR_TYPE_METER_PROFILE,
214 : : NULL,
215 : : "Invalid metering parameters");
216 : : }
217 [ # # ]: 0 : } else if (profile->alg == RTE_MTR_TRTCM_RFC2698) {
218 [ # # # # ]: 0 : if (profile->trtcm_rfc2698.cir >= cir_min &&
219 : 0 : profile->trtcm_rfc2698.cir < cir_max &&
220 [ # # # # ]: 0 : profile->trtcm_rfc2698.cbs < cbs_max &&
221 : 0 : profile->trtcm_rfc2698.cbs > 0 &&
222 [ # # # # ]: 0 : profile->trtcm_rfc2698.pir >= pir_min &&
223 [ # # ]: 0 : profile->trtcm_rfc2698.pir < pir_max &&
224 : 0 : profile->trtcm_rfc2698.cir < profile->trtcm_rfc2698.pir &&
225 [ # # # # ]: 0 : profile->trtcm_rfc2698.pbs > 0 &&
226 : : profile->trtcm_rfc2698.pbs < pbs_max)
227 : 0 : goto check_exist;
228 : : else
229 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
230 : : RTE_MTR_ERROR_TYPE_METER_PROFILE,
231 : : NULL,
232 : : "Invalid metering parameters");
233 : : } else {
234 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
235 : : RTE_MTR_ERROR_TYPE_METER_PROFILE,
236 : : NULL,
237 : : "algorithm not supported");
238 : : }
239 : :
240 : 0 : check_exist:
241 : : return 0;
242 : : }
243 : :
244 : : static struct zxdh_meter_profile
245 : : *zxdh_mtr_profile_find_by_id(struct zxdh_mtr_profile_list *mpl,
246 : : uint32_t meter_profile_id, uint16_t dpdk_portid)
247 : : {
248 : : struct zxdh_meter_profile *mp = NULL;
249 : :
250 [ # # # # : 0 : TAILQ_FOREACH(mp, mpl, next) {
# # ]
251 [ # # # # : 0 : if (meter_profile_id == mp->meter_profile_id && mp->dpdk_port_id == dpdk_portid)
# # # # #
# # # ]
252 : : return mp;
253 : : }
254 : : return NULL;
255 : : }
256 : :
257 : : static struct zxdh_meter_profile
258 : 0 : *zxdh_mtr_profile_res_alloc(struct rte_mempool *mtr_profile_mp)
259 : : {
260 [ # # ]: 0 : struct zxdh_meter_profile *meter_profile = NULL;
261 : :
262 [ # # ]: 0 : if (ZXDH_MP_ALLOC_OBJ_FUNC(mtr_profile_mp, meter_profile) != 0)
263 : : return NULL;
264 : :
265 : 0 : return meter_profile;
266 : : }
267 : :
268 : : static struct zxdh_meter_policy
269 : 0 : *zxdh_mtr_policy_res_alloc(struct rte_mempool *mtr_policy_mp)
270 : : {
271 [ # # ]: 0 : struct zxdh_meter_policy *policy = NULL;
272 : :
273 : : rte_mempool_get(mtr_policy_mp, (void **)&policy);
274 : 0 : PMD_DRV_LOG(INFO, "policy %p", policy);
275 : 0 : return policy;
276 : : }
277 : :
278 : : static int
279 : 0 : zxdh_hw_profile_free_direct(struct rte_eth_dev *dev, ZXDH_PROFILE_TYPE car_type,
280 : : uint16_t hw_profile_id, struct rte_mtr_error *error)
281 : : {
282 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
283 : 0 : uint16_t vport = hw->vport.vport;
284 : 0 : int ret = zxdh_np_car_profile_id_delete(vport, car_type,
285 : : (uint64_t)hw_profile_id);
286 [ # # ]: 0 : if (ret) {
287 : 0 : PMD_DRV_LOG(ERR, "port %u free hw profile %u failed", vport, hw_profile_id);
288 : 0 : return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL,
289 : : "Meter free profile failed");
290 : : }
291 : :
292 : : return 0;
293 : : }
294 : :
295 : : int
296 : 0 : zxdh_hw_profile_alloc_direct(struct rte_eth_dev *dev, ZXDH_PROFILE_TYPE car_type,
297 : : uint64_t *hw_profile_id, struct rte_mtr_error *error)
298 : : {
299 : 0 : uint64_t profile_id = HW_PROFILE_MAX;
300 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
301 : 0 : uint16_t vport = hw->vport.vport;
302 : 0 : int ret = zxdh_np_car_profile_id_add(vport, car_type, &profile_id);
303 : :
304 [ # # ]: 0 : if (ret) {
305 : 0 : PMD_DRV_LOG(ERR, "port %u alloc hw profile failed", vport);
306 : 0 : return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL,
307 : : "Meter offload alloc profile failed");
308 : : }
309 : 0 : *hw_profile_id = profile_id;
310 [ # # ]: 0 : if (*hw_profile_id == ZXDH_HW_PROFILE_MAX) {
311 : 0 : return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL,
312 : : "Meter offload alloc profile id invalid");
313 : : }
314 : :
315 : : return 0;
316 : : }
317 : :
318 : : static uint16_t
319 : 0 : zxdh_hw_profile_free(struct rte_eth_dev *dev, uint8_t car_type,
320 : : uint16_t hw_profile_id, struct rte_mtr_error *error)
321 : : {
322 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
323 : : int ret = 0;
324 : :
325 [ # # ]: 0 : if (hw->is_pf) {
326 : 0 : ret = zxdh_hw_profile_free_direct(dev, car_type, (uint64_t)hw_profile_id, error);
327 : : } else {
328 : 0 : struct zxdh_msg_info msg_info = {0};
329 : 0 : struct zxdh_msg_reply_info reply_info = {0};
330 : : struct zxdh_plcr_profile_free *zxdh_plcr_profile_free =
331 : : &msg_info.data.zxdh_plcr_profile_free;
332 : :
333 : 0 : zxdh_plcr_profile_free->profile_id = hw_profile_id;
334 : 0 : zxdh_plcr_profile_free->car_type = car_type;
335 : 0 : zxdh_msg_head_build(hw, ZXDH_PLCR_CAR_PROFILE_ID_DELETE, &msg_info);
336 : 0 : ret = zxdh_vf_send_msg_to_pf(dev, &msg_info,
337 : : ZXDH_MSG_HEAD_LEN + sizeof(struct zxdh_plcr_profile_free),
338 : : &reply_info, sizeof(struct zxdh_msg_reply_info));
339 : :
340 [ # # ]: 0 : if (ret)
341 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
342 : : RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL,
343 : : "Meter free profile failed ");
344 : : }
345 : :
346 : 0 : return ret;
347 : : }
348 : :
349 : : static int
350 : 0 : zxdh_hw_profile_alloc(struct rte_eth_dev *dev, uint64_t *hw_profile_id,
351 : : struct rte_mtr_error *error)
352 : : {
353 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
354 : : int ret = 0;
355 : :
356 [ # # ]: 0 : if (hw->is_pf) {
357 : 0 : ret = zxdh_hw_profile_alloc_direct(dev, CAR_A, hw_profile_id, error);
358 : : } else {
359 : 0 : struct zxdh_msg_info msg_info = {0};
360 : 0 : struct zxdh_msg_reply_info reply_info = {0};
361 : : struct zxdh_plcr_profile_add *zxdh_plcr_profile_add =
362 : : &msg_info.data.zxdh_plcr_profile_add;
363 : :
364 : : zxdh_plcr_profile_add->car_type = CAR_A;
365 : 0 : zxdh_msg_head_build(hw, ZXDH_PLCR_CAR_PROFILE_ID_ADD, &msg_info);
366 : 0 : ret = zxdh_vf_send_msg_to_pf(dev, &msg_info,
367 : : ZXDH_MSG_HEAD_LEN + sizeof(struct zxdh_plcr_profile_add),
368 : : &reply_info, sizeof(struct zxdh_msg_reply_info));
369 : :
370 [ # # ]: 0 : if (ret) {
371 : 0 : PMD_DRV_LOG(ERR,
372 : : "Failed to send msg: port 0x%x msg type ZXDH_PLCR_CAR_PROFILE_ID_ADD ",
373 : : hw->vport.vport);
374 : :
375 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
376 : : RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL,
377 : : "Meter offload alloc profile id msg failed ");
378 : : }
379 : 0 : *hw_profile_id = reply_info.reply_body.mtr_profile_info.profile_id;
380 [ # # ]: 0 : if (*hw_profile_id == ZXDH_HW_PROFILE_MAX) {
381 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
382 : : RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL,
383 : : "Meter offload alloc profile id invalid ");
384 : : }
385 : : }
386 : :
387 : : return ret;
388 : : }
389 : :
390 : : int
391 : 0 : zxdh_hw_profile_unref(struct rte_eth_dev *dev,
392 : : uint8_t car_type,
393 : : uint16_t hw_profile_id,
394 : : struct rte_mtr_error *error)
395 : : {
396 [ # # ]: 0 : if (hw_profile_id >= ZXDH_HW_PROFILE_MAX)
397 : : return -1;
398 : :
399 : : rte_spinlock_lock(&g_mtr_res.hw_plcr_res_lock);
400 [ # # ]: 0 : if (g_mtr_res.hw_profile_refcnt[hw_profile_id] == 0) {
401 : 0 : PMD_DRV_LOG(ERR, "del hw profile id %d but ref 0", hw_profile_id);
402 : : rte_spinlock_unlock(&g_mtr_res.hw_plcr_res_lock);
403 : 0 : return -1;
404 : : }
405 [ # # ]: 0 : if (--g_mtr_res.hw_profile_refcnt[hw_profile_id] == 0) {
406 : 0 : PMD_DRV_LOG(INFO, "del hw profile id %d ", hw_profile_id);
407 : 0 : zxdh_hw_profile_free(dev, car_type, hw_profile_id, error);
408 : : }
409 : : rte_spinlock_unlock(&g_mtr_res.hw_plcr_res_lock);
410 : 0 : return 0;
411 : : }
412 : :
413 : : static int
414 : 0 : zxdh_mtr_hw_counter_query(struct rte_eth_dev *dev,
415 : : bool clear,
416 : : bool dir,
417 : : struct zxdh_mtr_stats *mtr_stats,
418 : : struct rte_mtr_error *error)
419 : : {
420 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
421 : : int ret = 0;
422 : :
423 [ # # ]: 0 : if (hw->is_pf) {
424 : 0 : ret = zxdh_mtr_stats_get(dev, dir, mtr_stats);
425 [ # # ]: 0 : if (ret) {
426 : 0 : PMD_DRV_LOG(ERR,
427 : : "ZXDH_PORT_METER_STAT_GET port %u dir %d failed",
428 : : hw->vport.vport,
429 : : dir);
430 : :
431 : 0 : return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_STATS, NULL, "Failed to bind plcr flow.");
432 : : }
433 : : } else { /* send msg to pf */
434 : 0 : struct zxdh_msg_info msg_info = {0};
435 : 0 : struct zxdh_msg_reply_info reply_info = {0};
436 : : struct zxdh_mtr_stats_query *zxdh_mtr_stats_query =
437 : : &msg_info.data.zxdh_mtr_stats_query;
438 : :
439 : 0 : zxdh_mtr_stats_query->direction = dir;
440 : 0 : zxdh_mtr_stats_query->is_clr = !!clear;
441 : 0 : zxdh_msg_head_build(hw, ZXDH_PORT_METER_STAT_GET, &msg_info);
442 : 0 : ret = zxdh_vf_send_msg_to_pf(dev,
443 : : &msg_info,
444 : : sizeof(msg_info),
445 : : &reply_info,
446 : : sizeof(struct zxdh_msg_reply_info));
447 : :
448 [ # # ]: 0 : if (ret) {
449 : 0 : PMD_DRV_LOG(ERR,
450 : : "Failed to send msg: port 0x%x msg type ZXDH_PORT_METER_STAT_GET",
451 : : hw->vport.vport);
452 : 0 : return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_STATS, NULL, "Meter offload alloc profile failed");
453 : : }
454 : : struct zxdh_mtr_stats *hw_mtr_stats = &reply_info.reply_body.hw_mtr_stats;
455 : :
456 : 0 : mtr_stats->n_bytes_dropped = hw_mtr_stats->n_bytes_dropped;
457 : 0 : mtr_stats->n_pkts_dropped = hw_mtr_stats->n_pkts_dropped;
458 : : }
459 : :
460 : : return ret;
461 : : }
462 : :
463 : :
464 : : static void
465 : 0 : zxdh_mtr_profile_res_free(struct rte_eth_dev *dev,
466 : : struct rte_mempool *mtr_profile_mp,
467 : : struct zxdh_meter_profile *meter_profile,
468 : : struct rte_mtr_error *error)
469 : : {
470 [ # # ]: 0 : if (meter_profile->ref_cnt == 0) {
471 : 0 : ZXDH_MP_FREE_OBJ_FUNC(mtr_profile_mp, meter_profile);
472 : 0 : return;
473 : : }
474 [ # # ]: 0 : if (meter_profile->ref_cnt == 1) {
475 : 0 : meter_profile->ref_cnt--;
476 : 0 : zxdh_hw_profile_unref(dev, CAR_A, meter_profile->hw_profile_id, error);
477 : :
478 [ # # # # ]: 0 : TAILQ_REMOVE(&zxdh_shared_data->meter_profile_list, meter_profile, next);
479 : 0 : ZXDH_MP_FREE_OBJ_FUNC(mtr_profile_mp, meter_profile);
480 : : } else {
481 : 0 : PMD_DRV_LOG(INFO,
482 : : "profile %d ref %d is busy",
483 : : meter_profile->meter_profile_id,
484 : : meter_profile->ref_cnt);
485 : : }
486 : : }
487 : :
488 : : static uint16_t
489 : 0 : zxdh_check_hw_profile_exist(struct zxdh_mtr_profile_list *mpl,
490 : : struct rte_mtr_meter_profile *profile,
491 : : uint16_t hw_profile_owner_vport)
492 : : {
493 : : struct zxdh_meter_profile *mp;
494 : :
495 [ # # ]: 0 : TAILQ_FOREACH(mp, mpl, next) {
496 [ # # ]: 0 : if ((memcmp(profile, &mp->profile, sizeof(struct rte_mtr_meter_profile)) == 0) &&
497 [ # # ]: 0 : hw_profile_owner_vport == mp->hw_profile_owner_vport) {
498 : 0 : return mp->hw_profile_id;
499 : : }
500 : : }
501 : : return ZXDH_HW_PROFILE_MAX;
502 : : }
503 : :
504 : : static void
505 : 0 : zxdh_plcr_param_build(struct rte_mtr_meter_profile *profile,
506 : : void *plcr_param, uint16_t profile_id)
507 : : {
508 [ # # ]: 0 : if (profile->packet_mode == 0) {
509 : : ZXDH_STAT_CAR_PROFILE_CFG_T *p_car_byte_profile_cfg =
510 : : (ZXDH_STAT_CAR_PROFILE_CFG_T *)plcr_param;
511 : :
512 : 0 : p_car_byte_profile_cfg->profile_id = profile_id;
513 : 0 : p_car_byte_profile_cfg->pkt_sign = profile->packet_mode;
514 : 0 : p_car_byte_profile_cfg->cf = ZXDH_PLCR_CF_UNOVERFLOW;
515 : 0 : p_car_byte_profile_cfg->cm = ZXDH_PLCR_CM_BLIND;
516 [ # # ]: 0 : if (profile->alg == RTE_MTR_SRTCM_RFC2697) {
517 : 0 : p_car_byte_profile_cfg->cd = ZXDH_PLCR_CD_SRTCM;
518 : 0 : p_car_byte_profile_cfg->cir = profile->srtcm_rfc2697.cir * 8 / 1000;
519 : 0 : p_car_byte_profile_cfg->cbs = profile->srtcm_rfc2697.cbs;
520 : 0 : p_car_byte_profile_cfg->ebs = profile->srtcm_rfc2697.ebs;
521 : : } else {
522 : 0 : p_car_byte_profile_cfg->cd = ZXDH_PLCR_CD_TRTCM;
523 : 0 : p_car_byte_profile_cfg->cir = profile->trtcm_rfc2698.cir * 8 / 1000;
524 : 0 : p_car_byte_profile_cfg->cbs = profile->trtcm_rfc2698.cbs;
525 : 0 : p_car_byte_profile_cfg->eir = (profile->trtcm_rfc2698.pir -
526 : 0 : profile->trtcm_rfc2698.cir) * 8 / 1000;
527 : 0 : p_car_byte_profile_cfg->ebs =
528 : 0 : profile->trtcm_rfc2698.pbs - profile->trtcm_rfc2698.cbs;
529 : : }
530 : : } else {
531 : : ZXDH_STAT_CAR_PKT_PROFILE_CFG_T *p_car_pkt_profile_cfg =
532 : : (ZXDH_STAT_CAR_PKT_PROFILE_CFG_T *)plcr_param;
533 : :
534 : 0 : p_car_pkt_profile_cfg->profile_id = profile_id;
535 : 0 : p_car_pkt_profile_cfg->pkt_sign = profile->packet_mode;
536 : :
537 [ # # ]: 0 : if (profile->alg == RTE_MTR_SRTCM_RFC2697) {
538 : 0 : p_car_pkt_profile_cfg->cir = profile->srtcm_rfc2697.cir;
539 : 0 : p_car_pkt_profile_cfg->cbs = profile->srtcm_rfc2697.cbs;
540 : : } else {
541 : 0 : p_car_pkt_profile_cfg->cir = profile->trtcm_rfc2698.cir;
542 : 0 : p_car_pkt_profile_cfg->cbs = profile->trtcm_rfc2698.cbs;
543 : : }
544 : : }
545 : 0 : }
546 : :
547 : : static int
548 : 0 : zxdh_hw_profile_config_direct(struct rte_eth_dev *dev __rte_unused,
549 : : ZXDH_PROFILE_TYPE car_type,
550 : : uint16_t hw_profile_id,
551 : : struct zxdh_meter_profile *mp,
552 : : struct rte_mtr_error *error)
553 : : {
554 : 0 : int ret = zxdh_np_car_profile_cfg_set(mp->hw_profile_owner_vport,
555 : 0 : car_type, mp->profile.packet_mode,
556 : 0 : (uint32_t)hw_profile_id, &mp->plcr_param);
557 [ # # ]: 0 : if (ret) {
558 : 0 : PMD_DRV_LOG(ERR, " config hw profile %u failed", hw_profile_id);
559 : 0 : return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
560 : : "Meter offload cfg profile failed");
561 : : }
562 : :
563 : : return 0;
564 : : }
565 : :
566 : 0 : static int zxdh_hw_profile_config(struct rte_eth_dev *dev, uint16_t hw_profile_id,
567 : : struct zxdh_meter_profile *mp, struct rte_mtr_error *error)
568 : : {
569 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
570 : : int ret = 0;
571 : :
572 [ # # ]: 0 : if (hw->is_pf) {
573 : 0 : ret = zxdh_hw_profile_config_direct(dev, CAR_A, hw_profile_id, mp, error);
574 : : } else {
575 : 0 : struct zxdh_msg_info msg_info = {0};
576 : 0 : struct zxdh_msg_reply_info reply_info = {0};
577 : : struct zxdh_plcr_profile_cfg *zxdh_plcr_profile_cfg =
578 : : &msg_info.data.zxdh_plcr_profile_cfg;
579 : :
580 : : zxdh_plcr_profile_cfg->car_type = CAR_A;
581 : 0 : zxdh_plcr_profile_cfg->packet_mode = mp->profile.packet_mode;
582 : 0 : zxdh_plcr_profile_cfg->hw_profile_id = hw_profile_id;
583 : : rte_memcpy(&zxdh_plcr_profile_cfg->plcr_param,
584 [ # # ]: 0 : &mp->plcr_param,
585 : : sizeof(zxdh_plcr_profile_cfg->plcr_param));
586 : :
587 : 0 : zxdh_msg_head_build(hw, ZXDH_PLCR_CAR_PROFILE_CFG_SET, &msg_info);
588 : 0 : ret = zxdh_vf_send_msg_to_pf(dev,
589 : : &msg_info,
590 : : ZXDH_MSG_HEAD_LEN + sizeof(struct zxdh_plcr_profile_cfg),
591 : : &reply_info,
592 : : sizeof(struct zxdh_msg_reply_info));
593 : :
594 [ # # ]: 0 : if (ret) {
595 : 0 : PMD_DRV_LOG(ERR,
596 : : "Failed msg: port 0x%x msg type ZXDH_PLCR_CAR_PROFILE_CFG_SET ",
597 : : hw->vport.vport);
598 : :
599 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
600 : : RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
601 : : "Meter offload cfg profile failed ");
602 : : }
603 : : }
604 : :
605 : : return ret;
606 : : }
607 : :
608 : : static int
609 : 0 : zxdh_mtr_profile_offload(struct rte_eth_dev *dev, struct zxdh_meter_profile *mp,
610 : : struct rte_mtr_meter_profile *profile, struct rte_mtr_error *error)
611 : : {
612 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
613 : 0 : uint16_t hw_profile_owner_vport = ZXDH_GET_OWNER_PF_VPORT(hw->vport.vport);
614 : :
615 : 0 : mp->hw_profile_owner_vport = hw_profile_owner_vport;
616 : 0 : uint64_t hw_profile_id =
617 : 0 : zxdh_check_hw_profile_exist(&zxdh_shared_data->meter_profile_list,
618 : : profile,
619 : : hw_profile_owner_vport);
620 : :
621 [ # # ]: 0 : if (hw_profile_id == ZXDH_HW_PROFILE_MAX) {
622 : 0 : uint32_t ret = zxdh_hw_profile_alloc(dev, &hw_profile_id, error);
623 : :
624 [ # # ]: 0 : if (ret) {
625 : 0 : PMD_DRV_LOG(ERR, "hw_profile alloc fail");
626 : 0 : return ret;
627 : : }
628 : :
629 : 0 : zxdh_plcr_param_build(profile, &mp->plcr_param, hw_profile_id);
630 : 0 : ret = zxdh_hw_profile_config(dev, hw_profile_id, mp, error);
631 [ # # ]: 0 : if (ret) {
632 : 0 : PMD_DRV_LOG(ERR, "zxdh_hw_profile_config fail");
633 : : hw_profile_id = ZXDH_HW_PROFILE_MAX;
634 : 0 : return ret;
635 : : }
636 : : }
637 : 0 : zxdh_hw_profile_ref(hw_profile_id);
638 : 0 : mp->hw_profile_id = hw_profile_id;
639 : :
640 : 0 : return 0;
641 : : }
642 : :
643 : : static int
644 : 0 : zxdh_meter_profile_add(struct rte_eth_dev *dev,
645 : : uint32_t meter_profile_id,
646 : : struct rte_mtr_meter_profile *profile,
647 : : struct rte_mtr_error *error)
648 : : {
649 : : struct zxdh_meter_profile *mp;
650 : : int ret;
651 : :
652 : 0 : ret = zxdh_mtr_profile_validate(meter_profile_id, profile, error);
653 [ # # ]: 0 : if (ret)
654 : 0 : return -rte_mtr_error_set(error, ENOMEM,
655 : : RTE_MTR_ERROR_TYPE_METER_PROFILE,
656 : : NULL, "meter profile validate failed");
657 : 0 : mp = zxdh_mtr_profile_find_by_id(&zxdh_shared_data->meter_profile_list,
658 : : meter_profile_id,
659 : 0 : dev->data->port_id);
660 : :
661 [ # # ]: 0 : if (mp)
662 : 0 : return -rte_mtr_error_set(error, EEXIST,
663 : : RTE_MTR_ERROR_TYPE_METER_PROFILE,
664 : : NULL,
665 : : "meter profile is exists");
666 : :
667 : 0 : mp = zxdh_mtr_profile_res_alloc(zxdh_shared_data->mtr_profile_mp);
668 [ # # ]: 0 : if (mp == NULL)
669 : 0 : return -rte_mtr_error_set(error, ENOMEM,
670 : : RTE_MTR_ERROR_TYPE_METER_PROFILE,
671 : : NULL, "Meter profile res memory alloc failed.");
672 : :
673 : : memset(mp, 0, sizeof(struct zxdh_meter_profile));
674 : :
675 : 0 : mp->meter_profile_id = meter_profile_id;
676 : 0 : mp->dpdk_port_id = dev->data->port_id;
677 : 0 : mp->hw_profile_id = UINT16_MAX;
678 [ # # ]: 0 : rte_memcpy(&mp->profile, profile, sizeof(struct rte_mtr_meter_profile));
679 : :
680 : 0 : ret = zxdh_mtr_profile_offload(dev, mp, profile, error);
681 [ # # ]: 0 : if (ret) {
682 : 0 : PMD_DRV_LOG(ERR,
683 : : " port %d profile id %d offload failed ",
684 : : dev->data->port_id,
685 : : meter_profile_id);
686 : 0 : goto error;
687 : : }
688 : :
689 : 0 : TAILQ_INSERT_TAIL(&zxdh_shared_data->meter_profile_list, mp, next);
690 : 0 : PMD_DRV_LOG(DEBUG,
691 : : "add profile id %d mp %p mp->ref_cnt %d",
692 : : meter_profile_id,
693 : : mp,
694 : : mp->ref_cnt);
695 : :
696 : 0 : mp->ref_cnt++;
697 : :
698 : 0 : return 0;
699 : : error:
700 : 0 : zxdh_mtr_profile_res_free(dev, zxdh_shared_data->mtr_profile_mp, mp, error);
701 : 0 : return ret;
702 : : }
703 : :
704 : : static int
705 : 0 : zxdh_meter_profile_delete(struct rte_eth_dev *dev,
706 : : uint32_t meter_profile_id,
707 : : struct rte_mtr_error *error)
708 : : {
709 : : struct zxdh_meter_profile *mp;
710 : :
711 : 0 : mp = zxdh_mtr_profile_find_by_id(&zxdh_shared_data->meter_profile_list,
712 : : meter_profile_id,
713 : 0 : dev->data->port_id);
714 : :
715 [ # # ]: 0 : if (mp == NULL) {
716 : 0 : PMD_DRV_LOG(ERR, "del profile id %d unfind ", meter_profile_id);
717 : 0 : return -rte_mtr_error_set(error, ENOENT,
718 : : RTE_MTR_ERROR_TYPE_METER_PROFILE,
719 : : &meter_profile_id,
720 : : "Meter profile id is not exists.");
721 : : }
722 : 0 : zxdh_mtr_profile_res_free(dev, zxdh_shared_data->mtr_profile_mp, mp, error);
723 : :
724 : 0 : return 0;
725 : : }
726 : :
727 : : static int
728 : 0 : zxdh_meter_policy_add(struct rte_eth_dev *dev,
729 : : uint32_t policy_id,
730 : : struct rte_mtr_meter_policy_params *policy,
731 : : struct rte_mtr_error *error)
732 : : {
733 : : int ret = 0;
734 : : struct zxdh_meter_policy *mtr_policy = NULL;
735 : :
736 [ # # ]: 0 : if (policy_id >= ZXDH_MAX_POLICY_NUM)
737 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
738 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
739 : : NULL, "policy ID is invalid. ");
740 : 0 : mtr_policy = zxdh_mtr_policy_find_by_id(&zxdh_shared_data->mtr_policy_list,
741 : : policy_id,
742 : 0 : dev->data->port_id);
743 : :
744 [ # # ]: 0 : if (mtr_policy)
745 : 0 : return -rte_mtr_error_set(error, EEXIST,
746 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
747 : : NULL, "policy ID exists. ");
748 : : ret = zxdh_policy_validate_actions(policy->actions, error);
749 : : if (ret) {
750 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
751 : : RTE_MTR_ERROR_TYPE_METER_POLICY,
752 : : NULL, " only supports def action.");
753 : : }
754 : :
755 : 0 : mtr_policy = zxdh_mtr_policy_res_alloc(zxdh_shared_data->mtr_policy_mp);
756 [ # # ]: 0 : if (mtr_policy == NULL) {
757 : 0 : return -rte_mtr_error_set(error, ENOMEM,
758 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
759 : : NULL, "Meter policy res memory alloc failed.");
760 : : }
761 : : /* Fill profile info. */
762 : : memset(mtr_policy, 0, sizeof(struct zxdh_meter_policy));
763 : 0 : mtr_policy->policy_id = policy_id;
764 : 0 : mtr_policy->dpdk_port_id = dev->data->port_id;
765 [ # # ]: 0 : rte_memcpy(&mtr_policy->policy, policy, sizeof(struct rte_mtr_meter_policy_params));
766 : : /* Add to list. */
767 : 0 : TAILQ_INSERT_TAIL(&zxdh_shared_data->mtr_policy_list, mtr_policy, next);
768 : 0 : mtr_policy->ref_cnt++;
769 : 0 : PMD_DRV_LOG(INFO, "allic policy id %d ok %p ", mtr_policy->policy_id, mtr_policy);
770 : 0 : return 0;
771 : : }
772 : :
773 : : static int
774 : 0 : zxdh_meter_policy_delete(struct rte_eth_dev *dev,
775 : : uint32_t policy_id,
776 : : struct rte_mtr_error *error)
777 : : {
778 : : struct zxdh_meter_policy *mtr_policy = NULL;
779 : :
780 [ # # ]: 0 : if (policy_id >= ZXDH_MAX_POLICY_NUM)
781 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
782 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
783 : : NULL, "policy ID is invalid. ");
784 : 0 : mtr_policy = zxdh_mtr_policy_find_by_id(&zxdh_shared_data->mtr_policy_list,
785 : 0 : policy_id, dev->data->port_id);
786 : :
787 [ # # # # ]: 0 : if (mtr_policy && mtr_policy->ref_cnt == 1) {
788 [ # # ]: 0 : TAILQ_REMOVE(&zxdh_shared_data->mtr_policy_list, mtr_policy, next);
789 [ # # ]: 0 : MP_FREE_OBJ_FUNC(zxdh_shared_data->mtr_policy_mp, mtr_policy);
790 : : } else {
791 [ # # ]: 0 : if (mtr_policy) {
792 : 0 : PMD_DRV_LOG(INFO,
793 : : " policy id %d ref %d is busy ",
794 : : mtr_policy->policy_id,
795 : : mtr_policy->ref_cnt);
796 : : } else {
797 : 0 : PMD_DRV_LOG(ERR, " policy id %d is not exist ", policy_id);
798 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
799 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
800 : : NULL, "policy ID is not exist. ");
801 : : }
802 : : }
803 : : return 0;
804 : : }
805 : :
806 : : static int
807 : 0 : zxdh_meter_validate(uint32_t meter_id,
808 : : struct rte_mtr_params *params,
809 : : struct rte_mtr_error *error)
810 : : {
811 : : /* Meter params must not be NULL. */
812 [ # # ]: 0 : if (params == NULL)
813 : 0 : return -rte_mtr_error_set(error, EINVAL,
814 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS,
815 : : NULL, "Meter object params null.");
816 : : /* Previous meter color is not supported. */
817 [ # # ]: 0 : if (params->use_prev_mtr_color)
818 : 0 : return -rte_mtr_error_set(error, EINVAL,
819 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS,
820 : : NULL,
821 : : "Previous meter color not supported");
822 [ # # ]: 0 : if (meter_id > ZXDH_MAX_MTR_NUM / 2) {
823 : 0 : return -rte_mtr_error_set(error, EINVAL,
824 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS,
825 : : NULL,
826 : : " meter id exceed 1024 unsupported");
827 : : }
828 : : return 0;
829 : : }
830 : :
831 : : static int
832 : 0 : zxdh_check_port_mtr_bind(struct rte_eth_dev *dev, uint32_t dir)
833 : : {
834 : : struct zxdh_mtr_object *mtr_obj = NULL;
835 : :
836 [ # # ]: 0 : TAILQ_FOREACH(mtr_obj, &zxdh_shared_data->mtr_list, next) {
837 [ # # ]: 0 : if (mtr_obj->direction != dir)
838 : 0 : continue;
839 [ # # ]: 0 : if (mtr_obj->port_id == dev->data->port_id) {
840 : 0 : PMD_DRV_LOG(INFO,
841 : : "port %d dir %d already bind meter %d",
842 : : dev->data->port_id,
843 : : dir,
844 : : mtr_obj->meter_id);
845 : 0 : return -1;
846 : : }
847 : : }
848 : :
849 : : return 0;
850 : : }
851 : :
852 : : static struct zxdh_mtr_object
853 : 0 : *zxdh_mtr_obj_alloc(struct rte_mempool *mtr_mp)
854 : : {
855 [ # # ]: 0 : struct zxdh_mtr_object *mtr_obj = NULL;
856 : :
857 [ # # ]: 0 : if (ZXDH_MP_ALLOC_OBJ_FUNC(mtr_mp, mtr_obj) != 0)
858 : : return NULL;
859 : :
860 : 0 : return mtr_obj;
861 : : }
862 : :
863 : : static uint32_t dir_to_mtr_mode[] = {
864 : : ZXDH_PORT_EGRESS_METER_EN_OFF_FLAG,
865 : : ZXDH_PORT_INGRESS_METER_EN_OFF_FLAG
866 : : };
867 : :
868 : : static int
869 : 0 : zxdh_set_mtr_enable(struct rte_eth_dev *dev, uint8_t dir, bool enable, struct rte_mtr_error *error)
870 : : {
871 : 0 : struct zxdh_hw *priv = dev->data->dev_private;
872 : 0 : struct zxdh_port_attr_table port_attr = {0};
873 : : int ret = 0;
874 : :
875 [ # # ]: 0 : if (priv->is_pf) {
876 : 0 : ret = zxdh_get_port_attr(priv, priv->vport.vport, &port_attr);
877 : 0 : port_attr.ingress_meter_enable = enable;
878 : 0 : ret = zxdh_set_port_attr(priv, priv->vport.vport, &port_attr);
879 [ # # ]: 0 : if (ret) {
880 : 0 : PMD_DRV_LOG(ERR, "%s set port attr failed", __func__);
881 : 0 : return -ret;
882 : : }
883 : : } else {
884 : 0 : struct zxdh_msg_info msg_info = {0};
885 : : struct zxdh_port_attr_set_msg *attr_msg = &msg_info.data.port_attr_msg;
886 : :
887 : 0 : attr_msg->mode = dir_to_mtr_mode[dir];
888 : 0 : attr_msg->value = enable;
889 : 0 : zxdh_msg_head_build(priv, ZXDH_PORT_ATTRS_SET, &msg_info);
890 : 0 : ret = zxdh_vf_send_msg_to_pf(dev, &msg_info,
891 : : sizeof(struct zxdh_msg_head) + sizeof(struct zxdh_port_attr_set_msg),
892 : : NULL, 0);
893 : : }
894 [ # # ]: 0 : if (ret) {
895 : 0 : PMD_DRV_LOG(ERR, " port %d mtr enable failed", priv->port_id);
896 : 0 : return -rte_mtr_error_set(error, EEXIST,
897 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
898 : : "Meter enable failed.");
899 : : }
900 [ # # ]: 0 : if (dir == ZXDH_INGRESS)
901 : 0 : priv->i_mtr_en = !!enable;
902 : : else
903 : 0 : priv->e_mtr_en = !!enable;
904 : :
905 : : return ret;
906 : : }
907 : :
908 : : static void
909 : : zxdh_meter_build_actions(struct zxdh_meter_action *mtr_action,
910 : : struct rte_mtr_params *params)
911 : : {
912 : 0 : mtr_action->stats_mask = params->stats_mask;
913 : 0 : mtr_action->action[RTE_COLOR_RED] = ZXDH_MTR_POLICER_ACTION_DROP;
914 : : }
915 : :
916 : : static int
917 : 0 : zxdh_hw_plcrflow_config(struct rte_eth_dev *dev, uint16_t hw_flow_id,
918 : : struct zxdh_mtr_object *mtr, struct rte_mtr_error *error)
919 : : {
920 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
921 : : int ret = 0;
922 : :
923 [ # # ]: 0 : if (hw->is_pf) {
924 : 0 : uint64_t hw_profile_id = (uint64_t)mtr->profile->hw_profile_id;
925 : :
926 : 0 : ret = zxdh_np_stat_car_queue_cfg_set(hw->dev_id, CAR_A,
927 : 0 : hw_flow_id, 1, mtr->enable, hw_profile_id);
928 : :
929 [ # # ]: 0 : if (ret) {
930 : 0 : PMD_DRV_LOG(ERR, "dpp_stat_car_queue_cfg_set failed flowid %d profile id %d",
931 : : hw_flow_id, mtr->profile->hw_profile_id);
932 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
933 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS,
934 : : NULL, "Failed to bind plcr flow.");
935 : : ;
936 : : }
937 : : } else {
938 : 0 : struct zxdh_msg_info msg_info = {0};
939 : 0 : struct zxdh_msg_reply_info reply_info = {0};
940 : : struct zxdh_plcr_flow_cfg *zxdh_plcr_flow_cfg = &msg_info.data.zxdh_plcr_flow_cfg;
941 : :
942 : : zxdh_plcr_flow_cfg->car_type = CAR_A;
943 : 0 : zxdh_plcr_flow_cfg->flow_id = hw_flow_id;
944 : 0 : zxdh_plcr_flow_cfg->drop_flag = 1;
945 : 0 : zxdh_plcr_flow_cfg->plcr_en = mtr->enable;
946 : 0 : zxdh_plcr_flow_cfg->profile_id = mtr->profile->hw_profile_id;
947 : 0 : zxdh_msg_head_build(hw, ZXDH_PLCR_CAR_QUEUE_CFG_SET, &msg_info);
948 : 0 : ret = zxdh_vf_send_msg_to_pf(dev, &msg_info,
949 : : ZXDH_MSG_HEAD_LEN + sizeof(struct zxdh_plcr_flow_cfg),
950 : : &reply_info,
951 : : sizeof(struct zxdh_msg_reply_info));
952 [ # # ]: 0 : if (ret) {
953 : 0 : PMD_DRV_LOG(ERR,
954 : : "Failed msg: port 0x%x msg type ZXDH_PLCR_CAR_QUEUE_CFG_SET ",
955 : : hw->vport.vport);
956 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
957 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS,
958 : : NULL, "Failed to bind plcr flow.");
959 : : }
960 : : }
961 : :
962 : : return ret;
963 : : }
964 : :
965 : : static void
966 : 0 : zxdh_mtr_obj_free(struct rte_eth_dev *dev, struct zxdh_mtr_object *mtr_obj)
967 : : {
968 : 0 : struct zxdh_mtr_list *mtr_list = &zxdh_shared_data->mtr_list;
969 : 0 : struct rte_mempool *mtr_mp = zxdh_shared_data->mtr_mp;
970 : :
971 : 0 : PMD_DRV_LOG(INFO, "free port %d dir %d meter %d mtr refcnt:%d ....",
972 : : dev->data->port_id, mtr_obj->direction, mtr_obj->meter_id, mtr_obj->mtr_ref_cnt);
973 : :
974 [ # # ]: 0 : if (mtr_obj->policy)
975 : 0 : mtr_obj->policy->ref_cnt--;
976 : :
977 [ # # ]: 0 : if (mtr_obj->profile)
978 : 0 : mtr_obj->profile->ref_cnt--;
979 : :
980 [ # # ]: 0 : PMD_DRV_LOG(INFO,
981 : : "free port %d dir %d meter %d profile refcnt:%d ",
982 : : dev->data->port_id,
983 : : mtr_obj->direction,
984 : : mtr_obj->meter_id,
985 : : mtr_obj->profile ? mtr_obj->profile->ref_cnt : 0);
986 : :
987 [ # # ]: 0 : if (--mtr_obj->mtr_ref_cnt == 0) {
988 : 0 : PMD_DRV_LOG(INFO, "rm mtr %p refcnt:%d ....", mtr_obj, mtr_obj->mtr_ref_cnt);
989 [ # # # # ]: 0 : TAILQ_REMOVE(mtr_list, mtr_obj, next);
990 : 0 : MP_FREE_OBJ_FUNC(mtr_mp, mtr_obj);
991 : : }
992 : 0 : }
993 : :
994 : : static int
995 : : zxdh_mtr_flow_offlad(struct rte_eth_dev *dev,
996 : : struct zxdh_mtr_object *mtr,
997 : : struct rte_mtr_error *error)
998 : : {
999 : : uint16_t hw_flow_id;
1000 : :
1001 : 0 : hw_flow_id = mtr->vfid * 2 + ZXDH_PORT_MTR_FID_BASE + mtr->direction;
1002 : 0 : return zxdh_hw_plcrflow_config(dev, hw_flow_id, mtr, error);
1003 : : }
1004 : :
1005 : : static struct zxdh_mtr_object *
1006 : 0 : zxdh_mtr_find(uint32_t meter_id, uint16_t dpdk_portid)
1007 : : {
1008 : 0 : struct zxdh_mtr_list *mtr_list = &zxdh_shared_data->mtr_list;
1009 : : struct zxdh_mtr_object *mtr = NULL;
1010 : :
1011 [ # # ]: 0 : TAILQ_FOREACH(mtr, mtr_list, next) {
1012 : 0 : PMD_DRV_LOG(INFO,
1013 : : "mtrlist head %p mtr %p mtr->meterid %d to find mtrid %d",
1014 : : TAILQ_FIRST(mtr_list),
1015 : : mtr,
1016 : : mtr->meter_id,
1017 : : meter_id
1018 : : );
1019 : :
1020 [ # # # # ]: 0 : if (meter_id == mtr->meter_id && dpdk_portid == mtr->port_id)
1021 : 0 : return mtr;
1022 : : }
1023 : : return NULL;
1024 : : }
1025 : :
1026 : : static int
1027 : 0 : zxdh_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
1028 : : struct rte_mtr_params *params, int shared,
1029 : : struct rte_mtr_error *error)
1030 : : {
1031 : 0 : struct zxdh_hw *priv = dev->data->dev_private;
1032 : 0 : struct zxdh_mtr_list *mtr_list = &zxdh_shared_data->mtr_list;
1033 : : struct zxdh_mtr_object *mtr;
1034 : : struct zxdh_meter_profile *mtr_profile;
1035 : : struct zxdh_meter_policy *mtr_policy;
1036 : : uint8_t dir = 0;
1037 : : int ret;
1038 : :
1039 [ # # ]: 0 : if (shared)
1040 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
1041 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
1042 : : "Meter share is not supported");
1043 : :
1044 : 0 : ret = zxdh_meter_validate(meter_id, params, error);
1045 [ # # ]: 0 : if (ret)
1046 : : return ret;
1047 : :
1048 [ # # ]: 0 : if (zxdh_check_port_mtr_bind(dev, dir))
1049 : 0 : return -rte_mtr_error_set(error, EEXIST,
1050 : : RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
1051 : : "Meter object already bind to dev.");
1052 : :
1053 : 0 : mtr_profile = zxdh_mtr_profile_find_by_id(&zxdh_shared_data->meter_profile_list,
1054 : : params->meter_profile_id,
1055 : 0 : dev->data->port_id
1056 : : );
1057 : :
1058 [ # # ]: 0 : if (mtr_profile == NULL)
1059 : 0 : return -rte_mtr_error_set(error, EEXIST,
1060 [ # # ]: 0 : RTE_MTR_ERROR_TYPE_METER_PROFILE, ¶ms->meter_profile_id,
1061 : : "Meter profile object is not exists.");
1062 : 0 : mtr_profile->ref_cnt++;
1063 : 0 : mtr_policy = zxdh_mtr_policy_find_by_id(&zxdh_shared_data->mtr_policy_list,
1064 : 0 : params->meter_policy_id,
1065 : : dev->data->port_id);
1066 : :
1067 [ # # ]: 0 : if (mtr_policy == NULL) {
1068 : : ret = -rte_mtr_error_set(error, EEXIST,
1069 [ # # ]: 0 : RTE_MTR_ERROR_TYPE_METER_PROFILE, ¶ms->meter_policy_id,
1070 : : "Meter policy object is not exists.");
1071 : 0 : mtr_profile->ref_cnt--;
1072 : 0 : return ret;
1073 : : }
1074 : 0 : mtr_policy->ref_cnt++;
1075 : :
1076 : 0 : mtr = zxdh_mtr_obj_alloc(zxdh_shared_data->mtr_mp);
1077 [ # # ]: 0 : if (mtr == NULL) {
1078 : : ret = -rte_mtr_error_set(error, ENOMEM,
1079 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
1080 : : "Memory alloc failed for meter.");
1081 : 0 : mtr_policy->ref_cnt--;
1082 : 0 : mtr_profile->ref_cnt--;
1083 : 0 : return ret;
1084 : : }
1085 : : memset(mtr, 0, sizeof(struct zxdh_mtr_object));
1086 : :
1087 : 0 : mtr->meter_id = meter_id;
1088 : 0 : mtr->profile = mtr_profile;
1089 : :
1090 : : zxdh_meter_build_actions(&mtr->mtr_action, params);
1091 : 0 : TAILQ_INSERT_TAIL(mtr_list, mtr, next);
1092 : 0 : mtr->enable = !!params->meter_enable;
1093 : 0 : mtr->shared = !!shared;
1094 : 0 : mtr->mtr_ref_cnt++;
1095 : 0 : mtr->vfid = priv->vfid;
1096 : 0 : mtr->port_id = dev->data->port_id;
1097 : 0 : mtr->policy = mtr_policy;
1098 : 0 : mtr->direction = !!dir;
1099 [ # # ]: 0 : if (params->meter_enable) {
1100 : : ret = zxdh_mtr_flow_offlad(dev, mtr, error);
1101 [ # # ]: 0 : if (ret)
1102 : 0 : goto error;
1103 : : }
1104 : 0 : ret = zxdh_set_mtr_enable(dev, mtr->direction, 1, error);
1105 [ # # ]: 0 : if (ret)
1106 : 0 : goto error;
1107 : : return ret;
1108 : 0 : error:
1109 : 0 : zxdh_mtr_obj_free(dev, mtr);
1110 : 0 : return ret;
1111 : : }
1112 : :
1113 : : static int
1114 : 0 : zxdh_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,
1115 : : struct rte_mtr_error *error)
1116 : : {
1117 : : struct zxdh_mtr_object *mtr;
1118 : :
1119 : 0 : mtr = zxdh_mtr_find(meter_id, dev->data->port_id);
1120 [ # # ]: 0 : if (mtr == NULL)
1121 : 0 : return -rte_mtr_error_set(error, EEXIST,
1122 : : RTE_MTR_ERROR_TYPE_MTR_ID,
1123 : : NULL, "Meter object id not valid.");
1124 : 0 : mtr->enable = 0;
1125 : 0 : zxdh_set_mtr_enable(dev, mtr->direction, 0, error);
1126 : :
1127 [ # # ]: 0 : if (zxdh_mtr_flow_offlad(dev, mtr, error))
1128 : : return -1;
1129 : :
1130 : 0 : zxdh_mtr_obj_free(dev, mtr);
1131 : 0 : return 0;
1132 : : }
1133 : :
1134 : : void
1135 : 0 : zxdh_mtr_policy_res_free(struct rte_mempool *mtr_policy_mp, struct zxdh_meter_policy *policy)
1136 : : {
1137 : 0 : PMD_DRV_LOG(INFO, "to free policy %d ref %d ", policy->policy_id, policy->ref_cnt);
1138 : :
1139 [ # # ]: 0 : if (--policy->ref_cnt == 0) {
1140 [ # # # # ]: 0 : TAILQ_REMOVE(&zxdh_shared_data->mtr_policy_list, policy, next);
1141 : 0 : MP_FREE_OBJ_FUNC(mtr_policy_mp, policy);
1142 : : }
1143 : 0 : }
1144 : :
1145 : : static int
1146 : 0 : zxdh_mtr_stats_read(struct rte_eth_dev *dev,
1147 : : uint32_t mtr_id,
1148 : : struct rte_mtr_stats *stats,
1149 : : uint64_t *stats_mask,
1150 : : int clear,
1151 : : struct rte_mtr_error *error)
1152 : : {
1153 : 0 : struct zxdh_mtr_stats mtr_stat = {0};
1154 : : struct zxdh_mtr_object *mtr = NULL;
1155 : : int ret = 0;
1156 : : /* Meter object must exist. */
1157 : 0 : mtr = zxdh_mtr_find(mtr_id, dev->data->port_id);
1158 [ # # ]: 0 : if (mtr == NULL)
1159 : 0 : return -rte_mtr_error_set(error, ENOENT,
1160 : : RTE_MTR_ERROR_TYPE_MTR_ID,
1161 : : NULL, "Meter object id not valid.");
1162 : 0 : *stats_mask = RTE_MTR_STATS_N_BYTES_DROPPED | RTE_MTR_STATS_N_PKTS_DROPPED;
1163 : : memset(&mtr_stat, 0, sizeof(mtr_stat));
1164 : 0 : ret = zxdh_mtr_hw_counter_query(dev, clear, mtr->direction, &mtr_stat, error);
1165 [ # # ]: 0 : if (ret)
1166 [ # # ]: 0 : goto error;
1167 : 0 : stats->n_bytes_dropped = mtr_stat.n_bytes_dropped;
1168 : 0 : stats->n_pkts_dropped = mtr_stat.n_pkts_dropped;
1169 : :
1170 : 0 : return 0;
1171 : : error:
1172 : 0 : return -rte_mtr_error_set(error, ret, RTE_MTR_ERROR_TYPE_STATS, NULL,
1173 : : "Failed to read meter drop counters.");
1174 : : }
1175 : :
1176 : : static const struct rte_mtr_ops zxdh_mtr_ops = {
1177 : : .capabilities_get = zxdh_meter_cap_get,
1178 : : .meter_profile_add = zxdh_meter_profile_add,
1179 : : .meter_profile_delete = zxdh_meter_profile_delete,
1180 : : .create = zxdh_meter_create,
1181 : : .destroy = zxdh_meter_destroy,
1182 : : .stats_read = zxdh_mtr_stats_read,
1183 : : .meter_policy_add = zxdh_meter_policy_add,
1184 : : .meter_policy_delete = zxdh_meter_policy_delete,
1185 : : };
1186 : :
1187 : : int
1188 : 0 : zxdh_meter_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
1189 : : {
1190 : 0 : *(const struct rte_mtr_ops **)arg = &zxdh_mtr_ops;
1191 : 0 : return 0;
1192 : : }
1193 : :
1194 : : void
1195 : 0 : zxdh_mtr_release(struct rte_eth_dev *dev)
1196 : : {
1197 : 0 : struct zxdh_hw *priv = dev->data->dev_private;
1198 : : struct zxdh_meter_profile *profile;
1199 : 0 : struct rte_mtr_error error = {0};
1200 : : struct zxdh_mtr_object *mtr_obj;
1201 : :
1202 [ # # ]: 0 : RTE_TAILQ_FOREACH(mtr_obj, &zxdh_shared_data->mtr_list, next) {
1203 [ # # ]: 0 : if (mtr_obj->port_id == priv->port_id)
1204 : 0 : zxdh_mtr_obj_free(dev, mtr_obj);
1205 : : }
1206 : :
1207 : :
1208 [ # # ]: 0 : RTE_TAILQ_FOREACH(profile, &zxdh_shared_data->meter_profile_list, next) {
1209 [ # # ]: 0 : if (profile->dpdk_port_id == priv->port_id)
1210 : 0 : zxdh_mtr_profile_res_free(dev,
1211 : 0 : zxdh_shared_data->mtr_profile_mp,
1212 : : profile,
1213 : : &error
1214 : : );
1215 : : }
1216 : :
1217 : : struct zxdh_meter_policy *policy;
1218 : :
1219 [ # # ]: 0 : RTE_TAILQ_FOREACH(policy, &zxdh_shared_data->mtr_policy_list, next) {
1220 [ # # ]: 0 : if (policy->dpdk_port_id == priv->port_id)
1221 : 0 : zxdh_mtr_policy_res_free(zxdh_shared_data->mtr_policy_mp, policy);
1222 : : }
1223 : 0 : }
|