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 00304 int 00305 netsnmp_c64_check_for_32bit_wrap(struct counter64 *old_val, 00306 struct counter64 *new_val, 00307 int adjust) 00308 { 00309 if( (NULL == old_val) || (NULL == new_val) ) 00310 return -1; 00311 00312 DEBUGMSGTL(("9:c64:check_wrap", "check wrap 0x%0x.0x%0x 0x%0x.0x%0x\n", 00313 old_val->high, old_val->low, new_val->high, new_val->low)); 00314 00315 /* 00316 * check for wraps 00317 */ 00318 if ((new_val->low >= old_val->low) && 00319 (new_val->high == old_val->high)) { 00320 DEBUGMSGTL(("9:c64:check_wrap", "no wrap\n")); 00321 return 0; 00322 } 00323 00324 /* 00325 * low wrapped. did high change? 00326 */ 00327 if (new_val->high == old_val->high) { 00328 DEBUGMSGTL(("c64:check_wrap", "32 bit wrap\n")); 00329 if (adjust) { 00330 ++new_val->high; 00331 #if SIZEOF_LONG != 4 00332 new_val->high &= 0xffffffff; 00333 #endif 00334 } 00335 return 32; 00336 } 00337 else if ((new_val->high == (old_val->high + 1)) || 00338 ((0 == new_val->high) && (0xffffffff == old_val->high))) { 00339 DEBUGMSGTL(("c64:check_wrap", "64 bit wrap\n")); 00340 return 64; 00341 } 00342 00343 return -2; 00344 } 00345 00381 int 00382 netsnmp_c64_check32_and_update(struct counter64 *prev_val, struct counter64 *new_val, 00383 struct counter64 *old_prev_val, int *need_wrap_check) 00384 { 00385 int rc; 00386 00387 /* 00388 * counters are 32bit or unknown (which we'll treat as 32bit). 00389 * update the prev values with the difference between the 00390 * new stats and the prev old_stats: 00391 * prev->stats += (new->stats - prev->old_stats) 00392 */ 00393 if ((NULL == need_wrap_check) || (0 != *need_wrap_check)) { 00394 rc = netsnmp_c64_check_for_32bit_wrap(old_prev_val,new_val, 1); 00395 if (rc < 0) { 00396 snmp_log(LOG_ERR,"c64 32 bit check failed\n"); 00397 return -1; 00398 } 00399 } 00400 else 00401 rc = 0; 00402 00403 /* 00404 * update previous values 00405 */ 00406 (void) u64UpdateCounter(prev_val, new_val, old_prev_val); 00407 00408 /* 00409 * if wrap check was 32 bit, undo adjust, now that prev is updated 00410 */ 00411 if (32 == rc) { 00412 /* 00413 * check wrap incremented high, so reset it. (Because having 00414 * high set for a 32 bit counter will confuse us in the next update). 00415 */ 00416 netsnmp_assert(1 == new_val->high); 00417 new_val->high = 0; 00418 } 00419 else if (64 == rc) { 00420 /* 00421 * if we really have 64 bit counters, the summing we've been 00422 * doing for prev values should be equal to the new values. 00423 */ 00424 if ((prev_val->low != new_val->low) || 00425 (prev_val->high != new_val->high)) { 00426 snmp_log(LOG_ERR, "looks like a 64bit wrap, but prev!=new\n"); 00427 return -2; 00428 } 00429 else if (NULL != need_wrap_check) 00430 *need_wrap_check = 0; 00431 } 00432 00433 return 0; 00434 } 00435 00436 void 00437 printU64(char *buf, /* char [I64CHARSZ+1]; */ 00438 const U64 * pu64) { 00439 U64 u64a; 00440 U64 u64b; 00441 00442 char aRes[I64CHARSZ + 1]; 00443 unsigned int u; 00444 int j; 00445 00446 u64a.high = pu64->high; 00447 u64a.low = pu64->low; 00448 aRes[I64CHARSZ] = 0; 00449 for (j = 0; j < I64CHARSZ; j++) { 00450 divBy10(u64a, &u64b, &u); 00451 aRes[(I64CHARSZ - 1) - j] = (char) ('0' + u); 00452 u64a.high = u64b.high; 00453 u64a.low = u64b.low; 00454 if (isZeroU64(&u64a)) 00455 break; 00456 } 00457 strcpy(buf, &aRes[(I64CHARSZ - 1) - j]); 00458 } 00459 00460 void 00461 printI64(char *buf, /* char [I64CHARSZ+1]; */ 00462 const U64 * pu64) { 00463 U64 u64a; 00464 U64 u64b; 00465 00466 char aRes[I64CHARSZ + 1]; 00467 unsigned int u; 00468 int j, sign = 0; 00469 00470 if (pu64->high & 0x80000000) { 00471 u64a.high = ~pu64->high; 00472 u64a.low = ~pu64->low; 00473 sign = 1; 00474 incrByU32(&u64a, 1); /* bit invert and incr by 1 to print 2s complement */ 00475 } else { 00476 u64a.high = pu64->high; 00477 u64a.low = pu64->low; 00478 } 00479 00480 aRes[I64CHARSZ] = 0; 00481 for (j = 0; j < I64CHARSZ; j++) { 00482 divBy10(u64a, &u64b, &u); 00483 aRes[(I64CHARSZ - 1) - j] = (char) ('0' + u); 00484 u64a.high = u64b.high; 00485 u64a.low = u64b.low; 00486 if (isZeroU64(&u64a)) 00487 break; 00488 } 00489 if (sign == 1) { 00490 aRes[(I64CHARSZ - 1) - j - 1] = '-'; 00491 strcpy(buf, &aRes[(I64CHARSZ - 1) - j - 1]); 00492 return; 00493 } 00494 strcpy(buf, &aRes[(I64CHARSZ - 1) - j]); 00495 } 00496 00497 int 00498 read64(U64 * i64, const char *str) 00499 { 00500 U64 i64p; 00501 unsigned int u; 00502 int sign = 0; 00503 int ok = 0; 00504 00505 zeroU64(i64); 00506 if (*str == '-') { 00507 sign = 1; 00508 str++; 00509 } 00510 00511 while (*str && isdigit(*str)) { 00512 ok = 1; 00513 u = *str - '0'; 00514 multBy10(*i64, &i64p); 00515 memcpy(i64, &i64p, sizeof(i64p)); 00516 incrByU16(i64, u); 00517 str++; 00518 } 00519 if (sign) { 00520 i64->high = ~i64->high; 00521 i64->low = ~i64->low; 00522 incrByU16(i64, 1); 00523 } 00524 return ok; 00525 } 00526 00527 00528 00529 00530 #ifdef TESTING 00531 void 00532 main(int argc, char *argv[]) 00533 { 00534 int i; 00535 int j; 00536 int l; 00537 unsigned int u; 00538 U64 u64a; 00539 U64 u64b; 00540 #define MXSZ 20 00541 char aRes[MXSZ + 1]; 00542 00543 00544 if (argc < 2) { 00545 printf("This program takes numbers from the command line\n" 00546 "and prints them out.\n" "Usage: test <unsignedInt>...\n"); 00547 exit(1); 00548 } 00549 00550 aRes[MXSZ] = 0; 00551 00552 for (i = 1; i < argc; i++) { 00553 l = strlen(argv[i]); 00554 zeroU64(&u64a); 00555 for (j = 0; j < l; j++) { 00556 if (!isdigit(argv[i][j])) { 00557 printf("Argument is not a number \"%s\"\n", argv[i]); 00558 exit(1); 00559 } 00560 u = argv[i][j] - '0'; 00561 multBy10(u64a, &u64b); 00562 u64a = u64b; 00563 incrByU16(&u64a, u); 00564 } 00565 00566 printf("number \"%s\" in hex is '%08x%08x'h\n", 00567 argv[i], u64a.high, u64a.low); 00568 00569 printf("number is \"%s\"\n", printU64(&u64a)); 00570 for (j = 0; j < MXSZ; j++) { 00571 divBy10(u64a, &u64b, &u); 00572 aRes[(MXSZ - 1) - j] = (char) ('0' + u); 00573 u64a = u64b; 00574 if (isZeroU64(&u64a)) 00575 break; 00576 } 00577 00578 printf("number is \"%s\"\n", &aRes[(MXSZ - 1) - j]); 00579 } 00580 exit(0); 00581 } /* main */ 00582 #endif /* TESTING */ 00583 00584 /* 00585 * file: test.c 00586 */
1.3.9.1
Last modified: Thursday, 01-Mar-2007 16:20:09 PST
For questions regarding web content and site functionality, please write to the net-snmp-users mail list.