# HG changeset patch # User Mohana Rao Gorai # Date 1415066014 28800 # Node ID 909f3e5e9eb62bd637de6288774b34192f2a5f66 # Parent 20a6b15f93548be857783ebe89c1cf57e4a1a67c 16824703 net-snmp can't get "hrProcessorLoad" dynamically after change the No. of CPUs. diff -r 20a6b15f9354 -r 909f3e5e9eb6 components/net-snmp/patches/048.16824703.dyn_cpu.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/net-snmp/patches/048.16824703.dyn_cpu.patch Mon Nov 03 17:53:34 2014 -0800 @@ -0,0 +1,284 @@ +--- a/include/net-snmp/agent/hardware/cpu.h 2014-06-09 04:44:56.766491669 -0700 ++++ b/include/net-snmp/agent/hardware/cpu.h 2014-06-09 04:45:47.845551969 -0700 +@@ -52,6 +52,11 @@ + netsnmp_cpu_info *next; + }; + ++ /* Auxilary structure used for updating the new cpu list */ ++struct cpu_idx { ++ int idx; ++ struct cpu_idx *next; ++}; + + /* + * Possibly not all needed ?? +@@ -60,6 +65,7 @@ + netsnmp_cpu_info *netsnmp_cpu_get_next( netsnmp_cpu_info* ); + netsnmp_cpu_info *netsnmp_cpu_get_byIdx( int, int ); + netsnmp_cpu_info *netsnmp_cpu_get_byName( char*, int ); ++int netsnmp_update_cpu_list( struct cpu_idx * ); /* returns the number of deleted cpus */ + + netsnmp_cache *netsnmp_cpu_get_cache( void ); + int netsnmp_cpu_load( void ); +--- a/agent/mibgroup/hardware/cpu/cpu.c 2014-06-09 04:44:56.766855758 -0700 ++++ b/agent/mibgroup/hardware/cpu/cpu.c 2014-06-19 05:07:54.648759853 -0700 +@@ -244,3 +244,59 @@ + cpu2->pageIn = cpu->pageIn; + cpu2->pageOut = cpu->pageOut; + } ++ ++ /* ++ * Updates the cpu list, keeping the cpus whose indices are passed ++ * assumes the passed linked list of indices is sorted in ascending order ++ * returns the number of deleted cpus ++ */ ++int netsnmp_update_cpu_list( struct cpu_idx *new_cpu_list ) ++{ ++ netsnmp_cpu_info *prev, *current, *temp1, *temp2; ++ int n=0; ++ netsnmp_cpu_info *cpu; ++ ++ for( prev=current=_cpu_head; current && new_cpu_list ; ++ current=current->next, new_cpu_list=new_cpu_list->next ) { ++ if ( current->idx == new_cpu_list->idx ) { ++ prev=current; ++ } else { ++ current=current->next; ++ while ( current && (current->idx != new_cpu_list->idx) ) ++ current = current->next; ++ if ( !current ) { ++ /*This shouldn't happen. Something went really wrong */ ++ return -1; ++ } ++ ++ temp1 = prev->next; ++ prev->next = current; ++ prev = current; ++ /* remove the unassigned cpus */ ++ while ( temp1 != current ) { ++ temp2 = temp1; ++ temp1 = temp1->next; ++ n++; ++ SNMP_FREE(temp2->history); ++ SNMP_FREE(temp2); ++ } ++ } ++ } /*end of for */ ++ ++ if ( !current && new_cpu_list ) { ++ /* This shouldn't happen. */ ++ return -1; ++ } ++ ++ /* Delete the unassigned trailing cpus from the list */ ++ while ( current ) { ++ temp2 = current; ++ current = current->next; ++ n++; ++ SNMP_FREE(temp2->history); ++ SNMP_FREE(temp2); ++ } ++ prev->next = NULL; ++ return n; ++} ++ +--- a/agent/mibgroup/hardware/cpu/cpu_kstat.c 2014-06-09 04:44:56.766680662 -0700 ++++ b/agent/mibgroup/hardware/cpu/cpu_kstat.c 2014-06-19 04:53:47.176189429 -0700 +@@ -17,16 +17,16 @@ + extern kstat_ctl_t *kstat_fd; + extern int cpu_num; + int _cpu_status(char *state); ++static void add_new_kstat_cpu_entry(kstat_t *ksp); ++static struct cpu_idx * add_cpu_idx(struct cpu_idx * head, int idx); + + /* + * Initialise the list of CPUs on the system + * (including descriptions) + */ + void init_cpu_kstat( void ) { +- int i, n=0, clock, state_begin; +- char ctype[15], ftype[15], state[10]; ++ int n=0; + kstat_t *ksp; +- kstat_named_t *ks_data; + netsnmp_cpu_info *cpu = netsnmp_cpu_get_byIdx( -1, 1 ); + strcpy(cpu->name, "Overall CPU statistics"); + +@@ -41,36 +41,50 @@ + if ((strcmp(ksp->ks_module, "cpu_info") == 0) && + (strcmp(ksp->ks_class, "misc" ) == 0)) { + kstat_read(kstat_fd, ksp, NULL ); ++ add_new_kstat_cpu_entry(ksp); + n++; +- clock = 999999; +- memset(ctype, 0, sizeof(ctype)); +- memset(ftype, 0, sizeof(ftype)); +- memset(state, 0, sizeof(state)); +- for (i=0, ks_data = ksp->ks_data; i < ksp->ks_ndata; i++, ks_data++) { +- if ( strcmp( ks_data->name, "state" ) == 0 ) { +- strncpy( state, ks_data->value.c, sizeof(state)); +- state[sizeof(state)-1] = '\0'; +- } else if ( strcmp( ks_data->name, "state_begin" ) == 0 ) { +- state_begin = ks_data->value.i32; +- } else if ( strcmp( ks_data->name, "cpu_type" ) == 0 ) { +- strncpy( ctype, ks_data->value.c, sizeof(ctype)); +- state[sizeof(ctype)-1] = '\0'; +- } else if ( strcmp( ks_data->name, "fpu_type" ) == 0 ) { +- strncpy( ftype, ks_data->value.c, sizeof(ftype)); +- state[sizeof(ftype)-1] = '\0'; +- } else if ( strcmp( ks_data->name, "clock_MHz" ) == 0 ) { +- clock = ks_data->value.i32; +- } +- } +- i = ksp->ks_instance; +- cpu = netsnmp_cpu_get_byIdx( i, 1 ); +- sprintf( cpu->name, "cpu%d", i ); +- sprintf( cpu->descr, "CPU %d Sun %d MHz %s with %s FPU %s", +- i, clock, ctype, ftype, state ); +- cpu->status = _cpu_status(state); /* XXX - or in 'n_c_a_load' ? */ + } + } +- cpu_num = i; ++ cpu_num = n; ++} ++ ++ ++ /* ++ * adds the new cpu entry to the exisitng list ++ */ ++static void ++add_new_kstat_cpu_entry( kstat_t *ksp ) { ++ int i, clock, state_begin; ++ char ctype[15], ftype[15], state[10]; ++ kstat_named_t *ks_data; ++ netsnmp_cpu_info *cpu; ++ ++ clock = 999999; ++ memset(ctype, 0, sizeof(ctype)); ++ memset(ftype, 0, sizeof(ftype)); ++ memset(state, 0, sizeof(state)); ++ ++ for (i=0, ks_data = ksp->ks_data; i < ksp->ks_ndata; i++, ks_data++) { ++ if ( strcmp( ks_data->name, "state" ) == 0 ) { ++ strncpy( state, ks_data->value.c, sizeof(state)); ++ state[sizeof(state)-1] = '\0'; ++ } else if ( strcmp( ks_data->name, "state_begin" ) == 0 ) { ++ state_begin = ks_data->value.i32; ++ } else if ( strcmp( ks_data->name, "cpu_type" ) == 0 ) { ++ strncpy( ctype, ks_data->value.c, sizeof(ctype)); ++ ctype[sizeof(ctype)-1] = '\0'; ++ } else if ( strcmp( ks_data->name, "fpu_type" ) == 0 ) { ++ strncpy( ftype, ks_data->value.c, sizeof(ftype)); ++ ftype[sizeof(ftype)-1] = '\0'; ++ } else if ( strcmp( ks_data->name, "clock_MHz" ) == 0 ) { ++ clock = ks_data->value.i32; ++ } ++ } ++ i = ksp->ks_instance; ++ cpu = netsnmp_cpu_get_byIdx( i, 1 ); ++ sprintf( cpu->name, "cpu%d", i ); ++ sprintf( cpu->descr, "CPU %d Sun %d MHz %s with %s FPU %s", i, clock, ctype, ftype, state ); ++ cpu->status = _cpu_status(state); + } + + +@@ -78,11 +92,12 @@ + * Load the latest CPU usage statistics + */ + int netsnmp_cpu_arch_load( netsnmp_cache *cache, void *magic ) { +- int i=1; ++ int i=1, n=0; + kstat_t *ksp; + cpu_stat_t cs; + netsnmp_cpu_info *cpu = netsnmp_cpu_get_byIdx( -1, 0 ); + netsnmp_cpu_info *cpu2; ++ struct cpu_idx *new_cpu_list = NULL, *temp_cpu_idx; + + /* Clear overall stats, ready for summing individual CPUs */ + cpu->user_ticks = 0; +@@ -97,6 +112,32 @@ + + kstat_chain_update( kstat_fd ); + DEBUGMSGTL(("cpu", "cpu_kstat load\n ")); ++ ++ /* ++ * The stats update is three step. ++ * First - add in the new cpus' info to the linked list ++ */ ++ for (ksp = kstat_fd->kc_chain; ksp != NULL; ksp = ksp->ks_next) { ++ if (ksp->ks_flags & KSTAT_FLAG_INVALID) ++ continue; ++ if ((strcmp(ksp->ks_module, "cpu_info") == 0) && ++ (strcmp(ksp->ks_class, "misc" ) == 0)) { ++ kstat_read(kstat_fd, ksp, NULL ); ++ i = ksp->ks_instance; ++ new_cpu_list = add_cpu_idx( new_cpu_list, i); ++ cpu2 = netsnmp_cpu_get_byIdx( i, 0 ); ++ if ( !cpu2 ) { ++ add_new_kstat_cpu_entry(ksp); ++ n++; ++ } ++ } ++ } ++ ++ ++ /* Second - update the CPU list to reflect new kernel structures */ ++ n -= netsnmp_update_cpu_list( new_cpu_list ); ++ ++ /* Third - for updating stats for the new CPU set */ + for (ksp = kstat_fd->kc_chain; ksp != NULL; ksp = ksp->ks_next) { + if (ksp->ks_flags & KSTAT_FLAG_INVALID) + continue; +@@ -104,7 +145,7 @@ + i = ksp->ks_instance; + cpu2 = netsnmp_cpu_get_byIdx( i, 0 ); + if ( !cpu2 ) +- break; /* or continue ?*/ /*Skip new CPUs */ ++ continue; /* This shouldn't happen. Inconsistency in kstat CPU data */ + if ((ksp->ks_type != KSTAT_TYPE_RAW) || + (ksp->ks_data_size != sizeof(cs))|| + (kstat_read(kstat_fd, ksp, &cs) == -1)) { +@@ -138,9 +179,43 @@ + cpu->nCtxSwitches += (unsigned long)cs.cpu_sysinfo.pswitch; + } + } ++ cpu_num += n; ++ /* Clean up the temporary CPU index list */ ++ while(new_cpu_list) { ++ temp_cpu_idx = new_cpu_list; ++ new_cpu_list = new_cpu_list->next; ++ SNMP_FREE(temp_cpu_idx); ++ } + return 0; + } + ++ /* returns the new head */ ++static struct cpu_idx * ++add_cpu_idx(struct cpu_idx * head, int idx) ++{ ++ struct cpu_idx *cpu_idx, *current; ++ cpu_idx = SNMP_MALLOC_TYPEDEF( struct cpu_idx ); ++ if ( !cpu_idx ) { ++ DEBUGMSG(("cpu", "(cpu_idx creation failed)\n")); ++ return head; ++ } ++ ++ cpu_idx->idx = idx; ++ if ( !head || head->idx > idx ) { ++ cpu_idx->next = head; ++ return cpu_idx; ++ } ++ ++ for ( current=head; current; current=current->next ) { ++ if ( !current->next || current->next->idx > idx ) { ++ cpu_idx->next = current->next; ++ current->next = cpu_idx; ++ return head; ++ } ++ } ++ ++} ++ + int + _cpu_status( char *state) + {