components/net-snmp/patches/048.16824703.dyn_cpu.patch
author Mohana Rao Gorai <mohana.gorai@oracle.com>
Mon, 03 Nov 2014 17:53:34 -0800
branchs11u2-sru
changeset 3453 909f3e5e9eb6
permissions -rw-r--r--
16824703 net-snmp can't get "hrProcessorLoad" dynamically after change the No. of CPUs.

--- 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)
 {