Example #1
0
static void lr_rcv_get_port_links(IN osm_sa_t * sa,
				  IN const ib_link_record_t * p_lr,
				  IN const osm_port_t * p_src_port,
				  IN const osm_port_t * p_dest_port,
				  IN const ib_net64_t comp_mask,
				  IN cl_qlist_t * p_list,
				  IN const osm_physp_t * p_req_physp)
{
	const osm_physp_t *p_src_physp;
	const osm_physp_t *p_dest_physp;
	const cl_qmap_t *p_node_tbl;
	osm_node_t *p_node;
	uint8_t port_num;
	uint8_t num_ports;
	uint8_t dest_num_ports;
	uint8_t dest_port_num;

	OSM_LOG_ENTER(sa->p_log);

	if (p_src_port) {
		if (p_dest_port) {
			/*
			   Build an LR for every link connected between both ports.
			   The inner function will discard physp combinations
			   that do not actually connect.  Don't bother screening
			   for that here.
			 */
			num_ports = osm_node_get_num_physp(p_src_port->p_node);
			dest_num_ports =
			    osm_node_get_num_physp(p_dest_port->p_node);
			for (port_num = 1; port_num < num_ports; port_num++) {
				p_src_physp =
				    osm_node_get_physp_ptr(p_src_port->p_node,
							   port_num);
				for (dest_port_num = 1;
				     dest_port_num < dest_num_ports;
				     dest_port_num++) {
					p_dest_physp =
					    osm_node_get_physp_ptr(p_dest_port->
								   p_node,
								   dest_port_num);
					/* both physical ports should be with data */
					if (p_src_physp && p_dest_physp)
						lr_rcv_get_physp_link
						    (sa, p_lr, p_src_physp,
						     p_dest_physp, comp_mask,
						     p_list, p_req_physp);
				}
			}
		} else {
			/*
			   Build an LR for every link connected from the source port.
			 */
			if (comp_mask & IB_LR_COMPMASK_FROM_PORT) {
				port_num = p_lr->from_port_num;
				/* If the port number is out of the range of the p_src_port, then
				   this couldn't be a relevant record. */
				if (port_num <
				    p_src_port->p_node->physp_tbl_size) {
					p_src_physp =
					    osm_node_get_physp_ptr(p_src_port->
								   p_node,
								   port_num);
					if (p_src_physp)
						lr_rcv_get_physp_link
						    (sa, p_lr, p_src_physp,
						     NULL, comp_mask, p_list,
						     p_req_physp);
				}
			} else {
				num_ports =
				    osm_node_get_num_physp(p_src_port->p_node);
				for (port_num = 1; port_num < num_ports;
				     port_num++) {
					p_src_physp =
					    osm_node_get_physp_ptr(p_src_port->
								   p_node,
								   port_num);
					if (p_src_physp)
						lr_rcv_get_physp_link
						    (sa, p_lr, p_src_physp,
						     NULL, comp_mask, p_list,
						     p_req_physp);
				}
			}
		}
	} else {
		if (p_dest_port) {
			/*
			   Build an LR for every link connected to the dest port.
			 */
			if (comp_mask & IB_LR_COMPMASK_TO_PORT) {
				port_num = p_lr->to_port_num;
				/* If the port number is out of the range of the p_dest_port, then
				   this couldn't be a relevant record. */
				if (port_num <
				    p_dest_port->p_node->physp_tbl_size) {
					p_dest_physp =
					    osm_node_get_physp_ptr(p_dest_port->
								   p_node,
								   port_num);
					if (p_dest_physp)
						lr_rcv_get_physp_link
						    (sa, p_lr, NULL,
						     p_dest_physp, comp_mask,
						     p_list, p_req_physp);
				}
			} else {
				num_ports =
				    osm_node_get_num_physp(p_dest_port->p_node);
				for (port_num = 1; port_num < num_ports;
				     port_num++) {
					p_dest_physp =
					    osm_node_get_physp_ptr(p_dest_port->
								   p_node,
								   port_num);
					if (p_dest_physp)
						lr_rcv_get_physp_link
						    (sa, p_lr, NULL,
						     p_dest_physp, comp_mask,
						     p_list, p_req_physp);
				}
			}
		} else {
			/*
			   Process the world (recurse once back into this function).
			 */
			p_node_tbl = &sa->p_subn->node_guid_tbl;
			p_node = (osm_node_t *) cl_qmap_head(p_node_tbl);

			while (p_node != (osm_node_t *) cl_qmap_end(p_node_tbl)) {
				num_ports = osm_node_get_num_physp(p_node);
				for (port_num = 1; port_num < num_ports;
				     port_num++) {
					p_src_physp =
					    osm_node_get_physp_ptr(p_node,
								   port_num);
					if (p_src_physp)
						lr_rcv_get_physp_link
						    (sa, p_lr, p_src_physp,
						     NULL, comp_mask, p_list,
						     p_req_physp);
				}
				p_node = (osm_node_t *) cl_qmap_next(&p_node->
								     map_item);
			}
		}
	}

	OSM_LOG_EXIT(sa->p_log);
}
Example #2
0
/* UPDN callback function */
static int updn_lid_matrices(void *ctx)
{
	updn_t *p_updn = ctx;
	cl_map_item_t *item;
	osm_switch_t *p_sw;
	int ret = 0;

	OSM_LOG_ENTER(&p_updn->p_osm->log);

	for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl);
	     item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl);
	     item = cl_qmap_next(item)) {
		p_sw = (osm_switch_t *)item;
		p_sw->priv = create_updn_node(p_sw);
		if (!p_sw->priv) {
			OSM_LOG(&(p_updn->p_osm->log), OSM_LOG_ERROR, "ERR AA0C: "
				"cannot create updn node\n");
			OSM_LOG_EXIT(&p_updn->p_osm->log);
			return -1;
		}
	}

	/* First setup root nodes */
	p_updn->num_roots = 0;

	if (p_updn->p_osm->subn.opt.root_guid_file) {
		OSM_LOG(&p_updn->p_osm->log, OSM_LOG_DEBUG,
			"UPDN - Fetching root nodes from file \'%s\'\n",
			p_updn->p_osm->subn.opt.root_guid_file);

		ret = parse_node_map(p_updn->p_osm->subn.opt.root_guid_file,
				     rank_root_node, p_updn);
		if (ret) {
			OSM_LOG(&p_updn->p_osm->log, OSM_LOG_ERROR, "ERR AA02: "
				"cannot parse root guids file \'%s\'\n",
				p_updn->p_osm->subn.opt.root_guid_file);
			osm_ucast_mgr_build_lid_matrices(&p_updn->p_osm->sm.ucast_mgr);
			updn_find_root_nodes_by_min_hop(p_updn);
		} else if (p_updn->p_osm->subn.opt.connect_roots &&
			   p_updn->num_roots > 1)
			osm_ucast_mgr_build_lid_matrices(&p_updn->p_osm->sm.ucast_mgr);
	} else {
		osm_ucast_mgr_build_lid_matrices(&p_updn->p_osm->sm.ucast_mgr);
		updn_find_root_nodes_by_min_hop(p_updn);
	}

	if (p_updn->p_osm->subn.opt.ids_guid_file) {
		OSM_LOG(&p_updn->p_osm->log, OSM_LOG_DEBUG,
			"UPDN - update node ids from file \'%s\'\n",
			p_updn->p_osm->subn.opt.ids_guid_file);

		ret = parse_node_map(p_updn->p_osm->subn.opt.ids_guid_file,
				     update_id, p_updn->p_osm);
		if (ret)
			OSM_LOG(&p_updn->p_osm->log, OSM_LOG_ERROR, "ERR AA03: "
				"cannot parse node ids file \'%s\'\n",
				p_updn->p_osm->subn.opt.ids_guid_file);
	}

	/* Only if there are assigned root nodes do the algorithm, otherwise perform do nothing */
	if (p_updn->num_roots) {
		OSM_LOG(&p_updn->p_osm->log, OSM_LOG_DEBUG,
			"activating UPDN algorithm\n");
		ret = updn_build_lid_matrices(p_updn);
	} else {
		OSM_LOG(&p_updn->p_osm->log, OSM_LOG_INFO,
			"disabling UPDN algorithm, no root nodes were found\n");
		ret = -1;
	}

	if (OSM_LOG_IS_ACTIVE_V2(&p_updn->p_osm->log, OSM_LOG_ROUTING))
		osm_dump_qmap_to_file(p_updn->p_osm, "opensm-updn-roots.dump",
				      &p_updn->p_osm->subn.sw_guid_tbl,
				      dump_roots, NULL);

	for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl);
	     item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl);
	     item = cl_qmap_next(item)) {
		p_sw = (osm_switch_t *) item;
		delete_updn_node(p_sw->priv);
	}

	OSM_LOG_EXIT(&p_updn->p_osm->log);
	return ret;
}
static void ucast_cache_validate(osm_ucast_mgr_t * p_mgr)
{
	cache_switch_t *p_cache_sw;
	cache_switch_t *p_remote_cache_sw;
	unsigned port_num;
	unsigned max_ports;
	uint8_t remote_node_type;
	uint16_t lid_ho;
	uint16_t remote_lid_ho;
	osm_switch_t *p_sw;
	osm_switch_t *p_remote_sw;
	osm_node_t *p_node;
	osm_physp_t *p_physp;
	osm_physp_t *p_remote_physp;
	osm_port_t *p_remote_port;
	cl_qmap_t *p_sw_tbl;

	OSM_LOG_ENTER(p_mgr->p_log);
	if (!p_mgr->cache_valid)
		goto Exit;

	/* If there are no switches in the subnet, we are done */
	p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl;
	if (cl_qmap_count(p_sw_tbl) == 0) {
		osm_ucast_cache_invalidate(p_mgr);
		goto Exit;
	}

	/*
	 * Scan all the physical switch ports in the subnet.
	 * If the port need_update flag is on, check whether
	 * it's just some node/port reset or a cached topology
	 * change. Otherwise the cache is invalid.
	 */
	for (p_sw = (osm_switch_t *) cl_qmap_head(p_sw_tbl);
	     p_sw != (osm_switch_t *) cl_qmap_end(p_sw_tbl);
	     p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item)) {

		p_node = p_sw->p_node;

		lid_ho = cl_ntoh16(osm_node_get_base_lid(p_node, 0));
		p_cache_sw = cache_get_sw(p_mgr, lid_ho);

		max_ports = osm_node_get_num_physp(p_node);

		/* skip port 0 */
		for (port_num = 1; port_num < max_ports; port_num++) {

			p_physp = osm_node_get_physp_ptr(p_node, port_num);

			if (!p_physp || !p_physp->p_remote_physp ||
			    !osm_physp_link_exists(p_physp,
						   p_physp->p_remote_physp))
				/* no valid link */
				continue;

			/*
			 * While scanning all the physical ports in the subnet,
			 * mark corresponding leaf switches in the cache.
			 */
			if (p_cache_sw &&
			    !p_cache_sw->dropped &&
			    !cache_sw_is_leaf(p_cache_sw) &&
			    p_physp->p_remote_physp->p_node &&
			    osm_node_get_type(p_physp->p_remote_physp->
					      p_node) != IB_NODE_TYPE_SWITCH)
				cache_sw_set_leaf(p_cache_sw);

			if (!p_physp->need_update)
				continue;

			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
				"Checking switch lid %u, port %u\n",
				lid_ho, port_num);

			p_remote_physp = osm_physp_get_remote(p_physp);
			remote_node_type =
			    osm_node_get_type(p_remote_physp->p_node);

			if (remote_node_type == IB_NODE_TYPE_SWITCH)
				remote_lid_ho =
				    cl_ntoh16(osm_node_get_base_lid
					      (p_remote_physp->p_node, 0));
			else
				remote_lid_ho =
				    cl_ntoh16(osm_node_get_base_lid
					      (p_remote_physp->p_node,
					       osm_physp_get_port_num
					       (p_remote_physp)));

			if (!p_cache_sw ||
			    port_num >= p_cache_sw->num_ports ||
			    !p_cache_sw->ports[port_num].remote_lid_ho) {
				/*
				 * There is some uncached change on the port.
				 * In general, the reasons might be as follows:
				 *  - switch reset
				 *  - port reset (or port down/up)
				 *  - quick connection location change
				 *  - new link (or new switch)
				 *
				 * First two reasons allow cache usage, while
				 * the last two reasons should invalidate cache.
				 *
				 * In case of quick connection location change,
				 * cache would have been invalidated by
				 * osm_ucast_cache_check_new_link() function.
				 *
				 * In case of new link between two known nodes,
				 * cache also would have been invalidated by
				 * osm_ucast_cache_check_new_link() function.
				 *
				 * Another reason is cached link between two
				 * known switches went back. In this case the
				 * osm_ucast_cache_check_new_link() function would
				 * clear both sides of the link from the cache
				 * during the discovery process, so effectively
				 * this would be equivalent to port reset.
				 *
				 * So three possible reasons remain:
				 *  - switch reset
				 *  - port reset (or port down/up)
				 *  - link of a new switch
				 *
				 * To validate cache, we need to check only the
				 * third reason - link of a new node/switch:
				 *  - If this is the local switch that is new,
				 *    then it should have (p_sw->need_update == 2).
				 *  - If the remote node is switch and it's new,
				 *    then it also should have
				 *    (p_sw->need_update == 2).
				 *  - If the remote node is CA/RTR and it's new,
				 *    then its port should have is_new flag on.
				 */
				if (p_sw->need_update == 2) {
					OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
						"New switch found (lid %u)\n",
						lid_ho);
					osm_ucast_cache_invalidate(p_mgr);
					goto Exit;
				}

				if (remote_node_type == IB_NODE_TYPE_SWITCH) {

					p_remote_sw =
					    p_remote_physp->p_node->sw;
					if (p_remote_sw->need_update == 2) {
						/* this could also be case of
						   switch coming back with an
						   additional link that it
						   didn't have before */
						OSM_LOG(p_mgr->p_log,
							OSM_LOG_DEBUG,
							"New switch/link found (lid %u)\n",
							remote_lid_ho);
						osm_ucast_cache_invalidate
						    (p_mgr);
						goto Exit;
					}
				} else {
					/*
					 * Remote node is CA/RTR.
					 * Get p_port of the remote node and
					 * check its p_port->is_new flag.
					 */
					p_remote_port =
					    osm_get_port_by_guid(p_mgr->p_subn,
								 osm_physp_get_port_guid
								 (p_remote_physp));
					if (p_remote_port->is_new) {
						OSM_LOG(p_mgr->p_log,
							OSM_LOG_DEBUG,
							"New CA/RTR found (lid %u)\n",
							remote_lid_ho);
						osm_ucast_cache_invalidate
						    (p_mgr);
						goto Exit;
					}
				}
			} else {
				/*
				 * The change on the port is cached.
				 * In general, the reasons might be as follows:
				 *  - link between two known nodes went back
				 *  - one or more nodes went back, causing all
				 *    the links to reappear
				 *
				 * If it was link that went back, then this case
				 * would have been taken care of during the
				 * discovery by osm_ucast_cache_check_new_link(),
				 * so it's some node that went back.
				 */
				if ((p_cache_sw->ports[port_num].is_leaf &&
				     remote_node_type == IB_NODE_TYPE_SWITCH) ||
				    (!p_cache_sw->ports[port_num].is_leaf &&
				     remote_node_type != IB_NODE_TYPE_SWITCH)) {
					OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
						"Remote node type change on switch lid %u, port %u\n",
						lid_ho, port_num);
					osm_ucast_cache_invalidate(p_mgr);
					goto Exit;
				}

				if (p_cache_sw->ports[port_num].remote_lid_ho !=
				    remote_lid_ho) {
					OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
						"Remote lid change on switch lid %u, port %u"
						"(was %u, now %u)\n",
						lid_ho, port_num,
						p_cache_sw->ports[port_num].
						remote_lid_ho, remote_lid_ho);
					osm_ucast_cache_invalidate(p_mgr);
					goto Exit;
				}

				/*
				 * We don't care who is the node that has
				 * reappeared in the subnet (local or remote).
				 * What's important that the cached link matches
				 * the real fabrics link.
				 * Just clean it from cache.
				 */

				p_cache_sw->ports[port_num].remote_lid_ho = 0;
				p_cache_sw->ports[port_num].is_leaf = FALSE;
				if (p_cache_sw->dropped) {
					cache_restore_ucast_info(p_mgr,
								 p_cache_sw,
								 p_sw);
					p_cache_sw->dropped = FALSE;
				}

				OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
					"Restored link from cache: lid %u, port %u to lid %u\n",
					lid_ho, port_num, remote_lid_ho);
			}
		}
	}

	/* Remove all the cached switches that
	   have all their ports restored */
	cache_cleanup_switches(p_mgr);

	/*
	 * Done scanning all the physical switch ports in the subnet.
	 * Now we need to check the other side:
	 * Scan all the cached switches and their ports:
	 *  - If the cached switch is missing in the subnet
	 *    (dropped flag is on), check that it's a leaf switch.
	 *    If it's not a leaf, the cache is invalid, because
	 *    cache can tolerate only leaf switch removal.
	 *  - If the cached switch exists in fabric, check all
	 *    its cached ports. These cached ports represent
	 *    missing link in the fabric.
	 *    The missing links that can be tolerated are:
	 *      + link to missing CA/RTR
	 *      + link to missing leaf switch
	 */
	for (p_cache_sw = (cache_switch_t *) cl_qmap_head(&p_mgr->cache_sw_tbl);
	     p_cache_sw != (cache_switch_t *) cl_qmap_end(&p_mgr->cache_sw_tbl);
	     p_cache_sw =
	     (cache_switch_t *) cl_qmap_next(&p_cache_sw->map_item)) {

		if (p_cache_sw->dropped) {
			if (!cache_sw_is_leaf(p_cache_sw)) {
				OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
					"Missing non-leaf switch (lid %u)\n",
					cache_sw_get_base_lid_ho(p_cache_sw));
				osm_ucast_cache_invalidate(p_mgr);
				goto Exit;
			}

			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
				"Missing leaf switch (lid %u) - "
				"continuing validation\n",
				cache_sw_get_base_lid_ho(p_cache_sw));
			continue;
		}

		for (port_num = 1; port_num < p_cache_sw->num_ports; port_num++) {
			if (!p_cache_sw->ports[port_num].remote_lid_ho)
				continue;

			if (p_cache_sw->ports[port_num].is_leaf) {
				CL_ASSERT(cache_sw_is_leaf(p_cache_sw));
				OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
					"Switch lid %u, port %u: missing link to CA/RTR - "
					"continuing validation\n",
					cache_sw_get_base_lid_ho(p_cache_sw),
					port_num);
				continue;
			}

			p_remote_cache_sw = cache_get_sw(p_mgr,
							 p_cache_sw->
							 ports[port_num].
							 remote_lid_ho);

			if (!p_remote_cache_sw || !p_remote_cache_sw->dropped) {
				OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
					"Switch lid %u, port %u: missing link to existing switch\n",
					cache_sw_get_base_lid_ho(p_cache_sw),
					port_num);
				osm_ucast_cache_invalidate(p_mgr);
				goto Exit;
			}

			if (!cache_sw_is_leaf(p_remote_cache_sw)) {
				OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
					"Switch lid %u, port %u: missing link to non-leaf switch\n",
					cache_sw_get_base_lid_ho(p_cache_sw),
					port_num);
				osm_ucast_cache_invalidate(p_mgr);
				goto Exit;
			}

			/*
			 * At this point we know that the missing link is to
			 * a leaf switch. However, one case deserves a special
			 * treatment. If there was a link between two leaf
			 * switches, then missing leaf switch might break
			 * routing. It is possible that there are routes
			 * that use leaf switches to get from switch to switch
			 * and not just to get to the CAs behind the leaf switch.
			 */
			if (cache_sw_is_leaf(p_cache_sw) &&
			    cache_sw_is_leaf(p_remote_cache_sw)) {
				OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
					"Switch lid %u, port %u: missing leaf-2-leaf link\n",
					cache_sw_get_base_lid_ho(p_cache_sw),
					port_num);
				osm_ucast_cache_invalidate(p_mgr);
				goto Exit;
			}

			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
				"Switch lid %u, port %u: missing remote leaf switch - "
				"continuing validation\n",
				cache_sw_get_base_lid_ho(p_cache_sw),
				port_num);
		}
	}

	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Unicast cache is valid\n");
	ucast_cache_dump(p_mgr);
