File: opamergeperf2.sh

package info (click to toggle)
opa-fm 10.10.3.0.11-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, sid, trixie
  • size: 18,448 kB
  • sloc: ansic: 251,720; perl: 14,888; sh: 14,847; makefile: 4,001; exp: 1,106; xml: 905; cpp: 93
file content (243 lines) | stat: -rwxr-xr-x 13,909 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
#!/bin/bash
# BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# END_ICS_COPYRIGHT8   ****************************************

# [ICS VERSION STRING: unknown]

# take output from two runs of opaextractperf2 and merge them by computing
# differences in performance counters
tempfile="$(mktemp)"
trap "rm -f ${tempfile}.prefix1 ${tempfile}.prefix2; exit 1" SIGHUP SIGTERM SIGINT
trap "rm -f ${tempfile}.prefix1 ${tempfile}.prefix2" EXIT


Usage_full()
{
	echo "Usage: ${cmd} before.csv after.csv" >&2
	echo "              or" >&2
	echo "       ${cmd} --help" >&2
	echo "   --help - produce full help text." >&2
	echo "   before.csv - output from a opaextractperf2 run" >&2
	echo "   after.csv - output from a opaextractperf2 run" >&2
	echo >&2
	echo "${cmd} merges output from two opaextactperf2 runs from the same fabric" >&2
	echo "Counters for matching links will be computed (before subtracted from after)" >&2
	echo "and a CSV file equivalent to opaextractperf2's output format will be generated" >&2
	echo "suitable for importing into a spreadsheet or parsing by other scripts." >&2
	echo >&2
	echo "The before.csv and after.csv input files must be generated from the same" >&2
	echo "fabric, with before.csv containing counters prior to after.csv." >&2
	echo "Both files must have been generated to contain the running counters without" >&2
	echo "any counter clears between before.csv and after.csv and without using any" >&2
	echo "interval options to opareport which might report delta counters as" >&2
	echo "opposed to running counters, such as opareport -i" >&2
	echo "or opareport with both --begin and --end options." >&2
	echo >&2
	echo "for example:" >&2
	echo "   ${cmd} before.csv after.csv > delta.csv" >&2
	echo >&2
	exit 0
}

Usage()
{
	echo "Usage: ${cmd} before.csv after.csv" >&2
	echo "              or" >&2
	echo "       ${cmd} --help" >&2
	echo "   --help - produce full help text." >&2
	echo "   before.csv - output from a opaextractperf2 run" >&2
	echo "   after.csv - output from a opaextractperf2 run" >&2
	echo >&2
	echo "for example:" >&2
	echo "   ${cmd} before.csv after.csv > delta.csv" >&2
	echo >&2
	exit 2
}

## Main function
res=0

cmd=`basename $0`
if [ x"$1" = "x--help" ]
then
	Usage_full
fi

if [ "$#" != 2 ]
then
	Usage
fi

f1="$1"
f2="$2"
if [ ! -e "$f1" ]
then
	echo "$f1: Not Found" >&2
	Usage
fi
if [ ! -e "$f2" ]
then
	echo "$f2: Not Found" >&2
	Usage
fi

IFS=';'

# omit heading line
# add sequencing number and line number before desc;type;guid;port so same
# device in each file will sort next to eachother and f1 sorts before f2.
nl -s';' "$f1"|tail -n+2 | sed -e 's/^ */1;/'|sort --field-separator=';' --key='5,6' > ${tempfile}.prefix1
nl -s';' "$f2"|tail -n+2 | sed -e 's/^ */2;/'|sort --field-separator=';' --key='5,6' > ${tempfile}.prefix2
# some debug code which can help identify nodes which are not in both files
#cut -f3-6 -d';' ${tempfile}.prefix1 > ${tempfile}.nodes1
#cut -f3-6 -d';' ${tempfile}.prefix2 > ${tempfile}.nodes2
#if ! diff ${tempfile}.nodes1 ${tempfile}.nodes2 > /dev/null
#then
#	echo "$cmd: Warning: node list mismatch" >&2
#	#diff -c ${tempfile}.nodes1 ${tempfile}.nodes2 | head -20
#fi

