1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2020 Intel Corporation
5 #include "rte_malloc.h"
8 #include "igc_filter.h"
12 * igc_ethertype_filter_lookup - lookup ether-type filter
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
21 * >= 0, item index of the ether-type filter
22 * -1, the item not been found
25 igc_ethertype_filter_lookup(const struct igc_adapter *igc,
26 uint16_t ethertype, int *empty)
31 /* set to invalid valid */
34 /* search the filters array */
35 for (; i < IGC_MAX_ETQF_FILTERS; i++) {
36 if (igc->ethertype_filters[i].ether_type == ethertype)
38 if (igc->ethertype_filters[i].ether_type == 0) {
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 */
57 igc_del_ethertype_filter(struct rte_eth_dev *dev,
58 const struct igc_ethertype_filter *filter)
60 struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
61 struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
64 if (filter->ether_type == 0) {
65 PMD_DRV_LOG(ERR, "Ethertype 0 is not been supported");
69 ret = igc_ethertype_filter_lookup(igc, filter->ether_type, NULL);
73 "Ethertype (0x%04x) filter doesn't exist",
78 igc->ethertype_filters[ret].ether_type = 0;
80 IGC_WRITE_REG(hw, IGC_ETQF(ret), 0);
86 igc_add_ethertype_filter(struct rte_eth_dev *dev,
87 const struct igc_ethertype_filter *filter)
89 struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
90 struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
94 if (filter->ether_type == RTE_ETHER_TYPE_IPV4 ||
95 filter->ether_type == RTE_ETHER_TYPE_IPV6 ||
96 filter->ether_type == 0) {
98 "Unsupported ether_type(0x%04x) in ethertype filter",
103 ret = igc_ethertype_filter_lookup(igc, filter->ether_type, &empty);
105 PMD_DRV_LOG(ERR, "ethertype (0x%04x) filter exists.",
111 PMD_DRV_LOG(ERR, "no ethertype filter entry.");
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;
120 memcpy(&igc->ethertype_filters[ret], filter, sizeof(*filter));
122 IGC_WRITE_REG(hw, IGC_ETQF(ret), etqf);
127 /* clear all the ether type filters */
129 igc_clear_all_ethertype_filter(struct rte_eth_dev *dev)
131 struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
132 struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
135 for (i = 0; i < IGC_MAX_ETQF_FILTERS; i++)
136 IGC_WRITE_REG(hw, IGC_ETQF(i), 0);
139 memset(&igc->ethertype_filters, 0, sizeof(igc->ethertype_filters));
143 * igc_tuple_filter_lookup - lookup n-tuple filter
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
153 * >= 0, item index of the filter
154 * -1, the item not been found
157 igc_tuple_filter_lookup(const struct igc_adapter *igc,
158 const struct igc_ntuple_filter *ntuple,
164 /* set initial value */
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 */
176 /* get the empty entry */
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 */
194 /* Set hardware register values */
196 igc_enable_tuple_filter(struct rte_eth_dev *dev,
197 const struct igc_adapter *igc, uint8_t index)
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;
204 imir = info->dst_port;
205 imir |= (uint32_t)info->priority << IGC_IMIR_PRIORITY_SHIFT;
207 /* 0b means not compare. */
208 if (info->dst_port_mask == 0)
209 imir |= IGC_IMIR_PORT_BP;
211 ttqf = IGC_TTQF_DISABLE_MASK | IGC_TTQF_QUEUE_ENABLE;
212 ttqf |= (uint32_t)filter->queue << IGC_TTQF_QUEUE_SHIFT;
215 if (info->proto_mask)
216 ttqf &= ~IGC_TTQF_MASK_ENABLE;
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;
233 imir_ext |= IGC_IMIREXT_CTRL_BP;
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);
242 /* Reset hardware register values */
244 igc_disable_tuple_filter(struct rte_eth_dev *dev, uint8_t index)
246 struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
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);
255 igc_add_ntuple_filter(struct rte_eth_dev *dev,
256 const struct igc_ntuple_filter *ntuple)
258 struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
261 ret = igc_tuple_filter_lookup(igc, ntuple, &empty);
263 PMD_DRV_LOG(ERR, "filter exists.");
268 PMD_DRV_LOG(ERR, "filter no entry.");
273 memcpy(&igc->ntuple_filters[ret], ntuple, sizeof(*ntuple));
274 igc_enable_tuple_filter(dev, igc, (uint8_t)ret);
279 igc_del_ntuple_filter(struct rte_eth_dev *dev,
280 const struct igc_ntuple_filter *ntuple)
282 struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
285 ret = igc_tuple_filter_lookup(igc, ntuple, NULL);
287 PMD_DRV_LOG(ERR, "filter not exists.");
291 memset(&igc->ntuple_filters[ret], 0, sizeof(*ntuple));
292 igc_disable_tuple_filter(dev, (uint8_t)ret);
296 /* Clear all the n-tuple filters */
298 igc_clear_all_ntuple_filter(struct rte_eth_dev *dev)
300 struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
303 for (i = 0; i < IGC_MAX_NTUPLE_FILTERS; i++)
304 igc_disable_tuple_filter(dev, i);
306 memset(&igc->ntuple_filters, 0, sizeof(igc->ntuple_filters));
310 igc_set_syn_filter(struct rte_eth_dev *dev,
311 const struct igc_syn_filter *filter)
314 struct igc_adapter *igc;
315 uint32_t synqf, rfctl;
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);
323 igc = IGC_DEV_PRIVATE(dev);
325 if (igc->syn_filter.enable) {
326 PMD_DRV_LOG(ERR, "SYN filter has been enabled before!");
330 hw = IGC_DEV_PRIVATE_HW(dev);
331 synqf = (uint32_t)filter->queue << IGC_SYN_FILTER_QUEUE_SHIFT;
332 synqf |= IGC_SYN_FILTER_ENABLE;
334 rfctl = IGC_READ_REG(hw, IGC_RFCTL);
336 rfctl |= IGC_RFCTL_SYNQFP;
338 rfctl &= ~IGC_RFCTL_SYNQFP;
340 memcpy(&igc->syn_filter, filter, sizeof(igc->syn_filter));
341 igc->syn_filter.enable = 1;
343 IGC_WRITE_REG(hw, IGC_RFCTL, rfctl);
344 IGC_WRITE_REG(hw, IGC_SYNQF(0), synqf);
349 /* clear the SYN filter */
351 igc_clear_syn_filter(struct rte_eth_dev *dev)
353 struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
354 struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
356 IGC_WRITE_REG(hw, IGC_SYNQF(0), 0);
359 memset(&igc->syn_filter, 0, sizeof(igc->syn_filter));
363 igc_clear_all_filter(struct rte_eth_dev *dev)
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);
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)
379 switch (filter_type) {
380 case RTE_ETH_FILTER_GENERIC:
381 if (filter_op != RTE_ETH_FILTER_GET)
383 *(const void **)arg = &igc_flow_ops;
386 PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",