4 * Operations to compute and dump some MIB metrics.
6 * Copyright (c) 2000 Frank Strauss, Technical University of Braunschweig.
7 * Copyright (c) 2000 J. Schoenwaelder, Technical University of Braunschweig.
8 * Copyright (c) 2002 J. Schoenwaelder, University of Osnabrueck.
9 * Copyright (c) 2004 J. Schoenwaelder, International University Bremen.
11 * See the file "COPYING" for information on usage and redistribution
12 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 * @(#) $Id: dump-metrics.c 8090 2008-04-18 12:56:29Z strauss $
21 # count node references in notification definitions
35 static int silent = 0;
38 typedef struct BasetypeCounter {
40 unsigned long unknown;
41 unsigned long integer32;
42 unsigned long octetstring;
43 unsigned long objectidentifier;
44 unsigned long unsigned32;
45 unsigned long integer64;
46 unsigned long unsigned64;
47 unsigned long float32;
48 unsigned long float64;
49 unsigned long float128;
52 unsigned long pointer;
56 typedef struct StatusCounter {
58 unsigned long current;
59 unsigned long deprecated;
60 unsigned long obsolete;
65 typedef struct AccessCounter {
67 unsigned long noaccess;
69 unsigned long readonly;
70 unsigned long readwrite;
75 typedef struct IndexCounter {
78 unsigned long augment;
79 unsigned long reorder;
86 typedef struct IndexLenCounter {
88 unsigned long length[11];
93 typedef struct TableLenCounter {
95 unsigned long length[81];
100 typedef struct ScalarLenCounter {
102 unsigned long length[81];
107 typedef struct IndexComplexityCounter {
109 unsigned long complexity[100];
110 } IndexComplexityCounter;
114 typedef struct LengthCounter {
117 unsigned long descr_len;
118 unsigned long reference;
119 unsigned long reference_len;
121 unsigned long units_len;
122 unsigned long format;
123 unsigned long format_len;
128 typedef struct RowStatusCounter {
129 unsigned long basetables;
130 unsigned long rowstatus;
131 unsigned long storagetype;
136 typedef struct Metrics {
137 BasetypeCounter basetypesColumns;
138 BasetypeCounter basetypesScalars;
139 BasetypeCounter basetypesAll;
140 StatusCounter statusTypes;
141 StatusCounter statusTables;
142 StatusCounter statusColumns;
143 StatusCounter statusScalars;
144 StatusCounter statusNotifications;
145 StatusCounter statusGroups;
146 StatusCounter statusCompliances;
147 StatusCounter statusAll;
148 AccessCounter accessColumns;
149 AccessCounter accessScalars;
150 AccessCounter accessAll;
151 IndexCounter indexTables;
152 IndexLenCounter indexLenTables;
153 IndexComplexityCounter indexComplexity;
154 TableLenCounter tableLength;
155 ScalarLenCounter scalarLength;
156 LengthCounter lengthTypes;
157 LengthCounter lengthTables;
158 LengthCounter lengthRows;
159 LengthCounter lengthColumns;
160 LengthCounter lengthScalars;
161 LengthCounter lengthNotifications;
162 LengthCounter lengthAll;
167 typedef struct UsageCounter {
171 struct UsageCounter *nextPtr;
175 static UsageCounter *typeList = NULL;
176 static UsageCounter *extTypeList = NULL;
177 static UsageCounter *extNodeList = NULL;
178 static UsageCounter *extModuleList = NULL;
179 static UsageCounter *indexComplexityList = NULL;
181 #define INCR_NODE 0x01
182 #define INCR_TYPE 0x02
186 getDateString(time_t t)
188 static char *s = NULL;
194 smiAsprintf(&s, "%04d-%02d-%02d",
195 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
202 language(SmiLanguage language)
205 (language == SMI_LANGUAGE_UNKNOWN) ? "-" :
206 (language == SMI_LANGUAGE_SMIV1) ? "SMIv1" :
207 (language == SMI_LANGUAGE_SMIV2) ? "SMIv2" :
208 (language == SMI_LANGUAGE_SMING) ? "SMIng" :
215 calcSize(SmiModule *smiModule)
221 for (smiType = smiGetFirstType(smiModule);
223 smiType = smiGetNextType(smiType)) {
229 for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
231 smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
233 switch (smiNode->nodekind) {
234 case SMI_NODEKIND_SCALAR:
235 case SMI_NODEKIND_COLUMN:
236 case SMI_NODEKIND_NOTIFICATION:
249 typedef void (*ForEachIndexFunc) (FILE *f, SmiNode *groupNode, SmiNode *smiNode, void *data);
252 foreachIndexDo(FILE *f, SmiNode *smiNode, ForEachIndexFunc func, void *data)
254 SmiNode *indexNode = NULL, *iNode;
255 SmiElement *smiElement;
257 switch (smiNode->indexkind) {
258 case SMI_INDEX_INDEX:
259 case SMI_INDEX_REORDER:
262 case SMI_INDEX_EXPAND: /* TODO: we have to do more work here! */
264 case SMI_INDEX_AUGMENT:
265 case SMI_INDEX_SPARSE:
266 indexNode = smiGetRelatedNode(smiNode);
268 case SMI_INDEX_UNKNOWN:
272 for (smiElement = smiGetFirstElement(indexNode);
273 smiElement; smiElement = smiGetNextElement(smiElement)) {
274 iNode = smiGetElementNode(smiElement);
276 (func) (f, smiNode, iNode, data);
285 incrUsageCounter(UsageCounter *uCntList, char *module, char *name, int incr)
289 for (uCnt = uCntList; uCnt; uCnt = uCnt->nextPtr) {
290 if (strcmp(uCnt->module, module) == 0
291 && (! name || strcmp(uCnt->name, name) == 0)) {
297 uCnt = (UsageCounter *) xmalloc(sizeof(UsageCounter));
298 uCnt->module = xstrdup(module);
299 uCnt->name = name ? xstrdup(name) : NULL;
301 uCnt->nextPtr = uCntList;
312 incrTypeAndNodeUsageCounter(SmiModule *smiModule, SmiNode *smiNode, int flags)
318 * First check whether the node is external. If yes, increment the
319 * external node counter and we are done.
322 extModule = smiGetNodeModule(smiNode)->name;
324 && strcmp(extModule, smiModule->name) != 0) {
325 if (flags & INCR_NODE) {
326 extNodeList = incrUsageCounter(extNodeList,
327 extModule, smiNode->name, 1);
328 extModuleList = incrUsageCounter(extModuleList, extModule, NULL, 1);
334 * Next, check whether the type of the node is external. If yes,
335 * increment the external type counter and we are done. Do not
336 * count base types (that is types that have no parent type).
339 smiType = smiGetNodeType(smiNode);
344 if (smiType->name && smiGetParentType(smiType)) {
345 char *extModule = smiGetTypeModule(smiType)->name;
346 if (extModule /* && *extModule */
347 && strcmp(extModule, smiModule->name) != 0) {
348 if (flags & INCR_TYPE) {
349 extTypeList = incrUsageCounter(extTypeList,
350 extModule, smiType->name, 1);
351 extModuleList = incrUsageCounter(extModuleList, extModule, NULL, 1);
357 * Finally, count the type name (whether external or not does not
358 * matter here nor does it matter whether it is a base type or
362 if (! smiType->name && smiGetParentType(smiType)) {
363 smiType = smiGetParentType(smiType);
365 typeList = incrUsageCounter(typeList, smiGetTypeModule(smiType)->name,
372 incrIndexComplexityCounter(SmiModule *smiModule, SmiNode *smiNode, int complexity)
374 indexComplexityList = incrUsageCounter(indexComplexityList,
375 smiModule->name, smiNode->name, complexity);
381 cmp(const void *va, const void *vb)
383 UsageCounter **a = (UsageCounter **) va;
384 UsageCounter **b = (UsageCounter **) vb;
386 if ((*a)->count > (*b)->count) return -1;
387 if ((*a)->count < (*b)->count) return 1;
389 if ((*a)->module && (*b)->module) {
390 int x = strcmp((*a)->module, (*b)->module);
394 if ((*a)->name && (*b)->name) {
395 int x = strcmp((*a)->name, (*b)->name);
405 fprintRevisions(FILE *f, int modLen, SmiRevision *smiRevision,
406 SmiModule *smiModule, int size)
411 n = fprintRevisions(f, modLen,
412 smiGetNextRevision(smiRevision), smiModule, -1);
413 fprintf(f, "%-*s %7s ", modLen, smiModule->name,
414 (size >= 0) ? language(smiModule->language) : "-");
416 fprintf(f, "%4d", size);
420 fprintf(f, " %3d %s\n", n, getDateString(smiRevision->date));
424 if (!smiRevision && size >= 0) {
425 fprintf(f, "%-*s %7s ", modLen, smiModule->name,
426 language(smiModule->language));
427 fprintf(f, "%4d", size);
428 fprintf(f, " - ----------\n");
437 fprintRevision(FILE *f, int modc, SmiModule **modv)
442 for (i = 0; i < modc; i++) {
443 if (modLen < strlen(modv[i]->name)) {
444 modLen = strlen(modv[i]->name);
448 fprintf(f, "%-*s LANGUAGE SIZE REVISION DATE\n", modLen, "MODULE");
450 for (i = 0; i < modc; i++) {
451 fprintRevisions(f, modLen, smiGetFirstRevision(modv[i]),
452 modv[i], calcSize(modv[i]));
461 fprintTypeUsage(FILE *f, UsageCounter *typeUsageList)
464 int modLen = 8, nameLen = 8;
467 UsageCounter **sortCnt;
469 /* should be sorted */
471 for (uCnt = typeUsageList, cnt = 0; uCnt; uCnt = uCnt->nextPtr, cnt++) {
472 if (modLen < strlen(uCnt->module)) {
473 modLen = strlen(uCnt->module);
475 if (nameLen < strlen(uCnt->name)) {
476 nameLen = strlen(uCnt->name);
478 total += uCnt->count;
485 /* create an array for a quick qsort */
487 sortCnt = (UsageCounter **) xmalloc(cnt * sizeof(UsageCounter *));
488 memset(sortCnt, 0, cnt * sizeof(UsageCounter *));
489 for (uCnt = typeUsageList, i = 0; uCnt; uCnt = uCnt->nextPtr, i++) {
492 qsort(sortCnt, cnt, sizeof(UsageCounter *), cmp);
496 "# The following table shows the distribution of the number of references\n"
497 "# to defined types (including base types) in the set of loaded MIB\n"
501 fprintf(f, "%-*s %-*s USAGE\n", modLen, "MODULE", nameLen, "TYPE");
503 for (i = 0; i < cnt; i++) {
504 fprintf(f, "%-*s %-*s ",
505 modLen, sortCnt[i]->module, nameLen, sortCnt[i]->name);
507 fprintf(f, "%8u\n", sortCnt[i]->count);
509 fprintf(f, "%6.1f%%\n", (double) sortCnt[i]->count * 100 / total);
519 fprintExtTypeUsage(FILE *f, UsageCounter *typeUsageList)
522 int modLen = 8, nameLen = 8;
525 UsageCounter **sortCnt;
527 /* should be sorted */
529 for (uCnt = typeUsageList, cnt = 0; uCnt; uCnt = uCnt->nextPtr, cnt++) {
530 if (modLen < strlen(uCnt->module)) {
531 modLen = strlen(uCnt->module);
533 if (nameLen < strlen(uCnt->name)) {
534 nameLen = strlen(uCnt->name);
536 total += uCnt->count;
543 /* create an array for a quick qsort */
545 sortCnt = (UsageCounter **) xmalloc(cnt * sizeof(UsageCounter *));
546 memset(sortCnt, 0, cnt * sizeof(UsageCounter *));
547 for (uCnt = typeUsageList, i = 0; uCnt; uCnt = uCnt->nextPtr, i++) {
550 qsort(sortCnt, cnt, sizeof(UsageCounter *), cmp);
554 "# The following table shows the distribution of the number of references\n"
555 "# to externally defined types (excluding base types) in the set of loaded\n"
559 fprintf(f, "%-*s %-*s EXT-USAGE\n", modLen, "MODULE", nameLen, "TYPE");
561 for (i = 0; i < cnt; i++) {
562 fprintf(f, "%-*s %-*s ",
563 modLen, sortCnt[i]->module, nameLen, sortCnt[i]->name);
565 fprintf(f, "%8u\n", sortCnt[i]->count);
567 fprintf(f, "%6.1f%%\n", (double) sortCnt[i]->count * 100 / total);
577 fprintExtNodeUsage(FILE *f, UsageCounter *typeUsageList)
580 int modLen = 8, nameLen = 8;
583 UsageCounter **sortCnt;
585 /* should be sorted */
587 for (uCnt = typeUsageList, cnt = 0; uCnt; uCnt = uCnt->nextPtr, cnt++) {
588 if (modLen < strlen(uCnt->module)) {
589 modLen = strlen(uCnt->module);
591 if (nameLen < strlen(uCnt->name)) {
592 nameLen = strlen(uCnt->name);
594 total += uCnt->count;
601 /* create an array for a quick qsort */
603 sortCnt = (UsageCounter **) xmalloc(cnt * sizeof(UsageCounter *));
604 memset(sortCnt, 0, cnt * sizeof(UsageCounter *));
605 for (uCnt = typeUsageList, i = 0; uCnt; uCnt = uCnt->nextPtr, i++) {
608 qsort(sortCnt, cnt, sizeof(UsageCounter *), cmp);
612 "# The following table shows the distribution of the number of references\n"
613 "# to externally defined nodes in the set of loaded MIB modules.\n"
616 fprintf(f, "%-*s %-*s EXT-USAGE\n", modLen, "MODULE", nameLen, "NODE");
618 for (i = 0; i < cnt; i++) {
619 fprintf(f, "%-*s %-*s ",
620 modLen, sortCnt[i]->module, nameLen, sortCnt[i]->name);
622 fprintf(f, "%8u\n", sortCnt[i]->count);
624 fprintf(f, "%6.1f%%\n", (double) sortCnt[i]->count * 100 / total);
634 fprintModuleUsage(FILE *f, UsageCounter *modUsageList)
640 UsageCounter **sortCnt;
642 /* should be sorted */
644 for (uCnt = modUsageList, cnt = 0; uCnt; uCnt = uCnt->nextPtr, cnt++) {
645 if (modLen < strlen(uCnt->module)) {
646 modLen = strlen(uCnt->module);
648 total += uCnt->count;
655 /* create an array for a quick qsort */
657 sortCnt = (UsageCounter **) xmalloc(cnt * sizeof(UsageCounter *));
658 memset(sortCnt, 0, cnt * sizeof(UsageCounter *));
659 for (uCnt = modUsageList, i = 0; uCnt; uCnt = uCnt->nextPtr, i++) {
662 qsort(sortCnt, cnt, sizeof(UsageCounter *), cmp);
666 "# The following table shows the distribution of the number of references\n"
667 "# to externally defined items (such as types or objects) accumulated by\n"
668 "# the defining MIB module in the set of loaded MIB modules.\n"
671 fprintf(f, "%-*s EXT-USAGE\n", modLen, "MODULE");
673 for (i = 0; i < cnt; i++) {
674 fprintf(f, "%-*s ", modLen, sortCnt[i]->module);
676 fprintf(f, "%8u\n", sortCnt[i]->count);
678 fprintf(f, "%6.1f%%\n", (double) sortCnt[i]->count * 100 / total);
688 fprintIndexComplexity(FILE *f, UsageCounter *modUsageList)
695 UsageCounter **sortCnt;
697 /* should be sorted */
699 for (uCnt = modUsageList, cnt = 0; uCnt; uCnt = uCnt->nextPtr, cnt++) {
700 if (modLen < strlen(uCnt->module)) {
701 modLen = strlen(uCnt->module);
703 if (nameLen < strlen(uCnt->name)) {
704 nameLen = strlen(uCnt->name);
706 total += uCnt->count;
713 /* create an array for a quick qsort */
715 sortCnt = (UsageCounter **) xmalloc(cnt * sizeof(UsageCounter *));
716 memset(sortCnt, 0, cnt * sizeof(UsageCounter *));
717 for (uCnt = modUsageList, i = 0; uCnt; uCnt = uCnt->nextPtr, i++) {
720 qsort(sortCnt, cnt, sizeof(UsageCounter *), cmp);
724 "# The following table shows the distribution of the index complexity\n"
725 "# in the set of loaded MIB modules.\n"
728 fprintf(f, "%-*s %-*s COMPLEXITY\n", modLen, "MODULE", nameLen, "TABLE");
730 for (i = 0; i < cnt; i++) {
731 fprintf(f, "%-*s %-*s ", modLen, sortCnt[i]->module, nameLen, sortCnt[i]->name);
733 fprintf(f, "%8u\n", sortCnt[i]->count);
735 fprintf(f, "%6.1f%%\n", (double) sortCnt[i]->count);
745 freeUsageCounter(UsageCounter *usageCounterList)
747 UsageCounter *uCnt, *p;
749 for (uCnt = usageCounterList; uCnt; ) {
750 p = uCnt, uCnt = uCnt->nextPtr;
760 incrBasetypeCounter(BasetypeCounter *basetypeCounter, SmiNode *smiNode)
764 smiType = smiGetNodeType(smiNode);
766 basetypeCounter->total++;
767 switch (smiType->basetype) {
768 case SMI_BASETYPE_UNKNOWN:
769 basetypeCounter->unknown++;
771 case SMI_BASETYPE_INTEGER32:
772 basetypeCounter->integer32++;
774 case SMI_BASETYPE_OCTETSTRING:
775 basetypeCounter->octetstring++;
777 case SMI_BASETYPE_OBJECTIDENTIFIER:
778 basetypeCounter->objectidentifier++;
780 case SMI_BASETYPE_UNSIGNED32:
781 basetypeCounter->unsigned32++;
783 case SMI_BASETYPE_INTEGER64:
784 basetypeCounter->integer64++;
786 case SMI_BASETYPE_UNSIGNED64:
787 basetypeCounter->unsigned64++;
789 case SMI_BASETYPE_FLOAT32:
790 basetypeCounter->float32++;
792 case SMI_BASETYPE_FLOAT64:
793 basetypeCounter->float64++;
795 case SMI_BASETYPE_FLOAT128:
796 basetypeCounter->float128++;
798 case SMI_BASETYPE_ENUM:
799 basetypeCounter->enums++;
801 case SMI_BASETYPE_BITS:
802 basetypeCounter->bits++;
804 case SMI_BASETYPE_POINTER:
805 basetypeCounter->pointer++;
814 incrStatusCounter(StatusCounter *cnt, SmiStatus smiStatus)
818 case SMI_STATUS_CURRENT:
819 case SMI_STATUS_MANDATORY:
820 case SMI_STATUS_OPTIONAL:
823 case SMI_STATUS_DEPRECATED:
826 case SMI_STATUS_OBSOLETE:
829 case SMI_STATUS_UNKNOWN:
837 incrAccessCounter(AccessCounter *cnt, SmiAccess smiAccess)
841 case SMI_ACCESS_NOT_ACCESSIBLE:
844 case SMI_ACCESS_NOTIFY:
847 case SMI_ACCESS_READ_ONLY:
850 case SMI_ACCESS_READ_WRITE:
853 case SMI_ACCESS_INSTALL:
854 case SMI_ACCESS_INSTALL_NOTIFY:
855 case SMI_ACCESS_REPORT_ONLY:
856 case SMI_ACCESS_UNKNOWN:
857 case SMI_ACCESS_NOT_IMPLEMENTED:
858 case SMI_ACCESS_EVENT_ONLY:
866 incrIndexCounter(IndexCounter *cnt, SmiIndexkind indexkind)
870 case SMI_INDEX_INDEX:
873 case SMI_INDEX_AUGMENT:
876 case SMI_INDEX_REORDER:
879 case SMI_INDEX_SPARSE:
882 case SMI_INDEX_EXPAND:
885 case SMI_INDEX_UNKNOWN:
893 incrIndexLenCounter(IndexLenCounter *cnt, int len)
896 if (len < sizeof(cnt->length)/sizeof(cnt->length[0])) {
899 fprintf(stderr, "smidump: index len overflow: %d\n", len);
906 incrTableLenCounter(TableLenCounter *cnt, int len)
909 if (len < sizeof(cnt->length)/sizeof(cnt->length[0])) {
912 fprintf(stderr, "smidump: table len overflow: %d\n", len);
919 incrIndexComplexityMetric(IndexComplexityCounter *cnt, int cmplx)
922 if (cmplx < sizeof(cnt->complexity)/sizeof(cnt->complexity[0])) {
923 cnt->complexity[cmplx]++;
925 fprintf(stderr, "smidump: index complexity overflow: %d\n", cmplx);
932 incrLengthCounter(LengthCounter *cnt, char *description, char *reference,
933 char *units, char *format)
938 cnt->descr_len += strlen(description);
943 cnt->reference_len += strlen(reference);
947 cnt->units_len += strlen(units);
951 cnt->format_len += strlen(format);
958 incrRowStatusCounter(SmiNode *rowNode)
962 SmiModule *smiModule;
964 for (smiNode = smiGetFirstChildNode(rowNode);
966 smiNode = smiGetNextChildNode(smiNode)) {
967 smiType = smiGetNodeType(smiNode);
968 if (smiType && smiType->name) {
969 smiModule = smiGetTypeModule(smiType);
970 if (smiModule && smiModule->name
971 && strcmp(smiType->name, "RowStatus") == 0
972 && strcmp(smiModule->name, "SNMPv2-TC") == 0) {
980 fprintf(stderr, "** %s\t%s\t%s\n", rowNode->name,
981 smiNode->name, smiType->name);
982 /* xxx count rows indexed by ifIndex, InterfaceIndex, InterfaceIndexOrZero, ... */
990 count(FILE *f, SmiNode *row, SmiNode *col, void *data)
992 int *cnt = (int *) data;
1000 complexity(FILE *f, SmiNode *row, SmiNode *col, void *data)
1002 int *cmplx = (int *) data;
1004 unsigned long min, max;
1006 smiType = smiGetNodeType(col);
1011 switch (smiType->basetype) {
1012 case SMI_BASETYPE_INTEGER32:
1013 case SMI_BASETYPE_UNSIGNED32:
1014 case SMI_BASETYPE_ENUM:
1017 case SMI_BASETYPE_OCTETSTRING:
1018 case SMI_BASETYPE_OBJECTIDENTIFIER:
1019 case SMI_BASETYPE_BITS:
1021 min = smiGetMinSize(smiType);
1022 max = smiGetMaxSize(smiType);
1027 default: /* ignore everything else */
1035 yadayada(FILE *f, SmiNode *row, SmiNode *col, void *data)
1037 SmiModule *smiModule = (SmiModule *) data;
1040 if (col->access == SMI_ACCESS_NOT_ACCESSIBLE) {
1045 incrTypeAndNodeUsageCounter(smiModule, col, flags);
1051 addMetrics(Metrics *metrics, SmiModule *smiModule)
1057 for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
1059 smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
1060 len = smiNode->description ? strlen(smiNode->description) : 0;
1061 switch (smiNode->nodekind) {
1062 case SMI_NODEKIND_TABLE:
1063 incrStatusCounter(&metrics->statusTables, smiNode->status);
1064 incrStatusCounter(&metrics->statusAll, smiNode->status);
1065 incrLengthCounter(&metrics->lengthTables,
1066 smiNode->description, smiNode->reference,
1067 smiNode->units, smiNode->format);
1068 incrLengthCounter(&metrics->lengthAll,
1069 smiNode->description, smiNode->reference,
1070 smiNode->units, smiNode->format);
1072 case SMI_NODEKIND_ROW:
1073 incrIndexCounter(&metrics->indexTables, smiNode->indexkind);
1074 incrLengthCounter(&metrics->lengthRows,
1075 smiNode->description, smiNode->reference,
1076 smiNode->units, smiNode->format);
1077 incrLengthCounter(&metrics->lengthAll,
1078 smiNode->description, smiNode->reference,
1079 smiNode->units, smiNode->format);
1080 incrRowStatusCounter(smiNode);
1083 foreachIndexDo(NULL, smiNode, count, &cnt);
1084 incrIndexLenCounter(&metrics->indexLenTables, cnt);
1085 foreachIndexDo(NULL, smiNode, yadayada, smiModule);
1089 foreachIndexDo(NULL, smiNode, complexity, &cmplx);
1090 incrIndexComplexityCounter(smiModule, smiNode, cmplx);
1091 incrIndexComplexityMetric(&metrics->indexComplexity, cmplx);
1093 /* count the childs ... */
1095 SmiModule *smiModule = smiGetModule("SNMPv2-TC");
1097 SmiType *rowStatus = smiGetType(smiModule, "RowStatus");
1098 SmiType *storageType = smiGetType(smiModule, "StorageType");
1099 /* include index elements not in table */
1101 for (childNode = smiGetFirstChildNode(smiNode);
1103 childNode = smiGetNextChildNode(childNode)) {
1105 if (rowStatus == smiGetNodeType(childNode)) {
1106 fprintf(stderr, "**** GEEEEEE - ROWSTATUS\n");
1108 if (storageType == smiGetNodeType(childNode)) {
1109 fprintf(stderr, "**** GEEEEEE - STORAGETYPE\n");
1112 incrTableLenCounter(&metrics->tableLength, n);
1115 case SMI_NODEKIND_COLUMN:
1116 incrBasetypeCounter(&metrics->basetypesColumns, smiNode);
1117 incrBasetypeCounter(&metrics->basetypesAll, smiNode);
1118 incrStatusCounter(&metrics->statusColumns, smiNode->status);
1119 incrStatusCounter(&metrics->statusAll, smiNode->status);
1120 incrAccessCounter(&metrics->accessColumns, smiNode->access);
1121 incrAccessCounter(&metrics->accessAll, smiNode->access);
1122 incrLengthCounter(&metrics->lengthColumns,
1123 smiNode->description, smiNode->reference,
1124 smiNode->units, smiNode->format);
1125 incrLengthCounter(&metrics->lengthAll,
1126 smiNode->description, smiNode->reference,
1127 smiNode->units, smiNode->format);
1128 incrTypeAndNodeUsageCounter(smiModule, smiNode, INCR_TYPE);
1130 case SMI_NODEKIND_SCALAR:
1131 incrBasetypeCounter(&metrics->basetypesScalars, smiNode);
1132 incrBasetypeCounter(&metrics->basetypesAll, smiNode);
1133 incrStatusCounter(&metrics->statusScalars, smiNode->status);
1134 incrStatusCounter(&metrics->statusAll, smiNode->status);
1135 incrAccessCounter(&metrics->accessScalars, smiNode->access);
1136 incrAccessCounter(&metrics->accessAll, smiNode->access);
1137 incrLengthCounter(&metrics->lengthScalars,
1138 smiNode->description, smiNode->reference,
1139 smiNode->units, smiNode->format);
1140 incrLengthCounter(&metrics->lengthAll,
1141 smiNode->description, smiNode->reference,
1142 smiNode->units, smiNode->format);
1143 incrTypeAndNodeUsageCounter(smiModule, smiNode, INCR_TYPE);
1145 case SMI_NODEKIND_NOTIFICATION:
1146 incrStatusCounter(&metrics->statusNotifications, smiNode->status);
1147 incrStatusCounter(&metrics->statusAll, smiNode->status);
1148 incrLengthCounter(&metrics->lengthNotifications,
1149 smiNode->description, smiNode->reference,
1150 smiNode->units, smiNode->format);
1151 incrLengthCounter(&metrics->lengthAll,
1152 smiNode->description, smiNode->reference,
1153 smiNode->units, smiNode->format);
1155 case SMI_NODEKIND_GROUP:
1156 incrStatusCounter(&metrics->statusGroups, smiNode->status);
1157 incrStatusCounter(&metrics->statusAll, smiNode->status);
1159 case SMI_NODEKIND_COMPLIANCE:
1160 incrStatusCounter(&metrics->statusCompliances, smiNode->status);
1161 incrStatusCounter(&metrics->statusAll, smiNode->status);
1166 for (smiType = smiGetFirstType(smiModule);
1168 smiType = smiGetNextType(smiType)) {
1171 * Ignore all types with empty descriptions coming from the
1172 * "SNMPv2-SMI" module since they are not really defined
1173 * types but part of the language itself.
1176 if (! smiType->description) {
1177 SmiModule *m = smiGetTypeModule(smiType);
1178 if (m && strcmp(m->name, "SNMPv2-SMI") == 0) {
1183 incrStatusCounter(&metrics->statusTypes, smiType->status);
1184 incrStatusCounter(&metrics->statusAll, smiType->status);
1185 incrLengthCounter(&metrics->lengthTypes,
1186 smiType->description, smiType->reference,
1187 smiType->units, smiType->format);
1188 incrLengthCounter(&metrics->lengthAll,
1189 smiType->description, smiType->reference,
1190 smiType->units, smiType->format);
1197 fprintBasetypeCounter(FILE *f, BasetypeCounter *cnt, const char *s)
1202 "# The following table shows the basetype usage distribution in the\n"
1203 "# set of loaded MIB modules.\n"
1206 fprintf(f, "%-10s Int32 Uns32 Int64 Uns64 OctSt ObjId Enums Bits Flo32 Flo64 Flo128\n",
1212 fprintf(f, "%-10s %5lu %5lu %5lu %5lu %5lu %5lu %5lu %5lu %5lu %5lu %5lu\n", s,
1213 cnt->integer32, cnt->unsigned32,
1214 cnt->integer64, cnt->unsigned64,
1215 cnt->octetstring, cnt->objectidentifier,
1216 cnt->enums, cnt->bits,
1217 cnt->float32, cnt->float64, cnt->float128);
1219 fprintf(f, "%-10s %4.1f%% %4.1f%% %4.1f%% %4.1f%% %4.1f%% %4.1f%% %4.1f%% %4.1f%% %4.1f%% %4.1f%% %4.1f%%\n", s,
1220 cnt->total ? (double) cnt->integer32 * 100 / cnt->total : 0,
1221 cnt->total ? (double) cnt->unsigned32 * 100 / cnt->total : 0,
1222 cnt->total ? (double) cnt->integer64 * 100 / cnt->total : 0,
1223 cnt->total ? (double) cnt->unsigned64 * 100 / cnt->total : 0,
1224 cnt->total ? (double) cnt->octetstring * 100 / cnt->total : 0,
1225 cnt->total ? (double) cnt->objectidentifier * 100 / cnt->total : 0,
1226 cnt->total ? (double) cnt->enums * 100 / cnt->total : 0,
1227 cnt->total ? (double) cnt->bits * 100 / cnt->total : 0,
1228 cnt->total ? (double) cnt->float32 * 100 / cnt->total : 0,
1229 cnt->total ? (double) cnt->float64 * 100 / cnt->total : 0,
1230 cnt->total ? (double) cnt->float128 * 100 / cnt->total : 0);
1238 fprintStatusCounter(FILE *f, StatusCounter *cnt, char *s)
1243 "# The following table shows the status distribution of various\n"
1244 "# definitions contained in the set of loaded MIB modules.\n"
1247 fprintf(f, "%-14s %8s %8s %11s %9s\n", "CATEGORY",
1248 "TOTAL", "CURRENT", "DEPRECATED", "OBSOLETE");
1253 fprintf(f, "%-14s %8lu %8lu %11lu %9lu\n", s,
1254 cnt->total, cnt->current, cnt->deprecated, cnt->obsolete);
1256 fprintf(f, "%-14s %8lu %7.1f%% %10.1f%% %8.1f%%\n", s,
1258 cnt->total ? (double) cnt->current * 100 / cnt->total : 0,
1259 cnt->total ? (double) cnt->deprecated * 100 / cnt->total : 0,
1260 cnt->total ? (double) cnt->obsolete * 100 / cnt->total : 0);
1267 fprintAccessCounter(FILE *f, AccessCounter *cnt, char *s)
1272 "# The following table shows the access mode distribution of all scalar\n"
1273 "# or column definitions contained in the set of loaded MIB modules.\n"
1276 fprintf(f, "%-14s %8s %10s %9s %7s %8s\n", "CATEGORY",
1277 "TOTAL", "READWRITE", "READONLY", "NOTIFY", "NOACCES");
1282 fprintf(f, "%-14s %8lu %10lu %9lu %7lu %8lu\n", s,
1283 cnt->total, cnt->readwrite, cnt->readonly,
1284 cnt->notify, cnt->noaccess);
1286 fprintf(f, "%-14s %8lu %9.1f%% %8.1f%% %6.1f%% %7.1f%%\n", s,
1288 cnt->total ? (double) cnt->readwrite * 100 / cnt->total : 0,
1289 cnt->total ? (double) cnt->readonly * 100 / cnt->total : 0,
1290 cnt->total ? (double) cnt->notify * 100 / cnt->total : 0,
1291 cnt->total ? (double) cnt->noaccess * 100 / cnt->total : 0);
1298 fprintIndexCounter(FILE *f, IndexCounter *cnt, char *s)
1303 "# The following table shows the table index kind distribution of\n"
1304 "# table definitions contained in the set of loaded MIB modules.\n"
1306 fprintf(f, "%-14s %8s %8s %8s %8s %8s %8s\n", "CATEGORY",
1307 "TOTAL", "INDEX", "AUGMENT", "REORDER", "SPARSE", "EXPAND");
1313 fprintf(f, "%-14s %8lu %8lu %8lu %8lu %8lu %8lu\n", s,
1314 cnt->total, cnt->index, cnt->augment,
1315 cnt->reorder, cnt->sparse, cnt->expand);
1317 fprintf(f, "%-14s %8lu %7.1f%% %7.1f%% %7.1f%% %7.1f%% %7.1f%%\n", s,
1319 cnt->total ? (double) cnt->index * 100 / cnt->total : 0,
1320 cnt->total ? (double) cnt->augment * 100 / cnt->total : 0,
1321 cnt->total ? (double) cnt->reorder * 100 / cnt->total : 0,
1322 cnt->total ? (double) cnt->sparse * 100 / cnt->total : 0,
1323 cnt->total ? (double) cnt->expand * 100 / cnt->total : 0);
1330 fprintIndexLenCounter(FILE *f, IndexLenCounter *cnt, char *s)
1333 int n = sizeof(cnt->length)/sizeof(cnt->length[0]);
1339 "# The following table shows the table index length distribution of\n"
1340 "# table definitions contained in the set of loaded MIB modules.\n"
1343 fprintf(f, "%-10s %6s ", "CATEGORY", "TOTAL");
1344 for (i = 1; i < n; i++) {
1345 sprintf(buf, "[%d]", i);
1346 fprintf(f, " %5s", buf);
1352 fprintf(f, "%-10s %6lu ", s, cnt->total);
1354 for (i = 1; i < n; i++) {
1355 fprintf(f, " %5lu", cnt->length[i]);
1358 for (i = 1; i < n; i++) {
1359 fprintf(f, " %4.1f%%", (double) cnt->length[i] * 100 / cnt->total);
1369 fprintTableLenCounter(FILE *f, TableLenCounter *cnt, char *s)
1372 int n = sizeof(cnt->length)/sizeof(cnt->length[0]);
1378 "# The following table shows the table length distribution of\n"
1379 "# table definitions contained in the set of loaded MIB modules.\n"
1382 fprintf(f, "%-10s %6s ", "CATEGORY", "TOTAL");
1383 for (i = 1; i < n; i++) {
1384 sprintf(buf, "[%d]", i);
1385 fprintf(f, " %5s", buf);
1391 fprintf(f, "%-10s %6lu ", s, cnt->total);
1393 for (i = 1; i < n; i++) {
1394 fprintf(f, " %5lu", cnt->length[i]);
1397 for (i = 1; i < n; i++) {
1398 fprintf(f, " %4.1f%%", (double) cnt->length[i] * 100 / cnt->total);
1408 fprintLengthCounter(FILE *f, LengthCounter *cnt, char *s)
1413 "# The following table shows the text clause usage distribution of all\n"
1414 "# definitions contained in the set of loaded MIB modules.\n"
1417 fprintf(f, "%-14s %8s %12s %10s %8s %8s\n", "CATEGORY",
1418 "TOTAL", "DESCRIPTION", "REFERENCE", "UNIT", "FORMAT");
1423 fprintf(f, "%-14s %8lu %12lu %10lu %8lu %8lu\n", s,
1424 cnt->total, cnt->descr, cnt->reference,
1425 cnt->units, cnt->format);
1427 fprintf(f, "%-14s %8lu %11.1f%% %9.1f%% %7.1f%% %7.1f%%\n", s,
1429 cnt->total ? (double) cnt->descr * 100 / cnt->total : 0,
1430 cnt->total ? (double) cnt->reference * 100 / cnt->total : 0,
1431 cnt->total ? (double) cnt->units * 100 / cnt->total : 0,
1432 cnt->total ? (double) cnt->format * 100 / cnt->total : 0);
1439 fprintLengthCounter2(FILE *f, LengthCounter *cnt, char *s)
1444 "# The following table shows the %s text length distribution (in\n"
1445 "# bytes) of all definitions contained in the set of loaded MIB modules.\n"
1446 "\n", raw ? "total" : "average");
1448 fprintf(f, "%-14s %8s %12s %10s %8s %8s\n", "CATEGORY",
1449 "TOTAL", "DESCRIPTION", "REFERENCE", "UNIT", "FORMAT");
1454 fprintf(f, "%-14s %8lu %12lu %10lu %8lu %8lu\n", s,
1455 cnt->total, cnt->descr_len, cnt->reference_len,
1456 cnt->units_len, cnt->format_len);
1458 fprintf(f, "%-14s %8lu %12.1f %10.1f %8.1f %8.1f\n", s,
1460 cnt->descr ? (double) cnt->descr_len / cnt->descr : 0,
1461 cnt->reference ? (double) cnt->reference_len / cnt->reference : 0,
1462 cnt->units ? (double) cnt->units_len / cnt->units : 0,
1463 cnt->format ? (double) cnt->format_len / cnt->format : 0);
1470 fprintfComplexity(FILE *f, Metrics *metrics)
1472 unsigned long cmplx = 0, fctrs = 0;
1473 unsigned long total_cmplx = 0, total_fctrs = 0;
1477 "# The following table shows the complexity metrics of the set of loaded\n"
1481 fprintf(f, "%-14s %8s %8s %8s %8s\n", "CATEGORY", "TOTAL",
1482 "RAW", "WEIGHT", "COMPLEXITY");
1484 cmplx = metrics->accessScalars.readonly * 1;
1485 fctrs = metrics->accessScalars.readonly;
1486 fprintf(f, "%-14s %8lu %8lu\n", "Scalars (ro):", fctrs, cmplx);
1487 total_cmplx += cmplx;
1488 total_fctrs += fctrs;
1490 cmplx = metrics->accessScalars.readwrite * 2;
1491 fctrs = metrics->accessScalars.readwrite;
1492 fprintf(f, "%-14s %8lu %8lu\n", "Scalars (rw):", fctrs, cmplx);
1493 total_cmplx += cmplx;
1494 total_fctrs += fctrs;
1496 cmplx = metrics->accessColumns.readonly * 2;
1497 fctrs = metrics->accessColumns.readonly;
1498 fprintf(f, "%-14s %8lu %8lu\n", "Columns (ro):", fctrs, cmplx);
1499 total_cmplx += cmplx;
1500 total_fctrs += fctrs;
1502 cmplx = metrics->accessColumns.readwrite * 3;
1503 fctrs = metrics->accessColumns.readwrite;
1504 fprintf(f, "%-14s %8lu %8lu\n", "Columns (rw):", fctrs, cmplx);
1505 total_cmplx += cmplx;
1506 total_fctrs += fctrs;
1508 /* readcreate tables ? */
1510 /* table index complexity ? */
1515 for (i = 0; i < 100; i++) {
1516 cmplx += 3 * i * metrics->indexComplexity.complexity[i];
1518 fprintf(f, "%-14s %8lu %8lu\n", "Indexes:", metrics->indexComplexity.total, cmplx);
1521 fprintf(f, "%-14s %8lu %8lu\n", "Summary:", total_fctrs, total_cmplx);
1527 fprintMetrics(FILE *f, Metrics *metrics)
1529 fprintStatusCounter(f, NULL, NULL);
1530 fprintStatusCounter(f, &metrics->statusTypes, "Types:");
1531 fprintStatusCounter(f, &metrics->statusTables, "Tables:");
1532 fprintStatusCounter(f, &metrics->statusColumns, "Columns:");
1533 fprintStatusCounter(f, &metrics->statusScalars, "Scalars:");
1534 fprintStatusCounter(f, &metrics->statusNotifications, "Notifications:");
1535 fprintStatusCounter(f, &metrics->statusGroups, "Groups:");
1536 fprintStatusCounter(f, &metrics->statusCompliances, "Compliances:");
1537 fprintStatusCounter(f, &metrics->statusAll, "Summary:");
1539 fprintAccessCounter(f, NULL, NULL);
1540 fprintAccessCounter(f, &metrics->accessColumns, "Columns:");
1541 fprintAccessCounter(f, &metrics->accessScalars, "Scalars:");
1542 fprintAccessCounter(f, &metrics->accessAll, "Summary:");
1544 fprintIndexCounter(f, NULL, NULL);
1545 fprintIndexCounter(f, &metrics->indexTables, "Tables:");
1547 fprintIndexLenCounter(f, NULL, NULL);
1548 fprintIndexLenCounter(f, &metrics->indexLenTables, "Tables:");
1550 fprintTableLenCounter(f, NULL, NULL);
1551 fprintTableLenCounter(f, &metrics->tableLength, "Tables:");
1553 fprintLengthCounter(f, NULL, NULL);
1554 fprintLengthCounter(f, &metrics->lengthTypes, "Types:");
1555 fprintLengthCounter(f, &metrics->lengthTables, "Tables:");
1556 fprintLengthCounter(f, &metrics->lengthColumns, "Columns:");
1557 fprintLengthCounter(f, &metrics->lengthScalars, "Scalars:");
1558 fprintLengthCounter(f, &metrics->lengthNotifications, "Notifications:");
1559 fprintLengthCounter(f, &metrics->lengthAll, "Summary:");
1561 fprintLengthCounter2(f, NULL, NULL);
1562 fprintLengthCounter2(f, &metrics->lengthTypes, "Types:");
1563 fprintLengthCounter2(f, &metrics->lengthTables, "Tables:");
1564 fprintLengthCounter2(f, &metrics->lengthColumns, "Columns:");
1565 fprintLengthCounter2(f, &metrics->lengthScalars, "Scalars:");
1566 fprintLengthCounter2(f, &metrics->lengthNotifications, "Notifications:");
1567 fprintLengthCounter2(f, &metrics->lengthAll, "Summary:");
1569 fprintBasetypeCounter(f, NULL, NULL);
1570 fprintBasetypeCounter(f, &metrics->basetypesColumns, "Columns:");
1571 fprintBasetypeCounter(f, &metrics->basetypesScalars, "Scalars:");
1572 fprintBasetypeCounter(f, &metrics->basetypesAll, "Summary:");
1574 fprintfComplexity(f, metrics);
1576 fprintTypeUsage(f, typeList);
1577 freeUsageCounter(typeList), typeList = NULL;
1579 fprintExtTypeUsage(f, extTypeList);
1580 freeUsageCounter(extTypeList), extTypeList = NULL;
1582 fprintExtNodeUsage(f, extNodeList);
1583 freeUsageCounter(extNodeList), extNodeList = NULL;
1585 fprintModuleUsage(f, extModuleList);
1586 freeUsageCounter(extModuleList), extModuleList = NULL;
1588 fprintIndexComplexity(f, indexComplexityList);
1589 freeUsageCounter(indexComplexityList), indexComplexityList = NULL;
1596 dumpMetrics(int modc, SmiModule **modv, int flags, char *output)
1602 silent = (flags & SMIDUMP_FLAG_SILENT);
1605 f = fopen(output, "w");
1607 fprintf(stderr, "smidump: cannot open %s for writing: ", output);
1613 if (flags & SMIDUMP_FLAG_UNITE) {
1616 fprintf(f, "# united module metrics [%d modules] "
1617 "(generated by smidump " SMI_VERSION_STRING ")\n", modc);
1618 fprintf(f, "#\n# smidump -u -f metrics");
1619 if (raw) fprintf(f, " --metrics-raw");
1620 for (i = 0; i < modc; i++) {
1621 int len = strlen(modv[i]->name);
1622 if (pos + len > 70) {
1623 fprintf(f, " \\\n#\t"), pos = 8;
1625 fprintf(f, "%s ", modv[i]->name);
1628 fprintf(f, "%s\n", (pos == 8) ? "" : "\n");
1631 fprintRevision(f, modc, modv);
1633 for (i = 0; i < modc; i++) {
1634 memset(&metrics, 0, sizeof(Metrics));
1636 for (i = 0; i < modc; i++) {
1637 addMetrics(&metrics, modv[i]);
1639 fprintMetrics(f, &metrics);
1641 for (i = 0; i < modc; i++) {
1643 fprintf(f, "# %s module metrics (generated by smidump "
1644 SMI_VERSION_STRING ")\n\n", modv[i]->name);
1647 fprintRevision(f, 1, modv+i);
1649 memset(&metrics, 0, sizeof(Metrics));
1650 addMetrics(&metrics, modv[i]);
1651 fprintMetrics(f, &metrics);
1655 if (fflush(f) || ferror(f)) {
1656 perror("smidump: write error");
1670 static SmidumpDriverOption opt[] = {
1671 { "raw", OPT_FLAG, &raw, 0,
1672 "generate raw statistics (no percentages)"},
1673 { 0, OPT_END, 0, 0 }
1676 static SmidumpDriver driver = {
1681 "metrics characterizing MIB modules",
1686 smidumpRegisterDriver(&driver);