1#!/usr/bin/perl
2#
3# Copyright (c) 2007-2008 Voltaire, Inc. All rights reserved.
4# Copyright (c) 2006 The Regents of the University of California.
5#
6# This software is available to you under a choice of one of two
7# licenses.  You may choose to be licensed under the terms of the GNU
8# General Public License (GPL) Version 2, available from the file
9# COPYING in the main directory of this source tree, or the
10# OpenIB.org BSD license below:
11#
12#     Redistribution and use in source and binary forms, with or
13#     without modification, are permitted provided that the following
14#     conditions are met:
15#
16#      - Redistributions of source code must retain the above
17#        copyright notice, this list of conditions and the following
18#        disclaimer.
19#
20#      - Redistributions in binary form must reproduce the above
21#        copyright notice, this list of conditions and the following
22#        disclaimer in the documentation and/or other materials
23#        provided with the distribution.
24#
25# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32# SOFTWARE.
33#
34
35use strict;
36
37use Getopt::Std;
38use IBswcountlimits;
39
40sub usage_and_exit
41{
42	my $prog = $_[0];
43	print "Usage: $prog [-Rh]\n";
44	print
45"   Validate LIDs and GUIDs (check for zero and duplicates) in the local subnet\n";
46	print "   -h This help message\n";
47	print
48"   -R Recalculate ibnetdiscover information (Default is to reuse ibnetdiscover output)\n";
49	exit 2;
50}
51
52my $argv0          = `basename $0`;
53my $regenerate_map = undef;
54
55chomp $argv0;
56if (!getopts("hR")) { usage_and_exit $argv0; }
57if (defined $Getopt::Std::opt_h) { usage_and_exit $argv0; }
58if (defined $Getopt::Std::opt_R) { $regenerate_map = $Getopt::Std::opt_R; }
59
60sub validate_non_zero_lid
61{
62	my ($lid)      = shift(@_);
63	my ($nodeguid) = shift(@_);
64	my ($nodetype) = shift(@_);
65
66	if ($lid eq 0) {
67		print "LID 0 found for $nodetype NodeGUID $nodeguid\n";
68		return 1;
69	}
70	return 0;
71}
72
73sub validate_non_zero_guid
74{
75	my ($lid)      = shift(@_);
76	my ($guid)     = shift(@_);
77	my ($nodetype) = shift(@_);
78
79	if ($guid eq 0x0) {
80		print "$nodetype GUID 0x0 found with LID $lid\n";
81		return 1;
82	}
83	return 0;
84}
85
86$insert_lid::lids           = undef;
87$insert_nodeguid::nodeguids = undef;
88$insert_portguid::portguids = undef;
89
90sub insert_lid
91{
92	my ($lid)      = shift(@_);
93	my ($nodeguid) = shift(@_);
94	my ($nodetype) = shift(@_);
95	my $rec        = undef;
96	my $status     = "";
97
98	$status = validate_non_zero_lid($lid, $nodeguid, $nodetype);
99	if ($status eq 0) {
100		if (defined($insert_lid::lids{$lid})) {
101			print
102"LID $lid already defined for NodeGUID $insert_lid::lids{$lid}->{nodeguid}\n";
103		} else {
104			$rec = {lid => $lid, nodeguid => $nodeguid};
105			$insert_lid::lids{$lid} = $rec;
106		}
107	}
108}
109
110sub insert_nodeguid
111{
112	my ($lid)      = shift(@_);
113	my ($nodeguid) = shift(@_);
114	my ($nodetype) = shift(@_);
115	my $rec        = undef;
116	my $status     = "";
117
118	$status = validate_non_zero_guid($lid, $nodeguid, $nodetype);
119	if ($status eq 0) {
120		if (defined($insert_nodeguid::nodeguids{$nodeguid})) {
121			print
122"NodeGUID $nodeguid already defined for LID $insert_nodeguid::nodeguids{$nodeguid}->{lid}\n";
123		} else {
124			$rec = {lid => $lid, nodeguid => $nodeguid};
125			$insert_nodeguid::nodeguids{$nodeguid} = $rec;
126		}
127	}
128}
129
130sub validate_portguid
131{
132	my ($portguid)  = shift(@_);
133	my ($firstport) = shift(@_);
134
135	if (defined($insert_nodeguid::nodeguids{$portguid})
136		&& ($firstport ne "yes"))
137	{
138		print "PortGUID $portguid is invalid duplicate of a NodeGUID\n";
139	}
140}
141
142sub insert_portguid
143{
144	my ($lid)       = shift(@_);
145	my ($portguid)  = shift(@_);
146	my ($nodetype)  = shift(@_);
147	my ($firstport) = shift(@_);
148	my $rec         = undef;
149	my $status      = "";
150
151	$status = validate_non_zero_guid($lid, $portguid, $nodetype);
152	if ($status eq 0) {
153		if (defined($insert_portguid::portguids{$portguid})) {
154			print
155"PortGUID $portguid already defined for LID $insert_portguid::portguids{$portguid}->{lid}\n";
156		} else {
157			$rec = {lid => $lid, portguid => $portguid};
158			$insert_portguid::portguids{$portguid} = $rec;
159			validate_portguid($portguid, $firstport);
160		}
161	}
162}
163
164sub main
165{
166	if ($regenerate_map
167		|| !(-f "$IBswcountlimits::cache_dir/ibnetdiscover.topology"))
168	{
169		generate_ibnetdiscover_topology;
170	}
171
172	open IBNET_TOPO, "<$IBswcountlimits::cache_dir/ibnetdiscover.topology"
173	  or die "Failed to open ibnet topology: $!\n";
174
175	my $nodetype  = "";
176	my $nodeguid  = "";
177	my $portguid  = "";
178	my $lid       = "";
179	my $line      = "";
180	my $firstport = "";
181
182	while ($line = <IBNET_TOPO>) {
183
184		if ($line =~ /^caguid=(.*)/ || $line =~ /^rtguid=(.*)/) {
185			$nodeguid = $1;
186			$nodetype = "";
187		}
188
189		if ($line =~ /^switchguid=(.*)/) {
190			$nodeguid = $1;
191			$portguid = "";
192			$nodetype = "";
193		}
194		if ($line =~ /^switchguid=(.*)\((.*)\)/) {
195			$nodeguid = $1;
196			$portguid = "0x" . $2;
197		}
198
199		if ($line =~ /^Switch.*\"S-(.*)\"\s+# (.*) port.* lid (\d+) .*/) {
200			$nodetype  = "switch";
201			$firstport = "yes";
202			$lid       = $3;
203			insert_lid($lid, $nodeguid, $nodetype);
204			insert_nodeguid($lid, $nodeguid, $nodetype);
205			if ($portguid ne "") {
206				insert_portguid($lid, $portguid, $nodetype, $firstport);
207			}
208		}
209		if ($line =~ /^Ca.*/) {
210			$nodetype  = "ca";
211			$firstport = "yes";
212		}
213		if ($line =~ /^Rt.*/) {
214			$nodetype  = "router";
215			$firstport = "yes";
216		}
217
218		if ($nodetype eq "ca" || $nodetype eq "router") {
219			if ($line =~ /"S-(.*)\# lid (\d+) .*/) {
220				$lid = $2;
221				insert_lid($lid, $nodeguid, $nodetype);
222				if ($firstport eq "yes") {
223					insert_nodeguid($lid, $nodeguid, $nodetype);
224					$firstport = "no";
225				}
226			}
227			if ($line =~ /^.*"H-(.*)\# lid (\d+) .*/) {
228				$lid = $2;
229				insert_lid($lid, $nodeguid, $nodetype);
230				if ($firstport eq "yes") {
231					insert_nodeguid($lid, $nodeguid, $nodetype);
232					$firstport = "no";
233				}
234			}
235			if ($line =~ /^.*"R-(.*)\# lid (\d+) .*/) {
236				$lid = $2;
237				insert_lid($lid, $nodeguid, $nodetype);
238				if ($firstport eq "yes") {
239					insert_nodeguid($lid, $nodeguid, $nodetype);
240					$firstport = "no";
241				}
242			}
243			if ($line =~ /^\[(\d+)\]\((.*)\)/) {
244				$portguid = "0x" . $2;
245				insert_portguid($lid, $portguid, $nodetype, $firstport);
246			}
247		}
248
249	}
250
251	close IBNET_TOPO;
252}
253main;
254
255