and added files
[bcm963xx.git] / userapps / opensource / net-snmp / agent / mibgroup / Rmon / statistics.c
1 /**************************************************************
2  * Copyright (C) 2001 Tali Rozin, Optical Access
3  *
4  *                     All Rights Reserved
5  *
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.
11  *
12  * TALI 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
18  * SOFTWARE.
19  ******************************************************************/
20
21 #include <stdlib.h>
22 #include <sys/time.h>
23 #include <unistd.h>
24 #include <net-snmp/net-snmp-config.h>
25 #include <net-snmp/net-snmp-includes.h>
26 #include <net-snmp/agent/net-snmp-agent-includes.h>
27 #include "util_funcs.h"
28 #include "statistics.h"
29         /*
30          * Implementation headers 
31          */
32 #include "agutil_api.h"
33 #include "row_api.h"
34         /*
35          * File scope definitions section 
36          */
37         /*
38          * from MIB compilation 
39          */
40 #define MIB_DESCR       "EthStat"
41 #define etherStatsEntryFirstIndexBegin  11
42 #define IDetherStatsDroppedFrames        1
43 #define IDetherStatsCreateTime           2
44 #define IDetherStatsIndex                3
45 #define IDetherStatsDataSource           4
46 #define IDetherStatsDropEvents           5
47 #define IDetherStatsOctets               6
48 #define IDetherStatsPkts                 7
49 #define IDetherStatsBroadcastPkts        8
50 #define IDetherStatsMulticastPkts        9
51 #define IDetherStatsCRCAlignErrors       10
52 #define IDetherStatsUndersizePkts        11
53 #define IDetherStatsOversizePkts         12
54 #define IDetherStatsFragments            13
55 #define IDetherStatsJabbers              14
56 #define IDetherStatsCollisions           15
57 #define IDetherStatsPkts64Octets         16
58 #define IDetherStatsPkts65to127Octets    17
59 #define IDetherStatsPkts128to255Octets   18
60 #define IDetherStatsPkts256to511Octets   19
61 #define IDetherStatsPkts512to1023Octets  20
62 #define IDetherStatsPkts1024to1518Octets 21
63 #define IDetherStatsOwner                22
64 #define IDetherStatsStatus               23
65 #define Leaf_etherStatsDataSource        2
66 #define Leaf_etherStatsOwner             20
67 #define Leaf_etherStatsStatus            21
68 #define MIN_etherStatsIndex   1
69 #define MAX_etherStatsIndex   65535
70      typedef struct {
71          VAR_OID_T
72              data_source;
73          u_long
74              etherStatsCreateTime;
75          ETH_STATS_T
76              eth;
77      } CRTL_ENTRY_T;
78
79 /*
80  * Main section 
81  */
82
83      static TABLE_DEFINTION_T
84          StatCtrlTable;
85      static TABLE_DEFINTION_T *
86          table_ptr = &
87          StatCtrlTable;
88
89 /*
90  * Control Table RowApi Callbacks 
91  */
92
93      int
94      stat_Create(RMON_ENTRY_T * eptr)
95 {                               /* create the body: alloc it and set defaults */
96     CRTL_ENTRY_T   *body;
97     static VAR_OID_T data_src_if_index_1 =
98         { 11, {1, 3, 6, 1, 2, 1, 2, 2, 1, 1, 1} };
99
100     eptr->body = AGMALLOC(sizeof(CRTL_ENTRY_T));
101     if (!eptr->body)
102         return -3;
103     body = (CRTL_ENTRY_T *) eptr->body;
104
105     /*
106      * set defaults 
107      */
108     memcpy(&body->data_source, &data_src_if_index_1, sizeof(VAR_OID_T));
109     body->data_source.objid[body->data_source.length - 1] =
110         eptr->ctrl_index;
111     eptr->owner = AGSTRDUP("Startup Mgmt");
112     memset(&body->eth, 0, sizeof(ETH_STATS_T));
113
114     return 0;
115 }
116
117 int
118 stat_Validate(RMON_ENTRY_T * eptr)
119 {
120     /*
121      * T.B.D. (system dependent) check valid inteface in body->data_source; 
122      */
123
124     return 0;
125 }
126
127 int
128 stat_Activate(RMON_ENTRY_T * eptr)
129 {
130     CRTL_ENTRY_T   *body = (CRTL_ENTRY_T *) eptr->body;
131
132     body->etherStatsCreateTime = AGUTIL_sys_up_time();
133
134     return 0;
135 }
136
137 int
138 stat_Copy(RMON_ENTRY_T * eptr)
139 {
140     CRTL_ENTRY_T   *body = (CRTL_ENTRY_T *) eptr->body;
141     CRTL_ENTRY_T   *clone = (CRTL_ENTRY_T *) eptr->tmp;
142
143     if (snmp_oid_compare
144         (clone->data_source.objid, clone->data_source.length,
145          body->data_source.objid, body->data_source.length)) {
146         memcpy(&body->data_source, &clone->data_source, sizeof(VAR_OID_T));
147     }
148
149     return 0;
150 }
151
152 int
153 stat_Deactivate(RMON_ENTRY_T * eptr)
154 {
155     CRTL_ENTRY_T   *body = (CRTL_ENTRY_T *) eptr->body;
156     memset(&body->eth, 0, sizeof(ETH_STATS_T));
157     return 0;
158 }
159
160
161 /***************************************************
162  * Function:var_etherStats2Entry 
163  * Purpose: Handles the request for etherStats2Entry variable instances
164  ***************************************************/
165 u_char         *
166 var_etherStats2Entry(struct variable * vp, oid * name, size_t * length,
167                      int exact, size_t * var_len,
168                      WriteMethod ** write_method)
169 {
170     static long     long_return;
171     static CRTL_ENTRY_T theEntry;
172     RMON_ENTRY_T   *hdr;
173
174     *write_method = NULL;
175
176     hdr = ROWAPI_header_ControlEntry(vp, name, length, exact, var_len,
177                                      table_ptr,
178                                      &theEntry, sizeof(CRTL_ENTRY_T));
179     if (!hdr)
180         return NULL;
181
182     *var_len = sizeof(long);    /* default */
183
184     switch (vp->magic) {
185     case IDetherStatsDroppedFrames:
186         long_return = 0;
187         return (u_char *) & long_return;
188     case IDetherStatsCreateTime:
189         long_return = theEntry.etherStatsCreateTime;
190         return (u_char *) & long_return;
191     default:
192         ag_trace("%s: unknown vp->magic=%d", table_ptr->name,
193                  (int) vp->magic);
194         ERROR_MSG("");
195     };                          /* of switch by 'vp->magic'  */
196
197     return NULL;
198 }
199
200
201 /***************************************************
202  * Function:write_etherStatsEntry 
203  ***************************************************/
204 static int
205 write_etherStatsEntry(int action, u_char * var_val, u_char var_val_type,
206                       size_t var_val_len, u_char * statP,
207                       oid * name, size_t name_len)
208 {
209     long            long_temp;
210     int             leaf_id, snmp_status;
211     static int      prev_action = COMMIT;
212     RMON_ENTRY_T   *hdr;
213     CRTL_ENTRY_T   *cloned_body;
214     CRTL_ENTRY_T   *body;
215
216     switch (action) {
217     case RESERVE1:
218     case FREE:
219     case UNDO:
220     case ACTION:
221     case COMMIT:
222     default:
223         snmp_status =
224             ROWAPI_do_another_action(name, etherStatsEntryFirstIndexBegin,
225                                      action, &prev_action, table_ptr,
226                                      sizeof(CRTL_ENTRY_T));
227         if (SNMP_ERR_NOERROR != snmp_status) {
228             ag_trace("failed action %d with %d", action, snmp_status);
229         }
230         break;
231
232     case RESERVE2:
233         /*
234          * get values from PDU, check them and save them in the cloned entry 
235          */
236         long_temp = name[etherStatsEntryFirstIndexBegin];
237         leaf_id = (int) name[etherStatsEntryFirstIndexBegin - 1];
238         hdr = ROWAPI_find(table_ptr, long_temp);        /* it MUST be OK */
239         cloned_body = (CRTL_ENTRY_T *) hdr->tmp;
240         body = (CRTL_ENTRY_T *) hdr->body;
241         switch (leaf_id) {
242         case Leaf_etherStatsDataSource:
243             snmp_status = AGUTIL_get_oid_value(var_val, var_val_type,
244                                                var_val_len,
245                                                &cloned_body->data_source);
246             if (SNMP_ERR_NOERROR != snmp_status) {
247                 return snmp_status;
248             }
249             if (RMON1_ENTRY_UNDER_CREATION != hdr->status &&
250                 snmp_oid_compare(cloned_body->data_source.objid,
251                                  cloned_body->data_source.length,
252                                  body->data_source.objid,
253                                  body->data_source.length))
254                 return SNMP_ERR_BADVALUE;
255             break;
256
257             break;
258         case Leaf_etherStatsOwner:
259             if (hdr->new_owner)
260                 AGFREE(hdr->new_owner);
261             hdr->new_owner = AGMALLOC(MAX_OWNERSTRING);;
262             if (!hdr->new_owner)
263                 return SNMP_ERR_TOOBIG;
264             snmp_status = AGUTIL_get_string_value(var_val, var_val_type,
265                                                   var_val_len,
266                                                   MAX_OWNERSTRING,
267                                                   1, NULL, hdr->new_owner);
268             if (SNMP_ERR_NOERROR != snmp_status) {
269                 return snmp_status;
270             }
271             break;
272         case Leaf_etherStatsStatus:
273             snmp_status = AGUTIL_get_int_value(var_val, var_val_type,
274                                                var_val_len,
275                                                RMON1_ENTRY_VALID,
276                                                RMON1_ENTRY_INVALID,
277                                                &long_temp);
278             if (SNMP_ERR_NOERROR != snmp_status) {
279                 ag_trace("cannot browse etherStatsStatus");
280                 return snmp_status;
281             }
282             hdr->new_status = long_temp;
283             break;
284             break;
285         default:
286             ag_trace("%s:unknown leaf_id=%d\n", table_ptr->name,
287                      (int) leaf_id);
288             return SNMP_ERR_NOSUCHNAME;
289         }                       /* of switch by 'leaf_id' */
290         break;
291     }                           /* of switch by 'action' */
292
293     prev_action = action;
294     return SNMP_ERR_NOERROR;
295 }
296
297 /***************************************************
298  * Function:var_etherStatsEntry 
299  * Purpose: Handles the request for etherStatsEntry variable instances
300  ***************************************************/
301 u_char         *
302 var_etherStatsEntry(struct variable * vp, oid * name, size_t * length,
303                     int exact, size_t * var_len,
304                     WriteMethod ** write_method)
305 {
306     static long     long_return;
307     static CRTL_ENTRY_T theEntry;
308     RMON_ENTRY_T   *hdr;
309
310     *write_method = write_etherStatsEntry;
311     hdr = ROWAPI_header_ControlEntry(vp, name, length, exact, var_len,
312                                      table_ptr,
313                                      &theEntry, sizeof(CRTL_ENTRY_T));
314     if (!hdr)
315         return NULL;
316
317     if (RMON1_ENTRY_VALID == hdr->status)
318         SYSTEM_get_eth_statistics(&theEntry.data_source, &theEntry.eth);
319
320     *var_len = sizeof(long);
321
322     switch (vp->magic) {
323     case IDetherStatsIndex:
324         long_return = hdr->ctrl_index;
325         return (u_char *) & long_return;
326     case IDetherStatsDataSource:
327         *var_len = sizeof(oid) * theEntry.data_source.length;
328         return (unsigned char *) theEntry.data_source.objid;
329     case IDetherStatsDropEvents:
330         long_return = 0;        /* theEntry.eth.etherStatsDropEvents; */
331         return (u_char *) & long_return;
332     case IDetherStatsOctets:
333         long_return = theEntry.eth.octets;
334         return (u_char *) & long_return;
335     case IDetherStatsPkts:
336         long_return = theEntry.eth.packets;
337         return (u_char *) & long_return;
338     case IDetherStatsBroadcastPkts:
339         long_return = theEntry.eth.bcast_pkts;
340         return (u_char *) & long_return;
341     case IDetherStatsMulticastPkts:
342         long_return = theEntry.eth.mcast_pkts;
343         return (u_char *) & long_return;
344     case IDetherStatsCRCAlignErrors:
345         long_return = theEntry.eth.crc_align;
346         return (u_char *) & long_return;
347     case IDetherStatsUndersizePkts:
348         long_return = theEntry.eth.undersize;
349         return (u_char *) & long_return;
350     case IDetherStatsOversizePkts:
351         long_return = theEntry.eth.oversize;
352         return (u_char *) & long_return;
353     case IDetherStatsFragments:
354         long_return = theEntry.eth.fragments;
355         return (u_char *) & long_return;
356     case IDetherStatsJabbers:
357         long_return = theEntry.eth.jabbers;
358         return (u_char *) & long_return;
359     case IDetherStatsCollisions:
360         long_return = theEntry.eth.collisions;
361         return (u_char *) & long_return;
362     case IDetherStatsPkts64Octets:
363         long_return = theEntry.eth.pkts_64;
364         return (u_char *) & long_return;
365     case IDetherStatsPkts65to127Octets:
366         long_return = theEntry.eth.pkts_65_127;
367         return (u_char *) & long_return;
368     case IDetherStatsPkts128to255Octets:
369         long_return = theEntry.eth.pkts_128_255;
370         return (u_char *) & long_return;
371     case IDetherStatsPkts256to511Octets:
372         long_return = theEntry.eth.pkts_256_511;
373         return (u_char *) & long_return;
374     case IDetherStatsPkts512to1023Octets:
375         long_return = theEntry.eth.pkts_512_1023;
376         return (u_char *) & long_return;
377     case IDetherStatsPkts1024to1518Octets:
378         long_return = theEntry.eth.pkts_1024_1518;
379         return (u_char *) & long_return;
380     case IDetherStatsOwner:
381         if (hdr->owner) {
382             *var_len = strlen(hdr->owner);
383             return (unsigned char *) hdr->owner;
384         } else {
385             *var_len = 0;
386             return (unsigned char *) "";
387         }
388     case IDetherStatsStatus:
389         long_return = hdr->status;
390         return (u_char *) & long_return;
391     default:
392         ERROR_MSG("");
393     };                          /* of switch by 'vp->magic'  */
394
395     return NULL;
396 }
397
398 #if 1                           /* debug, but may be used for init. TBD: may be token snmpd.conf ? */
399 int
400 add_statistics_entry(int ctrl_index, int ifIndex)
401 {
402     int             ierr;
403
404     ierr = ROWAPI_new(table_ptr, ctrl_index);
405     switch (ierr) {
406     case -1:
407         ag_trace("max. number exedes\n");
408         break;
409     case -2:
410         ag_trace("malloc failed");
411         break;
412     case -3:
413         ag_trace("ClbkCreate failed");
414         break;
415     case 0:
416         break;
417     default:
418         ag_trace("Unknown code %d", ierr);
419         break;
420     }
421
422     if (!ierr) {
423         register RMON_ENTRY_T *eptr = ROWAPI_find(table_ptr, ctrl_index);
424         if (!eptr) {
425             ag_trace("cannot find it");
426             ierr = -4;
427         } else {
428             CRTL_ENTRY_T   *body = (CRTL_ENTRY_T *) eptr->body;
429
430             body->data_source.objid[body->data_source.length - 1] =
431                 ifIndex;
432
433             eptr->new_status = RMON1_ENTRY_VALID;
434             ierr = ROWAPI_commit(table_ptr, ctrl_index);
435             if (ierr) {
436                 ag_trace("ROWAPI_commit returned %d", ierr);
437             }
438         }
439     }
440
441     return ierr;
442 }
443 #endif
444
445 /***************************************************
446  * define Variables callbacks 
447  ***************************************************/
448 oid             oidstatisticsVariablesOid[] = { 1, 3, 6, 1, 2, 1, 16, 1 };
449
450 struct variable7 oidstatisticsVariables[] = {
451     {IDetherStatsIndex, ASN_INTEGER, RONLY, var_etherStatsEntry, 3,
452      {1, 1, 1}},
453     {IDetherStatsDataSource, ASN_OBJECT_ID, RWRITE, var_etherStatsEntry, 3,
454      {1, 1, 2}},
455     {IDetherStatsDropEvents, ASN_COUNTER, RONLY, var_etherStatsEntry, 3,
456      {1, 1, 3}},
457     {IDetherStatsOctets, ASN_COUNTER, RONLY, var_etherStatsEntry, 3,
458      {1, 1, 4}},
459     {IDetherStatsPkts, ASN_COUNTER, RONLY, var_etherStatsEntry, 3,
460      {1, 1, 5}},
461     {IDetherStatsBroadcastPkts, ASN_COUNTER, RONLY, var_etherStatsEntry, 3,
462      {1, 1, 6}},
463     {IDetherStatsMulticastPkts, ASN_COUNTER, RONLY, var_etherStatsEntry, 3,
464      {1, 1, 7}},
465     {IDetherStatsCRCAlignErrors, ASN_COUNTER, RONLY, var_etherStatsEntry,
466      3, {1, 1, 8}},
467     {IDetherStatsUndersizePkts, ASN_COUNTER, RONLY, var_etherStatsEntry, 3,
468      {1, 1, 9}},
469     {IDetherStatsOversizePkts, ASN_COUNTER, RONLY, var_etherStatsEntry, 3,
470      {1, 1, 10}},
471     {IDetherStatsFragments, ASN_COUNTER, RONLY, var_etherStatsEntry, 3,
472      {1, 1, 11}},
473     {IDetherStatsJabbers, ASN_COUNTER, RONLY, var_etherStatsEntry, 3,
474      {1, 1, 12}},
475     {IDetherStatsCollisions, ASN_COUNTER, RONLY, var_etherStatsEntry, 3,
476      {1, 1, 13}},
477     {IDetherStatsPkts64Octets, ASN_COUNTER, RONLY, var_etherStatsEntry, 3,
478      {1, 1, 14}},
479     {IDetherStatsPkts65to127Octets, ASN_COUNTER, RONLY,
480      var_etherStatsEntry, 3, {1, 1, 15}},
481     {IDetherStatsPkts128to255Octets, ASN_COUNTER, RONLY,
482      var_etherStatsEntry, 3, {1, 1, 16}},
483     {IDetherStatsPkts256to511Octets, ASN_COUNTER, RONLY,
484      var_etherStatsEntry, 3, {1, 1, 17}},
485     {IDetherStatsPkts512to1023Octets, ASN_COUNTER, RONLY,
486      var_etherStatsEntry, 3, {1, 1, 18}},
487     {IDetherStatsPkts1024to1518Octets, ASN_COUNTER, RONLY,
488      var_etherStatsEntry, 3, {1, 1, 19}},
489     {IDetherStatsOwner, ASN_OCTET_STR, RWRITE, var_etherStatsEntry, 3,
490      {1, 1, 20}},
491     {IDetherStatsStatus, ASN_INTEGER, RWRITE, var_etherStatsEntry, 3,
492      {1, 1, 21}},
493     {IDetherStatsDroppedFrames, ASN_COUNTER, RONLY, var_etherStats2Entry,
494      3, {4, 1, 1}},
495     {IDetherStatsCreateTime, ASN_TIMETICKS, RONLY, var_etherStats2Entry, 3,
496      {4, 1, 2}},
497 };
498
499 /***************************************************
500  * Function:init_statistics 
501  * Purpose: register statistics objects in the agent 
502  ***************************************************/
503 void
504 init_statistics(void)
505 {
506     REGISTER_MIB(MIB_DESCR, oidstatisticsVariables, variable7,
507                  oidstatisticsVariablesOid);
508
509     ROWAPI_init_table(&StatCtrlTable, MIB_DESCR, 0, &stat_Create, NULL, /* &stat_Clone, */
510                       NULL,     /* &stat_Delete, */
511                       &stat_Validate,
512                       &stat_Activate, &stat_Deactivate, &stat_Copy);
513
514 #if 0                           /* debug */
515     {
516         int             iii;
517         for (iii = 1; iii < 6; iii++) {
518             add_statistics_entry(iii, iii);
519         }
520
521         add_statistics_entry(10, 16);
522         add_statistics_entry(12, 11);
523     }
524 #endif
525 }
526
527 /*
528  * end of file statistics.c 
529  */