1b2bdc62aSAdrian Chadd /*- 2b2bdc62aSAdrian Chadd * Copyright (c) 2010-2011 Juniper Networks, Inc. 3b2bdc62aSAdrian Chadd * All rights reserved. 4b2bdc62aSAdrian Chadd * 5b2bdc62aSAdrian Chadd * This software was developed by Robert N. M. Watson under contract 6b2bdc62aSAdrian Chadd * to Juniper Networks, Inc. 7b2bdc62aSAdrian Chadd * 8b2bdc62aSAdrian Chadd * Redistribution and use in source and binary forms, with or without 9b2bdc62aSAdrian Chadd * modification, are permitted provided that the following conditions 10b2bdc62aSAdrian Chadd * are met: 11b2bdc62aSAdrian Chadd * 1. Redistributions of source code must retain the above copyright 12b2bdc62aSAdrian Chadd * notice, this list of conditions and the following disclaimer. 13b2bdc62aSAdrian Chadd * 2. Redistributions in binary form must reproduce the above copyright 14b2bdc62aSAdrian Chadd * notice, this list of conditions and the following disclaimer in the 15b2bdc62aSAdrian Chadd * documentation and/or other materials provided with the distribution. 16b2bdc62aSAdrian Chadd * 17b2bdc62aSAdrian Chadd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18b2bdc62aSAdrian Chadd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19b2bdc62aSAdrian Chadd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20b2bdc62aSAdrian Chadd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21b2bdc62aSAdrian Chadd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22b2bdc62aSAdrian Chadd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23b2bdc62aSAdrian Chadd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24b2bdc62aSAdrian Chadd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25b2bdc62aSAdrian Chadd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26b2bdc62aSAdrian Chadd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27b2bdc62aSAdrian Chadd * SUCH DAMAGE. 28b2bdc62aSAdrian Chadd */ 29b2bdc62aSAdrian Chadd 30b2bdc62aSAdrian Chadd #include <sys/cdefs.h> 31b2bdc62aSAdrian Chadd 32b2bdc62aSAdrian Chadd __FBSDID("$FreeBSD$"); 33b2bdc62aSAdrian Chadd 34b2bdc62aSAdrian Chadd #include "opt_inet6.h" 35b2bdc62aSAdrian Chadd #include "opt_pcbgroup.h" 36b2bdc62aSAdrian Chadd 37b2bdc62aSAdrian Chadd #ifndef PCBGROUP 38b2bdc62aSAdrian Chadd #error "options RSS depends on options PCBGROUP" 39b2bdc62aSAdrian Chadd #endif 40b2bdc62aSAdrian Chadd 41b2bdc62aSAdrian Chadd #include <sys/param.h> 42b2bdc62aSAdrian Chadd #include <sys/mbuf.h> 43b2bdc62aSAdrian Chadd #include <sys/socket.h> 44b2bdc62aSAdrian Chadd #include <sys/priv.h> 45b2bdc62aSAdrian Chadd #include <sys/kernel.h> 46b2bdc62aSAdrian Chadd #include <sys/smp.h> 47b2bdc62aSAdrian Chadd #include <sys/sysctl.h> 48b2bdc62aSAdrian Chadd #include <sys/sbuf.h> 49b2bdc62aSAdrian Chadd 50b2bdc62aSAdrian Chadd #include <net/if.h> 51b2bdc62aSAdrian Chadd #include <net/if_var.h> 52b2bdc62aSAdrian Chadd #include <net/netisr.h> 53b2bdc62aSAdrian Chadd #include <net/rss_config.h> 54b2bdc62aSAdrian Chadd 55b2bdc62aSAdrian Chadd #include <netinet/in.h> 56b2bdc62aSAdrian Chadd #include <netinet/in_pcb.h> 57b2bdc62aSAdrian Chadd #include <netinet6/in6_rss.h> 58b2bdc62aSAdrian Chadd #include <netinet/in_var.h> 59b2bdc62aSAdrian Chadd 60b2bdc62aSAdrian Chadd /* for software rss hash support */ 61b2bdc62aSAdrian Chadd #include <netinet/ip.h> 62b2bdc62aSAdrian Chadd #include <netinet/tcp.h> 63b2bdc62aSAdrian Chadd #include <netinet/udp.h> 64b2bdc62aSAdrian Chadd 65b2bdc62aSAdrian Chadd /* 66b2bdc62aSAdrian Chadd * Hash an IPv6 2-tuple. 67b2bdc62aSAdrian Chadd */ 68b2bdc62aSAdrian Chadd uint32_t 69b2bdc62aSAdrian Chadd rss_hash_ip6_2tuple(const struct in6_addr *src, const struct in6_addr *dst) 70b2bdc62aSAdrian Chadd { 71b2bdc62aSAdrian Chadd uint8_t data[sizeof(*src) + sizeof(*dst)]; 72b2bdc62aSAdrian Chadd u_int datalen; 73b2bdc62aSAdrian Chadd 74b2bdc62aSAdrian Chadd datalen = 0; 75b2bdc62aSAdrian Chadd bcopy(src, &data[datalen], sizeof(*src)); 76b2bdc62aSAdrian Chadd datalen += sizeof(*src); 77b2bdc62aSAdrian Chadd bcopy(dst, &data[datalen], sizeof(*dst)); 78b2bdc62aSAdrian Chadd datalen += sizeof(*dst); 79b2bdc62aSAdrian Chadd return (rss_hash(datalen, data)); 80b2bdc62aSAdrian Chadd } 81b2bdc62aSAdrian Chadd 82b2bdc62aSAdrian Chadd /* 83b2bdc62aSAdrian Chadd * Hash an IPv6 4-tuple. 84b2bdc62aSAdrian Chadd */ 85b2bdc62aSAdrian Chadd uint32_t 86b2bdc62aSAdrian Chadd rss_hash_ip6_4tuple(const struct in6_addr *src, u_short srcport, 87b2bdc62aSAdrian Chadd const struct in6_addr *dst, u_short dstport) 88b2bdc62aSAdrian Chadd { 89b2bdc62aSAdrian Chadd uint8_t data[sizeof(*src) + sizeof(*dst) + sizeof(srcport) + 90b2bdc62aSAdrian Chadd sizeof(dstport)]; 91b2bdc62aSAdrian Chadd u_int datalen; 92b2bdc62aSAdrian Chadd 93b2bdc62aSAdrian Chadd datalen = 0; 94b2bdc62aSAdrian Chadd bcopy(src, &data[datalen], sizeof(*src)); 95b2bdc62aSAdrian Chadd datalen += sizeof(*src); 96b2bdc62aSAdrian Chadd bcopy(dst, &data[datalen], sizeof(*dst)); 97b2bdc62aSAdrian Chadd datalen += sizeof(*dst); 98b2bdc62aSAdrian Chadd bcopy(&srcport, &data[datalen], sizeof(srcport)); 99b2bdc62aSAdrian Chadd datalen += sizeof(srcport); 100b2bdc62aSAdrian Chadd bcopy(&dstport, &data[datalen], sizeof(dstport)); 101b2bdc62aSAdrian Chadd datalen += sizeof(dstport); 102b2bdc62aSAdrian Chadd return (rss_hash(datalen, data)); 103b2bdc62aSAdrian Chadd } 10420dbdf88SAdrian Chadd 10520dbdf88SAdrian Chadd /* 10620dbdf88SAdrian Chadd * Calculate an appropriate ipv6 2-tuple or 4-tuple given the given 10720dbdf88SAdrian Chadd * IPv6 source/destination address, UDP or TCP source/destination ports 10820dbdf88SAdrian Chadd * and the protocol type. 10920dbdf88SAdrian Chadd * 11020dbdf88SAdrian Chadd * The protocol code may wish to do a software hash of the given 11120dbdf88SAdrian Chadd * tuple. This depends upon the currently configured RSS hash types. 11220dbdf88SAdrian Chadd * 11320dbdf88SAdrian Chadd * This assumes that the packet in question isn't a fragment. 11420dbdf88SAdrian Chadd * 11520dbdf88SAdrian Chadd * It also assumes the packet source/destination address 11620dbdf88SAdrian Chadd * are in "incoming" packet order (ie, source is "far" address.) 11720dbdf88SAdrian Chadd */ 11820dbdf88SAdrian Chadd int 11920dbdf88SAdrian Chadd rss_proto_software_hash_v6(const struct in6_addr *s, const struct in6_addr *d, 12020dbdf88SAdrian Chadd u_short sp, u_short dp, int proto, 12120dbdf88SAdrian Chadd uint32_t *hashval, uint32_t *hashtype) 12220dbdf88SAdrian Chadd { 12320dbdf88SAdrian Chadd uint32_t hash; 12420dbdf88SAdrian Chadd 12520dbdf88SAdrian Chadd /* 12620dbdf88SAdrian Chadd * Next, choose the hash type depending upon the protocol 12720dbdf88SAdrian Chadd * identifier. 12820dbdf88SAdrian Chadd */ 12920dbdf88SAdrian Chadd if ((proto == IPPROTO_TCP) && 13020dbdf88SAdrian Chadd (rss_gethashconfig() & RSS_HASHTYPE_RSS_TCP_IPV6)) { 13120dbdf88SAdrian Chadd hash = rss_hash_ip6_4tuple(s, sp, d, dp); 13220dbdf88SAdrian Chadd *hashval = hash; 13320dbdf88SAdrian Chadd *hashtype = M_HASHTYPE_RSS_TCP_IPV6; 13420dbdf88SAdrian Chadd return (0); 13520dbdf88SAdrian Chadd } else if ((proto == IPPROTO_UDP) && 13620dbdf88SAdrian Chadd (rss_gethashconfig() & RSS_HASHTYPE_RSS_UDP_IPV6)) { 13720dbdf88SAdrian Chadd hash = rss_hash_ip6_4tuple(s, sp, d, dp); 13820dbdf88SAdrian Chadd *hashval = hash; 13920dbdf88SAdrian Chadd *hashtype = M_HASHTYPE_RSS_UDP_IPV6; 14020dbdf88SAdrian Chadd return (0); 14120dbdf88SAdrian Chadd } else if (rss_gethashconfig() & RSS_HASHTYPE_RSS_IPV6) { 14220dbdf88SAdrian Chadd /* RSS doesn't hash on other protocols like SCTP; so 2-tuple */ 14320dbdf88SAdrian Chadd hash = rss_hash_ip6_2tuple(s, d); 14420dbdf88SAdrian Chadd *hashval = hash; 14520dbdf88SAdrian Chadd *hashtype = M_HASHTYPE_RSS_IPV6; 14620dbdf88SAdrian Chadd return (0); 14720dbdf88SAdrian Chadd } 14820dbdf88SAdrian Chadd 14920dbdf88SAdrian Chadd /* No configured available hashtypes! */ 150*e5562eb9SAdrian Chadd RSS_DEBUG("no available hashtypes!\n"); 15120dbdf88SAdrian Chadd return (-1); 15220dbdf88SAdrian Chadd } 153