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
******************************************************************/
21
#include <net-snmp/net-snmp-config.h>
26
#if TIME_WITH_SYS_TIME
28
# include <sys/timeb.h>
30
# include <sys/time.h>
35
# include <sys/time.h>
44
#include <net-snmp/net-snmp-includes.h>
45
#include <net-snmp/agent/net-snmp-agent-includes.h>
47
#include "util_funcs.h"
52
* Implementation headers
54
#include "agutil_api.h"
58
* File scope definitions section
61
#define historyControlEntryFirstIndexBegin 11
64
#define CTRL_DATASOURCE 4
65
#define CTRL_BUCKETSREQUESTED 5
66
#define CTRL_BUCKETSGRANTED 6
67
#define CTRL_INTERVAL 7
72
#define DATA_SAMPLEINDEX 4
73
#define DATA_INTERVALSTART 5
74
#define DATA_DROPEVENTS 6
77
#define DATA_BROADCASTPKTS 9
78
#define DATA_MULTICASTPKTS 10
79
#define DATA_CRCALIGNERRORS 11
80
#define DATA_UNDERSIZEPKTS 12
81
#define DATA_OVERSIZEPKTS 13
82
#define DATA_FRAGMENTS 14
83
#define DATA_JABBERS 15
84
#define DATA_COLLISIONS 16
85
#define DATA_UTILIZATION 17
88
* defaults & limitations
91
#define MAX_BUCKETS_IN_CRTL_ENTRY 50
92
#define HIST_DEF_BUCK_REQ 50
93
#define HIST_DEF_INTERVAL 1800
94
static VAR_OID_T DEFAULT_DATA_SOURCE = { 11, /* ifIndex.1 */
95
{1, 3, 6, 1, 2, 1, 2, 2, 1, 1, 1}
98
typedef struct data_struct_t {
99
struct data_struct_t *next;
101
u_long start_interval;
109
VAR_OID_T data_source;
112
DATA_ENTRY_T previous_bucket;
117
static TABLE_DEFINTION_T HistoryCtrlTable;
118
static TABLE_DEFINTION_T *table_ptr = &HistoryCtrlTable;
124
# define Leaf_historyControlDataSource 2
125
# define Leaf_historyControlBucketsRequested 3
126
# define Leaf_historyControlInterval 5
127
# define Leaf_historyControlOwner 6
128
# define Leaf_historyControlStatus 7
129
# define MIN_historyControlBucketsRequested 1
130
# define MAX_historyControlBucketsRequested 65535
131
# define MIN_historyControlInterval 1
132
# define MAX_historyControlInterval 3600
135
write_historyControl(int action, u_char * var_val, u_char var_val_type,
136
size_t var_val_len, u_char * statP,
137
oid * name, size_t name_len)
140
int leaf_id, snmp_status;
141
static int prev_action = COMMIT;
143
CRTL_ENTRY_T *cloned_body;
153
return ROWAPI_do_another_action(name,
154
historyControlEntryFirstIndexBegin,
155
action, &prev_action, table_ptr,
156
sizeof(CRTL_ENTRY_T));
159
* get values from PDU, check them and save them in the cloned entry
161
long_temp = name[historyControlEntryFirstIndexBegin];
162
leaf_id = (int) name[historyControlEntryFirstIndexBegin - 1];
163
hdr = ROWAPI_find(table_ptr, long_temp); /* it MUST be OK */
164
cloned_body = (CRTL_ENTRY_T *) hdr->tmp;
165
body = (CRTL_ENTRY_T *) hdr->body;
167
case Leaf_historyControlDataSource:
168
snmp_status = AGUTIL_get_oid_value(var_val, var_val_type,
170
&cloned_body->data_source);
171
if (SNMP_ERR_NOERROR != snmp_status) {
172
ag_trace("can't browse historyControlDataSource");
175
if (RMON1_ENTRY_UNDER_CREATION != hdr->status &&
176
snmp_oid_compare(cloned_body->data_source.objid,
177
cloned_body->data_source.length,
178
body->data_source.objid,
179
body->data_source.length)) {
181
("can't change historyControlDataSource - not Creation");
182
return SNMP_ERR_BADVALUE;
185
case Leaf_historyControlBucketsRequested:
186
snmp_status = AGUTIL_get_int_value(var_val, var_val_type,
188
MIN_historyControlBucketsRequested,
189
MAX_historyControlBucketsRequested,
192
if (SNMP_ERR_NOERROR != snmp_status) {
196
if (RMON1_ENTRY_UNDER_CREATION != hdr->status &&
197
cloned_body->scrlr.data_requested !=
198
body->scrlr.data_requested)
199
return SNMP_ERR_BADVALUE;
202
case Leaf_historyControlInterval:
203
snmp_status = AGUTIL_get_int_value(var_val, var_val_type,
205
MIN_historyControlInterval,
206
MAX_historyControlInterval,
207
&cloned_body->interval);
208
if (SNMP_ERR_NOERROR != snmp_status) {
212
if (RMON1_ENTRY_UNDER_CREATION != hdr->status &&
213
cloned_body->interval != body->interval)
214
return SNMP_ERR_BADVALUE;
217
case Leaf_historyControlOwner:
219
AGFREE(hdr->new_owner);
220
hdr->new_owner = AGMALLOC(MAX_OWNERSTRING);;
222
return SNMP_ERR_TOOBIG;
223
snmp_status = AGUTIL_get_string_value(var_val, var_val_type,
226
1, NULL, hdr->new_owner);
227
if (SNMP_ERR_NOERROR != snmp_status) {
232
case Leaf_historyControlStatus:
233
snmp_status = AGUTIL_get_int_value(var_val, var_val_type,
238
if (SNMP_ERR_NOERROR != snmp_status) {
241
hdr->new_status = long_temp;
244
ag_trace("%s:unknown leaf_id=%d\n", table_ptr->name,
246
return SNMP_ERR_NOSUCHNAME;
247
} /* of switch by 'leaf_id' */
250
} /* of switch by actions */
252
prev_action = action;
253
return SNMP_ERR_NOERROR;
257
* var_historyControlTable():
260
var_historyControlTable(struct variable *vp,
264
size_t * var_len, WriteMethod ** write_method)
266
static long long_ret;
267
static CRTL_ENTRY_T theEntry;
270
*write_method = write_historyControl;
271
hdr = ROWAPI_header_ControlEntry(vp, name, length, exact, var_len,
273
&theEntry, sizeof(CRTL_ENTRY_T));
277
*var_len = sizeof(long); /* default */
281
long_ret = hdr->ctrl_index;
282
return (unsigned char *) &long_ret;
284
case CTRL_DATASOURCE:
285
*var_len = sizeof(oid) * theEntry.data_source.length;
286
return (unsigned char *) theEntry.data_source.objid;
288
case CTRL_BUCKETSREQUESTED:
289
long_ret = theEntry.scrlr.data_requested;
290
return (unsigned char *) &long_ret;
292
case CTRL_BUCKETSGRANTED:
294
long_ret = theEntry.scrlr.data_granted;
295
return (unsigned char *) &long_ret;
298
long_ret = theEntry.interval;
299
return (unsigned char *) &long_ret;
303
*var_len = strlen(hdr->owner);
304
return (unsigned char *) hdr->owner;
307
return (unsigned char *) "";
311
long_ret = hdr->status;
312
return (unsigned char *) &long_ret;
315
ag_trace("HistoryControlTable: unknown vp->magic=%d",
323
* history row management control callbacks
327
compute_delta(ETH_STATS_T * delta,
328
ETH_STATS_T * newval, ETH_STATS_T * prevval)
330
#define CNT_DIF(X) delta->X = newval->X - prevval->X
345
history_get_backet(unsigned int clientreg, void *clientarg)
347
RMON_ENTRY_T *hdr_ptr;
350
ETH_STATS_T newSample;
353
* ag_trace ("history_get_backet: timer_id=%d", (int) clientreg);
355
hdr_ptr = (RMON_ENTRY_T *) clientarg;
358
("Err: history_get_backet: hdr_ptr=NULL ? (Inserted in shock)");
362
body = (CRTL_ENTRY_T *) hdr_ptr->body;
365
("Err: history_get_backet: body=NULL ? (Inserted in shock)");
369
if (RMON1_ENTRY_VALID != hdr_ptr->status) {
370
ag_trace("Err: history_get_backet when entry %d is not valid ?!!",
371
(int) hdr_ptr->ctrl_index);
373
* snmp_alarm_print_list ();
375
snmp_alarm_unregister(body->timer_id);
376
ag_trace("Err: unregistered %ld", (long) body->timer_id);
380
SYSTEM_get_eth_statistics(&body->data_source, &newSample);
382
bptr = ROWDATAAPI_locate_new_data(&body->scrlr);
385
("Err: history_get_backet for %d: empty bucket's list !??\n",
386
(int) hdr_ptr->ctrl_index);
390
bptr->data_index = ROWDATAAPI_get_total_number(&body->scrlr);
392
bptr->start_interval = body->previous_bucket.start_interval;
394
compute_delta(&bptr->EthData, &newSample,
395
&body->previous_bucket.EthData);
398
bptr->EthData.octets * 8 + bptr->EthData.packets * (96 + 64);
399
bptr->utilization /= body->coeff;
402
* update previous_bucket
404
body->previous_bucket.start_interval = AGUTIL_sys_up_time();
405
memcpy(&body->previous_bucket.EthData, &newSample,
406
sizeof(ETH_STATS_T));
410
* Control Table RowApi Callbacks
414
history_Create(RMON_ENTRY_T * eptr)
415
{ /* create the body: alloc it and set defaults */
418
eptr->body = AGMALLOC(sizeof(CRTL_ENTRY_T));
421
body = (CRTL_ENTRY_T *) eptr->body;
426
body->interval = HIST_DEF_INTERVAL;
428
memcpy(&body->data_source, &DEFAULT_DATA_SOURCE, sizeof(VAR_OID_T));
430
ROWDATAAPI_init(&body->scrlr, HIST_DEF_BUCK_REQ,
431
MAX_BUCKETS_IN_CRTL_ENTRY, sizeof(DATA_ENTRY_T), NULL);
437
history_Validate(RMON_ENTRY_T * eptr)
440
* T.B.D. (system dependent) check valid inteface in body->data_source;
446
history_Activate(RMON_ENTRY_T * eptr)
448
CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr->body;
450
body->coeff = 100000L * (long) body->interval;
452
ROWDATAAPI_set_size(&body->scrlr,
453
body->scrlr.data_requested,
454
(u_char)(RMON1_ENTRY_VALID == eptr->status) );
456
SYSTEM_get_eth_statistics(&body->data_source,
457
&body->previous_bucket.EthData);
458
body->previous_bucket.start_interval = AGUTIL_sys_up_time();
460
body->scrlr.current_data_ptr = body->scrlr.first_data_ptr;
462
* ag_trace ("Dbg: registered in history_Activate");
464
body->timer_id = snmp_alarm_register(body->interval, SA_REPEAT,
465
history_get_backet, eptr);
470
history_Deactivate(RMON_ENTRY_T * eptr)
472
CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr->body;
474
snmp_alarm_unregister(body->timer_id);
476
* ag_trace ("Dbg: unregistered in history_Deactivate timer_id=%d",
477
* (int) body->timer_id);
483
ROWDATAAPI_descructor(&body->scrlr);
489
history_Copy(RMON_ENTRY_T * eptr)
491
CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr->body;
492
CRTL_ENTRY_T *clone = (CRTL_ENTRY_T *) eptr->tmp;
494
if (body->scrlr.data_requested != clone->scrlr.data_requested) {
495
ROWDATAAPI_set_size(&body->scrlr, clone->scrlr.data_requested,
496
(u_char)(RMON1_ENTRY_VALID == eptr->status) );
499
if (body->interval != clone->interval) {
500
if (RMON1_ENTRY_VALID == eptr->status) {
501
snmp_alarm_unregister(body->timer_id);
503
snmp_alarm_register(clone->interval, SA_REPEAT,
504
history_get_backet, eptr);
507
body->interval = clone->interval;
511
(clone->data_source.objid, clone->data_source.length,
512
body->data_source.objid, body->data_source.length)) {
513
memcpy(&body->data_source, &clone->data_source, sizeof(VAR_OID_T));
520
history_extract_scroller(void *v_body)
522
CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) v_body;
527
* var_etherHistoryTable():
530
var_etherHistoryTable(struct variable *vp,
534
size_t * var_len, WriteMethod ** write_method)
536
static long long_ret;
537
static DATA_ENTRY_T theBucket;
541
*write_method = NULL;
542
hdr = ROWDATAAPI_header_DataEntry(vp, name, length, exact, var_len,
544
&history_extract_scroller,
545
sizeof(DATA_ENTRY_T), &theBucket);
549
*var_len = sizeof(long); /* default */
551
ctrl = (CRTL_ENTRY_T *) hdr->body;
555
long_ret = hdr->ctrl_index;
556
return (unsigned char *) &long_ret;
557
case DATA_SAMPLEINDEX:
558
long_ret = theBucket.data_index;
559
return (unsigned char *) &long_ret;
560
case DATA_INTERVALSTART:
562
return (unsigned char *) &theBucket.start_interval;
563
case DATA_DROPEVENTS:
565
return (unsigned char *) &long_ret;
568
return (unsigned char *) &theBucket.EthData.octets;
571
return (unsigned char *) &theBucket.EthData.packets;
572
case DATA_BROADCASTPKTS:
574
return (unsigned char *) &theBucket.EthData.bcast_pkts;
575
case DATA_MULTICASTPKTS:
577
return (unsigned char *) &theBucket.EthData.mcast_pkts;
578
case DATA_CRCALIGNERRORS:
580
return (unsigned char *) &theBucket.EthData.crc_align;
581
case DATA_UNDERSIZEPKTS:
583
return (unsigned char *) &theBucket.EthData.undersize;
584
case DATA_OVERSIZEPKTS:
586
return (unsigned char *) &theBucket.EthData.oversize;
589
return (unsigned char *) &theBucket.EthData.fragments;
592
return (unsigned char *) &theBucket.EthData.jabbers;
593
case DATA_COLLISIONS:
595
return (unsigned char *) &theBucket.EthData.collisions;
596
case DATA_UTILIZATION:
598
return (unsigned char *) &theBucket.utilization;
600
ag_trace("etherHistoryTable: unknown vp->magic=%d",
607
#if 1 /* debug, but may be used for init. TBD: may be token snmpd.conf ? */
609
add_hist_entry(int ctrl_index, int ifIndex,
610
u_long interval, u_long requested)
612
register RMON_ENTRY_T *eptr;
613
register CRTL_ENTRY_T *body;
616
ierr = ROWAPI_new(table_ptr, ctrl_index);
618
ag_trace("ROWAPI_new failed with %d", ierr);
622
eptr = ROWAPI_find(table_ptr, ctrl_index);
624
ag_trace("ROWAPI_find failed");
628
body = (CRTL_ENTRY_T *) eptr->body;
634
body->data_source.objid[body->data_source.length - 1] = ifIndex;
635
body->interval = interval;
636
body->scrlr.data_requested = requested;
638
eptr->new_status = RMON1_ENTRY_VALID;
639
ierr = ROWAPI_commit(table_ptr, ctrl_index);
641
ag_trace("ROWAPI_commit failed with %d", ierr);
651
* Registration & Initializatio section
654
oid historyControlTable_variables_oid[] =
655
{ 1, 3, 6, 1, 2, 1, 16, 2, 1 };
657
struct variable2 historyControlTable_variables[] = {
659
* magic number , variable type, ro/rw , callback fn , L, oidsuffix
661
{CTRL_INDEX, ASN_INTEGER, RONLY, var_historyControlTable, 2, {1, 1}},
662
{CTRL_DATASOURCE, ASN_OBJECT_ID, RWRITE, var_historyControlTable, 2,
664
{CTRL_BUCKETSREQUESTED, ASN_INTEGER, RWRITE, var_historyControlTable,
666
{CTRL_BUCKETSGRANTED, ASN_INTEGER, RONLY, var_historyControlTable, 2,
668
{CTRL_INTERVAL, ASN_INTEGER, RWRITE, var_historyControlTable, 2,
670
{CTRL_OWNER, ASN_OCTET_STR, RWRITE, var_historyControlTable, 2,
672
{CTRL_STATUS, ASN_INTEGER, RWRITE, var_historyControlTable, 2, {1, 7}},
676
oid etherHistoryTable_variables_oid[] =
677
{ 1, 3, 6, 1, 2, 1, 16, 2, 2 };
679
struct variable2 etherHistoryTable_variables[] = {
681
* magic number , variable type , ro/rw , callback fn , L, oidsuffix
683
{DATA_INDEX, ASN_INTEGER, RONLY, var_etherHistoryTable, 2, {1, 1}},
684
{DATA_SAMPLEINDEX, ASN_INTEGER, RONLY, var_etherHistoryTable, 2,
686
{DATA_INTERVALSTART, ASN_TIMETICKS, RONLY, var_etherHistoryTable, 2,
688
{DATA_DROPEVENTS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
690
{DATA_OCTETS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2, {1, 5}},
691
{DATA_PKTS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2, {1, 6}},
692
{DATA_BROADCASTPKTS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
694
{DATA_MULTICASTPKTS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
696
{DATA_CRCALIGNERRORS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
698
{DATA_UNDERSIZEPKTS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
700
{DATA_OVERSIZEPKTS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
702
{DATA_FRAGMENTS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
704
{DATA_JABBERS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2, {1, 13}},
705
{DATA_COLLISIONS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
707
{DATA_UTILIZATION, ASN_INTEGER, RONLY, var_etherHistoryTable, 2,
715
REGISTER_MIB("historyControlTable", historyControlTable_variables,
716
variable2, historyControlTable_variables_oid);
717
REGISTER_MIB("etherHistoryTable", etherHistoryTable_variables,
718
variable2, etherHistoryTable_variables_oid);
720
ROWAPI_init_table(&HistoryCtrlTable, "History", 0, &history_Create, NULL, /* &history_Clone, */
721
NULL, /* &history_Delete, */
724
&history_Deactivate, &history_Copy);
727
* add_hist_entry (2, 3, 4, 2);