| /************************************************************** |
| * Copyright (C) 2001 Alex Rozin, Optical Access |
| * |
| * All Rights Reserved |
| * |
| * Permission to use, copy, modify and distribute this software and its |
| * documentation for any purpose and without fee is hereby granted, |
| * provided that the above copyright notice appear in all copies and that |
| * both that copyright notice and this permission notice appear in |
| * supporting documentation. |
| * |
| * ALEX ROZIN DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING |
| * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL |
| * ALEX ROZIN BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR |
| * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, |
| * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, |
| * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS |
| * SOFTWARE. |
| ******************************************************************/ |
| |
| #include <net-snmp/net-snmp-config.h> |
| |
| #if HAVE_STDLIB_H |
| #include <stdlib.h> |
| #endif |
| #if TIME_WITH_SYS_TIME |
| # include <sys/time.h> |
| # include <time.h> |
| #else |
| # if HAVE_SYS_TIME_H |
| # include <sys/time.h> |
| # else |
| # include <time.h> |
| # endif |
| #endif |
| #if HAVE_UNISTD_H |
| #include <unistd.h> |
| #endif |
| |
| #include <net-snmp/net-snmp-includes.h> |
| #include <net-snmp/agent/net-snmp-agent-includes.h> |
| |
| #include "history.h" |
| |
| /* |
| * Implementation headers |
| */ |
| #include "agutil_api.h" |
| #include "row_api.h" |
| |
| /* |
| * File scope definitions section |
| */ |
| |
| #define historyControlEntryFirstIndexBegin 11 |
| |
| #define CTRL_INDEX 3 |
| #define CTRL_DATASOURCE 4 |
| #define CTRL_BUCKETSREQUESTED 5 |
| #define CTRL_BUCKETSGRANTED 6 |
| #define CTRL_INTERVAL 7 |
| #define CTRL_OWNER 8 |
| #define CTRL_STATUS 9 |
| |
| #define DATA_INDEX 3 |
| #define DATA_SAMPLEINDEX 4 |
| #define DATA_INTERVALSTART 5 |
| #define DATA_DROPEVENTS 6 |
| #define DATA_OCTETS 7 |
| #define DATA_PKTS 8 |
| #define DATA_BROADCASTPKTS 9 |
| #define DATA_MULTICASTPKTS 10 |
| #define DATA_CRCALIGNERRORS 11 |
| #define DATA_UNDERSIZEPKTS 12 |
| #define DATA_OVERSIZEPKTS 13 |
| #define DATA_FRAGMENTS 14 |
| #define DATA_JABBERS 15 |
| #define DATA_COLLISIONS 16 |
| #define DATA_UTILIZATION 17 |
| |
| /* |
| * defaults & limitations |
| */ |
| |
| #define MAX_BUCKETS_IN_CRTL_ENTRY 50 |
| #define HIST_DEF_BUCK_REQ 50 |
| #define HIST_DEF_INTERVAL 1800 |
| static VAR_OID_T DEFAULT_DATA_SOURCE = { 11, /* ifIndex.1 */ |
| {1, 3, 6, 1, 2, 1, 2, 2, 1, 1, 1} |
| }; |
| |
| typedef struct data_struct_t { |
| struct data_struct_t *next; |
| u_long data_index; |
| u_long start_interval; |
| u_long utilization; |
| ETH_STATS_T EthData; |
| } DATA_ENTRY_T; |
| |
| typedef struct { |
| u_long interval; |
| u_long timer_id; |
| VAR_OID_T data_source; |
| |
| u_long coeff; |
| DATA_ENTRY_T previous_bucket; |
| SCROLLER_T scrlr; |
| |
| } CRTL_ENTRY_T; |
| |
| static TABLE_DEFINTION_T HistoryCtrlTable; |
| static TABLE_DEFINTION_T *table_ptr = &HistoryCtrlTable; |
| |
| /* |
| * Main section |
| */ |
| |
| # define Leaf_historyControlDataSource 2 |
| # define Leaf_historyControlBucketsRequested 3 |
| # define Leaf_historyControlInterval 5 |
| # define Leaf_historyControlOwner 6 |
| # define Leaf_historyControlStatus 7 |
| # define MIN_historyControlBucketsRequested 1 |
| # define MAX_historyControlBucketsRequested 65535 |
| # define MIN_historyControlInterval 1 |
| # define MAX_historyControlInterval 3600 |
| |
| static int |
| write_historyControl(int action, u_char * var_val, u_char var_val_type, |
| size_t var_val_len, u_char * statP, |
| oid * name, size_t name_len) |
| { |
| long long_temp; |
| int leaf_id, snmp_status; |
| static int prev_action = COMMIT; |
| RMON_ENTRY_T *hdr; |
| CRTL_ENTRY_T *cloned_body; |
| CRTL_ENTRY_T *body; |
| |
| switch (action) { |
| case RESERVE1: |
| case FREE: |
| case UNDO: |
| case ACTION: |
| case COMMIT: |
| default: |
| return ROWAPI_do_another_action(name, |
| historyControlEntryFirstIndexBegin, |
| action, &prev_action, table_ptr, |
| sizeof(CRTL_ENTRY_T)); |
| case RESERVE2: |
| /* |
| * get values from PDU, check them and save them in the cloned entry |
| */ |
| long_temp = name[historyControlEntryFirstIndexBegin]; |
| leaf_id = (int) name[historyControlEntryFirstIndexBegin - 1]; |
| hdr = ROWAPI_find(table_ptr, long_temp); /* it MUST be OK */ |
| cloned_body = (CRTL_ENTRY_T *) hdr->tmp; |
| body = (CRTL_ENTRY_T *) hdr->body; |
| switch (leaf_id) { |
| case Leaf_historyControlDataSource: |
| snmp_status = AGUTIL_get_oid_value(var_val, var_val_type, |
| var_val_len, |
| &cloned_body->data_source); |
| if (SNMP_ERR_NOERROR != snmp_status) { |
| ag_trace("can't browse historyControlDataSource"); |
| return snmp_status; |
| } |
| if (RMON1_ENTRY_UNDER_CREATION != hdr->status && |
| snmp_oid_compare(cloned_body->data_source.objid, |
| cloned_body->data_source.length, |
| body->data_source.objid, |
| body->data_source.length)) { |
| ag_trace |
| ("can't change historyControlDataSource - not Creation"); |
| return SNMP_ERR_BADVALUE; |
| } |
| break; |
| case Leaf_historyControlBucketsRequested: |
| snmp_status = AGUTIL_get_int_value(var_val, var_val_type, |
| var_val_len, |
| MIN_historyControlBucketsRequested, |
| MAX_historyControlBucketsRequested, |
| (long *) &cloned_body->scrlr. |
| data_requested); |
| if (SNMP_ERR_NOERROR != snmp_status) { |
| return snmp_status; |
| } |
| #if 0 |
| if (RMON1_ENTRY_UNDER_CREATION != hdr->status && |
| cloned_body->scrlr.data_requested != |
| body->scrlr.data_requested) |
| return SNMP_ERR_BADVALUE; |
| #endif |
| break; |
| case Leaf_historyControlInterval: |
| snmp_status = AGUTIL_get_int_value(var_val, var_val_type, |
| var_val_len, |
| MIN_historyControlInterval, |
| MAX_historyControlInterval, |
| (long *) &cloned_body->interval); |
| if (SNMP_ERR_NOERROR != snmp_status) { |
| return snmp_status; |
| } |
| #if 0 |
| if (RMON1_ENTRY_UNDER_CREATION != hdr->status && |
| cloned_body->interval != body->interval) |
| return SNMP_ERR_BADVALUE; |
| #endif |
| break; |
| case Leaf_historyControlOwner: |
| if (hdr->new_owner) |
| AGFREE(hdr->new_owner); |
| hdr->new_owner = AGMALLOC(MAX_OWNERSTRING);; |
| if (!hdr->new_owner) |
| return SNMP_ERR_TOOBIG; |
| snmp_status = AGUTIL_get_string_value(var_val, var_val_type, |
| var_val_len, |
| MAX_OWNERSTRING, |
| 1, NULL, hdr->new_owner); |
| if (SNMP_ERR_NOERROR != snmp_status) { |
| return snmp_status; |
| } |
| |
| break; |
| case Leaf_historyControlStatus: |
| snmp_status = AGUTIL_get_int_value(var_val, var_val_type, |
| var_val_len, |
| RMON1_ENTRY_VALID, |
| RMON1_ENTRY_INVALID, |
| &long_temp); |
| if (SNMP_ERR_NOERROR != snmp_status) { |
| return snmp_status; |
| } |
| hdr->new_status = long_temp; |
| break; |
| default: |
| ag_trace("%s:unknown leaf_id=%d\n", table_ptr->name, |
| (int) leaf_id); |
| return SNMP_ERR_NOSUCHNAME; |
| } /* of switch by 'leaf_id' */ |
| break; |
| |
| } /* of switch by actions */ |
| |
| prev_action = action; |
| return SNMP_ERR_NOERROR; |
| } |
| |
| /* |
| * var_historyControlTable(): |
| */ |
| unsigned char * |
| var_historyControlTable(struct variable *vp, |
| oid * name, |
| size_t * length, |
| int exact, |
| size_t * var_len, WriteMethod ** write_method) |
| { |
| static unsigned char zero_octet_string[1]; |
| static long long_ret; |
| static CRTL_ENTRY_T theEntry; |
| RMON_ENTRY_T *hdr; |
| |
| *write_method = write_historyControl; |
| hdr = ROWAPI_header_ControlEntry(vp, name, length, exact, var_len, |
| table_ptr, |
| &theEntry, sizeof(CRTL_ENTRY_T)); |
| if (!hdr) |
| return NULL; |
| |
| *var_len = sizeof(long); /* default */ |
| |
| switch (vp->magic) { |
| case CTRL_INDEX: |
| long_ret = hdr->ctrl_index; |
| return (unsigned char *) &long_ret; |
| |
| case CTRL_DATASOURCE: |
| *var_len = sizeof(oid) * theEntry.data_source.length; |
| return (unsigned char *) theEntry.data_source.objid; |
| |
| case CTRL_BUCKETSREQUESTED: |
| long_ret = theEntry.scrlr.data_requested; |
| return (unsigned char *) &long_ret; |
| |
| case CTRL_BUCKETSGRANTED: |
| |
| long_ret = theEntry.scrlr.data_granted; |
| return (unsigned char *) &long_ret; |
| |
| case CTRL_INTERVAL: |
| long_ret = theEntry.interval; |
| return (unsigned char *) &long_ret; |
| |
| case CTRL_OWNER: |
| if (hdr->owner) { |
| *var_len = strlen(hdr->owner); |
| return (unsigned char *) hdr->owner; |
| } else { |
| *var_len = 0; |
| return zero_octet_string; |
| } |
| |
| case CTRL_STATUS: |
| long_ret = hdr->status; |
| return (unsigned char *) &long_ret; |
| |
| default: |
| ag_trace("HistoryControlTable: unknown vp->magic=%d", |
| (int) vp->magic); |
| ERROR_MSG(""); |
| } |
| return NULL; |
| } |
| |
| /* |
| * history row management control callbacks |
| */ |
| |
| static void |
| compute_delta(ETH_STATS_T * delta, |
| ETH_STATS_T * newval, ETH_STATS_T * prevval) |
| { |
| #define CNT_DIF(X) delta->X = newval->X - prevval->X |
| |
| CNT_DIF(octets); |
| CNT_DIF(packets); |
| CNT_DIF(bcast_pkts); |
| CNT_DIF(mcast_pkts); |
| CNT_DIF(crc_align); |
| CNT_DIF(undersize); |
| CNT_DIF(oversize); |
| CNT_DIF(fragments); |
| CNT_DIF(jabbers); |
| CNT_DIF(collisions); |
| } |
| |
| static void |
| history_get_backet(unsigned int clientreg, void *clientarg) |
| { |
| RMON_ENTRY_T *hdr_ptr; |
| CRTL_ENTRY_T *body; |
| DATA_ENTRY_T *bptr; |
| ETH_STATS_T newSample; |
| |
| /* |
| * ag_trace ("history_get_backet: timer_id=%d", (int) clientreg); |
| */ |
| hdr_ptr = (RMON_ENTRY_T *) clientarg; |
| if (!hdr_ptr) { |
| ag_trace |
| ("Err: history_get_backet: hdr_ptr=NULL ? (Inserted in shock)"); |
| return; |
| } |
| |
| body = (CRTL_ENTRY_T *) hdr_ptr->body; |
| if (!body) { |
| ag_trace |
| ("Err: history_get_backet: body=NULL ? (Inserted in shock)"); |
| return; |
| } |
| |
| if (RMON1_ENTRY_VALID != hdr_ptr->status) { |
| ag_trace("Err: history_get_backet when entry %d is not valid ?!!", |
| (int) hdr_ptr->ctrl_index); |
| /* |
| * snmp_alarm_print_list (); |
| */ |
| snmp_alarm_unregister(body->timer_id); |
| ag_trace("Err: unregistered %ld", (long) body->timer_id); |
| return; |
| } |
| |
| SYSTEM_get_eth_statistics(&body->data_source, &newSample); |
| |
| bptr = ROWDATAAPI_locate_new_data(&body->scrlr); |
| if (!bptr) { |
| ag_trace |
| ("Err: history_get_backet for %d: empty bucket's list !??\n", |
| (int) hdr_ptr->ctrl_index); |
| return; |
| } |
| |
| bptr->data_index = ROWDATAAPI_get_total_number(&body->scrlr); |
| |
| bptr->start_interval = body->previous_bucket.start_interval; |
| |
| compute_delta(&bptr->EthData, &newSample, |
| &body->previous_bucket.EthData); |
| |
| bptr->utilization = |
| bptr->EthData.octets * 8 + bptr->EthData.packets * (96 + 64); |
| bptr->utilization /= body->coeff; |
| |
| /* |
| * update previous_bucket |
| */ |
| body->previous_bucket.start_interval = AGUTIL_sys_up_time(); |
| memcpy(&body->previous_bucket.EthData, &newSample, |
| sizeof(ETH_STATS_T)); |
| } |
| |
| /* |
| * Control Table RowApi Callbacks |
| */ |
| |
| int |
| history_Create(RMON_ENTRY_T * eptr) |
| { /* create the body: alloc it and set defaults */ |
| CRTL_ENTRY_T *body; |
| |
| eptr->body = AGMALLOC(sizeof(CRTL_ENTRY_T)); |
| if (!eptr->body) |
| return -3; |
| body = (CRTL_ENTRY_T *) eptr->body; |
| |
| /* |
| * set defaults |
| */ |
| body->interval = HIST_DEF_INTERVAL; |
| body->timer_id = 0; |
| memcpy(&body->data_source, &DEFAULT_DATA_SOURCE, sizeof(VAR_OID_T)); |
| |
| ROWDATAAPI_init(&body->scrlr, HIST_DEF_BUCK_REQ, |
| MAX_BUCKETS_IN_CRTL_ENTRY, sizeof(DATA_ENTRY_T), NULL); |
| |
| return 0; |
| } |
| |
| int |
| history_Validate(RMON_ENTRY_T * eptr) |
| { |
| /* |
| * T.B.D. (system dependent) check valid inteface in body->data_source; |
| */ |
| return 0; |
| } |
| |
| int |
| history_Activate(RMON_ENTRY_T * eptr) |
| { |
| CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr->body; |
| |
| body->coeff = 100000L * (long) body->interval; |
| |
| ROWDATAAPI_set_size(&body->scrlr, |
| body->scrlr.data_requested, |
| (u_char)(RMON1_ENTRY_VALID == eptr->status) ); |
| |
| SYSTEM_get_eth_statistics(&body->data_source, |
| &body->previous_bucket.EthData); |
| body->previous_bucket.start_interval = AGUTIL_sys_up_time(); |
| |
| body->scrlr.current_data_ptr = body->scrlr.first_data_ptr; |
| /* |
| * ag_trace ("Dbg: registered in history_Activate"); |
| */ |
| body->timer_id = snmp_alarm_register(body->interval, SA_REPEAT, |
| history_get_backet, eptr); |
| return 0; |
| } |
| |
| int |
| history_Deactivate(RMON_ENTRY_T * eptr) |
| { |
| CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr->body; |
| |
| snmp_alarm_unregister(body->timer_id); |
| /* |
| * ag_trace ("Dbg: unregistered in history_Deactivate timer_id=%d", |
| * (int) body->timer_id); |
| */ |
| |
| /* |
| * free data list |
| */ |
| ROWDATAAPI_descructor(&body->scrlr); |
| |
| return 0; |
| } |
| |
| int |
| history_Copy(RMON_ENTRY_T * eptr) |
| { |
| CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr->body; |
| CRTL_ENTRY_T *clone = (CRTL_ENTRY_T *) eptr->tmp; |
| |
| if (body->scrlr.data_requested != clone->scrlr.data_requested) { |
| ROWDATAAPI_set_size(&body->scrlr, clone->scrlr.data_requested, |
| (u_char)(RMON1_ENTRY_VALID == eptr->status) ); |
| } |
| |
| if (body->interval != clone->interval) { |
| if (RMON1_ENTRY_VALID == eptr->status) { |
| snmp_alarm_unregister(body->timer_id); |
| body->timer_id = |
| snmp_alarm_register(clone->interval, SA_REPEAT, |
| history_get_backet, eptr); |
| } |
| |
| body->interval = clone->interval; |
| } |
| |
| if (snmp_oid_compare |
| (clone->data_source.objid, clone->data_source.length, |
| body->data_source.objid, body->data_source.length)) { |
| memcpy(&body->data_source, &clone->data_source, sizeof(VAR_OID_T)); |
| } |
| |
| return 0; |
| } |
| |
| static SCROLLER_T * |
| history_extract_scroller(void *v_body) |
| { |
| CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) v_body; |
| return &body->scrlr; |
| } |
| |
| /* |
| * var_etherHistoryTable(): |
| */ |
| unsigned char * |
| var_etherHistoryTable(struct variable *vp, |
| oid * name, |
| size_t * length, |
| int exact, |
| size_t * var_len, WriteMethod ** write_method) |
| { |
| static long long_ret; |
| static DATA_ENTRY_T theBucket; |
| RMON_ENTRY_T *hdr; |
| |
| *write_method = NULL; |
| hdr = ROWDATAAPI_header_DataEntry(vp, name, length, exact, var_len, |
| table_ptr, |
| &history_extract_scroller, |
| sizeof(DATA_ENTRY_T), &theBucket); |
| if (!hdr) |
| return NULL; |
| |
| *var_len = sizeof(long); /* default */ |
| |
| switch (vp->magic) { |
| case DATA_INDEX: |
| long_ret = hdr->ctrl_index; |
| return (unsigned char *) &long_ret; |
| case DATA_SAMPLEINDEX: |
| long_ret = theBucket.data_index; |
| return (unsigned char *) &long_ret; |
| case DATA_INTERVALSTART: |
| long_ret = 0; |
| return (unsigned char *) &theBucket.start_interval; |
| case DATA_DROPEVENTS: |
| long_ret = 0; |
| return (unsigned char *) &long_ret; |
| case DATA_OCTETS: |
| long_ret = 0; |
| return (unsigned char *) &theBucket.EthData.octets; |
| case DATA_PKTS: |
| long_ret = 0; |
| return (unsigned char *) &theBucket.EthData.packets; |
| case DATA_BROADCASTPKTS: |
| long_ret = 0; |
| return (unsigned char *) &theBucket.EthData.bcast_pkts; |
| case DATA_MULTICASTPKTS: |
| long_ret = 0; |
| return (unsigned char *) &theBucket.EthData.mcast_pkts; |
| case DATA_CRCALIGNERRORS: |
| long_ret = 0; |
| return (unsigned char *) &theBucket.EthData.crc_align; |
| case DATA_UNDERSIZEPKTS: |
| long_ret = 0; |
| return (unsigned char *) &theBucket.EthData.undersize; |
| case DATA_OVERSIZEPKTS: |
| long_ret = 0; |
| return (unsigned char *) &theBucket.EthData.oversize; |
| case DATA_FRAGMENTS: |
| long_ret = 0; |
| return (unsigned char *) &theBucket.EthData.fragments; |
| case DATA_JABBERS: |
| long_ret = 0; |
| return (unsigned char *) &theBucket.EthData.jabbers; |
| case DATA_COLLISIONS: |
| long_ret = 0; |
| return (unsigned char *) &theBucket.EthData.collisions; |
| case DATA_UTILIZATION: |
| long_ret = 0; |
| return (unsigned char *) &theBucket.utilization; |
| default: |
| ag_trace("etherHistoryTable: unknown vp->magic=%d", |
| (int) vp->magic); |
| ERROR_MSG(""); |
| } |
| return NULL; |
| } |
| |
| #if 1 /* debug, but may be used for init. TBD: may be token snmpd.conf ? */ |
| int |
| add_hist_entry(int ctrl_index, int ifIndex, |
| u_long interval, u_long requested) |
| { |
| register RMON_ENTRY_T *eptr; |
| register CRTL_ENTRY_T *body; |
| int ierr; |
| |
| ierr = ROWAPI_new(table_ptr, ctrl_index); |
| if (ierr) { |
| ag_trace("ROWAPI_new failed with %d", ierr); |
| return ierr; |
| } |
| |
| eptr = ROWAPI_find(table_ptr, ctrl_index); |
| if (!eptr) { |
| ag_trace("ROWAPI_find failed"); |
| return -4; |
| } |
| |
| body = (CRTL_ENTRY_T *) eptr->body; |
| |
| /* |
| * set parameters |
| */ |
| |
| body->data_source.objid[body->data_source.length - 1] = ifIndex; |
| body->interval = interval; |
| body->scrlr.data_requested = requested; |
| |
| eptr->new_status = RMON1_ENTRY_VALID; |
| ierr = ROWAPI_commit(table_ptr, ctrl_index); |
| if (ierr) { |
| ag_trace("ROWAPI_commit failed with %d", ierr); |
| } |
| |
| return ierr; |
| |
| } |
| |
| #endif |
| |
| /* |
| * Registration & Initializatio section |
| */ |
| |
| oid historyControlTable_variables_oid[] = |
| { 1, 3, 6, 1, 2, 1, 16, 2, 1 }; |
| |
| struct variable2 historyControlTable_variables[] = { |
| /* |
| * magic number , variable type, ro/rw , callback fn , L, oidsuffix |
| */ |
| {CTRL_INDEX, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, |
| var_historyControlTable, 2, {1, 1}}, |
| {CTRL_DATASOURCE, ASN_OBJECT_ID, NETSNMP_OLDAPI_RWRITE, |
| var_historyControlTable, 2, {1, 2}}, |
| {CTRL_BUCKETSREQUESTED, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE, |
| var_historyControlTable, 2, {1, 3}}, |
| {CTRL_BUCKETSGRANTED, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, |
| var_historyControlTable, 2, {1, 4}}, |
| {CTRL_INTERVAL, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE, |
| var_historyControlTable, 2, {1, 5}}, |
| {CTRL_OWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE, |
| var_historyControlTable, 2, {1, 6}}, |
| {CTRL_STATUS, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE, |
| var_historyControlTable, 2, {1, 7}}, |
| |
| }; |
| |
| oid etherHistoryTable_variables_oid[] = |
| { 1, 3, 6, 1, 2, 1, 16, 2, 2 }; |
| |
| struct variable2 etherHistoryTable_variables[] = { |
| /* |
| * magic number , variable type , ro/rw , callback fn , L, oidsuffix |
| */ |
| {DATA_INDEX, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, |
| var_etherHistoryTable, 2, {1, 1}}, |
| {DATA_SAMPLEINDEX, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, |
| var_etherHistoryTable, 2, {1, 2}}, |
| {DATA_INTERVALSTART, ASN_TIMETICKS, NETSNMP_OLDAPI_RONLY, |
| var_etherHistoryTable, 2, {1, 3}}, |
| {DATA_DROPEVENTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, |
| var_etherHistoryTable, 2, {1, 4}}, |
| {DATA_OCTETS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, |
| var_etherHistoryTable, 2, {1, 5}}, |
| {DATA_PKTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, |
| var_etherHistoryTable, 2, {1, 6}}, |
| {DATA_BROADCASTPKTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, |
| var_etherHistoryTable, 2, {1, 7}}, |
| {DATA_MULTICASTPKTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, |
| var_etherHistoryTable, 2, {1, 8}}, |
| {DATA_CRCALIGNERRORS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, |
| var_etherHistoryTable, 2, {1, 9}}, |
| {DATA_UNDERSIZEPKTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, |
| var_etherHistoryTable, 2, {1, 10}}, |
| {DATA_OVERSIZEPKTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, |
| var_etherHistoryTable, 2, {1, 11}}, |
| {DATA_FRAGMENTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, |
| var_etherHistoryTable, 2, {1, 12}}, |
| {DATA_JABBERS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, |
| var_etherHistoryTable, 2, {1, 13}}, |
| {DATA_COLLISIONS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, |
| var_etherHistoryTable, 2, {1, 14}}, |
| {DATA_UTILIZATION, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, |
| var_etherHistoryTable, 2, {1, 15}}, |
| |
| }; |
| |
| void |
| init_history(void) |
| { |
| REGISTER_MIB("historyControlTable", historyControlTable_variables, |
| variable2, historyControlTable_variables_oid); |
| REGISTER_MIB("etherHistoryTable", etherHistoryTable_variables, |
| variable2, etherHistoryTable_variables_oid); |
| |
| ROWAPI_init_table(&HistoryCtrlTable, "History", 0, &history_Create, NULL, /* &history_Clone, */ |
| NULL, /* &history_Delete, */ |
| &history_Validate, |
| &history_Activate, |
| &history_Deactivate, &history_Copy); |
| |
| /* |
| * add_hist_entry (2, 3, 4, 2); |
| */ |
| } |