1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /**************************************************************************** |
3 | * Driver for Solarflare network controllers and boards |
4 | * Copyright 2005-2013 Solarflare Communications Inc. |
5 | */ |
6 | |
7 | #ifndef EFX_FILTER_H |
8 | #define EFX_FILTER_H |
9 | |
10 | #include <linux/types.h> |
11 | #include <linux/if_ether.h> |
12 | #include <asm/byteorder.h> |
13 | |
14 | /** |
15 | * enum efx_filter_match_flags - Flags for hardware filter match type |
16 | * @EFX_FILTER_MATCH_REM_HOST: Match by remote IP host address |
17 | * @EFX_FILTER_MATCH_LOC_HOST: Match by local IP host address |
18 | * @EFX_FILTER_MATCH_REM_MAC: Match by remote MAC address |
19 | * @EFX_FILTER_MATCH_REM_PORT: Match by remote TCP/UDP port |
20 | * @EFX_FILTER_MATCH_LOC_MAC: Match by local MAC address |
21 | * @EFX_FILTER_MATCH_LOC_PORT: Match by local TCP/UDP port |
22 | * @EFX_FILTER_MATCH_ETHER_TYPE: Match by Ether-type |
23 | * @EFX_FILTER_MATCH_INNER_VID: Match by inner VLAN ID |
24 | * @EFX_FILTER_MATCH_OUTER_VID: Match by outer VLAN ID |
25 | * @EFX_FILTER_MATCH_IP_PROTO: Match by IP transport protocol |
26 | * @EFX_FILTER_MATCH_LOC_MAC_IG: Match by local MAC address I/G bit. |
27 | * @EFX_FILTER_MATCH_ENCAP_TYPE: Match by encapsulation type. |
28 | * Used for RX default unicast and multicast/broadcast filters. |
29 | * |
30 | * Only some combinations are supported, depending on NIC type: |
31 | * |
32 | * - Falcon supports RX filters matching by {TCP,UDP}/IPv4 4-tuple or |
33 | * local 2-tuple (only implemented for Falcon B0) |
34 | * |
35 | * - Siena supports RX and TX filters matching by {TCP,UDP}/IPv4 4-tuple |
36 | * or local 2-tuple, or local MAC with or without outer VID, and RX |
37 | * default filters |
38 | * |
39 | * - Huntington supports filter matching controlled by firmware, potentially |
40 | * using {TCP,UDP}/IPv{4,6} 4-tuple or local 2-tuple, local MAC or I/G bit, |
41 | * with or without outer and inner VID |
42 | */ |
43 | enum efx_filter_match_flags { |
44 | EFX_FILTER_MATCH_REM_HOST = 0x0001, |
45 | EFX_FILTER_MATCH_LOC_HOST = 0x0002, |
46 | EFX_FILTER_MATCH_REM_MAC = 0x0004, |
47 | EFX_FILTER_MATCH_REM_PORT = 0x0008, |
48 | EFX_FILTER_MATCH_LOC_MAC = 0x0010, |
49 | EFX_FILTER_MATCH_LOC_PORT = 0x0020, |
50 | EFX_FILTER_MATCH_ETHER_TYPE = 0x0040, |
51 | EFX_FILTER_MATCH_INNER_VID = 0x0080, |
52 | EFX_FILTER_MATCH_OUTER_VID = 0x0100, |
53 | EFX_FILTER_MATCH_IP_PROTO = 0x0200, |
54 | EFX_FILTER_MATCH_LOC_MAC_IG = 0x0400, |
55 | EFX_FILTER_MATCH_ENCAP_TYPE = 0x0800, |
56 | }; |
57 | |
58 | /** |
59 | * enum efx_filter_priority - priority of a hardware filter specification |
60 | * @EFX_FILTER_PRI_HINT: Performance hint |
61 | * @EFX_FILTER_PRI_AUTO: Automatic filter based on device address list |
62 | * or hardware requirements. This may only be used by the filter |
63 | * implementation for each NIC type. |
64 | * @EFX_FILTER_PRI_MANUAL: Manually configured filter |
65 | * @EFX_FILTER_PRI_REQUIRED: Required for correct behaviour (user-level |
66 | * networking and SR-IOV) |
67 | */ |
68 | enum efx_filter_priority { |
69 | EFX_FILTER_PRI_HINT = 0, |
70 | EFX_FILTER_PRI_AUTO, |
71 | EFX_FILTER_PRI_MANUAL, |
72 | EFX_FILTER_PRI_REQUIRED, |
73 | }; |
74 | |
75 | /** |
76 | * enum efx_filter_flags - flags for hardware filter specifications |
77 | * @EFX_FILTER_FLAG_RX_RSS: Use RSS to spread across multiple queues. |
78 | * By default, matching packets will be delivered only to the |
79 | * specified queue. If this flag is set, they will be delivered |
80 | * to a range of queues offset from the specified queue number |
81 | * according to the indirection table. |
82 | * @EFX_FILTER_FLAG_RX_SCATTER: Enable DMA scatter on the receiving |
83 | * queue. |
84 | * @EFX_FILTER_FLAG_RX_OVER_AUTO: Indicates a filter that is |
85 | * overriding an automatic filter (priority |
86 | * %EFX_FILTER_PRI_AUTO). This may only be set by the filter |
87 | * implementation for each type. A removal request will restore |
88 | * the automatic filter in its place. |
89 | * @EFX_FILTER_FLAG_RX: Filter is for RX |
90 | * @EFX_FILTER_FLAG_TX: Filter is for TX |
91 | */ |
92 | enum efx_filter_flags { |
93 | = 0x01, |
94 | EFX_FILTER_FLAG_RX_SCATTER = 0x02, |
95 | EFX_FILTER_FLAG_RX_OVER_AUTO = 0x04, |
96 | EFX_FILTER_FLAG_RX = 0x08, |
97 | EFX_FILTER_FLAG_TX = 0x10, |
98 | }; |
99 | |
100 | /** enum efx_encap_type - types of encapsulation |
101 | * @EFX_ENCAP_TYPE_NONE: no encapsulation |
102 | * @EFX_ENCAP_TYPE_VXLAN: VXLAN encapsulation |
103 | * @EFX_ENCAP_TYPE_NVGRE: NVGRE encapsulation |
104 | * @EFX_ENCAP_TYPE_GENEVE: GENEVE encapsulation |
105 | * @EFX_ENCAP_FLAG_IPV6: indicates IPv6 outer frame |
106 | * |
107 | * Contains both enumerated types and flags. |
108 | * To get just the type, OR with @EFX_ENCAP_TYPES_MASK. |
109 | */ |
110 | enum efx_encap_type { |
111 | EFX_ENCAP_TYPE_NONE = 0, |
112 | EFX_ENCAP_TYPE_VXLAN = 1, |
113 | EFX_ENCAP_TYPE_NVGRE = 2, |
114 | EFX_ENCAP_TYPE_GENEVE = 3, |
115 | |
116 | EFX_ENCAP_TYPES_MASK = 7, |
117 | EFX_ENCAP_FLAG_IPV6 = 8, |
118 | }; |
119 | |
120 | /** |
121 | * struct efx_filter_spec - specification for a hardware filter |
122 | * @match_flags: Match type flags, from &enum efx_filter_match_flags |
123 | * @priority: Priority of the filter, from &enum efx_filter_priority |
124 | * @flags: Miscellaneous flags, from &enum efx_filter_flags |
125 | * @rss_context: RSS context to use, if %EFX_FILTER_FLAG_RX_RSS is set. This |
126 | * is a user_id (with 0 meaning the driver/default RSS context), not an |
127 | * MCFW context_id. |
128 | * @dmaq_id: Source/target queue index, or %EFX_FILTER_RX_DMAQ_ID_DROP for |
129 | * an RX drop filter |
130 | * @outer_vid: Outer VLAN ID to match, if %EFX_FILTER_MATCH_OUTER_VID is set |
131 | * @inner_vid: Inner VLAN ID to match, if %EFX_FILTER_MATCH_INNER_VID is set |
132 | * @loc_mac: Local MAC address to match, if %EFX_FILTER_MATCH_LOC_MAC or |
133 | * %EFX_FILTER_MATCH_LOC_MAC_IG is set |
134 | * @rem_mac: Remote MAC address to match, if %EFX_FILTER_MATCH_REM_MAC is set |
135 | * @ether_type: Ether-type to match, if %EFX_FILTER_MATCH_ETHER_TYPE is set |
136 | * @ip_proto: IP transport protocol to match, if %EFX_FILTER_MATCH_IP_PROTO |
137 | * is set |
138 | * @loc_host: Local IP host to match, if %EFX_FILTER_MATCH_LOC_HOST is set |
139 | * @rem_host: Remote IP host to match, if %EFX_FILTER_MATCH_REM_HOST is set |
140 | * @loc_port: Local TCP/UDP port to match, if %EFX_FILTER_MATCH_LOC_PORT is set |
141 | * @rem_port: Remote TCP/UDP port to match, if %EFX_FILTER_MATCH_REM_PORT is set |
142 | * @encap_type: Encapsulation type to match (from &enum efx_encap_type), if |
143 | * %EFX_FILTER_MATCH_ENCAP_TYPE is set |
144 | * |
145 | * The efx_filter_init_rx() or efx_filter_init_tx() function *must* be |
146 | * used to initialise the structure. The efx_filter_set_*() functions |
147 | * may then be used to set @rss_context, @match_flags and related |
148 | * fields. |
149 | * |
150 | * The @priority field is used by software to determine whether a new |
151 | * filter may replace an old one. The hardware priority of a filter |
152 | * depends on which fields are matched. |
153 | */ |
154 | struct efx_filter_spec { |
155 | u32 match_flags:12; |
156 | u32 priority:2; |
157 | u32 flags:6; |
158 | u32 dmaq_id:12; |
159 | u32 ; |
160 | __be16 outer_vid __aligned(4); /* allow jhash2() of match values */ |
161 | __be16 inner_vid; |
162 | u8 loc_mac[ETH_ALEN]; |
163 | u8 rem_mac[ETH_ALEN]; |
164 | __be16 ether_type; |
165 | u8 ip_proto; |
166 | __be32 loc_host[4]; |
167 | __be32 rem_host[4]; |
168 | __be16 loc_port; |
169 | __be16 rem_port; |
170 | u32 encap_type:4; |
171 | /* total 65 bytes */ |
172 | }; |
173 | |
174 | enum { |
175 | EFX_FILTER_RX_DMAQ_ID_DROP = 0xfff |
176 | }; |
177 | |
178 | static inline void efx_filter_init_rx(struct efx_filter_spec *spec, |
179 | enum efx_filter_priority priority, |
180 | enum efx_filter_flags flags, |
181 | unsigned rxq_id) |
182 | { |
183 | memset(spec, 0, sizeof(*spec)); |
184 | spec->priority = priority; |
185 | spec->flags = EFX_FILTER_FLAG_RX | flags; |
186 | spec->rss_context = 0; |
187 | spec->dmaq_id = rxq_id; |
188 | } |
189 | |
190 | static inline void efx_filter_init_tx(struct efx_filter_spec *spec, |
191 | unsigned txq_id) |
192 | { |
193 | memset(spec, 0, sizeof(*spec)); |
194 | spec->priority = EFX_FILTER_PRI_REQUIRED; |
195 | spec->flags = EFX_FILTER_FLAG_TX; |
196 | spec->dmaq_id = txq_id; |
197 | } |
198 | |
199 | /** |
200 | * efx_filter_set_ipv4_local - specify IPv4 host, transport protocol and port |
201 | * @spec: Specification to initialise |
202 | * @proto: Transport layer protocol number |
203 | * @host: Local host address (network byte order) |
204 | * @port: Local port (network byte order) |
205 | */ |
206 | static inline int |
207 | efx_filter_set_ipv4_local(struct efx_filter_spec *spec, u8 proto, |
208 | __be32 host, __be16 port) |
209 | { |
210 | spec->match_flags |= |
211 | EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO | |
212 | EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT; |
213 | spec->ether_type = htons(ETH_P_IP); |
214 | spec->ip_proto = proto; |
215 | spec->loc_host[0] = host; |
216 | spec->loc_port = port; |
217 | return 0; |
218 | } |
219 | |
220 | /** |
221 | * efx_filter_set_ipv4_full - specify IPv4 hosts, transport protocol and ports |
222 | * @spec: Specification to initialise |
223 | * @proto: Transport layer protocol number |
224 | * @lhost: Local host address (network byte order) |
225 | * @lport: Local port (network byte order) |
226 | * @rhost: Remote host address (network byte order) |
227 | * @rport: Remote port (network byte order) |
228 | */ |
229 | static inline int |
230 | efx_filter_set_ipv4_full(struct efx_filter_spec *spec, u8 proto, |
231 | __be32 lhost, __be16 lport, |
232 | __be32 rhost, __be16 rport) |
233 | { |
234 | spec->match_flags |= |
235 | EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO | |
236 | EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT | |
237 | EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT; |
238 | spec->ether_type = htons(ETH_P_IP); |
239 | spec->ip_proto = proto; |
240 | spec->loc_host[0] = lhost; |
241 | spec->loc_port = lport; |
242 | spec->rem_host[0] = rhost; |
243 | spec->rem_port = rport; |
244 | return 0; |
245 | } |
246 | |
247 | enum { |
248 | EFX_FILTER_VID_UNSPEC = 0xffff, |
249 | }; |
250 | |
251 | /** |
252 | * efx_filter_set_eth_local - specify local Ethernet address and/or VID |
253 | * @spec: Specification to initialise |
254 | * @vid: Outer VLAN ID to match, or %EFX_FILTER_VID_UNSPEC |
255 | * @addr: Local Ethernet MAC address, or %NULL |
256 | */ |
257 | static inline int efx_filter_set_eth_local(struct efx_filter_spec *spec, |
258 | u16 vid, const u8 *addr) |
259 | { |
260 | if (vid == EFX_FILTER_VID_UNSPEC && addr == NULL) |
261 | return -EINVAL; |
262 | |
263 | if (vid != EFX_FILTER_VID_UNSPEC) { |
264 | spec->match_flags |= EFX_FILTER_MATCH_OUTER_VID; |
265 | spec->outer_vid = htons(vid); |
266 | } |
267 | if (addr != NULL) { |
268 | spec->match_flags |= EFX_FILTER_MATCH_LOC_MAC; |
269 | ether_addr_copy(dst: spec->loc_mac, src: addr); |
270 | } |
271 | return 0; |
272 | } |
273 | |
274 | /** |
275 | * efx_filter_set_uc_def - specify matching otherwise-unmatched unicast |
276 | * @spec: Specification to initialise |
277 | */ |
278 | static inline int efx_filter_set_uc_def(struct efx_filter_spec *spec) |
279 | { |
280 | spec->match_flags |= EFX_FILTER_MATCH_LOC_MAC_IG; |
281 | return 0; |
282 | } |
283 | |
284 | /** |
285 | * efx_filter_set_mc_def - specify matching otherwise-unmatched multicast |
286 | * @spec: Specification to initialise |
287 | */ |
288 | static inline int efx_filter_set_mc_def(struct efx_filter_spec *spec) |
289 | { |
290 | spec->match_flags |= EFX_FILTER_MATCH_LOC_MAC_IG; |
291 | spec->loc_mac[0] = 1; |
292 | return 0; |
293 | } |
294 | |
295 | static inline void efx_filter_set_encap_type(struct efx_filter_spec *spec, |
296 | enum efx_encap_type encap_type) |
297 | { |
298 | spec->match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE; |
299 | spec->encap_type = encap_type; |
300 | } |
301 | |
302 | static inline enum efx_encap_type efx_filter_get_encap_type( |
303 | const struct efx_filter_spec *spec) |
304 | { |
305 | if (spec->match_flags & EFX_FILTER_MATCH_ENCAP_TYPE) |
306 | return spec->encap_type; |
307 | return EFX_ENCAP_TYPE_NONE; |
308 | } |
309 | #endif /* EFX_FILTER_H */ |
310 | |