[IPoIB] Add support for generating unique MACs from Voltaire port GUIDS.
[mirror/winof/.git] / ulp / ipoib / kernel / ipoib_xfr_mgr.h
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  *\r
4  * This software is available to you under the OpenIB.org BSD license\r
5  * below:\r
6  *\r
7  *     Redistribution and use in source and binary forms, with or\r
8  *     without modification, are permitted provided that the following\r
9  *     conditions are met:\r
10  *\r
11  *      - Redistributions of source code must retain the above\r
12  *        copyright notice, this list of conditions and the following\r
13  *        disclaimer.\r
14  *\r
15  *      - Redistributions in binary form must reproduce the above\r
16  *        copyright notice, this list of conditions and the following\r
17  *        disclaimer in the documentation and/or other materials\r
18  *        provided with the distribution.\r
19  *\r
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
24  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
25  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
26  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
27  * SOFTWARE.\r
28  *\r
29  * $Id$\r
30  */\r
31 \r
32 \r
33 #ifndef _IPOIB_XFR_MGR_H_\r
34 #define _IPOIB_XFR_MGR_H_\r
35 \r
36 \r
37 #include <iba/ib_al.h>\r
38 #include <complib/cl_types.h>\r
39 #include <complib/cl_qpool.h>\r
40 #include <complib/cl_spinlock.h>\r
41 #include <complib/cl_qlist.h>\r
42 #include <complib/cl_qpool.h>\r
43 #include <complib/cl_list.h>\r
44 \r
45 \r
46 #include "ipoib_driver.h"\r
47 #include "ip_stats.h"\r
48 #include "ip_packet.h"\r
49 \r
50 \r
51 #include <complib/cl_packon.h>\r
52 /****s* IPoIB Driver/ipoib_hw_addr_t\r
53 * NAME\r
54 *   ipoib_hw_addr_t\r
55 *\r
56 * DESCRIPTION\r
57 *   The ipoib_hw_addr_t structure defines an IPoIB compatible hardware\r
58 *   address.  Values in this structure are stored in network order.\r
59 *\r
60 * SYNOPSIS\r
61 */\r
62 typedef struct _ipoib_hw_addr\r
63 {\r
64         uint32_t        flags_qpn;\r
65         ib_gid_t        gid;\r
66 \r
67 }       PACK_SUFFIX ipoib_hw_addr_t;\r
68 /*\r
69 * FIELDS\r
70 *       flags_qpn\r
71 *               Flags and queue pair number.  Use ipoib_addr_get_flags,\r
72 *               ipoib_addr_set_flags, ipoib_addr_set_qpn, and ipoib_addr_get_qpn\r
73 *               to manipulate the contents.\r
74 *\r
75 *       gid\r
76 *               IB GID value.\r
77 *\r
78 * SEE ALSO\r
79 *       IPoIB, ipoib_addr_get_flags, ipoib_addr_set_flags, ipoib_addr_set_qpn,\r
80 *       ipoib_addr_get_qpn\r
81 *********/\r
82 #include <complib/cl_packoff.h>\r
83 \r
84 \r
85 \r
86 #ifdef __cplusplus\r
87 extern "C"\r
88 {\r
89 #endif\r
90 \r
91 \r
92 /*\r
93  * Address accessors\r
94  */\r
95 \r
96 static inline uint8_t\r
97 ipoib_addr_get_flags(\r
98         IN              const   ipoib_hw_addr_t* const          p_addr )\r
99 {\r
100         return (uint8_t)(cl_ntoh32( p_addr->flags_qpn ) >> 24);\r
101 }\r
102 \r
103 static inline void\r
104 ipoib_addr_set_flags(\r
105         IN                              ipoib_hw_addr_t* const          p_addr,\r
106         IN              const   uint8_t                                         flags )\r
107 {\r
108         p_addr->flags_qpn &= cl_ntoh32( 0xFFFFFF00 );\r
109         p_addr->flags_qpn |= cl_ntoh32( flags );\r
110 }\r
111 \r
112 static inline net32_t\r
113 ipoib_addr_get_qpn(\r
114         IN              const   ipoib_hw_addr_t* const          p_addr )\r
115 {\r
116         return cl_ntoh32( cl_ntoh32( p_addr->flags_qpn ) >> 8 );\r
117 }\r
118 \r
119 static inline void\r
120 ipoib_addr_set_qpn(\r
121         IN                              ipoib_hw_addr_t* const          p_addr,\r
122         IN              const   net32_t                                         qpn )\r
123 {\r
124         p_addr->flags_qpn = cl_ntoh32( (cl_ntoh32(\r
125                 p_addr->flags_qpn ) & 0x000000FF ) | (cl_ntoh32( qpn ) << 8) );\r
126 }\r
127 \r
128 \r
129 /****f* IPOIB/ipoib_mac_from_sst_guid\r
130 * NAME\r
131 *       ipoib_mac_from_sst_guid\r
132 *\r
133 * DESCRIPTION\r
134 *       Generates an ethernet MAC address given a SilverStorm port GUID.\r
135 *\r
136 * SYNOPSIS\r
137 */\r
138 static inline ib_api_status_t\r
139 ipoib_mac_from_sst_guid(\r
140         IN              const   net64_t                                         port_guid,\r
141                 OUT                     mac_addr_t* const                       p_mac_addr )\r
142 {\r
143         const uint8_t   *p_guid = (const uint8_t*)&port_guid;\r
144         uint32_t                low24;\r
145 \r
146         /* Port guid is in network byte order.  OUI is in lower 3 bytes. */\r
147         ASSERT( p_guid[0] == 0x00 && p_guid[1] == 0x06 && p_guid[2] == 0x6a );\r
148 \r
149         /*\r
150          * We end up using only the lower 23-bits of the GUID.  Trap that\r
151          * the 24th (bit 23) through 27th (bit 26) bit aren't set.\r
152          */\r
153         if( port_guid & CL_HTON64( 0x0000000007800000 ) )\r
154                 return IB_INVALID_GUID;\r
155 \r
156         low24 = 0x00FFF000 -\r
157                 ((((uint32_t)cl_ntoh64( port_guid ) & 0x00FFFFFF) - 0x101) * 2);\r
158         low24 -= p_guid[3]; /* minus port number */\r
159 \r
160         p_mac_addr->addr[0] = p_guid[0];\r
161         p_mac_addr->addr[1] = p_guid[1];\r
162         p_mac_addr->addr[2] = p_guid[2];\r
163         p_mac_addr->addr[3] = (uint8_t)(low24 >> 16);\r
164         p_mac_addr->addr[4] = (uint8_t)(low24 >> 8);\r
165         p_mac_addr->addr[5] = (uint8_t)low24;\r
166         \r
167         return IB_SUCCESS;\r
168 }\r
169 /*\r
170 * PARAMETERS\r
171 *       port_guid\r
172 *               The port GUID, in network byte order, for which to generate a\r
173 *               MAC address.\r
174 *\r
175 *       p_mac_addr\r
176 *               Pointer to a mac address in which to store the results.\r
177 *\r
178 * RETURN VALUES\r
179 *       IB_SUCCESS\r
180 *               The MAC address was successfully converted.\r
181 *\r
182 *       IB_INVALID_GUID\r
183 *               The port GUID provided was not a known GUID format.\r
184 *\r
185 * NOTES\r
186 *       The algorithm to convert portGuid to MAC address is as per DN0074, and\r
187 *       assumes a 2 port HCA.\r
188 *\r
189 * SEE ALSO\r
190 *       IPOIB\r
191 *********/\r
192 \r
193 \r
194 /****f* IPOIB/ipoib_mac_from_mlx_guid\r
195 * NAME\r
196 *       ipoib_mac_from_sst_guid\r
197 *\r
198 * DESCRIPTION\r
199 *       Generates an ethernet MAC address given a Mellanox port GUID.\r
200 *\r
201 * SYNOPSIS\r
202 */\r
203 static inline ib_api_status_t\r
204 ipoib_mac_from_mlx_guid(\r
205         IN              const   net64_t                                         port_guid,\r
206                 OUT                     mac_addr_t* const                       p_mac_addr )\r
207 {\r
208         const uint8_t   *p_guid = (const uint8_t*)&port_guid;\r
209         uint32_t                low24;\r
210 \r
211         /* Port guid is in network byte order.  OUI is in lower 3 bytes. */\r
212         ASSERT( p_guid[0] == 0x00 && p_guid[1] == 0x02 && p_guid[2] == 0xc9 );\r
213 \r
214         if( (port_guid & CL_HTON64( 0x000000ffff000000 )) !=\r
215                 CL_HTON64(0x0000000200000000))\r
216         {\r
217                 return IB_INVALID_GUID;\r
218         }\r
219 \r
220         low24 = ((uint32_t)cl_ntoh64( port_guid ) & 0x00FFFFFF);\r
221 \r
222         p_mac_addr->addr[0] = p_guid[0];\r
223         p_mac_addr->addr[1] = p_guid[1];\r
224         p_mac_addr->addr[2] = p_guid[2];\r
225         p_mac_addr->addr[3] = (uint8_t)(low24 >> 16);\r
226         p_mac_addr->addr[4] = (uint8_t)(low24 >> 8);\r
227         p_mac_addr->addr[5] = (uint8_t)low24;\r
228         \r
229         return IB_SUCCESS;\r
230 }\r
231 /*\r
232 * PARAMETERS\r
233 *       port_guid\r
234 *               The port GUID, in network byte order, for which to generate a\r
235 *               MAC address.\r
236 *\r
237 *       p_mac_addr\r
238 *               Pointer to a mac address in which to store the results.\r
239 *\r
240 * RETURN VALUES\r
241 *       IB_SUCCESS\r
242 *               The MAC address was successfully converted.\r
243 *\r
244 *       IB_INVALID_GUID\r
245 *               The port GUID provided was not a known GUID format.\r
246 *\r
247 * SEE ALSO\r
248 *       IPOIB\r
249 *********/\r
250 \r
251 \r
252 /****f* IPOIB/ipoib_mac_from_voltaire_guid\r
253 * NAME\r
254 *       ipoib_mac_from_voltaire_guid\r
255 *\r
256 * DESCRIPTION\r
257 *       Generates an ethernet MAC address given a Voltaire port GUID.\r
258 *\r
259 * SYNOPSIS\r
260 */\r
261 static inline ib_api_status_t\r
262 ipoib_mac_from_voltaire_guid(\r
263         IN              const   net64_t                                         port_guid,\r
264                 OUT                     mac_addr_t* const                       p_mac_addr )\r
265 {\r
266         const uint8_t   *p_guid = (const uint8_t*)&port_guid;\r
267 \r
268         /* Port guid is in network byte order.  OUI is in lower 3 bytes. */\r
269         ASSERT( p_guid[0] == 0x00 && p_guid[1] == 0x08 && p_guid[2] == 0xf1 );\r
270 \r
271         p_mac_addr->addr[0] = p_guid[0];\r
272         p_mac_addr->addr[1] = p_guid[1];\r
273         p_mac_addr->addr[2] = p_guid[2];\r
274         p_mac_addr->addr[3] = p_guid[4] ^ p_guid[6];\r
275         p_mac_addr->addr[4] = p_guid[5] ^ p_guid[7];\r
276         p_mac_addr->addr[5] = p_guid[5] + p_guid[6] + p_guid[7];\r
277 \r
278         return IB_SUCCESS;\r
279 }\r
280 /*\r
281 * PARAMETERS\r
282 *       port_guid\r
283 *               The port GUID, in network byte order, for which to generate a\r
284 *               MAC address.\r
285 *\r
286 *       p_mac_addr\r
287 *               Pointer to a mac address in which to store the results.\r
288 *\r
289 * RETURN VALUES\r
290 *       IB_SUCCESS\r
291 *               The MAC address was successfully converted.\r
292 *\r
293 * SEE ALSO\r
294 *       IPOIB\r
295 *********/\r
296 \r
297 \r
298 /****f* IPOIB/ipoib_mac_from_guid\r
299 * NAME\r
300 *       ipoib_mac_from_guid\r
301 *\r
302 * DESCRIPTION\r
303 *       Generates an ethernet MAC address given a port GUID.\r
304 *\r
305 * SYNOPSIS\r
306 */\r
307 static inline ib_api_status_t\r
308 ipoib_mac_from_guid(\r
309         IN              const   net64_t                                         port_guid,\r
310                 OUT                     mac_addr_t* const                       p_mac_addr )\r
311 {\r
312         ib_api_status_t status;\r
313         const uint8_t   *p_guid = (const uint8_t*)&port_guid;\r
314         uint32_t                laa;\r
315 \r
316         /* Port guid is in network byte order.  OUI is in lower 3 bytes. */\r
317         if( p_guid[0] == 0x00 && p_guid[1] == 0x06 && p_guid[2] == 0x6a )\r
318         {\r
319                 status = ipoib_mac_from_sst_guid( port_guid, p_mac_addr );\r
320                 if( status == IB_SUCCESS )\r
321                         return IB_SUCCESS;\r
322         }\r
323         else if( p_guid[0] == 0x00 && p_guid[1] == 0x02 && p_guid[2] == 0xc9 )\r
324         {\r
325                 status = ipoib_mac_from_mlx_guid( port_guid, p_mac_addr );\r
326                 if( status == IB_SUCCESS )\r
327                         return IB_SUCCESS;\r
328         }\r
329         else if( p_guid[0] == 0x00 && p_guid[1] == 0x08 && p_guid[2] == 0xf1 )\r
330         {\r
331                 status = ipoib_mac_from_voltaire_guid( port_guid, p_mac_addr );\r
332                 if( status == IB_SUCCESS )\r
333                         return IB_SUCCESS;\r
334         }\r
335         \r
336         /* Value of zero is reserved. */\r
337         laa = cl_atomic_inc( &g_ipoib.laa_idx );\r
338 \r
339         if( !laa )\r
340                 return IB_INVALID_GUID;\r
341 \r
342         p_mac_addr->addr[0] = 2; /* LAA bit */\r
343         p_mac_addr->addr[1] = 0;\r
344         p_mac_addr->addr[2] = (uint8_t)(laa >> 24);\r
345         p_mac_addr->addr[3] = (uint8_t)(laa >> 16);\r
346         p_mac_addr->addr[4] = (uint8_t)(laa >> 8);\r
347         p_mac_addr->addr[5] = (uint8_t)laa;\r
348         \r
349         return IB_SUCCESS;\r
350 }\r
351 /*\r
352 * PARAMETERS\r
353 *       port_guid\r
354 *               The port GUID, in network byte order, for which to generate a\r
355 *               MAC address.\r
356 *\r
357 *       p_mac_addr\r
358 *               Pointer to a mac address in which to store the results.\r
359 *\r
360 * RETURN VALUES\r
361 *       IB_SUCCESS\r
362 *               The MAC address was successfully converted.\r
363 *\r
364 *       IB_INVALID_GUID\r
365 *               The port GUID provided was not a known GUID format.\r
366 *\r
367 * NOTES\r
368 *       Creates a locally administered address using a global incrementing counter.\r
369 *\r
370 * SEE ALSO\r
371 *       IPOIB\r
372 *********/\r
373 \r
374 \r
375 /****f* IPOIB/ipoib_sst_guid_from_mac\r
376 * NAME\r
377 *       ipoib_sst_guid_from_mac\r
378 *\r
379 * DESCRIPTION\r
380 *       Generates a port GUID given an ethernet MAC address.\r
381 *\r
382 * SYNOPSIS\r
383 */\r
384 static inline ib_api_status_t\r
385 ipoib_sst_guid_from_mac(\r
386         IN              const   mac_addr_t                                      mac,\r
387                 OUT                     net64_t* const                          p_port_guid )\r
388 {\r
389         uint8_t         *p_guid = (uint8_t*)p_port_guid;\r
390         uint32_t        low24;\r
391 \r
392         /* MAC address is in network byte order.  OUI is in lower 3 bytes. */\r
393         if( mac.addr[0] != 0x00 || \r
394                 mac.addr[1] != 0x06 || \r
395                 mac.addr[2] != 0x6a )\r
396         {\r
397                 return IB_INVALID_GUID;\r
398         }\r
399 \r
400         low24 = mac.addr[3] << 16 || mac.addr[4] << 8 || mac.addr[5];\r
401 \r
402         low24 = 0x00FFF000 - low24;\r
403         /* Divide by two */\r
404         low24 >>= 1;\r
405         /* Add the serial number base offset. */\r
406         low24 += 0x101;\r
407 \r
408         /* OUI */\r
409         p_guid[0] = mac.addr[0];\r
410         p_guid[1] = mac.addr[1];\r
411         p_guid[2] = mac.addr[2];\r
412         /* Port number */\r
413         p_guid[3] = mac.addr[5] & 0x01;\r
414         /* Type */\r
415         p_guid[4] = 0x98;\r
416         /* Serial Number */\r
417         p_guid[5] = (uint8_t)(low24 >> 16);\r
418         p_guid[6] = (uint8_t)(low24 >> 8);\r
419         p_guid[7] = (uint8_t)low24;\r
420         \r
421         return IB_SUCCESS;\r
422 }\r
423 /*\r
424 * PARAMETERS\r
425 *       port_guid\r
426 *               The port GUID, in network byte order, for which to generate a\r
427 *               MAC address.\r
428 *\r
429 *       p_mac_addr\r
430 *               Pointer to a mac address in which to store the results.\r
431 *\r
432 * RETURN VALUES\r
433 *       IB_SUCCESS\r
434 *               The MAC address was successfully converted.\r
435 *\r
436 *       IB_INVALID_GUID\r
437 *               The port GUID provided was not a known GUID format.\r
438 *\r
439 * NOTES\r
440 *       The algorithm to convert portGuid to MAC address is as per DN0074, and\r
441 *       assumes a 2 port HCA.\r
442 *\r
443 * SEE ALSO\r
444 *       IPOIB\r
445 *********/\r
446 \r
447 \r
448 /****f* IPOIB/ipoib_mlx_guid_from_mac\r
449 * NAME\r
450 *       ipoib_mlx_guid_from_mac\r
451 *\r
452 * DESCRIPTION\r
453 *       Generates a port GUID given an ethernet MAC address.\r
454 *\r
455 * SYNOPSIS\r
456 */\r
457 static inline ib_api_status_t\r
458 ipoib_mlx_guid_from_mac(\r
459         IN              const   mac_addr_t                                      mac,\r
460                 OUT                     net64_t* const                          p_port_guid )\r
461 {\r
462         uint8_t         *p_guid = (uint8_t*)p_port_guid;\r
463         uint32_t        low24;\r
464 \r
465         /* MAC address is in network byte order.  OUI is in lower 3 bytes. */\r
466         if( mac.addr[0] != 0x00 || \r
467                 mac.addr[1] != 0x02 || \r
468                 mac.addr[2] != 0xc9 )\r
469         {\r
470                 return IB_INVALID_GUID;\r
471         }\r
472 \r
473         low24 = mac.addr[3] << 16 || mac.addr[4] << 8 || mac.addr[5];\r
474 \r
475         /* OUI */\r
476         p_guid[0] = mac.addr[0];\r
477         p_guid[1] = mac.addr[1];\r
478         p_guid[2] = mac.addr[2];\r
479         p_guid[3] = 0x02;\r
480         p_guid[4] = 0x00;\r
481         /* Serial Number */\r
482         p_guid[5] = (uint8_t)(low24 >> 16);\r
483         p_guid[6] = (uint8_t)(low24 >> 8);\r
484         p_guid[7] = (uint8_t)low24;\r
485         \r
486         return IB_SUCCESS;\r
487 }\r
488 /*\r
489 * PARAMETERS\r
490 *       port_guid\r
491 *               The port GUID, in network byte order, for which to generate a\r
492 *               MAC address.\r
493 *\r
494 *       p_mac_addr\r
495 *               Pointer to a mac address in which to store the results.\r
496 *\r
497 * RETURN VALUES\r
498 *       IB_SUCCESS\r
499 *               The MAC address was successfully converted.\r
500 *\r
501 *       IB_INVALID_GUID\r
502 *               The port GUID provided was not a known GUID format.\r
503 *\r
504 * NOTES\r
505 *       The algorithm to convert portGuid to MAC address is as \r
506 *\r
507 * SEE ALSO\r
508 *       IPOIB\r
509 *********/\r
510 \r
511 \r
512 #ifdef __cplusplus\r
513 }\r
514 #endif\r
515 \r
516 #endif  /* _IPOIB_XFR_MGR_H_ */\r