1219820Sjeff#!/usr/bin/perl
2219820Sjeff#
3219820Sjeff# Copyright (c) 2007-2008 Voltaire, Inc. All rights reserved.
4219820Sjeff# Copyright (c) 2006 The Regents of the University of California.
5219820Sjeff#
6219820Sjeff# This software is available to you under a choice of one of two
7219820Sjeff# licenses.  You may choose to be licensed under the terms of the GNU
8219820Sjeff# General Public License (GPL) Version 2, available from the file
9219820Sjeff# COPYING in the main directory of this source tree, or the
10219820Sjeff# OpenIB.org BSD license below:
11219820Sjeff#
12219820Sjeff#     Redistribution and use in source and binary forms, with or
13219820Sjeff#     without modification, are permitted provided that the following
14219820Sjeff#     conditions are met:
15219820Sjeff#
16219820Sjeff#      - Redistributions of source code must retain the above
17219820Sjeff#        copyright notice, this list of conditions and the following
18219820Sjeff#        disclaimer.
19219820Sjeff#
20219820Sjeff#      - Redistributions in binary form must reproduce the above
21219820Sjeff#        copyright notice, this list of conditions and the following
22219820Sjeff#        disclaimer in the documentation and/or other materials
23219820Sjeff#        provided with the distribution.
24219820Sjeff#
25219820Sjeff# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26219820Sjeff# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27219820Sjeff# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28219820Sjeff# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29219820Sjeff# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30219820Sjeff# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31219820Sjeff# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32219820Sjeff# SOFTWARE.
33219820Sjeff#
34219820Sjeff
35219820Sjeffuse strict;
36219820Sjeff
37219820Sjeffuse Getopt::Std;
38219820Sjeffuse IBswcountlimits;
39219820Sjeff
40219820Sjeffsub usage_and_exit
41219820Sjeff{
42219820Sjeff	my $prog = $_[0];
43219820Sjeff	print "Usage: $prog [-Rh]\n";
44219820Sjeff	print
45219820Sjeff"   Validate LIDs and GUIDs (check for zero and duplicates) in the local subnet\n";
46219820Sjeff	print "   -h This help message\n";
47219820Sjeff	print
48219820Sjeff"   -R Recalculate ibnetdiscover information (Default is to reuse ibnetdiscover output)\n";
49219820Sjeff	exit 2;
50219820Sjeff}
51219820Sjeff
52219820Sjeffmy $argv0          = `basename $0`;
53219820Sjeffmy $regenerate_map = undef;
54219820Sjeff
55219820Sjeffchomp $argv0;
56219820Sjeffif (!getopts("hR")) { usage_and_exit $argv0; }
57219820Sjeffif (defined $Getopt::Std::opt_h) { usage_and_exit $argv0; }
58219820Sjeffif (defined $Getopt::Std::opt_R) { $regenerate_map = $Getopt::Std::opt_R; }
59219820Sjeff
60219820Sjeffsub validate_non_zero_lid
61219820Sjeff{
62219820Sjeff	my ($lid)      = shift(@_);
63219820Sjeff	my ($nodeguid) = shift(@_);
64219820Sjeff	my ($nodetype) = shift(@_);
65219820Sjeff
66219820Sjeff	if ($lid eq 0) {
67219820Sjeff		print "LID 0 found for $nodetype NodeGUID $nodeguid\n";
68219820Sjeff		return 1;
69219820Sjeff	}
70219820Sjeff	return 0;
71219820Sjeff}
72219820Sjeff
73219820Sjeffsub validate_non_zero_guid
74219820Sjeff{
75219820Sjeff	my ($lid)      = shift(@_);
76219820Sjeff	my ($guid)     = shift(@_);
77219820Sjeff	my ($nodetype) = shift(@_);
78219820Sjeff
79219820Sjeff	if ($guid eq 0x0) {
80219820Sjeff		print "$nodetype GUID 0x0 found with LID $lid\n";
81219820Sjeff		return 1;
82219820Sjeff	}
83219820Sjeff	return 0;
84219820Sjeff}
85219820Sjeff
86219820Sjeff$insert_lid::lids           = undef;
87219820Sjeff$insert_nodeguid::nodeguids = undef;
88219820Sjeff$insert_portguid::portguids = undef;
89219820Sjeff
90219820Sjeffsub insert_lid
91219820Sjeff{
92219820Sjeff	my ($lid)      = shift(@_);
93219820Sjeff	my ($nodeguid) = shift(@_);
94219820Sjeff	my ($nodetype) = shift(@_);
95219820Sjeff	my $rec        = undef;
96219820Sjeff	my $status     = "";
97219820Sjeff
98219820Sjeff	$status = validate_non_zero_lid($lid, $nodeguid, $nodetype);
99219820Sjeff	if ($status eq 0) {
100219820Sjeff		if (defined($insert_lid::lids{$lid})) {
101219820Sjeff			print
102219820Sjeff"LID $lid already defined for NodeGUID $insert_lid::lids{$lid}->{nodeguid}\n";
103219820Sjeff		} else {
104219820Sjeff			$rec = {lid => $lid, nodeguid => $nodeguid};
105219820Sjeff			$insert_lid::lids{$lid} = $rec;
106219820Sjeff		}
107219820Sjeff	}
108219820Sjeff}
109219820Sjeff
110219820Sjeffsub insert_nodeguid
111219820Sjeff{
112219820Sjeff	my ($lid)      = shift(@_);
113219820Sjeff	my ($nodeguid) = shift(@_);
114219820Sjeff	my ($nodetype) = shift(@_);
115219820Sjeff	my $rec        = undef;
116219820Sjeff	my $status     = "";
117219820Sjeff
118219820Sjeff	$status = validate_non_zero_guid($lid, $nodeguid, $nodetype);
119219820Sjeff	if ($status eq 0) {
120219820Sjeff		if (defined($insert_nodeguid::nodeguids{$nodeguid})) {
121219820Sjeff			print
122219820Sjeff"NodeGUID $nodeguid already defined for LID $insert_nodeguid::nodeguids{$nodeguid}->{lid}\n";
123219820Sjeff		} else {
124219820Sjeff			$rec = {lid => $lid, nodeguid => $nodeguid};
125219820Sjeff			$insert_nodeguid::nodeguids{$nodeguid} = $rec;
126219820Sjeff		}
127219820Sjeff	}
128219820Sjeff}
129219820Sjeff
130219820Sjeffsub validate_portguid
131219820Sjeff{
132219820Sjeff	my ($portguid)  = shift(@_);
133219820Sjeff	my ($firstport) = shift(@_);
134219820Sjeff
135219820Sjeff	if (defined($insert_nodeguid::nodeguids{$portguid})
136219820Sjeff		&& ($firstport ne "yes"))
137219820Sjeff	{
138219820Sjeff		print "PortGUID $portguid is invalid duplicate of a NodeGUID\n";
139219820Sjeff	}
140219820Sjeff}
141219820Sjeff
142219820Sjeffsub insert_portguid
143219820Sjeff{
144219820Sjeff	my ($lid)       = shift(@_);
145219820Sjeff	my ($portguid)  = shift(@_);
146219820Sjeff	my ($nodetype)  = shift(@_);
147219820Sjeff	my ($firstport) = shift(@_);
148219820Sjeff	my $rec         = undef;
149219820Sjeff	my $status      = "";
150219820Sjeff
151219820Sjeff	$status = validate_non_zero_guid($lid, $portguid, $nodetype);
152219820Sjeff	if ($status eq 0) {
153219820Sjeff		if (defined($insert_portguid::portguids{$portguid})) {
154219820Sjeff			print
155219820Sjeff"PortGUID $portguid already defined for LID $insert_portguid::portguids{$portguid}->{lid}\n";
156219820Sjeff		} else {
157219820Sjeff			$rec = {lid => $lid, portguid => $portguid};
158219820Sjeff			$insert_portguid::portguids{$portguid} = $rec;
159219820Sjeff			validate_portguid($portguid, $firstport);
160219820Sjeff		}
161219820Sjeff	}
162219820Sjeff}
163219820Sjeff
164219820Sjeffsub main
165219820Sjeff{
166219820Sjeff	if ($regenerate_map
167219820Sjeff		|| !(-f "$IBswcountlimits::cache_dir/ibnetdiscover.topology"))
168219820Sjeff	{
169219820Sjeff		generate_ibnetdiscover_topology;
170219820Sjeff	}
171219820Sjeff
172219820Sjeff	open IBNET_TOPO, "<$IBswcountlimits::cache_dir/ibnetdiscover.topology"
173219820Sjeff	  or die "Failed to open ibnet topology: $!\n";
174219820Sjeff
175219820Sjeff	my $nodetype  = "";
176219820Sjeff	my $nodeguid  = "";
177219820Sjeff	my $portguid  = "";
178219820Sjeff	my $lid       = "";
179219820Sjeff	my $line      = "";
180219820Sjeff	my $firstport = "";
181219820Sjeff
182219820Sjeff	while ($line = <IBNET_TOPO>) {
183219820Sjeff
184219820Sjeff		if ($line =~ /^caguid=(.*)/ || $line =~ /^rtguid=(.*)/) {
185219820Sjeff			$nodeguid = $1;
186219820Sjeff			$nodetype = "";
187219820Sjeff		}
188219820Sjeff
189219820Sjeff		if ($line =~ /^switchguid=(.*)/) {
190219820Sjeff			$nodeguid = $1;
191219820Sjeff			$portguid = "";
192219820Sjeff			$nodetype = "";
193219820Sjeff		}
194219820Sjeff		if ($line =~ /^switchguid=(.*)\((.*)\)/) {
195219820Sjeff			$nodeguid = $1;
196219820Sjeff			$portguid = "0x" . $2;
197219820Sjeff		}
198219820Sjeff
199219820Sjeff		if ($line =~ /^Switch.*\"S-(.*)\"\s+# (.*) port.* lid (\d+) .*/) {
200219820Sjeff			$nodetype  = "switch";
201219820Sjeff			$firstport = "yes";
202219820Sjeff			$lid       = $3;
203219820Sjeff			insert_lid($lid, $nodeguid, $nodetype);
204219820Sjeff			insert_nodeguid($lid, $nodeguid, $nodetype);
205219820Sjeff			if ($portguid ne "") {
206219820Sjeff				insert_portguid($lid, $portguid, $nodetype, $firstport);
207219820Sjeff			}
208219820Sjeff		}
209219820Sjeff		if ($line =~ /^Ca.*/) {
210219820Sjeff			$nodetype  = "ca";
211219820Sjeff			$firstport = "yes";
212219820Sjeff		}
213219820Sjeff		if ($line =~ /^Rt.*/) {
214219820Sjeff			$nodetype  = "router";
215219820Sjeff			$firstport = "yes";
216219820Sjeff		}
217219820Sjeff
218219820Sjeff		if ($nodetype eq "ca" || $nodetype eq "router") {
219219820Sjeff			if ($line =~ /"S-(.*)\# lid (\d+) .*/) {
220219820Sjeff				$lid = $2;
221219820Sjeff				insert_lid($lid, $nodeguid, $nodetype);
222219820Sjeff				if ($firstport eq "yes") {
223219820Sjeff					insert_nodeguid($lid, $nodeguid, $nodetype);
224219820Sjeff					$firstport = "no";
225219820Sjeff				}
226219820Sjeff			}
227219820Sjeff			if ($line =~ /^.*"H-(.*)\# lid (\d+) .*/) {
228219820Sjeff				$lid = $2;
229219820Sjeff				insert_lid($lid, $nodeguid, $nodetype);
230219820Sjeff				if ($firstport eq "yes") {
231219820Sjeff					insert_nodeguid($lid, $nodeguid, $nodetype);
232219820Sjeff					$firstport = "no";
233219820Sjeff				}
234219820Sjeff			}
235219820Sjeff			if ($line =~ /^.*"R-(.*)\# lid (\d+) .*/) {
236219820Sjeff				$lid = $2;
237219820Sjeff				insert_lid($lid, $nodeguid, $nodetype);
238219820Sjeff				if ($firstport eq "yes") {
239219820Sjeff					insert_nodeguid($lid, $nodeguid, $nodetype);
240219820Sjeff					$firstport = "no";
241219820Sjeff				}
242219820Sjeff			}
243219820Sjeff			if ($line =~ /^\[(\d+)\]\((.*)\)/) {
244219820Sjeff				$portguid = "0x" . $2;
245219820Sjeff				insert_portguid($lid, $portguid, $nodetype, $firstport);
246219820Sjeff			}
247219820Sjeff		}
248219820Sjeff
249219820Sjeff	}
250219820Sjeff
251219820Sjeff	close IBNET_TOPO;
252219820Sjeff}
253219820Sjeffmain;
254219820Sjeff
255