Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2018-2021 HiSilicon Limited.
3 : : */
4 : :
5 : : #include <ethdev_driver.h>
6 : : #include <rte_hash.h>
7 : : #include <rte_hash_crc.h>
8 : : #include <rte_io.h>
9 : : #include <rte_malloc.h>
10 : :
11 : : #include "hns3_ethdev.h"
12 : : #include "hns3_logs.h"
13 : :
14 : : #define HNS3_VLAN_TAG_TYPE_NONE 0
15 : : #define HNS3_VLAN_TAG_TYPE_TAG2 1
16 : : #define HNS3_VLAN_TAG_TYPE_TAG1 2
17 : : #define HNS3_VLAN_TAG_TYPE_TAG1_2 3
18 : :
19 : : #define HNS3_PF_ID_S 0
20 : : #define HNS3_PF_ID_M GENMASK(2, 0)
21 : : #define HNS3_VF_ID_S 3
22 : : #define HNS3_VF_ID_M GENMASK(10, 3)
23 : : #define HNS3_PORT_TYPE_B 11
24 : : #define HNS3_NETWORK_PORT_ID_S 0
25 : : #define HNS3_NETWORK_PORT_ID_M GENMASK(3, 0)
26 : :
27 : : #define HNS3_FD_EPORT_SW_EN_B 0
28 : :
29 : : #define HNS3_FD_AD_DATA_S 32
30 : : #define HNS3_FD_AD_DROP_B 0
31 : : #define HNS3_FD_AD_DIRECT_QID_B 1
32 : : #define HNS3_FD_AD_QID_S 2
33 : : #define HNS3_FD_AD_QID_M GENMASK(11, 2)
34 : : #define HNS3_FD_AD_USE_COUNTER_B 12
35 : : #define HNS3_FD_AD_COUNTER_NUM_S 13
36 : : #define HNS3_FD_AD_COUNTER_NUM_M GENMASK(19, 13)
37 : : #define HNS3_FD_AD_NXT_STEP_B 20
38 : : #define HNS3_FD_AD_NXT_KEY_S 21
39 : : #define HNS3_FD_AD_NXT_KEY_M GENMASK(25, 21)
40 : : #define HNS3_FD_AD_WR_RULE_ID_B 0
41 : : #define HNS3_FD_AD_RULE_ID_S 1
42 : : #define HNS3_FD_AD_RULE_ID_M GENMASK(12, 1)
43 : : #define HNS3_FD_AD_QUEUE_REGION_EN_B 16
44 : : #define HNS3_FD_AD_QUEUE_REGION_SIZE_S 17
45 : : #define HNS3_FD_AD_QUEUE_REGION_SIZE_M GENMASK(20, 17)
46 : : #define HNS3_FD_AD_COUNTER_HIGH_BIT 7
47 : : #define HNS3_FD_AD_COUNTER_HIGH_BIT_B 26
48 : : #define HNS3_FD_AD_QUEUE_ID_HIGH_BIT 10
49 : : #define HNS3_FD_AD_QUEUE_ID_HIGH_BIT_B 21
50 : :
51 : : enum HNS3_PORT_TYPE {
52 : : HOST_PORT,
53 : : NETWORK_PORT
54 : : };
55 : :
56 : : enum HNS3_FD_MODE {
57 : : HNS3_FD_MODE_DEPTH_2K_WIDTH_400B_STAGE_1,
58 : : HNS3_FD_MODE_DEPTH_1K_WIDTH_400B_STAGE_2,
59 : : HNS3_FD_MODE_DEPTH_4K_WIDTH_200B_STAGE_1,
60 : : HNS3_FD_MODE_DEPTH_2K_WIDTH_200B_STAGE_2,
61 : : };
62 : :
63 : : enum HNS3_FD_KEY_TYPE {
64 : : HNS3_FD_KEY_BASE_ON_PTYPE,
65 : : HNS3_FD_KEY_BASE_ON_TUPLE,
66 : : };
67 : :
68 : : enum HNS3_FD_META_DATA {
69 : : PACKET_TYPE_ID,
70 : : IP_FRAGEMENT,
71 : : ROCE_TYPE,
72 : : NEXT_KEY,
73 : : VLAN_NUMBER,
74 : : SRC_VPORT,
75 : : DST_VPORT,
76 : : TUNNEL_PACKET,
77 : : MAX_META_DATA,
78 : : };
79 : :
80 : : struct key_info {
81 : : uint8_t key_type;
82 : : uint8_t key_length;
83 : : };
84 : :
85 : : static const struct key_info meta_data_key_info[] = {
86 : : {PACKET_TYPE_ID, 6},
87 : : {IP_FRAGEMENT, 1},
88 : : {ROCE_TYPE, 1},
89 : : {NEXT_KEY, 5},
90 : : {VLAN_NUMBER, 2},
91 : : {SRC_VPORT, 12},
92 : : {DST_VPORT, 12},
93 : : {TUNNEL_PACKET, 1},
94 : : };
95 : :
96 : : static const struct key_info tuple_key_info[] = {
97 : : {OUTER_DST_MAC, 48},
98 : : {OUTER_SRC_MAC, 48},
99 : : {OUTER_VLAN_TAG_FST, 16},
100 : : {OUTER_VLAN_TAG_SEC, 16},
101 : : {OUTER_ETH_TYPE, 16},
102 : : {OUTER_L2_RSV, 16},
103 : : {OUTER_IP_TOS, 8},
104 : : {OUTER_IP_PROTO, 8},
105 : : {OUTER_SRC_IP, 32},
106 : : {OUTER_DST_IP, 32},
107 : : {OUTER_L3_RSV, 16},
108 : : {OUTER_SRC_PORT, 16},
109 : : {OUTER_DST_PORT, 16},
110 : : {OUTER_L4_RSV, 32},
111 : : {OUTER_TUN_VNI, 24},
112 : : {OUTER_TUN_FLOW_ID, 8},
113 : : {INNER_DST_MAC, 48},
114 : : {INNER_SRC_MAC, 48},
115 : : {INNER_VLAN_TAG1, 16},
116 : : {INNER_VLAN_TAG2, 16},
117 : : {INNER_ETH_TYPE, 16},
118 : : {INNER_L2_RSV, 16},
119 : : {INNER_IP_TOS, 8},
120 : : {INNER_IP_PROTO, 8},
121 : : {INNER_SRC_IP, 32},
122 : : {INNER_DST_IP, 32},
123 : : {INNER_L3_RSV, 16},
124 : : {INNER_SRC_PORT, 16},
125 : : {INNER_DST_PORT, 16},
126 : : {INNER_SCTP_TAG, 32},
127 : : };
128 : :
129 : : #define MAX_KEY_LENGTH 400
130 : : #define MAX_200B_KEY_LENGTH 200
131 : : #define MAX_META_DATA_LENGTH 16
132 : : #define MAX_KEY_DWORDS DIV_ROUND_UP(MAX_KEY_LENGTH / HNS3_BITS_PER_BYTE, 4)
133 : : #define MAX_KEY_BYTES (MAX_KEY_DWORDS * 4)
134 : :
135 : : enum HNS3_FD_PACKET_TYPE {
136 : : NIC_PACKET,
137 : : ROCE_PACKET,
138 : : };
139 : :
140 : : /* For each bit of TCAM entry, it uses a pair of 'x' and
141 : : * 'y' to indicate which value to match, like below:
142 : : * ----------------------------------
143 : : * | bit x | bit y | search value |
144 : : * ----------------------------------
145 : : * | 0 | 0 | always hit |
146 : : * ----------------------------------
147 : : * | 1 | 0 | match '0' |
148 : : * ----------------------------------
149 : : * | 0 | 1 | match '1' |
150 : : * ----------------------------------
151 : : * | 1 | 1 | invalid |
152 : : * ----------------------------------
153 : : * Then for input key(k) and mask(v), we can calculate the value by
154 : : * the formulae:
155 : : * x = (~k) & v
156 : : * y = k & v
157 : : */
158 : : #define calc_x(x, k, v) ((x) = (~(k) & (v)))
159 : : #define calc_y(y, k, v) ((y) = ((k) & (v)))
160 : :
161 : : struct hns3_fd_tcam_config_1_cmd {
162 : : uint8_t stage;
163 : : uint8_t xy_sel;
164 : : uint8_t port_info;
165 : : uint8_t rsv1[1];
166 : : rte_le32_t index;
167 : : uint8_t entry_vld;
168 : : uint8_t rsv2[7];
169 : : uint8_t tcam_data[8];
170 : : };
171 : :
172 : : struct hns3_fd_tcam_config_2_cmd {
173 : : uint8_t tcam_data[24];
174 : : };
175 : :
176 : : struct hns3_fd_tcam_config_3_cmd {
177 : : uint8_t tcam_data[20];
178 : : uint8_t rsv[4];
179 : : };
180 : :
181 : : struct hns3_get_fd_mode_cmd {
182 : : uint8_t mode;
183 : : uint8_t enable;
184 : : uint8_t rsv[22];
185 : : };
186 : :
187 : : struct hns3_get_fd_allocation_cmd {
188 : : rte_le32_t stage1_entry_num;
189 : : rte_le32_t stage2_entry_num;
190 : : rte_le16_t stage1_counter_num;
191 : : rte_le16_t stage2_counter_num;
192 : : uint8_t rsv[12];
193 : : };
194 : :
195 : : struct hns3_set_fd_key_config_cmd {
196 : : uint8_t stage;
197 : : uint8_t key_select;
198 : : uint8_t inner_sipv6_word_en;
199 : : uint8_t inner_dipv6_word_en;
200 : : uint8_t outer_sipv6_word_en;
201 : : uint8_t outer_dipv6_word_en;
202 : : uint8_t rsv1[2];
203 : : rte_le32_t tuple_mask;
204 : : rte_le32_t meta_data_mask;
205 : : uint8_t rsv2[8];
206 : : };
207 : :
208 : : struct hns3_fd_ad_config_cmd {
209 : : uint8_t stage;
210 : : uint8_t rsv1[3];
211 : : rte_le32_t index;
212 : : rte_le64_t ad_data;
213 : : uint8_t rsv2[8];
214 : : };
215 : :
216 : : struct hns3_fd_get_cnt_cmd {
217 : : uint8_t stage;
218 : : uint8_t rsv1[3];
219 : : rte_le16_t index;
220 : : uint8_t rsv2[2];
221 : : rte_le64_t value;
222 : : uint8_t rsv3[8];
223 : : };
224 : :
225 : 0 : static int hns3_get_fd_mode(struct hns3_hw *hw, uint8_t *fd_mode)
226 : : {
227 : : struct hns3_get_fd_mode_cmd *req;
228 : : struct hns3_cmd_desc desc;
229 : : int ret;
230 : :
231 : 0 : hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_FD_MODE_CTRL, true);
232 : :
233 : : req = (struct hns3_get_fd_mode_cmd *)desc.data;
234 : :
235 : 0 : ret = hns3_cmd_send(hw, &desc, 1);
236 [ # # ]: 0 : if (ret) {
237 : 0 : hns3_err(hw, "Get fd mode fail, ret=%d", ret);
238 : 0 : return ret;
239 : : }
240 : :
241 : 0 : *fd_mode = req->mode;
242 : :
243 : 0 : return ret;
244 : : }
245 : :
246 : 0 : static int hns3_get_fd_allocation(struct hns3_hw *hw,
247 : : uint32_t *stage1_entry_num,
248 : : uint32_t *stage2_entry_num,
249 : : uint16_t *stage1_counter_num,
250 : : uint16_t *stage2_counter_num)
251 : : {
252 : : struct hns3_get_fd_allocation_cmd *req;
253 : : struct hns3_cmd_desc desc;
254 : : int ret;
255 : :
256 : 0 : hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_FD_GET_ALLOCATION, true);
257 : :
258 : : req = (struct hns3_get_fd_allocation_cmd *)desc.data;
259 : :
260 : 0 : ret = hns3_cmd_send(hw, &desc, 1);
261 [ # # ]: 0 : if (ret) {
262 : 0 : hns3_err(hw, "Query fd allocation fail, ret=%d", ret);
263 : 0 : return ret;
264 : : }
265 : :
266 : 0 : *stage1_entry_num = rte_le_to_cpu_32(req->stage1_entry_num);
267 : 0 : *stage2_entry_num = rte_le_to_cpu_32(req->stage2_entry_num);
268 : 0 : *stage1_counter_num = rte_le_to_cpu_16(req->stage1_counter_num);
269 : 0 : *stage2_counter_num = rte_le_to_cpu_16(req->stage2_counter_num);
270 : :
271 : 0 : return ret;
272 : : }
273 : :
274 : 0 : static int hns3_set_fd_key_config(struct hns3_adapter *hns)
275 : : {
276 : : struct hns3_set_fd_key_config_cmd *req;
277 : : struct hns3_fd_key_cfg *key_cfg;
278 : : struct hns3_pf *pf = &hns->pf;
279 : 0 : struct hns3_hw *hw = &hns->hw;
280 : : struct hns3_cmd_desc desc;
281 : : int ret;
282 : :
283 : 0 : hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_FD_KEY_CONFIG, false);
284 : :
285 : : req = (struct hns3_set_fd_key_config_cmd *)desc.data;
286 : : key_cfg = &pf->fdir.fd_cfg.key_cfg[HNS3_FD_STAGE_1];
287 : 0 : req->stage = HNS3_FD_STAGE_1;
288 : 0 : req->key_select = key_cfg->key_sel;
289 : 0 : req->inner_sipv6_word_en = key_cfg->inner_sipv6_word_en;
290 : 0 : req->inner_dipv6_word_en = key_cfg->inner_dipv6_word_en;
291 : 0 : req->outer_sipv6_word_en = key_cfg->outer_sipv6_word_en;
292 : 0 : req->outer_dipv6_word_en = key_cfg->outer_dipv6_word_en;
293 : 0 : req->tuple_mask = rte_cpu_to_le_32(~key_cfg->tuple_active);
294 : 0 : req->meta_data_mask = rte_cpu_to_le_32(~key_cfg->meta_data_active);
295 : :
296 : 0 : ret = hns3_cmd_send(hw, &desc, 1);
297 [ # # ]: 0 : if (ret)
298 : 0 : hns3_err(hw, "Set fd key fail, ret=%d", ret);
299 : :
300 : 0 : return ret;
301 : : }
302 : :
303 : 0 : int hns3_init_fd_config(struct hns3_adapter *hns)
304 : : {
305 : : struct hns3_pf *pf = &hns->pf;
306 : 0 : struct hns3_hw *hw = &hns->hw;
307 : : struct hns3_fd_key_cfg *key_cfg;
308 : : int ret;
309 : :
310 : 0 : ret = hns3_get_fd_mode(hw, &pf->fdir.fd_cfg.fd_mode);
311 [ # # ]: 0 : if (ret)
312 : : return ret;
313 : :
314 [ # # # ]: 0 : switch (pf->fdir.fd_cfg.fd_mode) {
315 : 0 : case HNS3_FD_MODE_DEPTH_2K_WIDTH_400B_STAGE_1:
316 : 0 : pf->fdir.fd_cfg.max_key_length = MAX_KEY_LENGTH;
317 : 0 : break;
318 : 0 : case HNS3_FD_MODE_DEPTH_4K_WIDTH_200B_STAGE_1:
319 : 0 : pf->fdir.fd_cfg.max_key_length = MAX_200B_KEY_LENGTH;
320 : 0 : hns3_warn(hw, "Unsupported tunnel filter in 4K*200Bit");
321 : 0 : break;
322 : 0 : default:
323 : 0 : hns3_err(hw, "Unsupported flow director mode %u",
324 : : pf->fdir.fd_cfg.fd_mode);
325 : 0 : return -EOPNOTSUPP;
326 : : }
327 : :
328 : : key_cfg = &pf->fdir.fd_cfg.key_cfg[HNS3_FD_STAGE_1];
329 : 0 : key_cfg->key_sel = HNS3_FD_KEY_BASE_ON_TUPLE;
330 : 0 : key_cfg->inner_sipv6_word_en = IPV6_ADDR_WORD_MASK;
331 : 0 : key_cfg->inner_dipv6_word_en = IPV6_ADDR_WORD_MASK;
332 : 0 : key_cfg->outer_sipv6_word_en = 0;
333 : 0 : key_cfg->outer_dipv6_word_en = 0;
334 : :
335 : 0 : key_cfg->tuple_active = BIT(INNER_VLAN_TAG1) | BIT(INNER_ETH_TYPE) |
336 : : BIT(INNER_IP_PROTO) | BIT(INNER_IP_TOS) |
337 : : BIT(INNER_SRC_IP) | BIT(INNER_DST_IP) |
338 : : BIT(INNER_SRC_PORT) | BIT(INNER_DST_PORT);
339 : 0 : hns3_dbg(hw, "fdir tuple: inner<vlan_tag1 eth_type ip_src ip_dst "
340 : : "ip_proto ip_tos l4_src_port l4_dst_port>");
341 : :
342 : : /* If use max 400bit key, we can support tuples for ether type */
343 [ # # ]: 0 : if (pf->fdir.fd_cfg.max_key_length == MAX_KEY_LENGTH) {
344 : 0 : key_cfg->tuple_active |=
345 : : BIT(INNER_DST_MAC) | BIT(INNER_SRC_MAC) |
346 : : BIT(OUTER_SRC_PORT) | BIT(INNER_SCTP_TAG) |
347 : : BIT(OUTER_DST_PORT) | BIT(INNER_VLAN_TAG2) |
348 : : BIT(OUTER_TUN_VNI) | BIT(OUTER_TUN_FLOW_ID) |
349 : : BIT(OUTER_ETH_TYPE) | BIT(OUTER_IP_PROTO);
350 : 0 : hns3_dbg(hw, "fdir tuple more: inner<dst_mac src_mac "
351 : : "vlan_tag2 sctp_tag> outer<eth_type ip_proto "
352 : : "l4_src_port l4_dst_port tun_vni tun_flow_id>");
353 : : }
354 : :
355 : : /* roce_type is used to filter roce frames
356 : : * dst_vport is used to specify the rule
357 : : */
358 : 0 : key_cfg->meta_data_active = BIT(DST_VPORT) | BIT(TUNNEL_PACKET);
359 [ # # ]: 0 : if (pf->fdir.vlan_match_mode)
360 : 0 : key_cfg->meta_data_active |= BIT(VLAN_NUMBER);
361 : :
362 [ # # ]: 0 : hns3_dbg(hw, "fdir meta data: dst_vport tunnel_packet %s",
363 : : (pf->fdir.vlan_match_mode == HNS3_FDIR_VLAN_STRICT_MATCH) ?
364 : : "vlan_number" : "");
365 : :
366 : 0 : ret = hns3_get_fd_allocation(hw,
367 : : &pf->fdir.fd_cfg.rule_num[HNS3_FD_STAGE_1],
368 : : &pf->fdir.fd_cfg.rule_num[HNS3_FD_STAGE_2],
369 : : &pf->fdir.fd_cfg.cnt_num[HNS3_FD_STAGE_1],
370 : : &pf->fdir.fd_cfg.cnt_num[HNS3_FD_STAGE_2]);
371 [ # # ]: 0 : if (ret)
372 : : return ret;
373 : :
374 : 0 : hns3_dbg(hw, "fdir: stage1<rules-%u counters-%u> stage2<rules-%u counters=%u>",
375 : : pf->fdir.fd_cfg.rule_num[HNS3_FD_STAGE_1],
376 : : pf->fdir.fd_cfg.cnt_num[HNS3_FD_STAGE_1],
377 : : pf->fdir.fd_cfg.rule_num[HNS3_FD_STAGE_2],
378 : : pf->fdir.fd_cfg.cnt_num[HNS3_FD_STAGE_2]);
379 : :
380 : 0 : return hns3_set_fd_key_config(hns);
381 : : }
382 : :
383 : 0 : static int hns3_fd_tcam_config(struct hns3_hw *hw, bool sel_x, int loc,
384 : : uint8_t *key, bool is_add)
385 : : {
386 : : #define FD_TCAM_CMD_NUM 3
387 : : struct hns3_fd_tcam_config_1_cmd *req1;
388 : : struct hns3_fd_tcam_config_2_cmd *req2;
389 : : struct hns3_fd_tcam_config_3_cmd *req3;
390 : : struct hns3_cmd_desc desc[FD_TCAM_CMD_NUM];
391 : : int len;
392 : : int ret;
393 : :
394 : 0 : hns3_cmd_setup_basic_desc(&desc[0], HNS3_OPC_FD_TCAM_OP, false);
395 : 0 : desc[0].flag |= rte_cpu_to_le_16(HNS3_CMD_FLAG_NEXT);
396 : 0 : hns3_cmd_setup_basic_desc(&desc[1], HNS3_OPC_FD_TCAM_OP, false);
397 : 0 : desc[1].flag |= rte_cpu_to_le_16(HNS3_CMD_FLAG_NEXT);
398 : 0 : hns3_cmd_setup_basic_desc(&desc[2], HNS3_OPC_FD_TCAM_OP, false);
399 : :
400 : : req1 = (struct hns3_fd_tcam_config_1_cmd *)desc[0].data;
401 : : req2 = (struct hns3_fd_tcam_config_2_cmd *)desc[1].data;
402 : : req3 = (struct hns3_fd_tcam_config_3_cmd *)desc[2].data;
403 : :
404 : 0 : req1->stage = HNS3_FD_STAGE_1;
405 : 0 : req1->xy_sel = sel_x ? 1 : 0;
406 : 0 : hns3_set_bit(req1->port_info, HNS3_FD_EPORT_SW_EN_B, 0);
407 : 0 : req1->index = rte_cpu_to_le_32(loc);
408 [ # # ]: 0 : req1->entry_vld = sel_x ? is_add : 0;
409 : :
410 [ # # ]: 0 : if (key) {
411 : : len = sizeof(req1->tcam_data);
412 : : memcpy(req1->tcam_data, key, len);
413 : 0 : key += len;
414 : :
415 : : len = sizeof(req2->tcam_data);
416 : : memcpy(req2->tcam_data, key, len);
417 : 0 : key += len;
418 : :
419 : : len = sizeof(req3->tcam_data);
420 : : memcpy(req3->tcam_data, key, len);
421 : : }
422 : :
423 : 0 : ret = hns3_cmd_send(hw, desc, FD_TCAM_CMD_NUM);
424 [ # # ]: 0 : if (ret)
425 : 0 : hns3_err(hw, "Config tcam key fail, ret=%d loc=%d add=%d",
426 : : ret, loc, is_add);
427 : 0 : return ret;
428 : : }
429 : :
430 : 0 : static int hns3_fd_ad_config(struct hns3_hw *hw, int loc,
431 : : struct hns3_fd_ad_data *action)
432 : : {
433 : : struct hns3_fd_ad_config_cmd *req;
434 : : struct hns3_cmd_desc desc;
435 : : uint64_t ad_data = 0;
436 : : int ret;
437 : :
438 : 0 : hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_FD_AD_OP, false);
439 : :
440 : : req = (struct hns3_fd_ad_config_cmd *)desc.data;
441 : 0 : req->index = rte_cpu_to_le_32(loc);
442 : 0 : req->stage = HNS3_FD_STAGE_1;
443 : :
444 : 0 : hns3_set_bit(ad_data, HNS3_FD_AD_WR_RULE_ID_B,
445 : : action->write_rule_id_to_bd);
446 : 0 : hns3_set_field(ad_data, HNS3_FD_AD_RULE_ID_M, HNS3_FD_AD_RULE_ID_S,
447 : : action->rule_id);
448 [ # # ]: 0 : if (action->nb_queues > 1) {
449 : 0 : hns3_set_bit(ad_data, HNS3_FD_AD_QUEUE_REGION_EN_B, 1);
450 : 0 : hns3_set_field(ad_data, HNS3_FD_AD_QUEUE_REGION_SIZE_M,
451 : : HNS3_FD_AD_QUEUE_REGION_SIZE_S,
452 : : rte_log2_u32(action->nb_queues));
453 : : }
454 : : /* set extend bit if counter_id is in [128 ~ 255] */
455 [ # # ]: 0 : if (action->counter_id & BIT(HNS3_FD_AD_COUNTER_HIGH_BIT))
456 : 0 : hns3_set_bit(ad_data, HNS3_FD_AD_COUNTER_HIGH_BIT_B, 1);
457 : : /* set extend bit if queue id > 1024 */
458 [ # # ]: 0 : if (action->queue_id & BIT(HNS3_FD_AD_QUEUE_ID_HIGH_BIT))
459 : 0 : hns3_set_bit(ad_data, HNS3_FD_AD_QUEUE_ID_HIGH_BIT_B, 1);
460 : 0 : ad_data <<= HNS3_FD_AD_DATA_S;
461 : 0 : hns3_set_bit(ad_data, HNS3_FD_AD_DROP_B, action->drop_packet);
462 [ # # ]: 0 : if (action->nb_queues == 1)
463 : 0 : hns3_set_bit(ad_data, HNS3_FD_AD_DIRECT_QID_B, 1);
464 : 0 : hns3_set_field(ad_data, HNS3_FD_AD_QID_M, HNS3_FD_AD_QID_S,
465 : : action->queue_id);
466 : 0 : hns3_set_bit(ad_data, HNS3_FD_AD_USE_COUNTER_B, action->use_counter);
467 : 0 : hns3_set_field(ad_data, HNS3_FD_AD_COUNTER_NUM_M,
468 : : HNS3_FD_AD_COUNTER_NUM_S, action->counter_id);
469 : 0 : hns3_set_bit(ad_data, HNS3_FD_AD_NXT_STEP_B, action->use_next_stage);
470 : 0 : hns3_set_field(ad_data, HNS3_FD_AD_NXT_KEY_M, HNS3_FD_AD_NXT_KEY_S,
471 : : action->next_input_key);
472 : :
473 : 0 : req->ad_data = rte_cpu_to_le_64(ad_data);
474 : 0 : ret = hns3_cmd_send(hw, &desc, 1);
475 [ # # ]: 0 : if (ret)
476 : 0 : hns3_err(hw, "Config fd ad fail, ret=%d loc=%d", ret, loc);
477 : :
478 : 0 : return ret;
479 : : }
480 : :
481 : : static inline void hns3_fd_convert_mac(uint8_t *key, uint8_t *mask,
482 : : uint8_t *mac_x, uint8_t *mac_y)
483 : : {
484 : : uint8_t tmp;
485 : : int i;
486 : :
487 [ # # # # ]: 0 : for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) {
488 : 0 : tmp = RTE_ETHER_ADDR_LEN - 1 - i;
489 : 0 : calc_x(mac_x[tmp], key[i], mask[i]);
490 : 0 : calc_y(mac_y[tmp], key[i], mask[i]);
491 : : }
492 : : }
493 : :
494 : 0 : static void hns3_fd_convert_int16(uint32_t tuple, struct hns3_fdir_rule *rule,
495 : : uint8_t *val_x, uint8_t *val_y)
496 : : {
497 : : uint16_t tmp_x_s;
498 : : uint16_t tmp_y_s;
499 : : uint16_t mask;
500 : : uint16_t key;
501 : :
502 [ # # # # : 0 : switch (tuple) {
# # # # ]
503 : 0 : case OUTER_SRC_PORT:
504 : 0 : key = rule->key_conf.spec.outer_src_port;
505 : 0 : mask = rule->key_conf.mask.outer_src_port;
506 : 0 : break;
507 : 0 : case OUTER_DST_PORT:
508 : 0 : key = rule->key_conf.spec.tunnel_type;
509 : 0 : mask = rule->key_conf.mask.tunnel_type;
510 : 0 : break;
511 : 0 : case OUTER_ETH_TYPE:
512 : 0 : key = rule->key_conf.spec.outer_ether_type;
513 : 0 : mask = rule->key_conf.mask.outer_ether_type;
514 : 0 : break;
515 : 0 : case INNER_SRC_PORT:
516 : 0 : key = rule->key_conf.spec.src_port;
517 : 0 : mask = rule->key_conf.mask.src_port;
518 : 0 : break;
519 : 0 : case INNER_DST_PORT:
520 : 0 : key = rule->key_conf.spec.dst_port;
521 : 0 : mask = rule->key_conf.mask.dst_port;
522 : 0 : break;
523 : 0 : case INNER_VLAN_TAG1:
524 : 0 : key = rule->key_conf.spec.vlan_tag1;
525 : 0 : mask = rule->key_conf.mask.vlan_tag1;
526 : 0 : break;
527 : 0 : case INNER_VLAN_TAG2:
528 : 0 : key = rule->key_conf.spec.vlan_tag2;
529 : 0 : mask = rule->key_conf.mask.vlan_tag2;
530 : 0 : break;
531 : 0 : default:
532 : : /* INNER_ETH_TYPE: */
533 : 0 : key = rule->key_conf.spec.ether_type;
534 : 0 : mask = rule->key_conf.mask.ether_type;
535 : 0 : break;
536 : : }
537 : 0 : calc_x(tmp_x_s, key, mask);
538 : 0 : calc_y(tmp_y_s, key, mask);
539 : 0 : val_x[0] = rte_cpu_to_le_16(tmp_x_s) & 0xFF;
540 : 0 : val_x[1] = rte_cpu_to_le_16(tmp_x_s) >> HNS3_BITS_PER_BYTE;
541 : 0 : val_y[0] = rte_cpu_to_le_16(tmp_y_s) & 0xFF;
542 : 0 : val_y[1] = rte_cpu_to_le_16(tmp_y_s) >> HNS3_BITS_PER_BYTE;
543 : 0 : }
544 : :
545 : 0 : static inline void hns3_fd_convert_int32(uint32_t key, uint32_t mask,
546 : : uint8_t *val_x, uint8_t *val_y)
547 : : {
548 : : uint32_t tmp_x_l;
549 : : uint32_t tmp_y_l;
550 : :
551 : 0 : calc_x(tmp_x_l, key, mask);
552 : 0 : calc_y(tmp_y_l, key, mask);
553 : : memcpy(val_x, &tmp_x_l, sizeof(tmp_x_l));
554 : : memcpy(val_y, &tmp_y_l, sizeof(tmp_y_l));
555 : 0 : }
556 : :
557 : 0 : static bool hns3_fd_convert_tuple(struct hns3_hw *hw,
558 : : uint32_t tuple, uint8_t *key_x,
559 : : uint8_t *key_y, struct hns3_fdir_rule *rule)
560 : : {
561 : : struct hns3_fdir_key_conf *key_conf;
562 : : int tmp;
563 : : int i;
564 : :
565 [ # # ]: 0 : if ((rule->input_set & BIT(tuple)) == 0)
566 : : return true;
567 : :
568 : : key_conf = &rule->key_conf;
569 [ # # # # : 0 : switch (tuple) {
# # # # #
# # # ]
570 : 0 : case INNER_DST_MAC:
571 : 0 : hns3_fd_convert_mac(key_conf->spec.dst_mac,
572 : 0 : key_conf->mask.dst_mac, key_x, key_y);
573 : : break;
574 : 0 : case INNER_SRC_MAC:
575 : 0 : hns3_fd_convert_mac(key_conf->spec.src_mac,
576 : 0 : key_conf->mask.src_mac, key_x, key_y);
577 : : break;
578 : 0 : case OUTER_SRC_PORT:
579 : : case OUTER_DST_PORT:
580 : : case OUTER_ETH_TYPE:
581 : : case INNER_SRC_PORT:
582 : : case INNER_DST_PORT:
583 : : case INNER_VLAN_TAG1:
584 : : case INNER_VLAN_TAG2:
585 : : case INNER_ETH_TYPE:
586 : 0 : hns3_fd_convert_int16(tuple, rule, key_x, key_y);
587 : 0 : break;
588 : 0 : case INNER_SRC_IP:
589 : 0 : hns3_fd_convert_int32(key_conf->spec.src_ip[IP_ADDR_KEY_ID],
590 : : key_conf->mask.src_ip[IP_ADDR_KEY_ID],
591 : : key_x, key_y);
592 : 0 : break;
593 : 0 : case INNER_DST_IP:
594 : 0 : hns3_fd_convert_int32(key_conf->spec.dst_ip[IP_ADDR_KEY_ID],
595 : : key_conf->mask.dst_ip[IP_ADDR_KEY_ID],
596 : : key_x, key_y);
597 : 0 : break;
598 : 0 : case INNER_SCTP_TAG:
599 : 0 : hns3_fd_convert_int32(key_conf->spec.sctp_tag,
600 : : key_conf->mask.sctp_tag, key_x, key_y);
601 : 0 : break;
602 : : case OUTER_TUN_VNI:
603 [ # # ]: 0 : for (i = 0; i < VNI_OR_TNI_LEN; i++) {
604 : 0 : tmp = VNI_OR_TNI_LEN - 1 - i;
605 : 0 : calc_x(key_x[tmp],
606 : : key_conf->spec.outer_tun_vni[i],
607 : : key_conf->mask.outer_tun_vni[i]);
608 : 0 : calc_y(key_y[tmp],
609 : : key_conf->spec.outer_tun_vni[i],
610 : : key_conf->mask.outer_tun_vni[i]);
611 : : }
612 : : break;
613 : 0 : case OUTER_TUN_FLOW_ID:
614 : 0 : calc_x(*key_x, key_conf->spec.outer_tun_flow_id,
615 : : key_conf->mask.outer_tun_flow_id);
616 : 0 : calc_y(*key_y, key_conf->spec.outer_tun_flow_id,
617 : : key_conf->mask.outer_tun_flow_id);
618 : 0 : break;
619 : 0 : case INNER_IP_TOS:
620 : 0 : calc_x(*key_x, key_conf->spec.ip_tos, key_conf->mask.ip_tos);
621 : 0 : calc_y(*key_y, key_conf->spec.ip_tos, key_conf->mask.ip_tos);
622 : 0 : break;
623 : 0 : case OUTER_IP_PROTO:
624 : 0 : calc_x(*key_x, key_conf->spec.outer_proto,
625 : : key_conf->mask.outer_proto);
626 : 0 : calc_y(*key_y, key_conf->spec.outer_proto,
627 : : key_conf->mask.outer_proto);
628 : 0 : break;
629 : 0 : case INNER_IP_PROTO:
630 : 0 : calc_x(*key_x, key_conf->spec.ip_proto,
631 : : key_conf->mask.ip_proto);
632 : 0 : calc_y(*key_y, key_conf->spec.ip_proto,
633 : : key_conf->mask.ip_proto);
634 : 0 : break;
635 : 0 : default:
636 : 0 : hns3_warn(hw, "not support tuple of (%u)", tuple);
637 : 0 : return false;
638 : : }
639 : : return true;
640 : : }
641 : :
642 : : static uint32_t hns3_get_port_number(uint8_t pf_id, uint8_t vf_id)
643 : : {
644 : : uint32_t port_number = 0;
645 : :
646 : : hns3_set_field(port_number, HNS3_PF_ID_M, HNS3_PF_ID_S, pf_id);
647 : 0 : hns3_set_field(port_number, HNS3_VF_ID_M, HNS3_VF_ID_S, vf_id);
648 : : hns3_set_bit(port_number, HNS3_PORT_TYPE_B, HOST_PORT);
649 : :
650 : : return port_number;
651 : : }
652 : :
653 : 0 : static void hns3_fd_convert_meta_data(struct hns3_fd_key_cfg *cfg,
654 : : uint8_t vf_id,
655 : : struct hns3_fdir_rule *rule,
656 : : uint8_t *key_x, uint8_t *key_y)
657 : : {
658 : : uint16_t meta_data = 0;
659 : : uint32_t port_number;
660 : : uint8_t cur_pos = 0;
661 : : uint8_t tuple_size;
662 : : uint8_t shift_bits;
663 : : uint32_t tmp_x;
664 : : uint32_t tmp_y;
665 : : uint8_t i;
666 : :
667 [ # # ]: 0 : for (i = 0; i < MAX_META_DATA; i++) {
668 [ # # ]: 0 : if ((cfg->meta_data_active & BIT(i)) == 0)
669 : 0 : continue;
670 : :
671 : 0 : tuple_size = meta_data_key_info[i].key_length;
672 [ # # ]: 0 : if (i == TUNNEL_PACKET) {
673 : 0 : hns3_set_bit(meta_data, cur_pos,
674 : : rule->key_conf.spec.tunnel_type ? 1 : 0);
675 : 0 : cur_pos += tuple_size;
676 [ # # ]: 0 : } else if (i == VLAN_NUMBER) {
677 : : uint32_t vlan_tag;
678 : : uint8_t vlan_num;
679 : :
680 [ # # ]: 0 : if (rule->key_conf.spec.tunnel_type == 0)
681 : 0 : vlan_num = rule->key_conf.vlan_num;
682 : : else
683 : 0 : vlan_num = rule->key_conf.outer_vlan_num;
684 [ # # ]: 0 : if (vlan_num == 1)
685 : : vlan_tag = HNS3_VLAN_TAG_TYPE_TAG1;
686 [ # # ]: 0 : else if (vlan_num == VLAN_TAG_NUM_MAX)
687 : : vlan_tag = HNS3_VLAN_TAG_TYPE_TAG1_2;
688 : : else
689 : : vlan_tag = HNS3_VLAN_TAG_TYPE_NONE;
690 : 0 : hns3_set_field(meta_data,
691 : : GENMASK(cur_pos + tuple_size,
692 : : cur_pos), cur_pos, vlan_tag);
693 : 0 : cur_pos += tuple_size;
694 [ # # ]: 0 : } else if (i == DST_VPORT) {
695 : 0 : port_number = hns3_get_port_number(0, vf_id);
696 : 0 : hns3_set_field(meta_data,
697 : : GENMASK(cur_pos + tuple_size, cur_pos),
698 : : cur_pos, port_number);
699 : 0 : cur_pos += tuple_size;
700 : : }
701 : : }
702 : :
703 : 0 : calc_x(tmp_x, meta_data, 0xFFFF);
704 : 0 : calc_y(tmp_y, meta_data, 0xFFFF);
705 : 0 : shift_bits = sizeof(meta_data) * HNS3_BITS_PER_BYTE - cur_pos;
706 : :
707 : 0 : tmp_x = rte_cpu_to_le_32(tmp_x << shift_bits);
708 : 0 : tmp_y = rte_cpu_to_le_32(tmp_y << shift_bits);
709 : 0 : key_x[0] = tmp_x & 0xFF;
710 : 0 : key_x[1] = (tmp_x >> HNS3_BITS_PER_BYTE) & 0xFF;
711 : 0 : key_y[0] = tmp_y & 0xFF;
712 : 0 : key_y[1] = (tmp_y >> HNS3_BITS_PER_BYTE) & 0xFF;
713 : 0 : }
714 : :
715 : : /* A complete key is combined with meta data key and tuple key.
716 : : * Meta data key is stored at the MSB region, and tuple key is stored at
717 : : * the LSB region, unused bits will be filled 0.
718 : : */
719 : 0 : static int hns3_config_key(struct hns3_adapter *hns,
720 : : struct hns3_fdir_rule *rule)
721 : : {
722 : : struct hns3_pf *pf = &hns->pf;
723 : 0 : struct hns3_hw *hw = &hns->hw;
724 : : struct hns3_fd_key_cfg *key_cfg;
725 : : uint8_t *cur_key_x;
726 : : uint8_t *cur_key_y;
727 : : uint8_t key_x[MAX_KEY_BYTES] __rte_aligned(4);
728 : : uint8_t key_y[MAX_KEY_BYTES] __rte_aligned(4);
729 : 0 : uint8_t vf_id = rule->vf_id;
730 : : uint8_t meta_data_region;
731 : : uint8_t tuple_size;
732 : : uint8_t i;
733 : : int ret;
734 : :
735 : : memset(key_x, 0, sizeof(key_x));
736 : : memset(key_y, 0, sizeof(key_y));
737 : : cur_key_x = key_x;
738 : : cur_key_y = key_y;
739 : :
740 : 0 : key_cfg = &pf->fdir.fd_cfg.key_cfg[HNS3_FD_STAGE_1];
741 [ # # ]: 0 : for (i = 0; i < MAX_TUPLE; i++) {
742 : : bool tuple_valid;
743 : :
744 : 0 : tuple_size = tuple_key_info[i].key_length / HNS3_BITS_PER_BYTE;
745 [ # # ]: 0 : if (key_cfg->tuple_active & BIT(i)) {
746 : 0 : tuple_valid = hns3_fd_convert_tuple(hw, i, cur_key_x,
747 : : cur_key_y, rule);
748 [ # # ]: 0 : if (tuple_valid) {
749 : 0 : cur_key_x += tuple_size;
750 : 0 : cur_key_y += tuple_size;
751 : : }
752 : : }
753 : : }
754 : :
755 : 0 : meta_data_region = pf->fdir.fd_cfg.max_key_length / HNS3_BITS_PER_BYTE -
756 : : MAX_META_DATA_LENGTH / HNS3_BITS_PER_BYTE;
757 : :
758 : 0 : hns3_fd_convert_meta_data(key_cfg, vf_id, rule,
759 : : key_x + meta_data_region,
760 : : key_y + meta_data_region);
761 : :
762 : 0 : ret = hns3_fd_tcam_config(hw, false, rule->location, key_y, true);
763 [ # # ]: 0 : if (ret) {
764 : 0 : hns3_err(hw, "Config fd key_y fail, loc=%u, ret=%d",
765 : : rule->queue_id, ret);
766 : 0 : return ret;
767 : : }
768 : :
769 : 0 : ret = hns3_fd_tcam_config(hw, true, rule->location, key_x, true);
770 [ # # ]: 0 : if (ret)
771 : 0 : hns3_err(hw, "Config fd key_x fail, loc=%u, ret=%d",
772 : : rule->queue_id, ret);
773 : : return ret;
774 : : }
775 : :
776 : 0 : static int hns3_config_action(struct hns3_hw *hw, struct hns3_fdir_rule *rule)
777 : : {
778 : : struct hns3_fd_ad_data ad_data;
779 : :
780 : 0 : ad_data.ad_id = rule->location;
781 : :
782 [ # # ]: 0 : if (rule->action == HNS3_FD_ACTION_DROP_PACKET) {
783 : 0 : ad_data.drop_packet = true;
784 : 0 : ad_data.queue_id = 0;
785 : 0 : ad_data.nb_queues = 0;
786 : : } else {
787 : 0 : ad_data.drop_packet = false;
788 : 0 : ad_data.queue_id = rule->queue_id;
789 : 0 : ad_data.nb_queues = rule->nb_queues;
790 : : }
791 : :
792 [ # # ]: 0 : if (unlikely(rule->flags & HNS3_RULE_FLAG_COUNTER)) {
793 : 0 : ad_data.use_counter = true;
794 : 0 : ad_data.counter_id = rule->act_cnt.id;
795 : : } else {
796 : 0 : ad_data.use_counter = false;
797 : 0 : ad_data.counter_id = 0;
798 : : }
799 : :
800 [ # # ]: 0 : if (unlikely(rule->flags & HNS3_RULE_FLAG_FDID))
801 : 0 : ad_data.rule_id = rule->fd_id;
802 : : else
803 : 0 : ad_data.rule_id = rule->location;
804 : :
805 : 0 : ad_data.use_next_stage = false;
806 : 0 : ad_data.next_input_key = 0;
807 : :
808 : 0 : ad_data.write_rule_id_to_bd = true;
809 : :
810 : 0 : return hns3_fd_ad_config(hw, ad_data.ad_id, &ad_data);
811 : : }
812 : :
813 : 0 : static int hns3_fd_clear_all_rules(struct hns3_hw *hw, uint32_t rule_num)
814 : : {
815 : : uint32_t i;
816 : : int ret;
817 : :
818 [ # # ]: 0 : for (i = 0; i < rule_num; i++) {
819 : 0 : ret = hns3_fd_tcam_config(hw, true, i, NULL, false);
820 [ # # ]: 0 : if (ret)
821 : 0 : return ret;
822 : : }
823 : :
824 : : return 0;
825 : : }
826 : :
827 : 0 : int hns3_fdir_filter_init(struct hns3_adapter *hns)
828 : : {
829 : : struct hns3_pf *pf = &hns->pf;
830 : : struct hns3_fdir_info *fdir_info = &pf->fdir;
831 : 0 : uint32_t rule_num = fdir_info->fd_cfg.rule_num[HNS3_FD_STAGE_1];
832 : : char fdir_hash_name[RTE_HASH_NAMESIZE];
833 : 0 : struct rte_hash_parameters fdir_hash_params = {
834 : : .name = fdir_hash_name,
835 : : .entries = rule_num,
836 : : .key_len = sizeof(struct hns3_fdir_key_conf),
837 : : .hash_func = rte_hash_crc,
838 : : .hash_func_init_val = 0,
839 : : };
840 : : int ret;
841 : :
842 : 0 : ret = hns3_fd_clear_all_rules(&hns->hw, rule_num);
843 [ # # ]: 0 : if (ret) {
844 : 0 : PMD_INIT_LOG(ERR, "Clear all fd rules fail! ret = %d", ret);
845 : 0 : return ret;
846 : : }
847 : :
848 : 0 : fdir_hash_params.socket_id = rte_socket_id();
849 : 0 : TAILQ_INIT(&fdir_info->fdir_list);
850 : 0 : snprintf(fdir_hash_name, RTE_HASH_NAMESIZE, "%s", hns->hw.data->name);
851 : 0 : fdir_info->hash_handle = rte_hash_create(&fdir_hash_params);
852 [ # # ]: 0 : if (fdir_info->hash_handle == NULL) {
853 : 0 : PMD_INIT_LOG(ERR, "Create FDIR hash handle fail!");
854 : 0 : return -EINVAL;
855 : : }
856 : 0 : fdir_info->hash_map = rte_zmalloc("hns3 FDIR hash",
857 : : rule_num *
858 : : sizeof(struct hns3_fdir_rule_ele *),
859 : : 0);
860 [ # # ]: 0 : if (fdir_info->hash_map == NULL) {
861 : 0 : PMD_INIT_LOG(ERR, "Allocate memory for FDIR hash map fail!");
862 : 0 : rte_hash_free(fdir_info->hash_handle);
863 : 0 : return -ENOMEM;
864 : : }
865 : :
866 : : return 0;
867 : : }
868 : :
869 : 0 : void hns3_fdir_filter_uninit(struct hns3_adapter *hns)
870 : : {
871 : : struct hns3_pf *pf = &hns->pf;
872 : : struct hns3_fdir_info *fdir_info = &pf->fdir;
873 : : struct hns3_fdir_rule_ele *fdir_filter;
874 : :
875 [ # # ]: 0 : if (fdir_info->hash_map) {
876 : 0 : rte_free(fdir_info->hash_map);
877 : 0 : fdir_info->hash_map = NULL;
878 : : }
879 [ # # ]: 0 : if (fdir_info->hash_handle) {
880 : 0 : rte_hash_free(fdir_info->hash_handle);
881 : 0 : fdir_info->hash_handle = NULL;
882 : : }
883 : :
884 : 0 : fdir_filter = TAILQ_FIRST(&fdir_info->fdir_list);
885 [ # # ]: 0 : while (fdir_filter) {
886 [ # # ]: 0 : TAILQ_REMOVE(&fdir_info->fdir_list, fdir_filter, entries);
887 : 0 : hns3_fd_tcam_config(&hns->hw, true,
888 : 0 : fdir_filter->fdir_conf.location, NULL,
889 : : false);
890 : 0 : rte_free(fdir_filter);
891 : 0 : fdir_filter = TAILQ_FIRST(&fdir_info->fdir_list);
892 : : }
893 : 0 : }
894 : :
895 : : /*
896 : : * Find a key in the hash table.
897 : : * @return
898 : : * - Zero and positive values are key location.
899 : : * - -EINVAL if the parameters are invalid.
900 : : * - -ENOENT if the key is not found.
901 : : */
902 : 0 : static int hns3_fdir_filter_lookup(struct hns3_fdir_info *fdir_info,
903 : : struct hns3_fdir_key_conf *key)
904 : : {
905 : : hash_sig_t sig;
906 : : int ret;
907 : :
908 : 0 : sig = rte_hash_crc(key, sizeof(*key), 0);
909 : 0 : ret = rte_hash_lookup_with_hash(fdir_info->hash_handle, key, sig);
910 : :
911 : 0 : return ret;
912 : : }
913 : :
914 : 0 : static int hns3_insert_fdir_filter(struct hns3_hw *hw,
915 : : struct hns3_fdir_info *fdir_info,
916 : : struct hns3_fdir_rule_ele *fdir_filter)
917 : : {
918 : : struct hns3_fdir_key_conf *key;
919 : : hash_sig_t sig;
920 : : int ret;
921 : :
922 : 0 : key = &fdir_filter->fdir_conf.key_conf;
923 : 0 : sig = rte_hash_crc(key, sizeof(*key), 0);
924 : 0 : ret = rte_hash_add_key_with_hash(fdir_info->hash_handle, key, sig);
925 [ # # ]: 0 : if (ret < 0) {
926 : 0 : hns3_err(hw, "Hash table full? err:%d!", ret);
927 : 0 : return ret;
928 : : }
929 : :
930 : 0 : fdir_info->hash_map[ret] = fdir_filter;
931 : 0 : TAILQ_INSERT_TAIL(&fdir_info->fdir_list, fdir_filter, entries);
932 : :
933 : 0 : return ret;
934 : : }
935 : :
936 : 0 : static int hns3_remove_fdir_filter(struct hns3_hw *hw,
937 : : struct hns3_fdir_info *fdir_info,
938 : : struct hns3_fdir_key_conf *key)
939 : : {
940 : : struct hns3_fdir_rule_ele *fdir_filter;
941 : : hash_sig_t sig;
942 : : int ret;
943 : :
944 : 0 : sig = rte_hash_crc(key, sizeof(*key), 0);
945 : 0 : ret = rte_hash_del_key_with_hash(fdir_info->hash_handle, key, sig);
946 [ # # ]: 0 : if (ret < 0) {
947 : 0 : hns3_err(hw, "Delete hash key fail ret=%d", ret);
948 : 0 : return ret;
949 : : }
950 : :
951 : 0 : fdir_filter = fdir_info->hash_map[ret];
952 : 0 : fdir_info->hash_map[ret] = NULL;
953 [ # # ]: 0 : TAILQ_REMOVE(&fdir_info->fdir_list, fdir_filter, entries);
954 : :
955 : 0 : rte_free(fdir_filter);
956 : :
957 : 0 : return 0;
958 : : }
959 : :
960 : 0 : int hns3_fdir_filter_program(struct hns3_adapter *hns,
961 : : struct hns3_fdir_rule *rule, bool del)
962 : : {
963 : : struct hns3_pf *pf = &hns->pf;
964 : 0 : struct hns3_fdir_info *fdir_info = &pf->fdir;
965 : : struct hns3_fdir_rule_ele *node;
966 : 0 : struct hns3_hw *hw = &hns->hw;
967 : : int ret;
968 : :
969 [ # # ]: 0 : if (del) {
970 : 0 : ret = hns3_fd_tcam_config(hw, true, rule->location, NULL,
971 : : false);
972 [ # # ]: 0 : if (ret)
973 : 0 : hns3_err(hw, "Failed to delete fdir: %u src_ip:%x "
974 : : "dst_ip:%x src_port:%u dst_port:%u ret = %d",
975 : : rule->location,
976 : : rule->key_conf.spec.src_ip[IP_ADDR_KEY_ID],
977 : : rule->key_conf.spec.dst_ip[IP_ADDR_KEY_ID],
978 : : rule->key_conf.spec.src_port,
979 : : rule->key_conf.spec.dst_port, ret);
980 : : else
981 : 0 : ret = hns3_remove_fdir_filter(hw, fdir_info, &rule->key_conf);
982 : :
983 : 0 : return ret;
984 : : }
985 : :
986 : 0 : ret = hns3_fdir_filter_lookup(fdir_info, &rule->key_conf);
987 [ # # ]: 0 : if (ret >= 0) {
988 : 0 : hns3_err(hw, "Conflict with existing fdir loc: %d", ret);
989 : 0 : return -EINVAL;
990 : : }
991 : :
992 : 0 : node = rte_zmalloc("hns3 fdir rule", sizeof(struct hns3_fdir_rule_ele),
993 : : 0);
994 [ # # ]: 0 : if (node == NULL) {
995 : 0 : hns3_err(hw, "Failed to allocate fdir_rule memory");
996 : 0 : return -ENOMEM;
997 : : }
998 : :
999 [ # # ]: 0 : rte_memcpy(&node->fdir_conf, rule, sizeof(struct hns3_fdir_rule));
1000 : 0 : ret = hns3_insert_fdir_filter(hw, fdir_info, node);
1001 [ # # ]: 0 : if (ret < 0) {
1002 : 0 : rte_free(node);
1003 : 0 : return ret;
1004 : : }
1005 : 0 : rule->location = ret;
1006 : 0 : node->fdir_conf.location = ret;
1007 : :
1008 : 0 : ret = hns3_config_action(hw, rule);
1009 [ # # ]: 0 : if (!ret)
1010 : 0 : ret = hns3_config_key(hns, rule);
1011 [ # # ]: 0 : if (ret) {
1012 : 0 : hns3_err(hw, "Failed to config fdir: %u src_ip:%x dst_ip:%x "
1013 : : "src_port:%u dst_port:%u ret = %d",
1014 : : rule->location,
1015 : : rule->key_conf.spec.src_ip[IP_ADDR_KEY_ID],
1016 : : rule->key_conf.spec.dst_ip[IP_ADDR_KEY_ID],
1017 : : rule->key_conf.spec.src_port,
1018 : : rule->key_conf.spec.dst_port, ret);
1019 : 0 : (void)hns3_remove_fdir_filter(hw, fdir_info, &rule->key_conf);
1020 : : }
1021 : :
1022 : : return ret;
1023 : : }
1024 : :
1025 : : /* remove all the flow director filters */
1026 : 0 : int hns3_clear_all_fdir_filter(struct hns3_adapter *hns)
1027 : : {
1028 : : struct hns3_pf *pf = &hns->pf;
1029 : : struct hns3_fdir_info *fdir_info = &pf->fdir;
1030 : : struct hns3_fdir_rule_ele *fdir_filter;
1031 : 0 : struct hns3_hw *hw = &hns->hw;
1032 : : int succ_cnt = 0;
1033 : : int fail_cnt = 0;
1034 : : int ret = 0;
1035 : :
1036 : : /* flush flow director */
1037 : 0 : rte_hash_reset(fdir_info->hash_handle);
1038 : :
1039 : 0 : memset(fdir_info->hash_map, 0,
1040 : : sizeof(struct hns3_fdir_rule_ele *) *
1041 : 0 : fdir_info->fd_cfg.rule_num[HNS3_FD_STAGE_1]);
1042 : :
1043 : 0 : fdir_filter = TAILQ_FIRST(&fdir_info->fdir_list);
1044 [ # # ]: 0 : while (fdir_filter) {
1045 [ # # ]: 0 : TAILQ_REMOVE(&fdir_info->fdir_list, fdir_filter, entries);
1046 : 0 : ret = hns3_fd_tcam_config(hw, true,
1047 : 0 : fdir_filter->fdir_conf.location,
1048 : : NULL, false);
1049 [ # # ]: 0 : if (ret == 0)
1050 : 0 : succ_cnt++;
1051 : : else
1052 : 0 : fail_cnt++;
1053 : 0 : rte_free(fdir_filter);
1054 : 0 : fdir_filter = TAILQ_FIRST(&fdir_info->fdir_list);
1055 : : }
1056 : :
1057 [ # # ]: 0 : if (fail_cnt > 0) {
1058 : 0 : hns3_err(hw, "fail to delete all FDIR filter, success num = %d "
1059 : : "fail num = %d", succ_cnt, fail_cnt);
1060 : : ret = -EIO;
1061 : : }
1062 : :
1063 : 0 : return ret;
1064 : : }
1065 : :
1066 : 0 : int hns3_restore_all_fdir_filter(struct hns3_adapter *hns)
1067 : : {
1068 : : struct hns3_pf *pf = &hns->pf;
1069 : : struct hns3_fdir_info *fdir_info = &pf->fdir;
1070 : : struct hns3_fdir_rule_ele *fdir_filter;
1071 : 0 : struct hns3_hw *hw = &hns->hw;
1072 : : bool err = false;
1073 : : int ret;
1074 : :
1075 [ # # ]: 0 : if (hns->is_vf)
1076 : : return 0;
1077 : :
1078 : : /*
1079 : : * This API is called in the reset recovery process, the parent function
1080 : : * must hold hw->lock.
1081 : : * There maybe deadlock if acquire hw->flows_lock directly because rte
1082 : : * flow driver ops first acquire hw->flows_lock and then may acquire
1083 : : * hw->lock.
1084 : : * So here first release the hw->lock and then acquire the
1085 : : * hw->flows_lock to avoid deadlock.
1086 : : */
1087 : 0 : rte_spinlock_unlock(&hw->lock);
1088 : 0 : pthread_mutex_lock(&hw->flows_lock);
1089 [ # # ]: 0 : TAILQ_FOREACH(fdir_filter, &fdir_info->fdir_list, entries) {
1090 : 0 : ret = hns3_config_action(hw, &fdir_filter->fdir_conf);
1091 [ # # ]: 0 : if (!ret)
1092 : 0 : ret = hns3_config_key(hns, &fdir_filter->fdir_conf);
1093 [ # # ]: 0 : if (ret) {
1094 : : err = true;
1095 [ # # ]: 0 : if (ret == -EBUSY)
1096 : : break;
1097 : : }
1098 : : }
1099 : 0 : pthread_mutex_unlock(&hw->flows_lock);
1100 : : rte_spinlock_lock(&hw->lock);
1101 : :
1102 [ # # ]: 0 : if (err) {
1103 : 0 : hns3_err(hw, "Fail to restore FDIR filter, ret = %d", ret);
1104 : 0 : return -EIO;
1105 : : }
1106 : : return 0;
1107 : : }
1108 : :
1109 : 0 : int hns3_fd_get_count(struct hns3_hw *hw, uint32_t id, uint64_t *value)
1110 : : {
1111 : : struct hns3_fd_get_cnt_cmd *req;
1112 : : struct hns3_cmd_desc desc;
1113 : : int ret;
1114 : :
1115 : 0 : hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_FD_COUNTER_OP, true);
1116 : :
1117 : : req = (struct hns3_fd_get_cnt_cmd *)desc.data;
1118 : 0 : req->stage = HNS3_FD_STAGE_1;
1119 : 0 : req->index = rte_cpu_to_le_32(id);
1120 : :
1121 : 0 : ret = hns3_cmd_send(hw, &desc, 1);
1122 [ # # ]: 0 : if (ret) {
1123 : 0 : hns3_err(hw, "Read counter fail, ret=%d", ret);
1124 : 0 : return ret;
1125 : : }
1126 : :
1127 : 0 : *value = req->value;
1128 : :
1129 : 0 : return ret;
1130 : : }
|