1 /* $OpenBSD: if_trunk.c,v 1.30 2007/01/31 06:20:19 reyk Exp $ */
4 * Copyright (c) 2005, 2006 Reyk Floeter <reyk@openbsd.org>
5 * Copyright (c) 2007 Andrew Thompson <thompsa@FreeBSD.org>
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include <sys/cdefs.h>
22 #include "opt_inet6.h"
24 #include <sys/param.h>
26 #include <sys/fnv_hash.h>
28 #include <net/ethernet.h>
29 #include <net/infiniband.h>
31 #if defined(INET) || defined(INET6)
32 #include <netinet/in.h>
36 #include <netinet/ip.h>
40 #include <netinet/ip6.h>
44 m_common_hash_gethdr(const struct mbuf *m, const u_int off,
45 const u_int len, void *buf)
48 if (m->m_pkthdr.len < (off + len)) {
50 } else if (m->m_len < (off + len)) {
51 m_copydata(m, off, len, buf);
54 return (mtod(m, char *) + off);
58 m_ether_tcpip_hash_init(void)
63 return (fnv_32_buf(&seed, sizeof(seed), FNV1_32_INIT));
67 m_infiniband_tcpip_hash_init(void)
72 return (fnv_32_buf(&seed, sizeof(seed), FNV1_32_INIT));
75 static inline uint32_t
76 m_tcpip_hash(const uint32_t flags, const struct mbuf *m,
77 uint32_t p, int off, const uint16_t etype)
79 #if defined(INET) || defined(INET6)
93 const struct ip6_hdr *ip6;
99 ip = m_common_hash_gethdr(m, off, sizeof(*ip), &buf);
102 if (flags & MBUF_HASHFLAG_L3) {
103 p = fnv_32_buf(&ip->ip_src, sizeof(struct in_addr), p);
104 p = fnv_32_buf(&ip->ip_dst, sizeof(struct in_addr), p);
106 if (flags & MBUF_HASHFLAG_L4) {
107 const uint32_t *ports;
114 iphlen = ip->ip_hl << 2;
115 if (iphlen < sizeof(*ip))
118 ports = m_common_hash_gethdr(m,
119 off, sizeof(*ports), &buf);
122 p = fnv_32_buf(ports, sizeof(*ports), p);
132 ip6 = m_common_hash_gethdr(m, off, sizeof(*ip6), &buf);
135 if (flags & MBUF_HASHFLAG_L3) {
136 p = fnv_32_buf(&ip6->ip6_src, sizeof(struct in6_addr), p);
137 p = fnv_32_buf(&ip6->ip6_dst, sizeof(struct in6_addr), p);
139 if (flags & MBUF_HASHFLAG_L4) {
142 /* IPv6 flow label */
143 flow = ip6->ip6_flow & IPV6_FLOWLABEL_MASK;
144 p = fnv_32_buf(&flow, sizeof(flow), p);
155 m_ether_tcpip_hash(const uint32_t flags, const struct mbuf *m,
159 struct ether_vlan_header vlan;
161 const struct ether_header *eh;
162 const struct ether_vlan_header *vlan;
169 eh = mtod(m, struct ether_header *);
170 etype = ntohs(eh->ether_type);
171 if (flags & MBUF_HASHFLAG_L2) {
172 p = fnv_32_buf(&eh->ether_shost, ETHER_ADDR_LEN, p);
173 p = fnv_32_buf(&eh->ether_dhost, ETHER_ADDR_LEN, p);
175 /* Special handling for encapsulating VLAN frames */
176 if ((m->m_flags & M_VLANTAG) && (flags & MBUF_HASHFLAG_L2)) {
177 p = fnv_32_buf(&m->m_pkthdr.ether_vtag,
178 sizeof(m->m_pkthdr.ether_vtag), p);
179 } else if (etype == ETHERTYPE_VLAN) {
180 vlan = m_common_hash_gethdr(m, off, sizeof(*vlan), &buf);
184 if (flags & MBUF_HASHFLAG_L2)
185 p = fnv_32_buf(&vlan->evl_tag, sizeof(vlan->evl_tag), p);
186 etype = ntohs(vlan->evl_proto);
187 off += sizeof(*vlan) - sizeof(*eh);
189 return (m_tcpip_hash(flags, m, p, off, etype));
193 m_infiniband_tcpip_hash(const uint32_t flags, const struct mbuf *m,
196 const struct infiniband_header *ibh;
203 ibh = mtod(m, struct infiniband_header *);
204 etype = ntohs(ibh->ib_protocol);
205 if (flags & MBUF_HASHFLAG_L2)
206 p = fnv_32_buf(&ibh->ib_hwaddr, INFINIBAND_ADDR_LEN, p);
208 return (m_tcpip_hash(flags, m, p, off, etype));