static void removedir(const char *dirname) { DIR *dp; struct dirent *ep; char abs_filename[SSA_DB_HELPER_PATH_MAX]; dp = opendir(dirname); if (dp != NULL) { while ((ep = readdir(dp))) { snprintf(abs_filename, SSA_DB_HELPER_PATH_MAX, "%s/%s", dirname, ep->d_name); if (ep->d_type == DT_DIR) { if (strcmp(ep->d_name, ".") && strcmp(ep->d_name, "..")) removedir(abs_filename); } else { if (remove(abs_filename)) ssa_log(SSA_LOG_DEFAULT, "unable to remove file %s ERROR %d (%s)\n", abs_filename, errno, strerror(errno)); } } closedir(dp); } else { ssa_log_err(SSA_LOG_DEFAULT, "Couldn't open '%s' directory\n", dirname); } if (remove(dirname)) ssa_log(SSA_LOG_DEFAULT, "unable to remove directory %s ERROR %d (%s)\n", dirname, errno, strerror(errno)); }
static int distrib_process_msg(struct ssa_svc *svc, struct ssa_ctrl_msg_buf *msg, struct pollfd *pfd) { ssa_log(SSA_LOG_VERBOSE | SSA_LOG_CTRL, "%s\n", svc->name); switch(msg->hdr.type) { case SSA_CTRL_MAD: return distrib_process_ssa_mad(svc, msg, pfd); case SSA_DB_UPDATE: ssa_log(SSA_LOG_DEFAULT, "SSA DB update ssa_db %p epoch 0x%" PRIx64 "\n", ((struct ssa_db_update_msg *)msg)->db_upd.db, ((struct ssa_db_update_msg *)msg)->db_upd.epoch); if (smdb_dump) ssa_db_save(smdb_dump_dir, (struct ssa_db *)(((struct ssa_db_update_msg *)msg)->db_upd.db), smdb_dump); return 1; case SSA_CTRL_DEV_EVENT: case SSA_CONN_REQ: case SSA_CONN_DONE: case SSA_CONN_GONE: break; default: ssa_log_warn(SSA_LOG_CTRL, "ignoring unexpected message type %d\n", msg->hdr.type); break; } return 0; }
/* recursive function - equivalent to linux 'mkdir -p' */ static void mkpath(const char *dir, mode_t mode) { struct stat dstat; char path[128]; char *p = NULL; snprintf(path, sizeof path, "%s", dir); for (p = path + strlen(dir) - 1; p != path; p--) { if (*p != '/') continue; *p = '\0'; break; } if (!lstat(path, &dstat)) { if (!lstat(dir, &dstat)) removedir(dir); if (mkdir(dir, mode)) ssa_log(SSA_LOG_DEFAULT, "unable to create %s directory ERROR %d (%s)\n", dir, errno, strerror(errno)); return; } mkpath(path, mode); if (!lstat(dir, &dstat)) removedir(dir); if (mkdir(dir, mode)) ssa_log(SSA_LOG_DEFAULT, "unable to create %s directory ERROR %d (%s)\n", dir, errno, strerror(errno)); }
/** =========================================================================== */ 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; }
void ssa_log_options() { char hostname[HOST_NAME_MAX]; gethostname(hostname, HOST_NAME_MAX); ssa_log(SSA_LOG_DEFAULT, "SSA version %s\n", IB_SSA_VERSION); ssa_log(SSA_LOG_DEFAULT, "host name %s\n", hostname); ssa_log(SSA_LOG_DEFAULT, "log level 0x%x\n", log_level); ssa_log(SSA_LOG_DEFAULT, "accumulate log file: %s (%d)\n", accum_log_file ? "true" : "false", accum_log_file); }
static void distrib_destroy() { ssa_log(SSA_LOG_DEFAULT, "shutting down\n"); ssa_ctrl_stop(&ssa); ssa_log(SSA_LOG_CTRL, "shutting down access thread\n"); ssa_stop_access(&ssa); ssa_log(SSA_LOG_CTRL, "closing devices\n"); ssa_close_devices(&ssa); ssa_log(SSA_LOG_VERBOSE, "that's all folks!\n"); ssa_cleanup(&ssa); ssa_close_log(); ssa_close_lock_file(); }
static int distrib_process_ssa_mad(struct ssa_svc *svc, struct ssa_ctrl_msg_buf *msg, struct pollfd *pfd) { struct ssa_umad *umad; umad = &msg->data.umad; if (umad->umad.status) { ssa_log(SSA_LOG_DEFAULT, "SSA MAD method 0x%x (%s) attribute 0x%x (%s) received with status 0x%x\n", umad->packet.mad_hdr.method, ssa_method_str(umad->packet.mad_hdr.method), ntohs(umad->packet.mad_hdr.attr_id), ssa_attribute_str(umad->packet.mad_hdr.attr_id), umad->umad.status); return 0; } switch (umad->packet.mad_hdr.method) { case UMAD_METHOD_SET: if (ntohs(umad->packet.mad_hdr.attr_id) == SSA_ATTR_INFO_REC) { distrib_process_parent_set(svc, msg, pfd); return 1; } break; default: break; } return 0; }
static void *distrib_construct(int node_type, unsigned short daemon) { int ret; char msg[1024] = {}; ret = ssa_open_lock_file(lock_file, msg, sizeof msg); if (ret) { if (!daemon) fprintf(stderr, "%s\n", msg); openlog("ibssa", LOG_PERROR | LOG_PID, LOG_USER); syslog(LOG_INFO, "%s", msg); closelog(); return NULL; } ret = ssa_open_log(log_file); if (ret) { ssa_close_lock_file(); return NULL; } ssa_set_ssa_signal_handler(); ssa_log(SSA_LOG_DEFAULT, "Scalable SA Distribution/Access\n"); distrib_log_options(); ret = ssa_init(&ssa, node_type, sizeof(struct ssa_device), sizeof(struct ssa_port)); if (ret) { ssa_close_log(); ssa_close_lock_file(); return NULL; } return &ssa; }
/** =========================================================================== */ void ssa_db_lft_handle(void) { struct ssa_db_lft_change_rec *p_lft_change_rec; cl_list_item_t *p_item; pthread_mutex_lock(&ssa_db->lft_rec_list_lock); while ((p_item = cl_qlist_remove_head(&ssa_db->lft_rec_list)) != cl_qlist_end(&ssa_db->lft_rec_list)) { p_lft_change_rec = cl_item_obj(p_item, p_lft_change_rec, list_item); switch (p_lft_change_rec->lft_change.flags) { case LFT_CHANGED_BLOCK: lft_block_handle(p_lft_change_rec); break; case LFT_CHANGED_LFT_TOP: lft_top_handle(p_lft_change_rec); break; default: ssa_log(SSA_LOG_ALL, "Unknown LFT change event (%d)\n", p_lft_change_rec->lft_change.flags); break; } free(p_lft_change_rec); } pthread_mutex_unlock(&ssa_db->lft_rec_list_lock); }
void ssa_db_save(const char *path_dir, const struct ssa_db *p_ssa_db, enum ssa_db_helper_mode mode) { FILE *fd; int i = 0, tbls_n = 0; char buffer[SSA_DB_HELPER_PATH_MAX] = {}; ssa_log_func(SSA_LOG_DEFAULT); assert(p_ssa_db); mkpath(path_dir, S_IRWXU | S_IRWXG | S_IRWXO); tbls_n = ntohll(p_ssa_db->db_table_def.set_count); /****************** Dumping db_def record *******************/ sprintf(buffer, "%s/%s", path_dir, SSA_DB_HELPER_DB_DEF_NAME); fd = fopen(buffer, SSA_DB_HELPER_FILE_WRITE_MODE_TXT); if (!fd) { ssa_log_err(SSA_LOG_DEFAULT, "Failed opening %s file\n", buffer); return; } ssa_db_db_def_dump(fd, &p_ssa_db->db_def); fclose(fd); /************************************************************/ for (i = 0; i < tbls_n; ++i) { if (p_ssa_db->p_def_tbl[i].type == DBT_TYPE_DATA) { int j = 0, k = 0; struct db_id id = p_ssa_db->p_def_tbl[i].id; /* Data table id */ for (j = 0; j < tbls_n; j++) if (p_ssa_db->p_def_tbl[j].type == DBT_TYPE_DEF && ntohl(p_ssa_db->p_def_tbl[j].ref_table_id) == id.table) break; for (k = 0; k < p_ssa_db->data_tbl_cnt; k++) if (p_ssa_db->p_db_tables[k].id.table == id.table) break; /* creating a directory for each dataset */ sprintf(buffer, "mkdir \"%s/%s\"", path_dir, p_ssa_db->p_def_tbl[i].name); if (system(buffer) != 0) { ssa_log_err(SSA_LOG_DEFAULT, "unable to create %s/%s directory - %s (%d)\n", path_dir, p_ssa_db->p_def_tbl[i].name, strerror(errno), errno); break; } /* dump dataset and its field dataset */ sprintf(buffer, "%s/%s", path_dir, p_ssa_db->p_def_tbl[i].name); ssa_db_tbl_dump(buffer, p_ssa_db, i, j, k, mode); ssa_log(SSA_LOG_DEFAULT, "%s table was saved\n", p_ssa_db->p_def_tbl[i].name); } } }
static void *distrib_ctrl_handler(void *context) { struct ssa_svc *svc; struct ssa_port *port; int ret, d, p; SET_THREAD_NAME(ctrl_thread, "CTRL"); ssa_log(SSA_LOG_VERBOSE, "starting SSA framework\n"); ret = ssa_open_devices(&ssa); if (ret) { ssa_log(SSA_LOG_DEFAULT, "ERROR opening devices\n"); return NULL; } for (d = 0; d < ssa.dev_cnt; d++) { for (p = 1; p <= ssa_dev(&ssa, d)->port_cnt; p++) { port = ssa_dev_port(ssa_dev(&ssa, d), p); if (port->link_layer != IBV_LINK_LAYER_INFINIBAND) continue; svc = ssa_start_svc(port, SSA_DB_PATH_DATA, sizeof(struct ssa_distrib), distrib_process_msg, distrib_init_svc, distrib_destroy_svc); if (!svc) { ssa_log(SSA_LOG_DEFAULT, "ERROR starting service\n"); goto close; } } } ret = ssa_start_access(&ssa); if (ret) { ssa_log(SSA_LOG_DEFAULT, "ERROR starting access thread\n"); goto close; } ret = ssa_start_admin(&ssa); if (ret) { ssa_log(SSA_LOG_DEFAULT, "ERROR starting admin thread\n"); goto close; } ret = ssa_ctrl_run(&ssa); if (ret) { ssa_log(SSA_LOG_DEFAULT, "ERROR processing control\n"); ssa_stop_access(&ssa); goto close; } close: ssa_log(SSA_LOG_VERBOSE, "closing SSA framework\n"); ssa_stop_admin(); ssa_close_devices(&ssa); return context; }
/** =========================================================================== */ 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; }
/* TODO: Add meaningful return value */ void ssa_db_update(struct ssa_database *ssa_db) { ssa_log(SSA_LOG_VERBOSE, "[\n"); if (!ssa_db || !ssa_db->p_previous_db || !ssa_db->p_current_db || !ssa_db->p_dump_db) { /* error handling */ return; } /* Updating previous SMDB with current one */ if (ssa_db->p_current_db->initialized) { ssa_db_extract_delete(ssa_db->p_previous_db); ssa_db->p_previous_db = ssa_db->p_current_db; } else { ssa_db_extract_delete(ssa_db->p_current_db); } ssa_db->p_current_db = ssa_db->p_dump_db; ssa_db->p_dump_db = ssa_db_extract_init(); ssa_log(SSA_LOG_VERBOSE, "]\n"); }
/** =========================================================================== */ void ssa_db_validate_lft(int first) { struct smdb_lft_block lft_block; struct smdb_lft_top lft_top; int i; if (!first || !(ssa_get_log_level() & SSA_LOG_DB)) return; for (i = 0; i < cl_qmap_count(&ssa_db->p_lft_db->ep_db_lft_block_tbl); i++) { lft_block = ssa_db->p_lft_db->p_db_lft_block_tbl[i]; ssa_log(SSA_LOG_DB, "LFT Block Record: LID %u Block num %u\n", ntohs(lft_block.lid), ntohs(lft_block.block_num)); } for (i = 0; i < cl_qmap_count(&ssa_db->p_lft_db->ep_db_lft_top_tbl); i++) { lft_top = ssa_db->p_lft_db->p_db_lft_top_tbl[i]; ssa_log(SSA_LOG_DB, "LFT Top Record: LID %u New Top %u\n", ntohs(lft_top.lid), ntohs(lft_top.lft_top)); } }
/** =========================================================================== */ 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); }
/** =========================================================================== */ 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); }
struct host_addr *parse_addr(const char *addr_file, uint64_t size_hint, uint64_t *ipv4, uint64_t *ipv6, uint64_t *name) { FILE *fd = NULL; struct host_addr *tmp, *host_addrs = NULL; struct host_addr host_addr; struct stat fstats; char s[LINE_LEN], err_buf[64]; int idx, i = 0, line = 0; size_t records; uint16_t pkey = DEFAULT_PKEY; if (!(fd = fopen(addr_file, "r"))) { ssa_log_err(SSA_LOG_DEFAULT, "unable to open %s\n", addr_file); goto out; } if (fstat(fd->_fileno, &fstats) < 0) { ssa_log_err(SSA_LOG_DEFAULT, "unable to get addr file (%s) stats\n", addr_file); goto out; } size_hint = max(size_hint, fstats.st_size / LINE_LEN + 1); records = (size_hint / ADDRESS_BLOCK_SIZE + 1) * ADDRESS_BLOCK_SIZE; host_addrs = malloc(sizeof(*host_addrs) * records); if (!host_addrs) { ssa_log_err(SSA_LOG_DEFAULT, "unable to allocate memory\n"); goto out; } *ipv4 = *ipv6 = *name = 0; while (fgets(s, sizeof s, fd)) { line++; idx = 0; while (isspace(s[idx])) idx++; if (s[idx] == '#') continue; if (s[idx] == '[' && s[strlen(s) - 2] == ']') { pkey = get_pkey(s + idx); continue; } snprintf(err_buf, sizeof(err_buf), "%s:%d", addr_file, line); if (get_addr_record(s + idx, err_buf, pkey, &host_addr)) continue; if (i >= size_hint && !(i % ADDRESS_BLOCK_SIZE)) { tmp = realloc(host_addrs, sizeof(*host_addrs) * (i + ADDRESS_BLOCK_SIZE)); if (!tmp) { ssa_log_err(SSA_LOG_DEFAULT, "unable to allocate memory\n"); free(host_addrs); host_addrs = NULL; goto out; } host_addrs = tmp; } host_addrs[i++] = host_addr; if (host_addr.addr_type == ADDRESS_IP) (*ipv4)++; else if (host_addr.addr_type == ADDRESS_IP6) (*ipv6)++; else (*name)++; } ssa_log(SSA_LOG_VERBOSE, "IPv4 %lu IPv6 %lu NAME %lu\n", *ipv4, *ipv6, *name); out: if (fd) fclose(fd); return host_addrs; }
void ssa_log_options() { ssa_log(SSA_LOG_DEFAULT, "log level 0x%x\n", log_level); }
static void distrib_log_options(void) { ssa_log_options(); ssa_log(SSA_LOG_DEFAULT, "config file %s\n", opts_file); ssa_log(SSA_LOG_DEFAULT, "lock file %s\n", lock_file); ssa_log(SSA_LOG_DEFAULT, "node type %d (%s)\n", node_type, ssa_node_type_str(node_type)); ssa_log(SSA_LOG_DEFAULT, "smdb dump %d\n", smdb_dump); ssa_log(SSA_LOG_DEFAULT, "err smdb dump %d\n", err_smdb_dump); ssa_log(SSA_LOG_DEFAULT, "smdb dump dir %s\n", smdb_dump_dir); ssa_log(SSA_LOG_DEFAULT, "prdb dump %d\n", prdb_dump); ssa_log(SSA_LOG_DEFAULT, "prdb dump dir %s\n", prdb_dump_dir); ssa_log(SSA_LOG_DEFAULT, "smdb port %u\n", smdb_port); ssa_log(SSA_LOG_DEFAULT, "prdb port %u\n", prdb_port); ssa_log(SSA_LOG_DEFAULT, "admin port %u\n", admin_port); ssa_log(SSA_LOG_DEFAULT, "keepalive time %d\n", keepalive); #ifdef SIM_SUPPORT_FAKE_ACM if (node_type & SSA_NODE_ACCESS) { ssa_log(SSA_LOG_DEFAULT, "running in ACM clients simulated mode\n"); if (fake_acm_num >= 0) ssa_log(SSA_LOG_DEFAULT, "Max. number of simulated" " clients is %d\n", fake_acm_num); else ssa_log(SSA_LOG_DEFAULT, "Max. number of simulated" " clients is unlimited\n"); } #endif if (reconnect_max_count < 0 || reconnect_timeout < 0) { ssa_log(SSA_LOG_DEFAULT, "reconnection to upstream node disabled\n"); } else { ssa_log(SSA_LOG_DEFAULT, "max. number of reconnections to upstream node %d\n", reconnect_max_count); ssa_log(SSA_LOG_DEFAULT, "timeout between reconnections (in sec.) %d\n", reconnect_timeout); } if (rejoin_timeout < 0) ssa_log(SSA_LOG_DEFAULT, "rejoin to distribution tree after previous request failure disabled\n"); else ssa_log(SSA_LOG_DEFAULT, "timeout before next join request (in sec.) %d\n", rejoin_timeout ); }
/** =========================================================================== */ static int extract_alloc_tbls(osm_subn_t *p_subn, struct ssa_db_extract *p_ssa_db) { const osm_pkey_tbl_t *p_pkey_tbl; osm_switch_t *p_sw; osm_port_t *p_port; uint64_t links, ports, lft_blocks; uint32_t guids, nodes, lft_tops; uint32_t switch_ports_num = 0; uint32_t pkey_cnt = 0; uint16_t lids; nodes = (uint32_t) cl_qmap_count(&p_subn->node_guid_tbl); if (!p_ssa_db->p_node_tbl) { p_ssa_db->p_node_tbl = (struct smdb_node *) malloc(sizeof(*p_ssa_db->p_node_tbl) * nodes); if (!p_ssa_db->p_node_tbl) { ssa_log(SSA_LOG_DEFAULT, "ERROR - unable to allocate nodes table\n"); goto err0; } } lft_tops = (uint32_t) cl_qmap_count(&p_subn->sw_guid_tbl); if (!ssa_db->p_lft_db->p_db_lft_top_tbl) { ssa_db->p_lft_db->p_db_lft_top_tbl = (struct smdb_lft_top *) malloc(sizeof(*ssa_db->p_lft_db->p_db_lft_top_tbl) * lft_tops); if (!ssa_db->p_lft_db->p_db_lft_top_tbl) { ssa_log(SSA_LOG_DEFAULT, "ERROR - unable to allocate LFT tops table\n"); goto err1; } } lids = (uint16_t) cl_ptr_vector_get_size(&p_subn->port_lid_tbl); lft_blocks = ((lids % IB_SMP_DATA_SIZE) ? (lids / IB_SMP_DATA_SIZE + 1) : (lids / IB_SMP_DATA_SIZE)); lft_blocks = (uint64_t) lft_tops * lft_blocks * (1 << p_ssa_db->lmc); if (!ssa_db->p_lft_db->p_db_lft_block_tbl) { ssa_db->p_lft_db->p_db_lft_block_tbl = (struct smdb_lft_block *) malloc(sizeof(*ssa_db->p_lft_db->p_db_lft_block_tbl) * lft_blocks); if (!ssa_db->p_lft_db->p_db_lft_block_tbl) { ssa_log(SSA_LOG_DEFAULT, "ERROR - unable to allocate LFT blocks table\n"); goto err2; } } guids = (uint32_t) cl_qmap_count(&p_subn->port_guid_tbl); if (!p_ssa_db->p_guid_to_lid_tbl) { p_ssa_db->p_guid_to_lid_tbl = (struct smdb_guid2lid *) malloc(sizeof(*p_ssa_db->p_guid_to_lid_tbl) * guids); if (!p_ssa_db->p_guid_to_lid_tbl) { ssa_log(SSA_LOG_DEFAULT, "ERROR - unable to allocate GUID to LID table\n"); goto err3; } } for (p_sw = (osm_switch_t *)cl_qmap_head(&p_subn->sw_guid_tbl); p_sw != (osm_switch_t *)cl_qmap_end(&p_subn->sw_guid_tbl); p_sw = (osm_switch_t *)cl_qmap_next(&p_sw->map_item)) switch_ports_num += p_sw->num_ports; links = guids + switch_ports_num; if (!p_ssa_db->p_link_tbl) { p_ssa_db->p_link_tbl = (struct smdb_link *) malloc(sizeof(*p_ssa_db->p_link_tbl) * links); if (!p_ssa_db->p_link_tbl) { ssa_log(SSA_LOG_DEFAULT, "ERROR - unable to allocate links table\n"); goto err4; } } ports = links; if (!p_ssa_db->p_port_tbl) { p_ssa_db->p_port_tbl = (struct smdb_port *) malloc(sizeof(*p_ssa_db->p_port_tbl) * ports); if (!p_ssa_db->p_port_tbl) { ssa_log(SSA_LOG_DEFAULT, "ERROR - unable to allocate ports table\n"); goto err5; } } for (p_port = (osm_port_t *)cl_qmap_head(&p_subn->port_guid_tbl); p_port != (osm_port_t *)cl_qmap_end(&p_subn->port_guid_tbl); p_port = (osm_port_t *)cl_qmap_next(&p_port->map_item)) { p_pkey_tbl = osm_physp_get_pkey_tbl(p_port->p_physp); pkey_cnt += (uint32_t) cl_map_count((const cl_map_t *) &p_pkey_tbl->keys); } if (!p_ssa_db->p_pkey_tbl) { p_ssa_db->p_pkey_tbl = (uint16_t *) malloc(sizeof(*p_ssa_db->p_pkey_tbl) * pkey_cnt); if (!p_ssa_db->p_pkey_tbl) { ssa_log(SSA_LOG_DEFAULT, "ERROR - unable to allocate pkeys table\n"); goto err6; } } p_ssa_db->pkey_tbl_rec_num = pkey_cnt; return 0; err6: free(p_ssa_db->p_port_tbl); err5: free(p_ssa_db->p_link_tbl); err4: free(p_ssa_db->p_guid_to_lid_tbl); err3: free(ssa_db->p_lft_db->p_db_lft_block_tbl); err2: free(ssa_db->p_lft_db->p_db_lft_top_tbl); err1: free(p_ssa_db->p_node_tbl); err0: return -1; }
/** =========================================================================== */ void ssa_db_validate(struct ssa_db_extract *p_ssa_db) { struct smdb_guid2lid guid2lid; struct smdb_node node; struct smdb_link link; struct smdb_port port; uint64_t i; char buffer[64]; if (!p_ssa_db || !p_ssa_db->initialized || !(ssa_get_log_level() & SSA_LOG_DB)) return; ssa_log(SSA_LOG_DB, "[\n"); /* First, most Fabric/SM related parameters */ ssa_log(SSA_LOG_DB, "Subnet prefix 0x%" PRIx64 "\n", ntohll(p_ssa_db->subnet_prefix)); ssa_log(SSA_LOG_DB, "LMC %u Subnet timeout %u Both Pkeys %sabled\n", p_ssa_db->lmc, p_ssa_db->subnet_timeout, p_ssa_db->allow_both_pkeys ? "en" : "dis"); for (i = 0; i < cl_qmap_count(&p_ssa_db->ep_node_tbl); i++) { node = p_ssa_db->p_node_tbl[i]; if (node.node_type == IB_NODE_TYPE_SWITCH) sprintf(buffer, " with %s Switch Port 0\n", node.is_enhanced_sp0 ? "Enhanced" : "Base"); else sprintf(buffer, "\n"); ssa_log(SSA_LOG_DB, "Node GUID 0x%" PRIx64 " Type %d%s", ntohll(node.node_guid), node.node_type, buffer); } for (i = 0; i < cl_qmap_count(&p_ssa_db->ep_guid_to_lid_tbl); i++) { guid2lid = p_ssa_db->p_guid_to_lid_tbl[i]; ssa_log(SSA_LOG_DB, "Port GUID 0x%" PRIx64 " LID %u LMC %u is_switch %d\n", ntohll(guid2lid.guid), ntohs(guid2lid.lid), guid2lid.lmc, guid2lid.is_switch); } for (i = 0; i < cl_qmap_count(&p_ssa_db->ep_port_tbl); i++) { port = p_ssa_db->p_port_tbl[i]; ssa_log(SSA_LOG_DB, "Port LID %u Port Num %u\n", ntohs(port.port_lid), port.port_num); ssa_log(SSA_LOG_DB, "MTUCapability %u rate %u\n", port.mtu_cap, port.rate & SSA_DB_PORT_RATE_MASK); ssa_log(SSA_LOG_DB, "FDR10 %s active\n", (port.rate & SSA_DB_PORT_IS_FDR10_ACTIVE_MASK) ? "" : "not"); ssa_log(SSA_LOG_DB, "PKeys %u\n", ntohs(port.pkey_tbl_size) / sizeof(*p_ssa_db->p_pkey_tbl)); } for (i = 0; i < cl_qmap_count(&p_ssa_db->ep_link_tbl); i++) { link = p_ssa_db->p_link_tbl[i]; ssa_log(SSA_LOG_DB, "Link Record: from LID %u port %u to LID %u port %u\n", ntohs(link.from_lid), link.from_port_num, ntohs(link.to_lid), link.to_port_num); } ssa_log(SSA_LOG_DB, "]\n"); }
/** =========================================================================== */ struct ssa_db_extract *ssa_db_extract(osm_opensm_t *p_osm) { struct ssa_db_extract *p_ssa; osm_subn_t *p_subn = &p_osm->subn; osm_node_t *p_node, *p_next_node; osm_port_t *p_port, *p_next_port; uint64_t guid_to_lid_offset = 0; uint64_t node_offset = 0, link_offset = 0, port_offset = 0; uint64_t pkey_base_offset = 0, pkey_cur_offset = 0; uint64_t lft_top_offset = 0, lft_block_offset = 0; int lft_extract = 0; uint8_t ret = 0; ssa_log(SSA_LOG_VERBOSE, "[\n"); p_ssa = ssa_db->p_dump_db; extract_subnet_opts(p_subn, p_ssa); ret = extract_alloc_tbls(p_subn, p_ssa); if (ret) return NULL; if (cl_is_qmap_empty(&ssa_db->p_lft_db->ep_db_lft_block_tbl) && cl_is_qmap_empty(&ssa_db->p_lft_db->ep_db_lft_top_tbl)) lft_extract = 1; else if (cl_is_qmap_empty(&ssa_db->p_lft_db->ep_db_lft_block_tbl)) ssa_log_warn(SSA_LOG_DEFAULT, "inconsistent LFT block records\n"); else if (cl_is_qmap_empty(&ssa_db->p_lft_db->ep_db_lft_top_tbl)) ssa_log_warn(SSA_LOG_DEFAULT, "inconsistent LFT top records\n"); p_next_node = (osm_node_t *)cl_qmap_head(&p_subn->node_guid_tbl); while (p_next_node != (osm_node_t *)cl_qmap_end(&p_subn->node_guid_tbl)) { p_node = p_next_node; p_next_node = (osm_node_t *)cl_qmap_next(&p_node->map_item); extract_node(p_node, &node_offset, p_ssa); /* TODO: add more cases when full dump is needed */ if (!lft_extract) continue; /* Adding LFT tables * When the first SMDB dump is performed, all LFTs * are added automatically, further dumps or changes * will be done only on OSM_EVENT_ID_LFT_CHANGE */ if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) extract_lft(p_node->sw, &lft_top_offset, &lft_block_offset); } p_next_port = (osm_port_t *)cl_qmap_head(&p_subn->port_guid_tbl); while (p_next_port != (osm_port_t *)cl_qmap_end(&p_subn->port_guid_tbl)) { p_port = p_next_port; p_next_port = (osm_port_t *)cl_qmap_next(&p_port->map_item); extract_guid2lid(p_port, &guid_to_lid_offset, p_ssa); dump_port_qos(p_port); /* TODO:: add log info ??? */ if (osm_node_get_type(p_port->p_physp->p_node) == IB_NODE_TYPE_SWITCH) extract_switch_port(p_port, &pkey_base_offset, &pkey_cur_offset, &port_offset, &link_offset, p_ssa); else extract_host_port(p_port, &pkey_base_offset, &pkey_cur_offset, &port_offset, &link_offset, p_ssa); pkey_base_offset += pkey_cur_offset; pkey_cur_offset = 0; } p_ssa->initialized = 1; ssa_log(SSA_LOG_VERBOSE, "]\n"); return p_ssa; }
/** =========================================================================== */ static void dump_port_qos(osm_port_t *p_port) { #ifdef SSA_PLUGIN_VERBOSE_LOGGING const osm_pkey_tbl_t *p_pkey_tbl; const ib_pkey_table_t *block; //char *header_line = "#in out : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"; //char *separator_line = "#--------------------------------------------------------"; //ib_slvl_table_t *p_tbl; ib_net16_t pkey; uint16_t block_index, max_pkeys, pkey_idx; //uint8_t out_port, in_port, num_ports; //uint8_t n; // ssa_log(SSA_LOG_VERBOSE, "\t\t\tSLVL tables\n"); // ssa_log(SSA_LOG_VERBOSE, "%s\n", header_line); // ssa_log(SSA_LOG_VERBOSE, "%s\n", separator_line); // // out_port = p_port->p_physp->port_num; // num_ports = p_port->p_physp->p_node->node_info.num_ports; // if (osm_node_get_type(p_port->p_physp->p_node) == // IB_NODE_TYPE_SWITCH) { // /* no need to print SL2VL table for port that is down */ // /* TODO: not sure if it is needed */ // /*if (!p_port->p_physp->p_remote_physp) // continue; */ // // for (in_port = 0; in_port <= num_ports; in_port++) { // p_tbl = osm_physp_get_slvl_tbl(p_port->p_physp, // in_port); // for (i = 0, n = 0; i < 16; i++) // n += sprintf(buffer + n, " %-2d", // ib_slvl_table_get(p_tbl, i)); // ssa_log(SSA_LOG_VERBOSE, "%-3d %-3d :%s\n", // in_port, out_port, buffer); // } // } else { // p_tbl = osm_physp_get_slvl_tbl(p_port->p_physp, 0); // for (i = 0, n = 0; i < 16; i++) // n += sprintf(buffer + n, " %-2d", // ib_slvl_table_get(p_tbl, i)); // ssa_log(SSA_LOG_VERBOSE, "%-3d %-3d :%s\n", out_port, // out_port, buffer); // } // max_pkeys = ntohs(p_port->p_node->node_info.partition_cap); ssa_log(SSA_LOG_VERBOSE, "PartitionCap %u\n", max_pkeys); p_pkey_tbl = osm_physp_get_pkey_tbl(p_port->p_physp); ssa_log(SSA_LOG_VERBOSE, "PKey Table %u used blocks\n", p_pkey_tbl->used_blocks); for (block_index = 0; block_index < p_pkey_tbl->used_blocks; block_index++) { block = osm_pkey_tbl_new_block_get(p_pkey_tbl, block_index); if (!block) continue; for (pkey_idx = 0; pkey_idx < IB_NUM_PKEY_ELEMENTS_IN_BLOCK; pkey_idx++) { pkey = block->pkey_entry[pkey_idx]; if (ib_pkey_is_invalid(pkey)) continue; ssa_log(SSA_LOG_VERBOSE, "PKey 0x%04x at block %u " "index %u\n", ntohs(pkey), block_index, pkey_idx); } } #else (void)(p_port); #endif }
struct ssa_db *ssa_db_load(const char *path_dir, enum ssa_db_helper_mode mode) { DIR *d; FILE *fd; struct dirent *dir; struct ssa_db *p_ssa_db = NULL; char *tbl_names; uint64_t data_tbls_n = 0; uint64_t i = 0; struct db_table_def table_def; char buffer[SSA_DB_HELPER_PATH_MAX] = {}; ssa_log_func(SSA_LOG_DEFAULT); if (mode != SSA_DB_HELPER_STANDARD && mode != SSA_DB_HELPER_DEBUG) { ssa_log_err(SSA_LOG_DEFAULT, "mode (%d) not supported for loading\n", mode); return NULL; } d = opendir(path_dir); if (!d) return NULL; while ((dir = readdir(d)) != NULL) { if (dir->d_type != DT_DIR || !strcmp(dir->d_name, ".") || !strcmp(dir->d_name, "..")) continue; data_tbls_n++; } rewinddir(d); tbl_names = (char *) malloc(data_tbls_n * sizeof(*tbl_names) * DB_NAME_LEN); if (!tbl_names) { ssa_log_err(SSA_LOG_DEFAULT, "unable to allocate table names buffer\n"); closedir(d); return NULL; } while ((dir = readdir(d)) != NULL) { if (dir->d_type != DT_DIR || !strcmp(dir->d_name, ".") || !strcmp(dir->d_name, "..")) continue; sprintf(buffer, "%s/%s/%s", path_dir, dir->d_name, SSA_DB_HELPER_TABLE_DEF_NAME); fd = fopen(buffer, SSA_DB_HELPER_FILE_READ_MODE_TXT); if (!fd) { ssa_log_err(SSA_LOG_DEFAULT, "Failed opening %s file\n", buffer); closedir(d); goto Error; } ssa_db_table_def_load(fd, &table_def); fclose(fd); strcpy((tbl_names + DB_NAME_LEN * table_def.id.table), dir->d_name); } closedir(d); p_ssa_db = ssa_db_load_allocate_new(path_dir, tbl_names, data_tbls_n); if (!p_ssa_db) { ssa_log_err(SSA_LOG_DEFAULT, "Failed allocating SSA DB\n"); goto Error; } sprintf(buffer, "%s/%s", path_dir, SSA_DB_HELPER_DB_DEF_NAME); fd = fopen(buffer, SSA_DB_HELPER_FILE_READ_MODE_TXT); if (!fd) { ssa_log_err(SSA_LOG_DEFAULT, "Failed opening %s file\n", buffer); goto Error; } ssa_db_db_def_load(fd, &p_ssa_db->db_def); fclose(fd); ssa_db_dataset_init(&p_ssa_db->db_table_def, DB_DS_VERSION, sizeof(p_ssa_db->db_table_def), DBT_ACCESS_NET_ORDER, p_ssa_db->db_def.id.db, DBT_DEF_DS_ID, 0, 0 /* epoch */, 0 /* set_size */, 0 /* set_offset */, 0 /* set_count */); for (i = 0; i < data_tbls_n; i++) { sprintf(buffer, "%s/%s", path_dir, tbl_names + DB_NAME_LEN * i); ssa_db_tbl_load(buffer, p_ssa_db, i, mode); ssa_log(SSA_LOG_DEFAULT, "%s table was loaded\n", p_ssa_db->p_def_tbl[i].name); } free(tbl_names); return p_ssa_db; Error: free(tbl_names); if (p_ssa_db) ssa_db_destroy(p_ssa_db); return NULL; }