Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2020 Intel Corporation
3 : : */
4 : :
5 : : #include "rte_malloc.h"
6 : : #include "igc_logs.h"
7 : : #include "igc_txrx.h"
8 : : #include "igc_filter.h"
9 : : #include "igc_flow.h"
10 : :
11 : : /*
12 : : * igc_ethertype_filter_lookup - lookup ether-type filter
13 : : *
14 : : * @igc, IGC filter pointer
15 : : * @ethertype, ethernet type
16 : : * @empty, a place to store the index of empty entry if the item not found
17 : : * it's not smaller than 0 if valid, otherwise -1 for no empty entry.
18 : : * empty parameter is only valid if the return value of the function is -1
19 : : *
20 : : * Return value
21 : : * >= 0, item index of the ether-type filter
22 : : * -1, the item not been found
23 : : */
24 : : static inline int
25 : : igc_ethertype_filter_lookup(const struct igc_adapter *igc,
26 : : uint16_t ethertype, int *empty)
27 : : {
28 : : int i = 0;
29 : :
30 : : if (empty) {
31 : : /* set to invalid valid */
32 : : *empty = -1;
33 : :
34 : : /* search the filters array */
35 [ # # ]: 0 : for (; i < IGC_MAX_ETQF_FILTERS; i++) {
36 [ # # ]: 0 : if (igc->ethertype_filters[i].ether_type == ethertype)
37 : : return i;
38 [ # # ]: 0 : if (igc->ethertype_filters[i].ether_type == 0) {
39 : : /* get empty entry */
40 : : *empty = i;
41 : 0 : i++;
42 : 0 : break;
43 : : }
44 : : }
45 : : }
46 : :
47 : : /* search the rest of filters */
48 [ # # # # ]: 0 : for (; i < IGC_MAX_ETQF_FILTERS; i++) {
49 [ # # # # ]: 0 : if (igc->ethertype_filters[i].ether_type == ethertype)
50 : : return i; /* filter be found, return index */
51 : : }
52 : :
53 : : return -1;
54 : : }
55 : :
56 : : int
57 : 0 : igc_del_ethertype_filter(struct rte_eth_dev *dev,
58 : : const struct igc_ethertype_filter *filter)
59 : : {
60 : 0 : struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
61 : : struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
62 : : int ret;
63 : :
64 [ # # ]: 0 : if (filter->ether_type == 0) {
65 : 0 : PMD_DRV_LOG(ERR, "Ethertype 0 is not been supported");
66 : 0 : return -EINVAL;
67 : : }
68 : :
69 : 0 : ret = igc_ethertype_filter_lookup(igc, filter->ether_type, NULL);
70 [ # # ]: 0 : if (ret < 0) {
71 : : /* not found */
72 : 0 : PMD_DRV_LOG(ERR,
73 : : "Ethertype (0x%04x) filter doesn't exist",
74 : : filter->ether_type);
75 : 0 : return -ENOENT;
76 : : }
77 : :
78 : 0 : igc->ethertype_filters[ret].ether_type = 0;
79 : :
80 : 0 : IGC_WRITE_REG(hw, IGC_ETQF(ret), 0);
81 : 0 : IGC_WRITE_FLUSH(hw);
82 : 0 : return 0;
83 : : }
84 : :
85 : : int
86 : 0 : igc_add_ethertype_filter(struct rte_eth_dev *dev,
87 : : const struct igc_ethertype_filter *filter)
88 : : {
89 : 0 : struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
90 : : struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
91 : : uint32_t etqf;
92 : : int ret, empty;
93 : :
94 [ # # ]: 0 : if (filter->ether_type == RTE_ETHER_TYPE_IPV4 ||
95 [ # # ]: 0 : filter->ether_type == RTE_ETHER_TYPE_IPV6 ||
96 : : filter->ether_type == 0) {
97 : 0 : PMD_DRV_LOG(ERR,
98 : : "Unsupported ether_type(0x%04x) in ethertype filter",
99 : : filter->ether_type);
100 : 0 : return -EINVAL;
101 : : }
102 : :
103 : 0 : ret = igc_ethertype_filter_lookup(igc, filter->ether_type, &empty);
104 [ # # ]: 0 : if (ret >= 0) {
105 : 0 : PMD_DRV_LOG(ERR, "ethertype (0x%04x) filter exists.",
106 : : filter->ether_type);
107 : 0 : return -EEXIST;
108 : : }
109 : :
110 [ # # ]: 0 : if (empty < 0) {
111 : 0 : PMD_DRV_LOG(ERR, "no ethertype filter entry.");
112 : 0 : return -ENOSPC;
113 : : }
114 : : ret = empty;
115 : :
116 : 0 : etqf = filter->ether_type;
117 : 0 : etqf |= IGC_ETQF_FILTER_ENABLE | IGC_ETQF_QUEUE_ENABLE;
118 : 0 : etqf |= (uint32_t)filter->queue << IGC_ETQF_QUEUE_SHIFT;
119 : :
120 : 0 : memcpy(&igc->ethertype_filters[ret], filter, sizeof(*filter));
121 : :
122 : 0 : IGC_WRITE_REG(hw, IGC_ETQF(ret), etqf);
123 : 0 : IGC_WRITE_FLUSH(hw);
124 : 0 : return 0;
125 : : }
126 : :
127 : : /* clear all the ether type filters */
128 : : static void
129 : 0 : igc_clear_all_ethertype_filter(struct rte_eth_dev *dev)
130 : : {
131 : 0 : struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
132 : : struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
133 : : int i;
134 : :
135 [ # # ]: 0 : for (i = 0; i < IGC_MAX_ETQF_FILTERS; i++)
136 : 0 : IGC_WRITE_REG(hw, IGC_ETQF(i), 0);
137 : 0 : IGC_WRITE_FLUSH(hw);
138 : :
139 : 0 : memset(&igc->ethertype_filters, 0, sizeof(igc->ethertype_filters));
140 : 0 : }
141 : :
142 : : /*
143 : : * igc_tuple_filter_lookup - lookup n-tuple filter
144 : : *
145 : : * @igc, igc filter pointer
146 : : * @ntuple, n-tuple filter pointer
147 : : * @empty, a place to store the index of empty entry if the item not found
148 : : * it's not smaller than 0 if valid, otherwise -1 for no empty entry.
149 : : * The value of empty is uncertain if the return value of the function is
150 : : * not -1.
151 : : *
152 : : * Return value
153 : : * >= 0, item index of the filter
154 : : * -1, the item not been found
155 : : */
156 : : static int
157 : : igc_tuple_filter_lookup(const struct igc_adapter *igc,
158 : : const struct igc_ntuple_filter *ntuple,
159 : : int *empty)
160 : : {
161 : : int i = 0;
162 : :
163 : : if (empty) {
164 : : /* set initial value */
165 : : *empty = -1;
166 : :
167 : : /* search the filter array */
168 [ # # ]: 0 : for (; i < IGC_MAX_NTUPLE_FILTERS; i++) {
169 [ # # ]: 0 : if (igc->ntuple_filters[i].hash_val) {
170 : : /* compare the hash value */
171 [ # # ]: 0 : if (ntuple->hash_val ==
172 : : igc->ntuple_filters[i].hash_val)
173 : : /* filter be found, return index */
174 : : return i;
175 : : } else {
176 : : /* get the empty entry */
177 : : *empty = i;
178 : 0 : i++;
179 : 0 : break;
180 : : }
181 : : }
182 : : }
183 : :
184 : : /* search the rest of filters */
185 [ # # # # ]: 0 : for (; i < IGC_MAX_NTUPLE_FILTERS; i++) {
186 [ # # # # ]: 0 : if (ntuple->hash_val == igc->ntuple_filters[i].hash_val)
187 : : /* filter be found, return index */
188 : : return i;
189 : : }
190 : :
191 : : return -1;
192 : : }
193 : :
194 : : /* Set hardware register values */
195 : : static void
196 : 0 : igc_enable_tuple_filter(struct rte_eth_dev *dev,
197 : : const struct igc_adapter *igc, uint8_t index)
198 : : {
199 : 0 : struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
200 : 0 : const struct igc_ntuple_filter *filter = &igc->ntuple_filters[index];
201 : : const struct igc_ntuple_info *info = &filter->tuple_info;
202 : : uint32_t ttqf, imir, imir_ext = IGC_IMIREXT_SIZE_BP;
203 : :
204 : 0 : imir = info->dst_port;
205 : 0 : imir |= (uint32_t)info->priority << IGC_IMIR_PRIORITY_SHIFT;
206 : :
207 : : /* 0b means not compare. */
208 [ # # ]: 0 : if (info->dst_port_mask == 0)
209 : 0 : imir |= IGC_IMIR_PORT_BP;
210 : :
211 : : ttqf = IGC_TTQF_DISABLE_MASK | IGC_TTQF_QUEUE_ENABLE;
212 : 0 : ttqf |= (uint32_t)filter->queue << IGC_TTQF_QUEUE_SHIFT;
213 : 0 : ttqf |= info->proto;
214 : :
215 [ # # ]: 0 : if (info->proto_mask)
216 : 0 : ttqf &= ~IGC_TTQF_MASK_ENABLE;
217 : :
218 : : /* TCP flags bits setting. */
219 [ # # ]: 0 : if (info->tcp_flags & RTE_NTUPLE_TCP_FLAGS_MASK) {
220 [ # # ]: 0 : if (info->tcp_flags & RTE_TCP_URG_FLAG)
221 : : imir_ext |= IGC_IMIREXT_CTRL_URG;
222 [ # # ]: 0 : if (info->tcp_flags & RTE_TCP_ACK_FLAG)
223 : 0 : imir_ext |= IGC_IMIREXT_CTRL_ACK;
224 [ # # ]: 0 : if (info->tcp_flags & RTE_TCP_PSH_FLAG)
225 : 0 : imir_ext |= IGC_IMIREXT_CTRL_PSH;
226 [ # # ]: 0 : if (info->tcp_flags & RTE_TCP_RST_FLAG)
227 : 0 : imir_ext |= IGC_IMIREXT_CTRL_RST;
228 [ # # ]: 0 : if (info->tcp_flags & RTE_TCP_SYN_FLAG)
229 : 0 : imir_ext |= IGC_IMIREXT_CTRL_SYN;
230 [ # # ]: 0 : if (info->tcp_flags & RTE_TCP_FIN_FLAG)
231 : 0 : imir_ext |= IGC_IMIREXT_CTRL_FIN;
232 : : } else {
233 : : imir_ext |= IGC_IMIREXT_CTRL_BP;
234 : : }
235 : :
236 : 0 : IGC_WRITE_REG(hw, IGC_IMIR(index), imir);
237 : 0 : IGC_WRITE_REG(hw, IGC_TTQF(index), ttqf);
238 : 0 : IGC_WRITE_REG(hw, IGC_IMIREXT(index), imir_ext);
239 : 0 : IGC_WRITE_FLUSH(hw);
240 : 0 : }
241 : :
242 : : /* Reset hardware register values */
243 : : static void
244 : 0 : igc_disable_tuple_filter(struct rte_eth_dev *dev, uint8_t index)
245 : : {
246 : 0 : struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
247 : :
248 : 0 : IGC_WRITE_REG(hw, IGC_TTQF(index), IGC_TTQF_DISABLE_MASK);
249 : 0 : IGC_WRITE_REG(hw, IGC_IMIR(index), 0);
250 : 0 : IGC_WRITE_REG(hw, IGC_IMIREXT(index), 0);
251 : 0 : IGC_WRITE_FLUSH(hw);
252 : 0 : }
253 : :
254 : : int
255 : 0 : igc_add_ntuple_filter(struct rte_eth_dev *dev,
256 : : const struct igc_ntuple_filter *ntuple)
257 : : {
258 : 0 : struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
259 : : int ret, empty;
260 : :
261 : : ret = igc_tuple_filter_lookup(igc, ntuple, &empty);
262 [ # # ]: 0 : if (ret >= 0) {
263 : 0 : PMD_DRV_LOG(ERR, "filter exists.");
264 : 0 : return -EEXIST;
265 : : }
266 : :
267 [ # # ]: 0 : if (empty < 0) {
268 : 0 : PMD_DRV_LOG(ERR, "filter no entry.");
269 : 0 : return -ENOSPC;
270 : : }
271 : :
272 : : ret = empty;
273 : 0 : memcpy(&igc->ntuple_filters[ret], ntuple, sizeof(*ntuple));
274 : 0 : igc_enable_tuple_filter(dev, igc, (uint8_t)ret);
275 : 0 : return 0;
276 : : }
277 : :
278 : : int
279 : 0 : igc_del_ntuple_filter(struct rte_eth_dev *dev,
280 : : const struct igc_ntuple_filter *ntuple)
281 : : {
282 : 0 : struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
283 : : int ret;
284 : :
285 : : ret = igc_tuple_filter_lookup(igc, ntuple, NULL);
286 [ # # ]: 0 : if (ret < 0) {
287 : 0 : PMD_DRV_LOG(ERR, "filter not exists.");
288 : 0 : return -ENOENT;
289 : : }
290 : :
291 : 0 : memset(&igc->ntuple_filters[ret], 0, sizeof(*ntuple));
292 : 0 : igc_disable_tuple_filter(dev, (uint8_t)ret);
293 : 0 : return 0;
294 : : }
295 : :
296 : : /* Clear all the n-tuple filters */
297 : : static void
298 : 0 : igc_clear_all_ntuple_filter(struct rte_eth_dev *dev)
299 : : {
300 : 0 : struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
301 : : int i;
302 : :
303 [ # # ]: 0 : for (i = 0; i < IGC_MAX_NTUPLE_FILTERS; i++)
304 : 0 : igc_disable_tuple_filter(dev, i);
305 : :
306 : 0 : memset(&igc->ntuple_filters, 0, sizeof(igc->ntuple_filters));
307 : 0 : }
308 : :
309 : : int
310 : 0 : igc_set_syn_filter(struct rte_eth_dev *dev,
311 : : const struct igc_syn_filter *filter)
312 : : {
313 : : struct igc_hw *hw;
314 : : struct igc_adapter *igc;
315 : : uint32_t synqf, rfctl;
316 : :
317 [ # # ]: 0 : if (filter->queue >= IGC_QUEUE_PAIRS_NUM) {
318 : 0 : PMD_DRV_LOG(ERR, "out of range queue %u(max is %u)",
319 : : filter->queue, IGC_QUEUE_PAIRS_NUM);
320 : 0 : return -EINVAL;
321 : : }
322 : :
323 : 0 : igc = IGC_DEV_PRIVATE(dev);
324 : :
325 [ # # ]: 0 : if (igc->syn_filter.enable) {
326 : 0 : PMD_DRV_LOG(ERR, "SYN filter has been enabled before!");
327 : 0 : return -EEXIST;
328 : : }
329 : :
330 : : hw = IGC_DEV_PRIVATE_HW(dev);
331 : 0 : synqf = (uint32_t)filter->queue << IGC_SYN_FILTER_QUEUE_SHIFT;
332 : 0 : synqf |= IGC_SYN_FILTER_ENABLE;
333 : :
334 : 0 : rfctl = IGC_READ_REG(hw, IGC_RFCTL);
335 [ # # ]: 0 : if (filter->hig_pri)
336 : 0 : rfctl |= IGC_RFCTL_SYNQFP;
337 : : else
338 : 0 : rfctl &= ~IGC_RFCTL_SYNQFP;
339 : :
340 : 0 : memcpy(&igc->syn_filter, filter, sizeof(igc->syn_filter));
341 : 0 : igc->syn_filter.enable = 1;
342 : :
343 : 0 : IGC_WRITE_REG(hw, IGC_RFCTL, rfctl);
344 : 0 : IGC_WRITE_REG(hw, IGC_SYNQF(0), synqf);
345 : 0 : IGC_WRITE_FLUSH(hw);
346 : 0 : return 0;
347 : : }
348 : :
349 : : /* clear the SYN filter */
350 : : void
351 : 0 : igc_clear_syn_filter(struct rte_eth_dev *dev)
352 : : {
353 : 0 : struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
354 : : struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
355 : :
356 : 0 : IGC_WRITE_REG(hw, IGC_SYNQF(0), 0);
357 : 0 : IGC_WRITE_FLUSH(hw);
358 : :
359 : 0 : memset(&igc->syn_filter, 0, sizeof(igc->syn_filter));
360 : 0 : }
361 : :
362 : : void
363 : 0 : igc_clear_all_filter(struct rte_eth_dev *dev)
364 : : {
365 : 0 : igc_clear_all_ethertype_filter(dev);
366 : 0 : igc_clear_all_ntuple_filter(dev);
367 : 0 : igc_clear_syn_filter(dev);
368 : 0 : igc_clear_rss_filter(dev);
369 : 0 : }
370 : :
371 : : int
372 : 0 : eth_igc_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
373 : : const struct rte_flow_ops **ops)
374 : : {
375 : 0 : *ops = &igc_flow_ops;
376 : 0 : return 0;
377 : : }
|