Exit:
	OSM_LOG_EXIT(p_mgr->p_log);
}				/* osm_ucast_cache_validate() */
Example #4
0
/*        rank is a SWITCH for BFS purpose */
static int updn_subn_rank(IN updn_t * p_updn)
{
	osm_switch_t *p_sw;
	osm_physp_t *p_physp, *p_remote_physp;
	cl_qlist_t list;
	cl_map_item_t *item;
	struct updn_node *u, *remote_u;
	uint8_t num_ports, port_num;
	osm_log_t *p_log = &p_updn->p_osm->log;
	unsigned max_rank = 0;

	OSM_LOG_ENTER(p_log);
	cl_qlist_init(&list);

	/* add all roots to the list */
	for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl);
	     item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl);
	     item = cl_qmap_next(item)) {
		p_sw = (osm_switch_t *)item;
		u = p_sw->priv;
		if (!u->rank)
			cl_qlist_insert_tail(&list, &u->list);
	}

	/* BFS the list till it's empty */
	while (!cl_is_qlist_empty(&list)) {
		u = (struct updn_node *)cl_qlist_remove_head(&list);
		/* Go over all remote nodes and rank them (if not already visited) */
		p_sw = u->sw;
		num_ports = p_sw->num_ports;
		OSM_LOG(p_log, OSM_LOG_DEBUG,
			"Handling switch GUID 0x%" PRIx64 "\n",
			cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)));
		for (port_num = 1; port_num < num_ports; port_num++) {
			ib_net64_t port_guid;

			/* Current port fetched in order to get remote side */
			p_physp =
			    osm_node_get_physp_ptr(p_sw->p_node, port_num);

			if (!p_physp)
				continue;

			p_remote_physp = p_physp->p_remote_physp;

			/*
			   make sure that all the following occur on p_remote_physp:
			   1. The port isn't NULL
			   2. It is a switch
			 */
			if (p_remote_physp && p_remote_physp->p_node->sw) {
				remote_u = p_remote_physp->p_node->sw->priv;
				port_guid = p_remote_physp->port_guid;

				if (remote_u->rank > u->rank + 1) {
					remote_u->rank = u->rank + 1;
					max_rank = remote_u->rank;
					cl_qlist_insert_tail(&list,
							     &remote_u->list);
					OSM_LOG(p_log, OSM_LOG_DEBUG,
						"Rank of port GUID 0x%" PRIx64
						" = %u\n", cl_ntoh64(port_guid),
						remote_u->rank);
				}
			}
		}
	}

	/* Print Summary of ranking */
	OSM_LOG(p_log, OSM_LOG_VERBOSE,
		"Subnet ranking completed. Max Node Rank = %d\n", max_rank);
	OSM_LOG_EXIT(p_log);
	return 0;
}
Example #5
0
/* Find Root nodes automatically by Min Hop Table info */
static void updn_find_root_nodes_by_min_hop(OUT updn_t * p_updn)
{
	osm_opensm_t *p_osm = p_updn->p_osm;
	osm_switch_t *p_sw;
	osm_port_t *p_port;
	osm_physp_t *p_physp;
	cl_map_item_t *item;
	double thd1, thd2;
	unsigned i, cas_num = 0;
	unsigned *cas_per_sw;
	uint16_t lid_ho;

	OSM_LOG_ENTER(&p_osm->log);

	OSM_LOG(&p_osm->log, OSM_LOG_DEBUG,
		"Current number of ports in the subnet is %d\n",
		cl_qmap_count(&p_osm->subn.port_guid_tbl));

	lid_ho = (uint16_t) cl_ptr_vector_get_size(&p_updn->p_osm->subn.port_lid_tbl) + 1;
	cas_per_sw = malloc(lid_ho * sizeof(*cas_per_sw));
	if (!cas_per_sw) {
		OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR AA14: "
			"cannot alloc mem for CAs per switch counter array\n");
		goto _exit;
	}
	memset(cas_per_sw, 0, lid_ho * sizeof(*cas_per_sw));

	/* Find the Maximum number of CAs (and routers) for histogram normalization */
	OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
		"Finding the number of CAs and storing them in cl_map\n");
	for (item = cl_qmap_head(&p_updn->p_osm->subn.port_guid_tbl);
	     item != cl_qmap_end(&p_updn->p_osm->subn.port_guid_tbl);
	     item = cl_qmap_next(item)) {
		p_port = (osm_port_t *)item;
		if (!p_port->p_node->sw) {
			p_physp = p_port->p_physp->p_remote_physp;
			if (!p_physp || !p_physp->p_node->sw)
				continue;
			lid_ho = osm_node_get_base_lid(p_physp->p_node, 0);
			lid_ho = cl_ntoh16(lid_ho);
			cas_per_sw[lid_ho]++;
			cas_num++;
		}
	}

	thd1 = cas_num * 0.9;
	thd2 = cas_num * 0.05;
	OSM_LOG(&p_osm->log, OSM_LOG_DEBUG,
		"Found %u CAs and RTRs, %u SWs in the subnet. "
		"Thresholds are thd1 = %f && thd2 = %f\n",
		cas_num, cl_qmap_count(&p_osm->subn.sw_guid_tbl), thd1, thd2);

	OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
		"Passing through all switches to collect Min Hop info\n");
	for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl);
	     item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl);
	     item = cl_qmap_next(item)) {
		unsigned hop_hist[IB_SUBNET_PATH_HOPS_MAX];
		uint16_t max_lid_ho;
		uint8_t hop_val;
		uint16_t numHopBarsOverThd1 = 0;
		uint16_t numHopBarsOverThd2 = 0;

		p_sw = (osm_switch_t *) item;

		memset(hop_hist, 0, sizeof(hop_hist));

		max_lid_ho = p_sw->max_lid_ho;
		for (lid_ho = 1; lid_ho <= max_lid_ho; lid_ho++)
			if (cas_per_sw[lid_ho]) {
				hop_val =
				    osm_switch_get_least_hops(p_sw, lid_ho);
				if (hop_val >= IB_SUBNET_PATH_HOPS_MAX)
					continue;

				hop_hist[hop_val] += cas_per_sw[lid_ho];
			}

		/* Now recognize the spines by requiring one bar to be
		   above 90% of the number of CAs and RTRs */
		for (i = 0; i < IB_SUBNET_PATH_HOPS_MAX; i++) {
			if (hop_hist[i] > thd1)
				numHopBarsOverThd1++;
			if (hop_hist[i] > thd2)
				numHopBarsOverThd2++;
		}

		/* If thd conditions are valid - rank the root node */
		if (numHopBarsOverThd1 == 1 && numHopBarsOverThd2 == 1) {
			OSM_LOG(&p_osm->log, OSM_LOG_DEBUG,
				"Ranking GUID 0x%" PRIx64 " as root node\n",
				cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)));
			((struct updn_node *)p_sw->priv)->rank = 0;
			p_updn->num_roots++;
		}
	}

	free(cas_per_sw);
