Example #1
0
boolean_t osm_physp_share_pkey(IN osm_log_t * p_log,
			       IN const osm_physp_t * p_physp_1,
			       IN const osm_physp_t * p_physp_2,
			       IN boolean_t allow_both_pkeys)
{
	const osm_pkey_tbl_t *pkey_tbl1, *pkey_tbl2;

	if (p_physp_1 == p_physp_2)
		return TRUE;

	pkey_tbl1 = osm_physp_get_pkey_tbl(p_physp_1);
	pkey_tbl2 = osm_physp_get_pkey_tbl(p_physp_2);

	/*
	   The spec: 10.9.2 does not require each phys port to have PKey Table.
	   So actually if it does not, we need to use the default port instead.

	   HACK: meanwhile we will ignore the check
	 */
	if (cl_is_map_empty(&pkey_tbl1->keys)
	    || cl_is_map_empty(&pkey_tbl2->keys))
		return TRUE;

	return
	    !ib_pkey_is_invalid(osm_physp_find_common_pkey
				(p_physp_1, p_physp_2, allow_both_pkeys));
}
Example #2
0
boolean_t osm_physp_share_this_pkey(IN const osm_physp_t * p_physp1,
				    IN const osm_physp_t * p_physp2,
				    IN ib_net16_t pkey,
				    IN boolean_t allow_both_pkeys)
{
	ib_net16_t *pkey1, *pkey2;
	ib_net16_t full_pkey, limited_pkey;

	if (allow_both_pkeys) {
		full_pkey = pkey | IB_PKEY_TYPE_MASK;
		limited_pkey = pkey & ~IB_PKEY_TYPE_MASK;
		pkey1 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp1))->keys,
				   full_pkey);
		if (!pkey1)
			pkey1 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp1))->keys,
					   limited_pkey);
		pkey2 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp2))->keys,
				   full_pkey);
		if (!pkey2)
			pkey2 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp2))->keys,
					   limited_pkey);
	} else {
		pkey1 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp1))->keys,
				   ib_pkey_get_base(pkey));
		pkey2 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp2))->keys,
				   ib_pkey_get_base(pkey));
	}
	return (pkey1 && pkey2 && match_pkey(pkey1, pkey2));
}
static void sa_pkey_create(IN osm_sa_t * sa, IN osm_physp_t * p_physp,
			   IN osm_pkey_search_ctxt_t * p_ctxt,
			   IN uint16_t block)
{
	osm_pkey_item_t *p_rec_item;
	uint16_t lid;
	ib_pkey_table_t *tbl;

	OSM_LOG_ENTER(sa->p_log);

	p_rec_item = malloc(sizeof(*p_rec_item));
	if (p_rec_item == NULL) {
		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4602: "
			"rec_item alloc failed\n");
		goto Exit;
	}

	if (p_physp->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH)
		lid = p_physp->port_info.base_lid;
	else
		lid = osm_node_get_base_lid(p_physp->p_node, 0);

	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
		"New P_Key table for: port 0x%016" PRIx64
		", lid %u, port %u Block:%u\n",
		cl_ntoh64(osm_physp_get_port_guid(p_physp)),
		cl_ntoh16(lid), osm_physp_get_port_num(p_physp), block);

	memset(p_rec_item, 0, sizeof(*p_rec_item));

	p_rec_item->rec.lid = lid;
	p_rec_item->rec.block_num = block;
	p_rec_item->rec.port_num = osm_physp_get_port_num(p_physp);
	/* FIXME: There are ninf.PartitionCap or swinf.PartitionEnforcementCap
	   pkey entries so everything in that range is a valid block number
	   even if opensm is not using it. Return 0. However things outside
	   that range should return no entries.. Not sure how to figure that
	   here? The range of pkey_tbl can be less than the cap, so
	   this falsely triggers. */
	tbl = osm_pkey_tbl_block_get(osm_physp_get_pkey_tbl(p_physp), block);
	if (tbl)
		p_rec_item->rec.pkey_tbl = *tbl;

	cl_qlist_insert_tail(p_ctxt->p_list, &p_rec_item->list_item);

