print-sflow.c revision 190203
1190203Srpaulo/*
2190203Srpaulo * Copyright (c) 1998-2007 The TCPDUMP project
3190203Srpaulo *
4190203Srpaulo * Redistribution and use in source and binary forms, with or without
5190203Srpaulo * modification, are permitted provided that: (1) source code
6190203Srpaulo * distributions retain the above copyright notice and this paragraph
7190203Srpaulo * in its entirety, and (2) distributions including binary code include
8190203Srpaulo * the above copyright notice and this paragraph in its entirety in
9190203Srpaulo * the documentation or other materials provided with the distribution.
10190203Srpaulo * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
11190203Srpaulo * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
12190203Srpaulo * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13190203Srpaulo * FOR A PARTICULAR PURPOSE.
14190203Srpaulo *
15190203Srpaulo * The SFLOW protocol as per http://www.sflow.org/developers/specifications.php
16190203Srpaulo *
17190203Srpaulo * Original code by Carles Kishimoto <carles.kishimoto@gmail.com>
18190203Srpaulo */
19190203Srpaulo
20190203Srpaulo#ifndef lint
21190203Srpaulostatic const char rcsid[] _U_ =
22190203Srpaulo"@(#) $Header: /tcpdump/master/tcpdump/print-sflow.c,v 1.1 2007-08-08 17:20:58 hannes Exp $";
23190203Srpaulo#endif
24190203Srpaulo
25190203Srpaulo#ifdef HAVE_CONFIG_H
26190203Srpaulo#include "config.h"
27190203Srpaulo#endif
28190203Srpaulo
29190203Srpaulo#include <tcpdump-stdinc.h>
30190203Srpaulo
31190203Srpaulo#include <stdio.h>
32190203Srpaulo#include <stdlib.h>
33190203Srpaulo#include <string.h>
34190203Srpaulo
35190203Srpaulo#include "interface.h"
36190203Srpaulo#include "extract.h"
37190203Srpaulo#include "addrtoname.h"
38190203Srpaulo
39190203Srpaulo/*
40190203Srpaulo * sFlow datagram
41190203Srpaulo *
42190203Srpaulo * 0                   1                   2                   3
43190203Srpaulo * 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
44190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45190203Srpaulo * |                     Sflow version (2,4,5)                     |
46190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47190203Srpaulo * |               IP version (1 for IPv4 | 2 for IPv6)            |
48190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49190203Srpaulo * |                     IP Address AGENT (4 or 16 bytes)          |
50190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51190203Srpaulo * |                          Sub agent ID                         |
52190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53190203Srpaulo * |                      Datagram sequence number                 |
54190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55190203Srpaulo * |                      Switch uptime in ms                      |
56190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57190203Srpaulo * |                    num samples in datagram                    |
58190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59190203Srpaulo *
60190203Srpaulo */
61190203Srpaulo
62190203Srpaulostruct sflow_datagram_t {
63190203Srpaulo    u_int8_t 	version[4];
64190203Srpaulo    u_int8_t 	ip_version[4];
65190203Srpaulo    u_int8_t 	agent[4];
66190203Srpaulo    u_int8_t 	agent_id[4];
67190203Srpaulo    u_int8_t 	seqnum[4];
68190203Srpaulo    u_int8_t 	uptime[4];
69190203Srpaulo    u_int8_t 	samples[4];
70190203Srpaulo};
71190203Srpaulo
72190203Srpaulostruct sflow_sample_header {
73190203Srpaulo    u_int8_t	format[4];
74190203Srpaulo    u_int8_t	len[4];
75190203Srpaulo};
76190203Srpaulo
77190203Srpaulo#define		SFLOW_FLOW_SAMPLE		1
78190203Srpaulo#define		SFLOW_COUNTER_SAMPLE		2
79190203Srpaulo#define		SFLOW_EXPANDED_FLOW_SAMPLE	3
80190203Srpaulo#define		SFLOW_EXPANDED_COUNTER_SAMPLE	4
81190203Srpaulo
82190203Srpaulostatic const struct tok sflow_format_values[] = {
83190203Srpaulo    { SFLOW_FLOW_SAMPLE, "flow sample" },
84190203Srpaulo    { SFLOW_COUNTER_SAMPLE, "counter sample" },
85190203Srpaulo    { SFLOW_EXPANDED_FLOW_SAMPLE, "expanded flow sample" },
86190203Srpaulo    { SFLOW_EXPANDED_COUNTER_SAMPLE, "expanded counter sample" },
87190203Srpaulo    { 0, NULL}
88190203Srpaulo};
89190203Srpaulo
90190203Srpaulostruct sflow_expanded_flow_sample_t {
91190203Srpaulo    u_int8_t    seqnum[4];
92190203Srpaulo    u_int8_t    type[4];
93190203Srpaulo    u_int8_t    index[4];
94190203Srpaulo    u_int8_t    rate[4];
95190203Srpaulo    u_int8_t    pool[4];
96190203Srpaulo    u_int8_t    drops[4];
97190203Srpaulo    u_int8_t    in_interface_format[4];
98190203Srpaulo    u_int8_t    in_interface_value[4];
99190203Srpaulo    u_int8_t    out_interface_format[4];
100190203Srpaulo    u_int8_t    out_interface_value[4];
101190203Srpaulo    u_int8_t    records[4];
102190203Srpaulo};
103190203Srpaulo
104190203Srpaulo#define 	SFLOW_FLOW_RAW_PACKET			1
105190203Srpaulo#define 	SFLOW_FLOW_ETHERNET_FRAME		2
106190203Srpaulo#define 	SFLOW_FLOW_IPV4_DATA			3
107190203Srpaulo#define 	SFLOW_FLOW_IPV6_DATA			4
108190203Srpaulo#define 	SFLOW_FLOW_EXTENDED_SWITCH_DATA		1001
109190203Srpaulo#define 	SFLOW_FLOW_EXTENDED_ROUTER_DATA		1002
110190203Srpaulo#define 	SFLOW_FLOW_EXTENDED_GATEWAY_DATA 	1003
111190203Srpaulo#define 	SFLOW_FLOW_EXTENDED_USER_DATA		1004
112190203Srpaulo#define 	SFLOW_FLOW_EXTENDED_URL_DATA		1005
113190203Srpaulo#define 	SFLOW_FLOW_EXTENDED_MPLS_DATA		1006
114190203Srpaulo#define 	SFLOW_FLOW_EXTENDED_NAT_DATA		1007
115190203Srpaulo#define 	SFLOW_FLOW_EXTENDED_MPLS_TUNNEL		1008
116190203Srpaulo#define 	SFLOW_FLOW_EXTENDED_MPLS_VC		1009
117190203Srpaulo#define 	SFLOW_FLOW_EXTENDED_MPLS_FEC		1010
118190203Srpaulo#define 	SFLOW_FLOW_EXTENDED_MPLS_LVP_FEC	1011
119190203Srpaulo#define 	SFLOW_FLOW_EXTENDED_VLAN_TUNNEL		1012
120190203Srpaulo
121190203Srpaulostatic const struct tok sflow_flow_type_values[] = {
122190203Srpaulo    { SFLOW_FLOW_RAW_PACKET, "Raw packet"},
123190203Srpaulo    { SFLOW_FLOW_ETHERNET_FRAME, "Ethernet frame"},
124190203Srpaulo    { SFLOW_FLOW_IPV4_DATA, "IPv4 Data"},
125190203Srpaulo    { SFLOW_FLOW_IPV6_DATA, "IPv6 Data"},
126190203Srpaulo    { SFLOW_FLOW_EXTENDED_SWITCH_DATA, "Extended Switch data"},
127190203Srpaulo    { SFLOW_FLOW_EXTENDED_ROUTER_DATA, "Extended Router data"},
128190203Srpaulo    { SFLOW_FLOW_EXTENDED_GATEWAY_DATA, "Extended Gateway data"},
129190203Srpaulo    { SFLOW_FLOW_EXTENDED_USER_DATA, "Extended User data"},
130190203Srpaulo    { SFLOW_FLOW_EXTENDED_URL_DATA, "Extended URL data"},
131190203Srpaulo    { SFLOW_FLOW_EXTENDED_MPLS_DATA, "Extended MPLS data"},
132190203Srpaulo    { SFLOW_FLOW_EXTENDED_NAT_DATA, "Extended NAT data"},
133190203Srpaulo    { SFLOW_FLOW_EXTENDED_MPLS_TUNNEL, "Extended MPLS tunnel"},
134190203Srpaulo    { SFLOW_FLOW_EXTENDED_MPLS_VC, "Extended MPLS VC"},
135190203Srpaulo    { SFLOW_FLOW_EXTENDED_MPLS_FEC, "Extended MPLS FEC"},
136190203Srpaulo    { SFLOW_FLOW_EXTENDED_MPLS_LVP_FEC, "Extended MPLS LVP FEC"},
137190203Srpaulo    { SFLOW_FLOW_EXTENDED_VLAN_TUNNEL, "Extended VLAN Tunnel"},
138190203Srpaulo    { 0, NULL}
139190203Srpaulo};
140190203Srpaulo
141190203Srpaulo#define		SFLOW_HEADER_PROTOCOL_ETHERNET	1
142190203Srpaulo#define		SFLOW_HEADER_PROTOCOL_IPV4	11
143190203Srpaulo#define		SFLOW_HEADER_PROTOCOL_IPV6	12
144190203Srpaulo
145190203Srpaulostatic const struct tok sflow_flow_raw_protocol_values[] = {
146190203Srpaulo    { SFLOW_HEADER_PROTOCOL_ETHERNET, "Ethernet"},
147190203Srpaulo    { SFLOW_HEADER_PROTOCOL_IPV4, "IPv4"},
148190203Srpaulo    { SFLOW_HEADER_PROTOCOL_IPV6, "IPv6"},
149190203Srpaulo    { 0, NULL}
150190203Srpaulo};
151190203Srpaulo
152190203Srpaulostruct sflow_expanded_flow_raw_t {
153190203Srpaulo    u_int8_t    protocol[4];
154190203Srpaulo    u_int8_t    length[4];
155190203Srpaulo    u_int8_t    stripped_bytes[4];
156190203Srpaulo    u_int8_t    header_size[4];
157190203Srpaulo};
158190203Srpaulo
159190203Srpaulostruct sflow_expanded_counter_sample_t {
160190203Srpaulo    u_int8_t    seqnum[4];
161190203Srpaulo    u_int8_t    type[4];
162190203Srpaulo    u_int8_t    index[4];
163190203Srpaulo    u_int8_t    records[4];
164190203Srpaulo};
165190203Srpaulo
166190203Srpaulo#define         SFLOW_COUNTER_GENERIC           1
167190203Srpaulo#define         SFLOW_COUNTER_ETHERNET          2
168190203Srpaulo#define         SFLOW_COUNTER_TOKEN_RING        3
169190203Srpaulo#define         SFLOW_COUNTER_BASEVG            4
170190203Srpaulo#define         SFLOW_COUNTER_VLAN              5
171190203Srpaulo#define         SFLOW_COUNTER_PROCESSOR         1001
172190203Srpaulo
173190203Srpaulostatic const struct tok sflow_counter_type_values[] = {
174190203Srpaulo    { SFLOW_COUNTER_GENERIC, "Generic counter"},
175190203Srpaulo    { SFLOW_COUNTER_ETHERNET, "Ethernet counter"},
176190203Srpaulo    { SFLOW_COUNTER_TOKEN_RING, "Token ring counter"},
177190203Srpaulo    { SFLOW_COUNTER_BASEVG, "100 BaseVG counter"},
178190203Srpaulo    { SFLOW_COUNTER_VLAN, "Vlan counter"},
179190203Srpaulo    { SFLOW_COUNTER_PROCESSOR, "Processor counter"},
180190203Srpaulo    { 0, NULL}
181190203Srpaulo};
182190203Srpaulo
183190203Srpaulo#define		SFLOW_IFACE_DIRECTION_UNKNOWN		0
184190203Srpaulo#define		SFLOW_IFACE_DIRECTION_FULLDUPLEX	1
185190203Srpaulo#define		SFLOW_IFACE_DIRECTION_HALFDUPLEX	2
186190203Srpaulo#define		SFLOW_IFACE_DIRECTION_IN		3
187190203Srpaulo#define		SFLOW_IFACE_DIRECTION_OUT		4
188190203Srpaulo
189190203Srpaulostatic const struct tok sflow_iface_direction_values[] = {
190190203Srpaulo    { SFLOW_IFACE_DIRECTION_UNKNOWN, "unknown"},
191190203Srpaulo    { SFLOW_IFACE_DIRECTION_FULLDUPLEX, "full-duplex"},
192190203Srpaulo    { SFLOW_IFACE_DIRECTION_HALFDUPLEX, "half-duplex"},
193190203Srpaulo    { SFLOW_IFACE_DIRECTION_IN, "in"},
194190203Srpaulo    { SFLOW_IFACE_DIRECTION_OUT, "out"},
195190203Srpaulo    { 0, NULL}
196190203Srpaulo};
197190203Srpaulo
198190203Srpaulostruct sflow_generic_counter_t {
199190203Srpaulo    u_int8_t    ifindex[4];
200190203Srpaulo    u_int8_t    iftype[4];
201190203Srpaulo    u_int8_t    ifspeed[8];
202190203Srpaulo    u_int8_t    ifdirection[4];
203190203Srpaulo    u_int8_t    ifstatus[4];
204190203Srpaulo    u_int8_t    ifinoctets[8];
205190203Srpaulo    u_int8_t    ifinunicastpkts[4];
206190203Srpaulo    u_int8_t    ifinmulticastpkts[4];
207190203Srpaulo    u_int8_t    ifinbroadcastpkts[4];
208190203Srpaulo    u_int8_t    ifindiscards[4];
209190203Srpaulo    u_int8_t    ifinerrors[4];
210190203Srpaulo    u_int8_t    ifinunkownprotos[4];
211190203Srpaulo    u_int8_t    ifoutoctets[8];
212190203Srpaulo    u_int8_t    ifoutunicastpkts[4];
213190203Srpaulo    u_int8_t    ifoutmulticastpkts[4];
214190203Srpaulo    u_int8_t    ifoutbroadcastpkts[4];
215190203Srpaulo    u_int8_t    ifoutdiscards[4];
216190203Srpaulo    u_int8_t    ifouterrors[4];
217190203Srpaulo    u_int8_t    ifpromiscmode[4];
218190203Srpaulo};
219190203Srpaulo
220190203Srpaulostruct sflow_ethernet_counter_t {
221190203Srpaulo    u_int8_t    alignerrors[4];
222190203Srpaulo    u_int8_t    fcserrors[4];
223190203Srpaulo    u_int8_t    single_collision_frames[4];
224190203Srpaulo    u_int8_t    multiple_collision_frames[4];
225190203Srpaulo    u_int8_t    test_errors[4];
226190203Srpaulo    u_int8_t    deferred_transmissions[4];
227190203Srpaulo    u_int8_t    late_collisions[4];
228190203Srpaulo    u_int8_t    excessive_collisions[4];
229190203Srpaulo    u_int8_t    mac_transmit_errors[4];
230190203Srpaulo    u_int8_t    carrier_sense_errors[4];
231190203Srpaulo    u_int8_t    frame_too_longs[4];
232190203Srpaulo    u_int8_t    mac_receive_errors[4];
233190203Srpaulo    u_int8_t    symbol_errors[4];
234190203Srpaulo};
235190203Srpaulo
236190203Srpaulostruct sflow_100basevg_counter_t {
237190203Srpaulo    u_int8_t    in_highpriority_frames[4];
238190203Srpaulo    u_int8_t    in_highpriority_octets[8];
239190203Srpaulo    u_int8_t    in_normpriority_frames[4];
240190203Srpaulo    u_int8_t    in_normpriority_octets[8];
241190203Srpaulo    u_int8_t    in_ipmerrors[4];
242190203Srpaulo    u_int8_t    in_oversized[4];
243190203Srpaulo    u_int8_t    in_data_errors[4];
244190203Srpaulo    u_int8_t    in_null_addressed_frames[4];
245190203Srpaulo    u_int8_t    out_highpriority_frames[4];
246190203Srpaulo    u_int8_t    out_highpriority_octets[8];
247190203Srpaulo    u_int8_t    transitioninto_frames[4];
248190203Srpaulo    u_int8_t    hc_in_highpriority_octets[8];
249190203Srpaulo    u_int8_t    hc_in_normpriority_octets[8];
250190203Srpaulo    u_int8_t    hc_out_highpriority_octets[8];
251190203Srpaulo};
252190203Srpaulo
253190203Srpaulostruct sflow_vlan_counter_t {
254190203Srpaulo    u_int8_t    vlan_id[4];
255190203Srpaulo    u_int8_t    octets[8];
256190203Srpaulo    u_int8_t    unicast_pkt[4];
257190203Srpaulo    u_int8_t    multicast_pkt[4];
258190203Srpaulo    u_int8_t    broadcast_pkt[4];
259190203Srpaulo    u_int8_t    discards[4];
260190203Srpaulo};
261190203Srpaulo
262190203Srpaulovoid
263190203Srpaulosflow_print(const u_char *pptr, u_int len) {
264190203Srpaulo
265190203Srpaulo    const struct sflow_datagram_t *sflow_datagram;
266190203Srpaulo    const struct sflow_sample_header *sflow_sample;
267190203Srpaulo    const struct sflow_expanded_flow_sample_t *sflow_expanded_flow_sample;
268190203Srpaulo    const struct sflow_expanded_flow_raw_t *sflow_flow_raw;
269190203Srpaulo    const struct sflow_expanded_counter_sample_t *sflow_expanded_counter_sample;
270190203Srpaulo    const struct sflow_generic_counter_t *sflow_gen_counter;
271190203Srpaulo    const struct sflow_ethernet_counter_t *sflow_eth_counter;
272190203Srpaulo    const struct sflow_100basevg_counter_t *sflow_100basevg_counter;
273190203Srpaulo    const struct sflow_vlan_counter_t *sflow_vlan_counter;
274190203Srpaulo    const u_char *tptr;
275190203Srpaulo    int tlen;
276190203Srpaulo    u_int32_t sflow_sample_type, sflow_sample_len;
277190203Srpaulo    int nsamples, nrecords, counter_len, counter_type, flow_len, flow_type;
278190203Srpaulo
279190203Srpaulo    tptr=pptr;
280190203Srpaulo    tlen = len;
281190203Srpaulo    sflow_datagram = (const struct sflow_datagram_t *)pptr;
282190203Srpaulo    TCHECK(*sflow_datagram);
283190203Srpaulo
284190203Srpaulo    /*
285190203Srpaulo     * Sanity checking of the header.
286190203Srpaulo     */
287190203Srpaulo    if (EXTRACT_32BITS(sflow_datagram->version) != 5) {
288190203Srpaulo        printf("sFlow version %u packet not supported",
289190203Srpaulo               EXTRACT_32BITS(sflow_datagram->version));
290190203Srpaulo        return;
291190203Srpaulo    }
292190203Srpaulo
293190203Srpaulo    if (vflag < 1) {
294190203Srpaulo        printf("sFlowv%u, %s agent %s, agent-id %u, length %u",
295190203Srpaulo               EXTRACT_32BITS(sflow_datagram->version),
296190203Srpaulo               EXTRACT_32BITS(sflow_datagram->ip_version) == 1 ? "IPv4" : "IPv6",
297190203Srpaulo	       ipaddr_string(sflow_datagram->agent),
298190203Srpaulo               EXTRACT_32BITS(sflow_datagram->samples),
299190203Srpaulo               len);
300190203Srpaulo        return;
301190203Srpaulo    }
302190203Srpaulo
303190203Srpaulo    /* ok they seem to want to know everything - lets fully decode it */
304190203Srpaulo    nsamples=EXTRACT_32BITS(sflow_datagram->samples);
305190203Srpaulo    printf("sFlowv%u, %s agent %s, agent-id %u, seqnum %u, uptime %u, samples %u, length %u",
306190203Srpaulo           EXTRACT_32BITS(sflow_datagram->version),
307190203Srpaulo           EXTRACT_32BITS(sflow_datagram->ip_version) == 1 ? "IPv4" : "IPv6",
308190203Srpaulo           ipaddr_string(sflow_datagram->agent),
309190203Srpaulo           EXTRACT_32BITS(sflow_datagram->agent_id),
310190203Srpaulo           EXTRACT_32BITS(sflow_datagram->seqnum),
311190203Srpaulo           EXTRACT_32BITS(sflow_datagram->uptime),
312190203Srpaulo           nsamples,
313190203Srpaulo           len);
314190203Srpaulo
315190203Srpaulo    /* skip Common header */
316190203Srpaulo    tptr+=sizeof(const struct sflow_datagram_t);
317190203Srpaulo    tlen-=sizeof(const struct sflow_datagram_t);
318190203Srpaulo
319190203Srpaulo    while (nsamples > 0 && tlen > 0) {
320190203Srpaulo        sflow_sample = (const struct sflow_sample_header *)tptr;
321190203Srpaulo        sflow_sample_type = (EXTRACT_32BITS(sflow_sample->format)&0x0FFF);
322190203Srpaulo        sflow_sample_len = EXTRACT_32BITS(sflow_sample->len);
323190203Srpaulo
324190203Srpaulo        tptr+=sizeof(struct sflow_sample_header);
325190203Srpaulo        tlen-=sizeof(struct sflow_sample_header);
326190203Srpaulo
327190203Srpaulo        printf("\n\t%s (%u), length %u,",
328190203Srpaulo               tok2str(sflow_format_values, "Unknown", sflow_sample_type),
329190203Srpaulo               sflow_sample_type,
330190203Srpaulo               sflow_sample_len);
331190203Srpaulo
332190203Srpaulo        /* basic sanity check */
333190203Srpaulo        if (sflow_sample_type == 0 || sflow_sample_len ==0) {
334190203Srpaulo            return;
335190203Srpaulo        }
336190203Srpaulo
337190203Srpaulo        /* did we capture enough for fully decoding the sample ? */
338190203Srpaulo        if (!TTEST2(*tptr, sflow_sample_len))
339190203Srpaulo            goto trunc;
340190203Srpaulo
341190203Srpaulo	switch(sflow_sample_type) {
342190203Srpaulo        case SFLOW_FLOW_SAMPLE:				/* XXX */
343190203Srpaulo            break;
344190203Srpaulo
345190203Srpaulo        case SFLOW_COUNTER_SAMPLE:			/* XXX */
346190203Srpaulo            break;
347190203Srpaulo
348190203Srpaulo        case SFLOW_EXPANDED_FLOW_SAMPLE:
349190203Srpaulo            sflow_expanded_flow_sample = (const struct sflow_expanded_flow_sample_t *)tptr;
350190203Srpaulo            nrecords = EXTRACT_32BITS(sflow_expanded_flow_sample->records);
351190203Srpaulo
352190203Srpaulo            printf(" seqnum %u, type %u, idx %u, rate %u, pool %u, drops %u, records %u",
353190203Srpaulo                   EXTRACT_32BITS(sflow_expanded_flow_sample->seqnum),
354190203Srpaulo                   EXTRACT_32BITS(sflow_expanded_flow_sample->type),
355190203Srpaulo                   EXTRACT_32BITS(sflow_expanded_flow_sample->index),
356190203Srpaulo                   EXTRACT_32BITS(sflow_expanded_flow_sample->rate),
357190203Srpaulo                   EXTRACT_32BITS(sflow_expanded_flow_sample->pool),
358190203Srpaulo                   EXTRACT_32BITS(sflow_expanded_flow_sample->drops),
359190203Srpaulo                   EXTRACT_32BITS(sflow_expanded_flow_sample->records));
360190203Srpaulo
361190203Srpaulo            tptr+= sizeof(struct sflow_expanded_flow_sample_t);
362190203Srpaulo            tlen-= sizeof(struct sflow_expanded_flow_sample_t);
363190203Srpaulo
364190203Srpaulo            while ( nrecords > 0 && tlen > 0) {
365190203Srpaulo
366190203Srpaulo                /* decode Flow record - 2 bytes */
367190203Srpaulo                flow_type = EXTRACT_32BITS(tptr)&0x0FFF;
368190203Srpaulo                flow_len = EXTRACT_32BITS(tptr+4);
369190203Srpaulo                printf("\n\t  %s (%u) length %u",
370190203Srpaulo                       tok2str(sflow_flow_type_values,"Unknown",flow_type),
371190203Srpaulo                       flow_type,
372190203Srpaulo                       flow_len);
373190203Srpaulo
374190203Srpaulo                tptr += 8;
375190203Srpaulo                tlen -= 8;
376190203Srpaulo
377190203Srpaulo                /* did we capture enough for fully decoding the flow ? */
378190203Srpaulo                if (!TTEST2(*tptr, flow_len))
379190203Srpaulo                    goto trunc;
380190203Srpaulo
381190203Srpaulo                switch(flow_type) {
382190203Srpaulo                case SFLOW_FLOW_RAW_PACKET:
383190203Srpaulo                    sflow_flow_raw = (const struct sflow_expanded_flow_raw_t *)tptr;
384190203Srpaulo                    printf("\n\t    protocol %s (%u), length %u, stripped bytes %u, header_size %u",
385190203Srpaulo                           tok2str(sflow_flow_raw_protocol_values,"Unknown",EXTRACT_32BITS(sflow_flow_raw->protocol)),
386190203Srpaulo                           EXTRACT_32BITS(sflow_flow_raw->protocol),
387190203Srpaulo                           EXTRACT_32BITS(sflow_flow_raw->length),
388190203Srpaulo                           EXTRACT_32BITS(sflow_flow_raw->stripped_bytes),
389190203Srpaulo                           EXTRACT_32BITS(sflow_flow_raw->header_size));
390190203Srpaulo                    break;
391190203Srpaulo
392190203Srpaulo                    /*
393190203Srpaulo                     * FIXME those are the defined flow types that lack a decoder
394190203Srpaulo                     */
395190203Srpaulo                case SFLOW_FLOW_ETHERNET_FRAME:
396190203Srpaulo                case SFLOW_FLOW_IPV4_DATA:
397190203Srpaulo                case SFLOW_FLOW_IPV6_DATA:
398190203Srpaulo                case SFLOW_FLOW_EXTENDED_SWITCH_DATA:
399190203Srpaulo                case SFLOW_FLOW_EXTENDED_ROUTER_DATA:
400190203Srpaulo                case SFLOW_FLOW_EXTENDED_GATEWAY_DATA:
401190203Srpaulo                case SFLOW_FLOW_EXTENDED_USER_DATA:
402190203Srpaulo                case SFLOW_FLOW_EXTENDED_URL_DATA:
403190203Srpaulo                case SFLOW_FLOW_EXTENDED_MPLS_DATA:
404190203Srpaulo                case SFLOW_FLOW_EXTENDED_NAT_DATA:
405190203Srpaulo                case SFLOW_FLOW_EXTENDED_MPLS_TUNNEL:
406190203Srpaulo                case SFLOW_FLOW_EXTENDED_MPLS_VC:
407190203Srpaulo                case SFLOW_FLOW_EXTENDED_MPLS_FEC:
408190203Srpaulo                case SFLOW_FLOW_EXTENDED_MPLS_LVP_FEC:
409190203Srpaulo                case SFLOW_FLOW_EXTENDED_VLAN_TUNNEL:
410190203Srpaulo                    break;
411190203Srpaulo                default:
412190203Srpaulo                    if (vflag <= 1)
413190203Srpaulo                        print_unknown_data(tptr, "\n\t      ", flow_len);
414190203Srpaulo                    break;
415190203Srpaulo
416190203Srpaulo                }
417190203Srpaulo                tptr += flow_len;
418190203Srpaulo                tlen -= flow_len;
419190203Srpaulo                nrecords--;
420190203Srpaulo            }
421190203Srpaulo            break;
422190203Srpaulo
423190203Srpaulo        case SFLOW_EXPANDED_COUNTER_SAMPLE:
424190203Srpaulo            sflow_expanded_counter_sample = (const struct sflow_expanded_counter_sample_t *)tptr;
425190203Srpaulo            nrecords = EXTRACT_32BITS(sflow_expanded_counter_sample->records);
426190203Srpaulo
427190203Srpaulo            printf(" seqnum %u, type %u, idx %u, records %u",
428190203Srpaulo                   EXTRACT_32BITS(sflow_expanded_counter_sample->seqnum),
429190203Srpaulo                   EXTRACT_32BITS(sflow_expanded_counter_sample->type),
430190203Srpaulo                   EXTRACT_32BITS(sflow_expanded_counter_sample->index),
431190203Srpaulo                   nrecords);
432190203Srpaulo
433190203Srpaulo            tptr+= sizeof(struct sflow_expanded_counter_sample_t);
434190203Srpaulo            tlen-= sizeof(struct sflow_expanded_counter_sample_t);
435190203Srpaulo
436190203Srpaulo            while ( nrecords > 0 && tlen > 0) {
437190203Srpaulo
438190203Srpaulo                /* decode counter record - 2 bytes */
439190203Srpaulo                counter_type = EXTRACT_32BITS(tptr)&0x0FFF;
440190203Srpaulo                counter_len = EXTRACT_32BITS(tptr+4);
441190203Srpaulo                printf("\n\t    %s (%u) length %u",
442190203Srpaulo                       tok2str(sflow_counter_type_values,"Unknown",counter_type),
443190203Srpaulo                       counter_type,
444190203Srpaulo                       counter_len);
445190203Srpaulo
446190203Srpaulo                tptr += 8;
447190203Srpaulo                tlen -= 8;
448190203Srpaulo
449190203Srpaulo                /* did we capture enough for fully decoding the counter ? */
450190203Srpaulo                if (!TTEST2(*tptr, counter_len))
451190203Srpaulo                    goto trunc;
452190203Srpaulo
453190203Srpaulo                switch(counter_type) {
454190203Srpaulo                case SFLOW_COUNTER_GENERIC:
455190203Srpaulo                    sflow_gen_counter = (const struct sflow_generic_counter_t *)tptr;
456190203Srpaulo                    printf("\n\t      ifindex %u, iftype %u, ifspeed %u, ifdirection %u (%s)",
457190203Srpaulo                           EXTRACT_32BITS(sflow_gen_counter->ifindex),
458190203Srpaulo                           EXTRACT_32BITS(sflow_gen_counter->iftype),
459190203Srpaulo                           EXTRACT_32BITS(sflow_gen_counter->ifspeed),
460190203Srpaulo                           EXTRACT_32BITS(sflow_gen_counter->ifdirection),
461190203Srpaulo                           tok2str(sflow_iface_direction_values, "Unknown",
462190203Srpaulo                                   EXTRACT_32BITS(sflow_gen_counter->ifdirection)));
463190203Srpaulo                    printf("\n\t      ifstatus %u, adminstatus: %s, operstatus: %s",
464190203Srpaulo                           EXTRACT_32BITS(sflow_gen_counter->ifstatus),
465190203Srpaulo                           EXTRACT_32BITS(sflow_gen_counter->ifstatus)&1 ? "up" : "down",
466190203Srpaulo                           (EXTRACT_32BITS(sflow_gen_counter->ifstatus)>>1)&1 ? "up" : "down");
467190203Srpaulo                    printf("\n\t      In octets %" PRIu64
468190203Srpaulo                           ", unicast pkts %u, multicast pkts %u, broadcast pkts %u, discards %u",
469190203Srpaulo                           EXTRACT_64BITS(sflow_gen_counter->ifinoctets),
470190203Srpaulo                           EXTRACT_32BITS(sflow_gen_counter->ifinunicastpkts),
471190203Srpaulo                           EXTRACT_32BITS(sflow_gen_counter->ifinmulticastpkts),
472190203Srpaulo                           EXTRACT_32BITS(sflow_gen_counter->ifinbroadcastpkts),
473190203Srpaulo                           EXTRACT_32BITS(sflow_gen_counter->ifindiscards));
474190203Srpaulo                    printf("\n\t      In errors %u, unknown protos %u",
475190203Srpaulo                           EXTRACT_32BITS(sflow_gen_counter->ifinerrors),
476190203Srpaulo                           EXTRACT_32BITS(sflow_gen_counter->ifinunkownprotos));
477190203Srpaulo                    printf("\n\t      Out octets %" PRIu64
478190203Srpaulo                           ", unicast pkts %u, multicast pkts %u, broadcast pkts %u, discards %u",
479190203Srpaulo                           EXTRACT_64BITS(sflow_gen_counter->ifoutoctets),
480190203Srpaulo                           EXTRACT_32BITS(sflow_gen_counter->ifoutunicastpkts),
481190203Srpaulo                           EXTRACT_32BITS(sflow_gen_counter->ifoutmulticastpkts),
482190203Srpaulo                           EXTRACT_32BITS(sflow_gen_counter->ifoutbroadcastpkts),
483190203Srpaulo                           EXTRACT_32BITS(sflow_gen_counter->ifoutdiscards));
484190203Srpaulo                    printf("\n\t      Out errors %u, promisc mode %u",
485190203Srpaulo                           EXTRACT_32BITS(sflow_gen_counter->ifouterrors),
486190203Srpaulo                           EXTRACT_32BITS(sflow_gen_counter->ifpromiscmode));
487190203Srpaulo                    break;
488190203Srpaulo                case SFLOW_COUNTER_ETHERNET:
489190203Srpaulo                    sflow_eth_counter = (const struct sflow_ethernet_counter_t *)tptr;
490190203Srpaulo                    printf("\n\t      align errors %u, fcs errors %u, single collision %u, multiple collision %u, test error %u",
491190203Srpaulo                           EXTRACT_32BITS(sflow_eth_counter->alignerrors),
492190203Srpaulo                           EXTRACT_32BITS(sflow_eth_counter->fcserrors),
493190203Srpaulo                           EXTRACT_32BITS(sflow_eth_counter->single_collision_frames),
494190203Srpaulo                           EXTRACT_32BITS(sflow_eth_counter->multiple_collision_frames),
495190203Srpaulo                           EXTRACT_32BITS(sflow_eth_counter->test_errors));
496190203Srpaulo                    printf("\n\t      deferred %u, late collision %u, excessive collision %u, mac trans error %u",
497190203Srpaulo                           EXTRACT_32BITS(sflow_eth_counter->deferred_transmissions),
498190203Srpaulo                           EXTRACT_32BITS(sflow_eth_counter->late_collisions),
499190203Srpaulo                           EXTRACT_32BITS(sflow_eth_counter->excessive_collisions),
500190203Srpaulo                           EXTRACT_32BITS(sflow_eth_counter->mac_transmit_errors));
501190203Srpaulo                    printf("\n\t      carrier error %u, frames too long %u, mac receive errors %u, symbol errors %u",
502190203Srpaulo                           EXTRACT_32BITS(sflow_eth_counter->carrier_sense_errors),
503190203Srpaulo                           EXTRACT_32BITS(sflow_eth_counter->frame_too_longs),
504190203Srpaulo                           EXTRACT_32BITS(sflow_eth_counter->mac_receive_errors),
505190203Srpaulo                           EXTRACT_32BITS(sflow_eth_counter->symbol_errors));
506190203Srpaulo                    break;
507190203Srpaulo                case SFLOW_COUNTER_TOKEN_RING:			/* XXX */
508190203Srpaulo                    break;
509190203Srpaulo                case SFLOW_COUNTER_BASEVG:
510190203Srpaulo                    sflow_100basevg_counter = (const struct sflow_100basevg_counter_t *)tptr;
511190203Srpaulo                    printf("\n\t      in high prio frames %u, in high prio octets %" PRIu64,
512190203Srpaulo                           EXTRACT_32BITS(sflow_100basevg_counter->in_highpriority_frames),
513190203Srpaulo                           EXTRACT_64BITS(sflow_100basevg_counter->in_highpriority_octets));
514190203Srpaulo                    printf("\n\t      in norm prio frames %u, in norm prio octets %" PRIu64,
515190203Srpaulo                           EXTRACT_32BITS(sflow_100basevg_counter->in_normpriority_frames),
516190203Srpaulo                           EXTRACT_64BITS(sflow_100basevg_counter->in_normpriority_octets));
517190203Srpaulo                    printf("\n\t      in ipm errors %u, oversized %u, in data errors %u, null addressed frames %u",
518190203Srpaulo                           EXTRACT_32BITS(sflow_100basevg_counter->in_ipmerrors),
519190203Srpaulo                           EXTRACT_32BITS(sflow_100basevg_counter->in_oversized),
520190203Srpaulo                           EXTRACT_32BITS(sflow_100basevg_counter->in_data_errors),
521190203Srpaulo                           EXTRACT_32BITS(sflow_100basevg_counter->in_null_addressed_frames));
522190203Srpaulo                    printf("\n\t      out high prio frames %u, out high prio octets %" PRIu64
523190203Srpaulo                           ", trans into frames %u",
524190203Srpaulo                           EXTRACT_32BITS(sflow_100basevg_counter->out_highpriority_frames),
525190203Srpaulo                           EXTRACT_64BITS(sflow_100basevg_counter->out_highpriority_octets),
526190203Srpaulo                           EXTRACT_32BITS(sflow_100basevg_counter->transitioninto_frames));
527190203Srpaulo                    printf("\n\t      in hc high prio octets %" PRIu64
528190203Srpaulo                           ", in hc norm prio octets %" PRIu64
529190203Srpaulo                           ", out hc high prio octets %" PRIu64,
530190203Srpaulo                           EXTRACT_64BITS(sflow_100basevg_counter->hc_in_highpriority_octets),
531190203Srpaulo                           EXTRACT_64BITS(sflow_100basevg_counter->hc_in_normpriority_octets),
532190203Srpaulo                           EXTRACT_64BITS(sflow_100basevg_counter->hc_out_highpriority_octets));
533190203Srpaulo                    break;
534190203Srpaulo                case SFLOW_COUNTER_VLAN:
535190203Srpaulo                    sflow_vlan_counter = (const struct sflow_vlan_counter_t *)tptr;
536190203Srpaulo                    printf("\n\t      vlan_id %u, octets %" PRIu64
537190203Srpaulo                           ", unicast_pkt %u, multicast_pkt %u, broadcast_pkt %u, discards %u",
538190203Srpaulo                           EXTRACT_32BITS(sflow_vlan_counter->vlan_id),
539190203Srpaulo                           EXTRACT_64BITS(sflow_vlan_counter->octets),
540190203Srpaulo                           EXTRACT_32BITS(sflow_vlan_counter->unicast_pkt),
541190203Srpaulo                           EXTRACT_32BITS(sflow_vlan_counter->multicast_pkt),
542190203Srpaulo                           EXTRACT_32BITS(sflow_vlan_counter->broadcast_pkt),
543190203Srpaulo                           EXTRACT_32BITS(sflow_vlan_counter->discards));
544190203Srpaulo                    break;
545190203Srpaulo                case SFLOW_COUNTER_PROCESSOR:			/* XXX */
546190203Srpaulo                    break;
547190203Srpaulo                default:
548190203Srpaulo                    if (vflag <= 1)
549190203Srpaulo                        print_unknown_data(tptr, "\n\t\t", counter_len);
550190203Srpaulo                    break;
551190203Srpaulo                }
552190203Srpaulo                tptr += counter_len;
553190203Srpaulo                tlen -= counter_len;
554190203Srpaulo                nrecords--;
555190203Srpaulo            }
556190203Srpaulo            break;
557190203Srpaulo        default:
558190203Srpaulo            if (vflag <= 1)
559190203Srpaulo                print_unknown_data(tptr, "\n\t    ", sflow_sample_len);
560190203Srpaulo            break;
561190203Srpaulo        }
562190203Srpaulo        tptr += sflow_sample_len;
563190203Srpaulo        tlen -= sflow_sample_len;
564190203Srpaulo        nsamples--;
565190203Srpaulo    }
566190203Srpaulo    return;
567190203Srpaulo
568190203Srpaulo trunc:
569190203Srpaulo    printf("[|SFLOW]");
570190203Srpaulo}
571190203Srpaulo
572190203Srpaulo/*
573190203Srpaulo * Local Variables:
574190203Srpaulo * c-style: whitesmith
575190203Srpaulo * c-basic-offset: 4
576190203Srpaulo * End:
577190203Srpaulo */
578