--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/net-snmp/patches/048.16824703.dyn_cpu.patch Sun Nov 02 21:21:14 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)
+ {