Exit:
	OSM_LOG_EXIT(sa->p_log);
}
Example #4
0
/** ===========================================================================
 */
static void extract_host_port(osm_port_t *p_port, uint64_t *p_pkey_base_offset,
			      uint64_t *p_pkey_offset, uint64_t *p_port_offset,
			      uint64_t *p_link_offset,
			      struct ssa_db_extract *p_ssa_db)
{
	const osm_pkey_tbl_t *p_pkey_tbl;
	const ib_pkey_table_t *block;
	osm_physp_t *p_physp = p_port->p_physp;
	ib_net16_t pkey;
	uint16_t block_index, pkey_idx;

	p_pkey_tbl = osm_physp_get_pkey_tbl(p_physp);
	for (block_index = 0; block_index < p_pkey_tbl->used_blocks;
	     block_index++) {
		block = osm_pkey_tbl_block_get(p_pkey_tbl, block_index);
		if (!block)
			continue;
		for (pkey_idx = 0; pkey_idx < IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
		     pkey_idx++) {
			pkey = block->pkey_entry[pkey_idx];
			if (ib_pkey_is_invalid(pkey))
				continue;

			p_ssa_db->p_pkey_tbl[*p_pkey_base_offset + *p_pkey_offset] = pkey;
			*p_pkey_offset = *p_pkey_offset + 1;
		}
	}

	if (*p_pkey_offset >= SSA_EXTRACT_PKEYS_MAX) {
		ssa_log_err(SSA_LOG_DEFAULT,
			    "ERROR - truncating number of pkeys "
			    "from %d to %d (maximum) for LID %u\n",
			    *p_pkey_offset, SSA_EXTRACT_PKEYS_MAX - 1,
			    ntohs(osm_physp_get_base_lid(p_physp)));
		*p_pkey_offset = SSA_EXTRACT_PKEYS_MAX - 1;
	}

	extract_port(p_physp, NULL, htonll(*p_pkey_base_offset * sizeof(pkey)),
		     htons(*p_pkey_offset * sizeof(pkey)),
		     p_port_offset, p_ssa_db);

	if (!osm_physp_get_remote(p_physp))
		return;

	extract_link(p_physp, NULL, p_link_offset, p_ssa_db);
}
static void
__osm_sa_pkey_create(IN osm_sa_t * sa,
		     IN osm_physp_t * const p_physp,
		     IN osm_pkey_search_ctxt_t * const p_ctxt,
		     IN uint16_t block)
{
	osm_pkey_item_t *p_rec_item;
	uint16_t lid;
	ib_api_status_t status = IB_SUCCESS;

	OSM_LOG_ENTER(sa->p_log);

	p_rec_item = malloc(sizeof(*p_rec_item));
	if (p_rec_item == NULL) {
		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4602: "
			"rec_item alloc failed\n");
		status = IB_INSUFFICIENT_RESOURCES;
		goto Exit;
	}

	if (p_physp->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH)
		lid = p_physp->port_info.base_lid;
	else
		lid = osm_node_get_base_lid(p_physp->p_node, 0);

	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
		"New P_Key table for: port 0x%016" PRIx64
		", lid %u, port %u Block:%u\n",
		cl_ntoh64(osm_physp_get_port_guid(p_physp)),
		cl_ntoh16(lid), osm_physp_get_port_num(p_physp), block);

	memset(p_rec_item, 0, sizeof(*p_rec_item));

	p_rec_item->rec.lid = lid;
	p_rec_item->rec.block_num = block;
	p_rec_item->rec.port_num = osm_physp_get_port_num(p_physp);
	p_rec_item->rec.pkey_tbl =
	    *(osm_pkey_tbl_block_get(osm_physp_get_pkey_tbl(p_physp), block));

	cl_qlist_insert_tail(p_ctxt->p_list, &p_rec_item->list_item);

