aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-sflow.c
diff options
context:
space:
mode:
authorjmayer <jmayer@f5534014-38df-0310-8fa8-9805f1628bb7>2008-12-01 10:03:33 +0000
committerjmayer <jmayer@f5534014-38df-0310-8fa8-9805f1628bb7>2008-12-01 10:03:33 +0000
commitd9ee4833fa3854c00bfefde02c0c2e96ccdd3fe3 (patch)
tree280c9cd111b01e8b4485965dff9d37979781b377 /epan/dissectors/packet-sflow.c
parent21bd61f6d59d381ebcfea8e9a6e80be9beeaefc6 (diff)
The good:
- Implement the beginnings of sflow5 support. - Get rid if the inconsistencies regarding return values: Always return the offset. - Make more elements filterable - Make the naming of elements more consistent (not finished) - To see what's missing have a look at the TODO section at the beginning of the file and search for XXX in the code. The not so good: - Only tested with a single sample trace. No extended/expanded data in that trace. - This patch hopefully doesn't break sflow4 support, but I didn't have any traces to test with, so please test. - The names of many filters have changed to make things more consistent. git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@26891 f5534014-38df-0310-8fa8-9805f1628bb7
Diffstat (limited to 'epan/dissectors/packet-sflow.c')
-rw-r--r--epan/dissectors/packet-sflow.c1588
1 files changed, 1084 insertions, 504 deletions
diff --git a/epan/dissectors/packet-sflow.c b/epan/dissectors/packet-sflow.c
index f149b934d1..9f92f6b842 100644
--- a/epan/dissectors/packet-sflow.c
+++ b/epan/dissectors/packet-sflow.c
@@ -1,46 +1,43 @@
-/* packet-sflow.c
+/* packeto-sflow.c
* Routines for sFlow dissection
* Copyright 2003, Jeff Rizzo <riz@boogers.sf.ca.us>
+ * Copyright 2008, Joerg Mayer (see AUTHORS file)
*
* $Id$
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
- *
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-/* This file (mostly) implements a dissector for sFlow (RFC3176),
- * from the version 4 spec at http://www.sflow.org/SFLOW-DATAGRAM.txt .
+/* This file (mostly) implements a dissector for sFlow (RFC3176),
+ * from the version 4 spec at http://www.sflow.org/SFLOW-DATAGRAM.txt
+ * and the version 5 http://www.sflow.org/SFLOW-DATAGRAM5.txt.
*
* TODO:
+ * Insert more subtrees for some of the headers
* Fix the highlighting of the datastream when bits are selected
- * split things out into packet-sflow.h ?
- * make routines more consistent as to whether they return
- * 'offset' or bytes consumed ('len')
- * implement sampled_ipv4 and sampled_ipv6 packet data types
- * implement extended_user
- * implement extended_url
- * implement non-generic counters sampling
- * implement the samples from the draft version 5 spec; see
- * http://www.sflow.org/SFLOW-DATAGRAM5.txt (see epan/sminmpec.h
- * for tables of SMI Network Management Private Enterprise Codes;
- * use sminmpec_values, adding new values to epan/sminmpect.h and
- * and sminmpec_values in epan/sminmpec.c if necessary - don't create
- * your own table)
+ * (user add_item instead of add_text wherever sensible)
+ * Make naming and filtering more consistent
+ * Implement expanded flow samples
+ * Implement expanded counter samples
+ * Finish extended_user
+ * Finish extended_url
+ * Implement non-generic counters sampling
*/
#ifdef HAVE_CONFIG_H
@@ -56,8 +53,7 @@
#include <epan/packet.h>
#include <epan/prefs.h>
#include <epan/ipproto.h>
-
-/*#include "packet-sflow.h"*/
+#include <epan/sminmpec.h>
#define SFLOW_UDP_PORTS "6343"
@@ -75,19 +71,63 @@ static range_t *sflow_ports = NULL;
static gboolean global_dissect_samp_headers = TRUE;
static gboolean global_analyze_samp_ip_headers = FALSE;
+static const true_false_string yes_no_truth = {
+ "Yes",
+ "No"
+};
+#define ADDRESS_UNKNOWN 0
#define ADDRESS_IPV4 1
#define ADDRESS_IPV6 2
+static const value_string sflow_agent_address_type[] = {
+ { ADDRESS_UNKNOWN, "Unknown" },
+ { ADDRESS_IPV4, "IP_V4" },
+ { ADDRESS_IPV6, "IP_V6"},
+ { 0, NULL }
+};
+
#define FLOWSAMPLE 1
#define COUNTERSSAMPLE 2
-static const value_string sflow_sampletype[] = {
+static const value_string sflow4_sampletype[] = {
+ { FLOWSAMPLE, "Flow sample" },
+ { COUNTERSSAMPLE, "Counters sample" },
+ { 0, NULL }
+};
+
+#define EXPFLOWSAMPLES 3
+#define EXPCOUNTERSAMPLES 4
+
+static const value_string sflow5_sampletype[] = {
{ FLOWSAMPLE, "Flow sample" },
{ COUNTERSSAMPLE, "Counters sample" },
+ { EXPFLOWSAMPLES, "Expanded flow sample" },
+ { EXPCOUNTERSAMPLES, "Expanded counters sample" },
+ { 0, NULL }
+};
+
+static const value_string sflow_sample_sourceidtype[] = {
+ { 0, "ifIndex" },
+ { 1, "smonVlanDataSource" },
+ { 2, "entPhysicalEntry" },
+ { 0, NULL }
+};
+
+static const value_string if_direction_vals[] = {
+ { 0, "unknown" },
+ { 1, "full duplex" },
+ { 2, "half duplex" },
+ { 3, "in" },
+ { 4, "out" },
{ 0, NULL }
};
+static const true_false_string if_status_up_down = {
+ "Down",
+ "Up"
+};
+
/* interface counter types */
#define SFLOW_COUNTERS_GENERIC 1
#define SFLOW_COUNTERS_ETHERNET 2
@@ -96,6 +136,7 @@ static const value_string sflow_sampletype[] = {
#define SFLOW_COUNTERS_VG 5
#define SFLOW_COUNTERS_WAN 6
#define SFLOW_COUNTERS_VLAN 7
+#define SFLOW_COUNTERS_CPU 1001
static const value_string sflow_counterstype [] = {
{ SFLOW_COUNTERS_GENERIC, "Generic counters" },
@@ -104,19 +145,76 @@ static const value_string sflow_counterstype [] = {
{ SFLOW_COUNTERS_VG, "100baseVG counters" },
{ SFLOW_COUNTERS_WAN, "WAN counters" },
{ SFLOW_COUNTERS_VLAN, "VLAN counters" },
+ { SFLOW_COUNTERS_CPU, "CPU counters" },
+ { 0, NULL }
+};
+
+/* flow sample types */
+
+static const value_string sflow_flowsamplestype [] = {
{ 0, NULL }
};
#define MAX_HEADER_SIZE 256
-#define SFLOW_PACKET_DATA_TYPE_HEADER 1
-#define SFLOW_PACKET_DATA_TYPE_IPV4 2
-#define SFLOW_PACKET_DATA_TYPE_IPV6 3
+#define SFLOW4_PACKET_DATA_TYPE_HEADER 1
+#define SFLOW4_PACKET_DATA_TYPE_IPV4 2
+#define SFLOW4_PACKET_DATA_TYPE_IPV6 3
-static const value_string sflow_packet_information_type [] = {
- { SFLOW_PACKET_DATA_TYPE_HEADER, "Packet headers are sampled" },
- { SFLOW_PACKET_DATA_TYPE_IPV4, "IP Version 4 data" },
- { SFLOW_PACKET_DATA_TYPE_IPV6, "IP Version 6 data" },
+static const value_string sflow4_fs_record_type [] = {
+ { SFLOW4_PACKET_DATA_TYPE_HEADER, "Packet headers are sampled" },
+ { SFLOW4_PACKET_DATA_TYPE_IPV4, "IP Version 4 data" },
+ { SFLOW4_PACKET_DATA_TYPE_IPV6, "IP Version 6 data" },
+ { 0, NULL}
+};
+
+#define SFLOW_EXTENDED_SWITCH 1
+#define SFLOW_EXTENDED_ROUTER 2
+#define SFLOW_EXTENDED_GATEWAY 3
+#define SFLOW_EXTENDED_USER 4
+#define SFLOW_EXTENDED_URL 5
+
+static const value_string sflow_extended_data_types[] = {
+ { SFLOW_EXTENDED_SWITCH, "Extended switch information" },
+ { SFLOW_EXTENDED_ROUTER, "Extended router information" },
+ { SFLOW_EXTENDED_GATEWAY, "Extended gateway information" },
+ { SFLOW_EXTENDED_USER, "Extended user information" },
+ { SFLOW_EXTENDED_URL, "Extended URL information" },
+ { 0, NULL }
+};
+
+#define SFLOW5_PACKET_DATA_TYPE_RAWHEADER 1
+#define SFLOW5_PACKET_DATA_TYPE_ETHERNET 2
+#define SFLOW5_PACKET_DATA_TYPE_IPV4 3
+#define SFLOW5_PACKET_DATA_TYPE_IPV6 4
+#define SFLOW5_PACKET_DATA_TYPE_SWITCH 1001
+#define SFLOW5_PACKET_DATA_TYPE_ROUTER 1002
+#define SFLOW5_PACKET_DATA_TYPE_GATEWAY 1003
+#define SFLOW5_PACKET_DATA_TYPE_USER 1004
+#define SFLOW5_PACKET_DATA_TYPE_URL 1005
+#define SFLOW5_PACKET_DATA_TYPE_MPLS 1006
+#define SFLOW5_PACKET_DATA_TYPE_MPLSTUN 1008
+#define SFLOW5_PACKET_DATA_TYPE_MPLSVC 1009
+#define SFLOW5_PACKET_DATA_TYPE_MPLSFEC 1010
+#define SFLOW5_PACKET_DATA_TYPE_MPLSLVPFEC 1011
+#define SFLOW5_PACKET_DATA_TYPE_VLANTUN 1012
+
+static const value_string sflow5_packet_fs_record_type [] = {
+ { SFLOW5_PACKET_DATA_TYPE_RAWHEADER, "Raw header" },
+ { SFLOW5_PACKET_DATA_TYPE_ETHERNET, "Ethernet header" },
+ { SFLOW5_PACKET_DATA_TYPE_IPV4, "IPv4 header" },
+ { SFLOW5_PACKET_DATA_TYPE_IPV6, "IPv6 header" },
+ { SFLOW5_PACKET_DATA_TYPE_SWITCH, "Switch data" },
+ { SFLOW5_PACKET_DATA_TYPE_ROUTER, "Router data" },
+ { SFLOW5_PACKET_DATA_TYPE_GATEWAY, "Gateway data" },
+ { SFLOW5_PACKET_DATA_TYPE_USER, "User data" },
+ { SFLOW5_PACKET_DATA_TYPE_URL, "URL data" },
+ { SFLOW5_PACKET_DATA_TYPE_MPLS, "MPLS data" },
+ { SFLOW5_PACKET_DATA_TYPE_MPLSTUN, "MPLS tunnel data" },
+ { SFLOW5_PACKET_DATA_TYPE_MPLSVC, "MPLS VC data" },
+ { SFLOW5_PACKET_DATA_TYPE_MPLSFEC, "MPLS FEC data" },
+ { SFLOW5_PACKET_DATA_TYPE_MPLSLVPFEC, "MPLS LVP FEC data" },
+ { SFLOW5_PACKET_DATA_TYPE_VLANTUN, "Vlan tunnel data" },
{ 0, NULL}
};
@@ -151,23 +249,8 @@ static const value_string sflow_header_protocol[] = {
{ 0, NULL }
};
-/* extended data types */
-#define SFLOW_EXTENDED_SWITCH 1
-#define SFLOW_EXTENDED_ROUTER 2
-#define SFLOW_EXTENDED_GATEWAY 3
-#define SFLOW_EXTENDED_USER 4
-#define SFLOW_EXTENDED_URL 5
-
-static const value_string sflow_extended_data_types[] = {
- { SFLOW_EXTENDED_SWITCH, "Extended switch information" },
- { SFLOW_EXTENDED_ROUTER, "Extended router information" },
- { SFLOW_EXTENDED_GATEWAY, "Extended gateway information" },
- { SFLOW_EXTENDED_USER, "Extended user information" },
- { SFLOW_EXTENDED_URL, "Extended URL information" },
- { 0, NULL }
-};
-
+/* extended data types */
#define SFLOW_AS_SET 1
#define SFLOW_AS_SEQUENCE 2
@@ -178,6 +261,7 @@ static const value_string sflow_as_types[] = {
};
+#if 0
/* flow sample header */
struct sflow_flow_sample_header {
guint32 sequence_number;
@@ -185,8 +269,8 @@ struct sflow_flow_sample_header {
guint32 sampling_rate;
guint32 sample_pool;
guint32 drops;
- guint32 input;
- guint32 output;
+ guint32 input;
+ guint32 output;
};
/* counters sample header */
@@ -289,32 +373,100 @@ struct vlan_counters {
guint32 discards;
};
+/* Processor counters */
+
+struct cpu_counters {
+ guint32 cpuPercentage5s;
+ guint32 cpuPercentage1m;
+ guint32 cpuPercentage5m;
+ guint64 memTotal;
+ guint64 memFree;
+};
+#endif
+
/* Initialize the protocol and registered fields */
+
+/* sFlow Datagram */
static int proto_sflow = -1;
static int hf_sflow_version = -1;
-/*static int hf_sflow_agent_address_type = -1; */
+static int hf_sflow_agent_address_type = -1;
static int hf_sflow_agent_address_v4 = -1;
static int hf_sflow_agent_address_v6 = -1;
static int hf_sflow_sub_agent_id = -1;
static int hf_sflow_seqnum = -1;
static int hf_sflow_sysuptime = -1;
static int hf_sflow_numsamples = -1;
-static int hf_sflow_header_protocol = -1;
-static int hf_sflow_sampletype = -1;
-static int hf_sflow_header = -1;
-static int hf_sflow_ip_length = -1;
-static int hf_sflow_ip_protocol = -1;
-static int hf_sflow_src_ipv4 = -1;
-static int hf_sflow_dst_ipv4 = -1;
-static int hf_sflow_src_ipv6 = -1;
-static int hf_sflow_dst_ipv6 = -1;
-static int hf_sflow_src_port = -1;
-static int hf_sflow_dst_port = -1;
-static int hf_sflow_tcp_flags = -1;
-static int hf_sflow_tos = -1;
-static int hf_sflow_priority = -1;
-static int hf_sflow_packet_information_type = -1;
-static int hf_sflow_extended_information_type = -1;
+
+/* Sample header common to all sample types */
+static int hf_sflow_sample_type = -1;
+static int hf_sflow_sample_type_enterprise = -1;
+static int hf_sflow_sample_type_enterprisetype = -1;
+static int hf_sflow_sample_length = -1;
+
+/* Flowsample header */
+static int hf_sflow_fs_seqno = -1;
+static int hf_sflow_fs_sourceid_type = -1;
+static int hf_sflow_fs_sourceid_index = -1;
+static int hf_sflow_fs_samplingrate = -1;
+static int hf_sflow_fs_samplepool = -1;
+static int hf_sflow_fs_drops = -1;
+static int hf_sflow_fs_ifindexin = -1;
+static int hf_sflow_fs_multipleoutputs = -1;
+static int hf_sflow_fs_numoutinterfaces = -1;
+static int hf_sflow_fs_ifindexout = -1;
+static int hf_sflow_fs_numrecords = -1;
+static int hf_sflow_fs_recordlength = -1;
+
+/* Countersample header */
+static int hf_sflow_cs_seqno = -1;
+static int hf_sflow_cs_sourceid_type = -1;
+static int hf_sflow_cs_sourceid_index = -1;
+static int hf_sflow_cs_samplingrate = -1;
+static int hf_sflow_cs_samplinginterval = -1;
+static int hf_sflow_cs_numrecords = -1;
+static int hf_sflow_cs_record_type = -1;
+static int hf_sflow_cs_recordlength = -1;
+
+/* Flowsample Raw packet header */
+static int hf_sflow_fs_rawheader_protocol = -1;
+static int hf_sflow_fs_rawheader_framelength = -1;
+static int hf_sflow_fs_rawheader_stripped = -1;
+static int hf_sflow_fs_rawheader_headerlength = -1;
+static int hf_sflow_fs_rawheader = -1;
+
+/* Flowsample Ethernet packet */
+static int hf_sflow_fs_ethernet_framelength = -1;
+static int hf_sflow_fs_ethernet_srcmac = -1;
+static int hf_sflow_fs_ethernet_dstmac = -1;
+static int hf_sflow_fs_ethernet_type = -1;
+
+/* Flowsample IP packet */
+static int hf_sflow_fs_ip_length = -1;
+static int hf_sflow_fs_ip_protocol = -1;
+static int hf_sflow_fs_ip_srcipv4 = -1;
+static int hf_sflow_fs_ip_dstipv4 = -1;
+static int hf_sflow_fs_ip_srcipv6 = -1;
+static int hf_sflow_fs_ip_dstipv6 = -1;
+static int hf_sflow_fs_ip_srcport = -1;
+static int hf_sflow_fs_ip_dstport = -1;
+static int hf_sflow_fs_ip_tcpflags = -1;
+static int hf_sflow_fs_ip_tos = -1;
+static int hf_sflow_fs_ip_priority = -1;
+
+/* Flowsample Tokenring packet */
+
+/* Flowsample 100BaseVG packet */
+
+/* Flowsample VLAN packet */
+
+/* Flowsample CPU packet */
+
+/* sflow record */
+static int hf_sflow4_fs_record_type = -1;
+static int hf_sflow5_fs_record_type = -1;
+static int hf_sflow4_extended_information_type = -1;
+
+/* stuff used in extended flow records */
static int hf_sflow_vlan_in = -1; /* incoming 802.1Q VLAN ID */
static int hf_sflow_vlan_out = -1; /* outgoing 802.1Q VLAN ID */
static int hf_sflow_pri_in = -1; /* incominging 802.1p priority */
@@ -335,30 +487,49 @@ static int hf_sflow_community_entries = -1;
static int hf_sflow_community = -1;
static int hf_sflow_localpref = -1;
+/* generic counters */
static int hf_sflow_ifindex = -1;
static int hf_sflow_iftype = -1;
static int hf_sflow_ifspeed = -1;
static int hf_sflow_ifdirection = -1;
-static int hf_sflow_ifstatus = -1;
+static int hf_sflow_ifstatus_unused = -1;
+static int hf_sflow_ifstatus_admin = -1;
+static int hf_sflow_ifstatus_oper = -1;
static int hf_sflow_ifinoct = -1;
-static int hf_sflow_ifinpkt = -1;
+static int hf_sflow_ifinucast = -1;
static int hf_sflow_ifinmcast = -1;
static int hf_sflow_ifinbcast = -1;
static int hf_sflow_ifinerr = -1;
static int hf_sflow_ifindisc = -1;
static int hf_sflow_ifinunk = -1;
static int hf_sflow_ifoutoct = -1;
-static int hf_sflow_ifoutpkt = -1;
+static int hf_sflow_ifoutucast = -1;
static int hf_sflow_ifoutmcast = -1;
static int hf_sflow_ifoutbcast = -1;
static int hf_sflow_ifoutdisc = -1;
static int hf_sflow_ifouterr = -1;
static int hf_sflow_ifpromisc = -1;
+/* ethernet counters */
+static int hf_sflow_eth_dot3StatsAlignmentErrors = -1;
+static int hf_sflow_eth_dot3StatsFCSErrors = -1;
+static int hf_sflow_eth_dot3StatsSingleCollisionFrames = -1;
+static int hf_sflow_eth_dot3StatsMultipleCollisionFrames = -1;
+static int hf_sflow_eth_dot3StatsSQETestErrors = -1;
+static int hf_sflow_eth_dot3StatsDeferredTransmissions = -1;
+static int hf_sflow_eth_dot3StatsLateCollisions = -1;
+static int hf_sflow_eth_dot3StatsExcessiveCollisions = -1;
+static int hf_sflow_eth_dot3StatsInternalMacTransmitErrors = -1;
+static int hf_sflow_eth_dot3StatsCarrierSenseErrors = -1;
+static int hf_sflow_eth_dot3StatsFrameTooLongs = -1;
+static int hf_sflow_eth_dot3StatsInternalMacReceiveErrors = -1;
+static int hf_sflow_eth_dot3StatsSymbolErrors = -1;
+
/* Initialize the subtree pointers */
static gint ett_sflow = -1;
static gint ett_sflow_sample = -1;
static gint ett_sflow_extended_data = -1;
+static gint ett_sflow_counters_record = -1;
static gint ett_sflow_gw_as_dst = -1;
static gint ett_sflow_gw_as_dst_seg = -1;
static gint ett_sflow_gw_community = -1;
@@ -383,8 +554,8 @@ void proto_reg_handoff_sflow(void);
/* dissect a sampled header - layer 2 protocols */
static gint
-dissect_sflow_sampled_header(tvbuff_t *tvb, packet_info *pinfo,
- proto_tree *tree, volatile gint offset)
+dissect_sflow_sample_rawheaderdata(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ volatile gint offset, guint32 version)
{
guint32 header_proto, frame_length;
volatile guint32 header_length;
@@ -403,22 +574,22 @@ dissect_sflow_sampled_header(tvbuff_t *tvb, packet_info *pinfo,
volatile address save_dst;
header_proto = tvb_get_ntohl(tvb,offset);
- proto_tree_add_item(tree, hf_sflow_header_protocol, tvb, offset,
- 4, FALSE);
+ proto_tree_add_item(tree, hf_sflow_fs_rawheader_protocol, tvb, offset, 4, FALSE);
offset += 4;
frame_length = tvb_get_ntohl(tvb,offset);
- proto_tree_add_text(tree, tvb, offset, 4, "Frame Length: %d bytes",
- frame_length);
+ proto_tree_add_item(tree, hf_sflow_fs_rawheader_framelength, tvb, offset, 4, FALSE);
offset += 4;
+ if (version == 5) {
+ proto_tree_add_item(tree, hf_sflow_fs_rawheader_stripped, tvb, offset, 4, FALSE);
+ offset += 4;
+ }
header_length = tvb_get_ntohl(tvb,offset);
+ proto_tree_add_item(tree, hf_sflow_fs_rawheader_headerlength, tvb, offset, 4, FALSE);
offset += 4;
if (header_length % 4) /* XDR requires 4-byte alignment */
header_length += 4 - (header_length % 4);
-
-
- ti = proto_tree_add_item(tree, hf_sflow_header, tvb, offset,
- header_length, FALSE);
+ ti = proto_tree_add_item(tree, hf_sflow_fs_rawheader, tvb, offset, header_length, FALSE);
sflow_header_tree = proto_item_add_subtree(ti, ett_sflow_sampled_header);
/* hand the header off to the appropriate dissector. It's probably
@@ -428,7 +599,7 @@ dissect_sflow_sampled_header(tvbuff_t *tvb, packet_info *pinfo,
/* save some state */
save_writable = col_get_writable(pinfo->cinfo);
- /*
+ /*
If sFlow samples a TCP packet it is very likely that the
TCP analysis will flag the packet as having some error with
the sequence numbers. sFlow only report on a "sample" of
@@ -523,66 +694,114 @@ dissect_sflow_sampled_header(tvbuff_t *tvb, packet_info *pinfo,
return offset;
}
-/* extended switch data, after the packet data */
+static gint
+dissect_sflow_sample_ethernet(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ gint offset)
+{
+ proto_tree_add_item(tree, hf_sflow_fs_ethernet_framelength, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_fs_ethernet_srcmac, tvb, offset, 4, FALSE);
+ offset += 8;
+ proto_tree_add_item(tree, hf_sflow_fs_ethernet_dstmac, tvb, offset, 4, FALSE);
+ offset += 8;
+ proto_tree_add_item(tree, hf_sflow_fs_ethernet_type, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+/* dissect a sampled ipv4 or ipv4 header */
+static gint
+dissect_sflow_sample_ip(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ gint offset, guint32 ipversion)
+{
+ guint32 ip_proto;
+
+ proto_tree_add_item(tree, hf_sflow_fs_ip_length, tvb, offset, 4, FALSE);
+ offset += 4;
+ ip_proto = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint_format(tree, hf_sflow_fs_ip_protocol, tvb, offset,
+ 4, ip_proto, "Protocol: %s (0x%02x)", ipprotostr(ip_proto), ip_proto);
+ offset +=4;
+ if (ipversion == 4) {
+ proto_tree_add_item(tree, hf_sflow_fs_ip_srcipv4, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_fs_ip_dstipv4, tvb, offset, 4, FALSE);
+ offset += 4;
+ } else {
+ proto_tree_add_item(tree, hf_sflow_fs_ip_srcipv6, tvb, offset, 16, FALSE);
+ offset += 16;
+ proto_tree_add_item(tree, hf_sflow_fs_ip_dstipv6, tvb, offset, 16, FALSE);
+ offset += 16;
+ }
+ proto_tree_add_item(tree, hf_sflow_fs_ip_srcport, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_fs_ip_dstport, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_fs_ip_tcpflags, tvb, offset, 4, FALSE);
+ offset += 4;
+ if (ipversion == 4) {
+ proto_tree_add_item(tree, hf_sflow_fs_ip_tos, tvb, offset, 4, FALSE);
+ offset += 4;
+ } else {
+ proto_tree_add_item(tree, hf_sflow_fs_ip_priority, tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+ return offset;
+}
+
+/* extended switch data */
static gint
dissect_sflow_extended_switch(tvbuff_t *tvb, proto_tree *tree, gint offset)
{
- gint32 len = 0;
-
- proto_tree_add_item(tree, hf_sflow_vlan_in, tvb, offset + len, 4, FALSE);
- len += 4;
- proto_tree_add_item(tree, hf_sflow_pri_in, tvb, offset + len, 4, FALSE);
- len += 4;
- proto_tree_add_item(tree, hf_sflow_vlan_out, tvb, offset + len, 4, FALSE);
- len += 4;
- proto_tree_add_item(tree, hf_sflow_pri_out, tvb, offset + len, 4, FALSE);
- len += 4;
-
- return len;
+ proto_tree_add_item(tree, hf_sflow_vlan_in, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_pri_in, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_vlan_out, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_pri_out, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ return offset;
}
-/* extended router data, after the packet data */
+/* extended router data */
static gint
dissect_sflow_extended_router(tvbuff_t *tvb, proto_tree *tree, gint offset)
{
- gint32 len = 0;
guint32 address_type;
address_type = tvb_get_ntohl(tvb, offset);
- len += 4;
+ offset += 4;
switch (address_type) {
case ADDRESS_IPV4:
- proto_tree_add_item(tree, hf_sflow_nexthop_v4, tvb, offset + len,
- 4, FALSE);
- len += 4;
+ proto_tree_add_item(tree, hf_sflow_nexthop_v4, tvb, offset, 4, FALSE);
+ offset += 4;
break;
case ADDRESS_IPV6:
- proto_tree_add_item(tree, hf_sflow_nexthop_v6, tvb, offset + len,
- 16, FALSE);
- len += 16;
+ proto_tree_add_item(tree, hf_sflow_nexthop_v6, tvb, offset, 16, FALSE);
+ offset += 16;
break;
default:
- proto_tree_add_text(tree, tvb, offset + len - 4, 4,
- "Unknown address type (%d)", address_type);
- len += 4; /* not perfect, but what else to do? */
- return len; /* again, this is wrong. but... ? */
+ proto_tree_add_text(tree, tvb, offset - 4, 4,
+ "Unknown address type (%d)", address_type);
+ offset += 4; /* not perfect, but what else to do? */
+ return offset; /* again, this is wrong. but... ? */
};
- proto_tree_add_item(tree, hf_sflow_nexthop_src_mask, tvb, offset + len,
- 4, FALSE);
- len += 4;
- proto_tree_add_item(tree, hf_sflow_nexthop_dst_mask, tvb, offset + len,
- 4, FALSE);
- len += 4;
- return len;
+ proto_tree_add_item(tree, hf_sflow_nexthop_src_mask, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_nexthop_dst_mask, tvb, offset, 4, FALSE);
+ offset += 4;
+ return offset;
}
-/* extended router data, after the packet data */
+/* extended gateway data */
static gint
dissect_sflow_extended_gateway(tvbuff_t *tvb, proto_tree *tree, gint offset)
{
- gint32 len = 0;
gint32 i, j, comm_len, dst_len, dst_seg_len;
guint32 path_type;
gint32 kludge;
@@ -593,29 +812,26 @@ dissect_sflow_extended_gateway(tvbuff_t *tvb, proto_tree *tree, gint offset)
proto_tree *sflow_comm_tree;
proto_tree *sflow_dst_as_seg_tree;
- proto_tree_add_item(tree, hf_sflow_as, tvb, offset + len,
- 4, FALSE);
- len += 4;
+ proto_tree_add_item(tree, hf_sflow_as, tvb, offset, 4, FALSE);
+ offset += 4;
- proto_tree_add_item(tree, hf_sflow_src_as, tvb, offset + len,
- 4, FALSE);
- len += 4;
+ proto_tree_add_item(tree, hf_sflow_src_as, tvb, offset, 4, FALSE);
+ offset += 4;
- proto_tree_add_item(tree, hf_sflow_src_peer_as, tvb, offset + len,
- 4, FALSE);
- len += 4;
+ proto_tree_add_item(tree, hf_sflow_src_peer_as, tvb, offset, 4, FALSE);
+ offset += 4;
- dst_len = tvb_get_ntohl(tvb, offset+len);
- ti = proto_tree_add_uint(tree, hf_sflow_dst_as_entries, tvb, offset + len, 4, dst_len);
+ dst_len = tvb_get_ntohl(tvb, offset);
+ ti = proto_tree_add_uint(tree, hf_sflow_dst_as_entries, tvb, offset, 4, dst_len);
sflow_dst_as_tree = proto_item_add_subtree(ti, ett_sflow_gw_as_dst);
- len += 4;
+ offset += 4;
for (i = 0; i < dst_len; i++) {
if( version < 4 ) {
/* Version 2 AS paths are different than versions >= 4 as
follows:
- There is no type encoded in the packet.
+ There is no type encoded in the packet.
The destination ASs are encoded as an array of integers
rather as an array of arrays of integers. I just
@@ -633,338 +849,466 @@ dissect_sflow_extended_gateway(tvbuff_t *tvb, proto_tree *tree, gint offset)
kludge = 0;
sflow_dst_as_seg_tree = sflow_dst_as_tree;
} else {
- path_type = tvb_get_ntohl(tvb, offset+len);
- len += 4;
- dst_seg_len = tvb_get_ntohl(tvb, offset+len);
- len += 4;
+ path_type = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+ dst_seg_len = tvb_get_ntohl(tvb, offset);
+ offset += 4;
kludge = 8;
- ti = proto_tree_add_text(tree, tvb, offset+len-kludge, kludge,
- "%s, (%d entries)",
- val_to_str(path_type,
- sflow_as_types,
- "Unknown AS type"),
- dst_seg_len);
+ ti = proto_tree_add_text(tree, tvb, offset-kludge, kludge,
+ "%s, (%d entries)",
+ val_to_str(path_type, sflow_as_types, "Unknown AS type"),
+ dst_seg_len);
sflow_dst_as_seg_tree = proto_item_add_subtree(ti, ett_sflow_gw_as_dst_seg);
}
for (j = 0; j < dst_seg_len; j++) {
- proto_tree_add_item(sflow_dst_as_seg_tree,
- hf_sflow_dst_as, tvb, offset + len,
- 4, FALSE);
- len += 4;
+ proto_tree_add_item(sflow_dst_as_seg_tree, hf_sflow_dst_as,
+ tvb, offset, 4, FALSE);
+ offset += 4;
}
}
if( version >= 4 ) {
- comm_len = tvb_get_ntohl(tvb, offset+len);
+ comm_len = tvb_get_ntohl(tvb, offset);
- ti = proto_tree_add_uint(tree, hf_sflow_community_entries, tvb, offset + len, 4, comm_len);
+ ti = proto_tree_add_uint(tree, hf_sflow_community_entries, tvb, offset, 4, comm_len);
sflow_comm_tree = proto_item_add_subtree(ti, ett_sflow_gw_community);
- len += 4;
+ offset += 4;
for (i = 0; i < comm_len; i++) {
- proto_tree_add_item(sflow_comm_tree,
- hf_sflow_dst_as, tvb, offset + len,
- 4, FALSE);
- len += 4;
+ proto_tree_add_item(sflow_comm_tree, hf_sflow_dst_as, tvb,
+ offset, 4, FALSE);
+ offset += 4;
}
-
- proto_tree_add_item(tree, hf_sflow_localpref, tvb, offset + len,
- 4, FALSE);
- len += 4;
-
+ proto_tree_add_item(tree, hf_sflow_localpref, tvb, offset, 4, FALSE);
+ offset += 4;
}
- return len;
+ return offset;
+}
+
+/* extended url data */
+/* XXX the item stuff is missing */
+static gint
+dissect_sflow_extended_url(tvbuff_t *tvb, proto_tree *tree _U_, gint offset)
+{
+ guint32 url_string_len, host_string_len;
+
+ offset += 4;
+
+ url_string_len = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+
+ if (url_string_len & 3)
+ url_string_len += (4 - (url_string_len & 3));
+ offset += url_string_len;
+
+ host_string_len = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+
+ if (host_string_len & 3)
+ host_string_len += (4 - (host_string_len & 3));
+ offset += host_string_len;
+
+ return offset;
+}
+
+/* extended userdata */
+/* XXX the item stuff is missing */
+static gint
+dissect_sflow_extended_user(tvbuff_t *tvb, proto_tree *tree _U_, gint offset)
+{
+ guint32 src_user_string_len, dst_user_string_len;
+
+ offset += 4;
+
+ src_user_string_len = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+
+ if (src_user_string_len & 3)
+ src_user_string_len += (4 - (src_user_string_len & 3));
+ offset += src_user_string_len;
+
+ offset += 4;
+
+ dst_user_string_len = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+
+ if (dst_user_string_len & 3)
+ dst_user_string_len += (4 - (dst_user_string_len & 3));
+ offset += dst_user_string_len;
+
+ return offset;
}
/* dissect a flow sample */
static gint
dissect_sflow_flow_sample(tvbuff_t *tvb, packet_info *pinfo,
- proto_tree *tree, gint offset, proto_item *parent)
+ proto_tree *tree, gint offset, proto_item *parent, guint32 version)
{
- struct sflow_flow_sample_header flow_header;
proto_tree *extended_data_tree;
- proto_item *ti;
- guint32 packet_type, extended_data, ext_type, i;
- guint32 ip_proto;
+ proto_item *ti;
+ guint32 packet_type, extended_data, ext_type, i, j;
+ guint32 sequence_number;
+ guint32 output, num_records, record_length, sample_length;
+ gint return_offset = 0, nextoffset = 0;
- /* grab the flow header. This will remain in network byte
- order, so must convert each item before use */
- tvb_memcpy(tvb,(guint8 *)&flow_header,offset,sizeof(flow_header));
- proto_tree_add_text(tree, tvb, offset, 4,
- "Sequence number: %u",
- g_ntohl(flow_header.sequence_number));
- proto_item_append_text(parent, ", seq %u",
- g_ntohl(flow_header.sequence_number));
- proto_tree_add_text(tree, tvb, offset+4, 4,
- "Source ID class: %u index: %u",
- g_ntohl(flow_header.source_id) >> 24,
- g_ntohl(flow_header.source_id) & 0x00ffffff);
- proto_tree_add_text(tree, tvb, offset+8, 4,
- "Sampling rate: 1 out of %u packets",
- g_ntohl(flow_header.sampling_rate));
- proto_tree_add_text(tree, tvb, offset+12, 4,
- "Sample pool: %u total packets",
- g_ntohl(flow_header.sample_pool));
- proto_tree_add_text(tree, tvb, offset+16, 4,
- "Dropped packets: %u",
- g_ntohl(flow_header.drops));
- proto_tree_add_text(tree, tvb, offset+20, 4,
- "Input Interface: ifIndex %u",
- g_ntohl(flow_header.input));
- if (g_ntohl(flow_header.output) >> 31)
- proto_tree_add_text(tree, tvb, offset+24, 4,
- "multiple outputs: %u interfaces",
- g_ntohl(flow_header.output) & 0x00ffffff);
- else
- proto_tree_add_text(tree, tvb, offset+24, 4,
- "Output interface: ifIndex %u",
- g_ntohl(flow_header.output) & 0x00ffffff);
- offset += sizeof(flow_header);
-
- /* what kind of flow sample is it? */
- packet_type = tvb_get_ntohl(tvb, offset);
- proto_tree_add_uint(tree, hf_sflow_packet_information_type, tvb, offset,
- 4, packet_type);
- offset += 4;
- switch (packet_type) {
- case SFLOW_PACKET_DATA_TYPE_HEADER:
- offset = dissect_sflow_sampled_header(tvb, pinfo, tree, offset);
- break;
- case SFLOW_PACKET_DATA_TYPE_IPV4:
- case SFLOW_PACKET_DATA_TYPE_IPV6:
- proto_tree_add_item(tree, hf_sflow_ip_length, tvb, offset, 4, FALSE);
- offset += 4;
- ip_proto = tvb_get_ntohl(tvb, offset);
- proto_tree_add_uint_format(tree, hf_sflow_ip_protocol, tvb, offset,
- 4, ip_proto, "Protocol: %s (0x%02x)",
- ipprotostr(ip_proto), ip_proto);
- offset +=4;
- if (packet_type == SFLOW_PACKET_DATA_TYPE_IPV4) {
- proto_tree_add_item(tree, hf_sflow_src_ipv4, tvb, offset, 4, FALSE);
- offset += 4;
- proto_tree_add_item(tree, hf_sflow_dst_ipv4, tvb, offset, 4, FALSE);
- offset += 4;
- } else {
- proto_tree_add_item(tree, hf_sflow_src_ipv6, tvb, offset, 16, FALSE);
- offset += 16;
- proto_tree_add_item(tree, hf_sflow_dst_ipv6, tvb, offset, 16, FALSE);
- offset += 16;
- }
- proto_tree_add_item(tree, hf_sflow_src_port, tvb, offset, 4, FALSE);
+ if (version == 5) {
+ sample_length = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(tree, hf_sflow_sample_length, tvb, offset, 4, FALSE);
offset += 4;
- proto_tree_add_item(tree, hf_sflow_dst_port, tvb, offset, 4, FALSE);
+ return_offset = offset + sample_length;
+ }
+ sequence_number = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(tree, hf_sflow_fs_seqno, tvb, offset, 4, FALSE);
+ proto_item_append_text(parent, ", seq %u", sequence_number);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_sflow_fs_sourceid_type, tvb, offset, 4, FALSE);
+ proto_tree_add_item(tree, hf_sflow_fs_sourceid_index, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_sflow_fs_samplingrate, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_sflow_fs_samplepool, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_sflow_fs_drops, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_sflow_fs_ifindexin, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ output = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(tree, hf_sflow_fs_multipleoutputs, tvb, offset, 4, FALSE);
+ if (output >> 31)
+ proto_tree_add_item(tree, hf_sflow_fs_numoutinterfaces, tvb, offset, 4, FALSE);
+ else
+ proto_tree_add_item(tree, hf_sflow_fs_ifindexout, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ if (version == 5) {
+ num_records = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(tree, hf_sflow_fs_numrecords, tvb, offset, 4, FALSE);
offset += 4;
- proto_tree_add_item(tree, hf_sflow_tcp_flags, tvb, offset, 4, FALSE);
+ } else {
+ num_records = 1;
+ }
+ for (j = 0; j < num_records; j++) {
+ /* what kind of flow sample is it? */
+ packet_type = tvb_get_ntohl(tvb, offset);
+ if (version == 5)
+ proto_tree_add_item(tree, hf_sflow5_fs_record_type, tvb, offset, 4, FALSE);
+ else
+ proto_tree_add_item(tree, hf_sflow4_fs_record_type, tvb, offset, 4, FALSE);
offset += 4;
- if (packet_type == SFLOW_PACKET_DATA_TYPE_IPV4) {
- proto_tree_add_item(tree, hf_sflow_tos, tvb, offset, 4, FALSE);
+
+ if (version == 5) {
+ record_length = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(tree, hf_sflow_fs_recordlength, tvb, offset, 4, FALSE);
offset += 4;
+ nextoffset = offset + record_length;
+
+ switch (packet_type) {
+ case SFLOW5_PACKET_DATA_TYPE_RAWHEADER:
+ offset = dissect_sflow_sample_rawheaderdata(tvb, pinfo, tree, offset, version);
+ break;
+ case SFLOW5_PACKET_DATA_TYPE_ETHERNET:
+ offset = dissect_sflow_sample_ethernet(tvb, pinfo, tree, offset);
+ break;
+ case SFLOW5_PACKET_DATA_TYPE_IPV4:
+ offset = dissect_sflow_sample_ip(tvb, pinfo, tree, offset, 4);
+ break;
+ case SFLOW5_PACKET_DATA_TYPE_IPV6:
+ offset = dissect_sflow_sample_ip(tvb, pinfo, tree, offset, 6);
+ break;
+ case SFLOW5_PACKET_DATA_TYPE_SWITCH:
+ offset = dissect_sflow_extended_switch(tvb, extended_data_tree, offset);
+ break;
+ case SFLOW5_PACKET_DATA_TYPE_ROUTER:
+ offset = dissect_sflow_extended_router(tvb, extended_data_tree, offset);
+ break;
+ case SFLOW5_PACKET_DATA_TYPE_GATEWAY:
+ offset = dissect_sflow_extended_gateway(tvb, extended_data_tree, offset);
+ break;
+ case SFLOW5_PACKET_DATA_TYPE_USER:
+ case SFLOW5_PACKET_DATA_TYPE_URL:
+ case SFLOW5_PACKET_DATA_TYPE_MPLS:
+ case SFLOW5_PACKET_DATA_TYPE_MPLSTUN:
+ case SFLOW5_PACKET_DATA_TYPE_MPLSVC:
+ case SFLOW5_PACKET_DATA_TYPE_MPLSFEC:
+ case SFLOW5_PACKET_DATA_TYPE_MPLSLVPFEC:
+ case SFLOW5_PACKET_DATA_TYPE_VLANTUN:
+ default:
+ break;
+ };
+ offset = nextoffset;
} else {
- proto_tree_add_item(tree, hf_sflow_priority, tvb, offset, 4, FALSE);
+ switch (packet_type) {
+ case SFLOW4_PACKET_DATA_TYPE_IPV4:
+ offset = dissect_sflow_sample_ip(tvb, pinfo, tree, offset, 4);
+ break;
+ case SFLOW4_PACKET_DATA_TYPE_IPV6:
+ offset = dissect_sflow_sample_ip(tvb, pinfo, tree, offset, 6);
+ break;
+ }
+ /* still need to dissect extended data */
+ extended_data = tvb_get_ntohl(tvb,offset);
offset += 4;
+ for (i=0; i < extended_data; i++) {
+ /* figure out what kind of extended data it is */
+ ext_type = tvb_get_ntohl(tvb,offset);
+
+ /* create a subtree. Might want to move this to
+ * the end, so more info can be correct.
+ */
+ ti = proto_tree_add_text(tree, tvb, offset, -1, "%s",
+ val_to_str(ext_type,
+ sflow_extended_data_types,
+ "Unknown extended information"));
+ extended_data_tree = proto_item_add_subtree(ti, ett_sflow_extended_data);
+ proto_tree_add_uint(extended_data_tree,
+ hf_sflow4_extended_information_type, tvb, offset, 4,
+ ext_type);
+ offset += 4;
+ }
+
+ switch (ext_type) {
+ case SFLOW_EXTENDED_SWITCH:
+ offset = dissect_sflow_extended_switch(tvb, extended_data_tree, offset);
+ break;
+ case SFLOW_EXTENDED_ROUTER:
+ offset = dissect_sflow_extended_router(tvb, extended_data_tree, offset);
+ break;
+ case SFLOW_EXTENDED_GATEWAY:
+ offset = dissect_sflow_extended_gateway(tvb, extended_data_tree, offset);
+ break;
+ case SFLOW_EXTENDED_URL:
+ offset = dissect_sflow_extended_url(tvb, extended_data_tree, offset);
+ break;
+ case SFLOW_EXTENDED_USER:
+ offset = dissect_sflow_extended_user(tvb, extended_data_tree, offset);
+ break;
+ default:
+ break;
+ }
+ proto_item_set_end(ti, tvb, offset);
}
- break;
- default:
- break;
- };
- /* still need to dissect extended data */
- extended_data = tvb_get_ntohl(tvb,offset);
- offset += 4;
-
- for (i=0; i < extended_data; i++) {
- /* figure out what kind of extended data it is */
- ext_type = tvb_get_ntohl(tvb,offset);
-
- /* create a subtree. Might want to move this to
- * the end, so more info can be correct.
- */
- ti = proto_tree_add_text(tree, tvb, offset, -1, "%s",
- val_to_str(ext_type,
- sflow_extended_data_types,
- "Unknown extended information"));
- extended_data_tree = proto_item_add_subtree(ti, ett_sflow_extended_data);
- proto_tree_add_uint(extended_data_tree,
- hf_sflow_extended_information_type, tvb, offset, 4,
- ext_type);
- offset += 4;
-
- switch (ext_type) {
- case SFLOW_EXTENDED_SWITCH:
- offset += dissect_sflow_extended_switch(tvb, extended_data_tree,
- offset);
- break;
- case SFLOW_EXTENDED_ROUTER:
- offset += dissect_sflow_extended_router(tvb, extended_data_tree,
- offset);
- break;
- case SFLOW_EXTENDED_GATEWAY:
- offset += dissect_sflow_extended_gateway(tvb, extended_data_tree,
- offset);
- break;
- case SFLOW_EXTENDED_USER:
- break;
- case SFLOW_EXTENDED_URL:
- break;
- default:
- break;
- }
- proto_item_set_end(ti, tvb, offset);
}
- return offset;
-
+ if (version == 5)
+ return return_offset;
+ else
+ return offset;
}
/* dissect a counters sample */
static gint
dissect_sflow_counters_sample(tvbuff_t *tvb, proto_tree *tree,
- gint offset, proto_item *parent)
+ gint offset, proto_item *parent, guint32 version)
{
- struct sflow_counters_sample_header counters_header;
- struct if_counters ifc;
- struct ethernet_counters ethc;
- struct token_ring_counters tokc;
- struct vg_counters vgc;
- struct vlan_counters vlanc;
+ guint32 sequence_number, num_records, counters_type, record_length, j;
+ guint32 sample_length;
+ gint nextoffset = 0, return_offset = 0;
+ proto_tree *record_tree;
+ proto_item *ti; /* tree item */
- /* grab the flow header. This will remain in network byte
- order, so must convert each item before use */
- tvb_memcpy(tvb,(guint8 *)&counters_header,offset,sizeof(counters_header));
- proto_tree_add_text(tree, tvb, offset, 4,
- "Sequence number: %u",
- g_ntohl(counters_header.sequence_number));
- proto_item_append_text(parent, ", seq %u",
- g_ntohl(counters_header.sequence_number));
- proto_tree_add_text(tree, tvb, offset + 4, 4,
- "Source ID class: %u index: %u",
- g_ntohl(counters_header.source_id) >> 24,
- g_ntohl(counters_header.source_id) & 0x00ffffff);
- proto_tree_add_text(tree, tvb, offset + 8, 4,
- "Sampling Interval: %u",
- g_ntohl(counters_header.sampling_interval));
- proto_tree_add_text(tree, tvb, offset + 12, 4, "Counters type: %s",
- val_to_str(g_ntohl(counters_header.counters_type),
- sflow_counterstype, "Unknown type"));
-
- offset += sizeof(counters_header);
-
- /* most counters types have the "generic" counters first */
- switch (g_ntohl(counters_header.counters_type)) {
- case SFLOW_COUNTERS_GENERIC:
- case SFLOW_COUNTERS_ETHERNET:
- case SFLOW_COUNTERS_TOKENRING:
- case SFLOW_COUNTERS_FDDI:
- case SFLOW_COUNTERS_VG:
- case SFLOW_COUNTERS_WAN:
- tvb_memcpy(tvb,(guint8 *)&ifc, offset, sizeof(ifc));
- proto_item_append_text(parent, ", ifIndex %u",
- g_ntohl(ifc.ifIndex));
- proto_tree_add_item(tree, hf_sflow_ifindex, tvb, offset, 4, FALSE);
- offset += 4;
- proto_tree_add_item(tree, hf_sflow_iftype, tvb, offset, 4, FALSE);
- offset += 4;
- proto_tree_add_item(tree, hf_sflow_ifspeed, tvb, offset, 8, FALSE);
- offset += 8;
- proto_tree_add_item(tree, hf_sflow_ifdirection, tvb, offset,
- 4, FALSE);
- offset += 4;
- proto_tree_add_item(tree, hf_sflow_ifstatus, tvb, offset, 4, FALSE);
- offset += 4;
- proto_tree_add_item(tree, hf_sflow_ifinoct, tvb, offset, 8, FALSE);
- offset += 8;
- proto_tree_add_item(tree, hf_sflow_ifinpkt, tvb, offset, 4, FALSE);
- offset += 4;
- proto_tree_add_item(tree, hf_sflow_ifinmcast, tvb, offset,
- 4, FALSE);
- offset += 4;
- proto_tree_add_item(tree, hf_sflow_ifinbcast, tvb, offset,
- 4, FALSE);
- offset += 4;
- proto_tree_add_item(tree, hf_sflow_ifindisc, tvb, offset,
- 4, FALSE);
- offset += 4;
- proto_tree_add_item(tree, hf_sflow_ifinerr, tvb, offset,
- 4, FALSE);
- offset += 4;
- proto_tree_add_item(tree, hf_sflow_ifinunk, tvb, offset,
- 4, FALSE);
- offset += 4;
- proto_tree_add_item(tree, hf_sflow_ifoutoct, tvb, offset, 8, FALSE);
- offset += 8;
- proto_tree_add_item(tree, hf_sflow_ifoutpkt, tvb, offset, 4, FALSE);
- offset += 4;
- proto_tree_add_item(tree, hf_sflow_ifoutmcast, tvb, offset,
- 4, FALSE);
- offset += 4;
- proto_tree_add_item(tree, hf_sflow_ifoutbcast, tvb, offset,
- 4, FALSE);
+ if (version == 5) {
+ sample_length = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(tree, hf_sflow_sample_length, tvb, offset, 4, FALSE);
offset += 4;
- proto_tree_add_item(tree, hf_sflow_ifoutdisc, tvb, offset,
- 4, FALSE);
+ return_offset = offset + sample_length;
+ }
+ sequence_number = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(tree, hf_sflow_cs_seqno, tvb, offset, 4, FALSE);
+ proto_item_append_text(parent, ", seq %u", sequence_number);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_sflow_cs_sourceid_type, tvb, offset, 4, FALSE);
+ proto_tree_add_item(tree, hf_sflow_cs_sourceid_index, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ if (version == 5) {
+ num_records = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(tree, hf_sflow_cs_numrecords, tvb, offset, 4, FALSE);
offset += 4;
- proto_tree_add_item(tree, hf_sflow_ifouterr, tvb, offset,
- 4, FALSE);
+ } else {
+ num_records = 1;
+ proto_tree_add_item(tree, hf_sflow_cs_samplinginterval, tvb, offset, 4, FALSE);
offset += 4;
- proto_tree_add_item(tree, hf_sflow_ifpromisc, tvb, offset,
- 4, FALSE);
+ }
+
+ for (j = 0; j < num_records; j++) {
+ counters_type = tvb_get_ntohl(tvb, offset);
+ if (version == 5) {
+ /* To put the version 4 stuff also into a subree we'd need to calculate
+ the record length via a table */
+ record_length = tvb_get_ntohl(tvb, offset + 4);
+ ti = proto_tree_add_text(tree, tvb, offset, record_length + 8,
+ "%s record", val_to_str(counters_type, sflow_counterstype, "%u"));
+ record_tree = proto_item_add_subtree(ti, ett_sflow_counters_record);
+ } else {
+ record_tree = tree;
+ }
+ proto_tree_add_item(record_tree, hf_sflow_cs_record_type, tvb, offset, 4, FALSE);
offset += 4;
- break;
- };
- /* Some counter types have other info to gather */
- switch (g_ntohl(counters_header.counters_type)) {
- case SFLOW_COUNTERS_ETHERNET:
- tvb_memcpy(tvb,(guint8 *)&ethc, offset, sizeof(ethc));
- offset += sizeof(ethc);
- break;
- case SFLOW_COUNTERS_TOKENRING:
- tvb_memcpy(tvb,(guint8 *)&tokc, offset, sizeof(tokc));
- offset += sizeof(tokc);
- break;
- case SFLOW_COUNTERS_VG:
- tvb_memcpy(tvb,(guint8 *)&vgc, offset, sizeof(vgc));
- offset += sizeof(vgc);
- break;
- case SFLOW_COUNTERS_VLAN:
- tvb_memcpy(tvb,(guint8 *)&vlanc, offset, sizeof(vlanc));
- offset += sizeof(vlanc);
- break;
- default:
- break;
+ if (version == 5) {
+ proto_tree_add_item(record_tree, hf_sflow_cs_recordlength, tvb, offset, 4, FALSE);
+ offset += 4;
+ nextoffset = offset + record_length;
+ }
+
+ /* most counters types have the "generic" counters first */
+ switch (counters_type) {
+ case SFLOW_COUNTERS_ETHERNET:
+ case SFLOW_COUNTERS_TOKENRING:
+ case SFLOW_COUNTERS_FDDI:
+ case SFLOW_COUNTERS_VG:
+ case SFLOW_COUNTERS_WAN:
+ case SFLOW_COUNTERS_CPU:
+ if (version == 5)
+ break;
+ case SFLOW_COUNTERS_GENERIC:
+ proto_item_append_text(parent, ", ifIndex %u", tvb_get_ntohl(tvb, offset));
+ proto_tree_add_item(record_tree, hf_sflow_ifindex, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_iftype, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_ifspeed, tvb, offset, 8, FALSE);
+ offset += 8;
+ proto_tree_add_item(record_tree, hf_sflow_ifdirection, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_ifstatus_unused, tvb, offset, 4, FALSE);
+ proto_tree_add_item(record_tree, hf_sflow_ifstatus_oper, tvb, offset, 4, FALSE);
+ proto_tree_add_item(record_tree, hf_sflow_ifstatus_admin, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_ifinoct, tvb, offset, 8, FALSE);
+ offset += 8;
+ proto_tree_add_item(record_tree, hf_sflow_ifinucast, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_ifinmcast, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_ifinbcast, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_ifindisc, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_ifinerr, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_ifinunk, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_ifoutoct, tvb, offset, 8, FALSE);
+ offset += 8;
+ proto_tree_add_item(record_tree, hf_sflow_ifoutucast, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_ifoutmcast, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_ifoutbcast, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_ifoutdisc, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_ifouterr, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_ifpromisc, tvb, offset, 4, FALSE);
+ offset += 4;
+ break;
+ };
+
+ /* Some counter types have other info to gather */
+ switch (counters_type) {
+ case SFLOW_COUNTERS_ETHERNET:
+ proto_tree_add_item(record_tree, hf_sflow_eth_dot3StatsAlignmentErrors, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_eth_dot3StatsFCSErrors, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_eth_dot3StatsSingleCollisionFrames, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_eth_dot3StatsMultipleCollisionFrames, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_eth_dot3StatsSQETestErrors, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_eth_dot3StatsDeferredTransmissions, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_eth_dot3StatsLateCollisions, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_eth_dot3StatsExcessiveCollisions, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_eth_dot3StatsInternalMacTransmitErrors, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_eth_dot3StatsCarrierSenseErrors, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_eth_dot3StatsFrameTooLongs, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_eth_dot3StatsInternalMacReceiveErrors, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(record_tree, hf_sflow_eth_dot3StatsSymbolErrors, tvb, offset, 4, FALSE);
+ offset += 4;
+ break;
+ case SFLOW_COUNTERS_TOKENRING:
+ offset += 72;
+ break;
+ case SFLOW_COUNTERS_VG:
+ offset += 80;
+ break;
+ case SFLOW_COUNTERS_VLAN:
+ offset += 24;
+ break;
+ case SFLOW_COUNTERS_CPU:
+ offset += 28;
+ break;
+ default:
+ break;
+ }
+ if (version == 5)
+ offset = nextoffset;
}
- return offset;
+ if (version == 5)
+ return return_offset;
+ else
+ return offset;
}
/* Code to dissect the sflow samples */
static gint
-dissect_sflow_samples(tvbuff_t *tvb, packet_info *pinfo,
- proto_tree *tree, gint offset)
+dissect_sflow_samples(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gint offset, guint32 version)
{
proto_tree *sflow_sample_tree;
proto_item *ti; /* tree item */
- guint32 sample_type;
+ guint32 sample_type, sample_enterprise;
/* decide what kind of sample it is. */
- sample_type = tvb_get_ntohl(tvb,offset);
-
- ti = proto_tree_add_text(tree, tvb, offset, -1, "%s",
- val_to_str(sample_type, sflow_sampletype,
- "Unknown sample type"));
+ if (version != 5) {
+ sample_type = tvb_get_ntohl(tvb, offset);
+ ti = proto_tree_add_text(tree, tvb, offset, -1, "%s",
+ val_to_str(sample_type, sflow4_sampletype,
+ "Unknown sample type (v4)"));
+ } else {
+ sample_type = tvb_get_ntohl(tvb, offset) & 0x00000fff;
+ sample_enterprise = (tvb_get_ntohl(tvb, offset) & 0xfffff000) >> 12;
+ if (sample_enterprise == 0) {
+ ti = proto_tree_add_text(tree, tvb, offset, -1, "%s",
+ val_to_str(sample_type, sflow5_sampletype,
+ "Unknown sample type (v5)"));
+ } else {
+ ti = proto_tree_add_text(tree, tvb, offset, -1,
+ "Unsupported Enterprise: %s",
+ val_to_str(sample_enterprise, sminmpec_values, "%u"));
+ }
+ }
sflow_sample_tree = proto_item_add_subtree(ti, ett_sflow_sample);
- proto_tree_add_item(sflow_sample_tree, hf_sflow_sampletype, tvb,
- offset, 4, FALSE);
+ proto_tree_add_item(sflow_sample_tree, hf_sflow_sample_type, tvb, offset, 4, FALSE);
offset += 4;
switch (sample_type) {
case FLOWSAMPLE:
- offset = dissect_sflow_flow_sample(tvb, pinfo, sflow_sample_tree,
- offset, ti);
+ case EXPFLOWSAMPLES:
+ offset = dissect_sflow_flow_sample(tvb, pinfo, sflow_sample_tree, offset, ti, version);
break;
case COUNTERSSAMPLE:
- offset = dissect_sflow_counters_sample(tvb, sflow_sample_tree,
- offset, ti);
+ case EXPCOUNTERSAMPLES:
+ offset = dissect_sflow_counters_sample(tvb, sflow_sample_tree, offset, ti, version);
break;
default:
break;
@@ -979,22 +1323,22 @@ dissect_sflow(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
/* Set up structures needed to add the protocol subtree and manage it */
- proto_item *ti;
- proto_tree *sflow_tree;
+ proto_item *ti;
+ proto_tree *sflow_tree;
guint32 version, sub_agent_id, seqnum;
guint32 agent_address_type;
+ guint32 numsamples;
+ volatile guint offset=0;
+ guint i=0;
union {
guint8 v4[4];
guint8 v6[16];
} agent_address;
- guint32 numsamples;
- volatile guint offset=0;
- guint i=0;
/* Make entries in Protocol column and Info column on summary display */
- if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "sFlow");
-
+
/* create display subtree for the protocol */
ti = proto_tree_add_item(tree, proto_sflow, tvb, 0, -1, FALSE);
@@ -1002,34 +1346,32 @@ dissect_sflow(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
sflow_tree = proto_item_add_subtree(ti, ett_sflow);
version = tvb_get_ntohl(tvb, offset);
- if (check_col(pinfo->cinfo, COL_INFO))
+ if (check_col(pinfo->cinfo, COL_INFO))
col_add_fstr(pinfo->cinfo, COL_INFO, "V%u",
version);
- proto_tree_add_item(sflow_tree,
- hf_sflow_version, tvb, offset, 4, FALSE);
+ proto_tree_add_item(sflow_tree, hf_sflow_version, tvb, offset, 4, FALSE);
offset += 4;
agent_address_type = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(sflow_tree, hf_sflow_agent_address_type, tvb, offset, 4, FALSE);
offset += 4;
switch (agent_address_type) {
case ADDRESS_IPV4:
tvb_memcpy(tvb, agent_address.v4, offset, 4);
- if (check_col(pinfo->cinfo, COL_INFO))
+ if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, ", agent %s",
- ip_to_str(agent_address.v4));
- proto_tree_add_item(sflow_tree,
- hf_sflow_agent_address_v4, tvb, offset,
- 4, FALSE);
+ ip_to_str(agent_address.v4));
+ proto_tree_add_item(sflow_tree, hf_sflow_agent_address_v4,
+ tvb, offset, 4, FALSE);
offset += 4;
break;
case ADDRESS_IPV6:
tvb_memcpy(tvb, agent_address.v6, offset, 16);
- if (check_col(pinfo->cinfo, COL_INFO))
+ if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, ", agent %s",
- ip6_to_str((struct e_in6_addr *)agent_address.v6));
- proto_tree_add_item(sflow_tree,
- hf_sflow_agent_address_v6, tvb, offset,
- 16, FALSE);
+ ip6_to_str((struct e_in6_addr *)agent_address.v6));
+ proto_tree_add_item(sflow_tree, hf_sflow_agent_address_v6,
+ tvb, offset, 16, FALSE);
offset += 16;
break;
default:
@@ -1039,28 +1381,25 @@ dissect_sflow(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
if (version == 5) {
sub_agent_id = tvb_get_ntohl(tvb, offset);
- if (check_col(pinfo->cinfo, COL_INFO))
+ if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, ", sub-agent ID %u",
- sub_agent_id);
- proto_tree_add_uint(sflow_tree, hf_sflow_sub_agent_id, tvb,
- offset, 4, sub_agent_id);
+ sub_agent_id);
+ proto_tree_add_item(sflow_tree, hf_sflow_sub_agent_id,
+ tvb, offset, 4, FALSE);
offset += 4;
}
seqnum = tvb_get_ntohl(tvb, offset);
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, ", seq %u", seqnum);
- proto_tree_add_uint(sflow_tree, hf_sflow_seqnum, tvb,
- offset, 4, seqnum);
+ proto_tree_add_item(sflow_tree, hf_sflow_seqnum, tvb, offset, 4, FALSE);
offset += 4;
- proto_tree_add_item(sflow_tree, hf_sflow_sysuptime, tvb,
- offset, 4, FALSE);
+ proto_tree_add_item(sflow_tree, hf_sflow_sysuptime, tvb, offset, 4, FALSE);
offset += 4;
numsamples = tvb_get_ntohl(tvb,offset);
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, ", %u samples",
numsamples);
- proto_tree_add_uint(sflow_tree, hf_sflow_numsamples, tvb,
- offset, 4, numsamples);
+ proto_tree_add_item(sflow_tree, hf_sflow_numsamples, tvb, offset, 4, FALSE);
offset += 4;
/* Ok, we're now at the end of the sflow datagram header;
@@ -1068,15 +1407,9 @@ dissect_sflow(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
* the expected number of samples, and pass them to the appropriate
* dissectors.
*/
- if (version == 5) {
- proto_tree_add_text(sflow_tree, tvb, offset, -1,
- "sFlow V5 samples (please write and contribute code to dissect them!)");
- } else {
- for (i=0; i < numsamples; i++) {
- offset = dissect_sflow_samples(tvb, pinfo, sflow_tree,
- offset);
- }
- }
+
+ for (i=0; i < numsamples; i++)
+ offset = dissect_sflow_samples(tvb, pinfo, sflow_tree, offset, version);
return tvb_length(tvb);
}
@@ -1085,16 +1418,16 @@ dissect_sflow(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
static void
sflow_delete_callback(guint32 port)
{
- if ( port ) {
+ if (port) {
dissector_delete("udp.port", port, sflow_handle);
- }
+ }
}
static void
sflow_add_callback(guint32 port)
{
- if ( port ) {
+ if (port) {
dissector_add("udp.port", port, sflow_handle);
- }
+ }
}
@@ -1125,117 +1458,293 @@ proto_register_sflow(void)
/* Setup list of header fields See Section 1.6.1 for details*/
static hf_register_info hf[] = {
+
+ /* datagram header */
{ &hf_sflow_version,
{ "datagram version", "sflow.version",
- FT_UINT32, BASE_DEC, NULL, 0x0,
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "sFlow datagram version", HFILL }
+ },
+ { &hf_sflow_agent_address_type,
+ { "address type", "sflow.agent.addresstype",
+ FT_UINT32, BASE_DEC, VALS(sflow_agent_address_type), 0x0,
"sFlow datagram version", HFILL }
},
{ &hf_sflow_agent_address_v4,
{ "agent address", "sflow.agent",
- FT_IPv4, BASE_NONE, NULL, 0x0,
+ FT_IPv4, BASE_NONE, NULL, 0x0,
"sFlow Agent IP address", HFILL }
},
{ &hf_sflow_agent_address_v6,
{ "agent address", "sflow.agent.v6",
- FT_IPv6, BASE_NONE, NULL, 0x0,
+ FT_IPv6, BASE_NONE, NULL, 0x0,
"sFlow Agent IPv6 address", HFILL }
},
{ &hf_sflow_sub_agent_id,
{ "Sub-agent ID", "sflow.sub_agent_id",
- FT_UINT32, BASE_DEC, NULL, 0x0,
+ FT_UINT32, BASE_DEC, NULL, 0x0,
"sFlow sub-agent ID", HFILL }
},
{ &hf_sflow_seqnum,
{ "Sequence number", "sflow.sequence_number",
- FT_UINT32, BASE_DEC, NULL, 0x0,
+ FT_UINT32, BASE_DEC, NULL, 0x0,
"sFlow datagram sequence number", HFILL }
},
{ &hf_sflow_sysuptime,
{ "SysUptime", "sflow.sysuptime",
- FT_UINT32, BASE_DEC, NULL, 0x0,
+ FT_UINT32, BASE_DEC, NULL, 0x0,
"System Uptime", HFILL }
},
{ &hf_sflow_numsamples,
{ "NumSamples", "sflow.numsamples",
- FT_UINT32, BASE_DEC, NULL, 0x0,
+ FT_UINT32, BASE_DEC, NULL, 0x0,
"Number of samples in sFlow datagram", HFILL }
},
- { &hf_sflow_sampletype,
- { "sFlow sample type", "sflow.sampletype",
- FT_UINT32, BASE_DEC, VALS(sflow_sampletype), 0x0,
+
+ /* Common sample header */
+ { &hf_sflow_sample_type,
+ { "sFlow sample type", "sflow.sample.type",
+ FT_UINT32, BASE_DEC, VALS(sflow4_sampletype), 0x0,
"Type of sFlow sample", HFILL }
},
- { &hf_sflow_header_protocol,
- { "Header protocol", "sflow.header_protocol",
- FT_UINT32, BASE_DEC, VALS(sflow_header_protocol), 0x0,
+ { &hf_sflow_sample_type_enterprise,
+ { "sFlow sample type enterprise", "sflow.sample.enterprise",
+ FT_UINT32, BASE_DEC, NULL, 0xfffff000,
+ "Enterprise of sFlow sample", HFILL }
+ },
+ { &hf_sflow_sample_type_enterprisetype,
+ { "sFlow sample type", "sflow.sample.enterprisetype",
+ FT_UINT32, BASE_DEC, NULL, 0x00000fff,
+ "Enterprisetype of sFlow sample", HFILL }
+ },
+ { &hf_sflow_sample_length,
+ { "Sample length", "sflow.sample.length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+
+ /* Flowsample */
+ { &hf_sflow_fs_seqno,
+ { "Sequence number", "sflow.fs.seqno",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_sflow_fs_sourceid_type,
+ { "Source ID type", "sflow.fs.sourceidtype",
+ FT_UINT32, BASE_DEC, VALS(sflow_sample_sourceidtype), 0xff000000,
+ NULL, HFILL }
+ },
+ { &hf_sflow_fs_sourceid_index,
+ { "Source ID index", "sflow.fs.sourceidindex",
+ FT_UINT32, BASE_DEC, NULL, 0x00ffffff,
+ NULL, HFILL }
+ },
+ { &hf_sflow_fs_samplingrate,
+ { "Sampling rate", "sflow.fs.samplingrate",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Sample 1 out of N packets", HFILL }
+ },
+ { &hf_sflow_fs_samplepool,
+ { "Sample pool", "sflow.fs.pool",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Total number of packets", HFILL }
+ },
+ { &hf_sflow_fs_drops,
+ { "Dropped packets", "sflow.fs.pool",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_sflow_fs_ifindexin,
+ { "Input interface index", "sflow.fs.ifindexin",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_sflow_fs_multipleoutputs,
+ { "Multiple outputs", "sflow.fs.multipleoutputs",
+ FT_BOOLEAN, 32, TFS(&yes_no_truth), 0x80000000,
+ "Output to more than one interface", HFILL }
+ },
+ { &hf_sflow_fs_numoutinterfaces,
+ { "Number of interfaces", "sflow.fs.numoutinterfaces",
+ FT_UINT32, BASE_DEC, NULL, 0x7fffffff,
+ "Number of output interfaces", HFILL }
+ },
+ { &hf_sflow_fs_ifindexout,
+ { "Output interface index", "sflow.fs.ifindexout",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_sflow_fs_numrecords,
+ { "Number of records", "sflow.fs.numrecords",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of flowsample records", HFILL }
+ },
+ { &hf_sflow_fs_recordlength,
+ { "Recordlength", "sflow.fs.recordlength",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_sflow4_fs_record_type,
+ { "Sample type", "sflow.fs.recordtype",
+ FT_UINT32, BASE_DEC, VALS(sflow4_fs_record_type), 0x0,
+ "Type of flowsample", HFILL }
+ },
+ { &hf_sflow5_fs_record_type,
+ { "Sample type", "sflow.fs.recordtype",
+ FT_UINT32, BASE_DEC, VALS(sflow5_packet_fs_record_type), 0x0,
+ "Type of flowsample", HFILL }
+ },
+
+ /* Countersample */
+ { &hf_sflow_cs_seqno,
+ { "Sequence number", "sflow.cs.seqno",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_sflow_cs_sourceid_type,
+ { "Source ID type", "sflow.cs.sourceidtype",
+ FT_UINT32, BASE_DEC, VALS(sflow_sample_sourceidtype), 0xff000000,
+ NULL, HFILL }
+ },
+ { &hf_sflow_cs_sourceid_index,
+ { "Source ID index", "sflow.cs.sourceidindex",
+ FT_UINT32, BASE_DEC, NULL, 0x00ffffff,
+ NULL, HFILL }
+ },
+ { &hf_sflow_cs_samplingrate,
+ { "Sampling rate", "sflow.cs.samplingrate",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Sample 1 out of N packets", HFILL }
+ },
+ { &hf_sflow_cs_samplinginterval,
+ { "Sampling interval", "sflow.cs.samplinginterval",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_sflow_cs_numrecords,
+ { "Number of records", "sflow.cs.numrecords",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of countersample records", HFILL }
+ },
+ { &hf_sflow_cs_record_type,
+ { "Type of counters", "sflow.cs.recordtype",
+ FT_UINT32, BASE_DEC, VALS(sflow_counterstype), 0x0,
+ NULL, HFILL }
+ },
+ { &hf_sflow_cs_recordlength,
+ { "Recordlength", "sflow.cs.recordlength",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+
+ /* Flow record: raw packet header */
+ { &hf_sflow_fs_rawheader_protocol,
+ { "Header protocol", "sflow.fs.rawheader.protocol",
+ FT_UINT32, BASE_DEC, VALS(sflow_header_protocol), 0x0,
"Protocol of sampled header", HFILL }
},
- { &hf_sflow_header,
- { "Header of sampled packet", "sflow.header",
- FT_BYTES, BASE_HEX, NULL, 0x0,
+ { &hf_sflow_fs_rawheader_framelength,
+ { "Framelength", "sflow.fs.rawheader.framelength",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Total framelength of sampled packet", HFILL }
+ },
+ { &hf_sflow_fs_rawheader_stripped,
+ { "Stripped bytes", "sflow.fs.rawheader.stripped",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Bytes stripped from packet", HFILL }
+ },
+ { &hf_sflow_fs_rawheader_headerlength,
+ { "Headerlength", "sflow.fs.rawheader.headerlength",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Bytes sampled in packet", HFILL }
+ },
+ { &hf_sflow_fs_rawheader,
+ { "Header of sampled packet", "sflow.fs.rawheader",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
"Data from sampled header", HFILL }
},
- { &hf_sflow_packet_information_type,
- { "Sample type", "sflow.packet_information_type",
- FT_UINT32, BASE_DEC, VALS(sflow_packet_information_type), 0x0,
- "Type of sampled information", HFILL }
+
+ /* Flow record: ethernet header */
+ { &hf_sflow_fs_ethernet_framelength,
+ { "Framelength", "sflow.fs.ethernet.framelength",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Total framelength of sampled packet", HFILL }
+ },
+ { &hf_sflow_fs_ethernet_srcmac,
+ { "Ethertype", "sflow.fs.ethernet.srcmac",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ "Source MAC address of sampled packet", HFILL }
+ },
+ { &hf_sflow_fs_ethernet_dstmac,
+ { "Ethertype", "sflow.fs.ethernet.dstmac",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ "Destination MAC address of sampled packet", HFILL }
+ },
+ { &hf_sflow_fs_ethernet_type,
+ { "Ethertype", "sflow.fs.ethernet.type",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Ethertype of sampled packet", HFILL }
},
- { &hf_sflow_ip_length,
+
+ /* Flow record: ipv4 and ipv6 headers */
+ { &hf_sflow_fs_ip_length,
{ "IP Packet Length", "sflow.ip_length",
- FT_UINT32, BASE_DEC, NULL, 0x0,
+ FT_UINT32, BASE_DEC, NULL, 0x0,
"Length of IP Packet excluding lower layer encapsulation", HFILL }
},
- { &hf_sflow_ip_protocol,
+ { &hf_sflow_fs_ip_protocol,
{ "Protocol", "sflow.ip_protocol",
- FT_UINT32, BASE_HEX, NULL, 0x0,
+ FT_UINT32, BASE_HEX, NULL, 0x0,
"IP Protocol", HFILL }
},
- { &hf_sflow_src_ipv4,
+ { &hf_sflow_fs_ip_srcipv4,
{ "Src IP", "sflow.src_ipv4",
- FT_IPv4, BASE_NONE, NULL, 0x0,
+ FT_IPv4, BASE_NONE, NULL, 0x0,
"Source IPv4 Address", HFILL }
},
- { &hf_sflow_dst_ipv4,
+ { &hf_sflow_fs_ip_dstipv4,
{ "Dst IP", "sflow.dst_ipv4",
- FT_IPv4, BASE_NONE, NULL, 0x0,
+ FT_IPv4, BASE_NONE, NULL, 0x0,
"Destination IPv4 Address", HFILL }
},
- { &hf_sflow_src_ipv6,
+ { &hf_sflow_fs_ip_srcipv6,
{ "Src IP", "sflow.src_ipv6",
- FT_IPv6, BASE_NONE, NULL, 0x0,
+ FT_IPv6, BASE_NONE, NULL, 0x0,
"Source IPv6 Address", HFILL }
},
- { &hf_sflow_dst_ipv6,
+ { &hf_sflow_fs_ip_dstipv6,
{ "Dst IP", "sflow.dst_ipv6",
- FT_IPv6, BASE_NONE, NULL, 0x0,
+ FT_IPv6, BASE_NONE, NULL, 0x0,
"Destination IPv6 Address", HFILL }
},
- { &hf_sflow_src_port,
+ { &hf_sflow_fs_ip_srcport,
{ "Src Port", "sflow.src_port",
- FT_UINT32, BASE_DEC, NULL, 0x0,
+ FT_UINT32, BASE_DEC, NULL, 0x0,
"Source Port Number", HFILL }
},
- { &hf_sflow_dst_port,
+ { &hf_sflow_fs_ip_dstport,
{ "Dst Port", "sflow.dst_port",
- FT_UINT32, BASE_DEC, NULL, 0x0,
+ FT_UINT32, BASE_DEC, NULL, 0x0,
"Dst Port Number", HFILL }
},
- { &hf_sflow_tcp_flags,
- { "TCP Flags", "sflow.ip_protocol",
- FT_UINT32, BASE_HEX, NULL, 0x0,
+ { &hf_sflow_fs_ip_tcpflags,
+ { "TCP Flags", "sflow.ip_flags",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
"TCP Flags", HFILL }
},
- { &hf_sflow_tos,
+ { &hf_sflow_fs_ip_tos, /* IPv4 */
{ "ToS", "sflow.tos",
- FT_UINT32, BASE_HEX, NULL, 0x0,
+ FT_UINT32, BASE_HEX, NULL, 0x0,
"Type of Service", HFILL }
},
- { &hf_sflow_priority,
+ { &hf_sflow_fs_ip_priority, /* IPv6 */
{ "Priority", "sflow.priority",
- FT_UINT32, BASE_HEX, NULL, 0x0,
+ FT_UINT32, BASE_HEX, NULL, 0x0,
"Priority", HFILL }
},
- { &hf_sflow_extended_information_type,
+
+ /* XXX Fix naming for everything between here and hf_sflow_eth_... */
+ { &hf_sflow4_extended_information_type,
{ "Extended information type", "sflow.extended_information_type",
FT_UINT32, BASE_DEC, VALS(sflow_extended_data_types), 0x0,
"Type of extended information", HFILL }
@@ -1322,11 +1831,11 @@ proto_register_sflow(void)
"Gateway Communities", HFILL }
},
{ &hf_sflow_localpref,
- { "localpref", "sflow.localpref",
+ { "localpref", "sflow.localpref",
FT_UINT32, BASE_DEC, NULL, 0x0,
"Local preferences of AS route", HFILL }
},
- /**/
+ /* generic counters */
{ &hf_sflow_iftype,
{ "Interface Type", "sflow.iftype",
FT_UINT32, BASE_DEC, NULL, 0x0,
@@ -1339,23 +1848,33 @@ proto_register_sflow(void)
},
{ &hf_sflow_ifdirection,
{ "Interface Direction", "sflow.ifdirection",
- FT_UINT32, BASE_DEC, NULL, 0x0,
+ FT_UINT32, BASE_DEC, VALS(if_direction_vals), 0x0,
"Interface Direction", HFILL }
},
- { &hf_sflow_ifstatus,
- { "Interface Status", "sflow.ifstatus",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "Interface Status", HFILL }
+ { &hf_sflow_ifstatus_unused,
+ { "If status (unused)", "sflow.ifstatus.unused",
+ FT_UINT32, BASE_DEC, NULL, 0xfffffffc,
+ "Unused interface status bits", HFILL }
+ },
+ { &hf_sflow_ifstatus_admin,
+ { "If admin status", "sflow.ifstatus.admin",
+ FT_UINT32, BASE_DEC, NULL, 0x00000001,
+ "Interface admin status bit", HFILL }
+ },
+ { &hf_sflow_ifstatus_oper,
+ { "If oper status", "sflow.ifstatus.oper",
+ FT_UINT32, BASE_DEC, NULL, 0x00000002,
+ "Interface operational status bit", HFILL }
},
{ &hf_sflow_ifinoct,
{ "Input Octets", "sflow.ifinoct",
FT_UINT64, BASE_DEC, NULL, 0x0,
"Interface Input Octets", HFILL }
},
- { &hf_sflow_ifinpkt,
- { "Input Packets", "sflow.ifinpkt",
+ { &hf_sflow_ifinucast,
+ { "Input unicast packets", "sflow.ifinucast",
FT_UINT32, BASE_DEC, NULL, 0x0,
- "Interface Input Packets", HFILL }
+ "Interface Input Unicast Packets", HFILL }
},
{ &hf_sflow_ifinmcast,
{ "Input Multicast Packets", "sflow.ifinmcast",
@@ -1387,10 +1906,10 @@ proto_register_sflow(void)
FT_UINT64, BASE_DEC, NULL, 0x0,
"Outterface Output Octets", HFILL }
},
- { &hf_sflow_ifoutpkt,
- { "Output Packets", "sflow.ifoutpkt",
+ { &hf_sflow_ifoutucast,
+ { "Output unicast packets", "sflow.ifoutucast",
FT_UINT32, BASE_DEC, NULL, 0x0,
- "Interface Output Packets", HFILL }
+ "Interface Output Unicast Packets", HFILL }
},
{ &hf_sflow_ifoutmcast,
{ "Output Multicast Packets", "sflow.ifoutmcast",
@@ -1417,6 +1936,72 @@ proto_register_sflow(void)
FT_UINT32, BASE_DEC, NULL, 0x0,
"Interface Promiscuous Mode", HFILL }
},
+ /* ethernet counters */
+ { &hf_sflow_eth_dot3StatsAlignmentErrors,
+ { "dot3StatsAlignmentErrors", "sflow.cs.eth.dot3StatsAlignmentErrors",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_sflow_eth_dot3StatsFCSErrors,
+ { "dot3StatsFCSErrors", "sflow.cs.eth.dot3StatsFCSErrors",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_sflow_eth_dot3StatsSingleCollisionFrames,
+ { "dot3StatsSingleCollisionFrames", "sflow.cs.eth.dot3StatsSingleCollisionFrames",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_sflow_eth_dot3StatsMultipleCollisionFrames,
+ { "dot3StatsMultipleCollisionFrames", "sflow.cs.eth.dot3StatsMultipleCollisionFrames",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_sflow_eth_dot3StatsSQETestErrors,
+ { "dot3StatsSQETestErrors", "sflow.cs.eth.dot3StatsSQETestErrors",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_sflow_eth_dot3StatsDeferredTransmissions,
+ { "dot3StatsDeferredTransmissions", "sflow.cs.eth.dot3StatsDeferredTransmissions",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_sflow_eth_dot3StatsLateCollisions,
+ { "dot3StatsLateCollisions", "sflow.cs.eth.dot3StatsLateCollisions",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_sflow_eth_dot3StatsExcessiveCollisions,
+ { "dot3StatsExcessiveCollisions", "sflow.cs.eth.dot3StatsExcessiveCollisions",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_sflow_eth_dot3StatsInternalMacTransmitErrors,
+ { "dot3StatsInternalMacTransmitErrors", "sflow.cs.eth.dot3StatsInternalMacTransmitErrors",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_sflow_eth_dot3StatsCarrierSenseErrors,
+ { "dot3StatsCarrierSenseErrors", "sflow.cs.eth.dot3StatsCarrierSenseErrors",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_sflow_eth_dot3StatsFrameTooLongs,
+ { "dot3StatsFrameTooLongs", "sflow.cs.eth.dot3StatsFrameTooLongs",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_sflow_eth_dot3StatsInternalMacReceiveErrors,
+ { "dot3StatsInternalMacReceiveErrors", "sflow.cs.eth.dot3StatsInternalMacReceiveErrors",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_sflow_eth_dot3StatsSymbolErrors,
+ { "dot3StatsSymbolErrors", "sflow.cs.eth.dot3StatsSymbolErrors",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
};
/* Setup protocol subtree array */
@@ -1428,6 +2013,7 @@ proto_register_sflow(void)
&ett_sflow_gw_as_dst_seg,
&ett_sflow_gw_community,
&ett_sflow_sampled_header,
+ &ett_sflow_counters_record,
};
/* Register the protocol name and description */
@@ -1454,7 +2040,7 @@ proto_register_sflow(void)
" (default: " SFLOW_UDP_PORTS ")",
&global_sflow_ports, MAX_UDP_PORT);
- /*
+ /*
If I use a filter like "ip.src == 10.1.1.1" this will, in
addition to the usual suspects, find every sFlow packet
where *any* of the payload headers contain 10.1.1.1 as a
@@ -1468,7 +2054,7 @@ proto_register_sflow(void)
"Dissect data in sampled headers",
"Enabling dissection makes it easy to view protocol details in each of the sampled headers. Disabling dissection may reduce noise caused when display filters match the contents of any sampled header(s).",
&global_dissect_samp_headers);
- /*
+ /*
It is not clear to me that it *ever* makes sense to enable
this option. However, it was previously the default
behavior so I'll leave it as an option if someone thinks
@@ -1545,9 +2131,3 @@ proto_reg_handoff_sflow(void)
}
-
-/* Local Variables: ***/
-/* mode:C ***/
-/* c-basic-offset:4 ***/
-/* tab-width:4 ***/
-/* End: ***/