Home | History | Annotate | Line # | Download | only in net
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