Exit:
	OSM_LOG_EXIT(sa->p_log);
}
static void sa_pkey_check_physp(IN osm_sa_t * sa, IN osm_physp_t * p_physp,
				osm_pkey_search_ctxt_t * p_ctxt)
{
	ib_net64_t comp_mask = p_ctxt->comp_mask;
	uint16_t block, num_blocks;

	OSM_LOG_ENTER(sa->p_log);

	/* we got here with the phys port - all is left is to get the right block */
	if (comp_mask & IB_PKEY_COMPMASK_BLOCK) {
		sa_pkey_create(sa, p_physp, p_ctxt, p_ctxt->block_num);
	} else {
		num_blocks =
		    osm_pkey_tbl_get_num_blocks(osm_physp_get_pkey_tbl
						(p_physp));
		for (block = 0; block < num_blocks; block++)
			sa_pkey_create(sa, p_physp, p_ctxt, block);
	}

	OSM_LOG_EXIT(sa->p_log);
}
Example #7
0
boolean_t osm_physp_has_pkey(IN osm_log_t * p_log, IN ib_net16_t pkey,
			     IN const osm_physp_t * p_physp)
{
	ib_net16_t *p_pkey, pkey_base;
	const osm_pkey_tbl_t *pkey_tbl;
	boolean_t res = FALSE;

	OSM_LOG_ENTER(p_log);

	OSM_LOG(p_log, OSM_LOG_DEBUG,
		"Search for PKey: 0x%04x\n", cl_ntoh16(pkey));

	/* if the pkey given is an invalid pkey - return TRUE. */
	if (ib_pkey_is_invalid(pkey)) {
		OSM_LOG(p_log, OSM_LOG_DEBUG,
			"Given invalid PKey - we treat it loosely and allow it\n");
		res = TRUE;
		goto Exit;
	}

	pkey_base = ib_pkey_get_base(pkey);

	pkey_tbl = osm_physp_get_pkey_tbl(p_physp);

	p_pkey = cl_map_get(&pkey_tbl->keys, pkey_base);
	if (p_pkey) {
		res = TRUE;
		OSM_LOG(p_log, OSM_LOG_DEBUG,
			"PKey 0x%04x was found\n", cl_ntoh16(pkey));
	} else
		OSM_LOG(p_log, OSM_LOG_DEBUG,
			"PKey 0x%04x was not found\n", cl_ntoh16(pkey));

Exit:
	OSM_LOG_EXIT(p_log);
	return res;
}
Example #8
0
/** ===========================================================================
 */
