static void _lldpctl_atom_free_port(lldpctl_atom_t *atom) { struct _lldpctl_atom_port_t *port = (struct _lldpctl_atom_port_t *)atom; struct lldpd_hardware *hardware = port->hardware; struct lldpd_chassis *one_chassis, *one_chassis_next; struct lldpd_port *one_port; /* Free internal chassis atom. Should be freed immediately since we * should have the only reference. */ lldpctl_atom_dec_ref((lldpctl_atom_t*)port->chassis); /* We need to free the whole struct lldpd_hardware: local port, local * chassis and remote ports... The same chassis may be present several * times. We build a list of chassis (we don't use reference count). */ struct chassis_list chassis_list; TAILQ_INIT(&chassis_list); if (port->parent) lldpctl_atom_dec_ref((lldpctl_atom_t*)port->parent); else if (!hardware && port->port) { /* No parent, no hardware, we assume a single neighbor: one * port, one chassis. */ if (port->port->p_chassis) { lldpd_chassis_cleanup(port->port->p_chassis, 1); port->port->p_chassis = NULL; } lldpd_port_cleanup(port->port, 1); free(port->port); } if (!hardware) return; add_chassis(&chassis_list, port->port->p_chassis); TAILQ_FOREACH(one_port, &hardware->h_rports, p_entries) add_chassis(&chassis_list, one_port->p_chassis); /* Free hardware port */ lldpd_remote_cleanup(hardware, NULL, 1); lldpd_port_cleanup(port->port, 1); free(port->hardware); /* Free list of chassis */ for (one_chassis = TAILQ_FIRST(&chassis_list); one_chassis != NULL; one_chassis = one_chassis_next) { one_chassis_next = TAILQ_NEXT(one_chassis, c_entries); lldpd_chassis_cleanup(one_chassis, 1); } }
/* Main grouping function Algorithm: 1. pass on every Voltaire node 2. catch spine chip for every Voltaire node 2.1 build/interpolate chassis around this chip 2.2 go to 1. 3. pass on non Voltaire nodes (SystemImageGUID based grouping) 4. now group non Voltaire nodes by SystemImageGUID Returns: 0 on success, -1 on failure */ int group_nodes(ibnd_fabric_t * fabric) { ibnd_node_t *node; int chassisnum = 0; ibnd_chassis_t *chassis; ibnd_chassis_t *ch, *ch_next; chassis_scan_t chassis_scan; int vendor_id; chassis_scan.first_chassis = NULL; chassis_scan.current_chassis = NULL; chassis_scan.last_chassis = NULL; /* first pass on switches and build for every Voltaire node */ /* an appropriate chassis record (slotnum and position) */ /* according to internal connectivity */ /* not very efficient but clear code so... */ for (node = fabric->switches; node; node = node->type_next) { vendor_id = mad_get_field(node->info, 0,IB_NODE_VENDORID_F); if (vendor_id == VTR_VENDOR_ID && fill_voltaire_chassis_record(node)) goto cleanup; else if (vendor_id == MLX_VENDOR_ID && fill_mellanox_chassis_record(node)) goto cleanup; } /* separate every Voltaire chassis from each other and build linked list of them */ /* algorithm: catch spine and find all surrounding nodes */ for (node = fabric->switches; node; node = node->type_next) { if (mad_get_field(node->info, 0, IB_NODE_VENDORID_F) != VTR_VENDOR_ID) continue; if (!node->ch_found || (node->chassis && node->chassis->chassisnum) || !is_spine(node)) continue; if (add_chassis(&chassis_scan)) goto cleanup; chassis_scan.current_chassis->chassisnum = ++chassisnum; if (build_chassis(node, chassis_scan.current_chassis)) goto cleanup; } /* now make pass on nodes for chassis which are not Voltaire */ /* grouped by common SystemImageGUID */ for (node = fabric->nodes; node; node = node->next) { if (mad_get_field(node->info, 0, IB_NODE_VENDORID_F) == VTR_VENDOR_ID) continue; if (mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F)) { chassis = find_chassisguid(fabric, node); if (chassis) chassis->nodecount++; else { /* Possible new chassis */ if (add_chassis(&chassis_scan)) goto cleanup; chassis_scan.current_chassis->chassisguid = get_chassisguid(node); chassis_scan.current_chassis->nodecount = 1; if (!fabric->chassis) fabric->chassis = chassis_scan.first_chassis; } } } /* now, make another pass to see which nodes are part of chassis */ /* (defined as chassis->nodecount > 1) */ for (node = fabric->nodes; node; node = node->next) { vendor_id = mad_get_field(node->info, 0,IB_NODE_VENDORID_F); if (vendor_id == VTR_VENDOR_ID) continue; if (mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F)) { chassis = find_chassisguid(fabric, node); if (chassis && chassis->nodecount > 1) { if (!chassis->chassisnum) chassis->chassisnum = ++chassisnum; if (!node->ch_found) { node->ch_found = 1; add_node_to_chassis(chassis, node); } else if (vendor_id == MLX_VENDOR_ID){ insert_mellanox_line_and_spine(node, chassis); } } } } fabric->chassis = chassis_scan.first_chassis; return 0; cleanup: ch = chassis_scan.first_chassis; while (ch) { ch_next = ch->next; free(ch); ch = ch_next; } fabric->chassis = NULL; return -1; }