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