]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/netinet/in_rss.c
Import libc++ trunk r224926. This fixes a number of bugs, completes
[FreeBSD/FreeBSD.git] / sys / netinet / in_rss.c
1 /*-
2  * Copyright (c) 2010-2011 Juniper Networks, Inc.
3  * All rights reserved.
4  *
5  * This software was developed by Robert N. M. Watson under contract
6  * to Juniper Networks, Inc.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <sys/cdefs.h>
31
32 __FBSDID("$FreeBSD$");
33
34 #include "opt_inet6.h"
35 #include "opt_pcbgroup.h"
36
37 #ifndef PCBGROUP
38 #error "options RSS depends on options PCBGROUP"
39 #endif
40
41 #include <sys/param.h>
42 #include <sys/mbuf.h>
43 #include <sys/socket.h>
44 #include <sys/priv.h>
45 #include <sys/kernel.h>
46 #include <sys/smp.h>
47 #include <sys/sysctl.h>
48 #include <sys/sbuf.h>
49
50 #include <net/if.h>
51 #include <net/if_var.h>
52 #include <net/netisr.h>
53
54 #include <netinet/in.h>
55 #include <netinet/in_pcb.h>
56 #include <netinet/in_rss.h>
57 #include <netinet/in_var.h>
58 #include <netinet/toeplitz.h>
59
60 /* for software rss hash support */
61 #include <netinet/ip.h>
62 #include <netinet/tcp.h>
63 #include <netinet/udp.h>
64
65 /*-
66  * Operating system parts of receiver-side scaling (RSS), which allows
67  * network cards to direct flows to particular receive queues based on hashes
68  * of header tuples.  This implementation aligns RSS buckets with connection
69  * groups at the TCP/IP layer, so each bucket is associated with exactly one
70  * group.  As a result, the group lookup structures (and lock) should have an
71  * effective affinity with exactly one CPU.
72  *
73  * Network device drivers needing to configure RSS will query this framework
74  * for parameters, such as the current RSS key, hashing policies, number of
75  * bits, and indirection table mapping hashes to buckets and CPUs.  They may
76  * provide their own supplementary information, such as queue<->CPU bindings.
77  * It is the responsibility of the network device driver to inject packets
78  * into the stack on as close to the right CPU as possible, if playing by RSS
79  * rules.
80  *
81  * TODO:
82  *
83  * - Synchronization for rss_key and other future-configurable parameters.
84  * - Event handler drivers can register to pick up RSS configuration changes.
85  * - Should we allow rss_basecpu to be configured?
86  * - Randomize key on boot.
87  * - IPv6 support.
88  * - Statistics on how often there's a misalignment between hardware
89  *   placement and pcbgroup expectations.
90  */
91
92 SYSCTL_NODE(_net_inet, OID_AUTO, rss, CTLFLAG_RW, 0, "Receive-side steering");
93
94 /*
95  * Toeplitz is the only required hash function in the RSS spec, so use it by
96  * default.
97  */
98 static u_int    rss_hashalgo = RSS_HASH_TOEPLITZ;
99 SYSCTL_INT(_net_inet_rss, OID_AUTO, hashalgo, CTLFLAG_RDTUN, &rss_hashalgo, 0,
100     "RSS hash algorithm");
101
102 /*
103  * Size of the indirection table; at most 128 entries per the RSS spec.  We
104  * size it to at least 2 times the number of CPUs by default to allow useful
105  * rebalancing.  If not set explicitly with a loader tunable, we tune based
106  * on the number of CPUs present.
107  *
108  * XXXRW: buckets might be better to use for the tunable than bits.
109  */
110 static u_int    rss_bits;
111 SYSCTL_INT(_net_inet_rss, OID_AUTO, bits, CTLFLAG_RDTUN, &rss_bits, 0,
112     "RSS bits");
113
114 static u_int    rss_mask;
115 SYSCTL_INT(_net_inet_rss, OID_AUTO, mask, CTLFLAG_RD, &rss_mask, 0,
116     "RSS mask");
117
118 static const u_int      rss_maxbits = RSS_MAXBITS;
119 SYSCTL_INT(_net_inet_rss, OID_AUTO, maxbits, CTLFLAG_RD,
120     __DECONST(int *, &rss_maxbits), 0, "RSS maximum bits");
121
122 /*
123  * RSS's own count of the number of CPUs it could be using for processing.
124  * Bounded to 64 by RSS constants.
125  */
126 static u_int    rss_ncpus;
127 SYSCTL_INT(_net_inet_rss, OID_AUTO, ncpus, CTLFLAG_RD, &rss_ncpus, 0,
128     "Number of CPUs available to RSS");
129
130 #define RSS_MAXCPUS     (1 << (RSS_MAXBITS - 1))
131 static const u_int      rss_maxcpus = RSS_MAXCPUS;
132 SYSCTL_INT(_net_inet_rss, OID_AUTO, maxcpus, CTLFLAG_RD,
133     __DECONST(int *, &rss_maxcpus), 0, "RSS maximum CPUs that can be used");
134
135 /*
136  * Variable exists just for reporting rss_bits in a user-friendly way.
137  */
138 static u_int    rss_buckets;
139 SYSCTL_INT(_net_inet_rss, OID_AUTO, buckets, CTLFLAG_RD, &rss_buckets, 0,
140     "RSS buckets");
141
142 /*
143  * Base CPU number; devices will add this to all CPU numbers returned by the
144  * RSS indirection table.  Currently unmodifable in FreeBSD.
145  */
146 static const u_int      rss_basecpu;
147 SYSCTL_INT(_net_inet_rss, OID_AUTO, basecpu, CTLFLAG_RD,
148     __DECONST(int *, &rss_basecpu), 0, "RSS base CPU");
149
150 /*
151  * RSS secret key, intended to prevent attacks on load-balancing.  Its
152  * effectiveness may be limited by algorithm choice and available entropy
153  * during the boot.
154  *
155  * XXXRW: And that we don't randomize it yet!
156  *
157  * This is the default Microsoft RSS specification key which is also
158  * the Chelsio T5 firmware default key.
159  */
160 static uint8_t rss_key[RSS_KEYSIZE] = {
161         0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
162         0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
163         0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
164         0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
165         0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,
166 };
167
168 /*
169  * RSS hash->CPU table, which maps hashed packet headers to particular CPUs.
170  * Drivers may supplement this table with a seperate CPU<->queue table when
171  * programming devices.
172  */
173 struct rss_table_entry {
174         uint8_t         rte_cpu;        /* CPU affinity of bucket. */
175 };
176 static struct rss_table_entry   rss_table[RSS_TABLE_MAXLEN];
177
178 static inline u_int rss_gethashconfig_local(void);
179
180 static void
181 rss_init(__unused void *arg)
182 {
183         u_int i;
184         u_int cpuid;
185
186         /*
187          * Validate tunables, coerce to sensible values.
188          */
189         switch (rss_hashalgo) {
190         case RSS_HASH_TOEPLITZ:
191         case RSS_HASH_NAIVE:
192                 break;
193
194         default:
195                 printf("%s: invalid RSS hashalgo %u, coercing to %u",
196                     __func__, rss_hashalgo, RSS_HASH_TOEPLITZ);
197                 rss_hashalgo = RSS_HASH_TOEPLITZ;
198         }
199
200         /*
201          * Count available CPUs.
202          *
203          * XXXRW: Note incorrect assumptions regarding contiguity of this set
204          * elsewhere.
205          */
206         rss_ncpus = 0;
207         for (i = 0; i <= mp_maxid; i++) {
208                 if (CPU_ABSENT(i))
209                         continue;
210                 rss_ncpus++;
211         }
212         if (rss_ncpus > RSS_MAXCPUS)
213                 rss_ncpus = RSS_MAXCPUS;
214
215         /*
216          * Tune RSS table entries to be no less than 2x the number of CPUs
217          * -- unless we're running uniprocessor, in which case there's not
218          * much point in having buckets to rearrange for load-balancing!
219          */
220         if (rss_ncpus > 1) {
221                 if (rss_bits == 0)
222                         rss_bits = fls(rss_ncpus - 1) + 1;
223
224                 /*
225                  * Microsoft limits RSS table entries to 128, so apply that
226                  * limit to both auto-detected CPU counts and user-configured
227                  * ones.
228                  */
229                 if (rss_bits == 0 || rss_bits > RSS_MAXBITS) {
230                         printf("%s: RSS bits %u not valid, coercing to  %u",
231                             __func__, rss_bits, RSS_MAXBITS);
232                         rss_bits = RSS_MAXBITS;
233                 }
234
235                 /*
236                  * Figure out how many buckets to use; warn if less than the
237                  * number of configured CPUs, although this is not a fatal
238                  * problem.
239                  */
240                 rss_buckets = (1 << rss_bits);
241                 if (rss_buckets < rss_ncpus)
242                         printf("%s: WARNING: rss_buckets (%u) less than "
243                             "rss_ncpus (%u)\n", __func__, rss_buckets,
244                             rss_ncpus);
245                 rss_mask = rss_buckets - 1;
246         } else {
247                 rss_bits = 0;
248                 rss_buckets = 1;
249                 rss_mask = 0;
250         }
251
252         /*
253          * Set up initial CPU assignments: round-robin by default.
254          */
255         cpuid = CPU_FIRST();
256         for (i = 0; i < rss_buckets; i++) {
257                 rss_table[i].rte_cpu = cpuid;
258                 cpuid = CPU_NEXT(cpuid);
259         }
260
261         /*
262          * Randomize rrs_key.
263          *
264          * XXXRW: Not yet.  If nothing else, will require an rss_isbadkey()
265          * loop to check for "bad" RSS keys.
266          */
267 }
268 SYSINIT(rss_init, SI_SUB_SOFTINTR, SI_ORDER_SECOND, rss_init, NULL);
269
270 static uint32_t
271 rss_naive_hash(u_int keylen, const uint8_t *key, u_int datalen,
272     const uint8_t *data)
273 {
274         uint32_t v;
275         u_int i;
276
277         v = 0;
278         for (i = 0; i < keylen; i++)
279                 v += key[i];
280         for (i = 0; i < datalen; i++)
281                 v += data[i];
282         return (v);
283 }
284
285 static uint32_t
286 rss_hash(u_int datalen, const uint8_t *data)
287 {
288  
289         switch (rss_hashalgo) {
290         case RSS_HASH_TOEPLITZ:
291                 return (toeplitz_hash(sizeof(rss_key), rss_key, datalen,
292                     data));
293
294         case RSS_HASH_NAIVE:
295                 return (rss_naive_hash(sizeof(rss_key), rss_key, datalen,
296                     data));
297
298         default:
299                 panic("%s: unsupported/unknown hashalgo %d", __func__,
300                     rss_hashalgo);
301         }
302 }
303
304 /*
305  * Hash an IPv4 2-tuple.
306  */
307 uint32_t
308 rss_hash_ip4_2tuple(struct in_addr src, struct in_addr dst)
309 {
310         uint8_t data[sizeof(src) + sizeof(dst)];
311         u_int datalen;
312
313         datalen = 0;
314         bcopy(&src, &data[datalen], sizeof(src));
315         datalen += sizeof(src);
316         bcopy(&dst, &data[datalen], sizeof(dst));
317         datalen += sizeof(dst);
318         return (rss_hash(datalen, data));
319 }
320
321 /*
322  * Hash an IPv4 4-tuple.
323  */
324 uint32_t
325 rss_hash_ip4_4tuple(struct in_addr src, u_short srcport, struct in_addr dst,
326     u_short dstport)
327 {
328         uint8_t data[sizeof(src) + sizeof(dst) + sizeof(srcport) +
329             sizeof(dstport)];
330         u_int datalen;
331
332         datalen = 0;
333         bcopy(&src, &data[datalen], sizeof(src));
334         datalen += sizeof(src);
335         bcopy(&dst, &data[datalen], sizeof(dst));
336         datalen += sizeof(dst);
337         bcopy(&srcport, &data[datalen], sizeof(srcport));
338         datalen += sizeof(srcport);
339         bcopy(&dstport, &data[datalen], sizeof(dstport));
340         datalen += sizeof(dstport);
341         return (rss_hash(datalen, data));
342 }
343
344 #ifdef INET6
345 /*
346  * Hash an IPv6 2-tuple.
347  */
348 uint32_t
349 rss_hash_ip6_2tuple(const struct in6_addr *src, const struct in6_addr *dst)
350 {
351         uint8_t data[sizeof(*src) + sizeof(*dst)];
352         u_int datalen;
353
354         datalen = 0;
355         bcopy(src, &data[datalen], sizeof(*src));
356         datalen += sizeof(*src);
357         bcopy(dst, &data[datalen], sizeof(*dst));
358         datalen += sizeof(*dst);
359         return (rss_hash(datalen, data));
360 }
361
362 /*
363  * Hash an IPv6 4-tuple.
364  */
365 uint32_t
366 rss_hash_ip6_4tuple(const struct in6_addr *src, u_short srcport,
367     const struct in6_addr *dst, u_short dstport)
368 {
369         uint8_t data[sizeof(*src) + sizeof(*dst) + sizeof(srcport) +
370             sizeof(dstport)];
371         u_int datalen;
372
373         datalen = 0;
374         bcopy(src, &data[datalen], sizeof(*src));
375         datalen += sizeof(*src);
376         bcopy(dst, &data[datalen], sizeof(*dst));
377         datalen += sizeof(*dst);
378         bcopy(&srcport, &data[datalen], sizeof(srcport));
379         datalen += sizeof(srcport);
380         bcopy(&dstport, &data[datalen], sizeof(dstport));
381         datalen += sizeof(dstport);
382         return (rss_hash(datalen, data));
383 }
384 #endif /* INET6 */
385
386 /*
387  * Query the number of RSS bits in use.
388  */
389 u_int
390 rss_getbits(void)
391 {
392
393         return (rss_bits);
394 }
395
396 /*
397  * Query the RSS bucket associated with an RSS hash.
398  */
399 u_int
400 rss_getbucket(u_int hash)
401 {
402
403         return (hash & rss_mask);
404 }
405
406 /*
407  * Query the RSS layer bucket associated with the given
408  * entry in the RSS hash space.
409  *
410  * The RSS indirection table is 0 .. rss_buckets-1,
411  * covering the low 'rss_bits' of the total 128 slot
412  * RSS indirection table.  So just mask off rss_bits and
413  * return that.
414  *
415  * NIC drivers can then iterate over the 128 slot RSS
416  * indirection table and fetch which RSS bucket to
417  * map it to.  This will typically be a CPU queue
418  */
419 u_int
420 rss_get_indirection_to_bucket(u_int index)
421 {
422
423         return (index & rss_mask);
424 }
425
426 /*
427  * Query the RSS CPU associated with an RSS bucket.
428  */
429 u_int
430 rss_getcpu(u_int bucket)
431 {
432
433         return (rss_table[bucket].rte_cpu);
434 }
435
436 /*
437  * netisr CPU affinity lookup given just the hash and hashtype.
438  */
439 u_int
440 rss_hash2cpuid(uint32_t hash_val, uint32_t hash_type)
441 {
442
443         switch (hash_type) {
444         case M_HASHTYPE_RSS_IPV4:
445         case M_HASHTYPE_RSS_TCP_IPV4:
446         case M_HASHTYPE_RSS_UDP_IPV4:
447         case M_HASHTYPE_RSS_IPV6:
448         case M_HASHTYPE_RSS_TCP_IPV6:
449         case M_HASHTYPE_RSS_UDP_IPV6:
450                 return (rss_getcpu(rss_getbucket(hash_val)));
451         default:
452                 return (NETISR_CPUID_NONE);
453         }
454 }
455
456 /*
457  * Query the RSS bucket associated with the given hash value and
458  * type.
459  */
460 int
461 rss_hash2bucket(uint32_t hash_val, uint32_t hash_type, uint32_t *bucket_id)
462 {
463
464         switch (hash_type) {
465         case M_HASHTYPE_RSS_IPV4:
466         case M_HASHTYPE_RSS_TCP_IPV4:
467         case M_HASHTYPE_RSS_UDP_IPV4:
468         case M_HASHTYPE_RSS_IPV6:
469         case M_HASHTYPE_RSS_TCP_IPV6:
470         case M_HASHTYPE_RSS_UDP_IPV6:
471                 *bucket_id = rss_getbucket(hash_val);
472                 return (0);
473         default:
474                 return (-1);
475         }
476 }
477
478 /*
479  * netisr CPU affinity lookup routine for use by protocols.
480  */
481 struct mbuf *
482 rss_m2cpuid(struct mbuf *m, uintptr_t source, u_int *cpuid)
483 {
484
485         M_ASSERTPKTHDR(m);
486         *cpuid = rss_hash2cpuid(m->m_pkthdr.flowid, M_HASHTYPE_GET(m));
487         return (m);
488 }
489
490 int
491 rss_m2bucket(struct mbuf *m, uint32_t *bucket_id)
492 {
493
494         M_ASSERTPKTHDR(m);
495
496         return(rss_hash2bucket(m->m_pkthdr.flowid, M_HASHTYPE_GET(m),
497             bucket_id));
498 }
499
500 /*
501  * Calculate an appropriate ipv4 2-tuple or 4-tuple given the given
502  * IPv4 source/destination address, UDP or TCP source/destination ports
503  * and the protocol type.
504  *
505  * The protocol code may wish to do a software hash of the given
506  * tuple.  This depends upon the currently configured RSS hash types.
507  *
508  * This assumes that the packet in question isn't a fragment.
509  *
510  * It also assumes the packet source/destination address
511  * are in "incoming" packet order (ie, source is "far" address.)
512  */
513 int
514 rss_proto_software_hash_v4(struct in_addr s, struct in_addr d,
515     u_short sp, u_short dp, int proto,
516     uint32_t *hashval, uint32_t *hashtype)
517 {
518         uint32_t hash;
519
520         /*
521          * Next, choose the hash type depending upon the protocol
522          * identifier.
523          */
524         if ((proto == IPPROTO_TCP) &&
525             (rss_gethashconfig_local() & RSS_HASHTYPE_RSS_TCP_IPV4)) {
526                 hash = rss_hash_ip4_4tuple(s, sp, d, dp);
527                 *hashval = hash;
528                 *hashtype = M_HASHTYPE_RSS_TCP_IPV4;
529                 return (0);
530         } else if ((proto == IPPROTO_UDP) &&
531             (rss_gethashconfig_local() & RSS_HASHTYPE_RSS_UDP_IPV4)) {
532                 hash = rss_hash_ip4_4tuple(s, sp, d, dp);
533                 *hashval = hash;
534                 *hashtype = M_HASHTYPE_RSS_UDP_IPV4;
535                 return (0);
536         } else if (rss_gethashconfig_local() & RSS_HASHTYPE_RSS_IPV4) {
537                 /* RSS doesn't hash on other protocols like SCTP; so 2-tuple */
538                 hash = rss_hash_ip4_2tuple(s, d);
539                 *hashval = hash;
540                 *hashtype = M_HASHTYPE_RSS_IPV4;
541                 return (0);
542         }
543
544         /* No configured available hashtypes! */
545         printf("%s: no available hashtypes!\n", __func__);
546         return (-1);
547 }
548
549 /*
550  * Do a software calculation of the RSS for the given mbuf.
551  *
552  * This is typically used by the input path to recalculate the RSS after
553  * some form of packet processing (eg de-capsulation, IP fragment reassembly.)
554  *
555  * dir is the packet direction - RSS_HASH_PKT_INGRESS for incoming and
556  * RSS_HASH_PKT_EGRESS for outgoing.
557  *
558  * Returns 0 if a hash was done, -1 if no hash was done, +1 if
559  * the mbuf already had a valid RSS flowid.
560  *
561  * This function doesn't modify the mbuf.  It's up to the caller to
562  * assign flowid/flowtype as appropriate.
563  */
564 int
565 rss_mbuf_software_hash_v4(const struct mbuf *m, int dir, uint32_t *hashval,
566     uint32_t *hashtype)
567 {
568         const struct ip *ip;
569         const struct tcphdr *th;
570         const struct udphdr *uh;
571         uint32_t flowid;
572         uint32_t flowtype;
573         uint8_t proto;
574         int iphlen;
575         int is_frag = 0;
576
577         /*
578          * XXX For now this only handles hashing on incoming mbufs.
579          */
580         if (dir != RSS_HASH_PKT_INGRESS) {
581                 printf("%s: called on EGRESS packet!\n", __func__);
582                 return (-1);
583         }
584
585         /*
586          * First, validate that the mbuf we have is long enough
587          * to have an IPv4 header in it.
588          */
589         if (m->m_pkthdr.len < (sizeof(struct ip))) {
590                 printf("%s: short mbuf pkthdr\n", __func__);
591                 return (-1);
592         }
593         if (m->m_len < (sizeof(struct ip))) {
594                 printf("%s: short mbuf len\n", __func__);
595                 return (-1);
596         }
597
598         /* Ok, let's dereference that */
599         ip = mtod(m, struct ip *);
600         proto = ip->ip_p;
601         iphlen = ip->ip_hl << 2;
602
603         /*
604          * If this is a fragment then it shouldn't be four-tuple
605          * hashed just yet.  Once it's reassembled into a full
606          * frame it should be re-hashed.
607          */
608         if (ip->ip_off & htons(IP_MF | IP_OFFMASK))
609                 is_frag = 1;
610
611         /*
612          * If the mbuf flowid/flowtype matches the packet type,
613          * and we don't support the 4-tuple version of the given protocol,
614          * then signal to the owner that it can trust the flowid/flowtype
615          * details.
616          *
617          * This is a little picky - eg, if TCPv4 / UDPv4 hashing
618          * is supported but we got a TCP/UDP frame only 2-tuple hashed,
619          * then we shouldn't just "trust" the 2-tuple hash.  We need
620          * a 4-tuple hash.
621          */
622         flowid = m->m_pkthdr.flowid;
623         flowtype = M_HASHTYPE_GET(m);
624
625         if (flowtype != M_HASHTYPE_NONE) {
626                 switch (proto) {
627                 case IPPROTO_UDP:
628                         if ((rss_gethashconfig_local() & RSS_HASHTYPE_RSS_UDP_IPV4) &&
629                             (flowtype == M_HASHTYPE_RSS_UDP_IPV4) &&
630                             (is_frag == 0)) {
631                                 return (1);
632                         }
633                         /*
634                          * Only allow 2-tuple for UDP frames if we don't also
635                          * support 4-tuple for UDP.
636                          */
637                         if ((rss_gethashconfig_local() & RSS_HASHTYPE_RSS_IPV4) &&
638                             ((rss_gethashconfig_local() & RSS_HASHTYPE_RSS_UDP_IPV4) == 0) &&
639                             flowtype == M_HASHTYPE_RSS_IPV4) {
640                                 return (1);
641                         }
642                         break;
643                 case IPPROTO_TCP:
644                         if ((rss_gethashconfig_local() & RSS_HASHTYPE_RSS_TCP_IPV4) &&
645                             (flowtype == M_HASHTYPE_RSS_TCP_IPV4) &&
646                             (is_frag == 0)) {
647                                 return (1);
648                         }
649                         /*
650                          * Only allow 2-tuple for TCP frames if we don't also
651                          * support 2-tuple for TCP.
652                          */
653                         if ((rss_gethashconfig_local() & RSS_HASHTYPE_RSS_IPV4) &&
654                             ((rss_gethashconfig_local() & RSS_HASHTYPE_RSS_TCP_IPV4) == 0) &&
655                             flowtype == M_HASHTYPE_RSS_IPV4) {
656                                 return (1);
657                         }
658                         break;
659                 default:
660                         if ((rss_gethashconfig_local() & RSS_HASHTYPE_RSS_IPV4) &&
661                             flowtype == M_HASHTYPE_RSS_IPV4) {
662                                 return (1);
663                         }
664                         break;
665                 }
666         }
667
668         /*
669          * Decode enough information to make a hash decision.
670          *
671          * XXX TODO: does the hardware hash on 4-tuple if IP
672          *    options are present?
673          */
674         if ((rss_gethashconfig_local() & RSS_HASHTYPE_RSS_TCP_IPV4) &&
675             (proto == IPPROTO_TCP) &&
676             (is_frag == 0)) {
677                 if (m->m_len < iphlen + sizeof(struct tcphdr)) {
678                         printf("%s: short TCP frame?\n", __func__);
679                         return (-1);
680                 }
681                 th = (struct tcphdr *)((caddr_t)ip + iphlen);
682                 return rss_proto_software_hash_v4(ip->ip_src, ip->ip_dst,
683                     th->th_sport,
684                     th->th_dport,
685                     proto,
686                     hashval,
687                     hashtype);
688         } else if ((rss_gethashconfig_local() & RSS_HASHTYPE_RSS_UDP_IPV4) &&
689             (proto == IPPROTO_UDP) &&
690             (is_frag == 0)) {
691                 uh = (struct udphdr *)((caddr_t)ip + iphlen);
692                 if (m->m_len < iphlen + sizeof(struct udphdr)) {
693                         printf("%s: short UDP frame?\n", __func__);
694                         return (-1);
695                 }
696                 return rss_proto_software_hash_v4(ip->ip_src, ip->ip_dst,
697                     uh->uh_sport,
698                     uh->uh_dport,
699                     proto,
700                     hashval,
701                     hashtype);
702         } else if (rss_gethashconfig_local() & RSS_HASHTYPE_RSS_IPV4) {
703                 /* Default to 2-tuple hash */
704                 return rss_proto_software_hash_v4(ip->ip_src, ip->ip_dst,
705                     0,  /* source port */
706                     0,  /* destination port */
707                     0,  /* IPPROTO_IP */
708                     hashval,
709                     hashtype);
710         } else {
711                 printf("%s: no available hashtypes!\n", __func__);
712                 return (-1);
713         }
714 }
715
716 /*
717  * Similar to rss_m2cpuid, but designed to be used by the IP NETISR
718  * on incoming frames.
719  *
720  * If an existing RSS hash exists and it matches what the configured
721  * hashing is, then use it.
722  *
723  * If there's an existing RSS hash but the desired hash is different,
724  * or if there's no useful RSS hash, then calculate it via
725  * the software path.
726  *
727  * XXX TODO: definitely want statistics here!
728  */
729 struct mbuf *
730 rss_soft_m2cpuid(struct mbuf *m, uintptr_t source, u_int *cpuid)
731 {
732         uint32_t hash_val, hash_type;
733         int ret;
734
735         M_ASSERTPKTHDR(m);
736
737         ret = rss_mbuf_software_hash_v4(m, RSS_HASH_PKT_INGRESS,
738             &hash_val, &hash_type);
739         if (ret > 0) {
740                 /* mbuf has a valid hash already; don't need to modify it */
741                 *cpuid = rss_hash2cpuid(m->m_pkthdr.flowid, M_HASHTYPE_GET(m));
742         } else if (ret == 0) {
743                 /* hash was done; update */
744                 m->m_pkthdr.flowid = hash_val;
745                 M_HASHTYPE_SET(m, hash_type);
746                 *cpuid = rss_hash2cpuid(m->m_pkthdr.flowid, M_HASHTYPE_GET(m));
747         } else { /* ret < 0 */
748                 /* no hash was done */
749                 *cpuid = NETISR_CPUID_NONE;
750         }
751         return (m);
752 }
753
754 /*
755  * Query the RSS hash algorithm.
756  */
757 u_int
758 rss_gethashalgo(void)
759 {
760
761         return (rss_hashalgo);
762 }
763
764 /*
765  * Query the current RSS key; likely to be used by device drivers when
766  * configuring hardware RSS.  Caller must pass an array of size RSS_KEYSIZE.
767  *
768  * XXXRW: Perhaps we should do the accept-a-length-and-truncate thing?
769  */
770 void
771 rss_getkey(uint8_t *key)
772 {
773
774         bcopy(rss_key, key, sizeof(rss_key));
775 }
776
777 /*
778  * Query the number of buckets; this may be used by both network device
779  * drivers, which will need to populate hardware shadows of the software
780  * indirection table, and the network stack itself (such as when deciding how
781  * many connection groups to allocate).
782  */
783 u_int
784 rss_getnumbuckets(void)
785 {
786
787         return (rss_buckets);
788 }
789
790 /*
791  * Query the number of CPUs in use by RSS; may be useful to device drivers
792  * trying to figure out how to map a larger number of CPUs into a smaller
793  * number of receive queues.
794  */
795 u_int
796 rss_getnumcpus(void)
797 {
798
799         return (rss_ncpus);
800 }
801
802 static inline u_int
803 rss_gethashconfig_local(void)
804 {
805
806         /* Return 4-tuple for TCP; 2-tuple for others */
807         /*
808          * UDP may fragment more often than TCP and thus we'll end up with
809          * NICs returning 2-tuple fragments.
810          * udp_init() and udplite_init() both currently initialise things
811          * as 2-tuple.
812          * So for now disable UDP 4-tuple hashing until all of the other
813          * pieces are in place.
814          */
815         return (
816             RSS_HASHTYPE_RSS_IPV4
817         |    RSS_HASHTYPE_RSS_TCP_IPV4
818         |    RSS_HASHTYPE_RSS_IPV6
819         |    RSS_HASHTYPE_RSS_TCP_IPV6
820         |    RSS_HASHTYPE_RSS_IPV6_EX
821         |    RSS_HASHTYPE_RSS_TCP_IPV6_EX
822 #if 0
823         |    RSS_HASHTYPE_RSS_UDP_IPV4
824         |    RSS_HASHTYPE_RSS_UDP_IPV4_EX
825         |    RSS_HASHTYPE_RSS_UDP_IPV6
826         |    RSS_HASHTYPE_RSS_UDP_IPV6_EX
827 #endif
828         );
829 }
830
831 /*
832  * Return the supported RSS hash configuration.
833  *
834  * NICs should query this to determine what to configure in their redirection
835  * matching table.
836  */
837 u_int
838 rss_gethashconfig(void)
839 {
840
841         return (rss_gethashconfig_local());
842 }
843
844 /*
845  * XXXRW: Confirm that sysctl -a won't dump this keying material, don't want
846  * it appearing in debugging output unnecessarily.
847  */
848 static int
849 sysctl_rss_key(SYSCTL_HANDLER_ARGS)
850 {
851         uint8_t temp_rss_key[RSS_KEYSIZE];
852         int error;
853
854         error = priv_check(req->td, PRIV_NETINET_HASHKEY);
855         if (error)
856                 return (error);
857
858         bcopy(rss_key, temp_rss_key, sizeof(temp_rss_key));
859         error = sysctl_handle_opaque(oidp, temp_rss_key,
860             sizeof(temp_rss_key), req);
861         if (error)
862                 return (error);
863         if (req->newptr != NULL) {
864                 /* XXXRW: Not yet. */
865                 return (EINVAL);
866         }
867         return (0);
868 }
869 SYSCTL_PROC(_net_inet_rss, OID_AUTO, key,
870     CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0, sysctl_rss_key,
871     "", "RSS keying material");
872
873 static int
874 sysctl_rss_bucket_mapping(SYSCTL_HANDLER_ARGS)
875 {
876         struct sbuf *sb;
877         int error;
878         int i;
879
880         error = 0;
881         error = sysctl_wire_old_buffer(req, 0);
882         if (error != 0)
883                 return (error);
884         sb = sbuf_new_for_sysctl(NULL, NULL, 512, req);
885         if (sb == NULL)
886                 return (ENOMEM);
887         for (i = 0; i < rss_buckets; i++) {
888                 sbuf_printf(sb, "%s%d:%d", i == 0 ? "" : " ",
889                     i,
890                     rss_getcpu(i));
891         }
892         error = sbuf_finish(sb);
893         sbuf_delete(sb);
894
895         return (error);
896 }
897 SYSCTL_PROC(_net_inet_rss, OID_AUTO, bucket_mapping,
898     CTLTYPE_STRING | CTLFLAG_RD, NULL, 0,
899     sysctl_rss_bucket_mapping, "", "RSS bucket -> CPU mapping");