-/* Copyright (c) 2002-2009 InMon Corp. Licensed under the terms of the InMon sFlow licence: */
-/* http://www.inmon.com/technology/sflowlicense.txt */
+/* Copyright (c) 2002-2009 InMon Corp. Licensed under the terms of either the
+ * Sun Industry Standards Source License 1.1, that is available at:
+ * http://host-sflow.sourceforge.net/sissl.html
+ * or the InMon sFlow License, that is available at:
+ * http://www.inmon.com/technology/sflowlicense.txt
+ */
+
+#ifndef __CHECKER__ /* Don't run sparse on anything in this file. */
#include <assert.h>
#include "sflow_api.h"
}
void sfl_receiver_set_sFlowRcvrTimeout(SFLReceiver *receiver, time_t sFlowRcvrTimeout) {
receiver->sFlowRcvrTimeout =sFlowRcvrTimeout;
-}
+}
u_int32_t sfl_receiver_get_sFlowRcvrMaximumDatagramSize(SFLReceiver *receiver) {
return receiver->sFlowRcvrMaximumDatagramSize;
}
_________________ receiver write utilities __________________
-----------------_____________________________------------------
*/
-
+
inline static void put32(SFLReceiver *receiver, u_int32_t val)
{
*receiver->sampleCollector.datap++ = val;
putNet32(receiver, s->len);
memcpy(receiver->sampleCollector.datap, s->str, s->len);
receiver->sampleCollector.datap += (s->len + 3) / 4; /* pad to 4-byte boundary */
+ if ((s->len % 4) != 0){
+ u_int8_t padding = 4 - (s->len % 4);
+ memset(((u_int8_t*)receiver->sampleCollector.datap)-padding, 0, padding);
+ }
}
inline static u_int32_t stringEncodingLength(SFLString *s) {
return (addr->type == SFLADDRESSTYPE_IP_V6) ? 20 : 8; // type + address (unspecified == IPV4)
}
-inline static void putMACAddress(SFLReceiver *receiver, u_int8_t *mac)
+inline static void putMACAddress(SFLReceiver *receiver,
+ const struct eth_addr mac)
{
- memcpy(receiver->sampleCollector.datap, mac, 6);
+ memcpy(receiver->sampleCollector.datap, &mac, 6);
receiver->sampleCollector.datap += 2;
}
inline static u_int32_t gatewayEncodingLength(SFLExtended_gateway *gw) {
u_int32_t elemSiz = addressEncodingLength(&gw->nexthop);
u_int32_t seg = 0;
- elemSiz += 16; // as, src_as, src_peer_as, dst_as_path_segments
+ elemSiz += 16; // as, src_as, src_peer_as, dst_as_path_segments
for(; seg < gw->dst_as_path_segments; seg++) {
- elemSiz += 8; // type, length
+ elemSiz += 8; // type, length
elemSiz += 4 * gw->dst_as_path[seg].length; // set/seq bytes
}
elemSiz += 4; // communities_length
case SFLFLOW_EX_MPLS_FTN: elemSiz = mplsFtnEncodingLength(&elem->flowType.mpls_ftn); break;
case SFLFLOW_EX_MPLS_LDP_FEC: elemSiz = mplsLdpFecEncodingLength(&elem->flowType.mpls_ldp_fec); break;
case SFLFLOW_EX_VLAN_TUNNEL: elemSiz = vlanTunnelEncodingLength(&elem->flowType.vlan_tunnel); break;
+ case SFLFLOW_EX_IPV4_TUNNEL_EGRESS:
+ case SFLFLOW_EX_IPV4_TUNNEL_INGRESS:
+ elemSiz = sizeof(SFLSampled_ipv4);
+ break;
+ case SFLFLOW_EX_VNI_EGRESS:
+ case SFLFLOW_EX_VNI_INGRESS:
+ elemSiz = sizeof(SFLExtended_vni);
+ break;
default:
sflError(receiver, "unexpected packet_data_tag");
return -1;
// it over the limit, then we should send it now before going on.
if((receiver->sampleCollector.pktlen + packedSize) >= receiver->sFlowRcvrMaximumDatagramSize)
sendSample(receiver);
-
+
receiver->sampleCollector.numSamples++;
#ifdef SFL_USE_32BIT_INDEX
{
SFLFlow_sample_element *elem = fs->elements;
for(; elem != NULL; elem = elem->nxt) {
-
+
putNet32(receiver, elem->tag);
putNet32(receiver, elem->length); // length cached in computeFlowSampleSize()
-
+
switch(elem->tag) {
case SFLFLOW_HEADER:
putNet32(receiver, elem->flowType.header.header_protocol);
putNet32(receiver, elem->flowType.ethernet.eth_type);
break;
case SFLFLOW_IPV4:
+ case SFLFLOW_EX_IPV4_TUNNEL_EGRESS:
+ case SFLFLOW_EX_IPV4_TUNNEL_INGRESS:
putNet32(receiver, elem->flowType.ipv4.length);
putNet32(receiver, elem->flowType.ipv4.protocol);
put32(receiver, elem->flowType.ipv4.src_ip.addr);
case SFLFLOW_EX_MPLS_FTN: putMplsFtn(receiver, &elem->flowType.mpls_ftn); break;
case SFLFLOW_EX_MPLS_LDP_FEC: putMplsLdpFec(receiver, &elem->flowType.mpls_ldp_fec); break;
case SFLFLOW_EX_VLAN_TUNNEL: putVlanTunnel(receiver, &elem->flowType.vlan_tunnel); break;
+ case SFLFLOW_EX_VNI_EGRESS:
+ case SFLFLOW_EX_VNI_INGRESS:
+ putNet32(receiver, elem->flowType.tunnel_vni.vni);
+ break;
+
default:
sflError(receiver, "unexpected packet_data_tag");
return -1;
cs->num_elements++;
siz += 8; /* tag, length */
switch(elem->tag) {
- case SFLCOUNTERS_GENERIC: elemSiz = sizeof(elem->counterBlock.generic); break;
- case SFLCOUNTERS_ETHERNET: elemSiz = sizeof(elem->counterBlock.ethernet); break;
+ case SFLCOUNTERS_GENERIC: elemSiz = SFL_CTR_GENERIC_XDR_SIZE; break;
+ case SFLCOUNTERS_ETHERNET: elemSiz = SFL_CTR_ETHERNET_XDR_SIZE; break;
case SFLCOUNTERS_TOKENRING: elemSiz = sizeof(elem->counterBlock.tokenring); break;
case SFLCOUNTERS_VG: elemSiz = sizeof(elem->counterBlock.vg); break;
case SFLCOUNTERS_VLAN: elemSiz = sizeof(elem->counterBlock.vlan); break;
+ case SFLCOUNTERS_LACP: elemSiz = SFL_CTR_LACP_XDR_SIZE; break;
+ case SFLCOUNTERS_OPENFLOWPORT: elemSiz = SFL_CTR_OPENFLOWPORT_XDR_SIZE; break;
+ case SFLCOUNTERS_PORTNAME: elemSiz = stringEncodingLength(&elem->counterBlock.portName.portName); break;
+ case SFLCOUNTERS_APP_RESOURCES: elemSiz = SFL_CTR_APP_RESOURCES_XDR_SIZE; break;
+ case SFLCOUNTERS_OVSDP: elemSiz = SFL_CTR_OVSDP_XDR_SIZE; break;
default:
sflError(receiver, "unexpected counters_tag");
return -1;
// if the sample pkt is full enough so that this sample might put
// it over the limit, then we should send it now.
if((packedSize = computeCountersSampleSize(receiver, cs)) == -1) return -1;
-
+
// check in case this one sample alone is too big for the datagram
// in fact - if it is even half as big then we should ditch it. Very
// important to avoid overruning the packet buffer.
sflError(receiver, "counters sample too big for datagram");
return -1;
}
-
+
if((receiver->sampleCollector.pktlen + packedSize) >= receiver->sFlowRcvrMaximumDatagramSize)
sendSample(receiver);
-
+
receiver->sampleCollector.numSamples++;
-
+
#ifdef SFL_USE_32BIT_INDEX
putNet32(receiver, SFLCOUNTERS_SAMPLE_EXPANDED);
#else
#endif
putNet32(receiver, cs->num_elements);
-
+
{
SFLCounters_sample_element *elem = cs->elements;
for(; elem != NULL; elem = elem->nxt) {
-
+
putNet32(receiver, elem->tag);
putNet32(receiver, elem->length); // length cached in computeCountersSampleSize()
-
+
switch(elem->tag) {
case SFLCOUNTERS_GENERIC:
putGenericCounters(receiver, &(elem->counterBlock.generic));
putNet32(receiver, elem->counterBlock.vlan.broadcastPkts);
putNet32(receiver, elem->counterBlock.vlan.discards);
break;
+ case SFLCOUNTERS_LACP:
+ putMACAddress(receiver, elem->counterBlock.lacp.actorSystemID);
+ putMACAddress(receiver, elem->counterBlock.lacp.partnerSystemID);
+ putNet32(receiver, elem->counterBlock.lacp.attachedAggID);
+ put32(receiver, elem->counterBlock.lacp.portState.all);
+ putNet32(receiver, elem->counterBlock.lacp.LACPDUsRx);
+ putNet32(receiver, elem->counterBlock.lacp.markerPDUsRx);
+ putNet32(receiver, elem->counterBlock.lacp.markerResponsePDUsRx);
+ putNet32(receiver, elem->counterBlock.lacp.unknownRx);
+ putNet32(receiver, elem->counterBlock.lacp.illegalRx);
+ putNet32(receiver, elem->counterBlock.lacp.LACPDUsTx);
+ putNet32(receiver, elem->counterBlock.lacp.markerPDUsTx);
+ putNet32(receiver, elem->counterBlock.lacp.markerResponsePDUsTx);
+ break;
+ case SFLCOUNTERS_OPENFLOWPORT:
+ putNet64(receiver, elem->counterBlock.ofPort.datapath_id);
+ putNet32(receiver, elem->counterBlock.ofPort.port_no);
+ break;
+ case SFLCOUNTERS_PORTNAME:
+ putString(receiver, &elem->counterBlock.portName.portName);
+ break;
+ case SFLCOUNTERS_APP_RESOURCES:
+ putNet32(receiver, elem->counterBlock.appResources.user_time);
+ putNet32(receiver, elem->counterBlock.appResources.system_time);
+ putNet64(receiver, elem->counterBlock.appResources.mem_used);
+ putNet64(receiver, elem->counterBlock.appResources.mem_max);
+ putNet32(receiver, elem->counterBlock.appResources.fd_open);
+ putNet32(receiver, elem->counterBlock.appResources.fd_max);
+ putNet32(receiver, elem->counterBlock.appResources.conn_open);
+ putNet32(receiver, elem->counterBlock.appResources.conn_max);
+ break;
+ case SFLCOUNTERS_OVSDP:
+ putNet32(receiver, elem->counterBlock.ovsdp.n_hit);
+ putNet32(receiver, elem->counterBlock.ovsdp.n_missed);
+ putNet32(receiver, elem->counterBlock.ovsdp.n_lost);
+ putNet32(receiver, elem->counterBlock.ovsdp.n_mask_hit);
+ putNet32(receiver, elem->counterBlock.ovsdp.n_flows);
+ putNet32(receiver, elem->counterBlock.ovsdp.n_masks);
+ break;
default:
sflError(receiver, "unexpected counters_tag");
return -1;
*/
static void sendSample(SFLReceiver *receiver)
-{
+{
/* construct and send out the sample, then reset for the next one... */
/* first fill in the header with the latest values */
/* version, agent_address and sub_agent_id were pre-set. */
if(receiver->agent->sendFn) (*receiver->agent->sendFn)(receiver->agent->magic,
receiver->agent,
receiver,
- (u_char *)receiver->sampleCollector.data,
+ (u_char *)receiver->sampleCollector.data,
receiver->sampleCollector.pktlen);
else {
#ifdef SFLOW_DO_SOCKET
sfl_agent_error(receiver->agent, "receiver", msg);
resetSampleCollector(receiver);
}
+
+#endif /* !__CHECKER__ */