]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/ofed/drivers/net/mlx4/utils.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / ofed / drivers / net / mlx4 / utils.c
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$");
22
23 #include "opt_inet.h"
24 #include "opt_inet6.h"
25
26 #include <sys/param.h>
27 #include <sys/kernel.h>
28 #include <sys/malloc.h>
29 #include <sys/mbuf.h>
30 #include <sys/queue.h>
31 #include <sys/socket.h>
32 #include <sys/sockio.h>
33 #include <sys/sysctl.h>
34 #include <sys/module.h>
35 #include <sys/priv.h>
36 #include <sys/systm.h>
37 #include <sys/proc.h>
38 #include <sys/hash.h>
39 #include <sys/lock.h>
40 #include <sys/rmlock.h>
41 #include <sys/taskqueue.h>
42 #include <sys/eventhandler.h>
43
44 #include <net/ethernet.h>
45 #include <net/if.h>
46 #include <net/if_clone.h>
47 #include <net/if_arp.h>
48 #include <net/if_dl.h>
49 #include <net/if_llc.h>
50 #include <net/if_media.h>
51 #include <net/if_types.h>
52 #include <net/if_var.h>
53 #include <net/bpf.h>
54
55 #if defined(INET) || defined(INET6)
56 #include <netinet/in.h>
57 #endif
58 #ifdef INET
59 #include <netinet/in_systm.h>
60 #include <netinet/if_ether.h>
61 #include <netinet/ip.h>
62 #endif
63
64 #ifdef INET6
65 #include <netinet/ip6.h>
66 #include <netinet6/in6_var.h>
67 #include <netinet6/in6_ifattach.h>
68 #endif
69
70 #include <net/if_vlan_var.h>
71
72 #include "utils.h"
73
74 /* XXX this code should be factored out */
75 /* XXX copied from if_lagg.c */
76
77 static const void *
78 mlx4_en_gethdr(struct mbuf *m, u_int off, u_int len, void *buf)
79 {
80         if (m->m_pkthdr.len < (off + len)) {
81                 return (NULL);
82         } else if (m->m_len < (off + len)) {
83                 m_copydata(m, off, len, buf);
84                 return (buf);
85         }
86         return (mtod(m, char *) + off);
87 }
88
89 uint32_t
90 mlx4_en_hashmbuf(uint32_t flags, struct mbuf *m, uint32_t key)
91 {
92         uint16_t etype;
93         uint32_t p = key;
94         int off;
95         struct ether_header *eh;
96         const struct ether_vlan_header *vlan;
97 #ifdef INET
98         const struct ip *ip;
99         const uint32_t *ports;
100         int iphlen;
101 #endif
102 #ifdef INET6
103         const struct ip6_hdr *ip6;
104         uint32_t flow;
105 #endif
106         union {
107 #ifdef INET
108                 struct ip ip;
109 #endif
110 #ifdef INET6
111                 struct ip6_hdr ip6;
112 #endif
113                 struct ether_vlan_header vlan;
114                 uint32_t port;
115         } buf;
116
117
118         off = sizeof(*eh);
119         if (m->m_len < off)
120                 goto out;
121         eh = mtod(m, struct ether_header *);
122         etype = ntohs(eh->ether_type);
123         if (flags & MLX4_F_HASHL2) {
124                 p = hash32_buf(&eh->ether_shost, ETHER_ADDR_LEN, p);
125                 p = hash32_buf(&eh->ether_dhost, ETHER_ADDR_LEN, p);
126         }
127
128         /* Special handling for encapsulating VLAN frames */
129         if ((m->m_flags & M_VLANTAG) && (flags & MLX4_F_HASHL2)) {
130                 p = hash32_buf(&m->m_pkthdr.ether_vtag,
131                     sizeof(m->m_pkthdr.ether_vtag), p);
132         } else if (etype == ETHERTYPE_VLAN) {
133                 vlan = mlx4_en_gethdr(m, off,  sizeof(*vlan), &buf);
134                 if (vlan == NULL)
135                         goto out;
136
137                 if (flags & MLX4_F_HASHL2)
138                         p = hash32_buf(&vlan->evl_tag, sizeof(vlan->evl_tag), p);
139                 etype = ntohs(vlan->evl_proto);
140                 off += sizeof(*vlan) - sizeof(*eh);
141         }
142
143         switch (etype) {
144 #ifdef INET
145         case ETHERTYPE_IP:
146                 ip = mlx4_en_gethdr(m, off, sizeof(*ip), &buf);
147                 if (ip == NULL)
148                         goto out;
149
150                 if (flags & MLX4_F_HASHL3) {
151                         p = hash32_buf(&ip->ip_src, sizeof(struct in_addr), p);
152                         p = hash32_buf(&ip->ip_dst, sizeof(struct in_addr), p);
153                 }
154                 if (!(flags & MLX4_F_HASHL4))
155                         break;
156                 switch (ip->ip_p) {
157                         case IPPROTO_TCP:
158                         case IPPROTO_UDP:
159                         case IPPROTO_SCTP:
160                                 iphlen = ip->ip_hl << 2;
161                                 if (iphlen < sizeof(*ip))
162                                         break;
163                                 off += iphlen;
164                                 ports = mlx4_en_gethdr(m, off, sizeof(*ports), &buf);
165                                 if (ports == NULL)
166                                         break;
167                                 p = hash32_buf(ports, sizeof(*ports), p);
168                                 break;
169                 }
170                 break;
171 #endif
172 #ifdef INET6
173         case ETHERTYPE_IPV6:
174                 if (!(flags & MLX4_F_HASHL3))
175                         break;
176                 ip6 = mlx4_en_gethdr(m, off, sizeof(*ip6), &buf);
177                 if (ip6 == NULL)
178                         goto out;
179
180                 p = hash32_buf(&ip6->ip6_src, sizeof(struct in6_addr), p);
181                 p = hash32_buf(&ip6->ip6_dst, sizeof(struct in6_addr), p);
182                 flow = ip6->ip6_flow & IPV6_FLOWLABEL_MASK;
183                 p = hash32_buf(&flow, sizeof(flow), p); /* IPv6 flow label */
184                 break;
185 #endif
186         }
187 out:
188         return (p);
189 }