IFS=';'
{ 
# output heading
head -1 "$f1"
# compute counter differences f2 - f1
use_2=n # do _2 variables potentially have 1st line ("1") for a port
# sort by guid;port then prefix, this puts same ports next to eachother with
# line from f1 before line from f2
# the loop must handle cases where a device appears only in f1 or f2
# as well as where the neighbor to a device has changed between f1 and f2
# in a stable fabric these will not happen.  However in a fabric with a few
# bad links, devices offline or where cables have been moved, this can happen
( cat ${tempfile}.prefix1 ${tempfile}.prefix2|sort --field-separator=';' --key='5,6' --key '1,1'; echo "END" ) | \
	while read num_1 lineno_1 NodeDesc_1 NodeType_1 NodeGUID_1 PortNum_1 nNodeDesc_1 nNodeType_1 nNodeGUID_1 nPortNum_1 LinkSpeedActive_1 LinkWidthDnGradeTxActive_1 LinkWidthDnGradeRxActive_1 XmitDataMB_1 XmitData_1 XmitPkts_1 MulticastXmitPkts_1 RcvDataMB_1 RcvData_1 RcvPkts_1 MulticastRcvPkts_1 XmitWait_1 CongDiscards_1 XmitTimeCong_1 MarkFECN_1 RcvFECN_1 RcvBECN_1 RcvBubble_1 XmitWastedBW_1 XmitWaitData_1 LinkQualityIndicator_1 LocalLinkIntegrityErrors_1 RcvErrors_1 ExcessiveBufferOverruns_1 LinkErrorRecovery_1 LinkDowned_1 UncorrectableErrors_1 FMConfigErrors_1 XmitConstraintErrors_1 RcvConstraintErrors_1 RcvSwitchRelayErrors_1 XmitDiscards_1 RcvRemotePhysicalErrors_1
do
	if [ x"$num_1" = x"END" ]
	then
		# normal end of file
		break
	fi
	if ! [[ x"$RcvRemotePhysicalErrors_1" =~ ^x[0-9]+$ ]]
	then
		# lines with insufficient columns, extra columns or non-numeric in
		# last column will fail the test.  To balance performance and input
		# checking we only check the last column since invalid input files
		# will typically have the wrong number of columns
		if [ x"$num_1" = x"1" ]
		then
			echo "$cmd: Invalid input line: $lineno_1 file: $f1" >&2
		else
			echo "$cmd: Invalid input line: $lineno_1 file: $f2" >&2
		fi
		exit 1
	fi
	if [ x"$num_1" = x"2" ]
	then
		#echo "process num_1=2" >&2
		if [ "$use_2" != y  ]
		then
			# "2" without a preceeding "1", skip line just read into _1
			echo "$cmd: Warning: skipping unmatched line $lineno_1 in after: $NodeDesc_1;$NodeType_1;$NodeGUID_1;$PortNum_1" >&2
		else
			# _2 has our "1", _1 has our "2"
			if [ x"$NodeGUID_1" != x"$NodeGUID_2" -o  x"$PortNum_1" != x"$PortNum_2" ]
			then
				# got a "1" followed by a "2" and they don't match, skip both
				echo "$cmd: Warning: skipping unmatched line $lineno_2 in before: $NodeDesc_2;$NodeType_2;$NodeGUID_2;$PortNum_2" >&2
				echo "$cmd: Warning: skipping unmatched line $lineno_1 in after: $NodeDesc_1;$NodeType_1;$NodeGUID_1;$PortNum_1" >&2
			elif [ x"$nNodeGUID_1" != x"$nNodeGUID_2" -o  x"$nPortNum_1" != x"$nPortNum_2" ]
			then
				# we got a "1" followed by "2", however neighbor changed
				echo "$cmd: Warning: skipping changed line $lineno_2 in before: $NodeDesc_2;$NodeType_2;$NodeGUID_2;$PortNum_2;$nNodeDesc_2;$nNodeType_2;$nNodeGUID_2;$nPortNum_2" >&2
				echo "$cmd: Warning: skipping changed line $lineno_1 in after: $NodeDesc_1;$NodeType_1;$NodeGUID_1;$PortNum_1;$nNodeDesc_1;$nNodeType_1;$nNodeGUID_1;$nPortNum_1" >&2
			else
				#echo "process num_1=2 use_2" >&2
				# use _2 as before and _1 as after when compute delta
				# for fields not subtracted, show after (_1) as more recent
				echo "$NodeDesc_1;$NodeType_1;$NodeGUID_1;$PortNum_1;$nNodeDesc_1;$nNodeType_1;$nNodeGUID_1;$nPortNum_1;$LinkSpeedActive_1;$LinkWidthDnGradeTxActive_1;$LinkWidthDnGradeRxActive_1;$(($XmitDataMB_1 - $XmitDataMB_2));$(($XmitData_1 - $XmitData_2));$(($XmitPkts_1 - $XmitPkts_2));$(($MulticastXmitPkts_1 - $MulticastXmitPkts_2));$(($RcvDataMB_1 - $RcvDataMB_2));$(($RcvData_1 - $RcvData_2));$(($RcvPkts_1 - $RcvPkts_2));$(($MulticastRcvPkts_1 - $MulticastRcvPkts_2));$(($XmitWait_1 - $XmitWait_2));$(($CongDiscards_1 - $CongDiscards_2));$(($XmitTimeCong_1 - $XmitTimeCong_2));$(($MarkFECN_1 - $MarkFECN_2));$(($RcvFECN_1 - $RcvFECN_2));$(($RcvBECN_1 - $RcvBECN_2));$(($RcvBubble_1 - $RcvBubble_2));$(($XmitWastedBW_1 - $XmitWastedBW_2));$(($XmitWaitData_1 - $XmitWaitData_2));$(($LinkQualityIndicator_1 < $LinkQualityIndicator_2?$LinkQualityIndicator_1:$LinkQualityIndicator_2));$(($LocalLinkIntegrityErrors_1 - $LocalLinkIntegrityErrors_2));$(($RcvErrors_1 - $RcvErrors_2));$(($ExcessiveBufferOverruns_1 - $ExcessiveBufferOverruns_2));$(($LinkErrorRecovery_1 - $LinkErrorRecovery_2));$(($LinkDowned_1 - $LinkDowned_2));$(($UncorrectableErrors_1 - $UncorrectableErrors_2));$(($FMConfigErrors_1 - $FMConfigErrors_2));$(($XmitConstraintErrors_1 - $XmitConstraintErrors_2));$(($RcvConstraintErrors_1 - $RcvConstraintErrors_2));$(($RcvSwitchRelayErrors_1 - $RcvSwitchRelayErrors_2));$(($XmitDiscards_1 - $XmitDiscards_2));$(($RcvRemotePhysicalErrors_1 - $RcvRemotePhysicalErrors_2))"
			fi
		fi
	else
		# num_1 is "1"
		read num_2 lineno_2 NodeDesc_2 NodeType_2 NodeGUID_2 PortNum_2 nNodeDesc_2 nNodeType_2 nNodeGUID_2 nPortNum_2 LinkSpeedActive_2 LinkWidthDnGradeTxActive_2 LinkWidthDnGradeRxActive_2 XmitDataMB_2 XmitData_2 XmitPkts_2 MulticastXmitPkts_2 RcvDataMB_2 RcvData_2 RcvPkts_2 MulticastRcvPkts_2 XmitWait_2 CongDiscards_2 XmitTimeCong_2 MarkFECN_2 RcvFECN_2 RcvBECN_2 RcvBubble_2 XmitWastedBW_2 XmitWaitData_2 LinkQualityIndicator_2 LocalLinkIntegrityErrors_2 RcvErrors_2 ExcessiveBufferOverruns_2 LinkErrorRecovery_2 LinkDowned_2 UncorrectableErrors_2 FMConfigErrors_2 XmitConstraintErrors_2 RcvConstraintErrors_2 RcvSwitchRelayErrors_2 XmitDiscards_2 RcvRemotePhysicalErrors_2
		#echo "process num_2=$num_2" >&2
		if [ x"$num_2" = x"END" ]
		then
			# "1" without a "2" at end of file
			echo "$cmd: Warning: skipping unmatched line $lineno_1 in before: $NodeDesc_1;$NodeType_1;$NodeGUID_1;$PortNum_1" >&2
			break
		fi
		if ! [[ x"$RcvRemotePhysicalErrors_2" =~ ^x[0-9]+$ ]]
		then
			# lines with insufficient columns, extra columns or non-numeric in
			# last column will fail the test.  To balance performance and input
			# checking we only check the last column since invalid input files
			# will typically have the wrong number of columns
			if [ x"$num_2" = x"1" ]
			then
				echo "$cmd: Invalid input line: $lineno_2 file: $f1" >&2
			else
				echo "$cmd: Invalid input line: $lineno_2 file: $f2" >&2
			fi
			exit 1
		fi
		if [ x"$num_2" = x"1" ]
		then
			# two "1" in a row, skip _1, use this line for next pairing
			echo "$cmd: Warning: skipping unmatched line $lineno_1 in before: $NodeDesc_1;$NodeType_1;$NodeGUID_1;$PortNum_1" >&2
			use_2=y
			continue
		elif [ x"$num_1" != "x1" -o x"$num_2" != "x2" ]	# paranoid check
		then
			echo "$num_1 $num_2" >&2
			echo "$cmd: Script Error: Incorrect sort order" >&2
			exit 1
		else
			if [ x"$NodeGUID_1" != x"$NodeGUID_2" -o  x"$PortNum_1" != x"$PortNum_2" ]
			then
				# "1" followed by non-matching "2", skip both
				echo "$cmd: Warning: skipping unmatched line $lineno_1 in before: $NodeDesc_1;$NodeType_1;$NodeGUID_1;$PortNum_1" >&2
				echo "$cmd: Warning: skipping unmatched line $lineno_2 in after: $NodeDesc_2;$NodeType_2;$NodeGUID_2;$PortNum_2" >&2
			elif [ x"$nNodeGUID_1" != x"$nNodeGUID_2" -o  x"$nPortNum_1" != x"$nPortNum_2" ]
			then
				# we got a "1" followed by "2", however neighbor changed
				echo "$cmd: Warning: skipping changed line $lineno_1 in before: $NodeDesc_1;$NodeType_1;$NodeGUID_1;$PortNum_1;$nNodeDesc_1;$nNodeType_1;$nNodeGUID_1;$nPortNum_1" >&2
				echo "$cmd: Warning: skipping changed line $lineno_2 in after: $NodeDesc_2;$NodeType_2;$NodeGUID_2;$PortNum_2;$nNodeDesc_2;$nNodeType_2;$nNodeGUID_2;$nPortNum_2" >&2
			else
				# for fields not subtracted, show after (_2) as more recent
				echo "$NodeDesc_2;$NodeType_2;$NodeGUID_2;$PortNum_2;$nNodeDesc_2;$nNodeType_2;$nNodeGUID_2;$nPortNum_2;$LinkSpeedActive_2;$LinkWidthDnGradeTxActive_2;$LinkWidthDnGradeRxActive_2;$(($XmitDataMB_2 - $XmitDataMB_1));$(($XmitData_2 - $XmitData_1));$(($XmitPkts_2 - $XmitPkts_1));$(($MulticastXmitPkts_2 - $MulticastXmitPkts_1));$(($RcvDataMB_2 - $RcvDataMB_1));$(($RcvData_2 - $RcvData_1));$(($RcvPkts_2 - $RcvPkts_1));$(($MulticastRcvPkts_2 - $MulticastRcvPkts_1));$(($XmitWait_2 - $XmitWait_1));$(($CongDiscards_2 - $CongDiscards_1));$(($XmitTimeCong_2 - $XmitTimeCong_1));$(($MarkFECN_2 - $MarkFECN_1));$(($RcvFECN_2 - $RcvFECN_1));$(($RcvBECN_2 - $RcvBECN_1));$(($RcvBubble_2 - $RcvBubble_1));$(($XmitWastedBW_2 - $XmitWastedBW_1));$(($XmitWaitData_2 - $XmitWaitData_1));$(($LinkQualityIndicator_2 < $LinkQualityIndicator_1?$LinkQualityIndicator_2:$LinkQualityIndicator_1));$(($LocalLinkIntegrityErrors_2 - $LocalLinkIntegrityErrors_1));$(($RcvErrors_2 - $RcvErrors_1));$(($ExcessiveBufferOverruns_2 - $ExcessiveBufferOverruns_1));$(($LinkErrorRecovery_2 - $LinkErrorRecovery_1));$(($LinkDowned_2 - $LinkDowned_1));$(($UncorrectableErrors_2 - $UncorrectableErrors_1));$(($FMConfigErrors_2 - $FMConfigErrors_1));$(($XmitConstraintErrors_2 - $XmitConstraintErrors_1));$(($RcvConstraintErrors_2 - $RcvConstraintErrors_1));$(($RcvSwitchRelayErrors_2 - $RcvSwitchRelayErrors_1));$(($XmitDiscards_2 - $XmitDiscards_1));$(($RcvRemotePhysicalErrors_2 - $RcvRemotePhysicalErrors_1))"
			fi
		fi
	fi
	use_2=n
done
}
res=$?
rm -rf ${tempfile}.prefix1 ${tempfile}.prefix2
exit $res