2 * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.
\r
4 * This software is available to you under the OpenIB.org BSD license
\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
11 * - Redistributions of source code must retain the above
\r
12 * copyright notice, this list of conditions and the following
\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
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
33 #ifndef _IPOIB_XFR_MGR_H_
\r
34 #define _IPOIB_XFR_MGR_H_
\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
46 #include "ipoib_driver.h"
\r
47 #include "ip_stats.h"
\r
48 #include <ip_packet.h>
\r
51 #include <complib/cl_packon.h>
\r
52 /****s* IPoIB Driver/ipoib_hw_addr_t
\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
62 typedef struct _ipoib_hw_addr
\r
67 } PACK_SUFFIX ipoib_hw_addr_t;
\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
79 * IPoIB, ipoib_addr_get_flags, ipoib_addr_set_flags, ipoib_addr_set_qpn,
\r
80 * ipoib_addr_get_qpn
\r
82 #include <complib/cl_packoff.h>
\r
96 static inline uint8_t
\r
97 ipoib_addr_get_flags(
\r
98 IN const ipoib_hw_addr_t* const p_addr )
\r
100 return (uint8_t)(cl_ntoh32( p_addr->flags_qpn ) >> 24);
\r
104 ipoib_addr_set_flags(
\r
105 IN ipoib_hw_addr_t* const p_addr,
\r
106 IN const uint8_t flags )
\r
108 p_addr->flags_qpn &= cl_ntoh32( 0xFFFFFF00 );
\r
109 p_addr->flags_qpn |= cl_ntoh32( flags );
\r
112 static inline net32_t
\r
113 ipoib_addr_get_qpn(
\r
114 IN const ipoib_hw_addr_t* const p_addr )
\r
116 return cl_ntoh32( cl_ntoh32( p_addr->flags_qpn ) >> 8 );
\r
120 ipoib_addr_set_qpn(
\r
121 IN ipoib_hw_addr_t* const p_addr,
\r
122 IN const net32_t qpn )
\r
124 p_addr->flags_qpn = cl_ntoh32( (cl_ntoh32(
\r
125 p_addr->flags_qpn ) & 0x000000FF ) | (cl_ntoh32( qpn ) << 8) );
\r
129 /****f* IPOIB/ipoib_mac_from_sst_guid
\r
131 * ipoib_mac_from_sst_guid
\r
134 * Generates an ethernet MAC address given a SilverStorm port GUID.
\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
143 const uint8_t *p_guid = (const uint8_t*)&port_guid;
\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
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
153 if( port_guid & CL_HTON64( 0x0000000007800000 ) )
\r
154 return IB_INVALID_GUID;
\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
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
172 * The port GUID, in network byte order, for which to generate a
\r
176 * Pointer to a mac address in which to store the results.
\r
180 * The MAC address was successfully converted.
\r
183 * The port GUID provided was not a known GUID format.
\r
186 * The algorithm to convert portGuid to MAC address is as per DN0074, and
\r
187 * assumes a 2 port HCA.
\r
194 /****f* IPOIB/ipoib_mac_from_mlx_guid
\r
196 * ipoib_mac_from_mlx_guid
\r
199 * Generates an ethernet MAC address given a Mellanox port GUID.
\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
208 const uint8_t *p_guid = (const uint8_t*)&port_guid;
\r
210 net16_t guid_middle;
\r
212 /* Port guid is in network byte order. OUI is in lower 3 bytes. */
\r
213 ASSERT( p_guid[0] == 0x00 && p_guid[1] == 0x02 && p_guid[2] == 0xc9 );
\r
215 guid_middle = (net16_t)((port_guid & CL_HTON64( 0x000000ffff000000 )) >>24);
\r
217 if (guid_middle == 2) {
\r
218 p_mac_addr->addr[0] = 0;
\r
219 } else if (guid_middle == 3) {
\r
220 p_mac_addr->addr[0] = 2;
\r
222 return IB_INVALID_GUID;
\r
224 low24 = ((uint32_t)cl_ntoh64( port_guid ) & 0x00FFFFFF);
\r
226 p_mac_addr->addr[1] = p_guid[1];
\r
227 p_mac_addr->addr[2] = p_guid[2];
\r
228 p_mac_addr->addr[3] = (uint8_t)(low24 >> 16);
\r
229 p_mac_addr->addr[4] = (uint8_t)(low24 >> 8);
\r
230 p_mac_addr->addr[5] = (uint8_t)low24;
\r
235 /****f* IPOIB/ipoib_mac_from_dell_guid
\r
237 * ipoib_mac_from_dell_guid
\r
240 * Generates an ethernet MAC address given a DELL port GUID.
\r
244 static inline ib_api_status_t
\r
245 ipoib_mac_from_dell_guid(
\r
246 IN const net64_t port_guid,
\r
247 OUT mac_addr_t* const p_mac_addr )
\r
249 const uint8_t *p_guid = (const uint8_t*)&port_guid;
\r
251 /* Port guid is in network byte order. OUI is in lower 3 bytes. */
\r
252 ASSERT( p_guid[0] == 0x00 && p_guid[1] == 0x18 && p_guid[2] == 0x8b );
\r
254 p_mac_addr->addr[0] = p_guid[0];
\r
255 p_mac_addr->addr[1] = p_guid[1];
\r
256 p_mac_addr->addr[2] = p_guid[2];
\r
257 p_mac_addr->addr[3] = p_guid[5];
\r
258 p_mac_addr->addr[4] = p_guid[6];
\r
259 p_mac_addr->addr[5] = p_guid[7];
\r
266 * The port GUID, in network byte order, for which to generate a
\r
270 * Pointer to a mac address in which to store the results.
\r
274 * The MAC address was successfully converted.
\r
279 /****f* IPOIB/ipoib_mac_from_general_guid
\r
281 * ipoib_mac_from_dell_guid
\r
284 * Generates an ethernet MAC address given general port GUID and a bitwise mask
\r
288 static inline ib_api_status_t
\r
289 ipoib_mac_from_general_guid(
\r
290 IN const net64_t port_guid,
\r
291 IN uint32_t guid_mask,
\r
292 OUT mac_addr_t* const p_mac_addr )
\r
294 static const mac_addr_size = HW_ADDR_LEN;
\r
296 const uint8_t *p_guid = (const uint8_t*)&port_guid;
\r
297 int digit_counter = 0;
\r
299 //All non-zero bits of guid_mask indicates the number of an appropriate byte in
\r
300 // port_guid, that will be used in MAC address construction
\r
301 for (i = 7; guid_mask; guid_mask >>= 1, --i) {
\r
302 if (guid_mask & 1 ) {
\r
304 if (digit_counter > mac_addr_size) {
\r
305 //to avoid negative index
\r
306 return IB_INVALID_GUID_MASK;
\r
308 p_mac_addr->addr[mac_addr_size - digit_counter] = p_guid [i];
\r
311 // check for the mask validity: it should have 6 non-zero bits
\r
312 if (digit_counter != mac_addr_size) {
\r
313 return IB_INVALID_GUID_MASK;
\r
322 * The port GUID, in network byte order, for which to generate a
\r
326 * Each BIT in the mask indicates whether to include the appropriate BYTE
\r
327 * to the MAC address. Bit 0 corresponds to the less significant BYTE , i.e.
\r
328 * highest index in the MAC array
\r
331 * Pointer to a mac address in which to store the results.
\r
335 * The MAC address was successfully converted.
\r
338 * The port GUID provided was not a known GUID format.
\r
345 /****f* IPOIB/ipoib_mac_from_voltaire_guid
\r
347 * ipoib_mac_from_voltaire_guid
\r
350 * Generates an ethernet MAC address given a Voltaire port GUID.
\r
354 static inline ib_api_status_t
\r
355 ipoib_mac_from_voltaire_guid(
\r
356 IN const net64_t port_guid,
\r
357 OUT mac_addr_t* const p_mac_addr )
\r
359 const uint8_t *p_guid = (const uint8_t*)&port_guid;
\r
361 /* Port guid is in network byte order. OUI is in lower 3 bytes. */
\r
362 ASSERT( p_guid[0] == 0x00 && p_guid[1] == 0x08 && p_guid[2] == 0xf1 );
\r
364 p_mac_addr->addr[0] = p_guid[0];
\r
365 p_mac_addr->addr[1] = p_guid[1];
\r
366 p_mac_addr->addr[2] = p_guid[2];
\r
367 p_mac_addr->addr[3] = p_guid[4] ^ p_guid[6];
\r
368 p_mac_addr->addr[4] = p_guid[5] ^ p_guid[7];
\r
369 p_mac_addr->addr[5] = p_guid[5] + p_guid[6] + p_guid[7];
\r
375 /****f* IPOIB/ipoib_mac_from_guid
\r
377 * ipoib_mac_from_guid
\r
380 * Generates an ethernet MAC address given a port GUID.
\r
384 static inline ib_api_status_t
\r
385 ipoib_mac_from_guid(
\r
386 IN const net64_t port_guid,
\r
387 IN uint32_t guid_mask,
\r
388 OUT mac_addr_t* const p_mac_addr
\r
391 static const guid_default_mask = 0xE7; //==0b 11100111
\r
392 ib_api_status_t status = IB_INVALID_GUID;
\r
393 ib_api_status_t mask_status = IB_SUCCESS;
\r
394 const uint8_t *p_guid = (const uint8_t*)&port_guid;
\r
399 mask_status = ipoib_mac_from_general_guid(port_guid, guid_mask, p_mac_addr);
\r
400 if( mask_status == IB_SUCCESS )
\r
402 //otherwise, mask was invalid, getting back to standard flow
\r
403 /*if (status == IB_INVALID_GUID_MASK)
\r
405 IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR,
\r
406 ("Invalid GUID mask received, rejecting it") );
\r
410 if( p_guid[0] == 0 )
\r
412 if( p_guid[1] == 0x02 && p_guid[2] == 0xc9 )
\r
414 status = ipoib_mac_from_mlx_guid( port_guid, p_mac_addr );
\r
416 else if( p_guid[1] == 0x08 && p_guid[2] == 0xf1 )
\r
418 status = ipoib_mac_from_voltaire_guid( port_guid, p_mac_addr );
\r
420 else if( p_guid[1] == 0x30 && p_guid[2] == 0x48 )
\r
423 status =ipoib_mac_from_general_guid(port_guid, guid_default_mask, p_mac_addr);
\r
425 else if( p_guid[1] == 0x05 && p_guid[2] == 0xad )
\r
428 status =ipoib_mac_from_general_guid(port_guid, guid_default_mask, p_mac_addr);
\r
430 /* Port guid is in network byte order. OUI is in lower 3 bytes. */
\r
431 else if( p_guid[1] == 0x06 && p_guid[2] == 0x6a )
\r
433 status = ipoib_mac_from_sst_guid( port_guid, p_mac_addr );
\r
435 else if( p_guid[1] == 0x1a && p_guid[2] == 0x4b )
\r
438 status =ipoib_mac_from_general_guid(port_guid, guid_default_mask, p_mac_addr);
\r
440 else if( p_guid[1] == 0x18 && p_guid[2] == 0x8b )
\r
443 status =ipoib_mac_from_general_guid(port_guid, guid_default_mask, p_mac_addr);
\r
446 if (status == IB_SUCCESS )
\r
448 ASSERT ( mask_status == IB_SUCCESS || mask_status == IB_INVALID_GUID_MASK );
\r
449 return mask_status;
\r
453 /* Value of zero is reserved. */
\r
454 laa = cl_atomic_inc( &g_ipoib.laa_idx );
\r
457 return IB_INVALID_GUID;
\r
459 p_mac_addr->addr[0] = 2; /* LAA bit */
\r
460 p_mac_addr->addr[1] = 0;
\r
461 p_mac_addr->addr[2] = (uint8_t)(laa >> 24);
\r
462 p_mac_addr->addr[3] = (uint8_t)(laa >> 16);
\r
463 p_mac_addr->addr[4] = (uint8_t)(laa >> 8);
\r
464 p_mac_addr->addr[5] = (uint8_t)laa;
\r
466 return mask_status;
\r
471 * The port GUID, in network byte order, for which to generate a
\r
475 * Pointer to a mac address in which to store the results.
\r
479 * The MAC address was successfully converted.
\r
482 * The port GUID provided was not a known GUID format.
\r
485 * Creates a locally administered address using a global incrementing counter.
\r
492 /****f* IPOIB/ipoib_sst_guid_from_mac
\r
494 * ipoib_sst_guid_from_mac
\r
497 * Generates a port GUID given an ethernet MAC address.
\r
501 static inline ib_api_status_t
\r
502 ipoib_sst_guid_from_mac(
\r
503 IN const mac_addr_t mac,
\r
504 OUT net64_t* const p_port_guid )
\r
506 uint8_t *p_guid = (uint8_t*)p_port_guid;
\r
509 /* MAC address is in network byte order. OUI is in lower 3 bytes. */
\r
510 if( mac.addr[0] != 0x00 ||
\r
511 mac.addr[1] != 0x06 ||
\r
512 mac.addr[2] != 0x6a )
\r
514 return IB_INVALID_GUID;
\r
517 low24 = mac.addr[3] << 16 || mac.addr[4] << 8 || mac.addr[5];
\r
519 low24 = 0x00FFF000 - low24;
\r
520 /* Divide by two */
\r
522 /* Add the serial number base offset. */
\r
526 p_guid[0] = mac.addr[0];
\r
527 p_guid[1] = mac.addr[1];
\r
528 p_guid[2] = mac.addr[2];
\r
530 p_guid[3] = mac.addr[5] & 0x01;
\r
533 /* Serial Number */
\r
534 p_guid[5] = (uint8_t)(low24 >> 16);
\r
535 p_guid[6] = (uint8_t)(low24 >> 8);
\r
536 p_guid[7] = (uint8_t)low24;
\r
543 * The port GUID, in network byte order, for which to generate a
\r
547 * Pointer to a mac address in which to store the results.
\r
551 * The MAC address was successfully converted.
\r
554 * The port GUID provided was not a known GUID format.
\r
557 * The algorithm to convert portGuid to MAC address is as per DN0074, and
\r
558 * assumes a 2 port HCA.
\r
565 /****f* IPOIB/ipoib_mlx_guid_from_mac
\r
567 * ipoib_mlx_guid_from_mac
\r
570 * Generates a port GUID given an ethernet MAC address.
\r
574 static inline ib_api_status_t
\r
575 ipoib_mlx_guid_from_mac(
\r
576 IN const mac_addr_t mac,
\r
577 OUT net64_t* const p_port_guid )
\r
579 uint8_t *p_guid = (uint8_t*)p_port_guid;
\r
582 /* MAC address is in network byte order. OUI is in lower 3 bytes. */
\r
583 if( mac.addr[0] != 0x00 ||
\r
584 mac.addr[1] != 0x02 ||
\r
585 mac.addr[2] != 0xc9 )
\r
587 return IB_INVALID_GUID;
\r
590 low24 = mac.addr[3] << 16 || mac.addr[4] << 8 || mac.addr[5];
\r
593 p_guid[0] = mac.addr[0];
\r
594 p_guid[1] = mac.addr[1];
\r
595 p_guid[2] = mac.addr[2];
\r
598 /* Serial Number */
\r
599 p_guid[5] = (uint8_t)(low24 >> 16);
\r
600 p_guid[6] = (uint8_t)(low24 >> 8);
\r
601 p_guid[7] = (uint8_t)low24;
\r
608 * The port GUID, in network byte order, for which to generate a
\r
612 * Pointer to a mac address in which to store the results.
\r
616 * The MAC address was successfully converted.
\r
619 * The port GUID provided was not a known GUID format.
\r
622 * The algorithm to convert portGuid to MAC address is as
\r
629 /****f* IPOIB/ipoib_is_voltaire_router_gid
\r
631 * ipoib_is_voltaire_router_gid
\r
634 * Checks whether the GID belongs to Voltaire IP router
\r
640 ipoib_is_voltaire_router_gid(
\r
641 IN const ib_gid_t *p_gid )
\r
643 static const uint8_t VOLTAIRE_GUID_PREFIX[] = {0, 0x08, 0xf1, 0, 0x1};
\r
645 return !cl_memcmp( &p_gid->unicast.interface_id, VOLTAIRE_GUID_PREFIX,
\r
646 sizeof(VOLTAIRE_GUID_PREFIX) );
\r
654 #endif /* _IPOIB_XFR_MGR_H_ */
\r