_exit:
	OSM_LOG_EXIT(&p_osm->log);
	return;
}
static void populate_fwd_tbls(lash_t * p_lash)
{
	osm_log_t *p_log = &p_lash->p_osm->log;
	osm_subn_t *p_subn = &p_lash->p_osm->subn;
	osm_switch_t *p_sw, *p_next_sw, *p_dst_sw;
	osm_port_t *port;
	uint16_t max_lid_ho, lid;

	OSM_LOG_ENTER(p_log);

	p_next_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl);

	/* Go through each switch individually */
	while (p_next_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl)) {
		uint64_t current_guid;
		switch_t *sw;
		p_sw = p_next_sw;
		p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item);

		max_lid_ho = p_sw->max_lid_ho;
		current_guid = p_sw->p_node->node_info.port_guid;
		sw = p_sw->priv;

		memset(p_sw->new_lft, OSM_NO_PATH, p_sw->lft_size);

		for (lid = 1; lid <= max_lid_ho; lid++) {
			port = osm_get_port_by_lid_ho(p_subn, lid);
			if (!port)
				continue;

			p_dst_sw = get_osm_switch_from_port(port);
			if (p_dst_sw == p_sw) {
				uint8_t egress_port = port->p_node->sw ? 0 :
					port->p_physp->p_remote_physp->port_num;
				p_sw->new_lft[lid] = egress_port;
				OSM_LOG(p_log, OSM_LOG_VERBOSE,
					"LASH fwd MY SRC SRC GUID 0x%016" PRIx64
					" src lash id (%d), src lid no (%u) src lash port (%d) "
					"DST GUID 0x%016" PRIx64
					" src lash id (%d), src lash port (%d)\n",
					cl_ntoh64(current_guid), -1, lid,
					egress_port, cl_ntoh64(current_guid),
					-1, egress_port);
			} else if (p_dst_sw) {
				unsigned dst_lash_switch_id =
				    get_lash_id(p_dst_sw);
				uint8_t lash_egress_port =
				    (uint8_t) sw->
				    routing_table[dst_lash_switch_id].out_link;
				uint8_t physical_egress_port =
					get_next_port(sw, lash_egress_port);

				p_sw->new_lft[lid] = physical_egress_port;
				OSM_LOG(p_log, OSM_LOG_VERBOSE,
					"LASH fwd SRC GUID 0x%016" PRIx64
					" src lash id (%d), "
					"src lid no (%u) src lash port (%d) "
					"DST GUID 0x%016" PRIx64
					" src lash id (%d), src lash port (%d)\n",
					cl_ntoh64(current_guid), sw->id, lid,
					lash_egress_port,
					cl_ntoh64(p_dst_sw->p_node->node_info.
						  port_guid),
					dst_lash_switch_id,
					physical_egress_port);
			}
		}		/* for */
	}
	OSM_LOG_EXIT(p_log);
}
Example #7
0
int osm_qos_setup(osm_opensm_t * p_osm)
{
	struct qos_config ca_config, sw0_config, swe_config, rtr_config;
	struct qos_config *cfg;
	cl_qmap_t *p_tbl;
	cl_map_item_t *p_next;
	osm_port_t *p_port;
	osm_node_t *p_node;
	int ret = 0;
	int vlarb_only;
	qos_mad_list_t *p_list, *p_list_next;
	qos_mad_item_t *p_port_mad;
	cl_qlist_t qos_mad_list;

	if (!p_osm->subn.opt.qos)
		return 0;

	OSM_LOG_ENTER(&p_osm->log);

	qos_build_config(&ca_config, &p_osm->subn.opt.qos_ca_options,
			 &p_osm->subn.opt.qos_options);
	qos_build_config(&sw0_config, &p_osm->subn.opt.qos_sw0_options,
			 &p_osm->subn.opt.qos_options);
	qos_build_config(&swe_config, &p_osm->subn.opt.qos_swe_options,
			 &p_osm->subn.opt.qos_options);
	qos_build_config(&rtr_config, &p_osm->subn.opt.qos_rtr_options,
			 &p_osm->subn.opt.qos_options);

	cl_qlist_init(&qos_mad_list);

	cl_plock_excl_acquire(&p_osm->lock);

	/* read QoS policy config file */
	osm_qos_parse_policy_file(&p_osm->subn);
	p_tbl = &p_osm->subn.port_guid_tbl;
	p_next = cl_qmap_head(p_tbl);
	while (p_next != cl_qmap_end(p_tbl)) {
		vlarb_only = 0;
		p_port = (osm_port_t *) p_next;
		p_next = cl_qmap_next(p_next);

		p_list = (qos_mad_list_t *) malloc(sizeof(*p_list));
		if (!p_list)
			return -1;

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

		cl_qlist_init(&p_list->port_mad_list);

		p_node = p_port->p_node;
		if (p_node->sw) {
			if (qos_extports_setup(&p_osm->sm, p_node, &swe_config,
					       &p_list->port_mad_list))
				ret = -1;

			/* skip base port 0 */
			if (!ib_switch_info_is_enhanced_port0
			    (&p_node->sw->switch_info))
				goto Continue;

			if (ib_switch_info_get_opt_sl2vlmapping(&p_node->sw->switch_info) &&
			    p_osm->sm.p_subn->opt.use_optimized_slvl &&
			    !memcmp(&swe_config.sl2vl, &sw0_config.sl2vl,
				    sizeof(swe_config.sl2vl)))
				vlarb_only = 1;

			cfg = &sw0_config;
		} else if (osm_node_get_type(p_node) == IB_NODE_TYPE_ROUTER)
			cfg = &rtr_config;
		else
			cfg = &ca_config;

		if (qos_endport_setup(&p_osm->sm, p_port->p_physp, cfg,
				      vlarb_only, &p_list->port_mad_list))

			ret = -1;
Continue:
		/* if MAD list is not empty, add it to the global MAD list */
		if (cl_qlist_count(&p_list->port_mad_list)) {
			cl_qlist_insert_tail(&qos_mad_list, &p_list->list_item);
		} else {
			free(p_list);
		}
	}
	while (cl_qlist_count(&qos_mad_list)) {
		p_list_next = (qos_mad_list_t *) cl_qlist_head(&qos_mad_list);
		while (p_list_next !=
			(qos_mad_list_t *) cl_qlist_end(&qos_mad_list)) {
			p_list = p_list_next;
			p_list_next = (qos_mad_list_t *)
				      cl_qlist_next(&p_list->list_item);
			/* next MAD to send*/
			p_port_mad = (qos_mad_item_t *)
				     cl_qlist_remove_head(&p_list->port_mad_list);
			osm_send_req_mad(&p_osm->sm, p_port_mad->p_madw);
			osm_qos_mad_delete(&p_port_mad);
			/* remove the QoS MAD from global MAD list */
			if (cl_qlist_count(&p_list->port_mad_list) == 0) {
				cl_qlist_remove_item(&qos_mad_list, &p_list->list_item);
				free(p_list);
			}
		}
	}

	cl_plock_release(&p_osm->lock);
	OSM_LOG_EXIT(&p_osm->log);

	return ret;
}
static int discover_network_properties(lash_t * p_lash)
{
	int i, id = 0;
	uint8_t vl_min;
	osm_subn_t *p_subn = &p_lash->p_osm->subn;
	osm_switch_t *p_next_sw, *p_sw;
	osm_log_t *p_log = &p_lash->p_osm->log;

	p_lash->num_switches = cl_qmap_count(&p_subn->sw_guid_tbl);

	p_lash->switches = calloc(p_lash->num_switches, sizeof(switch_t *));
	if (!p_lash->switches)
		return -1;

	vl_min = 5;		/* set to a high value */

	p_next_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl);
	while (p_next_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl)) {
		uint16_t port_count;
		p_sw = p_next_sw;
		p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item);

		p_lash->switches[id] = switch_create(p_lash, id, p_sw);
		if (!p_lash->switches[id])
			return -1;
		id++;

		port_count = osm_node_get_num_physp(p_sw->p_node);

		/* Note, ignoring port 0. management port */
		for (i = 1; i < port_count; i++) {
			osm_physp_t *p_current_physp =
			    osm_node_get_physp_ptr(p_sw->p_node, i);

			if (p_current_physp
			    && p_current_physp->p_remote_physp) {

				ib_port_info_t *p_port_info =
				    &p_current_physp->port_info;
				uint8_t port_vl_min =
				    ib_port_info_get_op_vls(p_port_info);
				if (port_vl_min && port_vl_min < vl_min)
					vl_min = port_vl_min;
			}
		}		/* for */
	}			/* while */

	vl_min = 1 << (vl_min - 1);
	if (vl_min > 15)
		vl_min = 15;

	if (p_lash->p_osm->subn.opt.lash_start_vl >= vl_min) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D03: "
			"Start VL(%d) too high for min operational vl(%d)\n",
			p_lash->p_osm->subn.opt.lash_start_vl, vl_min);
		return -1;
	}

	p_lash->vl_min = vl_min - p_lash->p_osm->subn.opt.lash_start_vl;

	OSM_LOG(p_log, OSM_LOG_INFO,
		"min operational vl(%d) start vl(%d) max_switches(%d)\n",
		p_lash->vl_min, p_lash->p_osm->subn.opt.lash_start_vl,
		p_lash->num_switches);
	return 0;
}
Example #9
0
File: point.c Project: 01org/opa-ff
/* If possible compress a point into a simpler format
 * This looks for lists which consist of a single entry or
 * lists which include all the components of a higher level type
 */
