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 
55 BEGIN_C_DECLS
56 /*
57    Forward references.
58 */
59 struct osm_physp;
60 struct osm_port;
61 struct osm_subn;
62 struct osm_node;
63 struct 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 */
84 typedef 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 */
153 typedef 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 */
187 void 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 */
205 ib_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 */
223 void 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 */
241 static inline uint16_t
osm_pkey_tbl_get_num_blocks(IN const osm_pkey_tbl_t * p_pkey_tbl)242 osm_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 */
osm_pkey_tbl_block_get(const osm_pkey_tbl_t * p_pkey_tbl,uint16_t block)267 static 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 */
osm_pkey_tbl_new_block_get(const osm_pkey_tbl_t * p_pkey_tbl,uint16_t block)299 static 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  */
317 void 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 */
329 cl_status_t
330 osm_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 */
358 ib_api_status_t
359 osm_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 */
393 boolean_t
394 osm_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 */
422 void 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 */
442 ib_api_status_t
443 osm_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 */
473 ib_api_status_t
474 osm_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 */
507 boolean_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 */
543 ib_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 */
591 boolean_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 */
643 boolean_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 */
676 boolean_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 */
706 void 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 *********/
729 END_C_DECLS
730 #endif				/* _OSM_PKEY_H_ */
731