diff options
| author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
|---|---|---|
| committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
| commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
| tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/cmd/wrsmconf | |
| download | illumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz | |
OpenSolaris Launch
Diffstat (limited to 'usr/src/cmd/wrsmconf')
| -rw-r--r-- | usr/src/cmd/wrsmconf/Makefile | 112 | ||||
| -rw-r--r-- | usr/src/cmd/wrsmconf/mkconfig.c | 891 | ||||
| -rw-r--r-- | usr/src/cmd/wrsmconf/wrsmcfg | 53 | ||||
| -rw-r--r-- | usr/src/cmd/wrsmconf/wrsmconf.c | 817 | ||||
| -rw-r--r-- | usr/src/cmd/wrsmconf/wrsmconf_msgs.h | 53 |
5 files changed, 1926 insertions, 0 deletions
diff --git a/usr/src/cmd/wrsmconf/Makefile b/usr/src/cmd/wrsmconf/Makefile new file mode 100644 index 0000000000..b032be302b --- /dev/null +++ b/usr/src/cmd/wrsmconf/Makefile @@ -0,0 +1,112 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2001-2003 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +SCRIPT = wrsmcfg +INIT_D = $(ROOTETC)/init.d +INIT_PROG = $(INIT_D)/$(SCRIPT) +RCS_SSCRIPT = S29wrsmcfg +RCS_KSCRIPT = K44wrsmcfg +ROOTRCS_D = $(ROOTETC)/rcS.d +ROOTRCS_SLINK = $(ROOTRCS_D)/$(RCS_SSCRIPT) +ROOTRCS_KLINK = $(ROOTRCS_D)/$(RCS_KSCRIPT) +DATA_D = $(ROOTETC)/wrsm + +PROG = wrsmconf +ROOTFS_PROG = $(PROG) +PLATFORM = sun4u +OBJS = wrsmconf.o mkconfig.o +SRCS = $(OBJS:%.o=%.c) + + +include ../Makefile.cmd +include ../../Makefile.psm + +ROOTBIN= $(ROOT)/platform/sun4u/sbin +ROOTPROG= $(ROOTBIN)/$(PROG) +POFILE= wrsmconf_cmd.po +POFILES= wrsmconf.po mkconfig.po + +INS.root.sys = install -s -m 755 -f +$(CH)INS.root.sys = install -s -m 755 -u root -g sys -f +INSLINKTARGET= $(INIT_PROG) + + +CPPFLAGS += -I$(USR_PSM_INCL_DIR) +LDFLAGS += -L$(ROOT)/platform/sun4u/lib -R/platform/sun4u/lib +LDLIBS += -lwrsmconf + +.KEEP_STATE: + +all: $(ROOTFS_PROG) + +install: all $(ROOTPROG) $(INIT_PROG) $(ROOTRCS_SLINK) $(ROOTRCS_KLINK) $(DATA_D) + + +$(PROG): $(OBJS) + $(LINK.c) $(OBJS) -o $@ $(LDLIBS) + $(POST_PROCESS) + +$(DATA_D): + $(INS.dir.root.sys) + +$(ROOTBIN): + $(INS.dir.root.sys) + +$(INIT_D): + $(INS.dir.root.sys) + +$(ROOTRCS_D): + $(INS.dir.root.sys) + +$(ROOTRCS_SLINK): $(INIT_PROG) $(ROOTRCS_D) + $(INS.link) + +$(ROOTRCS_KLINK): $(INIT_PROG) $(ROOTRCS_D) + $(INS.link) + +$(INIT_PROG): $(INIT_D) $(SCRIPT) + $(INS.root.sys) $(INIT_D) $(SCRIPT) + +$(ROOTPROG): $(ROOTBIN) $(PROG) + $(INS.root.sys) $(ROOTBIN) $(PROG) + +clean: + $(RM) $(OBJS) + +lint: $(MACH)_lint + +i386_lint: + +sparc_lint: + $(LINT.c) -u $(SRCS) $(LDLIBS.cmd) + +$(POFILE): $(POFILES) + $(RM) $@ + cat $(POFILES) > $@ + +include ../Makefile.targ diff --git a/usr/src/cmd/wrsmconf/mkconfig.c b/usr/src/cmd/wrsmconf/mkconfig.c new file mode 100644 index 0000000000..58ac3233d4 --- /dev/null +++ b/usr/src/cmd/wrsmconf/mkconfig.c @@ -0,0 +1,891 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * This program converts a 'netlist' file into a config file, suitable + * for configuring the Wildcat RSM driver. + * + * Caveats: + * Handles 2-way wci striping, but not 4-way. + * Assumes you want to do as much striping as possible. + */ + +#include <sys/types.h> +#include <netdb.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <libintl.h> +#include <errno.h> +#include <sys/wrsm_types.h> +#include <sys/wrsm_config.h> +#include "wrsmconf_msgs.h" + +#ifdef DEBUG +#define TRACE(f) printf(f) +#define DPRINTF(s) printf s +#else +#define TRACE(f) +#define DPRINTF(s) +#endif + +#define MAXHOSTS 256 +#define MAXWCIS (3 * 18) +#define MAXLINKS 8 +#define MAXOPTLEN 80 +#define MAXULONGSTR 11 /* E.g., 0xffffffff or 4294967295 */ + + +#define NCSLICE_BASE 0xA1 /* Works for Serengeti and Starcat */ +#define NCSLICE_CTRL (multihop_allowed ? 10 : 4) /* Nodes per ctrl */ +#define COMM_BASE 2 /* Start with page 2 */ +#define PAGE_SIZE 0x2000 + +#define MAXCTRL ((WRSM_MAX_NCSLICES - 1) - ncslice_base)/NCSLICE_CTRL +#define WRSMCONF_CREATE "create" + +/* + * Macros to produce a quoted string containing the value of a + * preprocessor macro. For example, if SIZE is defined to be 256, + * VAL2STR(SIZE) is "256". This is used to construct format + * strings for scanf-family functions below. + */ +#define QUOTE(x) #x +#define VAL2STR(x) QUOTE(x) + +static int ncslice_base = NCSLICE_BASE; +static int controller = 0; /* Controller number to assign */ +static int gnid_offset = 0; +static boolean_t passthrough_allowed = B_FALSE; +static boolean_t multihop_allowed = B_FALSE; +static FILE *outf = stdout; + +typedef struct { + boolean_t in_use; + int remote_cnode; + int remote_wci; + int remote_link; +} link_info_t; + +typedef struct { + int wci_id; + link_info_t links[MAXLINKS]; +} wci_info_t; + +typedef struct { + boolean_t in_use; + char name[WRSM_HOSTNAMELEN]; + int num_wcis; + wci_info_t wcis[MAXWCIS]; + boolean_t wcswitch; +} host_info_t; + +typedef struct { + host_info_t hosts[MAXHOSTS]; + int num_hosts; + union { + struct { + uint32_t upper_word; + time_t clock_val; + } raw; + uint64_t val; + } version_stamp; +} config_info_t; + +typedef struct { + int wcia; + int wcib; +} stripe_group_t; + +typedef struct { + stripe_group_t sg[36]; + int nsg; +} stripe_list_t; + +typedef enum { + CAN_REACH_NO, + CAN_REACH_DIRECT, + CAN_REACH_MULTIHOP, + CAN_REACH_PASSTHROUGH +} can_reach_t; + +/* + * Finds the WCI associated with the given cnodeid, and if not found + * creates a new WCI for that cnode. + */ +static wci_info_t * +add_wci(config_info_t *config, int cnode, int wci_id) +{ + int i; + host_info_t *host = &(config->hosts[cnode]); + wci_info_t *wci; + + DPRINTF(("add_wci(cnode=%d, wci_id=%d)\n", cnode, wci_id)); + /* First search for a matching WCI */ + for (i = 0; i < host->num_wcis; i++) { + wci = &(host->wcis[i]); + if (wci->wci_id == wci_id) { + return (wci); + } + } + /* Otherwise, create the WCI */ + wci = &(host->wcis[host->num_wcis]); + wci->wci_id = wci_id; + host->num_wcis++; + return (wci); +} + +/* Adds link info to a host's wci */ +static void +add_link(config_info_t *config, int cnode, int wci_id, int link, + int rem_cnode, int rem_wci, int rem_link) +{ + host_info_t *host = &(config->hosts[cnode]); + wci_info_t *wci = add_wci(config, cnode, wci_id); + + DPRINTF(("add_link(cnode=%d, wci_id=%d, link=%d, rem_cnode=%d, " + "rem_wci=%d, rem_link=%d)\n", cnode, wci_id, link, rem_cnode, + rem_wci, rem_link)); + + /* Check for loopback links and ignore */ + if (cnode == rem_cnode && wci_id == rem_wci && link == rem_link) { + return; + } + + if (wci->links[link].in_use) { + (void) fprintf(stderr, MSG_LINK_IN_USE, + WRSMCONF_CREATE, host->name, wci->wci_id, link); + exit(1); + } + wci->links[link].in_use = B_TRUE; + wci->links[link].remote_cnode = rem_cnode; + wci->links[link].remote_wci = rem_wci; + wci->links[link].remote_link = rem_link; +} + +/* Creates a new host entry */ +static int +add_host(config_info_t *config, char *hostname, boolean_t wcswitch) +{ + int i; + int start = wcswitch ? 16 : 0; /* Bias switches to be > 16 */ + + DPRINTF(("add_host(hostname=%s, wcswitch=%d)\n", hostname, wcswitch)); + + for (i = start; i < MAXHOSTS; i++) { + if (!config->hosts[i].in_use) { + break; + } + } + if (i == MAXHOSTS) { + (void) fprintf(stderr, MSG_NUM_HOSTS, WRSMCONF_CREATE, + MAXHOSTS); + exit(1); + } + config->hosts[i].in_use = B_TRUE; + (void) strlcpy(config->hosts[i].name, hostname, WRSM_HOSTNAMELEN); + config->hosts[i].wcswitch = wcswitch; + + return (i); +} + +/* Given a host name, returns its cnode id, or creates a new one */ +static int +host2node(config_info_t *config, char *hostname) +{ + int i; + + /* First search for previous occurence */ + for (i = 0; i < MAXHOSTS; i++) { + if (config->hosts[i].in_use && + strcmp(hostname, config->hosts[i].name) == 0) { + return (i); + } + } + return (add_host(config, hostname, B_FALSE)); +} + +/* Parses the netlist file into the config structure */ +static void +parse_file(char *filename, config_info_t *config) +{ + char s[255]; + char t[255]; + FILE *f; + boolean_t show_usage; + + if (strcmp(filename, "-") == 0) { + f = stdin; + show_usage = isatty(0) ? B_TRUE : B_FALSE; + } else { + f = fopen(filename, "r"); + show_usage = B_TRUE; + } + + if (f == NULL) { + perror(filename); + exit(1); + } + if (show_usage) { + (void) fprintf(stderr, MSG_INPUT1); + (void) fprintf(stderr, MSG_INPUT2); + (void) fprintf(stderr, MSG_INPUT3); + } + while (fgets(t, sizeof (t), f)) { + int i; + int x; + char hosta[WRSM_HOSTNAMELEN+1]; + char hostb[WRSM_HOSTNAMELEN+1]; + char wciastr[MAXULONGSTR+1], wcibstr[MAXULONGSTR+1]; + int cnodea, wcia, linka, cnodeb, wcib, linkb; + + DPRINTF(("parsing line: %s\n", t)); + (void) fprintf(outf, "# %s", t); + for (i = 0; t[i]; i++) { + if (t[i] == '#') { + break; + } else if (t[i] == '.') { + s[i] = ' '; + } else if (t[i] == '=') { + s[i] = ' '; + } else { + s[i] = t[i]; + } + } + s[i] = 0; + + /* Check if this line is an "option" */ + if (s[0] == '-') { + char opt[MAXOPTLEN+1]; + char args[2][WRSM_HOSTNAMELEN+1]; + x = sscanf(&s[1], + "%" VAL2STR(MAXOPTLEN) "s " + "%" VAL2STR(WRSM_HOSTNAMELEN) "s " + "%" VAL2STR(WRSM_HOSTNAMELEN) "s", + opt, args[0], args[1]); + if (strcmp(opt, "multihop") == 0 && x == 1) { + multihop_allowed = B_TRUE; + } else if (strcmp(opt, "passthrough") == 0 && x == 1) { + passthrough_allowed = B_TRUE; + } else if (strcmp(opt, "host") == 0 && x == 2) { + (void) add_host(config, args[0], B_FALSE); + } else if (strcmp(opt, "switch") == 0 && x == 2) { + (void) add_host(config, args[0], B_TRUE); + multihop_allowed = B_TRUE; + } else if (strcmp(opt, "controller") == 0 && x == 2) { + controller = strtol(args[0], NULL, 0); + } else if (strcmp(opt, "ncslice") == 0 && x == 2) { + int n = strtol(args[0], NULL, 0); + if (n < 1 || n > 254) { + (void) fprintf(stderr, MSG_INVALID, + WRSMCONF_CREATE, "ncslice", n); + } else { + ncslice_base = n; + } + } else if (strcmp(opt, "gnid") == 0 && x == 2) { + gnid_offset = strtol(args[0], NULL, 0); + } else { + (void) fprintf(stderr, MSG_UNKNOWN, + WRSMCONF_CREATE, opt); + } + continue; + } + x = sscanf(s, + " %" VAL2STR(WRSM_HOSTNAMELEN) "s " + "%" VAL2STR(MAXULONGSTR) "s " + "%d " + "%" VAL2STR(WRSM_HOSTNAMELEN) "s " + "%" VAL2STR(MAXULONGSTR) "s " + "%d", + hosta, wciastr, &linka, hostb, wcibstr, &linkb); + if (x < 1) { + /* Blank line */ + continue; + } else if (x < 6) { + (void) fprintf(stderr, MSG_PARSE_ERR, + WRSMCONF_CREATE, t); + continue; + } + wcia = strtol(wciastr, NULL, 0); + wcib = strtol(wcibstr, NULL, 0); + if (linka > MAXLINKS || linkb > MAXLINKS) { + (void) fprintf(stderr, MSG_LINK_RANGE, + WRSMCONF_CREATE, s); + exit(1); + } + cnodea = host2node(config, hosta); + cnodeb = host2node(config, hostb); + /* Link goes it both directions, so add both directions */ + add_link(config, cnodea, wcia, linka, cnodeb, wcib, linkb); + add_link(config, cnodeb, wcib, linkb, cnodea, wcia, linka); + } +} + +/* + * The following functions generate the actual config file + */ + +/* Prints cnodeid section of config file */ +static void +print_cnodeids(config_info_t *config, int cnode) +{ + int i; + int comm_offset = (cnode + COMM_BASE) * PAGE_SIZE; + + for (i = 0; i < MAXHOSTS; i++) { + int ncslice = i + ncslice_base + controller * NCSLICE_CTRL; + int local_offset = (i + COMM_BASE) * PAGE_SIZE; + + if (!config->hosts[i].in_use || + config->hosts[i].wcswitch) { + continue; + } + + (void) fprintf(outf, "\tcnodeid %d {\n", i); + (void) fprintf(outf, "\t\tfmnodeid 0x%x %s\n", + i + gnid_offset, config->hosts[i].name); + (void) fprintf(outf, "\t\texported_ncslices { 0x%02x }\n", + ncslice); + (void) fprintf(outf, "\t\timported_ncslices { 0x%02x }\n", + cnode + ncslice_base + (controller * NCSLICE_CTRL)); + (void) fprintf(outf, "\t\tlocal_offset 0x%04x\n", + local_offset); + (void) fprintf(outf, "\t\tcomm_ncslice 0x%02x 0x%04x\n", + ncslice, comm_offset); + (void) fprintf(outf, "\t}\n"); + } +} + +/* Prints the link subsection of the wci section of the config file */ +static void +print_link(link_info_t *link) +{ + int remote_gnid; + + if (link->remote_cnode >= WRSM_MAX_WNODES) + remote_gnid = link->remote_cnode; + else + remote_gnid = link->remote_cnode + gnid_offset; + + (void) fprintf(outf, "\t\t\tremote_gnid %d\n", remote_gnid); + (void) fprintf(outf, "\t\t\tremote_link %d\n", link->remote_link); + (void) fprintf(outf, "\t\t\tremote_wci %d\n", link->remote_wci); +} + +/* Checks if a node is already reachable */ +static int +is_duplicate(int reachable_list[], int *num_reachable, int cnode) +{ + int i; + + for (i = 0; i < *num_reachable; i++) { + if (reachable_list[i] == cnode) { + return (B_TRUE); + } + } + reachable_list[*num_reachable] = cnode; + (*num_reachable)++; + return (B_FALSE); +} + +/* Prints the wci section of the config file */ +static void +print_wci(config_info_t *config, wci_info_t *wci, int cnode) +{ + int i; + int j; + boolean_t route_map_striping = B_FALSE; + + /* Check for route_map_striping */ + for (i = 0; i < MAXLINKS; i++) { + link_info_t *ilink = &(wci->links[i]); + if (!ilink->in_use) { + continue; + } + for (j = 0; j < i; j++) { + link_info_t *jlink = &(wci->links[j]); + if (!jlink->in_use) { + continue; + } + if (ilink->remote_cnode == jlink->remote_cnode && + ilink->remote_wci == jlink->remote_wci) { + route_map_striping = B_TRUE; + } + } + } + + (void) fprintf(outf, "\twci {\n"); + (void) fprintf(outf, "\t\tsafari_port_id %d\n", wci->wci_id); + (void) fprintf(outf, "\t\twnodeid %d\n", cnode); + (void) fprintf(outf, "\t\tgnid %d\n", cnode + gnid_offset); + (void) fprintf(outf, "\t\treachable (%d,%d,%d)", cnode, + cnode + gnid_offset, cnode); + + for (i = 0; i < MAXLINKS; i++) { + int reachable_list[MAXHOSTS]; + int num_reachable = 0; + link_info_t *link = &(wci->links[i]); + + /* Add ourselves to the reachable list */ + reachable_list[num_reachable++] = cnode; + + if (!link->in_use) { + continue; + } + /* Make sure it's not a dup */ + if (is_duplicate(reachable_list, &num_reachable, + link->remote_cnode)) { + continue; + } + + /* If not duplicate and remote node is a switch... */ + if (config->hosts[link->remote_cnode].wcswitch) { + /* Ignore switch, report on remote cnodes */ + wci_info_t *swwci = + &config->hosts[link->remote_cnode].wcis[0]; + + for (j = 0; j < MAXLINKS; j++) { + link_info_t *swlink = &(swwci->links[j]); + if (!swlink->in_use) { + continue; + } + if (is_duplicate(reachable_list, + &num_reachable, swlink->remote_cnode)) { + continue; + } + (void) fprintf(outf, " (%d,%d,%d)", + swlink->remote_cnode, + swlink->remote_cnode + gnid_offset, + swlink->remote_cnode); + } + } else { + (void) fprintf(outf, " (%d,%d,%d)", + link->remote_cnode, + link->remote_cnode + gnid_offset, + link->remote_cnode); + } + } + (void) fprintf(outf, "\n"); + (void) fprintf(outf, "\t\troute_map_striping %s\n", + (route_map_striping)?"true":"false"); + (void) fprintf(outf, "\t\ttopology_type distributed_switch\n"); + for (i = 0; i < MAXLINKS; i++) { + link_info_t *link = &(wci->links[i]); + if (link->in_use) { + (void) fprintf(outf, "\t\tlink %d {\n", i); + print_link(link); + (void) fprintf(outf, "\t\t}\n"); + } + } + (void) fprintf(outf, "\t}\n"); +} + +static wci_info_t * +wci_from_cnode(config_info_t *config, int cnode, int wci_id) +{ + int i; + DPRINTF(("wci_from_cnode(cnode=%d, wci=%d)\n", cnode, wci_id)); + for (i = 0; i < config->hosts[cnode].num_wcis; i++) { + if (config->hosts[cnode].wcis[i].wci_id == wci_id) { + return (&config->hosts[cnode].wcis[i]); + } + } + return (NULL); +} + +static boolean_t +wci_can_reach_direct(wci_info_t *wci, int dest_cnode) +{ + int link; + DPRINTF(("wci_can_reach_direct(wci=%d, dest_cnode=%d)\n", + wci->wci_id, dest_cnode)); + + /* Look for direct connect */ + for (link = 0; link < MAXLINKS; link++) { + if (wci->links[link].in_use && + wci->links[link].remote_cnode == dest_cnode) { + DPRINTF((" wci_can_reach_direct: TRUE\n")); + return (B_TRUE); + } + } + DPRINTF((" wci_can_reach_direct: FALSE\n")); + return (B_FALSE); +} + +static boolean_t +wci_can_reach_multihop(config_info_t *config, wci_info_t *wci, + int dest_cnode) +{ + int link; + + DPRINTF(("wci_can_reach_multihop(wci=%d, dest_cnode=%d)\n", + wci->wci_id, dest_cnode)); + + for (link = 0; link < MAXLINKS; link++) { + if (wci->links[link].in_use) { + /* Find the WCI at the other end of the link */ + wci_info_t *mh_wci = + wci_from_cnode(config, + wci->links[link].remote_cnode, + wci->links[link].remote_wci); + if (mh_wci == NULL) { + exit(1); + } + /* See if that WCI can get us where we're going */ + if (wci_can_reach_direct(mh_wci, dest_cnode)) { + DPRINTF((" wci_can_reach_multihop: TRUE\n")); + return (B_TRUE); + } + } + } + DPRINTF((" wci_can_reach_multihop: FALSE\n")); + return (B_FALSE); +} + +static boolean_t +cnode_can_reach_direct(config_info_t *config, int cnode, int dest_cnode) +{ + int i; + DPRINTF(("cnode_can_reach_direct(cnode=%d, dest_cnode=%d)\n", + cnode, dest_cnode)); + for (i = 0; i < config->hosts[cnode].num_wcis; i++) { + if (wci_can_reach_direct( + &config->hosts[cnode].wcis[i], + dest_cnode)) { + DPRINTF((" cnode_can_reach_direct: TRUE\n")); + return (B_TRUE); + } + } + DPRINTF((" cnode_can_reach_direct: FALSE\n")); + return (B_FALSE); +} + +static boolean_t +wci_can_reach_passthrough(config_info_t *config, wci_info_t *wci, + int dest_cnode, int *pt_cnode, int *num_switches) +{ + int link; + DPRINTF(("wci_can_reach_passthrough(wci=%d, dest_cnode=%d)\n", + wci->wci_id, dest_cnode)); + + *num_switches = 0; + /* Try all links, until we've found two switches */ + for (link = 0; link < MAXLINKS && *num_switches < 2; link++) { + /* + * If this link is in use, and the cnode at the other + * end of the link can reach the destination cnode, + * then we have a passthrough route. + */ + if (wci->links[link].in_use && + cnode_can_reach_direct(config, + wci->links[link].remote_cnode, + dest_cnode)) { + /* Remember the passthrough node */ + pt_cnode[*num_switches] = + wci->links[link].remote_cnode; + (*num_switches)++; + DPRINTF((" wci_can_reach_passthrough: TRUE\n")); + } + } + DPRINTF((" wci_can_reach_passthrough: %d\n", *num_switches)); + return (*num_switches > 0); +} + +/* Checks if this wci can reach the dest_cnode on one of its links */ +static can_reach_t +wci_can_reach(config_info_t *config, wci_info_t *wci, int dest_cnode, + int *pt_cnodes, int *num_switches) +{ + DPRINTF(("wci_can_reach(wci=%d, dest_cnode=%d)\n", + wci->wci_id, dest_cnode)); + + *pt_cnodes = -1; + *num_switches = 0; + + /* First try direct connect */ + if (wci_can_reach_direct(wci, dest_cnode)) { + return (CAN_REACH_DIRECT); + } + /* Look for multihop */ + if (multihop_allowed && + wci_can_reach_multihop(config, wci, dest_cnode)) { + return (CAN_REACH_MULTIHOP); + } + /* Finally, try passthrough */ + if (pt_cnodes != NULL && passthrough_allowed && + wci_can_reach_passthrough(config, wci, dest_cnode, + pt_cnodes, num_switches)) { + return (CAN_REACH_PASSTHROUGH); + } + return (CAN_REACH_NO); +} + +/* Given two wcis, returns their stripe group (or creates a new one) */ +static int +get_stripe_group(stripe_list_t *sl, int wcia, int wcib) { + int i; + + for (i = 0; i < sl->nsg; i++) { + if ((sl->sg[i].wcia == wcia && sl->sg[i].wcib == wcib) || + (sl->sg[i].wcia == wcib && sl->sg[i].wcib == wcia)) + return (i); + } + sl->sg[i].wcia = wcia; + sl->sg[i].wcib = wcib; + sl->nsg++; + return (i); +} + +/* Prints the stripe_group section of the config file */ +static void +print_stripe_groups(stripe_list_t *sl) +{ + int i; + for (i = 0; i < sl->nsg; i++) { + (void) fprintf(outf, "\tstripe_group %d { \n", i); + (void) fprintf(outf, "\t\twcis 0x%x 0x%x\n", + sl->sg[i].wcia, sl->sg[i].wcib); + (void) fprintf(outf, "\t}\n"); + } +} + +/* Prints the routing sections of the config file */ +static void +print_routing(config_info_t *config, int cnode) +{ + int i; + int j; + int k; + stripe_list_t sl; + host_info_t *host = &(config->hosts[cnode]); + int ptswitches[4]; + int num_switches = 0; + + sl.nsg = 0; + + for (i = 0; i < MAXHOSTS; i++) { + boolean_t same_node = (i == cnode); + boolean_t found_a_route = B_FALSE; + + if (!config->hosts[i].in_use || + config->hosts[i].wcswitch) { + continue; + } + + (void) fprintf(outf, "\trouting_policy %d { # %s\n", + i, same_node ? "loopback" : config->hosts[i].name); + /* First check for WCI striping */ + for (j = 0; j < host->num_wcis && !same_node; j++) { + wci_info_t *jwci = &(host->wcis[j]); + can_reach_t can_reach_j = wci_can_reach(config, + jwci, i, ptswitches, &num_switches); + if (can_reach_j == CAN_REACH_NO) { + continue; + } + for (k = 0; k < j; k++) { + wci_info_t *kwci = &(host->wcis[k]); + int sg; + int new_ptswitches[2]; + int new_switches = 0; + can_reach_t can_reach_k = + wci_can_reach(config, kwci, i, + new_ptswitches, + &new_switches); + if (can_reach_k != can_reach_j) { + continue; + } + found_a_route = B_TRUE; + + /* Make sure pt striping is balanced */ + if (num_switches == new_switches) { + int k; + for (k = 0; k < new_switches; k++) { + ptswitches[num_switches + k] = + new_ptswitches[k]; + } + num_switches += new_switches; + } else if (num_switches > 0) { + ptswitches[1] = new_ptswitches[0]; + num_switches = 2; + } + sg = get_stripe_group(&sl, jwci->wci_id, + kwci->wci_id); + (void) fprintf(outf, + "\t\tpreferred_route {\n"); + (void) fprintf(outf, + "\t\t\tstriping_level %d\n", + (can_reach_j == CAN_REACH_PASSTHROUGH) ? + num_switches : 2); + (void) fprintf(outf, + "\t\t\trouting_method %s\n", + (can_reach_j == CAN_REACH_PASSTHROUGH) ? + "passthrough" : "multihop"); + (void) fprintf(outf, + "\t\t\tstripe_group %d\n", sg); + if (can_reach_j == CAN_REACH_PASSTHROUGH) { + int k; + (void) fprintf(outf, + "\t\t\tswitches"); + for (k = 0; k < num_switches; k++) { + (void) fprintf(outf, " %d", + ptswitches[k]); + } + (void) fprintf(outf, "\n"); + } + (void) fprintf(outf, "\t\t}\n"); + } + } + + /* Next, find out how many WCIs go there */ + for (j = 0; j < host->num_wcis; j++) { + wci_info_t *wci = &(host->wcis[j]); + /* Note: We can always reach ourselves */ + can_reach_t can_reach; + if (same_node) { + can_reach = CAN_REACH_MULTIHOP; + } else { + can_reach = wci_can_reach(config, + wci, i, &ptswitches[0], &num_switches); + } + + if (can_reach == CAN_REACH_NO && i != cnode) { + continue; + } + found_a_route = B_TRUE; + (void) fprintf(outf, "\t\tpreferred_route {\n"); + (void) fprintf(outf, "\t\t\tstriping_level %d\n", + (can_reach == CAN_REACH_PASSTHROUGH) ? + num_switches : 1); + (void) fprintf(outf, "\t\t\trouting_method %s\n", + (can_reach == CAN_REACH_PASSTHROUGH) ? + "passthrough" : "multihop"); + (void) fprintf(outf, "\t\t\tuse_wci %d\n", + wci->wci_id); + if (can_reach == CAN_REACH_PASSTHROUGH) { + int k; + (void) fprintf(outf, "\t\t\tswitches"); + for (k = 0; k < num_switches; k++) { + (void) fprintf(outf, " %d", + ptswitches[k]); + } + (void) fprintf(outf, "\n"); + } + (void) fprintf(outf, "\t\t}\n"); + } + if (!found_a_route) { + (void) fprintf(stderr, MSG_NO_ROUTE, WRSMCONF_CREATE, + config->hosts[i].name, config->hosts[j].name); + (void) fprintf(outf, "\t\t/* NO ROUTE */\n"); + } + (void) fprintf(outf, "\t\twcis_balanced false\n"); + (void) fprintf(outf, "\t\tstriping_important true\n"); + if (passthrough_allowed && !same_node) { + (void) fprintf(outf, + "\t\tforwarding_ncslices 0x%x\n", + i + ncslice_base + (controller * NCSLICE_CTRL)); + } + (void) fprintf(outf, "\t}\n"); + } + print_stripe_groups(&sl); +} + +/* Prints a specific host configuration */ +static void +print_host(config_info_t *config, int cnode) +{ + int i; + host_info_t *host = &(config->hosts[cnode]); + + (void) fprintf(outf, "\n"); + (void) fprintf(outf, "#\n"); + (void) fprintf(outf, "# Config for host %s\n", host->name); + (void) fprintf(outf, "#\n"); + (void) fprintf(outf, "fmnodeid 0x%x %s\n", cnode + gnid_offset, + host->name); + (void) fprintf(outf, "controller %d {\n", controller); + (void) fprintf(outf, "\tconfig_protocol_version %u\n", + 2); + (void) fprintf(outf, "\tversion %llu\n", config->version_stamp.val); + (void) fprintf(outf, "\tlocal_cnodeid %d\n", cnode); + print_cnodeids(config, cnode); + for (i = 0; i < host->num_wcis; i++) { + print_wci(config, &(host->wcis[i]), cnode); + } + print_routing(config, cnode); + (void) fprintf(outf, "}\n"); +} + +/* Prints config file for all hosts */ +static void +print_config_file(config_info_t *config) +{ + int i; + for (i = 0; i < MAXHOSTS; i++) { + if (config->hosts[i].in_use && + !config->hosts[i].wcswitch) { + print_host(config, i); + } + } +} + +/* Main */ +int +mkconfig(char *input_file, char *output_file, int controller_id) +{ + config_info_t the_config; + + (void) memset(&the_config, 0, sizeof (the_config)); + (void) time(&the_config.version_stamp.raw.clock_val); + /* Set MSB to differentiate from FM-generated version stamps */ + the_config.version_stamp.raw.upper_word = 0x80000000; + + if (controller_id > MAXCTRL || controller_id < 0) { + errno = EINVAL; + perror(WRSMCONF_CREATE); + return (1); + } + controller = controller_id; + + if (input_file == NULL) + input_file = "-"; + if (output_file != NULL) { + outf = fopen(output_file, "w"); + if (outf == NULL) { + perror(WRSMCONF_CREATE); + return (1); + } + } + parse_file(input_file, &the_config); + if (the_config.num_hosts > NCSLICE_CTRL) { + (void) fprintf(stderr, MSG_NUM_HOSTS, + WRSMCONF_CREATE, NCSLICE_CTRL); + return (1); + } + print_config_file(&the_config); + return (0); +} diff --git a/usr/src/cmd/wrsmconf/wrsmcfg b/usr/src/cmd/wrsmconf/wrsmcfg new file mode 100644 index 0000000000..c6fefe7950 --- /dev/null +++ b/usr/src/cmd/wrsmconf/wrsmcfg @@ -0,0 +1,53 @@ +#!/sbin/sh +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2001 by Sun Microsystems, Inc. +# All rights reserved. +# +#ident "%Z%%M% %I% %E% SMI" + +CMD="/platform/sun4u/sbin/wrsmconf" + +platform=${_INIT_UTS_PLATFORM:-`/sbin/uname -i`} +serengeti="SUNW,Sun-Fire" +starcat="SUNW,Sun-Fire-15000" + +case "$1" in +'start') + if [ ${platform} = "${serengeti}" -o ${platform} = "${starcat}" ]; then + $CMD start + fi + ;; + +'stop') + if [ ${platform} = "${serengeti}" -o ${platform} = "${starcat}" ]; then + $CMD stop + fi + ;; + +*) + echo "Usage: $0 { start | stop }" + exit 1 + ;; +esac +exit 0 diff --git a/usr/src/cmd/wrsmconf/wrsmconf.c b/usr/src/cmd/wrsmconf/wrsmconf.c new file mode 100644 index 0000000000..a579e9b947 --- /dev/null +++ b/usr/src/cmd/wrsmconf/wrsmconf.c @@ -0,0 +1,817 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2001-2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * This file implments the RSM Proxy. + * + * The program is controlled by its command line arguments. + * The first argument is always the name of the command to be + * executed followed by some number of options with the + * appropriate parameter values. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <libintl.h> +#include <locale.h> +#include <sys/int_fmtio.h> +#include <sys/systeminfo.h> +#include <sys/wrsmconf.h> +#include <stddef.h> +#include <errno.h> +#include "wrsmconf_msgs.h" + +#define DEVNAME "/devices/wrsm@ffff,0:admin" +#define CTLRDEVNAME "/dev/wrsm%d" +#define MAX_WCI_IDS 54 + +extern int ErrorCount; + +struct dump_info { + wrsm_fmnodeid_t fmnode_id; + char host_name[WRSM_HOSTNAMELEN]; + uint32_t controller_id; + unsigned char cnode_id; +}; + +static void init_usage(void); +static void print_usage(boolean_t private); +static void print_command_usage(char *command); +static int dump_config(char *fn, int controller_id); +static int getinfo(int controller_id); +static void free_controller_info(struct dump_info ***controller_info); +static int compare(const void *left, const void *right); +static void print_column_headers(FILE *fp); +static void print_member_info(FILE *fp, struct dump_info **info, + int num_members); +static int topology(int cid); +static int check(int cid, char *hostname); +int mkconfig(char *input_file, char *output_file, int controller_id); + +/* Private function in libwrsmconf */ +extern void wrsm_print_controller(FILE *fp, wrsm_controller_t *cont); + +static struct { + char *name; + char *usage; +} commands[6], private_commands[] = { + { "usage", "[<command>]" }, + { "replace", "-f <in-filename> [-c <controller-id>] [-h <hostname>]" }, + { "install", "[-c <controller-id>] [-w <wci-id>]" }, + { "enable", "[-c <controller-id>] [-w <wci-id>]" }, + { "info", "[-c <controller-id>]" }, + { "read", "[-c <controller-id>] -f <in-filename> [-h <hostname>]" }, + { "start", "[-c <controller-id>]" }, + { "stop", "[-c <controller-id>]" }, + { "link_disable", "-w <wci-id> -l <linkno>" }, + { "link_enable", "-w <wci-id> -l <linkno>" }, + { "check", "[-c <controller-id>] [-h <hostname>]" }, + { "msgtest", "" }, + { NULL, NULL }, +}; + +static char *command_name; +extern char *optarg; +extern int optind; +extern int opterr; +extern int optopt; + +int +main(int argc, char **argv) +{ + char *file = NULL; + int controller_id = -1; + wrsm_safari_port_t wci_ids[MAX_WCI_IDS]; + size_t num_wcis = 0; + boolean_t got_controller_id = B_FALSE; + boolean_t got_hostname = B_FALSE; + char hostname[WRSM_HOSTNAMELEN] = ""; + char c; + char *command; + wrsm_controller_t *cont = NULL; + int wci_index = 0; + int rc; + int linkno = -1; + + (void) setlocale(LC_ALL, ""); + +#if !defined(TEXT_DOMAIN) +#define TEXT_DOMAIN "SYS_TEST" +#endif + (void) textdomain(TEXT_DOMAIN); + + command_name = argv[0]; + + if (argc < 2) { + print_usage(B_FALSE); + return (2); + } + + command = argv[1]; + + while ((c = getopt(argc-1, &argv[1], "c:f:h:l:w:")) + != EOF) { + switch (c) { + case 'c': + controller_id = atoi(optarg); + got_controller_id = B_TRUE; + break; + case 'f': + file = optarg; + break; + case 'w': + wci_ids[wci_index++] = + (wrsm_safari_port_t) + strtol(optarg, NULL, 0); + num_wcis++; + break; + case 'h': + (void) strcpy(hostname, optarg); + got_hostname = B_TRUE; + break; + case 'l': + linkno = (int)atoi(optarg); + break; + default: + print_command_usage(command); + return (1); + } + } + + if (strcmp(command, "create") == 0) { + if (!got_controller_id) { + errno = EINVAL; + perror(command); + print_command_usage(command); + return (1); + } + if (file == NULL) { + errno = EINVAL; + perror(command); + print_command_usage(command); + return (1); + } + rc = mkconfig(NULL, file, controller_id); + + } else if (strcmp(command, "initial") == 0) { + if (file == NULL) { + errno = EINVAL; + perror(command); + print_command_usage(command); + return (1); + } + + if (got_hostname) + rc = wrsm_read_config_for_host(file, &cont, hostname); + else + rc = wrsm_read_config(file, &cont); + if (rc != 0) { + (void) fprintf(stderr, MSG_FILE, command, file); + return (1); + } + if (got_controller_id && + controller_id != cont->controller_id) { + (void) fprintf(stderr, MSG_NOT_FOUND, + command, controller_id, file); + return (1); + } + + if ((rc = wrsm_initial_config(cont)) != 0) { + perror(command); + return (1); + } + + } else if (strcmp(command, "start") == 0) { + if (!got_controller_id) { + rc = wrsm_start_all_configs(); + return (rc ? 1 : 0); + } else if ((rc = wrsm_start_config(controller_id)) != 0) { + perror(command); + return (1); + } + + } else if (strcmp(command, "stop") == 0) { + if (!got_controller_id) { + rc = wrsm_stop_all_configs(); + return (rc ? 1 : 0); + } else if ((rc = wrsm_stop_config(controller_id)) != 0) { + perror(command); + return (1); + } + + } else if (strcmp(command, "remove") == 0) { + if (!got_controller_id) { + rc = wrsm_remove_all_configs(); + return (rc ? 1 : 0); + } else if ((rc = wrsm_remove_config(controller_id)) != 0) { + perror(command); + return (1); + } + + } else if (strcmp(command, "replace") == 0) { + if (file == NULL) { + errno = EINVAL; + perror(command); + print_command_usage(command); + return (1); + } + + if (got_hostname) + rc = wrsm_read_config_for_host(file, &cont, hostname); + else + rc = wrsm_read_config(file, &cont); + + if (rc != 0) { + (void) fprintf(stderr, MSG_FILE, command, file); + return (1); + } + if (got_controller_id && + controller_id != cont->controller_id) { + (void) fprintf(stderr, MSG_NOT_FOUND, + command, controller_id, file); + return (1); + } + if ((rc = wrsm_replace_config(cont)) != 0) { + perror(command); + return (1); + } + + } else if (strcmp(command, "install") == 0) { + if (!got_controller_id) { + controller_id = 0; + } + if ((rc = wrsm_install_config(controller_id, num_wcis, + wci_ids)) != 0) { + perror(command); + return (1); + } + + } else if (strcmp(command, "enable") == 0) { + if (!got_controller_id) { + controller_id = 0; + } + if ((rc = wrsm_enable_config(controller_id, num_wcis, + wci_ids)) != 0) { + perror(command); + return (1); + } + + } else if (strcmp(command, "dump") == 0) { + if (!got_controller_id) { + errno = EINVAL; + perror(command); + print_command_usage(command); + return (1); + } + if (file == NULL) { + errno = EINVAL; + perror(command); + print_command_usage(command); + return (1); + } + return (dump_config(file, controller_id)); + + } else if (strcmp(command, "info") == 0) { + return (getinfo(controller_id)); + + } else if (strcmp(command, "topology") == 0) { + return (topology(controller_id)); + + } else if (strcmp(command, "check") == 0) { + return (check(controller_id, got_hostname ? hostname : NULL)); + + } else if (strcmp(command, "usage") == 0) { + if (argc == 3) { + char *cmd = argv[2]; + if (strcmp(cmd, "private") == 0) { + print_usage(B_TRUE); + } else { + print_command_usage(cmd); + } + } else { + print_usage(B_FALSE); + } + + } else if (strcmp(command, "read") == 0) { + if (file == NULL) { + errno = EINVAL; + perror(command); + print_command_usage(command); + return (1); + } + + if (got_hostname) + rc = wrsm_read_config_for_host(file, &cont, hostname); + else + rc = wrsm_read_config(file, &cont); + if (rc != 0) { + (void) fprintf(stderr, MSG_FILE, command, file); + return (1); + } + if (got_controller_id && + controller_id != cont->controller_id) { + (void) fprintf(stderr, MSG_NOT_FOUND, + command, controller_id, file); + return (1); + } + wrsm_print_controller(stdout, cont); + + } else if (strcmp(command, "link_enable") == 0) { + + if ((num_wcis != 1) || (linkno == -1)) { + errno = EINVAL; + perror(command); + print_command_usage(command); + return (1); + } + rc = wrsm_link_enable(wci_ids[0], linkno); + if (rc != 0) { + perror(command); + return (1); + } + + } else if (strcmp(command, "link_disable") == 0) { + + if ((num_wcis != 1) || (linkno == -1)) { + errno = EINVAL; + perror(command); + print_command_usage(command); + return (1); + } + rc = wrsm_link_disable(wci_ids[0], linkno); + if (rc != 0) { + perror(command); + return (1); + } + + } else if (strcmp(command, "msgtest") == 0) { + (void) printf(MSG_FILE, command, "filename"); + (void) printf(MSG_NOT_FOUND, command, 32, "filename"); + (void) printf(MSG_INPUT1); + (void) printf(MSG_INPUT2); + (void) printf(MSG_INPUT3); + (void) printf(MSG_LINK_IN_USE, "create", "hostname", 1023, 2); + (void) printf(MSG_INVALID, "create", "ncslice", 255); + (void) printf(MSG_UNKNOWN, "create", "option"); + (void) printf(MSG_PARSE_ERR, "create", "unparsable line\n"); + (void) printf(MSG_LINK_RANGE, "create", "hostname.1023.3"); + (void) printf(MSG_NUM_HOSTS, "create", 10); + (void) printf(MSG_NO_ROUTE, "create", "hostname1", + "hostname2"); + } else { + errno = EINVAL; + perror(command_name); + print_usage(B_FALSE); + return (1); + } + + return (0); +} + +void +init_usage() +{ + commands[0].name = "create"; + commands[0].usage = + gettext("-c <controller id> -f <output file name>"); + commands[1].name = "initial"; + commands[1].usage = + gettext("[-c <controller id>] -f <input file name>"); + commands[2].name = "remove"; + commands[2].usage = gettext("[-c <controller id>]"); + commands[3].name = "topology"; + commands[3].usage = gettext("[-c <controller id>]"); + commands[4].name = "dump"; + commands[4].usage = + gettext("-c <controller id> -f <output file name>"); + commands[5].name = NULL; + commands[5].usage = NULL; +} + +void +print_usage(boolean_t private) +{ + int i; + + init_usage(); + (void) fprintf(stderr, gettext("usage: %s\n"), command_name); + for (i = 0; commands[i].name; ++i) + (void) printf("\t%s %s\n", commands[i].name, + commands[i].usage); + if (private) { + (void) printf("private commands:\n"); + for (i = 0; private_commands[i].name; i++) { + (void) printf("\t%s %s\n", private_commands[i].name, + private_commands[i].usage); + } + } +} + +static void +print_command_usage(char *command) +{ + int i; + + init_usage(); + (void) fprintf(stderr, gettext("usage: %s "), command_name); + for (i = 0; commands[i].name; ++i) { + if (strcmp(commands[i].name, command) == 0) { + (void) printf("%s %s\n", commands[i].name, + commands[i].usage); + break; + } + } + if (commands[i].name == NULL) { + print_usage(B_FALSE); + } +} + + + +/* + * If dump_config is called with a controller id that is less than 0, + * it scans all available controllers and prints the number of + * those which are active. If there is a valid controller-id + * argument, it gets the config data from the kernel, unparses + * it, and prints its contents. + */ +int +dump_config(char *file_name, int controller_id) +{ + wrsm_controller_t *config; + FILE *fd; + + if (file_name) { + fd = fopen(file_name, "w"); + } else { + fd = stdout; + } + if (fd == NULL) { + perror("dump"); + } + if (wrsm_get_config(controller_id, &config) != 0) { + return (1); + } + wrsm_print_controller(fd, config); + wrsm_free_config(config); + return (0); +} + +/* + * If getinfo is called with a controller id that is less than 0, + * it prints info on all available controllers. + */ +int +getinfo(int controller_id) +{ + wrsm_controller_t *config; + int i; + + if (controller_id < 0) { + int n; + + if ((n = wrsm_get_num_controllers()) < 0) { + perror("info"); + return (1); + } + for (i = 0; i < n; ++i) + if (wrsm_get_config(i, &config) == 0) { + (void) getinfo(i); + } + return (0); + } + + if (wrsm_get_config(controller_id, &config) != 0) { + perror("info"); + return (1); + } + (void) printf("controller %d cnodeid %d\n", config->controller_id, + config->cnodeid); + for (i = 0; i < config->nmembers; i++) { + int cnodeid = config->u_members.val.members[i]->cnodeid; + (void) printf(" cnodeid %d %s\n", cnodeid, + config->u_members.val.members[i]->hostname); + } + free(config); + return (0); +} + + +void +free_controller_info(struct dump_info ***controller_info) +{ + int controller_index = 0; + int member_index; + + if (controller_info == NULL) { + return; + } + + while (controller_info[controller_index] != NULL) { + member_index = 0; + while (controller_info[controller_index][member_index] + != NULL) { + free(controller_info[controller_index][member_index]); + member_index++; + } + free(controller_info[controller_index]); + controller_index++; + } + free(controller_info); +} + +int +compare(const void *left, const void *right) +{ + struct dump_info *lt = *((struct dump_info **)left); + struct dump_info *rt = *((struct dump_info **)right); + + if (lt->fmnode_id < rt->fmnode_id) { + return (-1); + } else if (lt->fmnode_id > rt->fmnode_id) { + return (1); + } else { + if (lt->controller_id < rt->controller_id) { + return (-1); + } else if (lt->controller_id > rt->controller_id) { + return (1); + } else { + return (0); + } + } +} + +void +print_column_headers(FILE *fp) +{ + (void) fprintf(fp, "%-25s", "FM Node ID"); + (void) fprintf(fp, "%-25s", "Node Name"); + (void) fprintf(fp, "%-25s", "Wildcat Cont Instance"); + (void) fprintf(fp, "%-25s\n", "Wildcat Cont HW Addr"); +} + +void +print_member_info(FILE *fp, struct dump_info **info, int num_members) +{ + int i; + + print_column_headers(fp); + for (i = 0; i < num_members; i++) { + (void) fprintf(fp, "%-25llu", info[i]->fmnode_id); + (void) fprintf(fp, "%-25s", info[i]->host_name); + (void) fprintf(fp, "%-25u", info[i]->controller_id); + (void) fprintf(fp, "%-25x\n", info[i]->cnode_id); + } +} + + + +int +topology(int cid) +{ + int num_conts; + int controller_id; + int i; + struct dump_info ***controller_info; + int cont_index = 0; + int member_index; + int total_num_members = 0; + struct dump_info **member_info; + int member_count; + + if (cid == -1) { + + /* get the number of controllers */ + if ((num_conts = wrsm_get_num_controllers()) < 0) { + perror("topology"); + return (1); + } + + } else { + + /* print the specific controller */ + num_conts = 1; + } + + /* allocate num_controllers info records to hold the needed data */ + if ((controller_info = (struct dump_info ***)calloc(num_conts + 1, + sizeof (struct dump_info **))) == NULL) { + perror("topology"); + return (1); + } + /* Set last pointer to NULL for easy structure traversal, redundant */ + controller_info[num_conts] = NULL; + + for (i = 0; i < num_conts; ++i) { + + wrsm_controller_t *unpacked; + if (cid == -1) + controller_id = i; + else + controller_id = cid; + + if (wrsm_get_config(controller_id, &unpacked) != 0) { + continue; + } + /* + * allocate memory for the number of members in this + * controller + */ + if ((controller_info[cont_index] = (struct dump_info **) + calloc(unpacked->nmembers + 1, + sizeof (struct dump_info *))) == NULL) { + perror("toplogy"); + free_controller_info(controller_info); + free(unpacked); + return (1); + } + /* + * Set last pointer to NULL for easy structure + * traversal + */ + controller_info[cont_index][unpacked->nmembers] = NULL; + + /* + * Allocate each member record used to hold the info + * we are after and place the appropriate controller + * info in the new dump_info structs + */ + for (member_index = 0; + member_index < unpacked->nmembers; + member_index++) { + if ((controller_info[cont_index][member_index] = + (struct dump_info *) + calloc(1, sizeof (struct dump_info))) + == NULL) { + perror("toplogy"); + free_controller_info(controller_info); + free(unpacked); + return (1); + } + controller_info[cont_index][member_index]->fmnode_id = + unpacked->u_members.val.members[member_index] + ->fmnodeid; + (void) strcpy(controller_info[cont_index] + [member_index]->host_name, + unpacked->u_members.val.members[member_index]-> + hostname); + controller_info[cont_index][member_index]-> + controller_id = unpacked->controller_id; + controller_info[cont_index][member_index]-> + cnode_id = unpacked-> + u_members.val.members[member_index]-> + cnodeid; + } + + total_num_members += unpacked->nmembers; + cont_index++; + free(unpacked); + } + + /* + * All the member info is retrieved so now we allocate space for + * a flat array for sorting + */ + if ((member_info = (struct dump_info **)calloc(total_num_members, + sizeof (struct dump_info *))) == NULL) { + perror("toplogy"); + free_controller_info(controller_info); + return (1); + } + + /* copy the struct dump_info *'s to the one-dimensional array */ + cont_index = 0; + member_count = 0; + while (controller_info[cont_index] != NULL) { + member_index = 0; + while (controller_info[cont_index][member_index] != NULL) { + member_info[member_count++] = + controller_info[cont_index][member_index]; + member_index++; + } + cont_index++; + } + + qsort(member_info, total_num_members, + sizeof (struct dump_info *), compare); + + print_member_info(stdout, member_info, total_num_members); + + free(member_info); + free_controller_info(controller_info); + return (0); +} + +static int +check_cnode(int controller_id, wrsm_cnodeid_t cnode, int *time_nsec) +{ + int fd; + int rc; + wrsm_ping_arg_t arg; + char devname[BUFSIZ]; + const int count = 100; + + (void) sprintf(devname, CTLRDEVNAME, controller_id); + fd = open(devname, O_RDONLY); + if (fd == -1) { + perror("open"); + return (1); + } + + arg.ioctl_version = WRSM_CF_IOCTL_VERSION; + arg.target = cnode; + arg.count = count; + rc = ioctl(fd, WRSM_CTLR_PING, &arg); + (void) close(fd); + *time_nsec = arg.time / count; + + return (rc); +} + +static int +check(int controller_id, char *hostname) +{ + wrsm_controller_t *config; + int retval = 0; + boolean_t host_found = B_FALSE; + int i; + + if (controller_id < 0) { + int n; + + if ((n = wrsm_get_num_controllers()) < 0) { + perror("info"); + return (1); + } + for (i = 0; i < n; ++i) { + if (wrsm_get_config(i, &config) == 0) { + if (check(i, hostname)) { + retval = 1; + } + } + } + return (retval); + } + + if (wrsm_get_config(controller_id, &config) != 0) { + perror("check"); + return (1); + } + + (void) printf("controller %d:\n", controller_id); + + for (i = 0; i < config->nmembers; i++) { + wrsm_net_member_t *member = config->u_members.val.members[i]; + if (hostname == NULL || + strcmp(member->hostname, hostname) == 0) { + int ave_time; + int rc; + + host_found = B_TRUE; + rc = check_cnode(controller_id, member->cnodeid, + &ave_time); + if (rc == 0) { + (void) printf(" check of %s successful, " + "time = %d ns\n", member->hostname, + ave_time); + } else { + (void) printf(" check of %s failed\n", + member->hostname); + retval = 1; + } + } + } + if (!host_found) { + retval = 1; + } + return (retval); +} diff --git a/usr/src/cmd/wrsmconf/wrsmconf_msgs.h b/usr/src/cmd/wrsmconf/wrsmconf_msgs.h new file mode 100644 index 0000000000..2738cb3a39 --- /dev/null +++ b/usr/src/cmd/wrsmconf/wrsmconf_msgs.h @@ -0,0 +1,53 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2001 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef _WRSMCONF_MSGS_H +#define _WRSMCONF_MSGS_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MSG_FILE gettext("%s: failed reading file %s\n") +#define MSG_NOT_FOUND gettext("%s: controller %d not found in file %s\n") +#define MSG_INPUT1 gettext("Enter netlist in the form:\n") +#define MSG_INPUT2 gettext(" hostname.wci.link=hostname.wci.link\n") +#define MSG_INPUT3 gettext("Hit CTRL-D when done.\n") +#define MSG_LINK_IN_USE gettext("%s: %s.%d.%d already in use\n") +#define MSG_INVALID gettext("%s: invalid value for %s: %d\n") +#define MSG_UNKNOWN gettext("%s: unknown option '%s'\n") +#define MSG_PARSE_ERR gettext("%s: could not parse line: %s") +#define MSG_LINK_RANGE gettext("%s: link number out of range: %s\n") +#define MSG_NUM_HOSTS gettext("%s: number of hosts exceeds limit of %d\n") +#define MSG_NO_ROUTE gettext("%s: no route from %s to %s\n") + +#ifdef __cplusplus +} +#endif + +#endif /* _WRSMCONF_MSGS_H */ |
