rss_config.c revision 1.3 1 1.3 knakahar /* $NetBSD: rss_config.c,v 1.3 2021/09/24 04:11:02 knakahara Exp $ */
2 1.1 knakahar
3 1.1 knakahar /*
4 1.1 knakahar * Copyright (c) 2018 Internet Initiative Japan Inc.
5 1.1 knakahar * All rights reserved.
6 1.1 knakahar *
7 1.1 knakahar * Redistribution and use in source and binary forms, with or without
8 1.1 knakahar * modification, are permitted provided that the following conditions
9 1.1 knakahar * are met:
10 1.1 knakahar * 1. Redistributions of source code must retain the above copyright
11 1.1 knakahar * notice, this list of conditions and the following disclaimer.
12 1.1 knakahar * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 knakahar * notice, this list of conditions and the following disclaimer in the
14 1.1 knakahar * documentation and/or other materials provided with the distribution.
15 1.1 knakahar *
16 1.1 knakahar * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 1.1 knakahar * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 1.1 knakahar * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 1.1 knakahar * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 1.1 knakahar * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 1.1 knakahar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 1.1 knakahar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 1.1 knakahar * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 1.1 knakahar * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 1.1 knakahar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 1.1 knakahar * POSSIBILITY OF SUCH DAMAGE.
27 1.1 knakahar */
28 1.1 knakahar
29 1.1 knakahar #include <sys/cdefs.h>
30 1.3 knakahar __KERNEL_RCSID(0, "$NetBSD: rss_config.c,v 1.3 2021/09/24 04:11:02 knakahara Exp $");
31 1.1 knakahar
32 1.1 knakahar #include <sys/param.h>
33 1.1 knakahar #include <sys/systm.h>
34 1.1 knakahar #include <sys/kernel.h>
35 1.3 knakahar #include <sys/mbuf.h>
36 1.1 knakahar
37 1.1 knakahar #include <net/rss_config.h>
38 1.3 knakahar #include <net/toeplitz.h>
39 1.3 knakahar
40 1.3 knakahar #include <netinet/in.h>
41 1.3 knakahar #include <netinet/ip.h>
42 1.3 knakahar #include <netinet/tcp.h>
43 1.3 knakahar #include <netinet/udp.h>
44 1.3 knakahar #include <netinet/ip6.h>
45 1.1 knakahar
46 1.1 knakahar /*
47 1.1 knakahar * Same as FreeBSD.
48 1.1 knakahar *
49 1.1 knakahar * This rss key is assumed for verification suite in many intel Gigabit and
50 1.1 knakahar * 10 Gigabit Controller specifications.
51 1.1 knakahar */
52 1.1 knakahar static uint8_t rss_default_key[RSS_KEYSIZE] = {
53 1.1 knakahar 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
54 1.1 knakahar 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
55 1.1 knakahar 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
56 1.1 knakahar 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
57 1.1 knakahar 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,
58 1.1 knakahar };
59 1.1 knakahar
60 1.1 knakahar #ifdef NOTYET
61 1.1 knakahar /*
62 1.1 knakahar * Same as DragonFlyBSD.
63 1.1 knakahar *
64 1.1 knakahar * This rss key make rss hash value symmetric, that is, the hash value
65 1.1 knakahar * calculated by func("source address", "destination address") equals to
66 1.1 knakahar * the hash value calculated by func("destination address", "source address").
67 1.1 knakahar */
68 1.1 knakahar static uint8_t rss_symmetric_key[RSS_KEYSIZE] = {
69 1.1 knakahar 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
70 1.1 knakahar 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
71 1.1 knakahar 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
72 1.1 knakahar 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
73 1.2 knakahar 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
74 1.1 knakahar };
75 1.1 knakahar #endif
76 1.1 knakahar
77 1.1 knakahar /*
78 1.1 knakahar * sizeof(key) must be more than or equal to RSS_KEYSIZE.
79 1.1 knakahar */
80 1.1 knakahar void
81 1.1 knakahar rss_getkey(uint8_t *key)
82 1.1 knakahar {
83 1.1 knakahar
84 1.1 knakahar memcpy(key, rss_default_key, sizeof(rss_default_key));
85 1.1 knakahar }
86 1.3 knakahar
87 1.3 knakahar /*
88 1.3 knakahar * Calculate rss hash value from IPv4 mbuf.
89 1.3 knakahar * This function should be called before ip_input().
90 1.3 knakahar */
91 1.3 knakahar uint32_t
92 1.3 knakahar rss_toeplitz_hash_from_mbuf_ipv4(const struct mbuf *m, u_int flag)
93 1.3 knakahar {
94 1.3 knakahar struct ip *ip;
95 1.3 knakahar int hlen;
96 1.3 knakahar uint8_t key[RSS_KEYSIZE];
97 1.3 knakahar
98 1.3 knakahar KASSERT((m->m_flags & M_PKTHDR) != 0);
99 1.3 knakahar KASSERT(m->m_len >= sizeof (struct ip));
100 1.3 knakahar
101 1.3 knakahar ip = mtod(m, struct ip *);
102 1.3 knakahar KASSERT(ip->ip_v == IPVERSION);
103 1.3 knakahar
104 1.3 knakahar hlen = ip->ip_hl << 2;
105 1.3 knakahar if (hlen < sizeof(struct ip))
106 1.3 knakahar return 0;
107 1.3 knakahar
108 1.3 knakahar rss_getkey(key);
109 1.3 knakahar
110 1.3 knakahar switch (ip->ip_p) {
111 1.3 knakahar case IPPROTO_TCP:
112 1.3 knakahar {
113 1.3 knakahar if ((flag & RSS_TOEPLITZ_USE_TCP_PORT) != 0) {
114 1.3 knakahar if (m->m_len >= hlen + sizeof(struct tcphdr)) {
115 1.3 knakahar struct tcphdr *th;
116 1.3 knakahar
117 1.3 knakahar th = (struct tcphdr *)(mtod(m, char *) + hlen);
118 1.3 knakahar return toeplitz_vhash(key, sizeof(key),
119 1.3 knakahar /* ip_src and ip_dst in struct ip must be sequential */
120 1.3 knakahar &ip->ip_src, sizeof(ip->ip_src) * 2,
121 1.3 knakahar /* th_sport and th_dport in tcphdr must be sequential */
122 1.3 knakahar &th->th_sport, sizeof(th->th_sport) * 2,
123 1.3 knakahar NULL);
124 1.3 knakahar } else if (m->m_pkthdr.len >= hlen + sizeof(struct tcphdr)) {
125 1.3 knakahar uint16_t ports[2];
126 1.3 knakahar
127 1.3 knakahar /* ditto */
128 1.3 knakahar m_copydata(__UNCONST(m), hlen + offsetof(struct tcphdr, th_sport),
129 1.3 knakahar sizeof(ports), ports);
130 1.3 knakahar return toeplitz_vhash(key, sizeof(key),
131 1.3 knakahar &ip->ip_src, sizeof(ip->ip_src) * 2,
132 1.3 knakahar ports, sizeof(ports),
133 1.3 knakahar NULL);
134 1.3 knakahar }
135 1.3 knakahar }
136 1.3 knakahar /*
137 1.3 knakahar * Treat as raw packet.
138 1.3 knakahar */
139 1.3 knakahar return toeplitz_vhash(key, sizeof(key),
140 1.3 knakahar /* ditto */
141 1.3 knakahar &ip->ip_src, sizeof(ip->ip_src) * 2,
142 1.3 knakahar NULL);
143 1.3 knakahar }
144 1.3 knakahar case IPPROTO_UDP:
145 1.3 knakahar {
146 1.3 knakahar if ((flag & RSS_TOEPLITZ_USE_UDP_PORT) != 0) {
147 1.3 knakahar if (m->m_len >= hlen + sizeof(struct udphdr)) {
148 1.3 knakahar struct udphdr *uh;
149 1.3 knakahar
150 1.3 knakahar uh = (struct udphdr *)(mtod(m, char *) + hlen);
151 1.3 knakahar return toeplitz_vhash(key, sizeof(key),
152 1.3 knakahar /* ip_src and ip_dst in struct ip must sequential */
153 1.3 knakahar &ip->ip_src, sizeof(ip->ip_src) * 2,
154 1.3 knakahar /* uh_sport and uh_dport in udphdr must be sequential */
155 1.3 knakahar &uh->uh_sport, sizeof(uh->uh_sport) * 2,
156 1.3 knakahar NULL);
157 1.3 knakahar } else if (m->m_pkthdr.len >= hlen + sizeof(struct udphdr)) {
158 1.3 knakahar uint16_t ports[2];
159 1.3 knakahar
160 1.3 knakahar /* ditto */
161 1.3 knakahar m_copydata(__UNCONST(m), hlen + offsetof(struct udphdr, uh_sport),
162 1.3 knakahar sizeof(ports), ports);
163 1.3 knakahar return toeplitz_vhash(key, sizeof(key),
164 1.3 knakahar &ip->ip_src, sizeof(ip->ip_src) * 2,
165 1.3 knakahar ports, sizeof(ports),
166 1.3 knakahar NULL);
167 1.3 knakahar }
168 1.3 knakahar }
169 1.3 knakahar /*
170 1.3 knakahar * Treat as raw packet.
171 1.3 knakahar */
172 1.3 knakahar return toeplitz_vhash(key, sizeof(key),
173 1.3 knakahar /* ditto */
174 1.3 knakahar &ip->ip_src, sizeof(ip->ip_src) * 2,
175 1.3 knakahar NULL);
176 1.3 knakahar }
177 1.3 knakahar /*
178 1.3 knakahar * Other protocols are treated as raw packets to apply RPS.
179 1.3 knakahar */
180 1.3 knakahar default:
181 1.3 knakahar return toeplitz_vhash(key, sizeof(key),
182 1.3 knakahar /* ditto */
183 1.3 knakahar &ip->ip_src, sizeof(ip->ip_src) * 2,
184 1.3 knakahar NULL);
185 1.3 knakahar }
186 1.3 knakahar }
187 1.3 knakahar
188 1.3 knakahar /*
189 1.3 knakahar * Calculate rss hash value from IPv6 mbuf.
190 1.3 knakahar * This function should be called before ip6_input().
191 1.3 knakahar */
192 1.3 knakahar uint32_t
193 1.3 knakahar rss_toeplitz_hash_from_mbuf_ipv6(const struct mbuf *m, u_int flag)
194 1.3 knakahar {
195 1.3 knakahar struct ip6_hdr *ip6;
196 1.3 knakahar int hlen;
197 1.3 knakahar uint8_t key[RSS_KEYSIZE];
198 1.3 knakahar
199 1.3 knakahar KASSERT((m->m_flags & M_PKTHDR) != 0);
200 1.3 knakahar KASSERT(m->m_len >= sizeof (struct ip6_hdr));
201 1.3 knakahar
202 1.3 knakahar ip6 = mtod(m, struct ip6_hdr *);
203 1.3 knakahar KASSERT((ip6->ip6_vfc & IPV6_VERSION_MASK) == IPV6_VERSION);
204 1.3 knakahar
205 1.3 knakahar hlen = sizeof(struct ip6_hdr);
206 1.3 knakahar rss_getkey(key);
207 1.3 knakahar
208 1.3 knakahar switch (ip6->ip6_nxt) {
209 1.3 knakahar case IPPROTO_TCP:
210 1.3 knakahar {
211 1.3 knakahar if ((flag & RSS_TOEPLITZ_USE_TCP_PORT) != 0) {
212 1.3 knakahar if (m->m_len >= hlen + sizeof(struct tcphdr)) {
213 1.3 knakahar struct tcphdr *th;
214 1.3 knakahar
215 1.3 knakahar th = (struct tcphdr *)(mtod(m, char *) + hlen);
216 1.3 knakahar return toeplitz_vhash(key, sizeof(key),
217 1.3 knakahar /* ip6_src and ip6_dst in ip6_hdr must be sequential */
218 1.3 knakahar &ip6->ip6_src, sizeof(ip6->ip6_src) * 2,
219 1.3 knakahar /* th_sport and th_dport in tcphdr must be sequential */
220 1.3 knakahar &th->th_sport, sizeof(th->th_sport) * 2,
221 1.3 knakahar NULL);
222 1.3 knakahar } else if (m->m_pkthdr.len >= hlen + sizeof(struct tcphdr)) {
223 1.3 knakahar uint16_t ports[2];
224 1.3 knakahar
225 1.3 knakahar /* ditto */
226 1.3 knakahar m_copydata(__UNCONST(m), hlen + offsetof(struct tcphdr, th_sport),
227 1.3 knakahar sizeof(ports), ports);
228 1.3 knakahar return toeplitz_vhash(key, sizeof(key),
229 1.3 knakahar &ip6->ip6_src, sizeof(ip6->ip6_src) * 2,
230 1.3 knakahar ports, sizeof(ports),
231 1.3 knakahar NULL);
232 1.3 knakahar }
233 1.3 knakahar }
234 1.3 knakahar /*
235 1.3 knakahar * Treat as raw packet.
236 1.3 knakahar */
237 1.3 knakahar return toeplitz_vhash(key, sizeof(key),
238 1.3 knakahar &ip6->ip6_src, sizeof(ip6->ip6_src) * 2,
239 1.3 knakahar NULL);
240 1.3 knakahar }
241 1.3 knakahar case IPPROTO_UDP:
242 1.3 knakahar {
243 1.3 knakahar if ((flag & RSS_TOEPLITZ_USE_UDP_PORT) != 0) {
244 1.3 knakahar if (m->m_len >= hlen + sizeof(struct udphdr)) {
245 1.3 knakahar struct udphdr *uh;
246 1.3 knakahar
247 1.3 knakahar uh = (struct udphdr *)(mtod(m, char *) + hlen);
248 1.3 knakahar return toeplitz_vhash(key, sizeof(key),
249 1.3 knakahar /* ip6_src and ip6_dst in ip6_hdr must sequential */
250 1.3 knakahar &ip6->ip6_src, sizeof(ip6->ip6_src) * 2,
251 1.3 knakahar /* uh_sport and uh_dport in udphdr must be sequential */
252 1.3 knakahar &uh->uh_sport, sizeof(uh->uh_sport) * 2,
253 1.3 knakahar NULL);
254 1.3 knakahar } else if (m->m_pkthdr.len >= hlen + sizeof(struct udphdr)) {
255 1.3 knakahar uint16_t ports[2];
256 1.3 knakahar
257 1.3 knakahar /* ditto */
258 1.3 knakahar m_copydata(__UNCONST(m), hlen + offsetof(struct udphdr, uh_sport),
259 1.3 knakahar sizeof(ports), ports);
260 1.3 knakahar return toeplitz_vhash(key, sizeof(key),
261 1.3 knakahar &ip6->ip6_src, sizeof(ip6->ip6_src) * 2,
262 1.3 knakahar &ports, sizeof(ports),
263 1.3 knakahar NULL);
264 1.3 knakahar }
265 1.3 knakahar }
266 1.3 knakahar /*
267 1.3 knakahar * Treat as raw packet.
268 1.3 knakahar */
269 1.3 knakahar return toeplitz_vhash(key, sizeof(key),
270 1.3 knakahar &ip6->ip6_src, sizeof(ip6->ip6_src) * 2,
271 1.3 knakahar NULL);
272 1.3 knakahar }
273 1.3 knakahar /*
274 1.3 knakahar * Other protocols are treated as raw packets to apply RPS.
275 1.3 knakahar */
276 1.3 knakahar default:
277 1.3 knakahar return toeplitz_vhash(key, sizeof(key),
278 1.3 knakahar &ip6->ip6_src, sizeof(ip6->ip6_src) * 2,
279 1.3 knakahar NULL);
280 1.3 knakahar }
281 1.3 knakahar
282 1.3 knakahar return 0;
283 1.3 knakahar }
284