hr_proc.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:14k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. /*
  2.  *  Host Resources MIB - proc processor group implementation - hr_proc.c
  3.  *
  4.  */
  5. #include <net-snmp/net-snmp-config.h>
  6. #if HAVE_STDLIB_H
  7. #include <stdlib.h>
  8. #endif
  9. #if HAVE_STRING_H
  10. #include <string.h>
  11. #else
  12. #include <strings.h>
  13. #endif
  14. #include <ctype.h>
  15. #include "host_res.h"
  16. #include "hr_proc.h"
  17. #include <net-snmp/agent/auto_nlist.h>
  18. #include <net-snmp/agent/agent_read_config.h>
  19. #include "ucd-snmp/loadave.h"
  20. #define HRPROC_MONOTONICALLY_INCREASING
  21.         /*********************
  22.  *
  23.  *  Kernel & interface information,
  24.  *   and internal forward declarations
  25.  *
  26.  *********************/
  27. extern void     Init_HR_Proc(void);
  28. extern int      Get_Next_HR_Proc(void);
  29. const char     *describe_proc(int);
  30. int             header_hrproc(struct variable *, oid *, size_t *, int,
  31.                               size_t *, WriteMethod **);
  32. #ifdef linux
  33. void detect_hrproc(void);
  34. #endif
  35. #ifdef solaris2
  36. #define MAX_NUM_HRPROC  128       /* will handle up to 128 processors */
  37. #include <kstat.h>
  38. #include <kernel_sunos5.h>
  39. hrtime_t  update_time = NULL;
  40. static int ncpus = 0;             /* derived from kstat system_misc ncpus*/
  41. struct cpuinfo {
  42.             int id;
  43.             char state[10];
  44.             int state_begin;
  45.             char cpu_type[15];
  46.             char fpu_type[15];
  47.             int clock_MHz;
  48.             };                    /* derived from kstat cpu_info*/
  49. static struct cpuinfo cpu[MAX_NUM_HRPROC];
  50. static char proc_description[96]; /* buffer to hold description of current cpu*/
  51. extern void kstat_CPU(void);
  52. int proc_status(int);
  53. #else
  54. #define MAX_NUM_HRPROC  32
  55. char proc_descriptions[MAX_NUM_HRPROC][BUFSIZ];
  56. #endif  /*solaris 2*/
  57.         /*********************
  58.  *
  59.  *  Initialisation & common implementation functions
  60.  *
  61.  *********************/
  62. static int      HRP_index;
  63. static int      HRP_max_index = 1;
  64. #define HRPROC_ID 1
  65. #define HRPROC_LOAD 2
  66. struct variable4 hrproc_variables[] = {
  67.     {HRPROC_ID, ASN_OBJECT_ID, RONLY, var_hrproc, 2, {1, 1}},
  68.     {HRPROC_LOAD, ASN_INTEGER, RONLY, var_hrproc, 2, {1, 2}}
  69. };
  70. oid             hrproc_variables_oid[] = { 1, 3, 6, 1, 2, 1, 25, 3, 3 };
  71. void
  72. init_hr_proc(void)
  73. {
  74.     init_device[HRDEV_PROC] = Init_HR_Proc;
  75.     next_device[HRDEV_PROC] = Get_Next_HR_Proc;
  76.     device_descr[HRDEV_PROC] = describe_proc;
  77. #ifdef solaris2
  78.     device_status[HRDEV_PROC] = proc_status;
  79.     update_time = NULL;
  80. #endif
  81. #ifdef HRPROC_MONOTONICALLY_INCREASING
  82.     dev_idx_inc[HRDEV_PROC] = 1;
  83. #endif
  84. #ifdef linux
  85.     detect_hrproc();
  86. #endif
  87.     REGISTER_MIB("host/hr_proc", hrproc_variables, variable4,
  88.                  hrproc_variables_oid);
  89. }
  90. /*
  91.  * header_hrproc(...
  92.  * Arguments:
  93.  * vp     IN      - pointer to variable entry that points here
  94.  * name    IN/OUT  - IN/name requested, OUT/name found
  95.  * length  IN/OUT  - length of IN/OUT oid's 
  96.  * exact   IN      - TRUE if an exact match was requested
  97.  * var_len OUT     - length of variable or 0 if function returned
  98.  * write_method
  99.  * 
  100.  */
  101. int
  102. header_hrproc(struct variable *vp,
  103.               oid * name,
  104.               size_t * length,
  105.               int exact, size_t * var_len, WriteMethod ** write_method)
  106. {
  107. #define HRPROC_ENTRY_NAME_LENGTH 11
  108.     oid             newname[MAX_OID_LEN];
  109.     int             proc_idx, LowIndex = -1;
  110.     int             result;
  111.     DEBUGMSGTL(("host/hr_proc", "var_hrproc: "));
  112.     DEBUGMSGOID(("host/hr_proc", name, *length));
  113.     DEBUGMSG(("host/hr_proc", " %dn", exact));
  114.     memcpy((char *) newname, (char *) vp->name, vp->namelen * sizeof(oid));
  115.     /*
  116.      * Find "next" proc entry 
  117.      */
  118.     Init_HR_Proc();
  119.     for (;;) {
  120.         proc_idx = Get_Next_HR_Proc();
  121.         if (proc_idx == -1)
  122.             break;
  123.         newname[HRPROC_ENTRY_NAME_LENGTH] = proc_idx;
  124.         result = snmp_oid_compare(name, *length, newname, vp->namelen + 1);
  125.         if (exact && (result == 0)) {
  126.             LowIndex = proc_idx;
  127.             /*
  128.              * Save processor status information 
  129.              */
  130.             break;
  131.         }
  132.         if ((!exact && (result < 0)) &&
  133.             (LowIndex == -1 || proc_idx < LowIndex)) {
  134.             LowIndex = proc_idx;
  135.             /*
  136.              * Save processor status information 
  137.              */
  138. #ifdef HRPROC_MONOTONICALLY_INCREASING
  139.             break;
  140. #endif
  141.         }
  142.     }
  143.     if (LowIndex == -1) {
  144.         DEBUGMSGTL(("host/hr_proc", "... index out of rangen"));
  145.         return (MATCH_FAILED);
  146.     }
  147.     memcpy((char *) name, (char *) newname,
  148.            (vp->namelen + 1) * sizeof(oid));
  149.     *length = vp->namelen + 1;
  150.     *write_method = 0;
  151.     *var_len = sizeof(long);    /* default to 'long' results */
  152.     DEBUGMSGTL(("host/hr_proc", "... get proc stats "));
  153.     DEBUGMSGOID(("host/hr_proc", name, *length));
  154.     DEBUGMSG(("host/hr_proc", "n"));
  155.     return LowIndex;
  156. }
  157.         /*********************
  158.  *
  159.  *  System specific implementation functions
  160.  *
  161.  *********************/
  162. u_char         *
  163. var_hrproc(struct variable * vp,
  164.            oid * name,
  165.            size_t * length,
  166.            int exact, size_t * var_len, WriteMethod ** write_method)
  167. {
  168.     int             proc_idx;
  169.     double          avenrun[3];
  170.     proc_idx =
  171.         header_hrproc(vp, name, length, exact, var_len, write_method);
  172.     if (proc_idx == MATCH_FAILED)
  173.         return NULL;
  174.     if (try_getloadavg(&avenrun[0], sizeof(avenrun) / sizeof(avenrun[0]))
  175.         == -1)
  176.         return NULL;
  177.     switch (vp->magic) {
  178.     case HRPROC_ID:
  179.         *var_len = nullOidLen;
  180.         return (u_char *) nullOid;
  181.     case HRPROC_LOAD:
  182. #if NO_DUMMY_VALUES
  183.         return NULL;
  184. #endif
  185.         long_return = avenrun[0] * 100; /* 1 minute average */
  186.         if (long_return > 100)
  187.             long_return = 100;
  188.         return (u_char *) & long_return;
  189.     default:
  190.         DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_hrprocn",
  191.                     vp->magic));
  192.     }
  193.     return NULL;
  194. }
  195.         /*********************
  196.  *
  197.  *  Internal implementation functions
  198.  *
  199.  *********************/
  200. void
  201. Init_HR_Proc(void)
  202. {
  203. #ifdef solaris2
  204.     hrtime_t  current_time;
  205. #endif
  206.     HRP_index = 0;
  207. #ifdef solaris2
  208.     current_time = gethrtime();
  209.     if (current_time > update_time + 2000000000) { /* two seconds */
  210.         kstat_CPU();
  211.         update_time = gethrtime();
  212.     }
  213. #endif
  214. }
  215. int
  216. Get_Next_HR_Proc(void)
  217. {
  218.     if (HRP_index < HRP_max_index)
  219.         return (HRDEV_PROC << HRDEV_TYPE_SHIFT) + HRP_index++;
  220.     else
  221.         return -1;
  222. }
  223. const char     *
  224. describe_proc(int idx)
  225. {
  226. #ifdef _SC_CPU_VERSION
  227.     int             result;
  228.     result = sysconf(_SC_CPU_VERSION);
  229.     switch (result) {
  230.     case CPU_HP_MC68020:
  231.         return (" Motorola MC68020 ");
  232.     case CPU_HP_MC68030:
  233.         return (" Motorola MC68030 ");
  234.     case CPU_HP_MC68040:
  235.         return (" Motorola MC68040 ");
  236.     case CPU_PA_RISC1_0:
  237.         return (" HP PA-RISC 1.0 ");
  238.     case CPU_PA_RISC1_1:
  239.         return (" HP PA-RISC 1.1 ");
  240.     case CPU_PA_RISC1_2:
  241.         return (" HP PA-RISC 1.2 ");
  242.     case CPU_PA_RISC2_0:
  243.         return (" HP PA-RISC 2.0 ");
  244.     default:
  245.         return ("An electronic chip with an HP label");
  246.     }
  247. #elif linux
  248.     return (proc_descriptions[idx & HRDEV_TYPE_MASK]);
  249. #elif solaris2
  250.     int cidx = idx & HRDEV_TYPE_MASK;
  251.     snprintf(proc_description,sizeof(proc_description)-1, 
  252.            "CPU %d Sun %d MHz %s with %s FPU %s",
  253.             cpu[cidx].id,cpu[cidx].clock_MHz,cpu[cidx].cpu_type,cpu[cidx].fpu_type,cpu[cidx].state);
  254.     return proc_description;
  255. #else
  256.     return ("An electronic chip that makes the computer work.");
  257. #endif
  258. }
  259. #ifdef linux
  260. void detect_hrproc(void)
  261. {
  262.     int i;
  263.     char tmpbuf[BUFSIZ], *cp;
  264.     FILE *fp;
  265.     /*
  266.      * Clear the buffers...
  267.      */
  268.     for ( i=0 ; i<MAX_NUM_HRPROC; i++ ) {
  269.         memset( proc_descriptions[i], '', BUFSIZ);
  270.     }
  271.     /*
  272.      * ... and try to interpret the CPU information
  273.      */
  274.     fp = fopen("/proc/cpuinfo", "r");
  275.     if (!fp) {
  276.         sprintf( proc_descriptions[0],
  277.                  "An electronic chip that makes the computer work.");
  278.         return;
  279.     }
  280.     i = 0;
  281.     while (fgets(tmpbuf, BUFSIZ, fp)) {
  282.         if ( !strncmp( tmpbuf, "vendor_id", 9)) {
  283.     /* Stomp on trailing newline... */
  284.             cp = &tmpbuf[strlen(tmpbuf)-1];
  285.     *cp = 0;
  286.     /* ... and then extract the value */
  287.             cp = index( tmpbuf, ':');
  288.     cp++;
  289.     while ( cp && isspace(*cp))
  290.         cp++;
  291.             snprintf( proc_descriptions[i], BUFSIZ, "%s", cp);
  292.         }
  293.         if ( !strncmp( tmpbuf, "model name", 10)) {
  294.     /* Stomp on trailing newline... */
  295.             cp = &tmpbuf[strlen(tmpbuf)-1];
  296.     *cp = 0;
  297.     /* ... and then extract the value */
  298.             cp = index( tmpbuf, ':');
  299.     cp++;
  300.     while ( cp && isspace(*cp))
  301.         cp++;
  302.             strncat( proc_descriptions[i], ": ",
  303.                      BUFSIZ-strlen(proc_descriptions[i]));
  304.             strncat( proc_descriptions[i], cp,
  305.                      BUFSIZ-strlen(proc_descriptions[i]));
  306.             i++;
  307.             if (i >= MAX_NUM_HRPROC) {
  308.                 i--;
  309.                 break;
  310.             }
  311.         }
  312.     }
  313.     HRP_max_index = i;
  314.     fclose(fp);
  315.     return;
  316. }
  317. #endif /* linux */
  318. #ifdef solaris2
  319. void kstat_CPU(void)
  320. {
  321. /* this routine asks the OS for the number of CPU's and uses that value
  322.  * to set HRP_max_index for later use.  Then it asks the OS for
  323.  * specific details of each CPU.  In Solaris, you cannot trust the 
  324.  * first CPU to be 0 or for CPU 0 to even exist, hence there is a 
  325.  * CPU id, state, cpu type, fpu type, state_begin (what does this do??)
  326.  * and CPU speed.  Results are stuffed into the cpu array (see above).
  327.  *
  328.  * In keeping with the spirit of the RFC, the number and index of CPU's
  329.  * is considered to be constant.  Hence, if you start yanking or adding
  330.  * CPU modules eg. on a V880, you will need to start and stop the daemon.
  331.  */
  332.     int i_cpu = -1;
  333.     int i,old_ncpus;
  334.     kstat_ctl_t *kc;
  335.     kstat_t *ksp;
  336.     kstat_named_t *ks_data;
  337.     old_ncpus = ncpus;
  338.     for (i = 0; i < ncpus; i++) {
  339.         strncpy(cpu[i].state,"missing",sizeof(cpu[i].state));
  340.         cpu[i].state[sizeof(cpu[i].state)-1]=''; /* null terminate */
  341.         cpu[i].id = 999999;
  342.         cpu[i].clock_MHz = 999999;
  343.         strncpy(cpu[i].cpu_type,"missing",sizeof(cpu[i].cpu_type));
  344.         cpu[i].state[sizeof(cpu[i].cpu_type)-1]=''; /* null terminate */
  345.         strncpy(cpu[i].fpu_type,"missing",sizeof(cpu[i].fpu_type));
  346.         cpu[i].state[sizeof(cpu[i].cpu_type)-1]=''; /* null terminate */
  347.         }
  348.     getKstat("system_misc", "ncpus", &ncpus);
  349.     if (ncpus > old_ncpus){
  350.         HRP_max_index = ncpus; /* the MIB says to retain indexes */
  351.         }
  352.     if ((old_ncpus != ncpus)&&(old_ncpus != 0)) {
  353.         if (ncpus > old_ncpus){
  354.             snmp_log(LOG_NOTICE,
  355.               "hr_proc: Cool ! Number of CPUs increased, must be hot-pluggable.n");
  356.             }
  357.         else {
  358.             snmp_log(LOG_NOTICE,
  359.                      "hr_proc: Lost at least one CPU, RIP.n");
  360.             }
  361.        }
  362.     if ((kc = kstat_open()) == NULL) {
  363.         DEBUGMSGTL(("hr_proc", "kstat_open failed"));
  364.         }
  365.     else {
  366.         for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next)  {
  367.             if (ksp->ks_type == KSTAT_TYPE_NAMED
  368.                &&  strcmp(ksp->ks_module, "cpu_info") == 0
  369.                &&  strcmp(ksp->ks_class, "misc") == 0) {
  370.                    if (kstat_read(kc, ksp, NULL) == -1)  {
  371.                       DEBUGMSGTL(("hr_proc", "kstat_read failed"));
  372.                       }
  373.                    else {
  374.                        i_cpu++;
  375.                        i = 0;
  376.                        cpu[i_cpu].id = ksp->ks_instance;
  377.                        for (ks_data = ksp->ks_data; i < ksp->ks_ndata; i++, ks_data++) {
  378.                            if (strcmp(ks_data->name,"state")==0) {
  379.                                strncpy(cpu[i_cpu].state,ks_data->value.c,sizeof(cpu[i_cpu].state));
  380.                                cpu[i_cpu].state[sizeof(cpu[i_cpu].state)-1]=''; /* null terminate */
  381.                                continue;
  382.                                }
  383.                            else if (strcmp(ks_data->name,"state_begin")==0)   {
  384.                                cpu[i_cpu].state_begin=ks_data->value.i32;
  385.                                continue;
  386.                                }
  387.                            else if (strcmp(ks_data->name,"cpu_type")==0)   {
  388.                                strncpy(cpu[i_cpu].cpu_type,ks_data->value.c,sizeof(cpu[i_cpu].cpu_type));
  389.                                cpu[i_cpu].state[sizeof(cpu[i_cpu].cpu_type)-1]=''; /* null terminate */
  390.                                continue;
  391.                                }
  392.                            else if (strcmp(ks_data->name,"fpu_type")==0)   {
  393.                                strncpy(cpu[i_cpu].fpu_type,ks_data->value.c,sizeof(cpu[i_cpu].fpu_type));
  394.                                cpu[i_cpu].state[sizeof(cpu[i_cpu].fpu_type)-1]=''; /* null terminate */
  395.                                continue;
  396.                                }
  397.                            else if (strcmp(ks_data->name,"clock_MHz")==0)   {
  398.                                cpu[i_cpu].clock_MHz=ks_data->value.i32;
  399.                                continue;
  400.                                }
  401.                            else    {
  402.                                    DEBUGMSGTL(("hr_proc","kstat unexpected cpu parameter"));
  403.                        }
  404.                    }
  405.                }
  406.            }
  407.         }
  408.     }
  409.     kstat_close(kc);
  410. }
  411. int
  412. proc_status(int idx)
  413. {
  414.     /*
  415.      * hrDeviceStatus OBJECT-TYPE
  416.      * SYNTAX     INTEGER {
  417.      * unknown(1), running(2), warning(3), testing(4), down(5)
  418.      * }
  419.      */
  420.     int cidx = idx & HRDEV_TYPE_MASK;
  421.     if (strcmp(cpu[cidx].state,"on-line")==0) {
  422.         return 2;                   /* running */
  423.          }
  424.     else if (strcmp(cpu[cidx].state,"off-line")==0) {
  425.         return 5;                   /* down */
  426.          }
  427.     else if (strcmp(cpu[cidx].state,"missing")==0) {
  428.         return 3;                   /* warning, went missing, see above */
  429.          }
  430.     else if (strcmp(cpu[cidx].state,"testing")==0) {
  431.         return 4;                   /* somebody must be testing code up above */
  432.          }
  433.     else {
  434.         return 1;                   /* unknown */
  435.          }
  436. }
  437. #endif /* solaris2 */