print-sflow.c revision 190203
1/*
2 * Copyright (c) 1998-2007 The TCPDUMP project
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that: (1) source code
6 * distributions retain the above copyright notice and this paragraph
7 * in its entirety, and (2) distributions including binary code include
8 * the above copyright notice and this paragraph in its entirety in
9 * the documentation or other materials provided with the distribution.
10 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
11 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
12 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13 * FOR A PARTICULAR PURPOSE.
14 *
15 * The SFLOW protocol as per http://www.sflow.org/developers/specifications.php
16 *
17 * Original code by Carles Kishimoto <carles.kishimoto@gmail.com>
18 */
19
20#ifndef lint
21static const char rcsid[] _U_ =
22"@(#) $Header: /tcpdump/master/tcpdump/print-sflow.c,v 1.1 2007-08-08 17:20:58 hannes Exp $";
23#endif
24
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#include <tcpdump-stdinc.h>
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34
35#include "interface.h"
36#include "extract.h"
37#include "addrtoname.h"
38
39/*
40 * sFlow datagram
41 *
42 * 0                   1                   2                   3
43 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
44 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45 * |                     Sflow version (2,4,5)                     |
46 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47 * |               IP version (1 for IPv4 | 2 for IPv6)            |
48 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49 * |                     IP Address AGENT (4 or 16 bytes)          |
50 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51 * |                          Sub agent ID                         |
52 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53 * |                      Datagram sequence number                 |
54 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55 * |                      Switch uptime in ms                      |
56 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57 * |                    num samples in datagram                    |
58 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59 *
60 */
61
62struct sflow_datagram_t {
63    u_int8_t 	version[4];
64    u_int8_t 	ip_version[4];
65    u_int8_t 	agent[4];
66    u_int8_t 	agent_id[4];
67    u_int8_t 	seqnum[4];
68    u_int8_t 	uptime[4];
69    u_int8_t 	samples[4];
70};
71
72struct sflow_sample_header {
73    u_int8_t	format[4];
74    u_int8_t	len[4];
75};
76
77#define		SFLOW_FLOW_SAMPLE		1
78#define		SFLOW_COUNTER_SAMPLE		2
79#define		SFLOW_EXPANDED_FLOW_SAMPLE	3
80#define		SFLOW_EXPANDED_COUNTER_SAMPLE	4
81
82static const struct tok sflow_format_values[] = {
83    { SFLOW_FLOW_SAMPLE, "flow sample" },
84    { SFLOW_COUNTER_SAMPLE, "counter sample" },
85    { SFLOW_EXPANDED_FLOW_SAMPLE, "expanded flow sample" },
86    { SFLOW_EXPANDED_COUNTER_SAMPLE, "expanded counter sample" },
87    { 0, NULL}
88};
89
90struct sflow_expanded_flow_sample_t {
91    u_int8_t    seqnum[4];
92    u_int8_t    type[4];
93    u_int8_t    index[4];
94    u_int8_t    rate[4];
95    u_int8_t    pool[4];
96    u_int8_t    drops[4];
97    u_int8_t    in_interface_format[4];
98    u_int8_t    in_interface_value[4];
99    u_int8_t    out_interface_format[4];
100    u_int8_t    out_interface_value[4];
101    u_int8_t    records[4];
102};
103
104#define 	SFLOW_FLOW_RAW_PACKET			1
105#define 	SFLOW_FLOW_ETHERNET_FRAME		2
106#define 	SFLOW_FLOW_IPV4_DATA			3
107#define 	SFLOW_FLOW_IPV6_DATA			4
108#define 	SFLOW_FLOW_EXTENDED_SWITCH_DATA		1001
109#define 	SFLOW_FLOW_EXTENDED_ROUTER_DATA		1002
110#define 	SFLOW_FLOW_EXTENDED_GATEWAY_DATA 	1003
111#define 	SFLOW_FLOW_EXTENDED_USER_DATA		1004
112#define 	SFLOW_FLOW_EXTENDED_URL_DATA		1005
113#define 	SFLOW_FLOW_EXTENDED_MPLS_DATA		1006
114#define 	SFLOW_FLOW_EXTENDED_NAT_DATA		1007
115#define 	SFLOW_FLOW_EXTENDED_MPLS_TUNNEL		1008
116#define 	SFLOW_FLOW_EXTENDED_MPLS_VC		1009
117#define 	SFLOW_FLOW_EXTENDED_MPLS_FEC		1010
118#define 	SFLOW_FLOW_EXTENDED_MPLS_LVP_FEC	1011
119#define 	SFLOW_FLOW_EXTENDED_VLAN_TUNNEL		1012
120
121static const struct tok sflow_flow_type_values[] = {
122    { SFLOW_FLOW_RAW_PACKET, "Raw packet"},
123    { SFLOW_FLOW_ETHERNET_FRAME, "Ethernet frame"},
124    { SFLOW_FLOW_IPV4_DATA, "IPv4 Data"},
125    { SFLOW_FLOW_IPV6_DATA, "IPv6 Data"},
126    { SFLOW_FLOW_EXTENDED_SWITCH_DATA, "Extended Switch data"},
127    { SFLOW_FLOW_EXTENDED_ROUTER_DATA, "Extended Router data"},
128    { SFLOW_FLOW_EXTENDED_GATEWAY_DATA, "Extended Gateway data"},
129    { SFLOW_FLOW_EXTENDED_USER_DATA, "Extended User data"},
130    { SFLOW_FLOW_EXTENDED_URL_DATA, "Extended URL data"},
131    { SFLOW_FLOW_EXTENDED_MPLS_DATA, "Extended MPLS data"},
132    { SFLOW_FLOW_EXTENDED_NAT_DATA, "Extended NAT data"},
133    { SFLOW_FLOW_EXTENDED_MPLS_TUNNEL, "Extended MPLS tunnel"},
134    { SFLOW_FLOW_EXTENDED_MPLS_VC, "Extended MPLS VC"},
135    { SFLOW_FLOW_EXTENDED_MPLS_FEC, "Extended MPLS FEC"},
136    { SFLOW_FLOW_EXTENDED_MPLS_LVP_FEC, "Extended MPLS LVP FEC"},
137    { SFLOW_FLOW_EXTENDED_VLAN_TUNNEL, "Extended VLAN Tunnel"},
138    { 0, NULL}
139};
140
141#define		SFLOW_HEADER_PROTOCOL_ETHERNET	1
142#define		SFLOW_HEADER_PROTOCOL_IPV4	11
143#define		SFLOW_HEADER_PROTOCOL_IPV6	12
144
145static const struct tok sflow_flow_raw_protocol_values[] = {
146    { SFLOW_HEADER_PROTOCOL_ETHERNET, "Ethernet"},
147    { SFLOW_HEADER_PROTOCOL_IPV4, "IPv4"},
148    { SFLOW_HEADER_PROTOCOL_IPV6, "IPv6"},
149    { 0, NULL}
150};
151
152struct sflow_expanded_flow_raw_t {
153    u_int8_t    protocol[4];
154    u_int8_t    length[4];
155    u_int8_t    stripped_bytes[4];
156    u_int8_t    header_size[4];
157};
158
159struct sflow_expanded_counter_sample_t {
160    u_int8_t    seqnum[4];
161    u_int8_t    type[4];
162    u_int8_t    index[4];
163    u_int8_t    records[4];
164};
165
166#define         SFLOW_COUNTER_GENERIC           1
167#define         SFLOW_COUNTER_ETHERNET          2
168#define         SFLOW_COUNTER_TOKEN_RING        3
169#define         SFLOW_COUNTER_BASEVG            4
170#define         SFLOW_COUNTER_VLAN              5
171#define         SFLOW_COUNTER_PROCESSOR         1001
172
173static const struct tok sflow_counter_type_values[] = {
174    { SFLOW_COUNTER_GENERIC, "Generic counter"},
175    { SFLOW_COUNTER_ETHERNET, "Ethernet counter"},
176    { SFLOW_COUNTER_TOKEN_RING, "Token ring counter"},
177    { SFLOW_COUNTER_BASEVG, "100 BaseVG counter"},
178    { SFLOW_COUNTER_VLAN, "Vlan counter"},
179    { SFLOW_COUNTER_PROCESSOR, "Processor counter"},
180    { 0, NULL}
181};
182
183#define		SFLOW_IFACE_DIRECTION_UNKNOWN		0
184#define		SFLOW_IFACE_DIRECTION_FULLDUPLEX	1
185#define		SFLOW_IFACE_DIRECTION_HALFDUPLEX	2
186#define		SFLOW_IFACE_DIRECTION_IN		3
187#define		SFLOW_IFACE_DIRECTION_OUT		4
188
189static const struct tok sflow_iface_direction_values[] = {
190    { SFLOW_IFACE_DIRECTION_UNKNOWN, "unknown"},
191    { SFLOW_IFACE_DIRECTION_FULLDUPLEX, "full-duplex"},
192    { SFLOW_IFACE_DIRECTION_HALFDUPLEX, "half-duplex"},
193    { SFLOW_IFACE_DIRECTION_IN, "in"},
194    { SFLOW_IFACE_DIRECTION_OUT, "out"},
195    { 0, NULL}
196};
197
198struct sflow_generic_counter_t {
199    u_int8_t    ifindex[4];
200    u_int8_t    iftype[4];
201    u_int8_t    ifspeed[8];
202    u_int8_t    ifdirection[4];
203    u_int8_t    ifstatus[4];
204    u_int8_t    ifinoctets[8];
205    u_int8_t    ifinunicastpkts[4];
206    u_int8_t    ifinmulticastpkts[4];
207    u_int8_t    ifinbroadcastpkts[4];
208    u_int8_t    ifindiscards[4];
209    u_int8_t    ifinerrors[4];
210    u_int8_t    ifinunkownprotos[4];
211    u_int8_t    ifoutoctets[8];
212    u_int8_t    ifoutunicastpkts[4];
213    u_int8_t    ifoutmulticastpkts[4];
214    u_int8_t    ifoutbroadcastpkts[4];
215    u_int8_t    ifoutdiscards[4];
216    u_int8_t    ifouterrors[4];
217    u_int8_t    ifpromiscmode[4];
218};
219
220struct sflow_ethernet_counter_t {
221    u_int8_t    alignerrors[4];
222    u_int8_t    fcserrors[4];
223    u_int8_t    single_collision_frames[4];
224    u_int8_t    multiple_collision_frames[4];
225    u_int8_t    test_errors[4];
226    u_int8_t    deferred_transmissions[4];
227    u_int8_t    late_collisions[4];
228    u_int8_t    excessive_collisions[4];
229    u_int8_t    mac_transmit_errors[4];
230    u_int8_t    carrier_sense_errors[4];
231    u_int8_t    frame_too_longs[4];
232    u_int8_t    mac_receive_errors[4];
233    u_int8_t    symbol_errors[4];
234};
235
236struct sflow_100basevg_counter_t {
237    u_int8_t    in_highpriority_frames[4];
238    u_int8_t    in_highpriority_octets[8];
239    u_int8_t    in_normpriority_frames[4];
240    u_int8_t    in_normpriority_octets[8];
241    u_int8_t    in_ipmerrors[4];
242    u_int8_t    in_oversized[4];
243    u_int8_t    in_data_errors[4];
244    u_int8_t    in_null_addressed_frames[4];
245    u_int8_t    out_highpriority_frames[4];
246    u_int8_t    out_highpriority_octets[8];
247    u_int8_t    transitioninto_frames[4];
248    u_int8_t    hc_in_highpriority_octets[8];
249    u_int8_t    hc_in_normpriority_octets[8];
250    u_int8_t    hc_out_highpriority_octets[8];
251};
252
253struct sflow_vlan_counter_t {
254    u_int8_t    vlan_id[4];
255    u_int8_t    octets[8];
256    u_int8_t    unicast_pkt[4];
257    u_int8_t    multicast_pkt[4];
258    u_int8_t    broadcast_pkt[4];
259    u_int8_t    discards[4];
260};
261
262void
263sflow_print(const u_char *pptr, u_int len) {
264
265    const struct sflow_datagram_t *sflow_datagram;
266    const struct sflow_sample_header *sflow_sample;
267    const struct sflow_expanded_flow_sample_t *sflow_expanded_flow_sample;
268    const struct sflow_expanded_flow_raw_t *sflow_flow_raw;
269    const struct sflow_expanded_counter_sample_t *sflow_expanded_counter_sample;
270    const struct sflow_generic_counter_t *sflow_gen_counter;
271    const struct sflow_ethernet_counter_t *sflow_eth_counter;
272    const struct sflow_100basevg_counter_t *sflow_100basevg_counter;
273    const struct sflow_vlan_counter_t *sflow_vlan_counter;
274    const u_char *tptr;
275    int tlen;
276    u_int32_t sflow_sample_type, sflow_sample_len;
277    int nsamples, nrecords, counter_len, counter_type, flow_len, flow_type;
278
279    tptr=pptr;
280    tlen = len;
281    sflow_datagram = (const struct sflow_datagram_t *)pptr;
282    TCHECK(*sflow_datagram);
283
284    /*
285     * Sanity checking of the header.
286     */
287    if (EXTRACT_32BITS(sflow_datagram->version) != 5) {
288        printf("sFlow version %u packet not supported",
289               EXTRACT_32BITS(sflow_datagram->version));
290        return;
291    }
292
293    if (vflag < 1) {
294        printf("sFlowv%u, %s agent %s, agent-id %u, length %u",
295               EXTRACT_32BITS(sflow_datagram->version),
296               EXTRACT_32BITS(sflow_datagram->ip_version) == 1 ? "IPv4" : "IPv6",
297	       ipaddr_string(sflow_datagram->agent),
298               EXTRACT_32BITS(sflow_datagram->samples),
299               len);
300        return;
301    }
302
303    /* ok they seem to want to know everything - lets fully decode it */
304    nsamples=EXTRACT_32BITS(sflow_datagram->samples);
305    printf("sFlowv%u, %s agent %s, agent-id %u, seqnum %u, uptime %u, samples %u, length %u",
306           EXTRACT_32BITS(sflow_datagram->version),
307           EXTRACT_32BITS(sflow_datagram->ip_version) == 1 ? "IPv4" : "IPv6",
308           ipaddr_string(sflow_datagram->agent),
309           EXTRACT_32BITS(sflow_datagram->agent_id),
310           EXTRACT_32BITS(sflow_datagram->seqnum),
311           EXTRACT_32BITS(sflow_datagram->uptime),
312           nsamples,
313           len);
314
315    /* skip Common header */
316    tptr+=sizeof(const struct sflow_datagram_t);
317    tlen-=sizeof(const struct sflow_datagram_t);
318
319    while (nsamples > 0 && tlen > 0) {
320        sflow_sample = (const struct sflow_sample_header *)tptr;
321        sflow_sample_type = (EXTRACT_32BITS(sflow_sample->format)&0x0FFF);
322        sflow_sample_len = EXTRACT_32BITS(sflow_sample->len);
323
324        tptr+=sizeof(struct sflow_sample_header);
325        tlen-=sizeof(struct sflow_sample_header);
326
327        printf("\n\t%s (%u), length %u,",
328               tok2str(sflow_format_values, "Unknown", sflow_sample_type),
329               sflow_sample_type,
330               sflow_sample_len);
331
332        /* basic sanity check */
333        if (sflow_sample_type == 0 || sflow_sample_len ==0) {
334            return;
335        }
336
337        /* did we capture enough for fully decoding the sample ? */
338        if (!TTEST2(*tptr, sflow_sample_len))
339            goto trunc;
340
341	switch(sflow_sample_type) {
342        case SFLOW_FLOW_SAMPLE:				/* XXX */
343            break;
344
345        case SFLOW_COUNTER_SAMPLE:			/* XXX */
346            break;
347
348        case SFLOW_EXPANDED_FLOW_SAMPLE:
349            sflow_expanded_flow_sample = (const struct sflow_expanded_flow_sample_t *)tptr;
350            nrecords = EXTRACT_32BITS(sflow_expanded_flow_sample->records);
351
352            printf(" seqnum %u, type %u, idx %u, rate %u, pool %u, drops %u, records %u",
353                   EXTRACT_32BITS(sflow_expanded_flow_sample->seqnum),
354                   EXTRACT_32BITS(sflow_expanded_flow_sample->type),
355                   EXTRACT_32BITS(sflow_expanded_flow_sample->index),
356                   EXTRACT_32BITS(sflow_expanded_flow_sample->rate),
357                   EXTRACT_32BITS(sflow_expanded_flow_sample->pool),
358                   EXTRACT_32BITS(sflow_expanded_flow_sample->drops),
359                   EXTRACT_32BITS(sflow_expanded_flow_sample->records));
360
361            tptr+= sizeof(struct sflow_expanded_flow_sample_t);
362            tlen-= sizeof(struct sflow_expanded_flow_sample_t);
363
364            while ( nrecords > 0 && tlen > 0) {
365
366                /* decode Flow record - 2 bytes */
367                flow_type = EXTRACT_32BITS(tptr)&0x0FFF;
368                flow_len = EXTRACT_32BITS(tptr+4);
369                printf("\n\t  %s (%u) length %u",
370                       tok2str(sflow_flow_type_values,"Unknown",flow_type),
371                       flow_type,
372                       flow_len);
373
374                tptr += 8;
375                tlen -= 8;
376
377                /* did we capture enough for fully decoding the flow ? */
378                if (!TTEST2(*tptr, flow_len))
379                    goto trunc;
380
381                switch(flow_type) {
382                case SFLOW_FLOW_RAW_PACKET:
383                    sflow_flow_raw = (const struct sflow_expanded_flow_raw_t *)tptr;
384                    printf("\n\t    protocol %s (%u), length %u, stripped bytes %u, header_size %u",
385                           tok2str(sflow_flow_raw_protocol_values,"Unknown",EXTRACT_32BITS(sflow_flow_raw->protocol)),
386                           EXTRACT_32BITS(sflow_flow_raw->protocol),
387                           EXTRACT_32BITS(sflow_flow_raw->length),
388                           EXTRACT_32BITS(sflow_flow_raw->stripped_bytes),
389                           EXTRACT_32BITS(sflow_flow_raw->header_size));
390                    break;
391
392                    /*
393                     * FIXME those are the defined flow types that lack a decoder
394                     */
395                case SFLOW_FLOW_ETHERNET_FRAME:
396                case SFLOW_FLOW_IPV4_DATA:
397                case SFLOW_FLOW_IPV6_DATA:
398                case SFLOW_FLOW_EXTENDED_SWITCH_DATA:
399                case SFLOW_FLOW_EXTENDED_ROUTER_DATA:
400                case SFLOW_FLOW_EXTENDED_GATEWAY_DATA:
401                case SFLOW_FLOW_EXTENDED_USER_DATA:
402                case SFLOW_FLOW_EXTENDED_URL_DATA:
403                case SFLOW_FLOW_EXTENDED_MPLS_DATA:
404                case SFLOW_FLOW_EXTENDED_NAT_DATA:
405                case SFLOW_FLOW_EXTENDED_MPLS_TUNNEL:
406                case SFLOW_FLOW_EXTENDED_MPLS_VC:
407                case SFLOW_FLOW_EXTENDED_MPLS_FEC:
408                case SFLOW_FLOW_EXTENDED_MPLS_LVP_FEC:
409                case SFLOW_FLOW_EXTENDED_VLAN_TUNNEL:
410                    break;
411                default:
412                    if (vflag <= 1)
413                        print_unknown_data(tptr, "\n\t      ", flow_len);
414                    break;
415
416                }
417                tptr += flow_len;
418                tlen -= flow_len;
419                nrecords--;
420            }
421            break;
422
423        case SFLOW_EXPANDED_COUNTER_SAMPLE:
424            sflow_expanded_counter_sample = (const struct sflow_expanded_counter_sample_t *)tptr;
425            nrecords = EXTRACT_32BITS(sflow_expanded_counter_sample->records);
426
427            printf(" seqnum %u, type %u, idx %u, records %u",
428                   EXTRACT_32BITS(sflow_expanded_counter_sample->seqnum),
429                   EXTRACT_32BITS(sflow_expanded_counter_sample->type),
430                   EXTRACT_32BITS(sflow_expanded_counter_sample->index),
431                   nrecords);
432
433            tptr+= sizeof(struct sflow_expanded_counter_sample_t);
434            tlen-= sizeof(struct sflow_expanded_counter_sample_t);
435
436            while ( nrecords > 0 && tlen > 0) {
437
438                /* decode counter record - 2 bytes */
439                counter_type = EXTRACT_32BITS(tptr)&0x0FFF;
440                counter_len = EXTRACT_32BITS(tptr+4);
441                printf("\n\t    %s (%u) length %u",
442                       tok2str(sflow_counter_type_values,"Unknown",counter_type),
443                       counter_type,
444                       counter_len);
445
446                tptr += 8;
447                tlen -= 8;
448
449                /* did we capture enough for fully decoding the counter ? */
450                if (!TTEST2(*tptr, counter_len))
451                    goto trunc;
452
453                switch(counter_type) {
454                case SFLOW_COUNTER_GENERIC:
455                    sflow_gen_counter = (const struct sflow_generic_counter_t *)tptr;
456                    printf("\n\t      ifindex %u, iftype %u, ifspeed %u, ifdirection %u (%s)",
457                           EXTRACT_32BITS(sflow_gen_counter->ifindex),
458                           EXTRACT_32BITS(sflow_gen_counter->iftype),
459                           EXTRACT_32BITS(sflow_gen_counter->ifspeed),
460                           EXTRACT_32BITS(sflow_gen_counter->ifdirection),
461                           tok2str(sflow_iface_direction_values, "Unknown",
462                                   EXTRACT_32BITS(sflow_gen_counter->ifdirection)));
463                    printf("\n\t      ifstatus %u, adminstatus: %s, operstatus: %s",
464                           EXTRACT_32BITS(sflow_gen_counter->ifstatus),
465                           EXTRACT_32BITS(sflow_gen_counter->ifstatus)&1 ? "up" : "down",
466                           (EXTRACT_32BITS(sflow_gen_counter->ifstatus)>>1)&1 ? "up" : "down");
467                    printf("\n\t      In octets %" PRIu64
468                           ", unicast pkts %u, multicast pkts %u, broadcast pkts %u, discards %u",
469                           EXTRACT_64BITS(sflow_gen_counter->ifinoctets),
470                           EXTRACT_32BITS(sflow_gen_counter->ifinunicastpkts),
471                           EXTRACT_32BITS(sflow_gen_counter->ifinmulticastpkts),
472                           EXTRACT_32BITS(sflow_gen_counter->ifinbroadcastpkts),
473                           EXTRACT_32BITS(sflow_gen_counter->ifindiscards));
474                    printf("\n\t      In errors %u, unknown protos %u",
475                           EXTRACT_32BITS(sflow_gen_counter->ifinerrors),
476                           EXTRACT_32BITS(sflow_gen_counter->ifinunkownprotos));
477                    printf("\n\t      Out octets %" PRIu64
478                           ", unicast pkts %u, multicast pkts %u, broadcast pkts %u, discards %u",
479                           EXTRACT_64BITS(sflow_gen_counter->ifoutoctets),
480                           EXTRACT_32BITS(sflow_gen_counter->ifoutunicastpkts),
481                           EXTRACT_32BITS(sflow_gen_counter->ifoutmulticastpkts),
482                           EXTRACT_32BITS(sflow_gen_counter->ifoutbroadcastpkts),
483                           EXTRACT_32BITS(sflow_gen_counter->ifoutdiscards));
484                    printf("\n\t      Out errors %u, promisc mode %u",
485                           EXTRACT_32BITS(sflow_gen_counter->ifouterrors),
486                           EXTRACT_32BITS(sflow_gen_counter->ifpromiscmode));
487                    break;
488                case SFLOW_COUNTER_ETHERNET:
489                    sflow_eth_counter = (const struct sflow_ethernet_counter_t *)tptr;
490                    printf("\n\t      align errors %u, fcs errors %u, single collision %u, multiple collision %u, test error %u",
491                           EXTRACT_32BITS(sflow_eth_counter->alignerrors),
492                           EXTRACT_32BITS(sflow_eth_counter->fcserrors),
493                           EXTRACT_32BITS(sflow_eth_counter->single_collision_frames),
494                           EXTRACT_32BITS(sflow_eth_counter->multiple_collision_frames),
495                           EXTRACT_32BITS(sflow_eth_counter->test_errors));
496                    printf("\n\t      deferred %u, late collision %u, excessive collision %u, mac trans error %u",
497                           EXTRACT_32BITS(sflow_eth_counter->deferred_transmissions),
498                           EXTRACT_32BITS(sflow_eth_counter->late_collisions),
499                           EXTRACT_32BITS(sflow_eth_counter->excessive_collisions),
500                           EXTRACT_32BITS(sflow_eth_counter->mac_transmit_errors));
501                    printf("\n\t      carrier error %u, frames too long %u, mac receive errors %u, symbol errors %u",
502                           EXTRACT_32BITS(sflow_eth_counter->carrier_sense_errors),
503                           EXTRACT_32BITS(sflow_eth_counter->frame_too_longs),
504                           EXTRACT_32BITS(sflow_eth_counter->mac_receive_errors),
505                           EXTRACT_32BITS(sflow_eth_counter->symbol_errors));
506                    break;
507                case SFLOW_COUNTER_TOKEN_RING:			/* XXX */
508                    break;
509                case SFLOW_COUNTER_BASEVG:
510                    sflow_100basevg_counter = (const struct sflow_100basevg_counter_t *)tptr;
511                    printf("\n\t      in high prio frames %u, in high prio octets %" PRIu64,
512                           EXTRACT_32BITS(sflow_100basevg_counter->in_highpriority_frames),
513                           EXTRACT_64BITS(sflow_100basevg_counter->in_highpriority_octets));
514                    printf("\n\t      in norm prio frames %u, in norm prio octets %" PRIu64,
515                           EXTRACT_32BITS(sflow_100basevg_counter->in_normpriority_frames),
516                           EXTRACT_64BITS(sflow_100basevg_counter->in_normpriority_octets));
517                    printf("\n\t      in ipm errors %u, oversized %u, in data errors %u, null addressed frames %u",
518                           EXTRACT_32BITS(sflow_100basevg_counter->in_ipmerrors),
519                           EXTRACT_32BITS(sflow_100basevg_counter->in_oversized),
520                           EXTRACT_32BITS(sflow_100basevg_counter->in_data_errors),
521                           EXTRACT_32BITS(sflow_100basevg_counter->in_null_addressed_frames));
522                    printf("\n\t      out high prio frames %u, out high prio octets %" PRIu64
523                           ", trans into frames %u",
524                           EXTRACT_32BITS(sflow_100basevg_counter->out_highpriority_frames),
525                           EXTRACT_64BITS(sflow_100basevg_counter->out_highpriority_octets),
526                           EXTRACT_32BITS(sflow_100basevg_counter->transitioninto_frames));
527                    printf("\n\t      in hc high prio octets %" PRIu64
528                           ", in hc norm prio octets %" PRIu64
529                           ", out hc high prio octets %" PRIu64,
530                           EXTRACT_64BITS(sflow_100basevg_counter->hc_in_highpriority_octets),
531                           EXTRACT_64BITS(sflow_100basevg_counter->hc_in_normpriority_octets),
532                           EXTRACT_64BITS(sflow_100basevg_counter->hc_out_highpriority_octets));
533                    break;
534                case SFLOW_COUNTER_VLAN:
535                    sflow_vlan_counter = (const struct sflow_vlan_counter_t *)tptr;
536                    printf("\n\t      vlan_id %u, octets %" PRIu64
537                           ", unicast_pkt %u, multicast_pkt %u, broadcast_pkt %u, discards %u",
538                           EXTRACT_32BITS(sflow_vlan_counter->vlan_id),
539                           EXTRACT_64BITS(sflow_vlan_counter->octets),
540                           EXTRACT_32BITS(sflow_vlan_counter->unicast_pkt),
541                           EXTRACT_32BITS(sflow_vlan_counter->multicast_pkt),
542                           EXTRACT_32BITS(sflow_vlan_counter->broadcast_pkt),
543                           EXTRACT_32BITS(sflow_vlan_counter->discards));
544                    break;
545                case SFLOW_COUNTER_PROCESSOR:			/* XXX */
546                    break;
547                default:
548                    if (vflag <= 1)
549                        print_unknown_data(tptr, "\n\t\t", counter_len);
550                    break;
551                }
552                tptr += counter_len;
553                tlen -= counter_len;
554                nrecords--;
555            }
556            break;
557        default:
558            if (vflag <= 1)
559                print_unknown_data(tptr, "\n\t    ", sflow_sample_len);
560            break;
561        }
562        tptr += sflow_sample_len;
563        tlen -= sflow_sample_len;
564        nsamples--;
565    }
566    return;
567
568 trunc:
569    printf("[|SFLOW]");
570}
571
572/*
573 * Local Variables:
574 * c-style: whitesmith
575 * c-basic-offset: 4
576 * End:
577 */
578