net-snmp 5.7
|
00001 00008 #include <net-snmp/net-snmp-config.h> 00009 #include <sys/types.h> 00010 #include <stdio.h> 00011 #include <stdlib.h> 00012 #include <ctype.h> 00013 #if HAVE_STRING_H 00014 #include <string.h> 00015 #else 00016 #include <strings.h> 00017 #endif 00018 00019 #include <net-snmp/types.h> 00020 #include <net-snmp/library/int64.h> 00021 #include <net-snmp/library/snmp_assert.h> 00022 #include <net-snmp/library/snmp_debug.h> 00023 #include <net-snmp/library/snmp_logging.h> 00024 00025 #include <net-snmp/net-snmp-features.h> 00026 00027 #define TRUE 1 00028 #define FALSE 0 00029 00038 void 00039 divBy10(U64 u64, U64 * pu64Q, unsigned int *puR) 00040 { 00041 unsigned long ulT; 00042 unsigned long ulQ; 00043 unsigned long ulR; 00044 00045 00046 /* 00047 * top 16 bits 00048 */ 00049 ulT = (u64.high >> 16) & 0x0ffff; 00050 ulQ = ulT / 10; 00051 ulR = ulT % 10; 00052 pu64Q->high = ulQ << 16; 00053 00054 /* 00055 * next 16 00056 */ 00057 ulT = (u64.high & 0x0ffff); 00058 ulT += (ulR << 16); 00059 ulQ = ulT / 10; 00060 ulR = ulT % 10; 00061 pu64Q->high = pu64Q->high | ulQ; 00062 00063 /* 00064 * next 16 00065 */ 00066 ulT = ((u64.low >> 16) & 0x0ffff) + (ulR << 16); 00067 ulQ = ulT / 10; 00068 ulR = ulT % 10; 00069 pu64Q->low = ulQ << 16; 00070 00071 /* 00072 * final 16 00073 */ 00074 ulT = (u64.low & 0x0ffff); 00075 ulT += (ulR << 16); 00076 ulQ = ulT / 10; 00077 ulR = ulT % 10; 00078 pu64Q->low = pu64Q->low | ulQ; 00079 00080 *puR = (unsigned int) (ulR); 00081 00082 00083 } /* divBy10 */ 00084 00085 00093 void 00094 multBy10(U64 u64, U64 * pu64P) 00095 { 00096 unsigned long ulT; 00097 unsigned long ulP; 00098 unsigned long ulK; 00099 00100 00101 /* 00102 * lower 16 bits 00103 */ 00104 ulT = u64.low & 0x0ffff; 00105 ulP = ulT * 10; 00106 ulK = ulP >> 16; 00107 pu64P->low = ulP & 0x0ffff; 00108 00109 /* 00110 * next 16 00111 */ 00112 ulT = (u64.low >> 16) & 0x0ffff; 00113 ulP = (ulT * 10) + ulK; 00114 ulK = ulP >> 16; 00115 pu64P->low = (ulP & 0x0ffff) << 16 | pu64P->low; 00116 00117 /* 00118 * next 16 bits 00119 */ 00120 ulT = u64.high & 0x0ffff; 00121 ulP = (ulT * 10) + ulK; 00122 ulK = ulP >> 16; 00123 pu64P->high = ulP & 0x0ffff; 00124 00125 /* 00126 * final 16 00127 */ 00128 ulT = (u64.high >> 16) & 0x0ffff; 00129 ulP = (ulT * 10) + ulK; 00130 ulK = ulP >> 16; 00131 pu64P->high = (ulP & 0x0ffff) << 16 | pu64P->high; 00132 00133 00134 } /* multBy10 */ 00135 00136 00144 void 00145 incrByU16(U64 * pu64, unsigned int u16) 00146 { 00147 unsigned long ulT1; 00148 unsigned long ulT2; 00149 unsigned long ulR; 00150 unsigned long ulK; 00151 00152 00153 /* 00154 * lower 16 bits 00155 */ 00156 ulT1 = pu64->low; 00157 ulT2 = ulT1 & 0x0ffff; 00158 ulR = ulT2 + u16; 00159 ulK = ulR >> 16; 00160 if (ulK == 0) { 00161 pu64->low = ulT1 + u16; 00162 return; 00163 } 00164 00165 /* 00166 * next 16 bits 00167 */ 00168 ulT2 = (ulT1 >> 16) & 0x0ffff; 00169 ulR = ulT2 + 1; 00170 ulK = ulR >> 16; 00171 if (ulK == 0) { 00172 pu64->low = ulT1 + u16; 00173 return; 00174 } 00175 00176 /* 00177 * next 32 - ignore any overflow 00178 */ 00179 pu64->low = (ulT1 + u16) & 0x0FFFFFFFFL; 00180 pu64->high++; 00181 #if SIZEOF_LONG != 4 00182 pu64->high &= 0xffffffff; 00183 #endif 00184 } /* incrByV16 */ 00185 00186 void 00187 incrByU32(U64 * pu64, unsigned int u32) 00188 { 00189 unsigned int tmp; 00190 tmp = pu64->low; 00191 pu64->low += u32; 00192 #if SIZEOF_LONG != 4 00193 pu64->low &= 0xffffffff; 00194 #endif 00195 if (pu64->low < tmp) { 00196 pu64->high++; 00197 #if SIZEOF_LONG != 4 00198 pu64->high &= 0xffffffff; 00199 #endif 00200 } 00201 } 00202 00206 void 00207 u64Subtract(const U64 * pu64one, const U64 * pu64two, U64 * pu64out) 00208 { 00209 if (pu64one->low < pu64two->low) { 00210 pu64out->low = 0xffffffff - pu64two->low + pu64one->low + 1; 00211 pu64out->high = pu64one->high - pu64two->high - 1; 00212 } else { 00213 pu64out->low = pu64one->low - pu64two->low; 00214 pu64out->high = pu64one->high - pu64two->high; 00215 } 00216 } 00217 00221 void 00222 u64Incr(U64 * pu64out, const U64 * pu64one) 00223 { 00224 pu64out->high += pu64one->high; 00225 #if SIZEOF_LONG != 4 00226 pu64out->high &= 0xffffffff; 00227 #endif 00228 incrByU32(pu64out, pu64one->low); 00229 } 00230 00234 void 00235 u64UpdateCounter(U64 * pu64out, const U64 * pu64one, const U64 * pu64two) 00236 { 00237 U64 tmp; 00238 u64Subtract(pu64one, pu64two, &tmp); 00239 u64Incr(pu64out, &tmp); 00240 } 00241 00245 netsnmp_feature_child_of(u64copy, netsnmp_unused) 00246 #ifndef NETSNMP_FEATURE_REMOVE_U64COPY 00247 void 00248 u64Copy(U64 * pu64one, const U64 * pu64two) 00249 { 00250 pu64one->high = pu64two->high; 00251 pu64one->low = pu64two->low; 00252 } 00253 #endif /* NETSNMP_FEATURE_REMOVE_U64COPY */ 00254 00261 void 00262 zeroU64(U64 * pu64) 00263 { 00264 pu64->low = 0; 00265 pu64->high = 0; 00266 } /* zeroU64 */ 00267 00268 00275 int 00276 isZeroU64(const U64 * pu64) 00277 { 00278 00279 if ((pu64->low == 0) && (pu64->high == 0)) 00280 return (TRUE); 00281 else 00282 return (FALSE); 00283 00284 } /* isZeroU64 */ 00285 00309 int 00310 netsnmp_c64_check_for_32bit_wrap(struct counter64 *old_val, 00311 struct counter64 *new_val, 00312 int adjust) 00313 { 00314 if( (NULL == old_val) || (NULL == new_val) ) 00315 return -1; 00316 00317 DEBUGMSGTL(("9:c64:check_wrap", "check wrap 0x%0lx.0x%0lx 0x%0lx.0x%0lx\n", 00318 old_val->high, old_val->low, new_val->high, new_val->low)); 00319 00320 /* 00321 * check for wraps 00322 */ 00323 if ((new_val->low >= old_val->low) && 00324 (new_val->high == old_val->high)) { 00325 DEBUGMSGTL(("9:c64:check_wrap", "no wrap\n")); 00326 return 0; 00327 } 00328 00329 /* 00330 * low wrapped. did high change? 00331 */ 00332 if (new_val->high == old_val->high) { 00333 DEBUGMSGTL(("c64:check_wrap", "32 bit wrap\n")); 00334 if (adjust) { 00335 ++new_val->high; 00336 #if SIZEOF_LONG != 4 00337 new_val->high &= 0xffffffff; 00338 #endif 00339 } 00340 return 32; 00341 } 00342 else if ((new_val->high == (old_val->high + 1)) || 00343 ((0 == new_val->high) && (0xffffffff == old_val->high))) { 00344 DEBUGMSGTL(("c64:check_wrap", "64 bit wrap\n")); 00345 return 64; 00346 } 00347 00348 return -2; 00349 } 00350 00386 int 00387 netsnmp_c64_check32_and_update(struct counter64 *prev_val, struct counter64 *new_val, 00388 struct counter64 *old_prev_val, int *need_wrap_check) 00389 { 00390 int rc; 00391 00392 /* 00393 * counters are 32bit or unknown (which we'll treat as 32bit). 00394 * update the prev values with the difference between the 00395 * new stats and the prev old_stats: 00396 * prev->stats += (new->stats - prev->old_stats) 00397 */ 00398 if ((NULL == need_wrap_check) || (0 != *need_wrap_check)) { 00399 rc = netsnmp_c64_check_for_32bit_wrap(old_prev_val,new_val, 1); 00400 if (rc < 0) { 00401 snmp_log(LOG_ERR,"c64 32 bit check failed\n"); 00402 return -1; 00403 } 00404 } 00405 else 00406 rc = 0; 00407 00408 /* 00409 * update previous values 00410 */ 00411 (void) u64UpdateCounter(prev_val, new_val, old_prev_val); 00412 00413 /* 00414 * if wrap check was 32 bit, undo adjust, now that prev is updated 00415 */ 00416 if (32 == rc) { 00417 /* 00418 * check wrap incremented high, so reset it. (Because having 00419 * high set for a 32 bit counter will confuse us in the next update). 00420 */ 00421 netsnmp_assert(1 == new_val->high); 00422 new_val->high = 0; 00423 } 00424 else if (64 == rc) { 00425 /* 00426 * if we really have 64 bit counters, the summing we've been 00427 * doing for prev values should be equal to the new values. 00428 */ 00429 if ((prev_val->low != new_val->low) || 00430 (prev_val->high != new_val->high)) { 00431 snmp_log(LOG_ERR, "looks like a 64bit wrap, but prev!=new\n"); 00432 return -2; 00433 } 00434 else if (NULL != need_wrap_check) 00435 *need_wrap_check = 0; 00436 } 00437 00438 return 0; 00439 } 00440 00441 void 00442 printU64(char *buf, /* char [I64CHARSZ+1]; */ 00443 const U64 * pu64) { 00444 U64 u64a; 00445 U64 u64b; 00446 00447 char aRes[I64CHARSZ + 1]; 00448 unsigned int u; 00449 int j; 00450 00451 u64a.high = pu64->high; 00452 u64a.low = pu64->low; 00453 aRes[I64CHARSZ] = 0; 00454 for (j = 0; j < I64CHARSZ; j++) { 00455 divBy10(u64a, &u64b, &u); 00456 aRes[(I64CHARSZ - 1) - j] = (char) ('0' + u); 00457 u64a.high = u64b.high; 00458 u64a.low = u64b.low; 00459 if (isZeroU64(&u64a)) 00460 break; 00461 } 00462 strcpy(buf, &aRes[(I64CHARSZ - 1) - j]); 00463 } 00464 00465 void 00466 printI64(char *buf, /* char [I64CHARSZ+1]; */ 00467 const U64 * pu64) { 00468 U64 u64a; 00469 U64 u64b; 00470 00471 char aRes[I64CHARSZ + 1]; 00472 unsigned int u; 00473 int j, sign = 0; 00474 00475 if (pu64->high & 0x80000000) { 00476 u64a.high = ~pu64->high; 00477 u64a.low = ~pu64->low; 00478 sign = 1; 00479 incrByU32(&u64a, 1); /* bit invert and incr by 1 to print 2s complement */ 00480 } else { 00481 u64a.high = pu64->high; 00482 u64a.low = pu64->low; 00483 } 00484 00485 aRes[I64CHARSZ] = 0; 00486 for (j = 0; j < I64CHARSZ; j++) { 00487 divBy10(u64a, &u64b, &u); 00488 aRes[(I64CHARSZ - 1) - j] = (char) ('0' + u); 00489 u64a.high = u64b.high; 00490 u64a.low = u64b.low; 00491 if (isZeroU64(&u64a)) 00492 break; 00493 } 00494 if (sign == 1) { 00495 aRes[(I64CHARSZ - 1) - j - 1] = '-'; 00496 strcpy(buf, &aRes[(I64CHARSZ - 1) - j - 1]); 00497 return; 00498 } 00499 strcpy(buf, &aRes[(I64CHARSZ - 1) - j]); 00500 } 00501 00502 int 00503 read64(U64 * i64, const char *str) 00504 { 00505 U64 i64p; 00506 unsigned int u; 00507 int sign = 0; 00508 int ok = 0; 00509 00510 zeroU64(i64); 00511 if (*str == '-') { 00512 sign = 1; 00513 str++; 00514 } 00515 00516 while (*str && isdigit((unsigned char)(*str))) { 00517 ok = 1; 00518 u = *str - '0'; 00519 multBy10(*i64, &i64p); 00520 memcpy(i64, &i64p, sizeof(i64p)); 00521 incrByU16(i64, u); 00522 str++; 00523 } 00524 if (sign) { 00525 i64->high = ~i64->high; 00526 i64->low = ~i64->low; 00527 incrByU16(i64, 1); 00528 } 00529 return ok; 00530 } 00531 00532 00533 00534 00535 #ifdef TESTING 00536 void 00537 main(int argc, char *argv[]) 00538 { 00539 int i; 00540 int j; 00541 int l; 00542 unsigned int u; 00543 U64 u64a; 00544 U64 u64b; 00545 #define MXSZ 20 00546 char aRes[MXSZ + 1]; 00547 00548 00549 if (argc < 2) { 00550 printf("This program takes numbers from the command line\n" 00551 "and prints them out.\n" "Usage: test <unsignedInt>...\n"); 00552 exit(1); 00553 } 00554 00555 aRes[MXSZ] = 0; 00556 00557 for (i = 1; i < argc; i++) { 00558 l = strlen(argv[i]); 00559 zeroU64(&u64a); 00560 for (j = 0; j < l; j++) { 00561 if (!isdigit(argv[i][j])) { 00562 printf("Argument is not a number \"%s\"\n", argv[i]); 00563 exit(1); 00564 } 00565 u = argv[i][j] - '0'; 00566 multBy10(u64a, &u64b); 00567 u64a = u64b; 00568 incrByU16(&u64a, u); 00569 } 00570 00571 printf("number \"%s\" in hex is '%08x%08x'h\n", 00572 argv[i], u64a.high, u64a.low); 00573 00574 printf("number is \"%s\"\n", printU64(&u64a)); 00575 for (j = 0; j < MXSZ; j++) { 00576 divBy10(u64a, &u64b, &u); 00577 aRes[(MXSZ - 1) - j] = (char) ('0' + u); 00578 u64a = u64b; 00579 if (isZeroU64(&u64a)) 00580 break; 00581 } 00582 00583 printf("number is \"%s\"\n", &aRes[(MXSZ - 1) - j]); 00584 } 00585 exit(0); 00586 } /* main */ 00587 #endif /* TESTING */ 00588 00589 /* 00590 * file: test.c 00591 */