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