in6_pcbgroup.c revision 268349
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: head/sys/netinet6/in6_pcbgroup.c 268349 2014-07-07 00:02:49Z bryanv $"); 33 34#include "opt_inet6.h" 35#include "opt_rss.h" 36 37#include <sys/param.h> 38#include <sys/mbuf.h> 39 40#include <netinet/in.h> 41#include <netinet/in_pcb.h> 42#include <netinet/in_rss.h> 43#ifdef INET6 44#include <netinet6/in6_pcb.h> 45#endif /* INET6 */ 46 47/* 48 * Given a hash of whatever the covered tuple might be, return a pcbgroup 49 * index. Where RSS is supported, try to align bucket selection with RSS CPU 50 * affinity strategy. 51 */ 52static __inline u_int 53in6_pcbgroup_getbucket(struct inpcbinfo *pcbinfo, uint32_t hash) 54{ 55 56#ifdef RSS 57 return (rss_getbucket(hash)); 58#else 59 return (hash % pcbinfo->ipi_npcbgroups); 60#endif 61} 62 63/* 64 * Map a (hashtype, hash) tuple into a connection group, or NULL if the hash 65 * information is insufficient to identify the pcbgroup. This might occur if 66 * a TCP packet turnsup with a 2-tuple hash, or if an RSS hash is present but 67 * RSS is not compiled into the kernel. 68 */ 69struct inpcbgroup * 70in6_pcbgroup_byhash(struct inpcbinfo *pcbinfo, u_int hashtype, uint32_t hash) 71{ 72 73#ifdef RSS 74 if ((pcbinfo->ipi_hashfields == IPI_HASHFIELDS_4TUPLE && 75 hashtype == M_HASHTYPE_RSS_TCP_IPV6) || 76 (pcbinfo->ipi_hashfields == IPI_HASHFIELDS_2TUPLE && 77 hashtype == M_HASHTYPE_RSS_IPV6)) 78 return (&pcbinfo->ipi_pcbgroups[ 79 in6_pcbgroup_getbucket(pcbinfo, hash)]); 80#endif 81 return (NULL); 82} 83 84struct inpcbgroup * 85in6_pcbgroup_bymbuf(struct inpcbinfo *pcbinfo, struct mbuf *m) 86{ 87 88 return (in6_pcbgroup_byhash(pcbinfo, M_HASHTYPE_GET(m), 89 m->m_pkthdr.flowid)); 90} 91 92struct inpcbgroup * 93in6_pcbgroup_bytuple(struct inpcbinfo *pcbinfo, const struct in6_addr *laddrp, 94 u_short lport, const struct in6_addr *faddrp, u_short fport) 95{ 96 uint32_t hash; 97 98 /* 99 * RSS note: we pass foreign addr/port as source, and local addr/port 100 * as destination, as we want to align with what the hardware is 101 * doing. 102 */ 103 switch (pcbinfo->ipi_hashfields) { 104 case IPI_HASHFIELDS_4TUPLE: 105#ifdef RSS 106 hash = rss_hash_ip6_4tuple(*faddrp, fport, *laddrp, lport); 107#else 108 hash = faddrp->s6_addr32[3] ^ fport; 109#endif 110 break; 111 112 case IPI_HASHFIELDS_2TUPLE: 113#ifdef RSS 114 hash = rss_hash_ip6_2tuple(*faddrp, *laddrp); 115#else 116 hash = faddrp->s6_addr32[3] ^ laddrp->s6_addr32[3]; 117#endif 118 break; 119 120 default: 121 hash = 0; 122 } 123 return (&pcbinfo->ipi_pcbgroups[in6_pcbgroup_getbucket(pcbinfo, 124 hash)]); 125} 126 127struct inpcbgroup * 128in6_pcbgroup_byinpcb(struct inpcb *inp) 129{ 130 131 return (in6_pcbgroup_bytuple(inp->inp_pcbinfo, &inp->in6p_laddr, 132 inp->inp_lport, &inp->in6p_faddr, inp->inp_fport)); 133} 134