void PointFabricCompress(Point *point)
{
	switch (point->Type) {
	case POINT_TYPE_NONE:
		break;
	case POINT_TYPE_PORT:
		break;
	case POINT_TYPE_PORT_LIST:
		{
		PortData *portp;
		LIST_ITERATOR head = ListHead(&point->u.portList);
		ASSERT(head);

		ASSERT(ListCount(&point->u.portList) >= 1);

		portp = (PortData*)ListObj(head);
		if (ListCount(&point->u.portList) == 1) {
			/* degenerate case, simplify as a single port */
			PointFabricDestroy(point);
			PointInitSimple(point, POINT_TYPE_PORT, portp);
		} else if (ListCount(&point->u.portList) == cl_qmap_count(&portp->nodep->Ports)) {
			/* maybe we can consolidate to a single node */
			LIST_ITERATOR i;
			DLIST *pList = &point->u.portList;

			for (i=ListHead(pList); portp && i != NULL; i = ListNext(pList, i)) {
				if (portp->nodep != ((PortData*)ListObj(i))->nodep)
					portp = NULL;	/* not in same node, flag for below */
			}
			if (portp) {
				/* degenerate case, simplify as a single node */
				PointFabricDestroy(point);
				PointInitSimple(point, POINT_TYPE_NODE, portp->nodep);
			}
#if 0
		} else {
			// the likelihood of this is low for port oriented searches
			// and it would present just the system image guide in the summary
			// and may be less obvious to the user than a list of ports
			/* maybe we can consolidate to a single system */
			LIST_ITERATOR i;
			DLIST *pList = &point->u.portList;

			for (i=ListHead(pList); portp && i != NULL; i = ListNext(pList, i)) {
				if (portp->nodep->systemp != ((PortData*)ListObj(i))->nodep->systemp)
					portp = NULL;	/* not in same system, flag for below */
			}
			if (portp) {
				/* all ports are in same system. is it a complete list? */
				/* count ports in the system */
				uint32 count = 0;
				cl_map_item_t *p;

				for (p=cl_qmap_head(&portp->nodep->systemp->Nodes); p != cl_qmap_end(&portp->nodep->systemp->Nodes); p = cl_qmap_next(p)) {
					NodeData *nodep = PARENT_STRUCT(p, NodeData, SystemNodesEntry);
					count += cl_qmap_count(&nodep->Ports);
				}
				if (ListCount(&point->u.portList) != count)
					portp = NULL;	/* incomplete list, flag for below */
			}
			if (portp) {
				/* degenerate case, simplify as a single system */
				PointFabricDestroy(point);
				PointInitSimple(point, POINT_TYPE_SYSTEM, portp->nodep->systemp);
			}
#endif
		}
		break;
		}
	case POINT_TYPE_NODE:
		break;
	case POINT_TYPE_NODE_LIST:
		{
		NodeData *nodep;
		LIST_ITERATOR head = ListHead(&point->u.nodeList);
		ASSERT(head);

		ASSERT(ListCount(&point->u.nodeList) >= 1);
		nodep = (NodeData*)ListObj(head);
		if (ListCount(&point->u.nodeList) == 1) {
			/* degenerate case, simplify as a single node */
			PointFabricDestroy(point);
			PointInitSimple(point, POINT_TYPE_NODE, nodep);
		} else if (ListCount(&point->u.nodeList) == cl_qmap_count(&nodep->systemp->Nodes)) {
			/* maybe we can consolidate to a single system */
			LIST_ITERATOR i;
			DLIST *pList = &point->u.nodeList;

			for (i=ListHead(pList); nodep && i != NULL; i = ListNext(pList, i)) {
				if (nodep->systemp != ((NodeData*)ListObj(i))->systemp)
					nodep = NULL;	/* not in same system, flag for below */
			}
			if (nodep) {
				/* degenerate case, simplify as a single system */
				PointFabricDestroy(point);
				PointInitSimple(point, POINT_TYPE_SYSTEM, nodep->systemp);
			}
		}
		break;
		}
#if !defined(VXWORKS) || defined(BUILD_DMC)
	case POINT_TYPE_IOC:
		break;
	case POINT_TYPE_IOC_LIST:
		{
		IocData *iocp;
		LIST_ITERATOR head = ListHead(&point->u.iocList);
		ASSERT(head);

		ASSERT(ListCount(&point->u.iocList) >= 1);
		iocp = (IocData*)ListObj(head);
		if (ListCount(&point->u.iocList) == 1) {
			/* degenerate case, simplify as a single IOC */
			PointFabricDestroy(point);
			PointInitSimple(point, POINT_TYPE_IOC, iocp);
		} else if (ListCount(&point->u.iocList) == QListCount(&iocp->ioup->Iocs)) {
			/* maybe we can consolidate to a single node */
			LIST_ITERATOR i;
			DLIST *pList = &point->u.iocList;

			for (i=ListHead(pList); iocp && i != NULL; i = ListNext(pList, i)) {
				if (iocp->ioup != ((IocData*)ListObj(i))->ioup)
					iocp = NULL;	/* not in same iou, flag for below */
			}
			if (iocp) {
				/* degenerate case, simplify as a single node */
				PointFabricDestroy(point);
				PointInitSimple(point, POINT_TYPE_NODE, iocp->ioup->nodep);
			}
#if 0
		} else {
			// the likelihood of this is low for ioc oriented searches
			// and it would present just the system image guide in the summary
			// and may be less obvious to the user than a list of iocs
			/* maybe we can consolidate to a single system */
			LIST_ITERATOR i;
			DLIST *pList = &point->u.iocList;

			for (i=ListHead(pList); iocp && i != NULL; i = ListNext(pList, i)) {
				if (iocp->ioup->nodep->systemp != ((IocData*)ListObj(i))->ioup->nodep->systemp)
					iocp = NULL;	/* not in same system, flag for below */
			}
			if (iocp) {
				/* all IOCs are in same system. is it a complete list? */
				/* count IOCs in the system */
				uint32 count = 0;
				cl_map_item_t *p;

				for (p=cl_qmap_head(&iocp->ioup->nodep->systemp->Nodes); p != cl_qmap_end(&iocp->ioup->nodep->systemp->Nodes); p = cl_qmap_next(p)) {
					NodeData *nodep = PARENT_STRUCT(p, NodeData, SystemNodesEntry);
					if (nodep->ioup)
						count += QListCount(&nodep->ioup->Iocs);
				}
				if (ListCount(&point->u.iocList) != count)
					iocp = NULL;	/* incomplete list, flag for below */
			}
			if (iocp) {
				/* degenerate case, simplify as a single system */
				PointFabricDestroy(point);
				PointInitSimple(point, POINT_TYPE_SYSTEM, iocp->ioup->nodep->systemp);
			}
#endif
		}
		break;
		}
#endif
	case POINT_TYPE_SYSTEM:
		break;
	}
}
/**********************************************************************
 * Make sure that the lid_port_tbl of the subnet has only the ports
 * that are recognized, and in the correct lid place. There could be
 * errors if we wanted to assign a certain port with lid X, but that
 * request didn't reach the port. In this case port_lid_tbl will have
 * the port under lid X, though the port isn't updated with this lid.
 * We will run a new heavy sweep (since there were errors in the
 * initialization), but here we'll clean the database from incorrect
 * information.
 **********************************************************************/
