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(hw->dev_id, 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(hw->dev_id, 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 : uint8_t zxdh_msg_reply_info[ZXDH_ST_SZ_BYTES(msg_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 : : zxdh_msg_reply_info, ZXDH_ST_SZ_BYTES(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 : uint8_t zxdh_msg_reply_info[ZXDH_ST_SZ_BYTES(msg_reply_info)] = {0};
361 : : struct zxdh_plcr_profile_add *zxdh_plcr_profile_add =
362 : : &msg_info.data.zxdh_plcr_profile_add;
363 : : void *reply_body_addr =
364 : : ZXDH_ADDR_OF(msg_reply_info, zxdh_msg_reply_info, reply_body);
365 : : void *mtr_profile_info_addr =
366 : : ZXDH_ADDR_OF(msg_reply_body, reply_body_addr, mtr_profile_info);
367 : :
368 : : zxdh_plcr_profile_add->car_type = CAR_A;
369 : 0 : zxdh_msg_head_build(hw, ZXDH_PLCR_CAR_PROFILE_ID_ADD, &msg_info);
370 : 0 : ret = zxdh_vf_send_msg_to_pf(dev, &msg_info,
371 : : ZXDH_MSG_HEAD_LEN + sizeof(struct zxdh_plcr_profile_add),
372 : : zxdh_msg_reply_info, ZXDH_ST_SZ_BYTES(msg_reply_info));
373 : :
374 [ # # ]: 0 : if (ret) {
375 : 0 : PMD_DRV_LOG(ERR,
376 : : "Failed to send msg: port 0x%x msg type ZXDH_PLCR_CAR_PROFILE_ID_ADD ",
377 : : hw->vport.vport);
378 : :
379 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
380 : : RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL,
381 : : "Meter offload alloc profile id msg failed ");
382 : : }
383 : 0 : *hw_profile_id = ZXDH_GET(mtr_profile_info, mtr_profile_info_addr, profile_id);
384 [ # # ]: 0 : if (*hw_profile_id == ZXDH_HW_PROFILE_MAX) {
385 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
386 : : RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL,
387 : : "Meter offload alloc profile id invalid ");
388 : : }
389 : : }
390 : :
391 : : return ret;
392 : : }
393 : :
394 : : int
395 : 0 : zxdh_hw_profile_unref(struct rte_eth_dev *dev,
396 : : uint8_t car_type,
397 : : uint16_t hw_profile_id,
398 : : struct rte_mtr_error *error)
399 : : {
400 [ # # ]: 0 : if (hw_profile_id >= ZXDH_HW_PROFILE_MAX)
401 : : return -1;
402 : :
403 : : rte_spinlock_lock(&g_mtr_res.hw_plcr_res_lock);
404 [ # # ]: 0 : if (g_mtr_res.hw_profile_refcnt[hw_profile_id] == 0) {
405 : 0 : PMD_DRV_LOG(ERR, "del hw profile id %d but ref 0", hw_profile_id);
406 : : rte_spinlock_unlock(&g_mtr_res.hw_plcr_res_lock);
407 : 0 : return -1;
408 : : }
409 [ # # ]: 0 : if (--g_mtr_res.hw_profile_refcnt[hw_profile_id] == 0) {
410 : 0 : PMD_DRV_LOG(INFO, "del hw profile id %d ", hw_profile_id);
411 : 0 : zxdh_hw_profile_free(dev, car_type, hw_profile_id, error);
412 : : }
413 : : rte_spinlock_unlock(&g_mtr_res.hw_plcr_res_lock);
414 : 0 : return 0;
415 : : }
416 : :
417 : : static int
418 : 0 : zxdh_mtr_hw_counter_query(struct rte_eth_dev *dev,
419 : : bool clear,
420 : : bool dir,
421 : : struct zxdh_mtr_stats *mtr_stats,
422 : : struct rte_mtr_error *error)
423 : : {
424 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
425 : : int ret = 0;
426 : :
427 [ # # ]: 0 : if (hw->is_pf) {
428 : 0 : ret = zxdh_mtr_stats_get(dev, dir, mtr_stats);
429 [ # # ]: 0 : if (ret) {
430 : 0 : PMD_DRV_LOG(ERR,
431 : : "ZXDH_PORT_METER_STAT_GET port %u dir %d failed",
432 : : hw->vport.vport,
433 : : dir);
434 : :
435 : 0 : return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_STATS, NULL, "Failed to bind plcr flow.");
436 : : }
437 : : } else { /* send msg to pf */
438 : 0 : struct zxdh_msg_info msg_info = {0};
439 : 0 : uint8_t zxdh_msg_reply_info[ZXDH_ST_SZ_BYTES(msg_reply_info)] = {0};
440 : : struct zxdh_mtr_stats_query *zxdh_mtr_stats_query =
441 : : &msg_info.data.zxdh_mtr_stats_query;
442 : :
443 : 0 : zxdh_mtr_stats_query->direction = dir;
444 : 0 : zxdh_mtr_stats_query->is_clr = !!clear;
445 : 0 : zxdh_msg_head_build(hw, ZXDH_PORT_METER_STAT_GET, &msg_info);
446 : 0 : ret = zxdh_vf_send_msg_to_pf(dev,
447 : : &msg_info,
448 : : sizeof(msg_info),
449 : : zxdh_msg_reply_info,
450 : : ZXDH_ST_SZ_BYTES(msg_reply_info));
451 : :
452 [ # # ]: 0 : if (ret) {
453 : 0 : PMD_DRV_LOG(ERR,
454 : : "Failed to send msg: port 0x%x msg type ZXDH_PORT_METER_STAT_GET",
455 : : hw->vport.vport);
456 : 0 : return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_STATS, NULL, "Meter offload alloc profile failed");
457 : : }
458 : : void *reply_body_addr =
459 : : ZXDH_ADDR_OF(msg_reply_info, zxdh_msg_reply_info, reply_body);
460 : : void *hw_mtr_stats_addr =
461 : : ZXDH_ADDR_OF(msg_reply_body, reply_body_addr, hw_mtr_stats);
462 : : struct zxdh_mtr_stats *hw_mtr_stats = (struct zxdh_mtr_stats *)hw_mtr_stats_addr;
463 : :
464 : 0 : mtr_stats->n_bytes_dropped = hw_mtr_stats->n_bytes_dropped;
465 : 0 : mtr_stats->n_pkts_dropped = hw_mtr_stats->n_pkts_dropped;
466 : : }
467 : :
468 : : return ret;
469 : : }
470 : :
471 : :
472 : : static void
473 : 0 : zxdh_mtr_profile_res_free(struct rte_eth_dev *dev,
474 : : struct rte_mempool *mtr_profile_mp,
475 : : struct zxdh_meter_profile *meter_profile,
476 : : struct rte_mtr_error *error)
477 : : {
478 [ # # ]: 0 : if (meter_profile->ref_cnt == 0) {
479 : 0 : ZXDH_MP_FREE_OBJ_FUNC(mtr_profile_mp, meter_profile);
480 : 0 : return;
481 : : }
482 [ # # ]: 0 : if (meter_profile->ref_cnt == 1) {
483 : 0 : meter_profile->ref_cnt--;
484 : 0 : zxdh_hw_profile_unref(dev, CAR_A, meter_profile->hw_profile_id, error);
485 : :
486 [ # # # # ]: 0 : TAILQ_REMOVE(&zxdh_shared_data->meter_profile_list, meter_profile, next);
487 : 0 : ZXDH_MP_FREE_OBJ_FUNC(mtr_profile_mp, meter_profile);
488 : : } else {
489 : 0 : PMD_DRV_LOG(INFO,
490 : : "profile %d ref %d is busy",
491 : : meter_profile->meter_profile_id,
492 : : meter_profile->ref_cnt);
493 : : }
494 : : }
495 : :
496 : : static uint16_t
497 : 0 : zxdh_check_hw_profile_exist(struct zxdh_mtr_profile_list *mpl,
498 : : struct rte_mtr_meter_profile *profile,
499 : : uint16_t hw_profile_owner_vport)
500 : : {
501 : : struct zxdh_meter_profile *mp;
502 : :
503 [ # # ]: 0 : TAILQ_FOREACH(mp, mpl, next) {
504 [ # # ]: 0 : if ((memcmp(profile, &mp->profile, sizeof(struct rte_mtr_meter_profile)) == 0) &&
505 [ # # ]: 0 : hw_profile_owner_vport == mp->hw_profile_owner_vport) {
506 : 0 : return mp->hw_profile_id;
507 : : }
508 : : }
509 : : return ZXDH_HW_PROFILE_MAX;
510 : : }
511 : :
512 : : static void
513 : 0 : zxdh_plcr_param_build(struct rte_mtr_meter_profile *profile,
514 : : void *plcr_param, uint16_t profile_id)
515 : : {
516 [ # # ]: 0 : if (profile->packet_mode == 0) {
517 : : ZXDH_STAT_CAR_PROFILE_CFG_T *p_car_byte_profile_cfg =
518 : : (ZXDH_STAT_CAR_PROFILE_CFG_T *)plcr_param;
519 : :
520 : 0 : p_car_byte_profile_cfg->profile_id = profile_id;
521 : 0 : p_car_byte_profile_cfg->pkt_sign = profile->packet_mode;
522 : 0 : p_car_byte_profile_cfg->cf = ZXDH_PLCR_CF_UNOVERFLOW;
523 : 0 : p_car_byte_profile_cfg->cm = ZXDH_PLCR_CM_BLIND;
524 [ # # ]: 0 : if (profile->alg == RTE_MTR_SRTCM_RFC2697) {
525 : 0 : p_car_byte_profile_cfg->cd = ZXDH_PLCR_CD_SRTCM;
526 : 0 : p_car_byte_profile_cfg->cir = profile->srtcm_rfc2697.cir * 8 / 1000;
527 : 0 : p_car_byte_profile_cfg->cbs = profile->srtcm_rfc2697.cbs;
528 : 0 : p_car_byte_profile_cfg->ebs = profile->srtcm_rfc2697.ebs;
529 : : } else {
530 : 0 : p_car_byte_profile_cfg->cd = ZXDH_PLCR_CD_TRTCM;
531 : 0 : p_car_byte_profile_cfg->cir = profile->trtcm_rfc2698.cir * 8 / 1000;
532 : 0 : p_car_byte_profile_cfg->cbs = profile->trtcm_rfc2698.cbs;
533 : 0 : p_car_byte_profile_cfg->eir = (profile->trtcm_rfc2698.pir -
534 : 0 : profile->trtcm_rfc2698.cir) * 8 / 1000;
535 : 0 : p_car_byte_profile_cfg->ebs =
536 : 0 : profile->trtcm_rfc2698.pbs - profile->trtcm_rfc2698.cbs;
537 : : }
538 : : } else {
539 : : ZXDH_STAT_CAR_PKT_PROFILE_CFG_T *p_car_pkt_profile_cfg =
540 : : (ZXDH_STAT_CAR_PKT_PROFILE_CFG_T *)plcr_param;
541 : :
542 : 0 : p_car_pkt_profile_cfg->profile_id = profile_id;
543 : 0 : p_car_pkt_profile_cfg->pkt_sign = profile->packet_mode;
544 : :
545 [ # # ]: 0 : if (profile->alg == RTE_MTR_SRTCM_RFC2697) {
546 : 0 : p_car_pkt_profile_cfg->cir = profile->srtcm_rfc2697.cir;
547 : 0 : p_car_pkt_profile_cfg->cbs = profile->srtcm_rfc2697.cbs;
548 : : } else {
549 : 0 : p_car_pkt_profile_cfg->cir = profile->trtcm_rfc2698.cir;
550 : 0 : p_car_pkt_profile_cfg->cbs = profile->trtcm_rfc2698.cbs;
551 : : }
552 : : }
553 : 0 : }
554 : :
555 : : static int
556 : 0 : zxdh_hw_profile_config_direct(struct rte_eth_dev *dev __rte_unused,
557 : : ZXDH_PROFILE_TYPE car_type,
558 : : uint16_t hw_profile_id,
559 : : struct zxdh_meter_profile *mp,
560 : : struct rte_mtr_error *error)
561 : : {
562 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
563 : 0 : int ret = zxdh_np_car_profile_cfg_set(hw->dev_id,
564 : 0 : mp->hw_profile_owner_vport,
565 : 0 : car_type, mp->profile.packet_mode,
566 : 0 : (uint32_t)hw_profile_id, &mp->plcr_param);
567 [ # # ]: 0 : if (ret) {
568 : 0 : PMD_DRV_LOG(ERR, " config hw profile %u failed", hw_profile_id);
569 : 0 : return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
570 : : "Meter offload cfg profile failed");
571 : : }
572 : :
573 : : return 0;
574 : : }
575 : :
576 : 0 : static int zxdh_hw_profile_config(struct rte_eth_dev *dev, uint16_t hw_profile_id,
577 : : struct zxdh_meter_profile *mp, struct rte_mtr_error *error)
578 : : {
579 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
580 : : int ret = 0;
581 : :
582 [ # # ]: 0 : if (hw->is_pf) {
583 : 0 : ret = zxdh_hw_profile_config_direct(dev, CAR_A, hw_profile_id, mp, error);
584 : : } else {
585 : 0 : struct zxdh_msg_info msg_info = {0};
586 : 0 : uint8_t zxdh_msg_reply_info[ZXDH_ST_SZ_BYTES(msg_reply_info)] = {0};
587 : : struct zxdh_plcr_profile_cfg *zxdh_plcr_profile_cfg =
588 : : &msg_info.data.zxdh_plcr_profile_cfg;
589 : :
590 : : zxdh_plcr_profile_cfg->car_type = CAR_A;
591 : 0 : zxdh_plcr_profile_cfg->packet_mode = mp->profile.packet_mode;
592 : 0 : zxdh_plcr_profile_cfg->hw_profile_id = hw_profile_id;
593 : : rte_memcpy(&zxdh_plcr_profile_cfg->plcr_param,
594 [ # # ]: 0 : &mp->plcr_param,
595 : : sizeof(zxdh_plcr_profile_cfg->plcr_param));
596 : :
597 : 0 : zxdh_msg_head_build(hw, ZXDH_PLCR_CAR_PROFILE_CFG_SET, &msg_info);
598 : 0 : ret = zxdh_vf_send_msg_to_pf(dev,
599 : : &msg_info,
600 : : ZXDH_MSG_HEAD_LEN + sizeof(struct zxdh_plcr_profile_cfg),
601 : : zxdh_msg_reply_info,
602 : : ZXDH_ST_SZ_BYTES(msg_reply_info)
603 : : );
604 [ # # ]: 0 : if (ret) {
605 : 0 : PMD_DRV_LOG(ERR,
606 : : "Failed msg: port 0x%x msg type ZXDH_PLCR_CAR_PROFILE_CFG_SET ",
607 : : hw->vport.vport);
608 : :
609 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
610 : : RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
611 : : "Meter offload cfg profile failed ");
612 : : }
613 : : }
614 : :
615 : : return ret;
616 : : }
617 : :
618 : : static int
619 : 0 : zxdh_mtr_profile_offload(struct rte_eth_dev *dev, struct zxdh_meter_profile *mp,
620 : : struct rte_mtr_meter_profile *profile, struct rte_mtr_error *error)
621 : : {
622 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
623 : 0 : uint16_t hw_profile_owner_vport = ZXDH_GET_OWNER_PF_VPORT(hw->vport.vport);
624 : :
625 : 0 : mp->hw_profile_owner_vport = hw_profile_owner_vport;
626 : 0 : uint64_t hw_profile_id =
627 : 0 : zxdh_check_hw_profile_exist(&zxdh_shared_data->meter_profile_list,
628 : : profile,
629 : : hw_profile_owner_vport);
630 : :
631 [ # # ]: 0 : if (hw_profile_id == ZXDH_HW_PROFILE_MAX) {
632 : 0 : uint32_t ret = zxdh_hw_profile_alloc(dev, &hw_profile_id, error);
633 : :
634 [ # # ]: 0 : if (ret) {
635 : 0 : PMD_DRV_LOG(ERR, "hw_profile alloc fail");
636 : 0 : return ret;
637 : : }
638 : :
639 : 0 : zxdh_plcr_param_build(profile, &mp->plcr_param, hw_profile_id);
640 : 0 : ret = zxdh_hw_profile_config(dev, hw_profile_id, mp, error);
641 [ # # ]: 0 : if (ret) {
642 : 0 : PMD_DRV_LOG(ERR, "zxdh_hw_profile_config fail");
643 : : hw_profile_id = ZXDH_HW_PROFILE_MAX;
644 : 0 : return ret;
645 : : }
646 : : }
647 : 0 : zxdh_hw_profile_ref(hw_profile_id);
648 : 0 : mp->hw_profile_id = hw_profile_id;
649 : :
650 : 0 : return 0;
651 : : }
652 : :
653 : : static int
654 : 0 : zxdh_meter_profile_add(struct rte_eth_dev *dev,
655 : : uint32_t meter_profile_id,
656 : : struct rte_mtr_meter_profile *profile,
657 : : struct rte_mtr_error *error)
658 : : {
659 : : struct zxdh_meter_profile *mp;
660 : : int ret;
661 : :
662 : 0 : ret = zxdh_mtr_profile_validate(meter_profile_id, profile, error);
663 [ # # ]: 0 : if (ret)
664 : 0 : return -rte_mtr_error_set(error, ENOMEM,
665 : : RTE_MTR_ERROR_TYPE_METER_PROFILE,
666 : : NULL, "meter profile validate failed");
667 : 0 : mp = zxdh_mtr_profile_find_by_id(&zxdh_shared_data->meter_profile_list,
668 : : meter_profile_id,
669 : 0 : dev->data->port_id);
670 : :
671 [ # # ]: 0 : if (mp)
672 : 0 : return -rte_mtr_error_set(error, EEXIST,
673 : : RTE_MTR_ERROR_TYPE_METER_PROFILE,
674 : : NULL,
675 : : "meter profile is exists");
676 : :
677 : 0 : mp = zxdh_mtr_profile_res_alloc(zxdh_shared_data->mtr_profile_mp);
678 [ # # ]: 0 : if (mp == NULL)
679 : 0 : return -rte_mtr_error_set(error, ENOMEM,
680 : : RTE_MTR_ERROR_TYPE_METER_PROFILE,
681 : : NULL, "Meter profile res memory alloc failed.");
682 : :
683 : : memset(mp, 0, sizeof(struct zxdh_meter_profile));
684 : :
685 : 0 : mp->meter_profile_id = meter_profile_id;
686 : 0 : mp->dpdk_port_id = dev->data->port_id;
687 : 0 : mp->hw_profile_id = UINT16_MAX;
688 [ # # ]: 0 : rte_memcpy(&mp->profile, profile, sizeof(struct rte_mtr_meter_profile));
689 : :
690 : 0 : ret = zxdh_mtr_profile_offload(dev, mp, profile, error);
691 [ # # ]: 0 : if (ret) {
692 : 0 : PMD_DRV_LOG(ERR,
693 : : " port %d profile id %d offload failed ",
694 : : dev->data->port_id,
695 : : meter_profile_id);
696 : 0 : goto error;
697 : : }
698 : :
699 : 0 : TAILQ_INSERT_TAIL(&zxdh_shared_data->meter_profile_list, mp, next);
700 : 0 : PMD_DRV_LOG(DEBUG,
701 : : "add profile id %d mp %p mp->ref_cnt %d",
702 : : meter_profile_id,
703 : : mp,
704 : : mp->ref_cnt);
705 : :
706 : 0 : mp->ref_cnt++;
707 : :
708 : 0 : return 0;
709 : : error:
710 : 0 : zxdh_mtr_profile_res_free(dev, zxdh_shared_data->mtr_profile_mp, mp, error);
711 : 0 : return ret;
712 : : }
713 : :
714 : : static int
715 : 0 : zxdh_meter_profile_delete(struct rte_eth_dev *dev,
716 : : uint32_t meter_profile_id,
717 : : struct rte_mtr_error *error)
718 : : {
719 : : struct zxdh_meter_profile *mp;
720 : :
721 : 0 : mp = zxdh_mtr_profile_find_by_id(&zxdh_shared_data->meter_profile_list,
722 : : meter_profile_id,
723 : 0 : dev->data->port_id);
724 : :
725 [ # # ]: 0 : if (mp == NULL) {
726 : 0 : PMD_DRV_LOG(ERR, "del profile id %d unfind ", meter_profile_id);
727 : 0 : return -rte_mtr_error_set(error, ENOENT,
728 : : RTE_MTR_ERROR_TYPE_METER_PROFILE,
729 : : &meter_profile_id,
730 : : "Meter profile id is not exists.");
731 : : }
732 : 0 : zxdh_mtr_profile_res_free(dev, zxdh_shared_data->mtr_profile_mp, mp, error);
733 : :
734 : 0 : return 0;
735 : : }
736 : :
737 : : static int
738 : 0 : zxdh_meter_policy_add(struct rte_eth_dev *dev,
739 : : uint32_t policy_id,
740 : : struct rte_mtr_meter_policy_params *policy,
741 : : struct rte_mtr_error *error)
742 : : {
743 : : int ret = 0;
744 : : struct zxdh_meter_policy *mtr_policy = NULL;
745 : :
746 [ # # ]: 0 : if (policy_id >= ZXDH_MAX_POLICY_NUM)
747 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
748 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
749 : : NULL, "policy ID is invalid. ");
750 : 0 : mtr_policy = zxdh_mtr_policy_find_by_id(&zxdh_shared_data->mtr_policy_list,
751 : : policy_id,
752 : 0 : dev->data->port_id);
753 : :
754 [ # # ]: 0 : if (mtr_policy)
755 : 0 : return -rte_mtr_error_set(error, EEXIST,
756 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
757 : : NULL, "policy ID exists. ");
758 : : ret = zxdh_policy_validate_actions(policy->actions, error);
759 : : if (ret) {
760 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
761 : : RTE_MTR_ERROR_TYPE_METER_POLICY,
762 : : NULL, " only supports def action.");
763 : : }
764 : :
765 : 0 : mtr_policy = zxdh_mtr_policy_res_alloc(zxdh_shared_data->mtr_policy_mp);
766 [ # # ]: 0 : if (mtr_policy == NULL) {
767 : 0 : return -rte_mtr_error_set(error, ENOMEM,
768 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
769 : : NULL, "Meter policy res memory alloc failed.");
770 : : }
771 : : /* Fill profile info. */
772 : : memset(mtr_policy, 0, sizeof(struct zxdh_meter_policy));
773 : 0 : mtr_policy->policy_id = policy_id;
774 : 0 : mtr_policy->dpdk_port_id = dev->data->port_id;
775 [ # # ]: 0 : rte_memcpy(&mtr_policy->policy, policy, sizeof(struct rte_mtr_meter_policy_params));
776 : : /* Add to list. */
777 : 0 : TAILQ_INSERT_TAIL(&zxdh_shared_data->mtr_policy_list, mtr_policy, next);
778 : 0 : mtr_policy->ref_cnt++;
779 : 0 : PMD_DRV_LOG(INFO, "allic policy id %d ok %p ", mtr_policy->policy_id, mtr_policy);
780 : 0 : return 0;
781 : : }
782 : :
783 : : static int
784 : 0 : zxdh_meter_policy_delete(struct rte_eth_dev *dev,
785 : : uint32_t policy_id,
786 : : struct rte_mtr_error *error)
787 : : {
788 : : struct zxdh_meter_policy *mtr_policy = NULL;
789 : :
790 [ # # ]: 0 : if (policy_id >= ZXDH_MAX_POLICY_NUM)
791 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
792 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
793 : : NULL, "policy ID is invalid. ");
794 : 0 : mtr_policy = zxdh_mtr_policy_find_by_id(&zxdh_shared_data->mtr_policy_list,
795 : 0 : policy_id, dev->data->port_id);
796 : :
797 [ # # # # ]: 0 : if (mtr_policy && mtr_policy->ref_cnt == 1) {
798 [ # # ]: 0 : TAILQ_REMOVE(&zxdh_shared_data->mtr_policy_list, mtr_policy, next);
799 [ # # ]: 0 : MP_FREE_OBJ_FUNC(zxdh_shared_data->mtr_policy_mp, mtr_policy);
800 : : } else {
801 [ # # ]: 0 : if (mtr_policy) {
802 : 0 : PMD_DRV_LOG(INFO,
803 : : " policy id %d ref %d is busy ",
804 : : mtr_policy->policy_id,
805 : : mtr_policy->ref_cnt);
806 : : } else {
807 : 0 : PMD_DRV_LOG(ERR, " policy id %d is not exist ", policy_id);
808 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
809 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
810 : : NULL, "policy ID is not exist. ");
811 : : }
812 : : }
813 : : return 0;
814 : : }
815 : :
816 : : static int
817 : 0 : zxdh_meter_validate(uint32_t meter_id,
818 : : struct rte_mtr_params *params,
819 : : struct rte_mtr_error *error)
820 : : {
821 : : /* Meter params must not be NULL. */
822 [ # # ]: 0 : if (params == NULL)
823 : 0 : return -rte_mtr_error_set(error, EINVAL,
824 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS,
825 : : NULL, "Meter object params null.");
826 : : /* Previous meter color is not supported. */
827 [ # # ]: 0 : if (params->use_prev_mtr_color)
828 : 0 : return -rte_mtr_error_set(error, EINVAL,
829 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS,
830 : : NULL,
831 : : "Previous meter color not supported");
832 [ # # ]: 0 : if (meter_id > ZXDH_MAX_MTR_NUM / 2) {
833 : 0 : return -rte_mtr_error_set(error, EINVAL,
834 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS,
835 : : NULL,
836 : : " meter id exceed 1024 unsupported");
837 : : }
838 : : return 0;
839 : : }
840 : :
841 : : static int
842 : 0 : zxdh_check_port_mtr_bind(struct rte_eth_dev *dev, uint32_t dir)
843 : : {
844 : : struct zxdh_mtr_object *mtr_obj = NULL;
845 : :
846 [ # # ]: 0 : TAILQ_FOREACH(mtr_obj, &zxdh_shared_data->mtr_list, next) {
847 [ # # ]: 0 : if (mtr_obj->direction != dir)
848 : 0 : continue;
849 [ # # ]: 0 : if (mtr_obj->port_id == dev->data->port_id) {
850 : 0 : PMD_DRV_LOG(INFO,
851 : : "port %d dir %d already bind meter %d",
852 : : dev->data->port_id,
853 : : dir,
854 : : mtr_obj->meter_id);
855 : 0 : return -1;
856 : : }
857 : : }
858 : :
859 : : return 0;
860 : : }
861 : :
862 : : static struct zxdh_mtr_object
863 : 0 : *zxdh_mtr_obj_alloc(struct rte_mempool *mtr_mp)
864 : : {
865 [ # # ]: 0 : struct zxdh_mtr_object *mtr_obj = NULL;
866 : :
867 [ # # ]: 0 : if (ZXDH_MP_ALLOC_OBJ_FUNC(mtr_mp, mtr_obj) != 0)
868 : : return NULL;
869 : :
870 : 0 : return mtr_obj;
871 : : }
872 : :
873 : : static uint32_t dir_to_mtr_mode[] = {
874 : : ZXDH_PORT_EGRESS_METER_EN_OFF_FLAG,
875 : : ZXDH_PORT_INGRESS_METER_EN_OFF_FLAG
876 : : };
877 : :
878 : : static int
879 : 0 : zxdh_set_mtr_enable(struct rte_eth_dev *dev, uint8_t dir, bool enable, struct rte_mtr_error *error)
880 : : {
881 : 0 : struct zxdh_hw *priv = dev->data->dev_private;
882 : 0 : struct zxdh_port_attr_table port_attr = {0};
883 : : int ret = 0;
884 : :
885 [ # # ]: 0 : if (priv->is_pf) {
886 : 0 : ret = zxdh_get_port_attr(priv, priv->vport.vport, &port_attr);
887 : 0 : port_attr.egress_meter_enable = enable;
888 : 0 : ret = zxdh_set_port_attr(priv, priv->vport.vport, &port_attr);
889 [ # # ]: 0 : if (ret) {
890 : 0 : PMD_DRV_LOG(ERR, "%s set port attr failed", __func__);
891 : 0 : return -ret;
892 : : }
893 : : } else {
894 : 0 : struct zxdh_msg_info msg_info = {0};
895 : : struct zxdh_port_attr_set_msg *attr_msg = &msg_info.data.port_attr_msg;
896 : :
897 : 0 : attr_msg->mode = dir_to_mtr_mode[dir];
898 : 0 : attr_msg->value = enable;
899 : 0 : zxdh_msg_head_build(priv, ZXDH_PORT_ATTRS_SET, &msg_info);
900 : 0 : ret = zxdh_vf_send_msg_to_pf(dev, &msg_info,
901 : : sizeof(struct zxdh_msg_head) + sizeof(struct zxdh_port_attr_set_msg),
902 : : NULL, 0);
903 : : }
904 [ # # ]: 0 : if (ret) {
905 : 0 : PMD_DRV_LOG(ERR, " port %d mtr enable failed", priv->port_id);
906 : 0 : return -rte_mtr_error_set(error, EEXIST,
907 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
908 : : "Meter enable failed.");
909 : : }
910 [ # # ]: 0 : if (dir == ZXDH_INGRESS)
911 : 0 : priv->i_mtr_en = !!enable;
912 : : else
913 : 0 : priv->e_mtr_en = !!enable;
914 : :
915 : : return ret;
916 : : }
917 : :
918 : : static void
919 : : zxdh_meter_build_actions(struct zxdh_meter_action *mtr_action,
920 : : struct rte_mtr_params *params)
921 : : {
922 : 0 : mtr_action->stats_mask = params->stats_mask;
923 : 0 : mtr_action->action[RTE_COLOR_RED] = ZXDH_MTR_POLICER_ACTION_DROP;
924 : : }
925 : :
926 : : static int
927 : 0 : zxdh_hw_plcrflow_config(struct rte_eth_dev *dev, uint16_t hw_flow_id,
928 : : struct zxdh_mtr_object *mtr, struct rte_mtr_error *error)
929 : : {
930 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
931 : : int ret = 0;
932 : :
933 [ # # ]: 0 : if (hw->is_pf) {
934 : 0 : uint64_t hw_profile_id = (uint64_t)mtr->profile->hw_profile_id;
935 : :
936 : 0 : ret = zxdh_np_stat_car_queue_cfg_set(hw->dev_id, CAR_A,
937 : 0 : hw_flow_id, 1, mtr->enable, hw_profile_id);
938 : :
939 [ # # ]: 0 : if (ret) {
940 : 0 : PMD_DRV_LOG(ERR, "dpp_stat_car_queue_cfg_set failed flowid %d profile id %d",
941 : : hw_flow_id, mtr->profile->hw_profile_id);
942 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
943 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS,
944 : : NULL, "Failed to bind plcr flow.");
945 : : ;
946 : : }
947 : : } else {
948 : 0 : struct zxdh_msg_info msg_info = {0};
949 : 0 : uint8_t zxdh_msg_reply_info[ZXDH_ST_SZ_BYTES(msg_reply_info)] = {0};
950 : : struct zxdh_plcr_flow_cfg *zxdh_plcr_flow_cfg = &msg_info.data.zxdh_plcr_flow_cfg;
951 : :
952 : : zxdh_plcr_flow_cfg->car_type = CAR_A;
953 : 0 : zxdh_plcr_flow_cfg->flow_id = hw_flow_id;
954 : 0 : zxdh_plcr_flow_cfg->drop_flag = 1;
955 : 0 : zxdh_plcr_flow_cfg->plcr_en = mtr->enable;
956 : 0 : zxdh_plcr_flow_cfg->profile_id = mtr->profile->hw_profile_id;
957 : 0 : zxdh_msg_head_build(hw, ZXDH_PLCR_CAR_QUEUE_CFG_SET, &msg_info);
958 : 0 : ret = zxdh_vf_send_msg_to_pf(dev, &msg_info,
959 : : ZXDH_MSG_HEAD_LEN + sizeof(struct zxdh_plcr_flow_cfg),
960 : : zxdh_msg_reply_info,
961 : : ZXDH_ST_SZ_BYTES(msg_reply_info));
962 [ # # ]: 0 : if (ret) {
963 : 0 : PMD_DRV_LOG(ERR,
964 : : "Failed msg: port 0x%x msg type ZXDH_PLCR_CAR_QUEUE_CFG_SET ",
965 : : hw->vport.vport);
966 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
967 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS,
968 : : NULL, "Failed to bind plcr flow.");
969 : : }
970 : : }
971 : :
972 : : return ret;
973 : : }
974 : :
975 : : static void
976 : 0 : zxdh_mtr_obj_free(struct rte_eth_dev *dev, struct zxdh_mtr_object *mtr_obj)
977 : : {
978 : 0 : struct zxdh_mtr_list *mtr_list = &zxdh_shared_data->mtr_list;
979 : 0 : struct rte_mempool *mtr_mp = zxdh_shared_data->mtr_mp;
980 : :
981 : 0 : PMD_DRV_LOG(INFO, "free port %d dir %d meter %d mtr refcnt:%d ....",
982 : : dev->data->port_id, mtr_obj->direction, mtr_obj->meter_id, mtr_obj->mtr_ref_cnt);
983 : :
984 [ # # ]: 0 : if (mtr_obj->policy)
985 : 0 : mtr_obj->policy->ref_cnt--;
986 : :
987 [ # # ]: 0 : if (mtr_obj->profile)
988 : 0 : mtr_obj->profile->ref_cnt--;
989 : :
990 [ # # ]: 0 : PMD_DRV_LOG(INFO,
991 : : "free port %d dir %d meter %d profile refcnt:%d ",
992 : : dev->data->port_id,
993 : : mtr_obj->direction,
994 : : mtr_obj->meter_id,
995 : : mtr_obj->profile ? mtr_obj->profile->ref_cnt : 0);
996 : :
997 [ # # ]: 0 : if (--mtr_obj->mtr_ref_cnt == 0) {
998 : 0 : PMD_DRV_LOG(INFO, "rm mtr %p refcnt:%d ....", mtr_obj, mtr_obj->mtr_ref_cnt);
999 [ # # # # ]: 0 : TAILQ_REMOVE(mtr_list, mtr_obj, next);
1000 : 0 : MP_FREE_OBJ_FUNC(mtr_mp, mtr_obj);
1001 : : }
1002 : 0 : }
1003 : :
1004 : : static int
1005 : : zxdh_mtr_flow_offlad(struct rte_eth_dev *dev,
1006 : : struct zxdh_mtr_object *mtr,
1007 : : struct rte_mtr_error *error)
1008 : : {
1009 : : uint16_t hw_flow_id;
1010 : :
1011 : 0 : hw_flow_id = mtr->vfid * 2 + ZXDH_PORT_MTR_FID_BASE + mtr->direction;
1012 : 0 : return zxdh_hw_plcrflow_config(dev, hw_flow_id, mtr, error);
1013 : : }
1014 : :
1015 : : static struct zxdh_mtr_object *
1016 : 0 : zxdh_mtr_find(uint32_t meter_id, uint16_t dpdk_portid)
1017 : : {
1018 : 0 : struct zxdh_mtr_list *mtr_list = &zxdh_shared_data->mtr_list;
1019 : : struct zxdh_mtr_object *mtr = NULL;
1020 : :
1021 [ # # ]: 0 : TAILQ_FOREACH(mtr, mtr_list, next) {
1022 : 0 : PMD_DRV_LOG(INFO,
1023 : : "mtrlist head %p mtr %p mtr->meterid %d to find mtrid %d",
1024 : : TAILQ_FIRST(mtr_list),
1025 : : mtr,
1026 : : mtr->meter_id,
1027 : : meter_id
1028 : : );
1029 : :
1030 [ # # # # ]: 0 : if (meter_id == mtr->meter_id && dpdk_portid == mtr->port_id)
1031 : 0 : return mtr;
1032 : : }
1033 : : return NULL;
1034 : : }
1035 : :
1036 : : static int
1037 : 0 : zxdh_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
1038 : : struct rte_mtr_params *params, int shared,
1039 : : struct rte_mtr_error *error)
1040 : : {
1041 : 0 : struct zxdh_hw *priv = dev->data->dev_private;
1042 : 0 : struct zxdh_mtr_list *mtr_list = &zxdh_shared_data->mtr_list;
1043 : : struct zxdh_mtr_object *mtr;
1044 : : struct zxdh_meter_profile *mtr_profile;
1045 : : struct zxdh_meter_policy *mtr_policy;
1046 : : uint8_t dir = 0;
1047 : : int ret;
1048 : :
1049 [ # # ]: 0 : if (shared)
1050 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
1051 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
1052 : : "Meter share is not supported");
1053 : :
1054 : 0 : ret = zxdh_meter_validate(meter_id, params, error);
1055 [ # # ]: 0 : if (ret)
1056 : : return ret;
1057 : :
1058 [ # # ]: 0 : if (zxdh_check_port_mtr_bind(dev, dir))
1059 : 0 : return -rte_mtr_error_set(error, EEXIST,
1060 : : RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
1061 : : "Meter object already bind to dev.");
1062 : :
1063 : 0 : mtr_profile = zxdh_mtr_profile_find_by_id(&zxdh_shared_data->meter_profile_list,
1064 : : params->meter_profile_id,
1065 : 0 : dev->data->port_id
1066 : : );
1067 : :
1068 [ # # ]: 0 : if (mtr_profile == NULL)
1069 : 0 : return -rte_mtr_error_set(error, EEXIST,
1070 [ # # ]: 0 : RTE_MTR_ERROR_TYPE_METER_PROFILE, ¶ms->meter_profile_id,
1071 : : "Meter profile object is not exists.");
1072 : 0 : mtr_profile->ref_cnt++;
1073 : 0 : mtr_policy = zxdh_mtr_policy_find_by_id(&zxdh_shared_data->mtr_policy_list,
1074 : 0 : params->meter_policy_id,
1075 : : dev->data->port_id);
1076 : :
1077 [ # # ]: 0 : if (mtr_policy == NULL) {
1078 : : ret = -rte_mtr_error_set(error, EEXIST,
1079 [ # # ]: 0 : RTE_MTR_ERROR_TYPE_METER_PROFILE, ¶ms->meter_policy_id,
1080 : : "Meter policy object is not exists.");
1081 : 0 : mtr_profile->ref_cnt--;
1082 : 0 : return ret;
1083 : : }
1084 : 0 : mtr_policy->ref_cnt++;
1085 : :
1086 : 0 : mtr = zxdh_mtr_obj_alloc(zxdh_shared_data->mtr_mp);
1087 [ # # ]: 0 : if (mtr == NULL) {
1088 : : ret = -rte_mtr_error_set(error, ENOMEM,
1089 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
1090 : : "Memory alloc failed for meter.");
1091 : 0 : mtr_policy->ref_cnt--;
1092 : 0 : mtr_profile->ref_cnt--;
1093 : 0 : return ret;
1094 : : }
1095 : : memset(mtr, 0, sizeof(struct zxdh_mtr_object));
1096 : :
1097 : 0 : mtr->meter_id = meter_id;
1098 : 0 : mtr->profile = mtr_profile;
1099 : :
1100 : : zxdh_meter_build_actions(&mtr->mtr_action, params);
1101 : 0 : TAILQ_INSERT_TAIL(mtr_list, mtr, next);
1102 : 0 : mtr->enable = !!params->meter_enable;
1103 : 0 : mtr->shared = !!shared;
1104 : 0 : mtr->mtr_ref_cnt++;
1105 : 0 : mtr->vfid = priv->vfid;
1106 : 0 : mtr->port_id = dev->data->port_id;
1107 : 0 : mtr->policy = mtr_policy;
1108 : 0 : mtr->direction = !!dir;
1109 [ # # ]: 0 : if (params->meter_enable) {
1110 : : ret = zxdh_mtr_flow_offlad(dev, mtr, error);
1111 [ # # ]: 0 : if (ret)
1112 : 0 : goto error;
1113 : : }
1114 : 0 : ret = zxdh_set_mtr_enable(dev, mtr->direction, 1, error);
1115 [ # # ]: 0 : if (ret)
1116 : 0 : goto error;
1117 : : return ret;
1118 : 0 : error:
1119 : 0 : zxdh_mtr_obj_free(dev, mtr);
1120 : 0 : return ret;
1121 : : }
1122 : :
1123 : : static int
1124 : 0 : zxdh_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,
1125 : : struct rte_mtr_error *error)
1126 : : {
1127 : : struct zxdh_mtr_object *mtr;
1128 : :
1129 : 0 : mtr = zxdh_mtr_find(meter_id, dev->data->port_id);
1130 [ # # ]: 0 : if (mtr == NULL)
1131 : 0 : return -rte_mtr_error_set(error, EEXIST,
1132 : : RTE_MTR_ERROR_TYPE_MTR_ID,
1133 : : NULL, "Meter object id not valid.");
1134 : 0 : mtr->enable = 0;
1135 : 0 : zxdh_set_mtr_enable(dev, mtr->direction, 0, error);
1136 : :
1137 [ # # ]: 0 : if (zxdh_mtr_flow_offlad(dev, mtr, error))
1138 : : return -1;
1139 : :
1140 : 0 : zxdh_mtr_obj_free(dev, mtr);
1141 : 0 : return 0;
1142 : : }
1143 : :
1144 : : void
1145 : 0 : zxdh_mtr_policy_res_free(struct rte_mempool *mtr_policy_mp, struct zxdh_meter_policy *policy)
1146 : : {
1147 : 0 : PMD_DRV_LOG(INFO, "to free policy %d ref %d ", policy->policy_id, policy->ref_cnt);
1148 : :
1149 [ # # ]: 0 : if (--policy->ref_cnt == 0) {
1150 [ # # # # ]: 0 : TAILQ_REMOVE(&zxdh_shared_data->mtr_policy_list, policy, next);
1151 : 0 : MP_FREE_OBJ_FUNC(mtr_policy_mp, policy);
1152 : : }
1153 : 0 : }
1154 : :
1155 : : static int
1156 : 0 : zxdh_mtr_stats_read(struct rte_eth_dev *dev,
1157 : : uint32_t mtr_id,
1158 : : struct rte_mtr_stats *stats,
1159 : : uint64_t *stats_mask,
1160 : : int clear,
1161 : : struct rte_mtr_error *error)
1162 : : {
1163 : 0 : struct zxdh_mtr_stats mtr_stat = {0};
1164 : : struct zxdh_mtr_object *mtr = NULL;
1165 : : int ret = 0;
1166 : : /* Meter object must exist. */
1167 : 0 : mtr = zxdh_mtr_find(mtr_id, dev->data->port_id);
1168 [ # # ]: 0 : if (mtr == NULL)
1169 : 0 : return -rte_mtr_error_set(error, ENOENT,
1170 : : RTE_MTR_ERROR_TYPE_MTR_ID,
1171 : : NULL, "Meter object id not valid.");
1172 : 0 : *stats_mask = RTE_MTR_STATS_N_BYTES_DROPPED | RTE_MTR_STATS_N_PKTS_DROPPED;
1173 : : memset(&mtr_stat, 0, sizeof(mtr_stat));
1174 : 0 : ret = zxdh_mtr_hw_counter_query(dev, clear, mtr->direction, &mtr_stat, error);
1175 [ # # ]: 0 : if (ret)
1176 [ # # ]: 0 : goto error;
1177 : 0 : stats->n_bytes_dropped = mtr_stat.n_bytes_dropped;
1178 : 0 : stats->n_pkts_dropped = mtr_stat.n_pkts_dropped;
1179 : :
1180 : 0 : return 0;
1181 : : error:
1182 : 0 : return -rte_mtr_error_set(error, ret, RTE_MTR_ERROR_TYPE_STATS, NULL,
1183 : : "Failed to read meter drop counters.");
1184 : : }
1185 : :
1186 : : static const struct rte_mtr_ops zxdh_mtr_ops = {
1187 : : .capabilities_get = zxdh_meter_cap_get,
1188 : : .meter_profile_add = zxdh_meter_profile_add,
1189 : : .meter_profile_delete = zxdh_meter_profile_delete,
1190 : : .create = zxdh_meter_create,
1191 : : .destroy = zxdh_meter_destroy,
1192 : : .stats_read = zxdh_mtr_stats_read,
1193 : : .meter_policy_add = zxdh_meter_policy_add,
1194 : : .meter_policy_delete = zxdh_meter_policy_delete,
1195 : : };
1196 : :
1197 : : int
1198 : 0 : zxdh_meter_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
1199 : : {
1200 : 0 : *(const struct rte_mtr_ops **)arg = &zxdh_mtr_ops;
1201 : 0 : return 0;
1202 : : }
1203 : :
1204 : : void
1205 : 0 : zxdh_mtr_release(struct rte_eth_dev *dev)
1206 : : {
1207 : 0 : struct zxdh_hw *priv = dev->data->dev_private;
1208 : : struct zxdh_meter_profile *profile;
1209 : 0 : struct rte_mtr_error error = {0};
1210 : : struct zxdh_mtr_object *mtr_obj;
1211 : :
1212 [ # # ]: 0 : RTE_TAILQ_FOREACH(mtr_obj, &zxdh_shared_data->mtr_list, next) {
1213 [ # # ]: 0 : if (mtr_obj->port_id == priv->port_id)
1214 : 0 : zxdh_mtr_obj_free(dev, mtr_obj);
1215 : : }
1216 : :
1217 : :
1218 [ # # ]: 0 : RTE_TAILQ_FOREACH(profile, &zxdh_shared_data->meter_profile_list, next) {
1219 [ # # ]: 0 : if (profile->dpdk_port_id == priv->port_id)
1220 : 0 : zxdh_mtr_profile_res_free(dev,
1221 : 0 : zxdh_shared_data->mtr_profile_mp,
1222 : : profile,
1223 : : &error
1224 : : );
1225 : : }
1226 : :
1227 : : struct zxdh_meter_policy *policy;
1228 : :
1229 [ # # ]: 0 : RTE_TAILQ_FOREACH(policy, &zxdh_shared_data->mtr_policy_list, next) {
1230 [ # # ]: 0 : if (policy->dpdk_port_id == priv->port_id)
1231 : 0 : zxdh_mtr_policy_res_free(zxdh_shared_data->mtr_policy_mp, policy);
1232 : : }
1233 : 0 : }
|