The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/uipc_mbufhash.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: if_trunk.c,v 1.30 2007/01/31 06:20:19 reyk Exp $      */
    2 
    3 /*
    4  * Copyright (c) 2005, 2006 Reyk Floeter <reyk@openbsd.org>
    5  * Copyright (c) 2007 Andrew Thompson <thompsa@FreeBSD.org>
    6  *
    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.
   10  *
   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.
   18  */
   19 
   20 #include <sys/cdefs.h>
   21 __FBSDID("$FreeBSD: releng/11.0/sys/kern/uipc_mbufhash.c 280173 2015-03-17 14:16:50Z glebius $");
   22 
   23 #include "opt_inet.h"
   24 #include "opt_inet6.h"
   25 
   26 #include <sys/param.h>
   27 #include <sys/mbuf.h>
   28 #include <sys/fnv_hash.h>
   29 
   30 #include <net/ethernet.h>
   31 
   32 #if defined(INET) || defined(INET6)
   33 #include <netinet/in.h>
   34 #endif
   35 
   36 #ifdef INET
   37 #include <netinet/ip.h>
   38 #endif
   39 
   40 #ifdef INET6
   41 #include <netinet/ip6.h>
   42 #endif
   43 
   44 static const void *
   45 m_ether_tcpip_hash_gethdr(const struct mbuf *m, const u_int off,
   46     const u_int len, void *buf)
   47 {
   48 
   49         if (m->m_pkthdr.len < (off + len)) {
   50                 return (NULL);
   51         } else if (m->m_len < (off + len)) {
   52                 m_copydata(m, off, len, buf);
   53                 return (buf);
   54         }
   55         return (mtod(m, char *) + off);
   56 }
   57 
   58 uint32_t
   59 m_ether_tcpip_hash_init(void)
   60 {
   61         uint32_t seed;
   62 
   63         seed = arc4random();
   64         return (fnv_32_buf(&seed, sizeof(seed), FNV1_32_INIT));
   65 }
   66 
   67 uint32_t
   68 m_ether_tcpip_hash(const uint32_t flags, const struct mbuf *m,
   69     const uint32_t key)
   70 {
   71         union {
   72 #ifdef INET
   73                 struct ip ip;
   74 #endif
   75 #ifdef INET6
   76                 struct ip6_hdr ip6;
   77 #endif
   78                 struct ether_vlan_header vlan;
   79                 uint32_t port;
   80         } buf;
   81         struct ether_header *eh;
   82         const struct ether_vlan_header *vlan;
   83 #ifdef INET
   84         const struct ip *ip;
   85 #endif
   86 #ifdef INET6
   87         const struct ip6_hdr *ip6;
   88 #endif
   89         uint32_t p;
   90         int off;
   91         uint16_t etype;
   92 
   93         p = key;
   94         off = sizeof(*eh);
   95         if (m->m_len < off)
   96                 goto done;
   97         eh = mtod(m, struct ether_header *);
   98         etype = ntohs(eh->ether_type);
   99         if (flags & MBUF_HASHFLAG_L2) {
  100                 p = fnv_32_buf(&eh->ether_shost, ETHER_ADDR_LEN, p);
  101                 p = fnv_32_buf(&eh->ether_dhost, ETHER_ADDR_LEN, p);
  102         }
  103         /* Special handling for encapsulating VLAN frames */
  104         if ((m->m_flags & M_VLANTAG) && (flags & MBUF_HASHFLAG_L2)) {
  105                 p = fnv_32_buf(&m->m_pkthdr.ether_vtag,
  106                     sizeof(m->m_pkthdr.ether_vtag), p);
  107         } else if (etype == ETHERTYPE_VLAN) {
  108                 vlan = m_ether_tcpip_hash_gethdr(m, off, sizeof(*vlan), &buf);
  109                 if (vlan == NULL)
  110                         goto done;
  111 
  112                 if (flags & MBUF_HASHFLAG_L2)
  113                         p = fnv_32_buf(&vlan->evl_tag, sizeof(vlan->evl_tag), p);
  114                 etype = ntohs(vlan->evl_proto);
  115                 off += sizeof(*vlan) - sizeof(*eh);
  116         }
  117         switch (etype) {
  118 #ifdef INET
  119         case ETHERTYPE_IP:
  120                 ip = m_ether_tcpip_hash_gethdr(m, off, sizeof(*ip), &buf);
  121                 if (ip == NULL)
  122                         break;
  123                 if (flags & MBUF_HASHFLAG_L3) {
  124                         p = fnv_32_buf(&ip->ip_src, sizeof(struct in_addr), p);
  125                         p = fnv_32_buf(&ip->ip_dst, sizeof(struct in_addr), p);
  126                 }
  127                 if (flags & MBUF_HASHFLAG_L4) {
  128                         const uint32_t *ports;
  129                         int iphlen;
  130 
  131                         switch (ip->ip_p) {
  132                         case IPPROTO_TCP:
  133                         case IPPROTO_UDP:
  134                         case IPPROTO_SCTP:
  135                                 iphlen = ip->ip_hl << 2;
  136                                 if (iphlen < sizeof(*ip))
  137                                         break;
  138                                 off += iphlen;
  139                                 ports = m_ether_tcpip_hash_gethdr(m,
  140                                     off, sizeof(*ports), &buf);
  141                                 if (ports == NULL)
  142                                         break;
  143                                 p = fnv_32_buf(ports, sizeof(*ports), p);
  144                                 break;
  145                         default:
  146                                 break;
  147                         }
  148                 }
  149                 break;
  150 #endif
  151 #ifdef INET6
  152         case ETHERTYPE_IPV6:
  153                 ip6 = m_ether_tcpip_hash_gethdr(m, off, sizeof(*ip6), &buf);
  154                 if (ip6 == NULL)
  155                         break;
  156                 if (flags & MBUF_HASHFLAG_L3) {
  157                         p = fnv_32_buf(&ip6->ip6_src, sizeof(struct in6_addr), p);
  158                         p = fnv_32_buf(&ip6->ip6_dst, sizeof(struct in6_addr), p);
  159                 }
  160                 if (flags & MBUF_HASHFLAG_L4) {
  161                         uint32_t flow;
  162 
  163                         /* IPv6 flow label */
  164                         flow = ip6->ip6_flow & IPV6_FLOWLABEL_MASK;
  165                         p = fnv_32_buf(&flow, sizeof(flow), p);
  166                 }
  167                 break;
  168 #endif
  169         default:
  170                 break;
  171         }
  172 done:
  173         return (p);
  174 }

Cache object: 2c99299fda7af75321cae5ac3bb7fd75


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.