1 /**************************************************************
2 * Copyright (C) 2001 Alex Rozin, Optical Access
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation for any purpose and without fee is hereby granted,
8 * provided that the above copyright notice appear in all copies and that
9 * both that copyright notice and this permission notice appear in
10 * supporting documentation.
12 * ALEX ROZIN DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
13 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
14 * ALEX ROZIN BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
15 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
16 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
17 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
19 ******************************************************************/
25 #include <net-snmp/net-snmp-config.h>
26 #include <net-snmp/net-snmp-includes.h>
27 #include <net-snmp/agent/net-snmp-agent-includes.h>
29 #include "util_funcs.h"
34 * Implementation headers
36 #include "agutil_api.h"
40 * File scope definitions section
43 #define historyControlEntryFirstIndexBegin 11
46 #define CTRL_DATASOURCE 4
47 #define CTRL_BUCKETSREQUESTED 5
48 #define CTRL_BUCKETSGRANTED 6
49 #define CTRL_INTERVAL 7
54 #define DATA_SAMPLEINDEX 4
55 #define DATA_INTERVALSTART 5
56 #define DATA_DROPEVENTS 6
59 #define DATA_BROADCASTPKTS 9
60 #define DATA_MULTICASTPKTS 10
61 #define DATA_CRCALIGNERRORS 11
62 #define DATA_UNDERSIZEPKTS 12
63 #define DATA_OVERSIZEPKTS 13
64 #define DATA_FRAGMENTS 14
65 #define DATA_JABBERS 15
66 #define DATA_COLLISIONS 16
67 #define DATA_UTILIZATION 17
70 * defaults & limitations
73 #define MAX_BUCKETS_IN_CRTL_ENTRY 50
74 #define HIST_DEF_BUCK_REQ 50
75 #define HIST_DEF_INTERVAL 1800
76 static VAR_OID_T DEFAULT_DATA_SOURCE = { 11, /* ifIndex.1 */
77 {1, 3, 6, 1, 2, 1, 2, 2, 1, 1, 1}
80 typedef struct data_struct_t {
81 struct data_struct_t *next;
83 u_long start_interval;
91 VAR_OID_T data_source;
94 DATA_ENTRY_T previous_bucket;
99 static TABLE_DEFINTION_T HistoryCtrlTable;
100 static TABLE_DEFINTION_T *table_ptr = &HistoryCtrlTable;
106 # define Leaf_historyControlDataSource 2
107 # define Leaf_historyControlBucketsRequested 3
108 # define Leaf_historyControlInterval 5
109 # define Leaf_historyControlOwner 6
110 # define Leaf_historyControlStatus 7
111 # define MIN_historyControlBucketsRequested 1
112 # define MAX_historyControlBucketsRequested 65535
113 # define MIN_historyControlInterval 1
114 # define MAX_historyControlInterval 3600
117 write_historyControl(int action, u_char * var_val, u_char var_val_type,
118 size_t var_val_len, u_char * statP,
119 oid * name, size_t name_len)
122 int leaf_id, snmp_status;
123 static int prev_action = COMMIT;
125 CRTL_ENTRY_T *cloned_body;
135 return ROWAPI_do_another_action(name,
136 historyControlEntryFirstIndexBegin,
137 action, &prev_action, table_ptr,
138 sizeof(CRTL_ENTRY_T));
141 * get values from PDU, check them and save them in the cloned entry
143 long_temp = name[historyControlEntryFirstIndexBegin];
144 leaf_id = (int) name[historyControlEntryFirstIndexBegin - 1];
145 hdr = ROWAPI_find(table_ptr, long_temp); /* it MUST be OK */
146 cloned_body = (CRTL_ENTRY_T *) hdr->tmp;
147 body = (CRTL_ENTRY_T *) hdr->body;
149 case Leaf_historyControlDataSource:
150 snmp_status = AGUTIL_get_oid_value(var_val, var_val_type,
152 &cloned_body->data_source);
153 if (SNMP_ERR_NOERROR != snmp_status) {
154 ag_trace("can't browse historyControlDataSource");
157 if (RMON1_ENTRY_UNDER_CREATION != hdr->status &&
158 snmp_oid_compare(cloned_body->data_source.objid,
159 cloned_body->data_source.length,
160 body->data_source.objid,
161 body->data_source.length)) {
163 ("can't change historyControlDataSource - not Creation");
164 return SNMP_ERR_BADVALUE;
167 case Leaf_historyControlBucketsRequested:
168 snmp_status = AGUTIL_get_int_value(var_val, var_val_type,
170 MIN_historyControlBucketsRequested,
171 MAX_historyControlBucketsRequested,
174 if (SNMP_ERR_NOERROR != snmp_status) {
178 if (RMON1_ENTRY_UNDER_CREATION != hdr->status &&
179 cloned_body->scrlr.data_requested !=
180 body->scrlr.data_requested)
181 return SNMP_ERR_BADVALUE;
184 case Leaf_historyControlInterval:
185 snmp_status = AGUTIL_get_int_value(var_val, var_val_type,
187 MIN_historyControlInterval,
188 MAX_historyControlInterval,
189 &cloned_body->interval);
190 if (SNMP_ERR_NOERROR != snmp_status) {
194 if (RMON1_ENTRY_UNDER_CREATION != hdr->status &&
195 cloned_body->interval != body->interval)
196 return SNMP_ERR_BADVALUE;
199 case Leaf_historyControlOwner:
201 AGFREE(hdr->new_owner);
202 hdr->new_owner = AGMALLOC(MAX_OWNERSTRING);;
204 return SNMP_ERR_TOOBIG;
205 snmp_status = AGUTIL_get_string_value(var_val, var_val_type,
208 1, NULL, hdr->new_owner);
209 if (SNMP_ERR_NOERROR != snmp_status) {
214 case Leaf_historyControlStatus:
215 snmp_status = AGUTIL_get_int_value(var_val, var_val_type,
220 if (SNMP_ERR_NOERROR != snmp_status) {
223 hdr->new_status = long_temp;
226 ag_trace("%s:unknown leaf_id=%d\n", table_ptr->name,
228 return SNMP_ERR_NOSUCHNAME;
229 } /* of switch by 'leaf_id' */
232 } /* of switch by actions */
234 prev_action = action;
235 return SNMP_ERR_NOERROR;
239 * var_historyControlTable():
242 var_historyControlTable(struct variable *vp,
246 size_t * var_len, WriteMethod ** write_method)
248 static long long_ret;
249 static CRTL_ENTRY_T theEntry;
252 *write_method = write_historyControl;
253 hdr = ROWAPI_header_ControlEntry(vp, name, length, exact, var_len,
255 &theEntry, sizeof(CRTL_ENTRY_T));
259 *var_len = sizeof(long); /* default */
263 long_ret = hdr->ctrl_index;
264 return (unsigned char *) &long_ret;
266 case CTRL_DATASOURCE:
267 *var_len = sizeof(oid) * theEntry.data_source.length;
268 return (unsigned char *) theEntry.data_source.objid;
270 case CTRL_BUCKETSREQUESTED:
271 long_ret = theEntry.scrlr.data_requested;
272 return (unsigned char *) &long_ret;
274 case CTRL_BUCKETSGRANTED:
276 long_ret = theEntry.scrlr.data_granted;
277 return (unsigned char *) &long_ret;
280 long_ret = theEntry.interval;
281 return (unsigned char *) &long_ret;
285 *var_len = strlen(hdr->owner);
286 return (unsigned char *) hdr->owner;
289 return (unsigned char *) "";
293 long_ret = hdr->status;
294 return (unsigned char *) &long_ret;
297 ag_trace("HistoryControlTable: unknown vp->magic=%d",
305 * history row management control callbacks
309 compute_delta(ETH_STATS_T * delta,
310 ETH_STATS_T * newval, ETH_STATS_T * prevval)
312 #define CNT_DIF(X) delta->X = newval->X - prevval->X
327 history_get_backet(unsigned int clientreg, void *clientarg)
329 RMON_ENTRY_T *hdr_ptr;
332 ETH_STATS_T newSample;
335 * ag_trace ("history_get_backet: timer_id=%d", (int) clientreg);
337 hdr_ptr = (RMON_ENTRY_T *) clientarg;
340 ("Err: history_get_backet: hdr_ptr=NULL ? (Inserted in shock)");
344 body = (CRTL_ENTRY_T *) hdr_ptr->body;
347 ("Err: history_get_backet: body=NULL ? (Inserted in shock)");
351 if (RMON1_ENTRY_VALID != hdr_ptr->status) {
352 ag_trace("Err: history_get_backet when entry %d is not valid ?!!",
353 (int) hdr_ptr->ctrl_index);
355 * snmp_alarm_print_list ();
357 snmp_alarm_unregister(body->timer_id);
358 ag_trace("Err: unregistered %ld", (long) body->timer_id);
362 SYSTEM_get_eth_statistics(&body->data_source, &newSample);
364 bptr = ROWDATAAPI_locate_new_data(&body->scrlr);
367 ("Err: history_get_backet for %d: empty bucket's list !??\n",
368 (int) hdr_ptr->ctrl_index);
372 bptr->data_index = ROWDATAAPI_get_total_number(&body->scrlr);
374 bptr->start_interval = body->previous_bucket.start_interval;
376 compute_delta(&bptr->EthData, &newSample,
377 &body->previous_bucket.EthData);
380 bptr->EthData.octets * 8 + bptr->EthData.packets * (96 + 64);
381 bptr->utilization /= body->coeff;
384 * update previous_bucket
386 body->previous_bucket.start_interval = AGUTIL_sys_up_time();
387 memcpy(&body->previous_bucket.EthData, &newSample,
388 sizeof(ETH_STATS_T));
392 * Control Table RowApi Callbacks
396 history_Create(RMON_ENTRY_T * eptr)
397 { /* create the body: alloc it and set defaults */
400 eptr->body = AGMALLOC(sizeof(CRTL_ENTRY_T));
403 body = (CRTL_ENTRY_T *) eptr->body;
408 body->interval = HIST_DEF_INTERVAL;
410 memcpy(&body->data_source, &DEFAULT_DATA_SOURCE, sizeof(VAR_OID_T));
412 ROWDATAAPI_init(&body->scrlr, HIST_DEF_BUCK_REQ,
413 MAX_BUCKETS_IN_CRTL_ENTRY, sizeof(DATA_ENTRY_T), NULL);
419 history_Validate(RMON_ENTRY_T * eptr)
422 * T.B.D. (system dependent) check valid inteface in body->data_source;
428 history_Activate(RMON_ENTRY_T * eptr)
430 CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr->body;
432 body->coeff = 100000L * (long) body->interval;
434 ROWDATAAPI_set_size(&body->scrlr,
435 body->scrlr.data_requested,
436 RMON1_ENTRY_VALID == eptr->status);
438 SYSTEM_get_eth_statistics(&body->data_source,
439 &body->previous_bucket.EthData);
440 body->previous_bucket.start_interval = AGUTIL_sys_up_time();
442 body->scrlr.current_data_ptr = body->scrlr.first_data_ptr;
444 * ag_trace ("Dbg: registered in history_Activate");
446 body->timer_id = snmp_alarm_register(body->interval, SA_REPEAT,
447 history_get_backet, eptr);
452 history_Deactivate(RMON_ENTRY_T * eptr)
454 CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr->body;
456 snmp_alarm_unregister(body->timer_id);
458 * ag_trace ("Dbg: unregistered in history_Deactivate timer_id=%d",
459 * (int) body->timer_id);
465 ROWDATAAPI_descructor(&body->scrlr);
471 history_Copy(RMON_ENTRY_T * eptr)
473 CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr->body;
474 CRTL_ENTRY_T *clone = (CRTL_ENTRY_T *) eptr->tmp;
476 if (body->scrlr.data_requested != clone->scrlr.data_requested) {
477 ROWDATAAPI_set_size(&body->scrlr, clone->scrlr.data_requested,
478 RMON1_ENTRY_VALID == eptr->status);
481 if (body->interval != clone->interval) {
482 if (RMON1_ENTRY_VALID == eptr->status) {
483 snmp_alarm_unregister(body->timer_id);
485 snmp_alarm_register(clone->interval, SA_REPEAT,
486 history_get_backet, eptr);
489 body->interval = clone->interval;
493 (clone->data_source.objid, clone->data_source.length,
494 body->data_source.objid, body->data_source.length)) {
495 memcpy(&body->data_source, &clone->data_source, sizeof(VAR_OID_T));
502 history_extract_scroller(void *v_body)
504 CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) v_body;
509 * var_etherHistoryTable():
512 var_etherHistoryTable(struct variable *vp,
516 size_t * var_len, WriteMethod ** write_method)
518 static long long_ret;
519 static DATA_ENTRY_T theBucket;
523 *write_method = NULL;
524 hdr = ROWDATAAPI_header_DataEntry(vp, name, length, exact, var_len,
526 &history_extract_scroller,
527 sizeof(DATA_ENTRY_T), &theBucket);
531 *var_len = sizeof(long); /* default */
533 ctrl = (CRTL_ENTRY_T *) hdr->body;
537 long_ret = hdr->ctrl_index;
538 return (unsigned char *) &long_ret;
539 case DATA_SAMPLEINDEX:
540 long_ret = theBucket.data_index;
541 return (unsigned char *) &long_ret;
542 case DATA_INTERVALSTART:
544 return (unsigned char *) &theBucket.start_interval;
545 case DATA_DROPEVENTS:
547 return (unsigned char *) &long_ret;
550 return (unsigned char *) &theBucket.EthData.octets;
553 return (unsigned char *) &theBucket.EthData.packets;
554 case DATA_BROADCASTPKTS:
556 return (unsigned char *) &theBucket.EthData.bcast_pkts;
557 case DATA_MULTICASTPKTS:
559 return (unsigned char *) &theBucket.EthData.mcast_pkts;
560 case DATA_CRCALIGNERRORS:
562 return (unsigned char *) &theBucket.EthData.crc_align;
563 case DATA_UNDERSIZEPKTS:
565 return (unsigned char *) &theBucket.EthData.undersize;
566 case DATA_OVERSIZEPKTS:
568 return (unsigned char *) &theBucket.EthData.oversize;
571 return (unsigned char *) &theBucket.EthData.fragments;
574 return (unsigned char *) &theBucket.EthData.jabbers;
575 case DATA_COLLISIONS:
577 return (unsigned char *) &theBucket.EthData.collisions;
578 case DATA_UTILIZATION:
580 return (unsigned char *) &theBucket.utilization;
582 ag_trace("etherHistoryTable: unknown vp->magic=%d",
589 #if 1 /* debug, but may be used for init. TBD: may be token snmpd.conf ? */
591 add_hist_entry(int ctrl_index, int ifIndex,
592 u_long interval, u_long requested)
594 register RMON_ENTRY_T *eptr;
595 register CRTL_ENTRY_T *body;
598 ierr = ROWAPI_new(table_ptr, ctrl_index);
600 ag_trace("ROWAPI_new failed with %d", ierr);
604 eptr = ROWAPI_find(table_ptr, ctrl_index);
606 ag_trace("ROWAPI_find failed");
610 body = (CRTL_ENTRY_T *) eptr->body;
616 body->data_source.objid[body->data_source.length - 1] = ifIndex;
617 body->interval = interval;
618 body->scrlr.data_requested = requested;
620 eptr->new_status = RMON1_ENTRY_VALID;
621 ierr = ROWAPI_commit(table_ptr, ctrl_index);
623 ag_trace("ROWAPI_commit failed with %d", ierr);
633 * Registration & Initializatio section
636 oid historyControlTable_variables_oid[] =
637 { 1, 3, 6, 1, 2, 1, 16, 2, 1 };
639 struct variable2 historyControlTable_variables[] = {
641 * magic number , variable type, ro/rw , callback fn , L, oidsuffix
643 {CTRL_INDEX, ASN_INTEGER, RONLY, var_historyControlTable, 2, {1, 1}},
644 {CTRL_DATASOURCE, ASN_OBJECT_ID, RWRITE, var_historyControlTable, 2,
646 {CTRL_BUCKETSREQUESTED, ASN_INTEGER, RWRITE, var_historyControlTable,
648 {CTRL_BUCKETSGRANTED, ASN_INTEGER, RONLY, var_historyControlTable, 2,
650 {CTRL_INTERVAL, ASN_INTEGER, RWRITE, var_historyControlTable, 2,
652 {CTRL_OWNER, ASN_OCTET_STR, RWRITE, var_historyControlTable, 2,
654 {CTRL_STATUS, ASN_INTEGER, RWRITE, var_historyControlTable, 2, {1, 7}},
658 oid etherHistoryTable_variables_oid[] =
659 { 1, 3, 6, 1, 2, 1, 16, 2, 2 };
661 struct variable2 etherHistoryTable_variables[] = {
663 * magic number , variable type , ro/rw , callback fn , L, oidsuffix
665 {DATA_INDEX, ASN_INTEGER, RONLY, var_etherHistoryTable, 2, {1, 1}},
666 {DATA_SAMPLEINDEX, ASN_INTEGER, RONLY, var_etherHistoryTable, 2,
668 {DATA_INTERVALSTART, ASN_TIMETICKS, RONLY, var_etherHistoryTable, 2,
670 {DATA_DROPEVENTS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
672 {DATA_OCTETS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2, {1, 5}},
673 {DATA_PKTS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2, {1, 6}},
674 {DATA_BROADCASTPKTS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
676 {DATA_MULTICASTPKTS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
678 {DATA_CRCALIGNERRORS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
680 {DATA_UNDERSIZEPKTS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
682 {DATA_OVERSIZEPKTS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
684 {DATA_FRAGMENTS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
686 {DATA_JABBERS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2, {1, 13}},
687 {DATA_COLLISIONS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
689 {DATA_UTILIZATION, ASN_INTEGER, RONLY, var_etherHistoryTable, 2,
697 REGISTER_MIB("historyControlTable", historyControlTable_variables,
698 variable2, historyControlTable_variables_oid);
699 REGISTER_MIB("etherHistoryTable", etherHistoryTable_variables,
700 variable2, etherHistoryTable_variables_oid);
702 ROWAPI_init_table(&HistoryCtrlTable, "History", 0, &history_Create, NULL, /* &history_Clone, */
703 NULL, /* &history_Delete, */
706 &history_Deactivate, &history_Copy);
709 * add_hist_entry (2, 3, 4, 2);