@@ -279,24 +279,80 @@ static int updn_subn_rank(IN updn_t * p_updn)
return 0;
}
-/* hack: preserve min hops entries to any other root switches */
-static void updn_clear_non_root_hops(updn_t * p_updn, osm_switch_t * p_sw)
+/**********************************************************************
+ **********************************************************************/
+/* Preserve min hops entries to any switch
+ * above certain level in the tree */
+static void updn_switch_clear_hops_below_rank(updn_t * p_updn,
+ osm_switch_t * p_sw, unsigned min_leaf_rank)
{
osm_port_t *p_port;
unsigned i;
for (i = 0; i < p_sw->num_hops; i++)
if (p_sw->hops[i]) {
- p_port =
- cl_ptr_vector_get(&p_updn->p_osm->subn.port_lid_tbl,
- i);
- if (!p_port || !p_port->p_node->sw
- || ((struct updn_node *)p_port->p_node->sw->priv)->
- rank != 0)
+ p_port = cl_ptr_vector_get(
+ &p_updn->p_osm->subn.port_lid_tbl, i);
+ if (!p_port || !p_port->p_node->sw ||
+ ((struct updn_node *)
+ p_port->p_node->sw->priv)->rank >= min_leaf_rank)
memset(p_sw->hops[i], 0xff, p_sw->num_ports);
}
}
+/**********************************************************************
+ **********************************************************************/
+static void updn_clear_hops(IN updn_t * p_updn)
+{
+ osm_subn_t *p_subn = &p_updn->p_osm->subn;
+ osm_switch_t *p_sw;
+ struct updn_node * p_updn_sw;
+ osm_physp_t * p_physp;
+ osm_port_t * p_port;
+ cl_map_item_t *item;
+ unsigned min_leaf_rank = 0xff;
+
+ if (p_subn->opt.connect_switches) {
+ /*
+ * Preserve roots to switches above the highest leaf
+ * switch (leaf switch with the lowest rank).
+ *
+ * Need to find the minimal rank of leaf switch.
+ * The fastest way would be to go through all the
+ * CA ports in the fabric and check the switch that
+ * is connected to them.
+ */
+ 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)
+ continue;
+ p_physp = p_port->p_physp->p_remote_physp;
+ if (!p_physp || !p_physp->p_node->sw)
+ continue;
+
+ p_updn_sw = (struct updn_node*)p_physp->p_node->sw->priv;
+ if (p_updn_sw->rank < min_leaf_rank)
+ min_leaf_rank = p_updn_sw->rank;
+ }
+ } else if (p_subn->opt.connect_roots)
+ min_leaf_rank = 1;
+
+ 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;
+ if (p_subn->opt.connect_switches || p_subn->opt.connect_roots)
+ updn_switch_clear_hops_below_rank(
+ p_updn, p_sw, min_leaf_rank);
+ else
+ osm_switch_clear_hops(p_sw);
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
static int updn_set_min_hop_table(IN updn_t * p_updn)
{
osm_subn_t *p_subn = &p_updn->p_osm->subn;
@@ -311,16 +367,8 @@ static int updn_set_min_hop_table(IN updn_t * p_updn)
OSM_LOG(p_log, OSM_LOG_VERBOSE,
"Init Min Hop Table of all switches [\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)) {
- p_sw = (osm_switch_t *)item;
- /* Clear Min Hop Table */
- if (p_subn->opt.connect_roots)
- updn_clear_non_root_hops(p_updn, p_sw);
- else
- osm_switch_clear_hops(p_sw);
- }
+ /* Clear Min Hop Table */
+ updn_clear_hops(p_updn);
OSM_LOG(p_log, OSM_LOG_VERBOSE,
"Init Min Hop Table of all switches ]\n");
@@ -598,7 +646,8 @@ static int updn_lid_matrices(void *ctx)
OSM_LOG(&p_updn->p_osm->log, OSM_LOG_ERROR, "ERR : "
"cannot parse root guids file \'%s\'\n",
p_updn->p_osm->subn.opt.root_guid_file);
- if (p_updn->p_osm->subn.opt.connect_roots &&
+ if ((p_updn->p_osm->subn.opt.connect_roots ||
+ p_updn->p_osm->subn.opt.connect_switches) &&
p_updn->num_roots > 1)
osm_ucast_mgr_build_lid_matrices(&p_updn->p_osm->sm.ucast_mgr);
} else {