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 <linux/in6.h> |
13 | #include <asm/byteorder.h> |
14 | |
15 | /** |
16 | * enum efx_filter_match_flags - Flags for hardware filter match type |
17 | * @EFX_FILTER_MATCH_REM_HOST: Match by remote IP host address |
18 | * @EFX_FILTER_MATCH_LOC_HOST: Match by local IP host address |
19 | * @EFX_FILTER_MATCH_REM_MAC: Match by remote MAC address |
20 | * @EFX_FILTER_MATCH_REM_PORT: Match by remote TCP/UDP port |
21 | * @EFX_FILTER_MATCH_LOC_MAC: Match by local MAC address |
22 | * @EFX_FILTER_MATCH_LOC_PORT: Match by local TCP/UDP port |
23 | * @EFX_FILTER_MATCH_ETHER_TYPE: Match by Ether-type |
24 | * @EFX_FILTER_MATCH_INNER_VID: Match by inner VLAN ID |
25 | * @EFX_FILTER_MATCH_OUTER_VID: Match by outer VLAN ID |
26 | * @EFX_FILTER_MATCH_IP_PROTO: Match by IP transport protocol |
27 | * @EFX_FILTER_MATCH_LOC_MAC_IG: Match by local MAC address I/G bit. |
28 | * @EFX_FILTER_MATCH_ENCAP_TYPE: Match by encapsulation type. |
29 | * Used for RX default unicast and multicast/broadcast filters. |
30 | * |
31 | * Only some combinations are supported, depending on NIC type: |
32 | * |
33 | * - Huntington supports filter matching controlled by firmware, potentially |
34 | * using {TCP,UDP}/IPv{4,6} 4-tuple or local 2-tuple, local MAC or I/G bit, |
35 | * with or without outer and inner VID |
36 | */ |
37 | enum efx_filter_match_flags { |
38 | EFX_FILTER_MATCH_REM_HOST = 0x0001, |
39 | EFX_FILTER_MATCH_LOC_HOST = 0x0002, |
40 | EFX_FILTER_MATCH_REM_MAC = 0x0004, |
41 | EFX_FILTER_MATCH_REM_PORT = 0x0008, |
42 | EFX_FILTER_MATCH_LOC_MAC = 0x0010, |
43 | EFX_FILTER_MATCH_LOC_PORT = 0x0020, |
44 | EFX_FILTER_MATCH_ETHER_TYPE = 0x0040, |
45 | EFX_FILTER_MATCH_INNER_VID = 0x0080, |
46 | EFX_FILTER_MATCH_OUTER_VID = 0x0100, |
47 | EFX_FILTER_MATCH_IP_PROTO = 0x0200, |
48 | EFX_FILTER_MATCH_LOC_MAC_IG = 0x0400, |
49 | EFX_FILTER_MATCH_ENCAP_TYPE = 0x0800, |
50 | }; |
51 | |
52 | /** |
53 | * enum efx_filter_priority - priority of a hardware filter specification |
54 | * @EFX_FILTER_PRI_HINT: Performance hint |
55 | * @EFX_FILTER_PRI_AUTO: Automatic filter based on device address list |
56 | * or hardware requirements. This may only be used by the filter |
57 | * implementation for each NIC type. |
58 | * @EFX_FILTER_PRI_MANUAL: Manually configured filter |
59 | * @EFX_FILTER_PRI_REQUIRED: Required for correct behaviour (user-level |
60 | * networking and SR-IOV) |
61 | */ |
62 | enum efx_filter_priority { |
63 | EFX_FILTER_PRI_HINT = 0, |
64 | EFX_FILTER_PRI_AUTO, |
65 | EFX_FILTER_PRI_MANUAL, |
66 | EFX_FILTER_PRI_REQUIRED, |
67 | }; |
68 | |
69 | /** |
70 | * enum efx_filter_flags - flags for hardware filter specifications |
71 | * @EFX_FILTER_FLAG_RX_RSS: Use RSS to spread across multiple queues. |
72 | * By default, matching packets will be delivered only to the |
73 | * specified queue. If this flag is set, they will be delivered |
74 | * to a range of queues offset from the specified queue number |
75 | * according to the indirection table. |
76 | * @EFX_FILTER_FLAG_RX_SCATTER: Enable DMA scatter on the receiving |
77 | * queue. |
78 | * @EFX_FILTER_FLAG_RX_OVER_AUTO: Indicates a filter that is |
79 | * overriding an automatic filter (priority |
80 | * %EFX_FILTER_PRI_AUTO). This may only be set by the filter |
81 | * implementation for each type. A removal request will restore |
82 | * the automatic filter in its place. |
83 | * @EFX_FILTER_FLAG_RX: Filter is for RX |
84 | * @EFX_FILTER_FLAG_TX: Filter is for TX |
85 | * @EFX_FILTER_FLAG_VPORT_ID: Virtual port ID for adapter switching. |
86 | */ |
87 | enum efx_filter_flags { |
88 | = 0x01, |
89 | EFX_FILTER_FLAG_RX_SCATTER = 0x02, |
90 | EFX_FILTER_FLAG_RX_OVER_AUTO = 0x04, |
91 | EFX_FILTER_FLAG_RX = 0x08, |
92 | EFX_FILTER_FLAG_TX = 0x10, |
93 | EFX_FILTER_FLAG_VPORT_ID = 0x20, |
94 | }; |
95 | |
96 | /** enum efx_encap_type - types of encapsulation |
97 | * @EFX_ENCAP_TYPE_NONE: no encapsulation |
98 | * @EFX_ENCAP_TYPE_VXLAN: VXLAN encapsulation |
99 | * @EFX_ENCAP_TYPE_NVGRE: NVGRE encapsulation |
100 | * @EFX_ENCAP_TYPE_GENEVE: GENEVE encapsulation |
101 | * @EFX_ENCAP_FLAG_IPV6: indicates IPv6 outer frame |
102 | * |
103 | * Contains both enumerated types and flags. |
104 | * To get just the type, OR with @EFX_ENCAP_TYPES_MASK. |
105 | */ |
106 | enum efx_encap_type { |
107 | EFX_ENCAP_TYPE_NONE = 0, |
108 | EFX_ENCAP_TYPE_VXLAN = 1, |
109 | EFX_ENCAP_TYPE_NVGRE = 2, |
110 | EFX_ENCAP_TYPE_GENEVE = 3, |
111 | |
112 | EFX_ENCAP_TYPES_MASK = 7, |
113 | EFX_ENCAP_FLAG_IPV6 = 8, |
114 | }; |
115 | |
116 | /** |
117 | * struct efx_filter_spec - specification for a hardware filter |
118 | * @match_flags: Match type flags, from &enum efx_filter_match_flags |
119 | * @priority: Priority of the filter, from &enum efx_filter_priority |
120 | * @flags: Miscellaneous flags, from &enum efx_filter_flags |
121 | * @rss_context: RSS context to use, if %EFX_FILTER_FLAG_RX_RSS is set. This |
122 | * is a user_id (with 0 meaning the driver/default RSS context), not an |
123 | * MCFW context_id. |
124 | * @dmaq_id: Source/target queue index, or %EFX_FILTER_RX_DMAQ_ID_DROP for |
125 | * an RX drop filter |
126 | * @vport_id: Virtual port ID associated with RX queue, for adapter switching, |
127 | * if %EFX_FILTER_FLAG_VPORT_ID is set. This is an MCFW vport_id, or on |
128 | * EF100 an mport selector. |
129 | * @outer_vid: Outer VLAN ID to match, if %EFX_FILTER_MATCH_OUTER_VID is set |
130 | * @inner_vid: Inner VLAN ID to match, if %EFX_FILTER_MATCH_INNER_VID is set |
131 | * @loc_mac: Local MAC address to match, if %EFX_FILTER_MATCH_LOC_MAC or |
132 | * %EFX_FILTER_MATCH_LOC_MAC_IG is set |
133 | * @rem_mac: Remote MAC address to match, if %EFX_FILTER_MATCH_REM_MAC is set |
134 | * @ether_type: Ether-type to match, if %EFX_FILTER_MATCH_ETHER_TYPE is set |
135 | * @ip_proto: IP transport protocol to match, if %EFX_FILTER_MATCH_IP_PROTO |
136 | * is set |
137 | * @loc_host: Local IP host to match, if %EFX_FILTER_MATCH_LOC_HOST is set |
138 | * @rem_host: Remote IP host to match, if %EFX_FILTER_MATCH_REM_HOST is set |
139 | * @loc_port: Local TCP/UDP port to match, if %EFX_FILTER_MATCH_LOC_PORT is set |
140 | * @rem_port: Remote TCP/UDP port to match, if %EFX_FILTER_MATCH_REM_PORT is set |
141 | * @encap_type: Encapsulation type to match (from &enum efx_encap_type), if |
142 | * %EFX_FILTER_MATCH_ENCAP_TYPE is set |
143 | * |
144 | * The efx_filter_init_rx() or efx_filter_init_tx() function *must* be |
145 | * used to initialise the structure. The efx_filter_set_*() functions |
146 | * may then be used to set @rss_context, @match_flags and related |
147 | * fields. |
148 | * |
149 | * The @priority field is used by software to determine whether a new |
150 | * filter may replace an old one. The hardware priority of a filter |
151 | * depends on which fields are matched. |
152 | */ |
153 | struct efx_filter_spec { |
154 | u32 match_flags:12; |
155 | u32 priority:2; |
156 | u32 flags:6; |
157 | u32 dmaq_id:12; |
158 | u32 ; |
159 | u32 vport_id; |
160 | __be16 outer_vid; |
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_ipv6_local - specify IPv6 host, transport protocol and port |
222 | * @spec: Specification to initialise |
223 | * @proto: Transport layer protocol number |
224 | * @host: Local host address (network byte order) |
225 | * @port: Local port (network byte order) |
226 | */ |
227 | static inline int |
228 | efx_filter_set_ipv6_local(struct efx_filter_spec *spec, u8 proto, |
229 | const struct in6_addr *host, __be16 port) |
230 | { |
231 | spec->match_flags |= |
232 | EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO | |
233 | EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT; |
234 | spec->ether_type = htons(ETH_P_IPV6); |
235 | spec->ip_proto = proto; |
236 | memcpy(spec->loc_host, host, sizeof(spec->loc_host)); |
237 | spec->loc_port = port; |
238 | return 0; |
239 | } |
240 | |
241 | /** |
242 | * efx_filter_set_ipv4_full - specify IPv4 hosts, transport protocol and ports |
243 | * @spec: Specification to initialise |
244 | * @proto: Transport layer protocol number |
245 | * @lhost: Local host address (network byte order) |
246 | * @lport: Local port (network byte order) |
247 | * @rhost: Remote host address (network byte order) |
248 | * @rport: Remote port (network byte order) |
249 | */ |
250 | static inline int |
251 | efx_filter_set_ipv4_full(struct efx_filter_spec *spec, u8 proto, |
252 | __be32 lhost, __be16 lport, |
253 | __be32 rhost, __be16 rport) |
254 | { |
255 | spec->match_flags |= |
256 | EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO | |
257 | EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT | |
258 | EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT; |
259 | spec->ether_type = htons(ETH_P_IP); |
260 | spec->ip_proto = proto; |
261 | spec->loc_host[0] = lhost; |
262 | spec->loc_port = lport; |
263 | spec->rem_host[0] = rhost; |
264 | spec->rem_port = rport; |
265 | return 0; |
266 | } |
267 | |
268 | enum { |
269 | EFX_FILTER_VID_UNSPEC = 0xffff, |
270 | }; |
271 | |
272 | /** |
273 | * efx_filter_set_eth_local - specify local Ethernet address and/or VID |
274 | * @spec: Specification to initialise |
275 | * @vid: Outer VLAN ID to match, or %EFX_FILTER_VID_UNSPEC |
276 | * @addr: Local Ethernet MAC address, or %NULL |
277 | */ |
278 | static inline int efx_filter_set_eth_local(struct efx_filter_spec *spec, |
279 | u16 vid, const u8 *addr) |
280 | { |
281 | if (vid == EFX_FILTER_VID_UNSPEC && addr == NULL) |
282 | return -EINVAL; |
283 | |
284 | if (vid != EFX_FILTER_VID_UNSPEC) { |
285 | spec->match_flags |= EFX_FILTER_MATCH_OUTER_VID; |
286 | spec->outer_vid = htons(vid); |
287 | } |
288 | if (addr != NULL) { |
289 | spec->match_flags |= EFX_FILTER_MATCH_LOC_MAC; |
290 | ether_addr_copy(dst: spec->loc_mac, src: addr); |
291 | } |
292 | return 0; |
293 | } |
294 | |
295 | /** |
296 | * efx_filter_set_uc_def - specify matching otherwise-unmatched unicast |
297 | * @spec: Specification to initialise |
298 | */ |
299 | static inline int efx_filter_set_uc_def(struct efx_filter_spec *spec) |
300 | { |
301 | spec->match_flags |= EFX_FILTER_MATCH_LOC_MAC_IG; |
302 | return 0; |
303 | } |
304 | |
305 | /** |
306 | * efx_filter_set_mc_def - specify matching otherwise-unmatched multicast |
307 | * @spec: Specification to initialise |
308 | */ |
309 | static inline int efx_filter_set_mc_def(struct efx_filter_spec *spec) |
310 | { |
311 | spec->match_flags |= EFX_FILTER_MATCH_LOC_MAC_IG; |
312 | spec->loc_mac[0] = 1; |
313 | return 0; |
314 | } |
315 | |
316 | /** |
317 | * efx_filter_set_vport_id - override virtual port id relating to filter |
318 | * @spec: Specification to initialise |
319 | * @vport_id: firmware ID of the virtual port |
320 | */ |
321 | static inline void efx_filter_set_vport_id(struct efx_filter_spec *spec, |
322 | u32 vport_id) |
323 | { |
324 | spec->flags |= EFX_FILTER_FLAG_VPORT_ID; |
325 | spec->vport_id = vport_id; |
326 | } |
327 | |
328 | static inline void efx_filter_set_encap_type(struct efx_filter_spec *spec, |
329 | enum efx_encap_type encap_type) |
330 | { |
331 | spec->match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE; |
332 | spec->encap_type = encap_type; |
333 | } |
334 | |
335 | static inline enum efx_encap_type efx_filter_get_encap_type( |
336 | const struct efx_filter_spec *spec) |
337 | { |
338 | if (spec->match_flags & EFX_FILTER_MATCH_ENCAP_TYPE) |
339 | return spec->encap_type; |
340 | return EFX_ENCAP_TYPE_NONE; |
341 | } |
342 | #endif /* EFX_FILTER_H */ |
343 | |