xref: /f-stack/dpdk/drivers/net/igc/igc_filter.c (revision 2d9fd380)
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
igc_ethertype_filter_lookup(const struct igc_adapter * igc,uint16_t ethertype,int * empty)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 		for (; i < IGC_MAX_ETQF_FILTERS; i++) {
36 			if (igc->ethertype_filters[i].ether_type == ethertype)
37 				return i;
38 			if (igc->ethertype_filters[i].ether_type == 0) {
39 				/* get empty entry */
40 				*empty = i;
41 				i++;
42 				break;
43 			}
44 		}
45 	}
46 
47 	/* search the rest of filters */
48 	for (; i < IGC_MAX_ETQF_FILTERS; i++) {
49 		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
igc_del_ethertype_filter(struct rte_eth_dev * dev,const struct igc_ethertype_filter * filter)57 igc_del_ethertype_filter(struct rte_eth_dev *dev,
58 			const struct igc_ethertype_filter *filter)
59 {
60 	struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
61 	struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
62 	int ret;
63 
64 	if (filter->ether_type == 0) {
65 		PMD_DRV_LOG(ERR, "Ethertype 0 is not been supported");
66 		return -EINVAL;
67 	}
68 
69 	ret = igc_ethertype_filter_lookup(igc, filter->ether_type, NULL);
70 	if (ret < 0) {
71 		/* not found */
72 		PMD_DRV_LOG(ERR,
73 			"Ethertype (0x%04x) filter doesn't exist",
74 			filter->ether_type);
75 		return -ENOENT;
76 	}
77 
78 	igc->ethertype_filters[ret].ether_type = 0;
79 
80 	IGC_WRITE_REG(hw, IGC_ETQF(ret), 0);
81 	IGC_WRITE_FLUSH(hw);
82 	return 0;
83 }
84 
85 int
igc_add_ethertype_filter(struct rte_eth_dev * dev,const struct igc_ethertype_filter * filter)86 igc_add_ethertype_filter(struct rte_eth_dev *dev,
87 			const struct igc_ethertype_filter *filter)
88 {
89 	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 	if (filter->ether_type == RTE_ETHER_TYPE_IPV4 ||
95 		filter->ether_type == RTE_ETHER_TYPE_IPV6 ||
96 		filter->ether_type == 0) {
97 		PMD_DRV_LOG(ERR,
98 			"Unsupported ether_type(0x%04x) in ethertype filter",
99 			filter->ether_type);
100 		return -EINVAL;
101 	}
102 
103 	ret = igc_ethertype_filter_lookup(igc, filter->ether_type, &empty);
104 	if (ret >= 0) {
105 		PMD_DRV_LOG(ERR, "ethertype (0x%04x) filter exists.",
106 				filter->ether_type);
107 		return -EEXIST;
108 	}
109 
110 	if (empty < 0) {
111 		PMD_DRV_LOG(ERR, "no ethertype filter entry.");
112 		return -ENOSPC;
113 	}
114 	ret = empty;
115 
116 	etqf = filter->ether_type;
117 	etqf |= IGC_ETQF_FILTER_ENABLE | IGC_ETQF_QUEUE_ENABLE;
118 	etqf |= (uint32_t)filter->queue << IGC_ETQF_QUEUE_SHIFT;
119 
120 	memcpy(&igc->ethertype_filters[ret], filter, sizeof(*filter));
121 
122 	IGC_WRITE_REG(hw, IGC_ETQF(ret), etqf);
123 	IGC_WRITE_FLUSH(hw);
124 	return 0;
125 }
126 
127 /* clear all the ether type filters */
128 static void
igc_clear_all_ethertype_filter(struct rte_eth_dev * dev)129 igc_clear_all_ethertype_filter(struct rte_eth_dev *dev)
130 {
131 	struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
132 	struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
133 	int i;
134 
135 	for (i = 0; i < IGC_MAX_ETQF_FILTERS; i++)
136 		IGC_WRITE_REG(hw, IGC_ETQF(i), 0);
137 	IGC_WRITE_FLUSH(hw);
138 
139 	memset(&igc->ethertype_filters, 0, sizeof(igc->ethertype_filters));
140 }
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
igc_tuple_filter_lookup(const struct igc_adapter * igc,const struct igc_ntuple_filter * ntuple,int * empty)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 		for (; i < IGC_MAX_NTUPLE_FILTERS; i++) {
169 			if (igc->ntuple_filters[i].hash_val) {
170 				/* compare the hase value */
171 				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 				i++;
179 				break;
180 			}
181 		}
182 	}
183 
184 	/* search the rest of filters */
185 	for (; i < IGC_MAX_NTUPLE_FILTERS; i++) {
186 		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
igc_enable_tuple_filter(struct rte_eth_dev * dev,const struct igc_adapter * igc,uint8_t index)196 igc_enable_tuple_filter(struct rte_eth_dev *dev,
197 			const struct igc_adapter *igc, uint8_t index)
198 {
199 	struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
200 	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 	imir = info->dst_port;
205 	imir |= (uint32_t)info->priority << IGC_IMIR_PRIORITY_SHIFT;
206 
207 	/* 0b means not compare. */
208 	if (info->dst_port_mask == 0)
209 		imir |= IGC_IMIR_PORT_BP;
210 
211 	ttqf = IGC_TTQF_DISABLE_MASK | IGC_TTQF_QUEUE_ENABLE;
212 	ttqf |= (uint32_t)filter->queue << IGC_TTQF_QUEUE_SHIFT;
213 	ttqf |= info->proto;
214 
215 	if (info->proto_mask)
216 		ttqf &= ~IGC_TTQF_MASK_ENABLE;
217 
218 	/* TCP flags bits setting. */
219 	if (info->tcp_flags & RTE_NTUPLE_TCP_FLAGS_MASK) {
220 		if (info->tcp_flags & RTE_TCP_URG_FLAG)
221 			imir_ext |= IGC_IMIREXT_CTRL_URG;
222 		if (info->tcp_flags & RTE_TCP_ACK_FLAG)
223 			imir_ext |= IGC_IMIREXT_CTRL_ACK;
224 		if (info->tcp_flags & RTE_TCP_PSH_FLAG)
225 			imir_ext |= IGC_IMIREXT_CTRL_PSH;
226 		if (info->tcp_flags & RTE_TCP_RST_FLAG)
227 			imir_ext |= IGC_IMIREXT_CTRL_RST;
228 		if (info->tcp_flags & RTE_TCP_SYN_FLAG)
229 			imir_ext |= IGC_IMIREXT_CTRL_SYN;
230 		if (info->tcp_flags & RTE_TCP_FIN_FLAG)
231 			imir_ext |= IGC_IMIREXT_CTRL_FIN;
232 	} else {
233 		imir_ext |= IGC_IMIREXT_CTRL_BP;
234 	}
235 
236 	IGC_WRITE_REG(hw, IGC_IMIR(index), imir);
237 	IGC_WRITE_REG(hw, IGC_TTQF(index), ttqf);
238 	IGC_WRITE_REG(hw, IGC_IMIREXT(index), imir_ext);
239 	IGC_WRITE_FLUSH(hw);
240 }
241 
242 /* Reset hardware register values */
243 static void
igc_disable_tuple_filter(struct rte_eth_dev * dev,uint8_t index)244 igc_disable_tuple_filter(struct rte_eth_dev *dev, uint8_t index)
245 {
246 	struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
247 
248 	IGC_WRITE_REG(hw, IGC_TTQF(index), IGC_TTQF_DISABLE_MASK);
249 	IGC_WRITE_REG(hw, IGC_IMIR(index), 0);
250 	IGC_WRITE_REG(hw, IGC_IMIREXT(index), 0);
251 	IGC_WRITE_FLUSH(hw);
252 }
253 
254 int
igc_add_ntuple_filter(struct rte_eth_dev * dev,const struct igc_ntuple_filter * ntuple)255 igc_add_ntuple_filter(struct rte_eth_dev *dev,
256 		const struct igc_ntuple_filter *ntuple)
257 {
258 	struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
259 	int ret, empty;
260 
261 	ret = igc_tuple_filter_lookup(igc, ntuple, &empty);
262 	if (ret >= 0) {
263 		PMD_DRV_LOG(ERR, "filter exists.");
264 		return -EEXIST;
265 	}
266 
267 	if (empty < 0) {
268 		PMD_DRV_LOG(ERR, "filter no entry.");
269 		return -ENOSPC;
270 	}
271 
272 	ret = empty;
273 	memcpy(&igc->ntuple_filters[ret], ntuple, sizeof(*ntuple));
274 	igc_enable_tuple_filter(dev, igc, (uint8_t)ret);
275 	return 0;
276 }
277 
278 int
igc_del_ntuple_filter(struct rte_eth_dev * dev,const struct igc_ntuple_filter * ntuple)279 igc_del_ntuple_filter(struct rte_eth_dev *dev,
280 		const struct igc_ntuple_filter *ntuple)
281 {
282 	struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
283 	int ret;
284 
285 	ret = igc_tuple_filter_lookup(igc, ntuple, NULL);
286 	if (ret < 0) {
287 		PMD_DRV_LOG(ERR, "filter not exists.");
288 		return -ENOENT;
289 	}
290 
291 	memset(&igc->ntuple_filters[ret], 0, sizeof(*ntuple));
292 	igc_disable_tuple_filter(dev, (uint8_t)ret);
293 	return 0;
294 }
295 
296 /* Clear all the n-tuple filters */
297 static void
igc_clear_all_ntuple_filter(struct rte_eth_dev * dev)298 igc_clear_all_ntuple_filter(struct rte_eth_dev *dev)
299 {
300 	struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
301 	int i;
302 
303 	for (i = 0; i < IGC_MAX_NTUPLE_FILTERS; i++)
304 		igc_disable_tuple_filter(dev, i);
305 
306 	memset(&igc->ntuple_filters, 0, sizeof(igc->ntuple_filters));
307 }
308 
309 int
igc_set_syn_filter(struct rte_eth_dev * dev,const struct igc_syn_filter * filter)310 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 	if (filter->queue >= IGC_QUEUE_PAIRS_NUM) {
318 		PMD_DRV_LOG(ERR, "out of range queue %u(max is %u)",
319 			filter->queue, IGC_QUEUE_PAIRS_NUM);
320 		return -EINVAL;
321 	}
322 
323 	igc = IGC_DEV_PRIVATE(dev);
324 
325 	if (igc->syn_filter.enable) {
326 		PMD_DRV_LOG(ERR, "SYN filter has been enabled before!");
327 		return -EEXIST;
328 	}
329 
330 	hw = IGC_DEV_PRIVATE_HW(dev);
331 	synqf = (uint32_t)filter->queue << IGC_SYN_FILTER_QUEUE_SHIFT;
332 	synqf |= IGC_SYN_FILTER_ENABLE;
333 
334 	rfctl = IGC_READ_REG(hw, IGC_RFCTL);
335 	if (filter->hig_pri)
336 		rfctl |= IGC_RFCTL_SYNQFP;
337 	else
338 		rfctl &= ~IGC_RFCTL_SYNQFP;
339 
340 	memcpy(&igc->syn_filter, filter, sizeof(igc->syn_filter));
341 	igc->syn_filter.enable = 1;
342 
343 	IGC_WRITE_REG(hw, IGC_RFCTL, rfctl);
344 	IGC_WRITE_REG(hw, IGC_SYNQF(0), synqf);
345 	IGC_WRITE_FLUSH(hw);
346 	return 0;
347 }
348 
349 /* clear the SYN filter */
350 void
igc_clear_syn_filter(struct rte_eth_dev * dev)351 igc_clear_syn_filter(struct rte_eth_dev *dev)
352 {
353 	struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
354 	struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
355 
356 	IGC_WRITE_REG(hw, IGC_SYNQF(0), 0);
357 	IGC_WRITE_FLUSH(hw);
358 
359 	memset(&igc->syn_filter, 0, sizeof(igc->syn_filter));
360 }
361 
362 void
igc_clear_all_filter(struct rte_eth_dev * dev)363 igc_clear_all_filter(struct rte_eth_dev *dev)
364 {
365 	igc_clear_all_ethertype_filter(dev);
366 	igc_clear_all_ntuple_filter(dev);
367 	igc_clear_syn_filter(dev);
368 	igc_clear_rss_filter(dev);
369 }
370 
371 int
eth_igc_filter_ctrl(struct rte_eth_dev * dev,enum rte_filter_type filter_type,enum rte_filter_op filter_op,void * arg)372 eth_igc_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type,
373 		enum rte_filter_op filter_op, void *arg)
374 {
375 	int ret = 0;
376 
377 	RTE_SET_USED(dev);
378 
379 	switch (filter_type) {
380 	case RTE_ETH_FILTER_GENERIC:
381 		if (filter_op != RTE_ETH_FILTER_GET)
382 			return -EINVAL;
383 		*(const void **)arg = &igc_flow_ops;
384 		break;
385 	default:
386 		PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
387 							filter_type);
388 		ret = -EINVAL;
389 	}
390 
391 	return ret;
392 }
393