static int
extract_alloc_tbls(osm_subn_t *p_subn, struct ssa_db_extract *p_ssa_db)
{
	const osm_pkey_tbl_t *p_pkey_tbl;
	osm_switch_t *p_sw;
	osm_port_t *p_port;
	uint64_t links, ports, lft_blocks;
	uint32_t guids, nodes, lft_tops;
	uint32_t switch_ports_num = 0;
	uint32_t pkey_cnt = 0;
	uint16_t lids;

	nodes = (uint32_t) cl_qmap_count(&p_subn->node_guid_tbl);
	if (!p_ssa_db->p_node_tbl) {
		p_ssa_db->p_node_tbl = (struct smdb_node *)
		    malloc(sizeof(*p_ssa_db->p_node_tbl) * nodes);
		if (!p_ssa_db->p_node_tbl) {
			ssa_log(SSA_LOG_DEFAULT,
				"ERROR - unable to allocate nodes table\n");
			goto err0;
		}
	}

	lft_tops = (uint32_t) cl_qmap_count(&p_subn->sw_guid_tbl);
	if (!ssa_db->p_lft_db->p_db_lft_top_tbl) {
		ssa_db->p_lft_db->p_db_lft_top_tbl = (struct smdb_lft_top *)
			malloc(sizeof(*ssa_db->p_lft_db->p_db_lft_top_tbl) *
			       lft_tops);
		if (!ssa_db->p_lft_db->p_db_lft_top_tbl) {
			ssa_log(SSA_LOG_DEFAULT,
				"ERROR - unable to allocate LFT tops table\n");
			goto err1;
		}
	}

	lids = (uint16_t) cl_ptr_vector_get_size(&p_subn->port_lid_tbl);

	lft_blocks = ((lids % IB_SMP_DATA_SIZE) ?
	    (lids / IB_SMP_DATA_SIZE + 1) : (lids / IB_SMP_DATA_SIZE));
	lft_blocks = (uint64_t) lft_tops * lft_blocks * (1 << p_ssa_db->lmc);
	if (!ssa_db->p_lft_db->p_db_lft_block_tbl) {
		ssa_db->p_lft_db->p_db_lft_block_tbl =
		    (struct smdb_lft_block *)
			malloc(sizeof(*ssa_db->p_lft_db->p_db_lft_block_tbl) *
			       lft_blocks);
		if (!ssa_db->p_lft_db->p_db_lft_block_tbl) {
			ssa_log(SSA_LOG_DEFAULT,
				"ERROR - unable to allocate LFT blocks table\n");
			goto err2;
		}
	}

	guids = (uint32_t) cl_qmap_count(&p_subn->port_guid_tbl);
	if (!p_ssa_db->p_guid_to_lid_tbl) {
		p_ssa_db->p_guid_to_lid_tbl = (struct smdb_guid2lid *)
				malloc(sizeof(*p_ssa_db->p_guid_to_lid_tbl) *
				       guids);
		if (!p_ssa_db->p_guid_to_lid_tbl) {
			ssa_log(SSA_LOG_DEFAULT,
				"ERROR - unable to allocate GUID to LID table\n");
			goto err3;
		}
	}

	for (p_sw = (osm_switch_t *)cl_qmap_head(&p_subn->sw_guid_tbl);
	     p_sw != (osm_switch_t *)cl_qmap_end(&p_subn->sw_guid_tbl);
	     p_sw = (osm_switch_t *)cl_qmap_next(&p_sw->map_item))
			switch_ports_num += p_sw->num_ports;

	links = guids + switch_ports_num;
	if (!p_ssa_db->p_link_tbl) {
		p_ssa_db->p_link_tbl = (struct smdb_link *)
				malloc(sizeof(*p_ssa_db->p_link_tbl) * links);
		if (!p_ssa_db->p_link_tbl) {
			ssa_log(SSA_LOG_DEFAULT,
				"ERROR - unable to allocate links table\n");
			goto err4;
		}
	}

	ports = links;
	if (!p_ssa_db->p_port_tbl) {
		p_ssa_db->p_port_tbl = (struct smdb_port *)
				malloc(sizeof(*p_ssa_db->p_port_tbl) * ports);
		if (!p_ssa_db->p_port_tbl) {
			ssa_log(SSA_LOG_DEFAULT,
				"ERROR - unable to allocate ports table\n");
			goto err5;
		}
	}

	for (p_port = (osm_port_t *)cl_qmap_head(&p_subn->port_guid_tbl);
	     p_port != (osm_port_t *)cl_qmap_end(&p_subn->port_guid_tbl);
	     p_port = (osm_port_t *)cl_qmap_next(&p_port->map_item)) {
		p_pkey_tbl = osm_physp_get_pkey_tbl(p_port->p_physp);
		pkey_cnt += (uint32_t)
		    cl_map_count((const cl_map_t *) &p_pkey_tbl->keys);
	}

	if (!p_ssa_db->p_pkey_tbl) {
		p_ssa_db->p_pkey_tbl = (uint16_t *)
		    malloc(sizeof(*p_ssa_db->p_pkey_tbl) * pkey_cnt);
		if (!p_ssa_db->p_pkey_tbl) {
			ssa_log(SSA_LOG_DEFAULT,
				"ERROR - unable to allocate pkeys table\n");
			goto err6;
		}
	}
	p_ssa_db->pkey_tbl_rec_num = pkey_cnt;

	return 0;

err6:
	free(p_ssa_db->p_port_tbl);
err5:
	free(p_ssa_db->p_link_tbl);
err4:
	free(p_ssa_db->p_guid_to_lid_tbl);
err3:
	free(ssa_db->p_lft_db->p_db_lft_block_tbl);
err2:
	free(ssa_db->p_lft_db->p_db_lft_top_tbl);
err1:
	free(p_ssa_db->p_node_tbl);
err0:
	return -1;
}
Example #9
0
/** ===========================================================================
 */
