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