static void state_mgr_check_tbl_consistency(IN osm_sm_t * sm)
{
	cl_qmap_t *p_port_guid_tbl;
	osm_port_t *p_port;
	osm_port_t *p_next_port;
	cl_ptr_vector_t *p_port_lid_tbl;
	size_t max_lid, ref_size, curr_size, lid;
	osm_port_t *p_port_ref, *p_port_stored;
	cl_ptr_vector_t ref_port_lid_tbl;
	uint16_t min_lid_ho;
	uint16_t max_lid_ho;
	uint16_t lid_ho;

	OSM_LOG_ENTER(sm->p_log);

	cl_ptr_vector_construct(&ref_port_lid_tbl);
	cl_ptr_vector_init(&ref_port_lid_tbl,
			   cl_ptr_vector_get_size(&sm->p_subn->port_lid_tbl),
			   OSM_SUBNET_VECTOR_GROW_SIZE);

	p_port_guid_tbl = &sm->p_subn->port_guid_tbl;

	/* Let's go over all the ports according to port_guid_tbl,
	 * and add the port to a reference port_lid_tbl. */
	p_next_port = (osm_port_t *) cl_qmap_head(p_port_guid_tbl);
	while (p_next_port != (osm_port_t *) cl_qmap_end(p_port_guid_tbl)) {
		p_port = p_next_port;
		p_next_port =
		    (osm_port_t *) cl_qmap_next(&p_next_port->map_item);

		osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
		for (lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++)
			cl_ptr_vector_set(&ref_port_lid_tbl, lid_ho, p_port);
	}

	p_port_lid_tbl = &sm->p_subn->port_lid_tbl;

	ref_size = cl_ptr_vector_get_size(&ref_port_lid_tbl);
	curr_size = cl_ptr_vector_get_size(p_port_lid_tbl);
	/* They should be the same, but compare it anyway */
	max_lid = (ref_size > curr_size) ? ref_size : curr_size;

	for (lid = 1; lid < max_lid; lid++) {
		p_port_ref = NULL;
		p_port_stored = NULL;
		cl_ptr_vector_at(p_port_lid_tbl, lid, (void *)&p_port_stored);
		cl_ptr_vector_at(&ref_port_lid_tbl, lid, (void *)&p_port_ref);

		if (p_port_stored == p_port_ref)
			/* This is the "good" case - both entries are the
			 * same for this lid. Nothing to do. */
			continue;

		if (p_port_ref == NULL)
			/* There is an object in the subnet database for this
			 * lid, but no such object exists in the reference
			 * port_list_tbl. This can occur if we wanted to assign
			 * a certain port with some lid (different than the one
			 * pre-assigned to it), and the port didn't get the
			 * PortInfo Set request. Due to this, the port is
			 * updated with its original lid in our database, but
			 * with the new lid we wanted to give it in our
			 * port_lid_tbl. */
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3322: "
				"lid %zu is wrongly assigned to port 0x%016"
				PRIx64 " (\'%s\' port %u) in port_lid_tbl\n",
				lid,
				cl_ntoh64(osm_port_get_guid(p_port_stored)),
				p_port_stored->p_node->print_desc,
				p_port_stored->p_physp->port_num);
		else if (p_port_stored == NULL)
			/* There is an object in the new database, but no
			 * object in our subnet database. This is the matching
			 * case of the prior check - the port still has its
			 * original lid. */
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3323: "
				"port 0x%016" PRIx64 " (\'%s\' port %u)"
				" exists in new port_lid_tbl under lid %zu,"
				" but missing in subnet port_lid_tbl db\n",
				cl_ntoh64(osm_port_get_guid(p_port_ref)),
				p_port_ref->p_node->print_desc,
				p_port_ref->p_physp->port_num, lid);
		else
			/* if we reached here then p_port_stored != p_port_ref.
			 * We were trying to set a lid to p_port_stored, but
			 * it didn't reach it, and p_port_ref also didn't get
			 * the lid update. */
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3324: "
				"lid %zu has port 0x%016" PRIx64
				" (\'%s\' port %u) in new port_lid_tbl db, "
				"and port 0x%016" PRIx64 " (\'%s\' port %u)"
				" in subnet port_lid_tbl db\n", lid,
				cl_ntoh64(osm_port_get_guid(p_port_ref)),
				p_port_ref->p_node->print_desc,
				p_port_ref->p_physp->port_num,
				cl_ntoh64(osm_port_get_guid(p_port_stored)),
				p_port_ref->p_node->print_desc,
				p_port_ref->p_physp->port_num);

		/* In any of these cases we want to set NULL in the
		 * port_lid_tbl, since this entry is invalid. Also, make sure
		 * we'll do another heavy sweep. */
		cl_ptr_vector_set(p_port_lid_tbl, lid, NULL);
		sm->p_subn->subnet_initialization_error = TRUE;
	}

	cl_ptr_vector_destroy(&ref_port_lid_tbl);
	OSM_LOG_EXIT(sm->p_log);
}
/**********************************************************************
 * Send Trap 64 on all new ports.
 **********************************************************************/