static void extract_switch_port(osm_port_t *p_port, uint64_t *p_pkey_base_offset,
				uint64_t *p_pkey_offset, uint64_t *p_port_offset,
				uint64_t *p_link_offset,
				struct ssa_db_extract *p_ssa_db)
{
	osm_node_t *p_node = p_port->p_physp->p_node;
	const osm_pkey_tbl_t *p_pkey_tbl;
	const ib_pkey_table_t *block;
	osm_physp_t *p_physp;
	uint32_t i;
	ib_net16_t pkey;
	uint16_t lid_ho, block_index, pkey_idx;

	for (i = 0; i < p_node->physp_tbl_size; i++) {
		p_physp = osm_node_get_physp_ptr(p_node, i);
		if (!p_physp)
			continue;

		/* TODO: add filtering for down ports */

		if (i == 0) {
			lid_ho = ntohs(osm_physp_get_base_lid(p_physp));

			p_pkey_tbl = osm_physp_get_pkey_tbl(p_physp);
			for (block_index = 0; block_index < p_pkey_tbl->used_blocks;
			     block_index++) {
				block = osm_pkey_tbl_block_get(p_pkey_tbl, block_index);
				if (!block)
					continue;
				for (pkey_idx = 0; pkey_idx < IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
				     pkey_idx++) {
					pkey = block->pkey_entry[pkey_idx];
					if (ib_pkey_is_invalid(pkey))
						continue;

					p_ssa_db->p_pkey_tbl[*p_pkey_base_offset + *p_pkey_offset] = pkey;
					*p_pkey_offset = *p_pkey_offset + 1;
				}
			}

			if (*p_pkey_offset >= SSA_EXTRACT_PKEYS_MAX) {
				ssa_log_err(SSA_LOG_DEFAULT,
					    "ERROR - truncating number of pkeys "
					    "from %d to %d (maximum) for LID %u\n",
					    *p_pkey_offset, SSA_EXTRACT_PKEYS_MAX - 1, lid_ho);
				*p_pkey_offset = SSA_EXTRACT_PKEYS_MAX - 1;
			}

			extract_port(p_physp, &lid_ho,
				     htonll(*p_pkey_base_offset * sizeof(pkey)),
				     htons(*p_pkey_offset * sizeof(pkey)),
				     p_port_offset, p_ssa_db);
		} else {
			extract_port(p_physp, &lid_ho, 0, 0, p_port_offset,
				     p_ssa_db);
		}

		if (!osm_physp_get_remote(p_physp))
			continue;

		extract_link(p_physp, &lid_ho, p_link_offset, p_ssa_db);
	}
}
Example #10
0
/** ===========================================================================
 */
