osm_ucast_dnup.c revision 321936
1193240Ssam/* 2193240Ssam * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved. 3193240Ssam * Copyright (c) 2002-2007,2009 Mellanox Technologies LTD. All rights reserved. 4193240Ssam * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5193240Ssam * Copyright (c) 2009 HNR Consulting. All rights reserved. 6193240Ssam * Copyright (c) 2009 Battelle Memorial Institue. All rights reserved. 7193240Ssam * 8193240Ssam * This software is available to you under a choice of one of two 9193240Ssam * licenses. You may choose to be licensed under the terms of the GNU 10193240Ssam * General Public License (GPL) Version 2, available from the file 11193240Ssam * COPYING in the main directory of this source tree, or the 12193240Ssam * OpenIB.org BSD license below: 13193240Ssam * 14193240Ssam * Redistribution and use in source and binary forms, with or 15193240Ssam * without modification, are permitted provided that the following 16193240Ssam * conditions are met: 17193240Ssam * 18193240Ssam * - Redistributions of source code must retain the above 19193240Ssam * copyright notice, this list of conditions and the following 20193240Ssam * disclaimer. 21193240Ssam * 22193240Ssam * - Redistributions in binary form must reproduce the above 23193240Ssam * copyright notice, this list of conditions and the following 24193240Ssam * disclaimer in the documentation and/or other materials 25193240Ssam * provided with the distribution. 26193240Ssam * 27193240Ssam * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 28193240Ssam * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 29193240Ssam * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 30193240Ssam * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 31193240Ssam * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 32193240Ssam * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 33193240Ssam * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 34193240Ssam * SOFTWARE. 35193240Ssam * 36193240Ssam */ 37193240Ssam 38193240Ssam/* 39193240Ssam * Abstract: 40193240Ssam * Implementation of Up Down Algorithm using ranking & Min Hop 41193240Ssam * Calculation functions 42193240Ssam */ 43193240Ssam 44193240Ssam#if HAVE_CONFIG_H 45193240Ssam# include <config.h> 46193240Ssam#endif /* HAVE_CONFIG_H */ 47193240Ssam 48193240Ssam#include <stdlib.h> 49193240Ssam#include <ctype.h> 50193240Ssam#include <complib/cl_debug.h> 51193240Ssam#include <complib/cl_qmap.h> 52193240Ssam#include <opensm/osm_file_ids.h> 53193240Ssam#define FILE_ID OSM_FILE_UCAST_DNUP_C 54193240Ssam#include <opensm/osm_switch.h> 55193240Ssam#include <opensm/osm_opensm.h> 56193240Ssam#include <opensm/osm_ucast_mgr.h> 57193240Ssam 58193240Ssam/* //////////////////////////// */ 59193240Ssam/* Local types */ 60193240Ssam/* //////////////////////////// */ 61193240Ssam 62193240Ssam/* direction */ 63193240Ssamtypedef enum dnup_switch_dir { 64193240Ssam UP = 0, 65193240Ssam DOWN, 66193240Ssam EQUAL 67193240Ssam} dnup_switch_dir_t; 68193240Ssam 69193240Ssam/* dnup structure */ 70193240Ssamtypedef struct dnup { 71193240Ssam osm_opensm_t *p_osm; 72193240Ssam} dnup_t; 73193240Ssam 74193240Ssamstruct dnup_node { 75193240Ssam cl_list_item_t list; 76193240Ssam osm_switch_t *sw; 77193240Ssam dnup_switch_dir_t dir; 78193240Ssam unsigned rank; 79193240Ssam unsigned visited; 80193240Ssam}; 81193240Ssam 82193240Ssam/* This function returns direction based on rank and guid info of current & 83193240Ssam remote ports */ 84193240Ssamstatic dnup_switch_dir_t dnup_get_dir(unsigned cur_rank, unsigned rem_rank) 85193240Ssam{ 86193240Ssam /* HACK: comes to solve root nodes connection, in a classic subnet root nodes do not connect 87193240Ssam directly, but in case they are we assign to root node an UP direction to allow DNUP to discover 88193240Ssam the subnet correctly (and not from the point of view of the last root node). 89193240Ssam */ 90193240Ssam if (!cur_rank && !rem_rank) 91193240Ssam return EQUAL; 92193240Ssam 93193240Ssam if (cur_rank < rem_rank) 94193240Ssam return DOWN; 95193240Ssam else if (cur_rank > rem_rank) 96193240Ssam return UP; 97193240Ssam else 98193240Ssam return EQUAL; 99193240Ssam} 100193240Ssam 101193240Ssam/********************************************************************** 102193240Ssam * This function does the bfs of min hop table calculation by guid index 103193240Ssam * as a starting point. 104193240Ssam **********************************************************************/ 105193240Ssamstatic int dnup_bfs_by_node(IN osm_log_t * p_log, IN osm_subn_t * p_subn, 106193240Ssam IN osm_switch_t * p_sw, IN uint8_t prune_weight, 107193240Ssam OUT uint8_t * max_hops) 108193240Ssam{ 109193240Ssam uint8_t pn, pn_rem; 110193240Ssam cl_qlist_t list; 111193240Ssam uint16_t lid; 112193240Ssam struct dnup_node *u; 113193240Ssam dnup_switch_dir_t next_dir, current_dir; 114193240Ssam 115193240Ssam OSM_LOG_ENTER(p_log); 116193240Ssam 117193240Ssam lid = osm_node_get_base_lid(p_sw->p_node, 0); 118193240Ssam lid = cl_ntoh16(lid); 119193240Ssam osm_switch_set_hops(p_sw, lid, 0, 0); 120193240Ssam 121193240Ssam OSM_LOG(p_log, OSM_LOG_DEBUG, 122193240Ssam "Starting from switch - port GUID 0x%" PRIx64 " lid %u\n", 123193240Ssam cl_ntoh64(p_sw->p_node->node_info.port_guid), lid); 124193240Ssam 125193240Ssam u = p_sw->priv; 126193240Ssam u->dir = DOWN; 127193240Ssam 128193240Ssam /* Update list with the new element */ 129193240Ssam cl_qlist_init(&list); 130193240Ssam cl_qlist_insert_tail(&list, &u->list); 131193240Ssam 132193240Ssam /* BFS the list till no next element */ 133193240Ssam while (!cl_is_qlist_empty(&list)) { 134193240Ssam u = (struct dnup_node *)cl_qlist_remove_head(&list); 135193240Ssam u->visited = 0; /* cleanup */ 136193240Ssam current_dir = u->dir; 137193240Ssam /* Go over all ports of the switch and find unvisited remote nodes */ 138193240Ssam for (pn = 1; pn < u->sw->num_ports; pn++) { 139193240Ssam osm_node_t *p_remote_node; 140193240Ssam struct dnup_node *rem_u; 141193240Ssam uint8_t current_min_hop, remote_min_hop, 142193240Ssam set_hop_return_value; 143193240Ssam osm_switch_t *p_remote_sw; 144193240Ssam 145193240Ssam p_remote_node = 146193240Ssam osm_node_get_remote_node(u->sw->p_node, pn, 147195377Ssam &pn_rem); 148195377Ssam /* If no remote node OR remote node is not a SWITCH 149193240Ssam continue to next pn */ 150193240Ssam if (!p_remote_node || !p_remote_node->sw) 151193240Ssam continue; 152193240Ssam /* Fetch remote guid only after validation of remote node */ 153193240Ssam p_remote_sw = p_remote_node->sw; 154193240Ssam rem_u = p_remote_sw->priv; 155193240Ssam /* Decide which direction to mark it (UP/DOWN) */ 156193240Ssam next_dir = dnup_get_dir(u->rank, rem_u->rank); 157193240Ssam 158193240Ssam /* Set MinHop value for the current lid */ 159193240Ssam current_min_hop = osm_switch_get_least_hops(u->sw, lid); 160193240Ssam /* Check hop count if better insert into list && update 161193240Ssam the remote node Min Hop Table */ 162193240Ssam remote_min_hop = 163193240Ssam osm_switch_get_hop_count(p_remote_sw, lid, pn_rem); 164193240Ssam 165193240Ssam /* Check if this is a legal step : the only illegal step is going 166193240Ssam from UP to DOWN */ 167193240Ssam if ((current_dir == UP) && (next_dir == DOWN)) { 168193240Ssam OSM_LOG(p_log, OSM_LOG_DEBUG, 169193240Ssam "Avoiding move from 0x%016" PRIx64 170193240Ssam " to 0x%016" PRIx64 "\n", 171193240Ssam cl_ntoh64(osm_node_get_node_guid(u->sw->p_node)), 172193240Ssam cl_ntoh64(osm_node_get_node_guid(p_remote_node))); 173193240Ssam /* Illegal step. If prune_weight is set, allow it with an 174193240Ssam * additional weight 175193240Ssam */ 176193240Ssam if(prune_weight) { 177193240Ssam current_min_hop+=prune_weight; 178193240Ssam if(current_min_hop >= 64) { 179193240Ssam OSM_LOG(p_log, OSM_LOG_ERROR, 180193240Ssam "ERR AE02: Too many hops on subnet," 181193240Ssam " can't relax illegal Dn/Up transition."); 182193240Ssam osm_switch_set_hops(p_remote_sw, lid, 183193240Ssam pn_rem, OSM_NO_PATH); 184193240Ssam } 185193240Ssam } else { 186193240Ssam continue; 187193240Ssam } 188193240Ssam } 189193240Ssam if (current_min_hop + 1 < remote_min_hop) { 190193240Ssam set_hop_return_value = 191193240Ssam osm_switch_set_hops(p_remote_sw, lid, 192193240Ssam pn_rem, 193193240Ssam current_min_hop + 1); 194193240Ssam if(max_hops && current_min_hop + 1 > *max_hops) { 195193240Ssam *max_hops = current_min_hop + 1; 196193240Ssam } 197193240Ssam if (set_hop_return_value) { 198193240Ssam OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AE01: " 199193240Ssam "Invalid value returned from set min hop is: %d\n", 200193240Ssam set_hop_return_value); 201193240Ssam } 202193240Ssam /* Check if remote port has already been visited */ 203193240Ssam if (!rem_u->visited) { 204193240Ssam /* Insert dnup_switch item into the list */ 205193240Ssam rem_u->dir = next_dir; 206193240Ssam rem_u->visited = 1; 207193240Ssam cl_qlist_insert_tail(&list, 208193240Ssam &rem_u->list); 209193240Ssam } 210193240Ssam } 211193240Ssam } 212193240Ssam } 213193240Ssam 214193240Ssam OSM_LOG_EXIT(p_log); 215193240Ssam return 0; 216193240Ssam} 217193240Ssam 218193240Ssam/* NOTE : PLS check if we need to decide that the first */ 219193240Ssam/* rank is a SWITCH for BFS purpose */ 220193240Ssamstatic int dnup_subn_rank(IN dnup_t * p_dnup) 221193240Ssam{ 222193240Ssam osm_switch_t *p_sw; 223193240Ssam osm_physp_t *p_physp, *p_remote_physp; 224193240Ssam cl_qlist_t list; 225193240Ssam cl_map_item_t *item; 226193240Ssam struct dnup_node *u, *remote_u; 227193240Ssam uint8_t num_ports, port_num; 228193240Ssam osm_log_t *p_log = &p_dnup->p_osm->log; 229193240Ssam unsigned max_rank = 0; 230193240Ssam 231193240Ssam OSM_LOG_ENTER(p_log); 232193240Ssam cl_qlist_init(&list); 233193240Ssam 234193240Ssam /* add all node level switches to the list */ 235193240Ssam for (item = cl_qmap_head(&p_dnup->p_osm->subn.sw_guid_tbl); 236193240Ssam item != cl_qmap_end(&p_dnup->p_osm->subn.sw_guid_tbl); 237193240Ssam item = cl_qmap_next(item)) { 238193240Ssam p_sw = (osm_switch_t *)item; 239193240Ssam u = p_sw->priv; 240193240Ssam if (u->rank == 0) 241193240Ssam cl_qlist_insert_tail(&list, &u->list); 242193240Ssam } 243193240Ssam 244193240Ssam /* BFS the list till it's empty */ 245193240Ssam while (!cl_is_qlist_empty(&list)) { 246193240Ssam u = (struct dnup_node *)cl_qlist_remove_head(&list); 247193240Ssam /* Go over all remote nodes and rank them (if not already visited) */ 248193240Ssam p_sw = u->sw; 249193240Ssam num_ports = p_sw->num_ports; 250193240Ssam OSM_LOG(p_log, OSM_LOG_DEBUG, 251193240Ssam "Handling switch GUID 0x%" PRIx64 "\n", 252193240Ssam cl_ntoh64(osm_node_get_node_guid(p_sw->p_node))); 253193240Ssam for (port_num = 1; port_num < num_ports; port_num++) { 254193240Ssam ib_net64_t port_guid; 255193240Ssam 256193240Ssam /* Current port fetched in order to get remote side */ 257193240Ssam p_physp = 258193240Ssam osm_node_get_physp_ptr(p_sw->p_node, port_num); 259193240Ssam 260193240Ssam if (!p_physp) 261193240Ssam continue; 262193240Ssam 263193240Ssam p_remote_physp = p_physp->p_remote_physp; 264193240Ssam 265193240Ssam /* 266193240Ssam make sure that all the following occur on p_remote_physp: 267193240Ssam 1. The port isn't NULL 268193240Ssam 2. It is a switch 269193240Ssam */ 270193240Ssam if (p_remote_physp && p_remote_physp->p_node->sw) { 271193240Ssam remote_u = p_remote_physp->p_node->sw->priv; 272193240Ssam port_guid = p_remote_physp->port_guid; 273193240Ssam 274193240Ssam if (remote_u->rank > u->rank + 1) { 275193240Ssam remote_u->rank = u->rank + 1; 276193240Ssam max_rank = remote_u->rank; 277193240Ssam cl_qlist_insert_tail(&list, 278193240Ssam &remote_u->list); 279193240Ssam OSM_LOG(p_log, OSM_LOG_DEBUG, 280193240Ssam "Rank of port GUID 0x%" PRIx64 281193240Ssam " = %u\n", cl_ntoh64(port_guid), 282193240Ssam remote_u->rank); 283193240Ssam } 284193240Ssam } 285193240Ssam } 286193240Ssam } 287193240Ssam 288193240Ssam /* Print Summary of ranking */ 289193240Ssam OSM_LOG(p_log, OSM_LOG_VERBOSE, 290193240Ssam "Subnet ranking completed. Max Node Rank = %d\n", max_rank); 291193240Ssam OSM_LOG_EXIT(p_log); 292193240Ssam return 0; 293193240Ssam} 294193240Ssam 295193240Ssamstatic int dnup_set_min_hop_table(IN dnup_t * p_dnup) 296193240Ssam{ 297193240Ssam osm_subn_t *p_subn = &p_dnup->p_osm->subn; 298193240Ssam osm_log_t *p_log = &p_dnup->p_osm->log; 299193240Ssam osm_switch_t *p_sw; 300193240Ssam struct dnup_node *u; 301193240Ssam cl_map_item_t *item; 302193240Ssam uint8_t max_hops = 0; 303193240Ssam 304193240Ssam OSM_LOG_ENTER(p_log); 305193240Ssam 306193240Ssam /* Go over all the switches in the subnet - for each init their Min Hop 307193240Ssam Table */ 308193240Ssam OSM_LOG(p_log, OSM_LOG_VERBOSE, 309193240Ssam "Init Min Hop Table of all switches [\n"); 310193240Ssam 311193240Ssam for (item = cl_qmap_head(&p_dnup->p_osm->subn.sw_guid_tbl); 312193240Ssam item != cl_qmap_end(&p_dnup->p_osm->subn.sw_guid_tbl); 313193240Ssam item = cl_qmap_next(item)) { 314193240Ssam p_sw = (osm_switch_t *)item; 315193240Ssam /* Clear Min Hop Table */ 316193240Ssam osm_switch_clear_hops(p_sw); 317193240Ssam } 318193240Ssam 319193240Ssam OSM_LOG(p_log, OSM_LOG_VERBOSE, 320193240Ssam "Init Min Hop Table of all switches ]\n"); 321193240Ssam 322193240Ssam /* Now do the BFS for each port in the subnet */ 323193240Ssam OSM_LOG(p_log, OSM_LOG_VERBOSE, 324193240Ssam "BFS through all port guids in the subnet [\n"); 325193240Ssam 326193240Ssam for (item = cl_qmap_head(&p_dnup->p_osm->subn.sw_guid_tbl); 327193240Ssam item != cl_qmap_end(&p_dnup->p_osm->subn.sw_guid_tbl); 328193240Ssam item = cl_qmap_next(item)) { 329193240Ssam p_sw = (osm_switch_t *)item; 330193240Ssam dnup_bfs_by_node(p_log, p_subn, p_sw, 0, &max_hops); 331193240Ssam } 332193240Ssam if(p_subn->opt.connect_roots) { 333193240Ssam /*This is probably not necessary, by I am more comfortable 334193240Ssam * clearing any possible side effects from the previous 335193240Ssam * dnup routing pass 336193240Ssam */ 337193240Ssam for (item = cl_qmap_head(&p_dnup->p_osm->subn.sw_guid_tbl); 338193240Ssam item != cl_qmap_end(&p_dnup->p_osm->subn.sw_guid_tbl); 339193240Ssam item = cl_qmap_next(item)) { 340193240Ssam p_sw = (osm_switch_t *)item; 341193240Ssam osm_switch_clear_hops(p_sw); 342193240Ssam u = (struct dnup_node *) p_sw->priv; 343193240Ssam u->visited = 0; 344193240Ssam } 345193240Ssam for (item = cl_qmap_head(&p_dnup->p_osm->subn.sw_guid_tbl); 346193240Ssam item != cl_qmap_end(&p_dnup->p_osm->subn.sw_guid_tbl); 347193240Ssam item = cl_qmap_next(item)) { 348193240Ssam p_sw = (osm_switch_t *)item; 349193240Ssam dnup_bfs_by_node(p_log, p_subn, p_sw, max_hops + 1, NULL); 350193240Ssam } 351193240Ssam } 352193240Ssam 353193240Ssam OSM_LOG(p_log, OSM_LOG_VERBOSE, 354193240Ssam "BFS through all port guids in the subnet ]\n"); 355193240Ssam /* Cleanup */ 356193240Ssam OSM_LOG_EXIT(p_log); 357193240Ssam return 0; 358193240Ssam} 359193240Ssam 360193240Ssamstatic int dnup_build_lid_matrices(IN dnup_t * p_dnup) 361193240Ssam{ 362193240Ssam int status; 363193240Ssam 364193240Ssam OSM_LOG_ENTER(&p_dnup->p_osm->log); 365193240Ssam 366193240Ssam OSM_LOG(&p_dnup->p_osm->log, OSM_LOG_VERBOSE, 367193240Ssam "Ranking all port guids in the list\n"); 368193240Ssam /* Check if it's not a switched subnet */ 369193240Ssam if (cl_is_qmap_empty(&p_dnup->p_osm->subn.sw_guid_tbl)) { 370193240Ssam OSM_LOG(&p_dnup->p_osm->log, OSM_LOG_ERROR, "ERR AEOB: " 371193240Ssam "This is not a switched subnet, cannot perform DNUP algorithm\n"); 372193240Ssam status = -1; 373193240Ssam goto _exit; 374193240Ssam } 375193240Ssam 376193240Ssam /* Rank the subnet switches */ 377193240Ssam dnup_subn_rank(p_dnup); 378193240Ssam 379193240Ssam /* After multiple ranking need to set Min Hop Table by DnUp algorithm */ 380193240Ssam OSM_LOG(&p_dnup->p_osm->log, OSM_LOG_VERBOSE, 381193240Ssam "Setting all switches' Min Hop Table\n"); 382193240Ssam status = dnup_set_min_hop_table(p_dnup); 383193240Ssam 384193240Ssam_exit: 385193240Ssam OSM_LOG_EXIT(&p_dnup->p_osm->log); 386193240Ssam return status; 387193240Ssam} 388193240Ssam 389193240Ssamstatic struct dnup_node *create_dnup_node(osm_switch_t * sw) 390193240Ssam{ 391193240Ssam struct dnup_node *u; 392193240Ssam 393193240Ssam u = malloc(sizeof(*u)); 394193240Ssam if (!u) 395193240Ssam return NULL; 396193240Ssam memset(u, 0, sizeof(*u)); 397193240Ssam u->sw = sw; 398193240Ssam u->rank = 0xffffffff; 399193240Ssam return u; 400193240Ssam} 401193240Ssam 402193240Ssamstatic void delete_dnup_node(struct dnup_node *u) 403193240Ssam{ 404193240Ssam u->sw->priv = NULL; 405193240Ssam free(u); 406193240Ssam} 407193240Ssam 408193240Ssam/* DNUP callback function */ 409193240Ssamstatic int dnup_lid_matrices(void *ctx) 410193240Ssam{ 411193240Ssam dnup_t *p_dnup = ctx; 412193240Ssam cl_map_item_t *item; 413193240Ssam osm_switch_t *p_sw; 414193240Ssam int ret = 0; 415193240Ssam int num_leafs = 0; 416193240Ssam uint8_t pn, pn_rem; 417193240Ssam 418193240Ssam OSM_LOG_ENTER(&p_dnup->p_osm->log); 419193240Ssam 420193240Ssam for (item = cl_qmap_head(&p_dnup->p_osm->subn.sw_guid_tbl); 421193240Ssam item != cl_qmap_end(&p_dnup->p_osm->subn.sw_guid_tbl); 422193240Ssam item = cl_qmap_next(item)) { 423195618Srpaulo p_sw = (osm_switch_t *)item; 424193240Ssam p_sw->priv = create_dnup_node(p_sw); 425193240Ssam if (!p_sw->priv) { 426193240Ssam OSM_LOG(&(p_dnup->p_osm->log), OSM_LOG_ERROR, "ERR AE0C: " 427193240Ssam "cannot create dnup node\n"); 428193240Ssam OSM_LOG_EXIT(&p_dnup->p_osm->log); 429193240Ssam return -1; 430193240Ssam } 431193240Ssam } 432193240Ssam 433193240Ssam 434193240Ssam /* First setup node level nodes */ 435193240Ssam for (item = cl_qmap_head(&p_dnup->p_osm->subn.sw_guid_tbl); 436193240Ssam item != cl_qmap_end(&p_dnup->p_osm->subn.sw_guid_tbl); 437193240Ssam item = cl_qmap_next(item)) { 438193240Ssam p_sw = (osm_switch_t *)item; 439193240Ssam 440193240Ssam for (pn = 0; pn < p_sw->num_ports; pn++) { 441193240Ssam osm_node_t *p_remote_node; 442193240Ssam p_remote_node = osm_node_get_remote_node(p_sw->p_node, pn, &pn_rem); 443193240Ssam if(p_remote_node && !p_remote_node->sw) { 444193240Ssam struct dnup_node *u = p_sw->priv; 445193240Ssam u->rank = 0; 446193240Ssam OSM_LOG(&(p_dnup->p_osm->log), 447193240Ssam OSM_LOG_VERBOSE, "(%s) rank 0 leaf switch\n", 448193240Ssam p_sw->p_node->print_desc); 449193240Ssam num_leafs++; 450193240Ssam break; 451193240Ssam } 452193240Ssam } 453193240Ssam } 454193240Ssam 455193240Ssam if(num_leafs == 0) { 456193240Ssam OSM_LOG(&(p_dnup->p_osm->log), 457193240Ssam OSM_LOG_ERROR, "ERR AE0D: No leaf switches found, DnUp routing failed\n"); 458193240Ssam OSM_LOG_EXIT(&p_dnup->p_osm->log); 459193240Ssam return -1; 460193240Ssam } 461193240Ssam 462193240Ssam ret = dnup_build_lid_matrices(p_dnup); 463193240Ssam 464193240Ssam for (item = cl_qmap_head(&p_dnup->p_osm->subn.sw_guid_tbl); 465193240Ssam item != cl_qmap_end(&p_dnup->p_osm->subn.sw_guid_tbl); 466193240Ssam item = cl_qmap_next(item)) { 467193240Ssam p_sw = (osm_switch_t *) item; 468193240Ssam delete_dnup_node(p_sw->priv); 469193240Ssam } 470193240Ssam 471193240Ssam OSM_LOG_EXIT(&p_dnup->p_osm->log); 472193240Ssam return ret; 473193240Ssam} 474193240Ssam 475193240Ssamstatic void dnup_delete(void *context) 476193240Ssam{ 477193240Ssam free(context); 478193240Ssam} 479193240Ssam 480193240Ssamint osm_ucast_dnup_setup(struct osm_routing_engine *r, osm_opensm_t *osm) 481193240Ssam{ 482193240Ssam dnup_t *dnup; 483193240Ssam 484193240Ssam OSM_LOG_ENTER(&osm->log); 485193240Ssam 486193240Ssam dnup = malloc(sizeof(dnup_t)); 487193240Ssam if (!dnup) 488193240Ssam return -1; 489193240Ssam memset(dnup, 0, sizeof(dnup_t)); 490193240Ssam 491193240Ssam dnup->p_osm = osm; 492193240Ssam 493193240Ssam r->context = dnup; 494193240Ssam r->destroy = dnup_delete; 495193240Ssam r->build_lid_matrices = dnup_lid_matrices; 496193240Ssam 497193240Ssam OSM_LOG_EXIT(&osm->log); 498193240Ssam return 0; 499193240Ssam} 500193240Ssam