1/*
2 * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5 *
6 * This software is available to you under a choice of one of two
7 * licenses.  You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
11 *
12 *     Redistribution and use in source and binary forms, with or
13 *     without modification, are permitted provided that the following
14 *     conditions are met:
15 *
16 *      - Redistributions of source code must retain the above
17 *        copyright notice, this list of conditions and the following
18 *        disclaimer.
19 *
20 *      - Redistributions in binary form must reproduce the above
21 *        copyright notice, this list of conditions and the following
22 *        disclaimer in the documentation and/or other materials
23 *        provided with the distribution.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 * SOFTWARE.
33 *
34 */
35
36#ifndef _OSM_PKEY_H_
37#define _OSM_PKEY_H_
38
39#include <iba/ib_types.h>
40#include <complib/cl_dispatcher.h>
41#include <complib/cl_map.h>
42#include <opensm/osm_base.h>
43#include <opensm/osm_log.h>
44#include <opensm/osm_msgdef.h>
45
46#ifdef __cplusplus
47#  define BEGIN_C_DECLS extern "C" {
48#  define END_C_DECLS   }
49#else				/* !__cplusplus */
50#  define BEGIN_C_DECLS
51#  define END_C_DECLS
52#endif				/* __cplusplus */
53
54BEGIN_C_DECLS
55/*
56   Forward references.
57*/
58struct osm_physp;
59struct osm_port;
60struct osm_subn;
61struct osm_node;
62struct osm_physp;
63
64/*
65 * Abstract:
66 * 	Declaration of pkey manipulation functions.
67 */
68
69/****s* OpenSM: osm_pkey_tbl_t
70* NAME
71*	osm_pkey_tbl_t
72*
73* DESCRIPTION
74*	This object represents a pkey table. The need for a special object
75*  is required to optimize search performance of a PKey in the IB standard
76*  non sorted table.
77*
78*	The osm_pkey_tbl_t object should be treated as opaque and should
79*	be manipulated only through the provided functions.
80*
81* SYNOPSIS
82*/
83typedef struct osm_pkeybl {
84	cl_ptr_vector_t blocks;
85	cl_ptr_vector_t new_blocks;
86	cl_map_t keys;
87	cl_qlist_t pending;
88	uint16_t used_blocks;
89	uint16_t max_blocks;
90} osm_pkey_tbl_t;
91/*
92* FIELDS
93*	blocks
94*		The IBA defined blocks of pkey values, updated from the subnet
95*
96*	new_blocks
97*		The blocks of pkey values, will be used for updates by SM
98*
99*	keys
100*		A set holding all keys
101*
102*	pending
103*		A list of osm_pending_pkey structs that is temporarily set by
104*		the pkey mgr and used during pkey mgr algorithm only
105*
106*	used_blocks
107*		Tracks the number of blocks having non-zero pkeys
108*
109*	max_blocks
110*		The maximal number of blocks this partition table might hold
111*		this value is based on node_info (for port 0 or CA) or
112*		switch_info updated on receiving the node_info or switch_info
113*		GetResp
114*
115* NOTES
116* 'blocks' vector should be used to store pkey values obtained from
117* the port and SM pkey manager should not change it directly, for this
118* purpose 'new_blocks' should be used.
119*
120* The only pkey values stored in 'blocks' vector will be mapped with
121* 'keys' map
122*
123*********/
124
125/****s* OpenSM: osm_pending_pkey_t
126* NAME
127*	osm_pending_pkey_t
128*
129* DESCRIPTION
130*	This objects stores temporary information on pkeys, their target block,
131*  and index during the pkey manager operation
132*
133* SYNOPSIS
134*/
135typedef struct osm_pending_pkey {
136	cl_list_item_t list_item;
137	uint16_t pkey;
138	uint16_t block;
139	uint8_t index;
140	boolean_t is_new;
141} osm_pending_pkey_t;
142/*
143* FIELDS
144*	pkey
145*		The actual P_Key
146*
147*	block
148*		The block index based on the previous table extracted from the
149*		device
150*
151*	index
152*		The index of the pkey within the block
153*
154*	is_new
155*		TRUE for new P_Keys such that the block and index are invalid
156*		in that case
157*
158*********/
159
160/****f* OpenSM: osm_pkey_tbl_construct
161* NAME
162*  osm_pkey_tbl_construct
163*
164* DESCRIPTION
165*  Constructs the PKey table object
166*
167* SYNOPSIS
168*/
169void osm_pkey_tbl_construct(IN osm_pkey_tbl_t * p_pkey_tbl);
170/*
171*  p_pkey_tbl
172*     [in] Pointer to osm_pkey_tbl_t object.
173*
174* NOTES
175*
176*********/
177
178/****f* OpenSM: osm_pkey_tbl_init
179* NAME
180*  osm_pkey_tbl_init
181*
182* DESCRIPTION
183*  Inits the PKey table object
184*
185* SYNOPSIS
186*/
187ib_api_status_t osm_pkey_tbl_init(IN osm_pkey_tbl_t * p_pkey_tbl);
188/*
189*  p_pkey_tbl
190*     [in] Pointer to osm_pkey_tbl_t object.
191*
192* NOTES
193*
194*********/
195
196/****f* OpenSM: osm_pkey_tbl_destroy
197* NAME
198*  osm_pkey_tbl_destroy
199*
200* DESCRIPTION
201*  Destroys the PKey table object
202*
203* SYNOPSIS
204*/
205void osm_pkey_tbl_destroy(IN osm_pkey_tbl_t * p_pkey_tbl);
206/*
207*  p_pkey_tbl
208*     [in] Pointer to osm_pkey_tbl_t object.
209*
210* NOTES
211*
212*********/
213
214/****f* OpenSM: osm_pkey_get_num_blocks
215* NAME
216*  osm_pkey_get_num_blocks
217*
218* DESCRIPTION
219*  Obtain the number of blocks in IB PKey table
220*
221* SYNOPSIS
222*/
223static inline uint16_t
224osm_pkey_tbl_get_num_blocks(IN const osm_pkey_tbl_t * p_pkey_tbl)
225{
226	return ((uint16_t) (cl_ptr_vector_get_size(&p_pkey_tbl->blocks)));
227}
228
229/*
230*  p_pkey_tbl
231*     [in] Pointer to osm_pkey_tbl_t object.
232*
233* RETURN VALUES
234*  The IB pkey table of that pkey table element
235*
236* NOTES
237*
238*********/
239
240/****f* OpenSM: osm_pkey_tbl_block_get
241* NAME
242*  osm_pkey_tbl_block_get
243*
244* DESCRIPTION
245*  Obtain the pointer to the IB PKey table block stored in the object
246*
247* SYNOPSIS
248*/
249static inline ib_pkey_table_t *osm_pkey_tbl_block_get(const osm_pkey_tbl_t *
250						      p_pkey_tbl,
251						      uint16_t block)
252{
253	return ((block < cl_ptr_vector_get_size(&p_pkey_tbl->blocks)) ?
254		cl_ptr_vector_get(&p_pkey_tbl->blocks, block) : NULL);
255};
256
257/*
258*  p_pkey_tbl
259*     [in] Pointer to osm_pkey_tbl_t object.
260*
261*  block
262*     [in] The lock number to get
263*
264* RETURN VALUES
265*  The IB pkey table of that pkey table element
266*
267* NOTES
268*
269*********/
270
271/****f* OpenSM: osm_pkey_tbl_new_block_get
272* NAME
273*  osm_pkey_tbl_new_block_get
274*
275* DESCRIPTION
276*  The same as above but for new block
277*
278* SYNOPSIS
279*/
280static inline ib_pkey_table_t *osm_pkey_tbl_new_block_get(const osm_pkey_tbl_t *
281							  p_pkey_tbl,
282							  uint16_t block)
283{
284	return (block < cl_ptr_vector_get_size(&p_pkey_tbl->new_blocks)) ?
285	    cl_ptr_vector_get(&p_pkey_tbl->new_blocks, block) : NULL;
286};
287
288/****f* OpenSM: osm_pkey_tbl_set_new_entry
289* NAME
290*  osm_pkey_tbl_set_new_entry
291*
292* DESCRIPTION
293*   Stores the given pkey in the "new" blocks array and update
294*   the "map" to show that on the "old" blocks
295*
296* SYNOPSIS
297*/
298ib_api_status_t
299osm_pkey_tbl_set_new_entry(IN osm_pkey_tbl_t * p_pkey_tbl,
300			   IN uint16_t block_idx,
301			   IN uint8_t pkey_idx, IN uint16_t pkey);
302/*
303* p_pkey_tbl
304*   [in] Pointer to the PKey table
305*
306* block_idx
307*   [in] The block index to use
308*
309* pkey_idx
310*   [in] The index within the block
311*
312* pkey
313*   [in] PKey to store
314*
315* RETURN VALUES
316*   IB_SUCCESS if OK
317*   IB_ERROR if failed
318*
319*********/
320
321/****f* OpenSM: osm_pkey_find_next_free_entry
322* NAME
323*  osm_pkey_find_next_free_entry
324*
325* DESCRIPTION
326*  Find the next free entry in the PKey table starting at the given
327*  index and block number. The user should increment pkey_idx before
328*  next call
329*  Inspect the "new" blocks array for empty space.
330*
331* SYNOPSIS
332*/
333boolean_t
334osm_pkey_find_next_free_entry(IN osm_pkey_tbl_t * p_pkey_tbl,
335			      OUT uint16_t * p_block_idx,
336			      OUT uint8_t * p_pkey_idx);
337/*
338* p_pkey_tbl
339*   [in] Pointer to the PKey table
340*
341* p_block_idx
342*   [out] The block index to use
343*
344* p_pkey_idx
345*   [out] The index within the block to use
346*
347* RETURN VALUES
348*   TRUE if found
349*   FALSE if did not find
350*
351*********/
352
353/****f* OpenSM: osm_pkey_tbl_init_new_blocks
354* NAME
355*  osm_pkey_tbl_init_new_blocks
356*
357* DESCRIPTION
358*  Initializes new_blocks vector content (allocate and clear)
359*
360* SYNOPSIS
361*/
362void osm_pkey_tbl_init_new_blocks(const osm_pkey_tbl_t * p_pkey_tbl);
363/*
364*  p_pkey_tbl
365*     [in] Pointer to osm_pkey_tbl_t object.
366*
367* NOTES
368*
369*********/
370
371/****f* OpenSM: osm_pkey_tbl_get_block_and_idx
372* NAME
373*  osm_pkey_tbl_get_block_and_idx
374*
375* DESCRIPTION
376*  Set the block index and pkey index the given
377*  pkey is found in. Return IB_NOT_FOUND if could
378*  not find it, IB_SUCCESS if OK
379*
380* SYNOPSIS
381*/
382ib_api_status_t
383osm_pkey_tbl_get_block_and_idx(IN osm_pkey_tbl_t * p_pkey_tbl,
384			       IN uint16_t * p_pkey,
385			       OUT uint16_t * block_idx,
386			       OUT uint8_t * pkey_index);
387/*
388*  p_pkey_tbl
389*     [in] Pointer to osm_pkey_tbl_t object.
390*
391*  p_pkey
392*     [in] Pointer to the P_Key entry searched
393*
394*  p_block_idx
395*     [out] Pointer to the block index to be updated
396*
397*  p_pkey_idx
398*     [out] Pointer to the pkey index (in the block) to be updated
399*
400* NOTES
401*
402*********/
403
404/****f* OpenSM: osm_pkey_tbl_set
405* NAME
406*  osm_pkey_tbl_set
407*
408* DESCRIPTION
409*  Set the PKey table block provided in the PKey object.
410*
411* SYNOPSIS
412*/
413ib_api_status_t
414osm_pkey_tbl_set(IN osm_pkey_tbl_t * p_pkey_tbl,
415		 IN uint16_t block, IN ib_pkey_table_t * p_tbl);
416/*
417*  p_pkey_tbl
418*     [in] Pointer to osm_pkey_tbl_t object.
419*
420*  block
421*     [in] The block number to set
422*
423*  p_tbl
424*     [in] The IB PKey block to copy to the object
425*
426* RETURN VALUES
427*  IB_SUCCESS or IB_ERROR
428*
429* NOTES
430*
431*********/
432
433/****f* OpenSM: osm_physp_share_this_pkey
434* NAME
435*  osm_physp_share_this_pkey
436*
437* DESCRIPTION
438*  Checks if the given physical ports share the specified pkey.
439*
440* SYNOPSIS
441*/
442boolean_t osm_physp_share_this_pkey(IN const struct osm_physp *const p_physp1,
443				    IN const struct osm_physp *const p_physp2,
444				    IN const ib_net16_t pkey);
445/*
446* PARAMETERS
447*
448*  p_physp1
449*     [in] Pointer to an osm_physp_t object.
450*
451*  p_physp2
452*     [in] Pointer to an osm_physp_t object.
453*
454*  pkey
455*     [in] value of P_Key to check.
456*
457* RETURN VALUES
458*  Returns TRUE if the two ports are matching.
459*  FALSE otherwise.
460*
461* NOTES
462*
463*********/
464
465/****f* OpenSM: osm_physp_find_common_pkey
466* NAME
467*  osm_physp_find_common_pkey
468*
469* DESCRIPTION
470*  Returns first matching P_Key values for specified physical ports.
471*
472* SYNOPSIS
473*/
474ib_net16_t osm_physp_find_common_pkey(IN const struct osm_physp *const
475				      p_physp1,
476				      IN const struct osm_physp *const
477				      p_physp2);
478/*
479* PARAMETERS
480*
481*  p_physp1
482*     [in] Pointer to an osm_physp_t object.
483*
484*  p_physp2
485*     [in] Pointer to an osm_physp_t object.
486*
487* RETURN VALUES
488*  Returns value of first shared P_Key or INVALID P_Key (0x0) if not
489*  found.
490*
491* NOTES
492*
493*********/
494
495/****f* OpenSM: osm_physp_share_pkey
496* NAME
497*  osm_physp_share_pkey
498*
499* DESCRIPTION
500*  Checks if the given physical ports share a pkey.
501*  The meaning P_Key matching:
502*  10.9.3 :
503*   In the following, let M_P_Key(Message P_Key) be the P_Key in the incoming
504*   packet and E_P_Key(Endnode P_Key) be the P_Key it is being compared against
505*   in the packet's destination endnode.
506*
507*    If:
508*    * neither M_P_Key nor E_P_Key are the invalid P_Key
509*    * and the low-order 15 bits of the M_P_Key match the low order 15
510*      bits of the E_P_Key
511*    * and the high order bit(membership type) of both the M_P_Key and
512*      E_P_Key are not both 0 (i.e., both are not Limited members of
513*      the partition)
514*
515*    then the P_Keys are said to match.
516*
517* SYNOPSIS
518*/
519boolean_t osm_physp_share_pkey(IN osm_log_t * p_log,
520			       IN const struct osm_physp *const p_physp_1,
521			       IN const struct osm_physp *const p_physp_2);
522
523/*
524* PARAMETERS
525*  p_log
526*     [in] Pointer to a log object.
527*
528*  p_physp_1
529*     [in] Pointer to an osm_physp_t object.
530*
531*  p_physp_2
532*     [in] Pointer to an osm_physp_t object.
533*
534* RETURN VALUES
535*  Returns TRUE if the 2 physical ports are matching.
536*  FALSE otherwise.
537*
538* NOTES
539*
540*********/
541
542/****f* OpenSM: osm_port_share_pkey
543* NAME
544*  osm_port_share_pkey
545*
546* DESCRIPTION
547*  Checks if the given ports (on their default physical port) share a pkey.
548*  The meaning P_Key matching:
549*  10.9.3 :
550*   In the following, let M_P_Key(Message P_Key) be the P_Key in the incoming
551*   packet and E_P_Key(Endnode P_Key) be the P_Key it is being compared against
552*   in the packet's destination endnode.
553*
554*    If:
555*    * neither M_P_Key nor E_P_Key are the invalid P_Key
556*    * and the low-order 15 bits of the M_P_Key match the low order 15
557*      bits of the E_P_Key
558*    * and the high order bit(membership type) of both the M_P_Key and
559*      E_P_Key are not both 0 (i.e., both are not Limited members of
560*      the partition)
561*
562*    then the P_Keys are said to match.
563*
564* SYNOPSIS
565*/
566boolean_t osm_port_share_pkey(IN osm_log_t * p_log,
567			      IN const struct osm_port *const p_port_1,
568			      IN const struct osm_port *const p_port_2);
569
570/*
571* PARAMETERS
572*  p_log
573*     [in] Pointer to a log object.
574*
575*  p_port_1
576*     [in] Pointer to an osm_port_t object.
577*
578*  p_port_2
579*     [in] Pointer to an osm_port_t object.
580*
581* RETURN VALUES
582*  Returns TRUE if the 2 ports are matching.
583*  FALSE otherwise.
584*
585* NOTES
586*
587*********/
588
589/****f* OpenSM: osm_physp_has_pkey
590* NAME
591*  osm_physp_has_pkey
592*
593* DESCRIPTION
594*  Checks if the given lids and port_numbers share a pkey.
595*  The meaning P_Key matching:
596*  10.9.3 :
597*   In the following, let M_P_Key(Message P_Key) be the P_Key in the incoming
598*   packet and E_P_Key(Endnode P_Key) be the P_Key it is being compared against
599*   in the packet's destination endnode.
600*
601*    If:
602*    * neither M_P_Key nor E_P_Key are the invalid P_Key
603*    * and the low-order 15 bits of the M_P_Key match the low order 15
604*      bits of the E_P_Key
605*    * and the high order bit(membership type) of both the M_P_Key and
606*      E_P_Key are not both 0 (i.e., both are not Limited members of
607*      the partition)
608*
609*    then the P_Keys are said to match.
610*
611* SYNOPSIS
612*/
613boolean_t osm_physp_has_pkey(IN osm_log_t * p_log,
614			     IN const ib_net16_t pkey,
615			     IN const struct osm_physp *const p_physp);
616
617/*
618* PARAMETERS
619*  p_log
620*     [in] Pointer to a log object.
621*
622*  pkey
623*     [in] pkey number to look for.
624*
625*  p_physp
626*     [in] Pointer to osm_physp_t object.
627*
628* RETURN VALUES
629*  Returns TRUE if the p_physp has the pkey given. False otherwise.
630*
631* NOTES
632*
633*********/
634
635END_C_DECLS
636#endif				/* _OSM_PKEY_H_ */
637