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 : static void hns3_set_tuple_config(struct hns3_adapter *hns,
304 : : struct hns3_fd_key_cfg *key_cfg)
305 : : {
306 : 0 : enum hns3_fdir_tuple_config tuple_cfg = hns->pf.fdir.tuple_cfg;
307 : :
308 [ # # ]: 0 : if (tuple_cfg == HNS3_FDIR_TUPLE_CONFIG_DEFAULT)
309 : : return;
310 : :
311 [ # # ]: 0 : if (hns->pf.fdir.fd_cfg.max_key_length != MAX_KEY_LENGTH) {
312 : 0 : hns3_warn(&hns->hw, "fdir tuple config only valid with 400bit key!");
313 : 0 : return;
314 : : }
315 : :
316 [ # # # # : 0 : switch (tuple_cfg) {
# # # ]
317 : 0 : case HNS3_FDIR_TUPLE_OUTVLAN_REPLACE_INSMAC:
318 : 0 : key_cfg->tuple_active &= ~BIT(INNER_SRC_MAC);
319 : 0 : key_cfg->tuple_active |= BIT(OUTER_VLAN_TAG_FST);
320 : 0 : key_cfg->tuple_active |= BIT(OUTER_VLAN_TAG_SEC);
321 : 0 : break;
322 : 0 : case HNS3_FDIR_TUPLE_OUTVLAN_REPLACE_INDMAC:
323 : 0 : key_cfg->tuple_active &= ~BIT(INNER_DST_MAC);
324 : 0 : key_cfg->tuple_active |= BIT(OUTER_VLAN_TAG_FST);
325 : 0 : key_cfg->tuple_active |= BIT(OUTER_VLAN_TAG_SEC);
326 : 0 : break;
327 : 0 : case HNS3_FDIR_TUPLE_OUTVLAN_REPLACE_INSIP:
328 : 0 : key_cfg->tuple_active &= ~BIT(INNER_SRC_IP);
329 : 0 : key_cfg->tuple_active |= BIT(OUTER_VLAN_TAG_FST);
330 : 0 : key_cfg->tuple_active |= BIT(OUTER_VLAN_TAG_SEC);
331 : 0 : break;
332 : 0 : case HNS3_FDIR_TUPLE_OUTVLAN_REPLACE_INDIP:
333 : 0 : key_cfg->tuple_active &= ~BIT(INNER_DST_IP);
334 : 0 : key_cfg->tuple_active |= BIT(OUTER_VLAN_TAG_FST);
335 : 0 : key_cfg->tuple_active |= BIT(OUTER_VLAN_TAG_SEC);
336 : 0 : break;
337 : 0 : case HNS3_FDIR_TUPLE_OUTVLAN_REPLACE_SCTPTAG:
338 : 0 : key_cfg->tuple_active &= ~BIT(INNER_SCTP_TAG);
339 : 0 : key_cfg->tuple_active |= BIT(OUTER_VLAN_TAG_FST);
340 : 0 : key_cfg->tuple_active |= BIT(OUTER_VLAN_TAG_SEC);
341 : 0 : break;
342 : 0 : case HNS3_FDIR_TUPLE_OUTVLAN_REPLACE_TUNVNI:
343 : 0 : key_cfg->tuple_active &= ~BIT(OUTER_TUN_VNI);
344 : 0 : key_cfg->tuple_active |= BIT(OUTER_VLAN_TAG_FST);
345 : 0 : key_cfg->tuple_active |= BIT(OUTER_VLAN_TAG_SEC);
346 : 0 : break;
347 : 0 : default:
348 : 0 : hns3_err(&hns->hw, "invalid fdir tuple config %u!", tuple_cfg);
349 : 0 : return;
350 : : }
351 : :
352 : 0 : hns3_info(&hns->hw, "fdir tuple config %s!", hns3_tuple_config_name(tuple_cfg));
353 : : }
354 : :
355 : 0 : int hns3_init_fd_config(struct hns3_adapter *hns)
356 : : {
357 : : struct hns3_pf *pf = &hns->pf;
358 : 0 : struct hns3_hw *hw = &hns->hw;
359 : : struct hns3_fd_key_cfg *key_cfg;
360 : : int ret;
361 : :
362 : 0 : ret = hns3_get_fd_mode(hw, &pf->fdir.fd_cfg.fd_mode);
363 [ # # ]: 0 : if (ret)
364 : : return ret;
365 : :
366 [ # # # ]: 0 : switch (pf->fdir.fd_cfg.fd_mode) {
367 : 0 : case HNS3_FD_MODE_DEPTH_2K_WIDTH_400B_STAGE_1:
368 : 0 : pf->fdir.fd_cfg.max_key_length = MAX_KEY_LENGTH;
369 : 0 : break;
370 : 0 : case HNS3_FD_MODE_DEPTH_4K_WIDTH_200B_STAGE_1:
371 : 0 : pf->fdir.fd_cfg.max_key_length = MAX_200B_KEY_LENGTH;
372 : 0 : hns3_warn(hw, "Unsupported tunnel filter in 4K*200Bit");
373 : 0 : break;
374 : 0 : default:
375 : 0 : hns3_err(hw, "Unsupported flow director mode %u",
376 : : pf->fdir.fd_cfg.fd_mode);
377 : 0 : return -EOPNOTSUPP;
378 : : }
379 : :
380 : 0 : key_cfg = &pf->fdir.fd_cfg.key_cfg[HNS3_FD_STAGE_1];
381 : 0 : key_cfg->key_sel = HNS3_FD_KEY_BASE_ON_TUPLE;
382 : 0 : key_cfg->inner_sipv6_word_en = IPV6_ADDR_WORD_MASK;
383 : 0 : key_cfg->inner_dipv6_word_en = IPV6_ADDR_WORD_MASK;
384 : 0 : key_cfg->outer_sipv6_word_en = 0;
385 : 0 : key_cfg->outer_dipv6_word_en = 0;
386 : :
387 : 0 : key_cfg->tuple_active = BIT(INNER_VLAN_TAG1) | BIT(INNER_ETH_TYPE) |
388 : : BIT(INNER_IP_PROTO) | BIT(INNER_IP_TOS) |
389 : : BIT(INNER_SRC_IP) | BIT(INNER_DST_IP) |
390 : : BIT(INNER_SRC_PORT) | BIT(INNER_DST_PORT);
391 : 0 : hns3_dbg(hw, "fdir tuple: inner<vlan_tag1 eth_type ip_src ip_dst "
392 : : "ip_proto ip_tos l4_src_port l4_dst_port>");
393 : :
394 : : /* If use max 400bit key, we can support tuples for ether type */
395 [ # # ]: 0 : if (pf->fdir.fd_cfg.max_key_length == MAX_KEY_LENGTH) {
396 : 0 : key_cfg->tuple_active |=
397 : : BIT(INNER_DST_MAC) | BIT(INNER_SRC_MAC) |
398 : : BIT(OUTER_SRC_PORT) | BIT(INNER_SCTP_TAG) |
399 : : BIT(OUTER_DST_PORT) | BIT(INNER_VLAN_TAG2) |
400 : : BIT(OUTER_TUN_VNI) | BIT(OUTER_TUN_FLOW_ID) |
401 : : BIT(OUTER_ETH_TYPE) | BIT(OUTER_IP_PROTO);
402 : 0 : hns3_dbg(hw, "fdir tuple more: inner<dst_mac src_mac "
403 : : "vlan_tag2 sctp_tag> outer<eth_type ip_proto "
404 : : "l4_src_port l4_dst_port tun_vni tun_flow_id>");
405 : : }
406 : :
407 : 0 : hns3_set_tuple_config(hns, key_cfg);
408 : :
409 : : /* roce_type is used to filter roce frames
410 : : * dst_vport is used to specify the rule
411 : : */
412 : 0 : key_cfg->meta_data_active = BIT(DST_VPORT) | BIT(TUNNEL_PACKET);
413 [ # # ]: 0 : if (pf->fdir.vlan_match_mode)
414 : 0 : key_cfg->meta_data_active |= BIT(VLAN_NUMBER);
415 : :
416 [ # # ]: 0 : hns3_dbg(hw, "fdir meta data: dst_vport tunnel_packet %s",
417 : : (pf->fdir.vlan_match_mode == HNS3_FDIR_VLAN_STRICT_MATCH) ?
418 : : "vlan_number" : "");
419 : :
420 : 0 : ret = hns3_get_fd_allocation(hw,
421 : : &pf->fdir.fd_cfg.rule_num[HNS3_FD_STAGE_1],
422 : : &pf->fdir.fd_cfg.rule_num[HNS3_FD_STAGE_2],
423 : : &pf->fdir.fd_cfg.cnt_num[HNS3_FD_STAGE_1],
424 : : &pf->fdir.fd_cfg.cnt_num[HNS3_FD_STAGE_2]);
425 [ # # ]: 0 : if (ret)
426 : : return ret;
427 : :
428 : 0 : hns3_dbg(hw, "fdir: stage1<rules-%u counters-%u> stage2<rules-%u counters=%u>",
429 : : pf->fdir.fd_cfg.rule_num[HNS3_FD_STAGE_1],
430 : : pf->fdir.fd_cfg.cnt_num[HNS3_FD_STAGE_1],
431 : : pf->fdir.fd_cfg.rule_num[HNS3_FD_STAGE_2],
432 : : pf->fdir.fd_cfg.cnt_num[HNS3_FD_STAGE_2]);
433 : :
434 : 0 : return hns3_set_fd_key_config(hns);
435 : : }
436 : :
437 : 0 : static int hns3_fd_tcam_config(struct hns3_hw *hw, bool sel_x, int loc,
438 : : uint8_t *key, bool is_add)
439 : : {
440 : : #define FD_TCAM_CMD_NUM 3
441 : : struct hns3_fd_tcam_config_1_cmd *req1;
442 : : struct hns3_fd_tcam_config_2_cmd *req2;
443 : : struct hns3_fd_tcam_config_3_cmd *req3;
444 : : struct hns3_cmd_desc desc[FD_TCAM_CMD_NUM];
445 : : int len;
446 : : int ret;
447 : :
448 : 0 : hns3_cmd_setup_basic_desc(&desc[0], HNS3_OPC_FD_TCAM_OP, false);
449 : 0 : desc[0].flag |= rte_cpu_to_le_16(HNS3_CMD_FLAG_NEXT);
450 : 0 : hns3_cmd_setup_basic_desc(&desc[1], HNS3_OPC_FD_TCAM_OP, false);
451 : 0 : desc[1].flag |= rte_cpu_to_le_16(HNS3_CMD_FLAG_NEXT);
452 : 0 : hns3_cmd_setup_basic_desc(&desc[2], HNS3_OPC_FD_TCAM_OP, false);
453 : :
454 : : req1 = (struct hns3_fd_tcam_config_1_cmd *)desc[0].data;
455 : : req2 = (struct hns3_fd_tcam_config_2_cmd *)desc[1].data;
456 : : req3 = (struct hns3_fd_tcam_config_3_cmd *)desc[2].data;
457 : :
458 : 0 : req1->stage = HNS3_FD_STAGE_1;
459 : 0 : req1->xy_sel = sel_x ? 1 : 0;
460 : 0 : hns3_set_bit(req1->port_info, HNS3_FD_EPORT_SW_EN_B, 0);
461 : 0 : req1->index = rte_cpu_to_le_32(loc);
462 [ # # ]: 0 : req1->entry_vld = sel_x ? is_add : 0;
463 : :
464 [ # # ]: 0 : if (key) {
465 : : len = sizeof(req1->tcam_data);
466 : : memcpy(req1->tcam_data, key, len);
467 : 0 : key += len;
468 : :
469 : : len = sizeof(req2->tcam_data);
470 : : memcpy(req2->tcam_data, key, len);
471 : 0 : key += len;
472 : :
473 : : len = sizeof(req3->tcam_data);
474 : : memcpy(req3->tcam_data, key, len);
475 : : }
476 : :
477 : 0 : ret = hns3_cmd_send(hw, desc, FD_TCAM_CMD_NUM);
478 [ # # ]: 0 : if (ret)
479 : 0 : hns3_err(hw, "Config tcam key fail, ret=%d loc=%d add=%d",
480 : : ret, loc, is_add);
481 : 0 : return ret;
482 : : }
483 : :
484 : 0 : static int hns3_fd_ad_config(struct hns3_hw *hw, int loc,
485 : : struct hns3_fd_ad_data *action)
486 : : {
487 : : struct hns3_fd_ad_config_cmd *req;
488 : : struct hns3_cmd_desc desc;
489 : : uint64_t ad_data = 0;
490 : : int ret;
491 : :
492 : 0 : hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_FD_AD_OP, false);
493 : :
494 : : req = (struct hns3_fd_ad_config_cmd *)desc.data;
495 : 0 : req->index = rte_cpu_to_le_32(loc);
496 : 0 : req->stage = HNS3_FD_STAGE_1;
497 : :
498 : 0 : hns3_set_bit(ad_data, HNS3_FD_AD_WR_RULE_ID_B,
499 : : action->write_rule_id_to_bd);
500 : 0 : hns3_set_field(ad_data, HNS3_FD_AD_RULE_ID_M, HNS3_FD_AD_RULE_ID_S,
501 : : action->rule_id);
502 [ # # ]: 0 : if (action->nb_queues > 1) {
503 : 0 : hns3_set_bit(ad_data, HNS3_FD_AD_QUEUE_REGION_EN_B, 1);
504 : 0 : hns3_set_field(ad_data, HNS3_FD_AD_QUEUE_REGION_SIZE_M,
505 : : HNS3_FD_AD_QUEUE_REGION_SIZE_S,
506 : : rte_log2_u32(action->nb_queues));
507 : : }
508 : : /* set extend bit if counter_id is in [128 ~ 255] */
509 [ # # ]: 0 : if (action->counter_id & BIT(HNS3_FD_AD_COUNTER_HIGH_BIT))
510 : 0 : hns3_set_bit(ad_data, HNS3_FD_AD_COUNTER_HIGH_BIT_B, 1);
511 : : /* set extend bit if queue id > 1024 */
512 [ # # ]: 0 : if (action->queue_id & BIT(HNS3_FD_AD_QUEUE_ID_HIGH_BIT))
513 : 0 : hns3_set_bit(ad_data, HNS3_FD_AD_QUEUE_ID_HIGH_BIT_B, 1);
514 : 0 : ad_data <<= HNS3_FD_AD_DATA_S;
515 : 0 : hns3_set_bit(ad_data, HNS3_FD_AD_DROP_B, action->drop_packet);
516 [ # # ]: 0 : if (action->nb_queues == 1)
517 : 0 : hns3_set_bit(ad_data, HNS3_FD_AD_DIRECT_QID_B, 1);
518 : 0 : hns3_set_field(ad_data, HNS3_FD_AD_QID_M, HNS3_FD_AD_QID_S,
519 : : action->queue_id);
520 : 0 : hns3_set_bit(ad_data, HNS3_FD_AD_USE_COUNTER_B, action->use_counter);
521 : 0 : hns3_set_field(ad_data, HNS3_FD_AD_COUNTER_NUM_M,
522 : : HNS3_FD_AD_COUNTER_NUM_S, action->counter_id);
523 : 0 : hns3_set_bit(ad_data, HNS3_FD_AD_NXT_STEP_B, action->use_next_stage);
524 : 0 : hns3_set_field(ad_data, HNS3_FD_AD_NXT_KEY_M, HNS3_FD_AD_NXT_KEY_S,
525 : : action->next_input_key);
526 : :
527 : 0 : req->ad_data = rte_cpu_to_le_64(ad_data);
528 : 0 : ret = hns3_cmd_send(hw, &desc, 1);
529 [ # # ]: 0 : if (ret)
530 : 0 : hns3_err(hw, "Config fd ad fail, ret=%d loc=%d", ret, loc);
531 : :
532 : 0 : return ret;
533 : : }
534 : :
535 : : static inline void hns3_fd_convert_mac(uint8_t *key, uint8_t *mask,
536 : : uint8_t *mac_x, uint8_t *mac_y)
537 : : {
538 : : uint8_t tmp;
539 : : int i;
540 : :
541 [ # # # # ]: 0 : for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) {
542 : 0 : tmp = RTE_ETHER_ADDR_LEN - 1 - i;
543 : 0 : calc_x(mac_x[tmp], key[i], mask[i]);
544 : 0 : calc_y(mac_y[tmp], key[i], mask[i]);
545 : : }
546 : : }
547 : :
548 : 0 : static void hns3_fd_convert_int16(uint32_t tuple, struct hns3_fdir_rule *rule,
549 : : uint8_t *val_x, uint8_t *val_y)
550 : : {
551 : : uint16_t tmp_x_s;
552 : : uint16_t tmp_y_s;
553 : : uint16_t mask;
554 : : uint16_t key;
555 : :
556 [ # # # # : 0 : switch (tuple) {
# # # # #
# ]
557 : 0 : case OUTER_VLAN_TAG_FST:
558 : 0 : key = rule->key_conf.spec.outer_vlan_tag1;
559 : 0 : mask = rule->key_conf.mask.outer_vlan_tag1;
560 : 0 : break;
561 : 0 : case OUTER_VLAN_TAG_SEC:
562 : 0 : key = rule->key_conf.spec.outer_vlan_tag2;
563 : 0 : mask = rule->key_conf.mask.outer_vlan_tag2;
564 : 0 : break;
565 : 0 : case OUTER_SRC_PORT:
566 : 0 : key = rule->key_conf.spec.outer_src_port;
567 : 0 : mask = rule->key_conf.mask.outer_src_port;
568 : 0 : break;
569 : 0 : case OUTER_DST_PORT:
570 : 0 : key = rule->key_conf.spec.tunnel_type;
571 : 0 : mask = rule->key_conf.mask.tunnel_type;
572 : 0 : break;
573 : 0 : case OUTER_ETH_TYPE:
574 : 0 : key = rule->key_conf.spec.outer_ether_type;
575 : 0 : mask = rule->key_conf.mask.outer_ether_type;
576 : 0 : break;
577 : 0 : case INNER_SRC_PORT:
578 : 0 : key = rule->key_conf.spec.src_port;
579 : 0 : mask = rule->key_conf.mask.src_port;
580 : 0 : break;
581 : 0 : case INNER_DST_PORT:
582 : 0 : key = rule->key_conf.spec.dst_port;
583 : 0 : mask = rule->key_conf.mask.dst_port;
584 : 0 : break;
585 : 0 : case INNER_VLAN_TAG1:
586 : 0 : key = rule->key_conf.spec.vlan_tag1;
587 : 0 : mask = rule->key_conf.mask.vlan_tag1;
588 : 0 : break;
589 : 0 : case INNER_VLAN_TAG2:
590 : 0 : key = rule->key_conf.spec.vlan_tag2;
591 : 0 : mask = rule->key_conf.mask.vlan_tag2;
592 : 0 : break;
593 : 0 : default:
594 : : /* INNER_ETH_TYPE: */
595 : 0 : key = rule->key_conf.spec.ether_type;
596 : 0 : mask = rule->key_conf.mask.ether_type;
597 : 0 : break;
598 : : }
599 : 0 : calc_x(tmp_x_s, key, mask);
600 : 0 : calc_y(tmp_y_s, key, mask);
601 : 0 : val_x[0] = rte_cpu_to_le_16(tmp_x_s) & 0xFF;
602 : 0 : val_x[1] = rte_cpu_to_le_16(tmp_x_s) >> HNS3_BITS_PER_BYTE;
603 : 0 : val_y[0] = rte_cpu_to_le_16(tmp_y_s) & 0xFF;
604 : 0 : val_y[1] = rte_cpu_to_le_16(tmp_y_s) >> HNS3_BITS_PER_BYTE;
605 : 0 : }
606 : :
607 : 0 : static inline void hns3_fd_convert_int32(uint32_t key, uint32_t mask,
608 : : uint8_t *val_x, uint8_t *val_y)
609 : : {
610 : : uint32_t tmp_x_l;
611 : : uint32_t tmp_y_l;
612 : :
613 : 0 : calc_x(tmp_x_l, key, mask);
614 : 0 : calc_y(tmp_y_l, key, mask);
615 : : memcpy(val_x, &tmp_x_l, sizeof(tmp_x_l));
616 : : memcpy(val_y, &tmp_y_l, sizeof(tmp_y_l));
617 : 0 : }
618 : :
619 : 0 : static bool hns3_fd_convert_tuple(struct hns3_hw *hw,
620 : : uint32_t tuple, uint8_t *key_x,
621 : : uint8_t *key_y, struct hns3_fdir_rule *rule)
622 : : {
623 : : struct hns3_fdir_key_conf *key_conf;
624 : : int tmp;
625 : : int i;
626 : :
627 [ # # ]: 0 : if ((rule->input_set & BIT(tuple)) == 0)
628 : : return true;
629 : :
630 : : key_conf = &rule->key_conf;
631 [ # # # # : 0 : switch (tuple) {
# # # # #
# # # ]
632 : 0 : case INNER_DST_MAC:
633 : 0 : hns3_fd_convert_mac(key_conf->spec.dst_mac,
634 : 0 : key_conf->mask.dst_mac, key_x, key_y);
635 : : break;
636 : 0 : case INNER_SRC_MAC:
637 : 0 : hns3_fd_convert_mac(key_conf->spec.src_mac,
638 : 0 : key_conf->mask.src_mac, key_x, key_y);
639 : : break;
640 : 0 : case OUTER_VLAN_TAG_FST:
641 : : case OUTER_VLAN_TAG_SEC:
642 : : case OUTER_SRC_PORT:
643 : : case OUTER_DST_PORT:
644 : : case OUTER_ETH_TYPE:
645 : : case INNER_SRC_PORT:
646 : : case INNER_DST_PORT:
647 : : case INNER_VLAN_TAG1:
648 : : case INNER_VLAN_TAG2:
649 : : case INNER_ETH_TYPE:
650 : 0 : hns3_fd_convert_int16(tuple, rule, key_x, key_y);
651 : 0 : break;
652 : 0 : case INNER_SRC_IP:
653 : 0 : hns3_fd_convert_int32(key_conf->spec.src_ip[IP_ADDR_KEY_ID],
654 : : key_conf->mask.src_ip[IP_ADDR_KEY_ID],
655 : : key_x, key_y);
656 : 0 : break;
657 : 0 : case INNER_DST_IP:
658 : 0 : hns3_fd_convert_int32(key_conf->spec.dst_ip[IP_ADDR_KEY_ID],
659 : : key_conf->mask.dst_ip[IP_ADDR_KEY_ID],
660 : : key_x, key_y);
661 : 0 : break;
662 : 0 : case INNER_SCTP_TAG:
663 : 0 : hns3_fd_convert_int32(key_conf->spec.sctp_tag,
664 : : key_conf->mask.sctp_tag, key_x, key_y);
665 : 0 : break;
666 : : case OUTER_TUN_VNI:
667 [ # # ]: 0 : for (i = 0; i < VNI_OR_TNI_LEN; i++) {
668 : 0 : tmp = VNI_OR_TNI_LEN - 1 - i;
669 : 0 : calc_x(key_x[tmp],
670 : : key_conf->spec.outer_tun_vni[i],
671 : : key_conf->mask.outer_tun_vni[i]);
672 : 0 : calc_y(key_y[tmp],
673 : : key_conf->spec.outer_tun_vni[i],
674 : : key_conf->mask.outer_tun_vni[i]);
675 : : }
676 : : break;
677 : 0 : case OUTER_TUN_FLOW_ID:
678 : 0 : calc_x(*key_x, key_conf->spec.outer_tun_flow_id,
679 : : key_conf->mask.outer_tun_flow_id);
680 : 0 : calc_y(*key_y, key_conf->spec.outer_tun_flow_id,
681 : : key_conf->mask.outer_tun_flow_id);
682 : 0 : break;
683 : 0 : case INNER_IP_TOS:
684 : 0 : calc_x(*key_x, key_conf->spec.ip_tos, key_conf->mask.ip_tos);
685 : 0 : calc_y(*key_y, key_conf->spec.ip_tos, key_conf->mask.ip_tos);
686 : 0 : break;
687 : 0 : case OUTER_IP_PROTO:
688 : 0 : calc_x(*key_x, key_conf->spec.outer_proto,
689 : : key_conf->mask.outer_proto);
690 : 0 : calc_y(*key_y, key_conf->spec.outer_proto,
691 : : key_conf->mask.outer_proto);
692 : 0 : break;
693 : 0 : case INNER_IP_PROTO:
694 : 0 : calc_x(*key_x, key_conf->spec.ip_proto,
695 : : key_conf->mask.ip_proto);
696 : 0 : calc_y(*key_y, key_conf->spec.ip_proto,
697 : : key_conf->mask.ip_proto);
698 : 0 : break;
699 : 0 : default:
700 : 0 : hns3_warn(hw, "not support tuple of (%u)", tuple);
701 : 0 : return false;
702 : : }
703 : : return true;
704 : : }
705 : :
706 : : static uint32_t hns3_get_port_number(uint8_t pf_id, uint8_t vf_id)
707 : : {
708 : : uint32_t port_number = 0;
709 : :
710 : : hns3_set_field(port_number, HNS3_PF_ID_M, HNS3_PF_ID_S, pf_id);
711 : 0 : hns3_set_field(port_number, HNS3_VF_ID_M, HNS3_VF_ID_S, vf_id);
712 : : hns3_set_bit(port_number, HNS3_PORT_TYPE_B, HOST_PORT);
713 : :
714 : : return port_number;
715 : : }
716 : :
717 : 0 : static void hns3_fd_convert_meta_data(struct hns3_fd_key_cfg *cfg,
718 : : uint8_t vf_id,
719 : : struct hns3_fdir_rule *rule,
720 : : uint8_t *key_x, uint8_t *key_y)
721 : : {
722 : : uint16_t meta_data = 0;
723 : : uint32_t port_number;
724 : : uint8_t cur_pos = 0;
725 : : uint8_t tuple_size;
726 : : uint8_t shift_bits;
727 : : uint32_t tmp_x;
728 : : uint32_t tmp_y;
729 : : uint8_t i;
730 : :
731 [ # # ]: 0 : for (i = 0; i < MAX_META_DATA; i++) {
732 [ # # ]: 0 : if ((cfg->meta_data_active & BIT(i)) == 0)
733 : 0 : continue;
734 : :
735 : 0 : tuple_size = meta_data_key_info[i].key_length;
736 [ # # ]: 0 : if (i == TUNNEL_PACKET) {
737 : 0 : hns3_set_bit(meta_data, cur_pos,
738 : : rule->key_conf.spec.tunnel_type ? 1 : 0);
739 : 0 : cur_pos += tuple_size;
740 [ # # ]: 0 : } else if (i == VLAN_NUMBER) {
741 : : uint32_t vlan_tag;
742 : : uint8_t vlan_num;
743 : :
744 [ # # ]: 0 : if (rule->key_conf.spec.tunnel_type == 0)
745 : 0 : vlan_num = rule->key_conf.vlan_num;
746 : : else
747 : 0 : vlan_num = rule->key_conf.outer_vlan_num;
748 [ # # ]: 0 : if (vlan_num == 1)
749 : : vlan_tag = HNS3_VLAN_TAG_TYPE_TAG1;
750 [ # # ]: 0 : else if (vlan_num == VLAN_TAG_NUM_MAX)
751 : : vlan_tag = HNS3_VLAN_TAG_TYPE_TAG1_2;
752 : : else
753 : : vlan_tag = HNS3_VLAN_TAG_TYPE_NONE;
754 : 0 : hns3_set_field(meta_data,
755 : : GENMASK(cur_pos + tuple_size,
756 : : cur_pos), cur_pos, vlan_tag);
757 : 0 : cur_pos += tuple_size;
758 [ # # ]: 0 : } else if (i == DST_VPORT) {
759 : 0 : port_number = hns3_get_port_number(0, vf_id);
760 : 0 : hns3_set_field(meta_data,
761 : : GENMASK(cur_pos + tuple_size, cur_pos),
762 : : cur_pos, port_number);
763 : 0 : cur_pos += tuple_size;
764 : : }
765 : : }
766 : :
767 : 0 : calc_x(tmp_x, meta_data, 0xFFFF);
768 : 0 : calc_y(tmp_y, meta_data, 0xFFFF);
769 : 0 : shift_bits = sizeof(meta_data) * HNS3_BITS_PER_BYTE - cur_pos;
770 : :
771 : 0 : tmp_x = rte_cpu_to_le_32(tmp_x << shift_bits);
772 : 0 : tmp_y = rte_cpu_to_le_32(tmp_y << shift_bits);
773 : 0 : key_x[0] = tmp_x & 0xFF;
774 : 0 : key_x[1] = (tmp_x >> HNS3_BITS_PER_BYTE) & 0xFF;
775 : 0 : key_y[0] = tmp_y & 0xFF;
776 : 0 : key_y[1] = (tmp_y >> HNS3_BITS_PER_BYTE) & 0xFF;
777 : 0 : }
778 : :
779 : : /* A complete key is combined with meta data key and tuple key.
780 : : * Meta data key is stored at the MSB region, and tuple key is stored at
781 : : * the LSB region, unused bits will be filled 0.
782 : : */
783 : 0 : static int hns3_config_key(struct hns3_adapter *hns,
784 : : struct hns3_fdir_rule *rule)
785 : : {
786 : : struct hns3_pf *pf = &hns->pf;
787 : 0 : struct hns3_hw *hw = &hns->hw;
788 : : struct hns3_fd_key_cfg *key_cfg;
789 : : uint8_t *cur_key_x;
790 : : uint8_t *cur_key_y;
791 : : alignas(4) uint8_t key_x[MAX_KEY_BYTES];
792 : : alignas(4) uint8_t key_y[MAX_KEY_BYTES];
793 : 0 : uint8_t vf_id = rule->vf_id;
794 : : uint8_t meta_data_region;
795 : : uint8_t tuple_size;
796 : : uint8_t i;
797 : : int ret;
798 : :
799 : : memset(key_x, 0, sizeof(key_x));
800 : : memset(key_y, 0, sizeof(key_y));
801 : : cur_key_x = key_x;
802 : : cur_key_y = key_y;
803 : :
804 : 0 : key_cfg = &pf->fdir.fd_cfg.key_cfg[HNS3_FD_STAGE_1];
805 [ # # ]: 0 : for (i = 0; i < MAX_TUPLE; i++) {
806 : : bool tuple_valid;
807 : :
808 : 0 : tuple_size = tuple_key_info[i].key_length / HNS3_BITS_PER_BYTE;
809 [ # # ]: 0 : if (key_cfg->tuple_active & BIT(i)) {
810 : 0 : tuple_valid = hns3_fd_convert_tuple(hw, i, cur_key_x,
811 : : cur_key_y, rule);
812 [ # # ]: 0 : if (tuple_valid) {
813 : 0 : cur_key_x += tuple_size;
814 : 0 : cur_key_y += tuple_size;
815 : : }
816 : : }
817 : : }
818 : :
819 : 0 : meta_data_region = pf->fdir.fd_cfg.max_key_length / HNS3_BITS_PER_BYTE -
820 : : MAX_META_DATA_LENGTH / HNS3_BITS_PER_BYTE;
821 : :
822 : 0 : hns3_fd_convert_meta_data(key_cfg, vf_id, rule,
823 : : key_x + meta_data_region,
824 : : key_y + meta_data_region);
825 : :
826 : 0 : ret = hns3_fd_tcam_config(hw, false, rule->location, key_y, true);
827 [ # # ]: 0 : if (ret) {
828 : 0 : hns3_err(hw, "Config fd key_y fail, loc=%u, ret=%d",
829 : : rule->queue_id, ret);
830 : 0 : return ret;
831 : : }
832 : :
833 : 0 : ret = hns3_fd_tcam_config(hw, true, rule->location, key_x, true);
834 [ # # ]: 0 : if (ret)
835 : 0 : hns3_err(hw, "Config fd key_x fail, loc=%u, ret=%d",
836 : : rule->queue_id, ret);
837 : : return ret;
838 : : }
839 : :
840 : 0 : static int hns3_config_action(struct hns3_hw *hw, struct hns3_fdir_rule *rule)
841 : : {
842 : : struct hns3_fd_ad_data ad_data;
843 : :
844 : 0 : ad_data.ad_id = rule->location;
845 : :
846 [ # # ]: 0 : if (rule->action == HNS3_FD_ACTION_DROP_PACKET) {
847 : 0 : ad_data.drop_packet = true;
848 : 0 : ad_data.queue_id = 0;
849 : 0 : ad_data.nb_queues = 0;
850 : : } else {
851 : 0 : ad_data.drop_packet = false;
852 : 0 : ad_data.queue_id = rule->queue_id;
853 : 0 : ad_data.nb_queues = rule->nb_queues;
854 : : }
855 : :
856 [ # # ]: 0 : if (unlikely(rule->flags & HNS3_RULE_FLAG_COUNTER)) {
857 : 0 : ad_data.use_counter = true;
858 : 0 : ad_data.counter_id = rule->act_cnt.id;
859 : : } else {
860 : 0 : ad_data.use_counter = false;
861 : 0 : ad_data.counter_id = 0;
862 : : }
863 : :
864 [ # # ]: 0 : if (unlikely(rule->flags & HNS3_RULE_FLAG_FDID))
865 : 0 : ad_data.rule_id = rule->fd_id;
866 : : else
867 : 0 : ad_data.rule_id = rule->location;
868 : :
869 : 0 : ad_data.use_next_stage = false;
870 : 0 : ad_data.next_input_key = 0;
871 : :
872 : 0 : ad_data.write_rule_id_to_bd = true;
873 : :
874 : 0 : return hns3_fd_ad_config(hw, ad_data.ad_id, &ad_data);
875 : : }
876 : :
877 : 0 : static int hns3_fd_clear_all_rules(struct hns3_hw *hw, uint32_t rule_num)
878 : : {
879 : : uint32_t i;
880 : : int ret;
881 : :
882 [ # # ]: 0 : for (i = 0; i < rule_num; i++) {
883 : 0 : ret = hns3_fd_tcam_config(hw, true, i, NULL, false);
884 [ # # ]: 0 : if (ret)
885 : 0 : return ret;
886 : : }
887 : :
888 : : return 0;
889 : : }
890 : :
891 : 0 : int hns3_fdir_filter_init(struct hns3_adapter *hns)
892 : : {
893 : : struct hns3_pf *pf = &hns->pf;
894 : : struct hns3_fdir_info *fdir_info = &pf->fdir;
895 : 0 : uint32_t rule_num = fdir_info->fd_cfg.rule_num[HNS3_FD_STAGE_1];
896 : : char fdir_hash_name[RTE_HASH_NAMESIZE];
897 : 0 : struct rte_hash_parameters fdir_hash_params = {
898 : : .name = fdir_hash_name,
899 : : .entries = rule_num,
900 : : .key_len = sizeof(struct hns3_fdir_key_conf),
901 : : .hash_func = rte_hash_crc,
902 : : .hash_func_init_val = 0,
903 : : .extra_flag = RTE_HASH_EXTRA_FLAGS_EXT_TABLE,
904 : : };
905 : : int ret;
906 : :
907 : 0 : ret = hns3_fd_clear_all_rules(&hns->hw, rule_num);
908 [ # # ]: 0 : if (ret) {
909 : 0 : PMD_INIT_LOG(ERR, "Clear all fd rules fail! ret = %d", ret);
910 : 0 : return ret;
911 : : }
912 : :
913 : 0 : fdir_hash_params.socket_id = rte_socket_id();
914 : 0 : TAILQ_INIT(&fdir_info->fdir_list);
915 : 0 : snprintf(fdir_hash_name, RTE_HASH_NAMESIZE, "%s", hns->hw.data->name);
916 : 0 : fdir_info->hash_handle = rte_hash_create(&fdir_hash_params);
917 [ # # ]: 0 : if (fdir_info->hash_handle == NULL) {
918 : 0 : PMD_INIT_LOG(ERR, "Create FDIR hash handle fail!");
919 : 0 : return -EINVAL;
920 : : }
921 : 0 : fdir_info->hash_map = rte_zmalloc("hns3 FDIR hash",
922 : : rule_num *
923 : : sizeof(struct hns3_fdir_rule_ele *),
924 : : 0);
925 [ # # ]: 0 : if (fdir_info->hash_map == NULL) {
926 : 0 : PMD_INIT_LOG(ERR, "Allocate memory for FDIR hash map fail!");
927 : 0 : rte_hash_free(fdir_info->hash_handle);
928 : 0 : return -ENOMEM;
929 : : }
930 : :
931 : : return 0;
932 : : }
933 : :
934 : 0 : void hns3_fdir_filter_uninit(struct hns3_adapter *hns)
935 : : {
936 : : struct hns3_pf *pf = &hns->pf;
937 : : struct hns3_fdir_info *fdir_info = &pf->fdir;
938 : : struct hns3_fdir_rule_ele *fdir_filter;
939 : :
940 [ # # ]: 0 : if (fdir_info->hash_map) {
941 : 0 : rte_free(fdir_info->hash_map);
942 : 0 : fdir_info->hash_map = NULL;
943 : : }
944 [ # # ]: 0 : if (fdir_info->hash_handle) {
945 : 0 : rte_hash_free(fdir_info->hash_handle);
946 : 0 : fdir_info->hash_handle = NULL;
947 : : }
948 : :
949 : 0 : fdir_filter = TAILQ_FIRST(&fdir_info->fdir_list);
950 [ # # ]: 0 : while (fdir_filter) {
951 [ # # ]: 0 : TAILQ_REMOVE(&fdir_info->fdir_list, fdir_filter, entries);
952 : 0 : hns3_fd_tcam_config(&hns->hw, true,
953 : 0 : fdir_filter->fdir_conf.location, NULL,
954 : : false);
955 : 0 : rte_free(fdir_filter);
956 : 0 : fdir_filter = TAILQ_FIRST(&fdir_info->fdir_list);
957 : : }
958 : 0 : }
959 : :
960 : : /*
961 : : * Find a key in the hash table.
962 : : * @return
963 : : * - Zero and positive values are key location.
964 : : * - -EINVAL if the parameters are invalid.
965 : : * - -ENOENT if the key is not found.
966 : : */
967 : 0 : static int hns3_fdir_filter_lookup(struct hns3_fdir_info *fdir_info,
968 : : struct hns3_fdir_key_conf *key)
969 : : {
970 : : hash_sig_t sig;
971 : : int ret;
972 : :
973 : 0 : sig = rte_hash_crc(key, sizeof(*key), 0);
974 : 0 : ret = rte_hash_lookup_with_hash(fdir_info->hash_handle, key, sig);
975 : :
976 : 0 : return ret;
977 : : }
978 : :
979 : 0 : static int hns3_insert_fdir_filter(struct hns3_hw *hw,
980 : : struct hns3_fdir_info *fdir_info,
981 : : struct hns3_fdir_rule_ele *fdir_filter)
982 : : {
983 : : struct hns3_fdir_key_conf *key;
984 : : hash_sig_t sig;
985 : : int index;
986 : :
987 : 0 : key = &fdir_filter->fdir_conf.key_conf;
988 : 0 : sig = rte_hash_crc(key, sizeof(*key), 0);
989 : 0 : index = rte_hash_add_key_with_hash(fdir_info->hash_handle, key, sig);
990 [ # # ]: 0 : if (index < 0) {
991 : 0 : hns3_err(hw, "Hash table full? err:%d!", index);
992 : 0 : return index;
993 : : }
994 : :
995 [ # # ]: 0 : if (fdir_info->index_cfg == HNS3_FDIR_INDEX_CONFIG_PRIORITY)
996 : 0 : index = fdir_filter->fdir_conf.location;
997 : :
998 : 0 : fdir_info->hash_map[index] = fdir_filter;
999 : 0 : TAILQ_INSERT_TAIL(&fdir_info->fdir_list, fdir_filter, entries);
1000 : :
1001 : 0 : return index;
1002 : : }
1003 : :
1004 : 0 : static int hns3_remove_fdir_filter(struct hns3_hw *hw,
1005 : : struct hns3_fdir_info *fdir_info,
1006 : : struct hns3_fdir_rule *rule)
1007 : : {
1008 : : struct hns3_fdir_rule_ele *fdir_filter;
1009 : : hash_sig_t sig;
1010 : : int index;
1011 : :
1012 : 0 : sig = rte_hash_crc(&rule->key_conf, sizeof(rule->key_conf), 0);
1013 : 0 : index = rte_hash_del_key_with_hash(fdir_info->hash_handle, &rule->key_conf, sig);
1014 [ # # ]: 0 : if (index < 0) {
1015 : 0 : hns3_err(hw, "Delete hash key fail ret=%d", index);
1016 : 0 : return index;
1017 : : }
1018 : :
1019 [ # # ]: 0 : if (fdir_info->index_cfg == HNS3_FDIR_INDEX_CONFIG_PRIORITY)
1020 : 0 : index = rule->location;
1021 : 0 : fdir_filter = fdir_info->hash_map[index];
1022 : 0 : fdir_info->hash_map[index] = NULL;
1023 [ # # ]: 0 : TAILQ_REMOVE(&fdir_info->fdir_list, fdir_filter, entries);
1024 : :
1025 : 0 : rte_free(fdir_filter);
1026 : :
1027 : 0 : return 0;
1028 : : }
1029 : :
1030 : 0 : int hns3_fdir_filter_program(struct hns3_adapter *hns,
1031 : : struct hns3_fdir_rule *rule, bool del)
1032 : : {
1033 : : struct hns3_pf *pf = &hns->pf;
1034 : 0 : struct hns3_fdir_info *fdir_info = &pf->fdir;
1035 : : struct hns3_fdir_rule_ele *node;
1036 : 0 : struct hns3_hw *hw = &hns->hw;
1037 : : int ret;
1038 : :
1039 [ # # ]: 0 : if (del) {
1040 : 0 : ret = hns3_fd_tcam_config(hw, true, rule->location, NULL,
1041 : : false);
1042 [ # # ]: 0 : if (ret)
1043 : 0 : hns3_err(hw, "Failed to delete fdir: %u src_ip:%x "
1044 : : "dst_ip:%x src_port:%u dst_port:%u ret = %d",
1045 : : rule->location,
1046 : : rule->key_conf.spec.src_ip[IP_ADDR_KEY_ID],
1047 : : rule->key_conf.spec.dst_ip[IP_ADDR_KEY_ID],
1048 : : rule->key_conf.spec.src_port,
1049 : : rule->key_conf.spec.dst_port, ret);
1050 : : else
1051 : 0 : ret = hns3_remove_fdir_filter(hw, fdir_info, rule);
1052 : :
1053 : 0 : return ret;
1054 : : }
1055 : :
1056 : 0 : ret = hns3_fdir_filter_lookup(fdir_info, &rule->key_conf);
1057 [ # # ]: 0 : if (ret >= 0) {
1058 : 0 : hns3_err(hw, "Conflict with existing fdir loc: %d", ret);
1059 : 0 : return -EINVAL;
1060 : : }
1061 : :
1062 : 0 : node = rte_zmalloc("hns3 fdir rule", sizeof(struct hns3_fdir_rule_ele),
1063 : : 0);
1064 [ # # ]: 0 : if (node == NULL) {
1065 : 0 : hns3_err(hw, "Failed to allocate fdir_rule memory");
1066 : 0 : return -ENOMEM;
1067 : : }
1068 : :
1069 [ # # ]: 0 : rte_memcpy(&node->fdir_conf, rule, sizeof(struct hns3_fdir_rule));
1070 : 0 : ret = hns3_insert_fdir_filter(hw, fdir_info, node);
1071 [ # # ]: 0 : if (ret < 0) {
1072 : 0 : rte_free(node);
1073 : 0 : return ret;
1074 : : }
1075 : 0 : rule->location = ret;
1076 : 0 : node->fdir_conf.location = ret;
1077 : :
1078 : 0 : ret = hns3_config_action(hw, rule);
1079 [ # # ]: 0 : if (!ret)
1080 : 0 : ret = hns3_config_key(hns, rule);
1081 [ # # ]: 0 : if (ret) {
1082 : 0 : hns3_err(hw, "Failed to config fdir: %u src_ip:%x dst_ip:%x "
1083 : : "src_port:%u dst_port:%u ret = %d",
1084 : : rule->location,
1085 : : rule->key_conf.spec.src_ip[IP_ADDR_KEY_ID],
1086 : : rule->key_conf.spec.dst_ip[IP_ADDR_KEY_ID],
1087 : : rule->key_conf.spec.src_port,
1088 : : rule->key_conf.spec.dst_port, ret);
1089 : 0 : (void)hns3_remove_fdir_filter(hw, fdir_info, rule);
1090 : : }
1091 : :
1092 : : return ret;
1093 : : }
1094 : :
1095 : : /* remove all the flow director filters */
1096 : 0 : int hns3_clear_all_fdir_filter(struct hns3_adapter *hns)
1097 : : {
1098 : : struct hns3_pf *pf = &hns->pf;
1099 : : struct hns3_fdir_info *fdir_info = &pf->fdir;
1100 : : struct hns3_fdir_rule_ele *fdir_filter;
1101 : 0 : struct hns3_hw *hw = &hns->hw;
1102 : : int succ_cnt = 0;
1103 : : int fail_cnt = 0;
1104 : : int ret = 0;
1105 : :
1106 : : /* flush flow director */
1107 : 0 : rte_hash_reset(fdir_info->hash_handle);
1108 : :
1109 : 0 : memset(fdir_info->hash_map, 0,
1110 : : sizeof(struct hns3_fdir_rule_ele *) *
1111 : 0 : fdir_info->fd_cfg.rule_num[HNS3_FD_STAGE_1]);
1112 : :
1113 : 0 : fdir_filter = TAILQ_FIRST(&fdir_info->fdir_list);
1114 [ # # ]: 0 : while (fdir_filter) {
1115 [ # # ]: 0 : TAILQ_REMOVE(&fdir_info->fdir_list, fdir_filter, entries);
1116 : 0 : ret = hns3_fd_tcam_config(hw, true,
1117 : 0 : fdir_filter->fdir_conf.location,
1118 : : NULL, false);
1119 [ # # ]: 0 : if (ret == 0)
1120 : 0 : succ_cnt++;
1121 : : else
1122 : 0 : fail_cnt++;
1123 : 0 : rte_free(fdir_filter);
1124 : 0 : fdir_filter = TAILQ_FIRST(&fdir_info->fdir_list);
1125 : : }
1126 : :
1127 [ # # ]: 0 : if (fail_cnt > 0) {
1128 : 0 : hns3_err(hw, "fail to delete all FDIR filter, success num = %d "
1129 : : "fail num = %d", succ_cnt, fail_cnt);
1130 : : ret = -EIO;
1131 : : }
1132 : :
1133 : 0 : return ret;
1134 : : }
1135 : :
1136 : 0 : int hns3_restore_all_fdir_filter(struct hns3_adapter *hns)
1137 : : {
1138 : : struct hns3_pf *pf = &hns->pf;
1139 : : struct hns3_fdir_info *fdir_info = &pf->fdir;
1140 : : struct hns3_fdir_rule_ele *fdir_filter;
1141 : 0 : struct hns3_hw *hw = &hns->hw;
1142 : : bool err = false;
1143 : : int ret;
1144 : :
1145 [ # # ]: 0 : if (hns->is_vf)
1146 : : return 0;
1147 : :
1148 : : /*
1149 : : * This API is called in the reset recovery process, the parent function
1150 : : * must hold hw->lock.
1151 : : * There maybe deadlock if acquire hw->flows_lock directly because rte
1152 : : * flow driver ops first acquire hw->flows_lock and then may acquire
1153 : : * hw->lock.
1154 : : * So here first release the hw->lock and then acquire the
1155 : : * hw->flows_lock to avoid deadlock.
1156 : : */
1157 : 0 : rte_spinlock_unlock(&hw->lock);
1158 : 0 : pthread_mutex_lock(&hw->flows_lock);
1159 [ # # ]: 0 : TAILQ_FOREACH(fdir_filter, &fdir_info->fdir_list, entries) {
1160 : 0 : ret = hns3_config_action(hw, &fdir_filter->fdir_conf);
1161 [ # # ]: 0 : if (!ret)
1162 : 0 : ret = hns3_config_key(hns, &fdir_filter->fdir_conf);
1163 [ # # ]: 0 : if (ret) {
1164 : : err = true;
1165 [ # # ]: 0 : if (ret == -EBUSY)
1166 : : break;
1167 : : }
1168 : : }
1169 : 0 : pthread_mutex_unlock(&hw->flows_lock);
1170 : : rte_spinlock_lock(&hw->lock);
1171 : :
1172 [ # # ]: 0 : if (err) {
1173 : 0 : hns3_err(hw, "Fail to restore FDIR filter, ret = %d", ret);
1174 : 0 : return -EIO;
1175 : : }
1176 : : return 0;
1177 : : }
1178 : :
1179 : 0 : int hns3_fd_get_count(struct hns3_hw *hw, uint32_t id, uint64_t *value)
1180 : : {
1181 : : struct hns3_fd_get_cnt_cmd *req;
1182 : : struct hns3_cmd_desc desc;
1183 : : int ret;
1184 : :
1185 : 0 : hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_FD_COUNTER_OP, true);
1186 : :
1187 : : req = (struct hns3_fd_get_cnt_cmd *)desc.data;
1188 : 0 : req->stage = HNS3_FD_STAGE_1;
1189 : 0 : req->index = rte_cpu_to_le_32(id);
1190 : :
1191 : 0 : ret = hns3_cmd_send(hw, &desc, 1);
1192 [ # # ]: 0 : if (ret) {
1193 : 0 : hns3_err(hw, "Read counter fail, ret=%d", ret);
1194 : 0 : return ret;
1195 : : }
1196 : :
1197 : 0 : *value = req->value;
1198 : :
1199 : 0 : return ret;
1200 : : }
1201 : :
1202 : : static struct {
1203 : : enum hns3_fdir_tuple_config tuple_cfg;
1204 : : const char *name;
1205 : : } tuple_config_map[] = {
1206 : : { HNS3_FDIR_TUPLE_CONFIG_DEFAULT, "default" },
1207 : : { HNS3_FDIR_TUPLE_OUTVLAN_REPLACE_INSMAC, "+outvlan-insmac" },
1208 : : { HNS3_FDIR_TUPLE_OUTVLAN_REPLACE_INDMAC, "+outvlan-indmac" },
1209 : : { HNS3_FDIR_TUPLE_OUTVLAN_REPLACE_INSIP, "+outvlan-insip" },
1210 : : { HNS3_FDIR_TUPLE_OUTVLAN_REPLACE_INDIP, "+outvlan-indip" },
1211 : : { HNS3_FDIR_TUPLE_OUTVLAN_REPLACE_SCTPTAG, "+outvlan-sctptag" },
1212 : : { HNS3_FDIR_TUPLE_OUTVLAN_REPLACE_TUNVNI, "+outvlan-tunvni" }
1213 : : };
1214 : :
1215 : : enum hns3_fdir_tuple_config
1216 : 0 : hns3_parse_tuple_config(const char *name)
1217 : : {
1218 : : uint32_t i;
1219 : :
1220 [ # # ]: 0 : for (i = 0; i < RTE_DIM(tuple_config_map); i++) {
1221 [ # # ]: 0 : if (!strcmp(name, tuple_config_map[i].name))
1222 : 0 : return tuple_config_map[i].tuple_cfg;
1223 : : }
1224 : :
1225 : : return HNS3_FDIR_TUPLE_CONFIG_BUTT;
1226 : : }
1227 : :
1228 : : const char *
1229 : 0 : hns3_tuple_config_name(enum hns3_fdir_tuple_config tuple_cfg)
1230 : : {
1231 : : uint32_t i;
1232 : :
1233 [ # # ]: 0 : for (i = 0; i < RTE_DIM(tuple_config_map); i++) {
1234 [ # # ]: 0 : if (tuple_cfg == tuple_config_map[i].tuple_cfg)
1235 : 0 : return tuple_config_map[i].name;
1236 : : }
1237 : :
1238 : : return "unknown";
1239 : : }
1240 : :
1241 : : static struct {
1242 : : enum hns3_fdir_index_config cfg;
1243 : : const char *name;
1244 : : } index_cfg_map[] = {
1245 : : { HNS3_FDIR_INDEX_CONFIG_HASH, "hash"},
1246 : : { HNS3_FDIR_INDEX_CONFIG_PRIORITY, "priority"},
1247 : : };
1248 : :
1249 : : const char *
1250 : 0 : hns3_fdir_index_config_name(enum hns3_fdir_index_config cfg)
1251 : : {
1252 : : uint32_t i;
1253 : :
1254 [ # # ]: 0 : for (i = 0; i < RTE_DIM(index_cfg_map); i++) {
1255 [ # # ]: 0 : if (cfg == index_cfg_map[i].cfg)
1256 : 0 : return index_cfg_map[i].name;
1257 : : }
1258 : :
1259 : : return "unknown";
1260 : : }
|