xref: /dpdk/drivers/net/ionic/ionic_rx_filter.c (revision c5d0bb79fd113360187531602902a622ae964c53)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2018-2022 Advanced Micro Devices, Inc.
3  */
4 
5 #include <errno.h>
6 #include <stdbool.h>
7 
8 #include <rte_malloc.h>
9 
10 #include "ionic.h"
11 #include "ionic_lif.h"
12 #include "ionic_rx_filter.h"
13 
14 void
ionic_rx_filter_free(struct ionic_rx_filter * f)15 ionic_rx_filter_free(struct ionic_rx_filter *f)
16 {
17 	LIST_REMOVE(f, by_id);
18 	LIST_REMOVE(f, by_hash);
19 	rte_free(f);
20 }
21 
22 int
ionic_rx_filters_init(struct ionic_lif * lif)23 ionic_rx_filters_init(struct ionic_lif *lif)
24 {
25 	uint32_t i;
26 
27 	rte_spinlock_init(&lif->rx_filters.lock);
28 
29 	for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
30 		LIST_INIT(&lif->rx_filters.by_hash[i]);
31 		LIST_INIT(&lif->rx_filters.by_id[i]);
32 	}
33 
34 	return 0;
35 }
36 
37 void
ionic_rx_filters_deinit(struct ionic_lif * lif)38 ionic_rx_filters_deinit(struct ionic_lif *lif)
39 {
40 	struct ionic_rx_filter *f;
41 	uint32_t i;
42 
43 	for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
44 		while (!LIST_EMPTY(&lif->rx_filters.by_id[i])) {
45 			f = LIST_FIRST(&lif->rx_filters.by_id[i]);
46 			ionic_rx_filter_free(f);
47 		}
48 	}
49 }
50 
51 int
ionic_rx_filter_save(struct ionic_lif * lif,uint32_t flow_id,uint16_t rxq_index,struct ionic_admin_ctx * ctx)52 ionic_rx_filter_save(struct ionic_lif *lif, uint32_t flow_id,
53 		uint16_t rxq_index, struct ionic_admin_ctx *ctx)
54 {
55 	struct ionic_rx_filter *f;
56 	uint32_t key;
57 
58 	f = rte_zmalloc("ionic", sizeof(*f), RTE_CACHE_LINE_SIZE);
59 	if (!f)
60 		return -ENOMEM;
61 
62 	f->flow_id = flow_id;
63 	f->filter_id = rte_le_to_cpu_32(ctx->comp.rx_filter_add.filter_id);
64 	f->rxq_index = rxq_index;
65 	memcpy(&f->cmd, &ctx->cmd, sizeof(f->cmd));
66 	f->match = rte_le_to_cpu_16(f->cmd.match);
67 
68 	switch (f->match) {
69 	case IONIC_RX_FILTER_MATCH_VLAN:
70 		key = rte_le_to_cpu_16(f->cmd.vlan.vlan);
71 		break;
72 	case IONIC_RX_FILTER_MATCH_MAC:
73 		memcpy(&key, f->cmd.mac.addr, sizeof(key));
74 		break;
75 	default:
76 		return -EINVAL;
77 	}
78 
79 	key &= IONIC_RX_FILTER_HLISTS_MASK;
80 
81 	rte_spinlock_lock(&lif->rx_filters.lock);
82 
83 	LIST_INSERT_HEAD(&lif->rx_filters.by_hash[key], f, by_hash);
84 
85 	key = f->filter_id & IONIC_RX_FILTER_HLISTS_MASK;
86 
87 	LIST_INSERT_HEAD(&lif->rx_filters.by_id[key], f, by_id);
88 
89 	rte_spinlock_unlock(&lif->rx_filters.lock);
90 
91 	return 0;
92 }
93 
94 struct ionic_rx_filter *
ionic_rx_filter_by_vlan(struct ionic_lif * lif,uint16_t vid)95 ionic_rx_filter_by_vlan(struct ionic_lif *lif, uint16_t vid)
96 {
97 	uint32_t key = vid & IONIC_RX_FILTER_HLISTS_MASK;
98 	struct ionic_rx_filter *f;
99 	__le16 vid_le = rte_cpu_to_le_16(vid);
100 
101 	LIST_FOREACH(f, &lif->rx_filters.by_hash[key], by_hash) {
102 		if (f->match != IONIC_RX_FILTER_MATCH_VLAN)
103 			continue;
104 		if (f->cmd.vlan.vlan == vid_le)
105 			return f;
106 	}
107 
108 	return NULL;
109 }
110 
111 struct ionic_rx_filter *
ionic_rx_filter_by_addr(struct ionic_lif * lif,const uint8_t * addr)112 ionic_rx_filter_by_addr(struct ionic_lif *lif, const uint8_t *addr)
113 {
114 	const uint32_t key = *(const uint32_t *)addr &
115 		IONIC_RX_FILTER_HLISTS_MASK;
116 	struct ionic_rx_filter *f;
117 
118 	LIST_FOREACH(f, &lif->rx_filters.by_hash[key], by_hash) {
119 		if (f->match != IONIC_RX_FILTER_MATCH_MAC)
120 			continue;
121 		if (memcmp(addr, f->cmd.mac.addr, RTE_ETHER_ADDR_LEN) == 0)
122 			return f;
123 	}
124 
125 	return NULL;
126 }
127