static void dump_port_qos(osm_port_t *p_port)
{
#ifdef SSA_PLUGIN_VERBOSE_LOGGING
	const osm_pkey_tbl_t *p_pkey_tbl;
	const ib_pkey_table_t *block;
	//char *header_line =    "#in out : 0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15";
	//char *separator_line = "#--------------------------------------------------------";
	//ib_slvl_table_t *p_tbl;
	ib_net16_t pkey;
	uint16_t block_index, max_pkeys, pkey_idx;
	//uint8_t out_port, in_port, num_ports;
	//uint8_t n;

//	ssa_log(SSA_LOG_VERBOSE, "\t\t\tSLVL tables\n");
//	ssa_log(SSA_LOG_VERBOSE, "%s\n", header_line);
//	ssa_log(SSA_LOG_VERBOSE, "%s\n", separator_line);
//
//	out_port = p_port->p_physp->port_num;
//	num_ports = p_port->p_physp->p_node->node_info.num_ports;
//	if (osm_node_get_type(p_port->p_physp->p_node) ==
//		IB_NODE_TYPE_SWITCH) {
//		/* no need to print SL2VL table for port that is down */
//		/* TODO: not sure if it is needed */
//		/*if (!p_port->p_physp->p_remote_physp)
//			continue; */
//
//		for (in_port = 0; in_port <= num_ports; in_port++) {
//			p_tbl = osm_physp_get_slvl_tbl(p_port->p_physp,
//						       in_port);
//			for (i = 0, n = 0; i < 16; i++)
//				n += sprintf(buffer + n, " %-2d",
//					ib_slvl_table_get(p_tbl, i));
//				ssa_log(SSA_LOG_VERBOSE, "%-3d %-3d :%s\n",
//					in_port, out_port, buffer);
//		}
//	} else {
//		p_tbl = osm_physp_get_slvl_tbl(p_port->p_physp, 0);
//		for (i = 0, n = 0; i < 16; i++)
//			n += sprintf(buffer + n, " %-2d",
//					ib_slvl_table_get(p_tbl, i));
//			ssa_log(SSA_LOG_VERBOSE, "%-3d %-3d :%s\n", out_port,
//				out_port, buffer);
//	}
//
	max_pkeys = ntohs(p_port->p_node->node_info.partition_cap);
	ssa_log(SSA_LOG_VERBOSE, "PartitionCap %u\n", max_pkeys);
	p_pkey_tbl = osm_physp_get_pkey_tbl(p_port->p_physp);
	ssa_log(SSA_LOG_VERBOSE, "PKey Table %u used blocks\n",
		p_pkey_tbl->used_blocks);
	for (block_index = 0; block_index < p_pkey_tbl->used_blocks;
	     block_index++) {
		block = osm_pkey_tbl_new_block_get(p_pkey_tbl, block_index);
		if (!block)
			continue;
		for (pkey_idx = 0; pkey_idx < IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
		     pkey_idx++) {
			pkey = block->pkey_entry[pkey_idx];
			if (ib_pkey_is_invalid(pkey))
				continue;
			ssa_log(SSA_LOG_VERBOSE, "PKey 0x%04x at block %u "
				"index %u\n", ntohs(pkey), block_index,
				pkey_idx);
		}
	}
#else
	(void)(p_port);
#endif
}
Example #11
0
ib_net16_t osm_physp_find_common_pkey(IN const osm_physp_t * p_physp1,
				      IN const osm_physp_t * p_physp2,
				      IN boolean_t allow_both_pkeys)
{
	ib_net16_t *pkey1, *pkey2;
	uint64_t pkey1_base, pkey2_base;
	const osm_pkey_tbl_t *pkey_tbl1, *pkey_tbl2;
	cl_map_iterator_t map_iter1, map_iter2;

	pkey_tbl1 = osm_physp_get_pkey_tbl(p_physp1);
	pkey_tbl2 = osm_physp_get_pkey_tbl(p_physp2);

	map_iter1 = cl_map_head(&pkey_tbl1->keys);
	map_iter2 = cl_map_head(&pkey_tbl2->keys);

	/* we rely on the fact the map are sorted by pkey */
	while ((map_iter1 != cl_map_end(&pkey_tbl1->keys)) &&
	       (map_iter2 != cl_map_end(&pkey_tbl2->keys))) {
		pkey1 = (ib_net16_t *) cl_map_obj(map_iter1);
		pkey2 = (ib_net16_t *) cl_map_obj(map_iter2);

		if (match_pkey(pkey1, pkey2))
			return *pkey1;

		/* advance the lower value if they are not equal */
		pkey1_base = cl_map_key(map_iter1);
		pkey2_base = cl_map_key(map_iter2);
		if (pkey2_base == pkey1_base) {
			map_iter1 = cl_map_next(map_iter1);
			map_iter2 = cl_map_next(map_iter2);
		} else if (pkey2_base < pkey1_base)
			map_iter2 = cl_map_next(map_iter2);
		else
			map_iter1 = cl_map_next(map_iter1);
	}

	if (!allow_both_pkeys)
		return 0;

	/*
	   When using allow_both_pkeys, the keys in pkey tables are the
	   pkey value including membership bit.
	   Therefore, in order to complete the search, we also need to
	   compare port\s 1 full pkeys with port 2 limited pkeys, and
	   port 2 full pkeys with port 1 full pkeys.
	*/

	map_iter1 = cl_map_head(&pkey_tbl1->keys);
	map_iter2 = cl_map_head(&pkey_tbl2->keys);

	/* comparing pkey_tbl1 full with pkey_tbl2 limited */
	while ((map_iter1 != cl_map_end(&pkey_tbl1->keys)) &&
	       (map_iter2 != cl_map_end(&pkey_tbl2->keys))) {
		pkey1 = (ib_net16_t *) cl_map_obj(map_iter1);
		pkey2 = (ib_net16_t *) cl_map_obj(map_iter2);

		if (!ib_pkey_is_full_member(*pkey1)) {
			map_iter1 = cl_map_next(map_iter1);
			continue;
		}
		if (ib_pkey_is_full_member(*pkey2)) {
			map_iter2 = cl_map_next(map_iter2);
			continue;
		}

		if (match_pkey(pkey1, pkey2))
			return *pkey1;

		/* advance the lower value if they are not equal */
		pkey1_base = ib_pkey_get_base(cl_map_key(map_iter1));
		pkey2_base = ib_pkey_get_base(cl_map_key(map_iter2));
		if (pkey2_base == pkey1_base) {
			map_iter1 = cl_map_next(map_iter1);
			map_iter2 = cl_map_next(map_iter2);
		} else if (pkey2_base < pkey1_base)
			map_iter2 = cl_map_next(map_iter2);
		else
			map_iter1 = cl_map_next(map_iter1);
	}

	map_iter1 = cl_map_head(&pkey_tbl1->keys);
	map_iter2 = cl_map_head(&pkey_tbl2->keys);

	/* comparing pkey_tbl1 limited with pkey_tbl2 full */
	while ((map_iter1 != cl_map_end(&pkey_tbl1->keys)) &&
	       (map_iter2 != cl_map_end(&pkey_tbl2->keys))) {
		pkey1 = (ib_net16_t *) cl_map_obj(map_iter1);
		pkey2 = (ib_net16_t *) cl_map_obj(map_iter2);

		if (ib_pkey_is_full_member(*pkey1)) {
			map_iter1 = cl_map_next(map_iter1);
			continue;
		}
		if (!ib_pkey_is_full_member(*pkey2)) {
			map_iter2 = cl_map_next(map_iter2);
			continue;
		}

		if (match_pkey(pkey1, pkey2))
			return *pkey1;

		/* advance the lower value if they are not equal */
		pkey1_base = ib_pkey_get_base(cl_map_key(map_iter1));
		pkey2_base = ib_pkey_get_base(cl_map_key(map_iter2));
		if (pkey2_base == pkey1_base) {
			map_iter1 = cl_map_next(map_iter1);
			map_iter2 = cl_map_next(map_iter2);
		} else if (pkey2_base < pkey1_base)
			map_iter2 = cl_map_next(map_iter2);
		else
			map_iter1 = cl_map_next(map_iter1);
	}

	return 0;
}