static void state_mgr_report_new_ports(IN osm_sm_t * sm)
{
	ib_gid_t port_gid;
	ib_mad_notice_attr_t notice;
	ib_api_status_t status;
	ib_net64_t port_guid;
	cl_map_item_t *p_next;
	osm_port_t *p_port;
	uint16_t min_lid_ho;
	uint16_t max_lid_ho;

	OSM_LOG_ENTER(sm->p_log);

	CL_PLOCK_ACQUIRE(sm->p_lock);
	p_next = cl_qmap_head(&sm->p_subn->port_guid_tbl);
	while (p_next != cl_qmap_end(&sm->p_subn->port_guid_tbl)) {
		p_port = (osm_port_t *) p_next;
		p_next = cl_qmap_next(p_next);

		if (!p_port->is_new)
			continue;

		port_guid = osm_port_get_guid(p_port);
		/* issue a notice - trap 64 */

		/* details of the notice */
		notice.generic_type = 0x83;	/* is generic subn mgt type */
		ib_notice_set_prod_type_ho(&notice, 4);	/* A Class Manager generator */
		/* endport becomes reachable */
		notice.g_or_v.generic.trap_num = CL_HTON16(64);
		/* The sm_base_lid is saved in network order already. */
		notice.issuer_lid = sm->p_subn->sm_base_lid;
		/* following C14-72.1.1 and table 119 p739 */
		/* we need to provide the GID */
		port_gid.unicast.prefix = sm->p_subn->opt.subnet_prefix;
		port_gid.unicast.interface_id = port_guid;
		memcpy(&(notice.data_details.ntc_64_67.gid), &(port_gid),
		       sizeof(ib_gid_t));

		/* According to page 653 - the issuer gid in this case of trap
		 * is the SM gid, since the SM is the initiator of this trap. */
		notice.issuer_gid.unicast.prefix =
		    sm->p_subn->opt.subnet_prefix;
		notice.issuer_gid.unicast.interface_id =
		    sm->p_subn->sm_port_guid;

		status = osm_report_notice(sm->p_log, sm->p_subn, &notice);
		if (status != IB_SUCCESS)
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3318: "
				"Error sending trap reports on GUID:0x%016"
				PRIx64 " (%s)\n", port_gid.unicast.interface_id,
				ib_get_err_str(status));
		osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
		OSM_LOG(sm->p_log, OSM_LOG_INFO,
			"Discovered new port with GUID:0x%016" PRIx64
			" LID range [%u,%u] of node: %s\n",
			cl_ntoh64(port_gid.unicast.interface_id),
			min_lid_ho, max_lid_ho,
			p_port->p_node ? p_port->p_node->
			print_desc : "UNKNOWN");

		p_port->is_new = 0;
	}
	CL_PLOCK_RELEASE(sm->p_lock);

	OSM_LOG_EXIT(sm->p_log);
}
/**********************************************************************
 Initiates a lightweight sweep of the subnet.
 Used during normal sweeps after the subnet is up.
**********************************************************************/
static ib_api_status_t state_mgr_light_sweep_start(IN osm_sm_t * sm)
{
	ib_api_status_t status = IB_SUCCESS;
	osm_bind_handle_t h_bind;
	cl_qmap_t *p_sw_tbl;
	cl_map_item_t *p_next;
	osm_node_t *p_node;
	osm_physp_t *p_physp;
	uint8_t port_num;

	OSM_LOG_ENTER(sm->p_log);

	p_sw_tbl = &sm->p_subn->sw_guid_tbl;

	/*
	 * First, get the bind handle.
	 */
	h_bind = osm_sm_mad_ctrl_get_bind_handle(&sm->mad_ctrl);
	if (h_bind == OSM_BIND_INVALID_HANDLE) {
		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
			"No bound ports. Deferring sweep...\n");
		status = IB_INVALID_STATE;
		goto _exit;
	}

	OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "INITIATING LIGHT SWEEP");
	CL_PLOCK_ACQUIRE(sm->p_lock);
	cl_qmap_apply_func(p_sw_tbl, state_mgr_get_sw_info, sm);
	CL_PLOCK_RELEASE(sm->p_lock);

	CL_PLOCK_ACQUIRE(sm->p_lock);
	cl_qmap_apply_func(&sm->p_subn->node_guid_tbl, state_mgr_get_node_desc,
			   sm);
	CL_PLOCK_RELEASE(sm->p_lock);

	/* now scan the list of physical ports that were not down but have no remote port */
	CL_PLOCK_ACQUIRE(sm->p_lock);
	p_next = cl_qmap_head(&sm->p_subn->node_guid_tbl);
	while (p_next != cl_qmap_end(&sm->p_subn->node_guid_tbl)) {
		p_node = (osm_node_t *) p_next;
		p_next = cl_qmap_next(p_next);

		for (port_num = 1; port_num < osm_node_get_num_physp(p_node);
		     port_num++) {
			p_physp = osm_node_get_physp_ptr(p_node, port_num);
			if (p_physp && (osm_physp_get_port_state(p_physp) !=
					IB_LINK_DOWN)
			    && !osm_physp_get_remote(p_physp)) {
				OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3315: "
					"Unknown remote side for node 0x%016"
					PRIx64
					" (%s) port %u. Adding to light sweep sampling list\n",
					cl_ntoh64(osm_node_get_node_guid
						  (p_node)),
					p_node->print_desc, port_num);

				osm_dump_dr_path_v2(sm->p_log,
						    osm_physp_get_dr_path_ptr
						    (p_physp), FILE_ID, OSM_LOG_ERROR);

				state_mgr_get_remote_port_info(sm, p_physp);
			}
		}
	}

	cl_qmap_apply_func(&sm->p_subn->sm_guid_tbl, query_sm_info, sm);

	CL_PLOCK_RELEASE(sm->p_lock);

_exit:
	OSM_LOG_EXIT(sm->p_log);
	return status;
}