#include "extract.h"
#include "addrtoname.h"
-/*
+/*
* sFlow datagram
- *
+ *
* 0 1 2 3
* 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | num samples in datagram |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
+ *
*/
struct sflow_datagram_t {
{ SFLOW_HEADER_PROTOCOL_IPV6, "IPv6"},
{ 0, NULL}
};
-
+
struct sflow_expanded_flow_raw_t {
u_int8_t protocol[4];
u_int8_t length[4];
u_int8_t header_size[4];
};
+struct sflow_ethernet_frame_t {
+ u_int8_t length[4];
+ u_int8_t src_mac[8];
+ u_int8_t dst_mac[8];
+ u_int8_t type[4];
+};
+
struct sflow_extended_switch_data_t {
u_int8_t src_vlan[4];
u_int8_t src_pri[4];
{ SFLOW_IFACE_DIRECTION_IN, "in"},
{ SFLOW_IFACE_DIRECTION_OUT, "out"},
{ 0, NULL}
-};
+};
struct sflow_generic_counter_t {
u_int8_t ifindex[4];
u_int8_t iftype[4];
u_int8_t ifspeed[8];
- u_int8_t ifdirection[4];
+ u_int8_t ifdirection[4];
u_int8_t ifstatus[4];
- u_int8_t ifinoctets[8];
- u_int8_t ifinunicastpkts[4];
- u_int8_t ifinmulticastpkts[4];
- u_int8_t ifinbroadcastpkts[4];
- u_int8_t ifindiscards[4];
- u_int8_t ifinerrors[4];
- u_int8_t ifinunkownprotos[4];
+ u_int8_t ifinoctets[8];
+ u_int8_t ifinunicastpkts[4];
+ u_int8_t ifinmulticastpkts[4];
+ u_int8_t ifinbroadcastpkts[4];
+ u_int8_t ifindiscards[4];
+ u_int8_t ifinerrors[4];
+ u_int8_t ifinunkownprotos[4];
u_int8_t ifoutoctets[8];
- u_int8_t ifoutunicastpkts[4];
- u_int8_t ifoutmulticastpkts[4];
- u_int8_t ifoutbroadcastpkts[4];
- u_int8_t ifoutdiscards[4];
- u_int8_t ifouterrors[4];
- u_int8_t ifpromiscmode[4];
+ u_int8_t ifoutunicastpkts[4];
+ u_int8_t ifoutmulticastpkts[4];
+ u_int8_t ifoutbroadcastpkts[4];
+ u_int8_t ifoutdiscards[4];
+ u_int8_t ifouterrors[4];
+ u_int8_t ifpromiscmode[4];
};
struct sflow_ethernet_counter_t {
u_int8_t in_highpriority_octets[8];
u_int8_t in_normpriority_frames[4];
u_int8_t in_normpriority_octets[8];
- u_int8_t in_ipmerrors[4];
- u_int8_t in_oversized[4];
+ u_int8_t in_ipmerrors[4];
+ u_int8_t in_oversized[4];
u_int8_t in_data_errors[4];
u_int8_t in_null_addressed_frames[4];
u_int8_t out_highpriority_frames[4];
sflow_gen_counter = (const struct sflow_generic_counter_t *)pointer;
- printf("\n\t ifindex %u, iftype %u, ifspeed %u, ifdirection %u (%s)",
+ printf("\n\t ifindex %u, iftype %u, ifspeed %" PRIu64 ", ifdirection %u (%s)",
EXTRACT_32BITS(sflow_gen_counter->ifindex),
EXTRACT_32BITS(sflow_gen_counter->iftype),
- EXTRACT_32BITS(sflow_gen_counter->ifspeed),
+ EXTRACT_64BITS(sflow_gen_counter->ifspeed),
EXTRACT_32BITS(sflow_gen_counter->ifdirection),
tok2str(sflow_iface_direction_values, "Unknown",
EXTRACT_32BITS(sflow_gen_counter->ifdirection)));
EXTRACT_32BITS(sflow_gen_counter->ifoutmulticastpkts),
EXTRACT_32BITS(sflow_gen_counter->ifoutbroadcastpkts),
EXTRACT_32BITS(sflow_gen_counter->ifoutdiscards));
- printf("\n\t Out errors %u, promisc mode %u",
+ printf("\n\t Out errors %u, promisc mode %u",
EXTRACT_32BITS(sflow_gen_counter->ifouterrors),
EXTRACT_32BITS(sflow_gen_counter->ifpromiscmode));
EXTRACT_32BITS(sflow_eth_counter->single_collision_frames),
EXTRACT_32BITS(sflow_eth_counter->multiple_collision_frames),
EXTRACT_32BITS(sflow_eth_counter->test_errors));
- printf("\n\t deferred %u, late collision %u, excessive collision %u, mac trans error %u",
+ printf("\n\t deferred %u, late collision %u, excessive collision %u, mac trans error %u",
EXTRACT_32BITS(sflow_eth_counter->deferred_transmissions),
EXTRACT_32BITS(sflow_eth_counter->late_collisions),
EXTRACT_32BITS(sflow_eth_counter->excessive_collisions),
EXTRACT_32BITS(sflow_eth_counter->mac_transmit_errors));
- printf("\n\t carrier error %u, frames too long %u, mac receive errors %u, symbol errors %u",
+ printf("\n\t carrier error %u, frames too long %u, mac receive errors %u, symbol errors %u",
EXTRACT_32BITS(sflow_eth_counter->carrier_sense_errors),
EXTRACT_32BITS(sflow_eth_counter->frame_too_longs),
EXTRACT_32BITS(sflow_eth_counter->mac_receive_errors),
print_sflow_counter_vlan(const u_char *pointer, u_int len) {
const struct sflow_vlan_counter_t *sflow_vlan_counter;
-
+
if (len < sizeof(struct sflow_vlan_counter_t))
return 1;
u_int tlen;
u_int counter_type;
u_int counter_len;
+ u_int enterprise;
const struct sflow_counter_record_t *sflow_counter_record;
nrecords = records;
return 1;
sflow_counter_record = (const struct sflow_counter_record_t *)tptr;
- counter_type = EXTRACT_32BITS(sflow_counter_record->format);
+ enterprise = EXTRACT_32BITS(sflow_counter_record->format);
+ counter_type = enterprise & 0x0FFF;
+ enterprise = enterprise >> 20;
counter_len = EXTRACT_32BITS(sflow_counter_record->length);
- printf("\n\t %s (%u) length %u",
- tok2str(sflow_counter_type_values,"Unknown",counter_type),
+ printf("\n\t enterprise %u, %s (%u) length %u",
+ enterprise,
+ (enterprise == 0) ? tok2str(sflow_counter_type_values,"Unknown",counter_type) : "Unknown",
counter_type,
counter_len);
if (tlen < counter_len)
return 1;
-
- switch (counter_type) {
- case SFLOW_COUNTER_GENERIC:
- if (print_sflow_counter_generic(tptr,tlen))
- return 1;
- break;
- case SFLOW_COUNTER_ETHERNET:
- if (print_sflow_counter_ethernet(tptr,tlen))
- return 1;
- break;
- case SFLOW_COUNTER_TOKEN_RING:
- if (print_sflow_counter_token_ring(tptr,tlen))
- return 1;
- break;
- case SFLOW_COUNTER_BASEVG:
- if (print_sflow_counter_basevg(tptr,tlen))
- return 1;
- break;
- case SFLOW_COUNTER_VLAN:
- if (print_sflow_counter_vlan(tptr,tlen))
- return 1;
- break;
- case SFLOW_COUNTER_PROCESSOR:
- if (print_sflow_counter_processor(tptr,tlen))
- return 1;
- break;
- default:
- if (vflag <= 1)
- print_unknown_data(tptr, "\n\t\t", counter_len);
- break;
+ if (enterprise == 0) {
+ switch (counter_type) {
+ case SFLOW_COUNTER_GENERIC:
+ if (print_sflow_counter_generic(tptr,tlen))
+ return 1;
+ break;
+ case SFLOW_COUNTER_ETHERNET:
+ if (print_sflow_counter_ethernet(tptr,tlen))
+ return 1;
+ break;
+ case SFLOW_COUNTER_TOKEN_RING:
+ if (print_sflow_counter_token_ring(tptr,tlen))
+ return 1;
+ break;
+ case SFLOW_COUNTER_BASEVG:
+ if (print_sflow_counter_basevg(tptr,tlen))
+ return 1;
+ break;
+ case SFLOW_COUNTER_VLAN:
+ if (print_sflow_counter_vlan(tptr,tlen))
+ return 1;
+ break;
+ case SFLOW_COUNTER_PROCESSOR:
+ if (print_sflow_counter_processor(tptr,tlen))
+ return 1;
+ break;
+ default:
+ if (vflag <= 1)
+ print_unknown_data(gndo,tptr, "\n\t\t", counter_len);
+ break;
+ }
}
tptr += counter_len;
tlen -= counter_len;
nrecords--;
-
+
}
return 0;
nrecords = EXTRACT_32BITS(sflow_counter_sample->records);
type = typesource >> 24;
index = typesource & 0x0FFF;
-
+
printf(" seqnum %u, type %u, idx %u, records %u",
EXTRACT_32BITS(sflow_counter_sample->seqnum),
type,
EXTRACT_32BITS(sflow_expanded_counter_sample->type),
EXTRACT_32BITS(sflow_expanded_counter_sample->index),
nrecords);
-
+
return sflow_print_counter_records(pointer + sizeof(struct sflow_expanded_counter_sample_t),
len - sizeof(struct sflow_expanded_counter_sample_t),
nrecords);
return 0;
}
+static int
+print_sflow_ethernet_frame(const u_char *pointer, u_int len) {
+
+ const struct sflow_ethernet_frame_t *sflow_ethernet_frame;
+
+ if (len < sizeof(struct sflow_ethernet_frame_t))
+ return 1;
+
+ sflow_ethernet_frame = (const struct sflow_ethernet_frame_t *)pointer;
+
+ printf("\n\t frame len %u, type %u",
+ EXTRACT_32BITS(sflow_ethernet_frame->length),
+ EXTRACT_32BITS(sflow_ethernet_frame->type));
+
+ return 0;
+}
static int
print_sflow_extended_switch_data(const u_char *pointer, u_int len) {
const u_char *tptr;
u_int tlen;
u_int flow_type;
+ u_int enterprise;
u_int flow_len;
const struct sflow_flow_record_t *sflow_flow_record;
sflow_flow_record = (const struct sflow_flow_record_t *)tptr;
- flow_type = EXTRACT_32BITS(sflow_flow_record->format) & 0x0FFF;
+ /* so, the funky encoding means we cannot blythly mask-off
+ bits, we must also check the enterprise. */
+
+ enterprise = EXTRACT_32BITS(sflow_flow_record->format);
+ flow_type = enterprise & 0x0FFF;
+ enterprise = enterprise >> 12;
flow_len = EXTRACT_32BITS(sflow_flow_record->length);
- printf("\n\t %s (%u) length %u",
- tok2str(sflow_flow_type_values,"Unknown",flow_type),
+ printf("\n\t enterprise %u %s (%u) length %u",
+ enterprise,
+ (enterprise == 0) ? tok2str(sflow_flow_type_values,"Unknown",flow_type) : "Unknown",
flow_type,
flow_len);
if (tlen < flow_len)
return 1;
- switch (flow_type) {
- case SFLOW_FLOW_RAW_PACKET:
- if (print_sflow_raw_packet(tptr,tlen))
- return 1;
- break;
- case SFLOW_FLOW_EXTENDED_SWITCH_DATA:
- if (print_sflow_extended_switch_data(tptr,tlen))
- return 1;
- break;
- /* FIXME these need a decoder */
- case SFLOW_FLOW_ETHERNET_FRAME:
- case SFLOW_FLOW_IPV4_DATA:
- case SFLOW_FLOW_IPV6_DATA:
- case SFLOW_FLOW_EXTENDED_ROUTER_DATA:
- case SFLOW_FLOW_EXTENDED_GATEWAY_DATA:
- case SFLOW_FLOW_EXTENDED_USER_DATA:
- case SFLOW_FLOW_EXTENDED_URL_DATA:
- case SFLOW_FLOW_EXTENDED_MPLS_DATA:
- case SFLOW_FLOW_EXTENDED_NAT_DATA:
- case SFLOW_FLOW_EXTENDED_MPLS_TUNNEL:
- case SFLOW_FLOW_EXTENDED_MPLS_VC:
- case SFLOW_FLOW_EXTENDED_MPLS_FEC:
- case SFLOW_FLOW_EXTENDED_MPLS_LVP_FEC:
- case SFLOW_FLOW_EXTENDED_VLAN_TUNNEL:
- break;
- default:
- if (vflag <= 1)
- print_unknown_data(tptr, "\n\t\t", flow_len);
- break;
+ if (enterprise == 0) {
+ switch (flow_type) {
+ case SFLOW_FLOW_RAW_PACKET:
+ if (print_sflow_raw_packet(tptr,tlen))
+ return 1;
+ break;
+ case SFLOW_FLOW_EXTENDED_SWITCH_DATA:
+ if (print_sflow_extended_switch_data(tptr,tlen))
+ return 1;
+ break;
+ case SFLOW_FLOW_ETHERNET_FRAME:
+ if (print_sflow_ethernet_frame(tptr,tlen))
+ return 1;
+ break;
+ /* FIXME these need a decoder */
+ case SFLOW_FLOW_IPV4_DATA:
+ case SFLOW_FLOW_IPV6_DATA:
+ case SFLOW_FLOW_EXTENDED_ROUTER_DATA:
+ case SFLOW_FLOW_EXTENDED_GATEWAY_DATA:
+ case SFLOW_FLOW_EXTENDED_USER_DATA:
+ case SFLOW_FLOW_EXTENDED_URL_DATA:
+ case SFLOW_FLOW_EXTENDED_MPLS_DATA:
+ case SFLOW_FLOW_EXTENDED_NAT_DATA:
+ case SFLOW_FLOW_EXTENDED_MPLS_TUNNEL:
+ case SFLOW_FLOW_EXTENDED_MPLS_VC:
+ case SFLOW_FLOW_EXTENDED_MPLS_FEC:
+ case SFLOW_FLOW_EXTENDED_MPLS_LVP_FEC:
+ case SFLOW_FLOW_EXTENDED_VLAN_TUNNEL:
+ break;
+ default:
+ if (vflag <= 1)
+ print_unknown_data(gndo,tptr, "\n\t\t", flow_len);
+ break;
+ }
}
tptr += flow_len;
tlen -= flow_len;
type = typesource >> 24;
index = typesource & 0x0FFF;
- printf(" seqnum %u, type %u, idx %u, records %u",
+ printf(" seqnum %u, type %u, idx %u, rate %u, pool %u, drops %u, input %u output %u records %u",
EXTRACT_32BITS(sflow_flow_sample->seqnum),
type,
index,
+ EXTRACT_32BITS(sflow_flow_sample->rate),
+ EXTRACT_32BITS(sflow_flow_sample->pool),
+ EXTRACT_32BITS(sflow_flow_sample->drops),
+ EXTRACT_32BITS(sflow_flow_sample->in_interface),
+ EXTRACT_32BITS(sflow_flow_sample->out_interface),
nrecords);
return sflow_print_flow_records(pointer + sizeof(struct sflow_flow_sample_t),
EXTRACT_32BITS(sflow_expanded_flow_sample->pool),
EXTRACT_32BITS(sflow_expanded_flow_sample->drops),
EXTRACT_32BITS(sflow_expanded_flow_sample->records));
-
+
return sflow_print_flow_records(pointer + sizeof(struct sflow_expanded_flow_sample_t),
len - sizeof(struct sflow_expanded_flow_sample_t),
nrecords);
EXTRACT_32BITS(sflow_datagram->version),
EXTRACT_32BITS(sflow_datagram->ip_version) == 1 ? "IPv4" : "IPv6",
ipaddr_string(sflow_datagram->agent),
- EXTRACT_32BITS(sflow_datagram->samples),
+ EXTRACT_32BITS(sflow_datagram->agent_id),
len);
return;
}
tptr += sizeof(struct sflow_sample_header);
tlen -= sizeof(struct sflow_sample_header);
-
+
printf("\n\t%s (%u), length %u,",
tok2str(sflow_format_values, "Unknown", sflow_sample_type),
sflow_sample_type,
default:
if (vflag <= 1)
- print_unknown_data(tptr, "\n\t ", sflow_sample_len);
+ print_unknown_data(gndo,tptr, "\n\t ", sflow_sample_len);
break;
}
tptr += sflow_sample_len;