/** =========================================================================== */ static void extract_lft(osm_switch_t *p_sw, uint64_t *p_top_offset, uint64_t *p_block_offset) { struct ep_map_rec *p_map_rec; uint64_t rec_key; uint16_t max_block, lid_ho, i; max_block = p_sw->lft_size / IB_SMP_DATA_SIZE; lid_ho = ntohs(osm_node_get_base_lid(p_sw->p_node, 0)); rec_key = (uint64_t) lid_ho; smdb_lft_top_init(lid_ho, p_sw->lft_size, &ssa_db->p_lft_db->p_db_lft_top_tbl[*p_top_offset]); p_map_rec = ep_map_rec_init(*p_top_offset); cl_qmap_insert(&ssa_db->p_lft_db->ep_db_lft_top_tbl, rec_key, &p_map_rec->map_item); *p_top_offset = *p_top_offset + 1; for (i = 0; i < max_block; i++) { rec_key = ep_rec_gen_key(lid_ho, i); smdb_lft_block_init(p_sw, lid_ho, i, &ssa_db->p_lft_db->p_db_lft_block_tbl[*p_block_offset]); p_map_rec = ep_map_rec_init(*p_block_offset); cl_qmap_insert(&ssa_db->p_lft_db->ep_db_lft_block_tbl, rec_key, &p_map_rec->map_item); *p_block_offset = *p_block_offset + 1; } }
osm_prtn_t *osm_prtn_make_new(osm_log_t * p_log, osm_subn_t * p_subn, const char *name, uint16_t pkey) { osm_prtn_t *p = NULL, *p_check; pkey &= cl_hton16((uint16_t) ~ 0x8000); if (!pkey) { if (name && (p = osm_prtn_find_by_name(p_subn, name))) return p; if (!(pkey = generate_pkey(p_subn))) return NULL; } p = osm_prtn_new(name, pkey); if (!p) { OSM_LOG(p_log, OSM_LOG_ERROR, "Unable to create" " partition \'%s\' (0x%04x)\n", name, cl_ntoh16(pkey)); return NULL; } p_check = (osm_prtn_t *) cl_qmap_insert(&p_subn->prtn_pkey_tbl, p->pkey, &p->map_item); if (p != p_check) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "Duplicated partition" " definition: \'%s\' (0x%04x) prev name \'%s\'" ". Will use it\n", name, cl_ntoh16(pkey), p_check->name); osm_prtn_delete(p_subn, &p); p = p_check; } return p; }
/** =========================================================================== */ static void extract_node(osm_node_t *p_node, uint64_t *p_offset, struct ssa_db_extract *p_ssa_db) { struct ep_map_rec *p_map_rec; #ifdef SSA_PLUGIN_VERBOSE_LOGGING char buffer[64]; if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) sprintf(buffer, " with %s Switch Port 0\n", ib_switch_info_is_enhanced_port0( &p_node->sw->switch_info) ? "Enhanced" : "Base"); else sprintf(buffer, "\n"); ssa_log(SSA_LOG_VERBOSE, "Node GUID 0x%" PRIx64 " Type %d%s", ntohll(osm_node_get_node_guid(p_node)), osm_node_get_type(p_node), buffer); #endif smdb_node_init(p_node, &p_ssa_db->p_node_tbl[*p_offset]); p_map_rec = ep_map_rec_init(*p_offset); if (!p_map_rec) { /* add memory allocation failure handling */ ssa_log(SSA_LOG_VERBOSE, "Quick MAP rec memory allocation failed\n"); } cl_qmap_insert(&p_ssa_db->ep_node_tbl, osm_node_get_node_guid(p_node), &p_map_rec->map_item); *p_offset = *p_offset + 1; }
/** =========================================================================== */ static void extract_port(osm_physp_t *p_physp, uint16_t *p_lid_ho, uint64_t pkey_base_offset, uint16_t pkey_tbl_size, uint64_t *p_port_offset, struct ssa_db_extract *p_ssa_db) { struct ep_map_rec *p_map_rec; uint64_t rec_key; uint16_t lid_ho; if (p_lid_ho) { /* in case of switch port */ rec_key = ep_rec_gen_key(*p_lid_ho, osm_physp_get_port_num(p_physp)); lid_ho = *p_lid_ho; } else { rec_key = ep_rec_gen_key(ntohs(osm_physp_get_base_lid(p_physp)), osm_physp_get_port_num(p_physp)); lid_ho = 0; } smdb_port_init(p_physp, pkey_base_offset, pkey_tbl_size, htons(lid_ho), &p_ssa_db->p_port_tbl[*p_port_offset]); p_map_rec = ep_map_rec_init(*p_port_offset); cl_qmap_insert(&p_ssa_db->ep_port_tbl, rec_key, &p_map_rec->map_item); *p_port_offset = *p_port_offset + 1; }
/* insert nodes to the database */ static perfmgr_db_err_t insert(perfmgr_db_t * db, db_node_t * node) { cl_map_item_t *rc = cl_qmap_insert(&db->pc_data, node->node_guid, (cl_map_item_t *) node); if ((void *)rc != (void *)node) return PERFMGR_EVENT_DB_FAIL; return PERFMGR_EVENT_DB_SUCCESS; }
static int map_name(void *cxt, uint64_t guid, char *p) { cl_qmap_t *map = cxt; name_map_item_t *item; p = strtok(p, "\"#"); if (!p) return 0; item = malloc(sizeof(*item)); if (!item) return -1; item->guid = guid; item->name = strdup(p); cl_qmap_insert(map, item->guid, (cl_map_item_t *)item); return 0; }
static void cache_add_sw_link(osm_ucast_mgr_t * p_mgr, osm_physp_t *p, uint16_t remote_lid_ho, boolean_t is_ca) { cache_switch_t *p_cache_sw; uint16_t lid_ho = cl_ntoh16(osm_node_get_base_lid(p->p_node, 0)); OSM_LOG_ENTER(p_mgr->p_log); if (!lid_ho || !remote_lid_ho || !p->port_num) goto Exit; OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Caching switch port: lid %u [port %u] -> lid %u (%s)\n", lid_ho, p->port_num, remote_lid_ho, (is_ca) ? "CA/RTR" : "SW"); p_cache_sw = cache_get_sw(p_mgr, lid_ho); if (!p_cache_sw) { p_cache_sw = cache_sw_new(lid_ho, p->p_node->sw->num_ports); if (!p_cache_sw) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD01: Out of memory - cache is invalid\n"); osm_ucast_cache_invalidate(p_mgr); goto Exit; } cl_qmap_insert(&p_mgr->cache_sw_tbl, lid_ho, &p_cache_sw->map_item); } if (p->port_num >= p_cache_sw->num_ports) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD02: Wrong switch? - cache is invalid\n"); osm_ucast_cache_invalidate(p_mgr); goto Exit; } if (is_ca) cache_sw_set_leaf(p_cache_sw); if (p_cache_sw->ports[p->port_num].remote_lid_ho == 0) { /* cache this link only if it hasn't been already cached */ p_cache_sw->ports[p->port_num].remote_lid_ho = remote_lid_ho; p_cache_sw->ports[p->port_num].is_leaf = is_ca; } Exit: OSM_LOG_EXIT(p_mgr->p_log); }
/** =========================================================================== */ static void extract_link(osm_physp_t *p_physp, uint16_t *p_lid_ho, uint64_t *p_link_offset, struct ssa_db_extract *p_ssa_db) { struct ep_map_rec *p_map_rec; uint64_t rec_key; if (p_lid_ho) rec_key = ep_rec_gen_key(*p_lid_ho, osm_physp_get_port_num(p_physp)); else rec_key = ep_rec_gen_key(ntohs(osm_physp_get_base_lid(p_physp)), osm_physp_get_port_num(p_physp)); smdb_link_init(p_physp, &p_ssa_db->p_link_tbl[*p_link_offset]); p_map_rec = ep_map_rec_init(*p_link_offset); cl_qmap_insert(&p_ssa_db->ep_link_tbl, rec_key, &p_map_rec->map_item); *p_link_offset = *p_link_offset + 1; }
/** =========================================================================== */ static void extract_guid2lid(osm_port_t *p_port, uint64_t *p_offset, struct ssa_db_extract *p_ssa_db) { struct ep_map_rec *p_map_rec; #ifdef SSA_PLUGIN_VERBOSE_LOGGING uint8_t is_fdr10_active; ssa_log(SSA_LOG_VERBOSE, "Port GUID 0x%" PRIx64 " LID %u Port state %d" "(%s)\n", ntohll(osm_physp_get_port_guid(p_port->p_physp)), ntohs(osm_port_get_base_lid(p_port)), osm_physp_get_port_state(p_port->p_physp), (osm_physp_get_port_state(p_port->p_physp) < 5 ? port_state_str[osm_physp_get_port_state(p_port->p_physp)] : "???")); is_fdr10_active = p_port->p_physp->ext_port_info.link_speed_active & FDR10; ssa_log(SSA_LOG_VERBOSE, "FDR10 %s active\n", is_fdr10_active ? "" : "not"); #endif /* check for valid LID first */ if ((ntohs(osm_port_get_base_lid(p_port)) < IB_LID_UCAST_START_HO) || (ntohs(osm_port_get_base_lid(p_port)) > IB_LID_UCAST_END_HO)) { ssa_log(SSA_LOG_VERBOSE, "Port GUID 0x%" PRIx64 " has invalid LID %u\n", ntohll(osm_physp_get_port_guid(p_port->p_physp)), ntohs(osm_port_get_base_lid(p_port))); } smdb_guid2lid_init(p_port, &p_ssa_db->p_guid_to_lid_tbl[*p_offset]); p_map_rec = ep_map_rec_init(*p_offset); if (!p_map_rec) { /* add memory allocation failure handling */ ssa_log(SSA_LOG_VERBOSE, "Quick MAP rec memory allocation failed\n"); } cl_qmap_insert(&p_ssa_db->ep_guid_to_lid_tbl, osm_physp_get_port_guid(p_port->p_physp), &p_map_rec->map_item); *p_offset = *p_offset + 1; }
/** =========================================================================== */ static void lft_block_handle(struct ssa_db_lft_change_rec *p_lft_change_rec) { struct ep_map_rec *p_map_rec, *p_map_rec_old; uint64_t rec_num, key; uint16_t block_num; rec_num = cl_qmap_count(&ssa_db->p_lft_db->ep_dump_lft_block_tbl); if (rec_num % SSA_TABLE_BLOCK_SIZE == 0) { ssa_db->p_lft_db->p_dump_lft_block_tbl = (struct smdb_lft_block *) realloc(&ssa_db->p_lft_db->p_dump_lft_block_tbl[0], (rec_num / SSA_TABLE_BLOCK_SIZE + 1) * SSA_TABLE_BLOCK_SIZE * sizeof(*ssa_db->p_lft_db->p_dump_lft_block_tbl)); } block_num = p_lft_change_rec->lft_change.block_num; ssa_log(SSA_LOG_VERBOSE, "LFT change block event received " "for LID %u Block %u\n", ntohs(p_lft_change_rec->lid), block_num); key = ep_rec_gen_key(ntohs(p_lft_change_rec->lid), block_num); p_map_rec = ep_map_rec_init(rec_num); p_map_rec_old = (struct ep_map_rec *) cl_qmap_insert(&ssa_db->p_lft_db->ep_dump_lft_block_tbl, key, &p_map_rec->map_item); if (p_map_rec != p_map_rec_old) { /* in case of a record with the same key already exist */ rec_num = p_map_rec_old->offset; free(p_map_rec); } ssa_db->p_lft_db->p_dump_lft_block_tbl[rec_num].lid = p_lft_change_rec->lid; ssa_db->p_lft_db->p_dump_lft_block_tbl[rec_num].block_num = htons(block_num); memcpy(ssa_db->p_lft_db->p_dump_lft_block_tbl[rec_num].block, p_lft_change_rec->block, IB_SMP_DATA_SIZE); }
ib_api_status_t __osmv_txnmgr_insert_txn(IN osmv_txn_mgr_t * p_tx_mgr, IN osmv_txn_ctx_t * p_txn, IN uint64_t key) { cl_map_obj_t *p_obj = NULL; cl_map_item_t *p_item; uint64_t tmp_key; CL_ASSERT(p_tx_mgr); CL_ASSERT(p_txn); key = osmv_txn_get_key(p_txn); p_obj = malloc(sizeof(cl_map_obj_t)); if (NULL == p_obj) return IB_INSUFFICIENT_MEMORY; osm_log(p_tx_mgr->p_log, OSM_LOG_DEBUG, "__osmv_txnmgr_insert_txn: " "Inserting key: 0x%llX to map ptr:%p\n", key, p_tx_mgr->p_txn_map); memset(p_obj, 0, sizeof(cl_map_obj_t)); cl_qmap_set_obj(p_obj, p_txn); /* assuming lookup with this key was made and the result was IB_NOT_FOUND */ cl_qmap_insert(p_tx_mgr->p_txn_map, key, &p_obj->item); p_item = cl_qmap_head(p_tx_mgr->p_txn_map); while (p_item != cl_qmap_end(p_tx_mgr->p_txn_map)) { tmp_key = cl_qmap_key(p_item); osm_log(p_tx_mgr->p_log, OSM_LOG_DEBUG, "__osmv_txnmgr_insert_txn: " "Found key 0x%llX \n", tmp_key); p_item = cl_qmap_next(p_item); } return IB_SUCCESS; }
/** =========================================================================== */ static void lft_top_handle(struct ssa_db_lft_change_rec *p_lft_change_rec) { struct ep_map_rec *p_map_rec, *p_map_rec_old; uint64_t rec_num, key; rec_num = cl_qmap_count(&ssa_db->p_lft_db->ep_dump_lft_top_tbl); if (rec_num % SSA_TABLE_BLOCK_SIZE == 0) { ssa_db->p_lft_db->p_dump_lft_top_tbl = (struct smdb_lft_top *) realloc(&ssa_db->p_lft_db->p_dump_lft_top_tbl[0], (rec_num / SSA_TABLE_BLOCK_SIZE + 1) * SSA_TABLE_BLOCK_SIZE * sizeof(*ssa_db->p_lft_db->p_dump_lft_top_tbl)); } ssa_log(SSA_LOG_VERBOSE, "LFT change top event received " "for LID %u New Top %u\n", ntohs(p_lft_change_rec->lid), p_lft_change_rec->lft_change.lft_top); key = (uint64_t) ntohs(p_lft_change_rec->lid); p_map_rec = ep_map_rec_init(rec_num); p_map_rec_old = (struct ep_map_rec *) cl_qmap_insert(&ssa_db->p_lft_db->ep_dump_lft_top_tbl, key, &p_map_rec->map_item); if (p_map_rec != p_map_rec_old) { /* in case of a record with the same key already exist */ rec_num = p_map_rec_old->offset; free(p_map_rec); } ssa_db->p_lft_db->p_dump_lft_top_tbl[rec_num].lid = p_lft_change_rec->lid; ssa_db->p_lft_db->p_dump_lft_top_tbl[rec_num].lft_top = htons(p_lft_change_rec->lft_change.lft_top); }
Status_t sm_routing_addModuleFac(const char * name, routing_mod_factory fac) { Status_t s; cl_map_obj_t * wrp = NULL; if (name == NULL || strlen(name) == 0 || fac == NULL) return VSTATUS_ILLPARM; if (cl_qmap_get(&moduleFacMap, UGLY_CHAR_U64(name)) != cl_qmap_end(&moduleFacMap)) return VSTATUS_BAD; if ((s = vs_pool_alloc(&sm_pool, sizeof(cl_map_obj_t), (void*)&wrp)) != VSTATUS_OK) return s; memset(wrp, 0, sizeof(*wrp)); wrp->p_object = fac; if (cl_qmap_insert(&moduleFacMap, UGLY_CHAR_U64(name), &wrp->item) == NULL) return VSTATUS_BAD; return VSTATUS_OK; }
/********************************************************************** The plock must NOT be held before calling this function. **********************************************************************/ static void ni_rcv_process_new(IN osm_sm_t * sm, IN const osm_madw_t * p_madw) { osm_node_t *p_node; osm_node_t *p_node_check; osm_port_t *p_port; osm_port_t *p_port_check; osm_router_t *p_rtr = NULL; osm_router_t *p_rtr_check; cl_qmap_t *p_rtr_guid_tbl; ib_node_info_t *p_ni; ib_smp_t *p_smp; osm_ni_context_t *p_ni_context; osm_alias_guid_t *p_alias_guid, *p_alias_guid_check; uint8_t port_num; OSM_LOG_ENTER(sm->p_log); p_smp = osm_madw_get_smp_ptr(p_madw); p_ni = ib_smp_get_payload_ptr(p_smp); p_ni_context = osm_madw_get_ni_context_ptr(p_madw); port_num = ib_node_info_get_local_port_num(p_ni); osm_dump_smp_dr_path_v2(sm->p_log, p_smp, FILE_ID, OSM_LOG_VERBOSE); OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Discovered new %s node," "\n\t\t\t\tGUID 0x%" PRIx64 ", TID 0x%" PRIx64 "\n", ib_get_node_type_str(p_ni->node_type), cl_ntoh64(p_ni->node_guid), cl_ntoh64(p_smp->trans_id)); if (PF(port_num > p_ni->num_ports)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D0A: " "New %s node GUID 0x%" PRIx64 "is non-compliant and " "is being ignored since the " "local port num %u > num ports %u\n", ib_get_node_type_str(p_ni->node_type), cl_ntoh64(p_ni->node_guid), port_num, p_ni->num_ports); goto Exit; } p_node = osm_node_new(p_madw); if (PF(p_node == NULL)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D07: " "Unable to create new node object\n"); goto Exit; } /* Create a new port object to represent this node's physical ports in the port table. */ p_port = osm_port_new(p_ni, p_node); if (PF(p_port == NULL)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D14: " "Unable to create new port object\n"); osm_node_delete(&p_node); goto Exit; } /* Add the new port object to the database. */ p_port_check = (osm_port_t *) cl_qmap_insert(&sm->p_subn->port_guid_tbl, p_ni->port_guid, &p_port->map_item); if (PF(p_port_check != p_port)) { /* We should never be here! Somehow, this port GUID already exists in the table. */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D15: " "Duplicate Port GUID 0x%" PRIx64 "! Found by the two directed routes:\n", cl_ntoh64(p_ni->port_guid)); osm_dump_dr_path_v2(sm->p_log, osm_physp_get_dr_path_ptr(p_port->p_physp), FILE_ID, OSM_LOG_ERROR); osm_dump_dr_path_v2(sm->p_log, osm_physp_get_dr_path_ptr(p_port_check-> p_physp), FILE_ID, OSM_LOG_ERROR); osm_port_delete(&p_port); osm_node_delete(&p_node); goto Exit; } p_alias_guid = osm_alias_guid_new(p_ni->port_guid, p_port); if (PF(!p_alias_guid)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D18: " "alias guid memory allocation failed" " for port GUID 0x%" PRIx64 "\n", cl_ntoh64(p_ni->port_guid)); goto alias_done2; } /* insert into alias guid table */ p_alias_guid_check = (osm_alias_guid_t *) cl_qmap_insert(&sm->p_subn->alias_port_guid_tbl, p_alias_guid->alias_guid, &p_alias_guid->map_item); if (p_alias_guid_check != p_alias_guid) { /* alias GUID is a duplicate */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D19: " "Duplicate alias port GUID 0x%" PRIx64 "\n", cl_ntoh64(p_ni->port_guid)); osm_alias_guid_delete(&p_alias_guid); } alias_done2: /* If we are a master, then this means the port is new on the subnet. Mark it as new - need to send trap 64 on these ports. The condition that we are master is true, since if we are in discovering state (meaning we woke up from standby or we are just initializing), then these ports may be new to us, but are not new on the subnet. If we are master, then the subnet as we know it is the updated one, and any new ports we encounter should cause trap 64. C14-72.1.1 */ if (sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER) p_port->is_new = 1; /* If there were RouterInfo or other router attribute, this would be elsewhere */ if (p_ni->node_type == IB_NODE_TYPE_ROUTER) { if (PF((p_rtr = osm_router_new(p_port)) == NULL)) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D1A: " "Unable to create new router object\n"); else { p_rtr_guid_tbl = &sm->p_subn->rtr_guid_tbl; p_rtr_check = (osm_router_t *) cl_qmap_insert(p_rtr_guid_tbl, p_ni->port_guid, &p_rtr->map_item); if (PF(p_rtr_check != p_rtr)) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D1B: " "Unable to add port GUID:0x%016" PRIx64 " to router table\n", cl_ntoh64(p_ni->port_guid)); } } p_node_check = (osm_node_t *) cl_qmap_insert(&sm->p_subn->node_guid_tbl, p_ni->node_guid, &p_node->map_item); if (PF(p_node_check != p_node)) { /* This node must have been inserted by another thread. This is unexpected, but is not an error. We can simply clean-up, since the other thread will see this processing through to completion. */ OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Discovery race detected at node 0x%" PRIx64 "\n", cl_ntoh64(p_ni->node_guid)); osm_node_delete(&p_node); p_node = p_node_check; ni_rcv_set_links(sm, p_node, port_num, p_ni_context); goto Exit; } else ni_rcv_set_links(sm, p_node, port_num, p_ni_context); p_node->discovery_count++; ni_rcv_get_node_desc(sm, p_node, p_madw); switch (p_ni->node_type) { case IB_NODE_TYPE_CA: case IB_NODE_TYPE_ROUTER: ni_rcv_process_new_ca_or_router(sm, p_node, p_madw); break; case IB_NODE_TYPE_SWITCH: ni_rcv_process_new_switch(sm, p_node, p_madw); break; default: OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D16: " "Unknown node type %u with GUID 0x%" PRIx64 "\n", p_ni->node_type, cl_ntoh64(p_ni->node_guid)); break; } Exit: OSM_LOG_EXIT(sm->p_log); }
/********************************************************************** The plock must be held before calling this function. **********************************************************************/ static void ni_rcv_process_existing_ca_or_router(IN osm_sm_t * sm, IN osm_node_t * p_node, IN const osm_madw_t * p_madw) { ib_node_info_t *p_ni; ib_smp_t *p_smp; osm_port_t *p_port; osm_port_t *p_port_check; uint8_t port_num; osm_dr_path_t *p_dr_path; osm_alias_guid_t *p_alias_guid, *p_alias_guid_check; OSM_LOG_ENTER(sm->p_log); p_smp = osm_madw_get_smp_ptr(p_madw); p_ni = ib_smp_get_payload_ptr(p_smp); port_num = ib_node_info_get_local_port_num(p_ni); /* Determine if we have encountered this node through a previously undiscovered port. If so, build the new port object. */ p_port = osm_get_port_by_guid(sm->p_subn, p_ni->port_guid); if (!p_port) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Creating new port object with GUID 0x%" PRIx64 "\n", cl_ntoh64(p_ni->port_guid)); osm_node_init_physp(p_node, port_num, p_madw); p_port = osm_port_new(p_ni, p_node); if (PF(p_port == NULL)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D04: " "Unable to create new port object\n"); goto Exit; } /* Add the new port object to the database. */ p_port_check = (osm_port_t *) cl_qmap_insert(&sm->p_subn->port_guid_tbl, p_ni->port_guid, &p_port->map_item); if (PF(p_port_check != p_port)) { /* We should never be here! Somehow, this port GUID already exists in the table. */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D12: " "Port 0x%" PRIx64 " already in the database!\n", cl_ntoh64(p_ni->port_guid)); osm_port_delete(&p_port); goto Exit; } p_alias_guid = osm_alias_guid_new(p_ni->port_guid, p_port); if (PF(!p_alias_guid)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D11: " "alias guid memory allocation failed" " for port GUID 0x%" PRIx64 "\n", cl_ntoh64(p_ni->port_guid)); goto alias_done; } /* insert into alias guid table */ p_alias_guid_check = (osm_alias_guid_t *) cl_qmap_insert(&sm->p_subn->alias_port_guid_tbl, p_alias_guid->alias_guid, &p_alias_guid->map_item); if (p_alias_guid_check != p_alias_guid) { /* alias GUID is a duplicate */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D13: " "Duplicate alias port GUID 0x%" PRIx64 "\n", cl_ntoh64(p_ni->port_guid)); osm_alias_guid_delete(&p_alias_guid); osm_port_delete(&p_port); goto Exit; } alias_done: /* If we are a master, then this means the port is new on the subnet. Mark it as new - need to send trap 64 for these ports. The condition that we are master is true, since if we are in discovering state (meaning we woke up from standby or we are just initializing), then these ports may be new to us, but are not new on the subnet. If we are master, then the subnet as we know it is the updated one, and any new ports we encounter should cause trap 64. C14-72.1.1 */ if (sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER) p_port->is_new = 1; } else { osm_physp_t *p_physp = osm_node_get_physp_ptr(p_node, port_num); if (PF(p_physp == NULL)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D1C: " "No physical port found for node GUID 0x%" PRIx64 " port %u. Might be duplicate port GUID\n", cl_ntoh64(p_node->node_info.node_guid), port_num); goto Exit; } /* Update the DR Path to the port, in case the old one is no longer available. */ p_dr_path = osm_physp_get_dr_path_ptr(p_physp); osm_dr_path_init(p_dr_path, p_smp->hop_count, p_smp->initial_path); } ni_rcv_get_port_info(sm, p_node, p_madw); Exit: OSM_LOG_EXIT(sm->p_log); }
ib_api_status_t osm_transaction_mgr_insert_madw(IN osm_bind_handle_t * const p_bind, IN osm_madw_t * p_madw) { #ifdef OSM_VENDOR_INTF_MTL osm_vendor_t *const p_vend = ((osm_mtl_bind_info_t *) p_bind)->p_vend; #else osm_vendor_t *const p_vend = ((osm_ts_bind_info_t *) p_bind)->p_vend; #endif osm_transaction_mgr_t *trans_mgr_p; osm_madw_req_t *osm_madw_req_p; uint64_t timeout; uint64_t waking_time; cl_status_t cl_status; uint64_t key; const ib_mad_t *mad_p = p_madw->p_mad; OSM_LOG_ENTER(p_vend->p_log); CL_ASSERT(mad_p); trans_mgr_p = (osm_transaction_mgr_t *) p_vend->p_transaction_mgr; timeout = (uint64_t) (p_vend->timeout) * 1000; /* change the miliseconds value of timeout to microseconds. */ waking_time = timeout + cl_get_time_stamp(); osm_madw_req_p = (osm_madw_req_t *) malloc(sizeof(osm_madw_req_t)); osm_madw_req_p->p_madw = p_madw; osm_madw_req_p->waking_time = waking_time; osm_madw_req_p->retry_cnt = OSM_DEFAULT_RETRY_COUNT; osm_madw_req_p->p_bind = p_bind; osm_log(p_vend->p_log, OSM_LOG_DEBUG, "osm_transaction_mgr_insert_madw: " "Inserting MADW:%p with waking_time: <0x%" PRIx64 "> TID:<0x%" PRIx64 ">.\n", p_madw, waking_time, p_madw->p_mad->trans_id); /* Get the lock on the manager */ cl_spinlock_acquire(&(trans_mgr_p->transaction_mgr_lock)); /* If the list is empty - need to start the timer with timer of timeout (in miliseconds) */ if (cl_is_qlist_empty(trans_mgr_p->madw_reqs_list_p)) { /* stop the timer if it is running */ cl_timer_stop(&trans_mgr_p->madw_list_timer); /* start the timer to the timeout (in miliseconds) */ cl_status = cl_timer_start(&trans_mgr_p->madw_list_timer, p_vend->timeout); if (cl_status != CL_SUCCESS) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_transaction_mgr_insert_madw : ERROR 1000: " "Failed to start timer\n"); } } /* insert the object to the qlist and the qmap */ cl_qlist_insert_tail(trans_mgr_p->madw_reqs_list_p, &(osm_madw_req_p->list_item)); /* get the key */ key = (uint64_t) mad_p->trans_id; cl_qmap_insert(trans_mgr_p->madw_by_tid_map_p, key, &(osm_madw_req_p->map_item)); cl_spinlock_release(&trans_mgr_p->transaction_mgr_lock); OSM_LOG_EXIT(p_vend->p_log); return (IB_SUCCESS); }
/********************************************************************** Lock must be held on entry to this function. **********************************************************************/ static void si_rcv_process_new(IN osm_sm_t * sm, IN osm_node_t * p_node, IN const osm_madw_t * p_madw) { osm_switch_t *p_sw; osm_switch_t *p_check; ib_switch_info_t *p_si; ib_smp_t *p_smp; cl_qmap_t *p_sw_guid_tbl; CL_ASSERT(sm); OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_madw); p_sw_guid_tbl = &sm->p_subn->sw_guid_tbl; p_smp = osm_madw_get_smp_ptr(p_madw); p_si = ib_smp_get_payload_ptr(p_smp); osm_dump_switch_info_v2(sm->p_log, p_si, FILE_ID, OSM_LOG_DEBUG); p_sw = osm_switch_new(p_node, p_madw); if (p_sw == NULL) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3608: " "Unable to allocate new switch object\n"); goto Exit; } /* set subnet max mlid to the minimum MulticastFDBCap of all switches */ if (cl_ntoh16(p_si->mcast_cap) + IB_LID_MCAST_START_HO - 1 < sm->p_subn->max_mcast_lid_ho) { sm->p_subn->max_mcast_lid_ho = cl_ntoh16(p_si->mcast_cap) + IB_LID_MCAST_START_HO - 1; OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Subnet max multicast lid is 0x%X\n", sm->p_subn->max_mcast_lid_ho); } /* set subnet max unicast lid to the minimum LinearFDBCap of all switches */ if (cl_ntoh16(p_si->lin_cap) < sm->p_subn->max_ucast_lid_ho) { sm->p_subn->max_ucast_lid_ho = cl_ntoh16(p_si->lin_cap); OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Subnet max unicast lid is 0x%X\n", sm->p_subn->max_ucast_lid_ho); } p_check = (osm_switch_t *) cl_qmap_insert(p_sw_guid_tbl, osm_node_get_node_guid (p_node), &p_sw->map_item); if (p_check != p_sw) { /* This shouldn't happen since we hold the lock! */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3605: " "Unable to add new switch object to database\n"); osm_switch_delete(&p_sw); goto Exit; } p_node->sw = p_sw; /* Update the switch info according to the info we just received. */ osm_switch_set_switch_info(p_sw, p_si); #if 0 /* Don't bother retrieving the current unicast and multicast tables from the switches. The current version of SM does not support silent take-over of an existing multicast configuration. Gathering the multicast tables can also generate large amounts of extra subnet-init traffic. The code to retrieve the tables was fully debugged. */ si_rcv_get_fwd_tbl(sm, p_sw); if (!sm->p_subn->opt.disable_multicast) si_rcv_get_mcast_fwd_tbl(sm, p_sw); #endif Exit: OSM_LOG_EXIT(sm->p_log); }
cl_status_t cl_event_wheel_reg(IN cl_event_wheel_t * const p_event_wheel, IN const uint64_t key, IN const uint64_t aging_time_usec, IN cl_pfn_event_aged_cb_t pfn_callback, IN void *const context) { cl_event_wheel_reg_info_t *p_event; uint64_t timeout; uint32_t to; cl_status_t cl_status = CL_SUCCESS; cl_list_item_t *prev_event_list_item; cl_map_item_t *p_map_item; /* Get the lock on the manager */ cl_spinlock_acquire(&(p_event_wheel->lock)); cl_event_wheel_dump(p_event_wheel); /* Make sure such a key does not exists */ p_map_item = cl_qmap_get(&p_event_wheel->events_map, key); if (p_map_item != cl_qmap_end(&p_event_wheel->events_map)) { CL_DBG("cl_event_wheel_reg: Already exists key:0x%" PRIx64 "\n", key); /* already there - remove it from the list as it is getting a new time */ p_event = PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, map_item); /* remove the item from the qlist */ cl_qlist_remove_item(&p_event_wheel->events_wheel, &p_event->list_item); /* and the qmap */ cl_qmap_remove_item(&p_event_wheel->events_map, &p_event->map_item); } else { /* make a new one */ p_event = (cl_event_wheel_reg_info_t *) malloc(sizeof(cl_event_wheel_reg_info_t)); p_event->num_regs = 0; } p_event->key = key; p_event->aging_time = aging_time_usec; p_event->pfn_aged_callback = pfn_callback; p_event->context = context; p_event->num_regs++; CL_DBG("cl_event_wheel_reg: Registering event key:0x%" PRIx64 " aging in %u [msec]\n", p_event->key, (uint32_t) ((p_event->aging_time - cl_get_time_stamp()) / 1000)); /* If the list is empty - need to start the timer */ if (cl_is_qlist_empty(&p_event_wheel->events_wheel)) { /* Edward Bortnikov 03/29/2003 * ++TBD Consider moving the timer manipulation behind the list manipulation. */ /* calculate the new timeout */ timeout = (p_event->aging_time - cl_get_time_stamp() + 500) / 1000; /* stop the timer if it is running */ /* Edward Bortnikov 03/29/2003 * Don't call cl_timer_stop() because it spins forever. * cl_timer_start() will invoke cl_timer_stop() by itself. * * The problematic scenario is when __cl_event_wheel_callback() * is in race condition with this code. It sets timer.in_timer_cb * to TRUE and then blocks on p_event_wheel->lock. Following this, * the call to cl_timer_stop() hangs. Following this, the whole system * enters into a deadlock. * * cl_timer_stop(&p_event_wheel->timer); */ /* The timeout for the cl_timer_start should be given as uint32_t. if there is an overflow - warn about it. */ to = (uint32_t) timeout; if (timeout > (uint32_t) timeout) { to = 0xffffffff; /* max 32 bit timer */ CL_DBG("cl_event_wheel_reg: timeout requested is " "too large. Using timeout: %u\n", to); } /* start the timer to the timeout [msec] */ cl_status = cl_timer_start(&p_event_wheel->timer, to); if (cl_status != CL_SUCCESS) { CL_DBG("cl_event_wheel_reg : ERR 6203: " "Failed to start timer\n"); goto Exit; } } /* insert the object to the qlist and the qmap */ /* BUT WE MUST INSERT IT IN A SORTED MANNER */ prev_event_list_item = cl_qlist_find_from_tail(&p_event_wheel->events_wheel, __event_will_age_before, &p_event->aging_time); cl_qlist_insert_next(&p_event_wheel->events_wheel, prev_event_list_item, &p_event->list_item); cl_qmap_insert(&p_event_wheel->events_map, key, &(p_event->map_item)); Exit: cl_spinlock_release(&p_event_wheel->lock); return cl_status; }