mkconfig.c revision a83cadce5d3331b64803bfc641036cec23602c74
/*
* 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
* 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 <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
#else
#define TRACE(f)
#define DPRINTF(s)
#endif
#define MAXHOSTS 256
#define MAXLINKS 8
#define MAXOPTLEN 80
#define PAGE_SIZE 0x2000
#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
static int ncslice_base = NCSLICE_BASE;
static int controller = 0; /* Controller number to assign */
static int gnid_offset = 0;
typedef struct {
int remote_cnode;
int remote_wci;
int remote_link;
} link_info_t;
typedef struct {
int wci_id;
} wci_info_t;
typedef struct {
char name[WRSM_HOSTNAMELEN];
int num_wcis;
} host_info_t;
typedef struct {
int num_hosts;
union {
struct {
} raw;
typedef struct {
int wcia;
int wcib;
typedef struct {
int nsg;
typedef enum {
} 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 *
{
int i;
/* First search for a matching WCI */
return (wci);
}
}
/* Otherwise, create the WCI */
return (wci);
}
/* Adds link info to a host's wci */
static void
{
DPRINTF(("add_link(cnode=%d, wci_id=%d, link=%d, rem_cnode=%d, "
/* Check for loopback links and ignore */
return;
}
exit(1);
}
}
/* Creates a new host entry */
static int
{
int i;
break;
}
}
if (i == MAXHOSTS) {
MAXHOSTS);
exit(1);
}
return (i);
}
/* Given a host name, returns its cnode id, or creates a new one */
static int
{
int i;
/* First search for previous occurence */
for (i = 0; i < MAXHOSTS; i++) {
return (i);
}
}
}
/* Parses the netlist file into the config structure */
static void
{
char s[255];
char t[255];
FILE *f;
f = stdin;
} else {
show_usage = B_TRUE;
}
if (f == NULL) {
exit(1);
}
if (show_usage) {
}
while (fgets(t, sizeof (t), f)) {
int i;
int x;
DPRINTF(("parsing line: %s\n", 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] == '-') {
x = sscanf(&s[1],
if (n < 1 || n > 254) {
WRSMCONF_CREATE, "ncslice", n);
} else {
ncslice_base = n;
}
} else {
}
continue;
}
x = sscanf(s,
"%d "
"%d",
if (x < 1) {
/* Blank line */
continue;
} else if (x < 6) {
WRSMCONF_CREATE, t);
continue;
}
WRSMCONF_CREATE, s);
exit(1);
}
/* Link goes it both directions, so add both directions */
}
}
/*
* The following functions generate the actual config file
*/
/* Prints cnodeid section of config file */
static void
{
int i;
for (i = 0; i < MAXHOSTS; i++) {
continue;
}
ncslice);
}
}
/* Prints the link subsection of the wci section of the config file */
static void
{
int remote_gnid;
else
}
/* Checks if a node is already reachable */
static int
{
int i;
for (i = 0; i < *num_reachable; i++) {
if (reachable_list[i] == cnode) {
return (B_TRUE);
}
}
(*num_reachable)++;
return (B_FALSE);
}
/* Prints the wci section of the config file */
static void
{
int i;
int j;
/* Check for route_map_striping */
for (i = 0; i < MAXLINKS; i++) {
continue;
}
for (j = 0; j < i; j++) {
continue;
}
}
}
}
for (i = 0; i < MAXLINKS; i++) {
int reachable_list[MAXHOSTS];
int num_reachable = 0;
/* Add ourselves to the reachable list */
continue;
}
/* Make sure it's not a dup */
link->remote_cnode)) {
continue;
}
/* If not duplicate and remote node is a switch... */
/* Ignore switch, report on remote cnodes */
wci_info_t *swwci =
for (j = 0; j < MAXLINKS; j++) {
continue;
}
continue;
}
}
} else {
link->remote_cnode);
}
}
for (i = 0; i < MAXLINKS; i++) {
}
}
}
static wci_info_t *
{
int i;
}
}
return (NULL);
}
static boolean_t
{
int link;
DPRINTF(("wci_can_reach_direct(wci=%d, dest_cnode=%d)\n",
/* Look for direct connect */
DPRINTF((" wci_can_reach_direct: TRUE\n"));
return (B_TRUE);
}
}
DPRINTF((" wci_can_reach_direct: FALSE\n"));
return (B_FALSE);
}
static boolean_t
int dest_cnode)
{
int link;
DPRINTF(("wci_can_reach_multihop(wci=%d, dest_cnode=%d)\n",
/* Find the WCI at the other end of the link */
wci_info_t *mh_wci =
exit(1);
}
/* See if that WCI can get us where we're going */
DPRINTF((" wci_can_reach_multihop: TRUE\n"));
return (B_TRUE);
}
}
}
DPRINTF((" wci_can_reach_multihop: FALSE\n"));
return (B_FALSE);
}
static boolean_t
{
int i;
DPRINTF(("cnode_can_reach_direct(cnode=%d, dest_cnode=%d)\n",
cnode, dest_cnode));
if (wci_can_reach_direct(
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
{
int link;
DPRINTF(("wci_can_reach_passthrough(wci=%d, dest_cnode=%d)\n",
*num_switches = 0;
/* Try all links, until we've found two switches */
/*
* 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.
*/
dest_cnode)) {
/* Remember the passthrough node */
pt_cnode[*num_switches] =
(*num_switches)++;
DPRINTF((" wci_can_reach_passthrough: TRUE\n"));
}
}
return (*num_switches > 0);
}
/* Checks if this wci can reach the dest_cnode on one of its links */
static can_reach_t
int *pt_cnodes, int *num_switches)
{
DPRINTF(("wci_can_reach(wci=%d, dest_cnode=%d)\n",
*pt_cnodes = -1;
*num_switches = 0;
/* First try direct connect */
return (CAN_REACH_DIRECT);
}
/* Look for multihop */
if (multihop_allowed &&
return (CAN_REACH_MULTIHOP);
}
/* Finally, try passthrough */
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
int i;
return (i);
}
return (i);
}
/* Prints the stripe_group section of the config file */
static void
{
int i;
}
}
/* Prints the routing sections of the config file */
static void
{
int i;
int j;
int k;
int ptswitches[4];
int num_switches = 0;
for (i = 0; i < MAXHOSTS; i++) {
continue;
}
/* First check for WCI striping */
if (can_reach_j == CAN_REACH_NO) {
continue;
}
for (k = 0; k < j; k++) {
int sg;
int new_ptswitches[2];
int new_switches = 0;
&new_switches);
if (can_reach_k != can_reach_j) {
continue;
}
/* 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];
}
} else if (num_switches > 0) {
num_switches = 2;
}
"\t\tpreferred_route {\n");
"\t\t\tstriping_level %d\n",
(can_reach_j == CAN_REACH_PASSTHROUGH) ?
num_switches : 2);
"\t\t\trouting_method %s\n",
(can_reach_j == CAN_REACH_PASSTHROUGH) ?
"passthrough" : "multihop");
"\t\t\tstripe_group %d\n", sg);
if (can_reach_j == CAN_REACH_PASSTHROUGH) {
int k;
"\t\t\tswitches");
for (k = 0; k < num_switches; k++) {
ptswitches[k]);
}
}
}
}
/* Next, find out how many WCIs go there */
/* Note: We can always reach ourselves */
if (same_node) {
} else {
}
continue;
}
(can_reach == CAN_REACH_PASSTHROUGH) ?
num_switches : 1);
(can_reach == CAN_REACH_PASSTHROUGH) ?
"passthrough" : "multihop");
if (can_reach == CAN_REACH_PASSTHROUGH) {
int k;
for (k = 0; k < num_switches; k++) {
ptswitches[k]);
}
}
}
if (!found_a_route) {
}
if (passthrough_allowed && !same_node) {
"\t\tforwarding_ncslices 0x%x\n",
}
}
}
/* Prints a specific host configuration */
static void
{
int i;
2);
}
}
/* Prints config file for all hosts */
static void
{
int i;
for (i = 0; i < MAXHOSTS; i++) {
print_host(config, i);
}
}
}
/* Main */
int
{
/* Set MSB to differentiate from FM-generated version stamps */
return (1);
}
if (input_file == NULL)
input_file = "-";
if (output_file != NULL) {
return (1);
}
}
return (1);
}
return (0);
}