1 /* Copyright (c) 2002-2009 InMon Corp. Licensed under the terms of either the
2 * Sun Industry Standards Source License 1.1, that is available at:
3 * http://host-sflow.sourceforge.net/sissl.html
4 * or the InMon sFlow License, that is available at:
5 * http://www.inmon.com/technology/sflowlicense.txt
8 #ifndef __CHECKER__ /* Don't run sparse on anything in this file. */
11 #include "sflow_api.h"
13 static void resetSampleCollector(SFLReceiver
*receiver
);
14 static void sendSample(SFLReceiver
*receiver
);
15 static void sflError(SFLReceiver
*receiver
, char *errm
);
16 inline static void putNet32(SFLReceiver
*receiver
, u_int32_t val
);
17 inline static void putAddress(SFLReceiver
*receiver
, SFLAddress
*addr
);
18 #ifdef SFLOW_DO_SOCKET
19 static void initSocket(SFLReceiver
*receiver
);
22 /*_________________--------------------------__________________
23 _________________ sfl_receiver_init __________________
24 -----------------__________________________------------------
27 void sfl_receiver_init(SFLReceiver
*receiver
, SFLAgent
*agent
)
29 /* first clear everything */
30 memset(receiver
, 0, sizeof(*receiver
));
32 /* now copy in the parameters */
33 receiver
->agent
= agent
;
36 receiver
->sFlowRcvrMaximumDatagramSize
= SFL_DEFAULT_DATAGRAM_SIZE
;
37 receiver
->sFlowRcvrPort
= SFL_DEFAULT_COLLECTOR_PORT
;
39 #ifdef SFLOW_DO_SOCKET
40 /* initialize the socket address */
44 /* preset some of the header fields */
45 receiver
->sampleCollector
.datap
= receiver
->sampleCollector
.data
;
46 putNet32(receiver
, SFLDATAGRAM_VERSION5
);
47 putAddress(receiver
, &agent
->myIP
);
48 putNet32(receiver
, agent
->subId
);
50 /* prepare to receive the first sample */
51 resetSampleCollector(receiver
);
54 /*_________________---------------------------__________________
55 _________________ reset __________________
56 -----------------___________________________------------------
58 called on timeout, or when owner string is cleared
61 static void reset(SFLReceiver
*receiver
) {
62 // ask agent to tell samplers and pollers to stop sending samples
63 sfl_agent_resetReceiver(receiver
->agent
, receiver
);
65 sfl_receiver_init(receiver
, receiver
->agent
);
68 #ifdef SFLOW_DO_SOCKET
69 /*_________________---------------------------__________________
70 _________________ initSocket __________________
71 -----------------___________________________------------------
74 static void initSocket(SFLReceiver
*receiver
) {
75 if(receiver
->sFlowRcvrAddress
.type
== SFLADDRESSTYPE_IP_V6
) {
76 struct sockaddr_in6
*sa6
= &receiver
->receiver6
;
77 sa6
->sin6_port
= htons((u_int16_t
)receiver
->sFlowRcvrPort
);
78 sa6
->sin6_family
= AF_INET6
;
79 sa6
->sin6_addr
= receiver
->sFlowRcvrAddress
.address
.ip_v6
;
82 struct sockaddr_in
*sa4
= &receiver
->receiver4
;
83 sa4
->sin_port
= htons((u_int16_t
)receiver
->sFlowRcvrPort
);
84 sa4
->sin_family
= AF_INET
;
85 sa4
->sin_addr
= receiver
->sFlowRcvrAddress
.address
.ip_v4
;
90 /*_________________----------------------------------------_____________
91 _________________ MIB Vars _____________
92 -----------------________________________________________-------------
95 char * sfl_receiver_get_sFlowRcvrOwner(SFLReceiver
*receiver
) {
96 return receiver
->sFlowRcvrOwner
;
98 void sfl_receiver_set_sFlowRcvrOwner(SFLReceiver
*receiver
, char *sFlowRcvrOwner
) {
99 receiver
->sFlowRcvrOwner
= sFlowRcvrOwner
;
100 if(sFlowRcvrOwner
== NULL
|| sFlowRcvrOwner
[0] == '\0') {
101 // reset condition! owner string was cleared
105 time_t sfl_receiver_get_sFlowRcvrTimeout(SFLReceiver
*receiver
) {
106 return receiver
->sFlowRcvrTimeout
;
108 void sfl_receiver_set_sFlowRcvrTimeout(SFLReceiver
*receiver
, time_t sFlowRcvrTimeout
) {
109 receiver
->sFlowRcvrTimeout
=sFlowRcvrTimeout
;
111 u_int32_t
sfl_receiver_get_sFlowRcvrMaximumDatagramSize(SFLReceiver
*receiver
) {
112 return receiver
->sFlowRcvrMaximumDatagramSize
;
114 void sfl_receiver_set_sFlowRcvrMaximumDatagramSize(SFLReceiver
*receiver
, u_int32_t sFlowRcvrMaximumDatagramSize
) {
115 u_int32_t mdz
= sFlowRcvrMaximumDatagramSize
;
116 if(mdz
< SFL_MIN_DATAGRAM_SIZE
) mdz
= SFL_MIN_DATAGRAM_SIZE
;
117 receiver
->sFlowRcvrMaximumDatagramSize
= mdz
;
119 SFLAddress
*sfl_receiver_get_sFlowRcvrAddress(SFLReceiver
*receiver
) {
120 return &receiver
->sFlowRcvrAddress
;
122 void sfl_receiver_set_sFlowRcvrAddress(SFLReceiver
*receiver
, SFLAddress
*sFlowRcvrAddress
) {
123 if(sFlowRcvrAddress
) receiver
->sFlowRcvrAddress
= *sFlowRcvrAddress
; // structure copy
124 #ifdef SFLOW_DO_SOCKET
125 initSocket(receiver
);
128 u_int32_t
sfl_receiver_get_sFlowRcvrPort(SFLReceiver
*receiver
) {
129 return receiver
->sFlowRcvrPort
;
131 void sfl_receiver_set_sFlowRcvrPort(SFLReceiver
*receiver
, u_int32_t sFlowRcvrPort
) {
132 receiver
->sFlowRcvrPort
= sFlowRcvrPort
;
133 // update the socket structure
134 #ifdef SFLOW_DO_SOCKET
135 initSocket(receiver
);
139 /*_________________---------------------------__________________
140 _________________ sfl_receiver_tick __________________
141 -----------------___________________________------------------
144 void sfl_receiver_tick(SFLReceiver
*receiver
, time_t now
)
146 // if there are any samples to send, flush them now
147 if(receiver
->sampleCollector
.numSamples
> 0) sendSample(receiver
);
149 if(receiver
->sFlowRcvrTimeout
&& (u_int32_t
)receiver
->sFlowRcvrTimeout
!= 0xFFFFFFFF) {
150 // count down one tick and reset if we reach 0
151 if(--receiver
->sFlowRcvrTimeout
== 0) reset(receiver
);
155 /*_________________-----------------------------__________________
156 _________________ receiver write utilities __________________
157 -----------------_____________________________------------------
160 inline static void put32(SFLReceiver
*receiver
, u_int32_t val
)
162 *receiver
->sampleCollector
.datap
++ = val
;
165 inline static void putNet32(SFLReceiver
*receiver
, u_int32_t val
)
167 *receiver
->sampleCollector
.datap
++ = htonl(val
);
170 inline static void putNet32_run(SFLReceiver
*receiver
, void *obj
, size_t quads
)
172 u_int32_t
*from
= (u_int32_t
*)obj
;
173 while(quads
--) putNet32(receiver
, *from
++);
176 inline static void putNet64(SFLReceiver
*receiver
, u_int64_t val64
)
178 u_int32_t
*firstQuadPtr
= receiver
->sampleCollector
.datap
;
179 // first copy the bytes in
180 memcpy((u_char
*)firstQuadPtr
, &val64
, 8);
182 // swap the bytes, and reverse the quads too
183 u_int32_t tmp
= *receiver
->sampleCollector
.datap
++;
184 *firstQuadPtr
= htonl(*receiver
->sampleCollector
.datap
);
185 *receiver
->sampleCollector
.datap
++ = htonl(tmp
);
187 else receiver
->sampleCollector
.datap
+= 2;
190 inline static void put128(SFLReceiver
*receiver
, u_char
*val
)
192 memcpy(receiver
->sampleCollector
.datap
, val
, 16);
193 receiver
->sampleCollector
.datap
+= 4;
196 inline static void putString(SFLReceiver
*receiver
, SFLString
*s
)
198 putNet32(receiver
, s
->len
);
199 memcpy(receiver
->sampleCollector
.datap
, s
->str
, s
->len
);
200 receiver
->sampleCollector
.datap
+= (s
->len
+ 3) / 4; /* pad to 4-byte boundary */
201 if ((s
->len
% 4) != 0){
202 u_int8_t padding
= 4 - (s
->len
% 4);
203 memset(((u_int8_t
*)receiver
->sampleCollector
.datap
)-padding
, 0, padding
);
207 inline static u_int32_t
stringEncodingLength(SFLString
*s
) {
208 // answer in bytes, so remember to mulitply by 4 after rounding up to nearest 4-byte boundary
209 return 4 + (((s
->len
+ 3) / 4) * 4);
212 inline static void putAddress(SFLReceiver
*receiver
, SFLAddress
*addr
)
214 // encode unspecified addresses as IPV4:0.0.0.0 - or should we flag this as an error?
215 if(addr
->type
== 0) {
216 putNet32(receiver
, SFLADDRESSTYPE_IP_V4
);
220 putNet32(receiver
, addr
->type
);
221 if(addr
->type
== SFLADDRESSTYPE_IP_V4
) put32(receiver
, addr
->address
.ip_v4
.addr
);
222 else put128(receiver
, addr
->address
.ip_v6
.addr
);
226 inline static u_int32_t
addressEncodingLength(SFLAddress
*addr
) {
227 return (addr
->type
== SFLADDRESSTYPE_IP_V6
) ? 20 : 8; // type + address (unspecified == IPV4)
230 inline static void putMACAddress(SFLReceiver
*receiver
,
231 const struct eth_addr mac
)
233 memcpy(receiver
->sampleCollector
.datap
, &mac
, 6);
234 receiver
->sampleCollector
.datap
+= 2;
237 inline static void putSwitch(SFLReceiver
*receiver
, SFLExtended_switch
*sw
)
239 putNet32(receiver
, sw
->src_vlan
);
240 putNet32(receiver
, sw
->src_priority
);
241 putNet32(receiver
, sw
->dst_vlan
);
242 putNet32(receiver
, sw
->dst_priority
);
245 inline static void putRouter(SFLReceiver
*receiver
, SFLExtended_router
*router
)
247 putAddress(receiver
, &router
->nexthop
);
248 putNet32(receiver
, router
->src_mask
);
249 putNet32(receiver
, router
->dst_mask
);
252 inline static u_int32_t
routerEncodingLength(SFLExtended_router
*router
) {
253 return addressEncodingLength(&router
->nexthop
) + 8;
256 inline static void putGateway(SFLReceiver
*receiver
, SFLExtended_gateway
*gw
)
258 putAddress(receiver
, &gw
->nexthop
);
259 putNet32(receiver
, gw
->as
);
260 putNet32(receiver
, gw
->src_as
);
261 putNet32(receiver
, gw
->src_peer_as
);
262 putNet32(receiver
, gw
->dst_as_path_segments
);
265 for(; seg
< gw
->dst_as_path_segments
; seg
++) {
266 putNet32(receiver
, gw
->dst_as_path
[seg
].type
);
267 putNet32(receiver
, gw
->dst_as_path
[seg
].length
);
268 putNet32_run(receiver
, gw
->dst_as_path
[seg
].as
.seq
, gw
->dst_as_path
[seg
].length
);
271 putNet32(receiver
, gw
->communities_length
);
272 putNet32_run(receiver
, gw
->communities
, gw
->communities_length
);
273 putNet32(receiver
, gw
->localpref
);
276 inline static u_int32_t
gatewayEncodingLength(SFLExtended_gateway
*gw
) {
277 u_int32_t elemSiz
= addressEncodingLength(&gw
->nexthop
);
279 elemSiz
+= 16; // as, src_as, src_peer_as, dst_as_path_segments
280 for(; seg
< gw
->dst_as_path_segments
; seg
++) {
281 elemSiz
+= 8; // type, length
282 elemSiz
+= 4 * gw
->dst_as_path
[seg
].length
; // set/seq bytes
284 elemSiz
+= 4; // communities_length
285 elemSiz
+= 4 * gw
->communities_length
; // communities
286 elemSiz
+= 4; // localpref
290 inline static void putUser(SFLReceiver
*receiver
, SFLExtended_user
*user
)
292 putNet32(receiver
, user
->src_charset
);
293 putString(receiver
, &user
->src_user
);
294 putNet32(receiver
, user
->dst_charset
);
295 putString(receiver
, &user
->dst_user
);
298 inline static u_int32_t
userEncodingLength(SFLExtended_user
*user
) {
300 + stringEncodingLength(&user
->src_user
)
302 + stringEncodingLength(&user
->dst_user
);
305 inline static void putUrl(SFLReceiver
*receiver
, SFLExtended_url
*url
)
307 putNet32(receiver
, url
->direction
);
308 putString(receiver
, &url
->url
);
309 putString(receiver
, &url
->host
);
312 inline static u_int32_t
urlEncodingLength(SFLExtended_url
*url
) {
314 + stringEncodingLength(&url
->url
)
315 + stringEncodingLength(&url
->host
);
318 inline static void putLabelStack(SFLReceiver
*receiver
, SFLLabelStack
*labelStack
)
320 putNet32(receiver
, labelStack
->depth
);
321 putNet32_run(receiver
, labelStack
->stack
, labelStack
->depth
);
324 inline static u_int32_t
labelStackEncodingLength(SFLLabelStack
*labelStack
) {
325 return 4 + (4 * labelStack
->depth
);
328 inline static void putMpls(SFLReceiver
*receiver
, SFLExtended_mpls
*mpls
)
330 putAddress(receiver
, &mpls
->nextHop
);
331 putLabelStack(receiver
, &mpls
->in_stack
);
332 putLabelStack(receiver
, &mpls
->out_stack
);
335 inline static u_int32_t
mplsEncodingLength(SFLExtended_mpls
*mpls
) {
336 return addressEncodingLength(&mpls
->nextHop
)
337 + labelStackEncodingLength(&mpls
->in_stack
)
338 + labelStackEncodingLength(&mpls
->out_stack
);
341 inline static void putNat(SFLReceiver
*receiver
, SFLExtended_nat
*nat
)
343 putAddress(receiver
, &nat
->src
);
344 putAddress(receiver
, &nat
->dst
);
347 inline static u_int32_t
natEncodingLength(SFLExtended_nat
*nat
) {
348 return addressEncodingLength(&nat
->src
)
349 + addressEncodingLength(&nat
->dst
);
352 inline static void putMplsTunnel(SFLReceiver
*receiver
, SFLExtended_mpls_tunnel
*tunnel
)
354 putString(receiver
, &tunnel
->tunnel_lsp_name
);
355 putNet32(receiver
, tunnel
->tunnel_id
);
356 putNet32(receiver
, tunnel
->tunnel_cos
);
359 inline static u_int32_t
mplsTunnelEncodingLength(SFLExtended_mpls_tunnel
*tunnel
) {
360 return stringEncodingLength(&tunnel
->tunnel_lsp_name
) + 8;
363 inline static void putMplsVc(SFLReceiver
*receiver
, SFLExtended_mpls_vc
*vc
)
365 putString(receiver
, &vc
->vc_instance_name
);
366 putNet32(receiver
, vc
->vll_vc_id
);
367 putNet32(receiver
, vc
->vc_label_cos
);
370 inline static u_int32_t
mplsVcEncodingLength(SFLExtended_mpls_vc
*vc
) {
371 return stringEncodingLength( &vc
->vc_instance_name
) + 8;
374 inline static void putMplsFtn(SFLReceiver
*receiver
, SFLExtended_mpls_FTN
*ftn
)
376 putString(receiver
, &ftn
->mplsFTNDescr
);
377 putNet32(receiver
, ftn
->mplsFTNMask
);
380 inline static u_int32_t
mplsFtnEncodingLength(SFLExtended_mpls_FTN
*ftn
) {
381 return stringEncodingLength( &ftn
->mplsFTNDescr
) + 4;
384 inline static void putMplsLdpFec(SFLReceiver
*receiver
, SFLExtended_mpls_LDP_FEC
*ldpfec
)
386 putNet32(receiver
, ldpfec
->mplsFecAddrPrefixLength
);
389 inline static u_int32_t
mplsLdpFecEncodingLength(SFLExtended_mpls_LDP_FEC
*ldpfec
) {
393 inline static void putVlanTunnel(SFLReceiver
*receiver
, SFLExtended_vlan_tunnel
*vlanTunnel
)
395 putLabelStack(receiver
, &vlanTunnel
->stack
);
398 inline static u_int32_t
vlanTunnelEncodingLength(SFLExtended_vlan_tunnel
*vlanTunnel
) {
399 return labelStackEncodingLength(&vlanTunnel
->stack
);
403 inline static void putGenericCounters(SFLReceiver
*receiver
, SFLIf_counters
*counters
)
405 putNet32(receiver
, counters
->ifIndex
);
406 putNet32(receiver
, counters
->ifType
);
407 putNet64(receiver
, counters
->ifSpeed
);
408 putNet32(receiver
, counters
->ifDirection
);
409 putNet32(receiver
, counters
->ifStatus
);
410 putNet64(receiver
, counters
->ifInOctets
);
411 putNet32(receiver
, counters
->ifInUcastPkts
);
412 putNet32(receiver
, counters
->ifInMulticastPkts
);
413 putNet32(receiver
, counters
->ifInBroadcastPkts
);
414 putNet32(receiver
, counters
->ifInDiscards
);
415 putNet32(receiver
, counters
->ifInErrors
);
416 putNet32(receiver
, counters
->ifInUnknownProtos
);
417 putNet64(receiver
, counters
->ifOutOctets
);
418 putNet32(receiver
, counters
->ifOutUcastPkts
);
419 putNet32(receiver
, counters
->ifOutMulticastPkts
);
420 putNet32(receiver
, counters
->ifOutBroadcastPkts
);
421 putNet32(receiver
, counters
->ifOutDiscards
);
422 putNet32(receiver
, counters
->ifOutErrors
);
423 putNet32(receiver
, counters
->ifPromiscuousMode
);
427 /*_________________-----------------------------__________________
428 _________________ computeFlowSampleSize __________________
429 -----------------_____________________________------------------
432 static int computeFlowSampleSize(SFLReceiver
*receiver
, SFL_FLOW_SAMPLE_TYPE
*fs
)
434 SFLFlow_sample_element
*elem
= fs
->elements
;
435 #ifdef SFL_USE_32BIT_INDEX
436 u_int siz
= 52; /* tag, length, sequence_number, ds_class, ds_index, sampling_rate,
437 sample_pool, drops, inputFormat, input, outputFormat, output, number of elements */
439 u_int siz
= 40; /* tag, length, sequence_number, source_id, sampling_rate,
440 sample_pool, drops, input, output, number of elements */
443 fs
->num_elements
= 0; /* we're going to count them again even if this was set by the client */
444 for(; elem
!= NULL
; elem
= elem
->nxt
) {
447 siz
+= 8; /* tag, length */
450 elemSiz
= 16; /* header_protocol, frame_length, stripped, header_length */
451 elemSiz
+= ((elem
->flowType
.header
.header_length
+ 3) / 4) * 4; /* header, rounded up to nearest 4 bytes */
453 case SFLFLOW_ETHERNET
: elemSiz
= sizeof(SFLSampled_ethernet
); break;
454 case SFLFLOW_IPV4
: elemSiz
= sizeof(SFLSampled_ipv4
); break;
455 case SFLFLOW_IPV6
: elemSiz
= sizeof(SFLSampled_ipv6
); break;
456 case SFLFLOW_EX_SWITCH
: elemSiz
= sizeof(SFLExtended_switch
); break;
457 case SFLFLOW_EX_ROUTER
: elemSiz
= routerEncodingLength(&elem
->flowType
.router
); break;
458 case SFLFLOW_EX_GATEWAY
: elemSiz
= gatewayEncodingLength(&elem
->flowType
.gateway
); break;
459 case SFLFLOW_EX_USER
: elemSiz
= userEncodingLength(&elem
->flowType
.user
); break;
460 case SFLFLOW_EX_URL
: elemSiz
= urlEncodingLength(&elem
->flowType
.url
); break;
461 case SFLFLOW_EX_MPLS
: elemSiz
= mplsEncodingLength(&elem
->flowType
.mpls
); break;
462 case SFLFLOW_EX_NAT
: elemSiz
= natEncodingLength(&elem
->flowType
.nat
); break;
463 case SFLFLOW_EX_MPLS_TUNNEL
: elemSiz
= mplsTunnelEncodingLength(&elem
->flowType
.mpls_tunnel
); break;
464 case SFLFLOW_EX_MPLS_VC
: elemSiz
= mplsVcEncodingLength(&elem
->flowType
.mpls_vc
); break;
465 case SFLFLOW_EX_MPLS_FTN
: elemSiz
= mplsFtnEncodingLength(&elem
->flowType
.mpls_ftn
); break;
466 case SFLFLOW_EX_MPLS_LDP_FEC
: elemSiz
= mplsLdpFecEncodingLength(&elem
->flowType
.mpls_ldp_fec
); break;
467 case SFLFLOW_EX_VLAN_TUNNEL
: elemSiz
= vlanTunnelEncodingLength(&elem
->flowType
.vlan_tunnel
); break;
468 case SFLFLOW_EX_IPV4_TUNNEL_EGRESS
:
469 case SFLFLOW_EX_IPV4_TUNNEL_INGRESS
:
470 elemSiz
= sizeof(SFLSampled_ipv4
);
472 case SFLFLOW_EX_VNI_EGRESS
:
473 case SFLFLOW_EX_VNI_INGRESS
:
474 elemSiz
= sizeof(SFLExtended_vni
);
477 sflError(receiver
, "unexpected packet_data_tag");
481 // cache the element size, and accumulate it into the overall FlowSample size
482 elem
->length
= elemSiz
;
489 /*_________________-------------------------------__________________
490 _________________ sfl_receiver_writeFlowSample __________________
491 -----------------_______________________________------------------
494 int sfl_receiver_writeFlowSample(SFLReceiver
*receiver
, SFL_FLOW_SAMPLE_TYPE
*fs
)
497 if(fs
== NULL
) return -1;
498 if((packedSize
= computeFlowSampleSize(receiver
, fs
)) == -1) return -1;
500 // check in case this one sample alone is too big for the datagram
501 // in fact - if it is even half as big then we should ditch it. Very
502 // important to avoid overruning the packet buffer.
503 if(packedSize
> (int)(receiver
->sFlowRcvrMaximumDatagramSize
/ 2)) {
504 sflError(receiver
, "flow sample too big for datagram");
508 // if the sample pkt is full enough so that this sample might put
509 // it over the limit, then we should send it now before going on.
510 if((receiver
->sampleCollector
.pktlen
+ packedSize
) >= receiver
->sFlowRcvrMaximumDatagramSize
)
511 sendSample(receiver
);
513 receiver
->sampleCollector
.numSamples
++;
515 #ifdef SFL_USE_32BIT_INDEX
516 putNet32(receiver
, SFLFLOW_SAMPLE_EXPANDED
);
518 putNet32(receiver
, SFLFLOW_SAMPLE
);
521 putNet32(receiver
, packedSize
- 8); // don't include tag and len
522 putNet32(receiver
, fs
->sequence_number
);
524 #ifdef SFL_USE_32BIT_INDEX
525 putNet32(receiver
, fs
->ds_class
);
526 putNet32(receiver
, fs
->ds_index
);
528 putNet32(receiver
, fs
->source_id
);
531 putNet32(receiver
, fs
->sampling_rate
);
532 putNet32(receiver
, fs
->sample_pool
);
533 putNet32(receiver
, fs
->drops
);
535 #ifdef SFL_USE_32BIT_INDEX
536 putNet32(receiver
, fs
->inputFormat
);
537 putNet32(receiver
, fs
->input
);
538 putNet32(receiver
, fs
->outputFormat
);
539 putNet32(receiver
, fs
->output
);
541 putNet32(receiver
, fs
->input
);
542 putNet32(receiver
, fs
->output
);
545 putNet32(receiver
, fs
->num_elements
);
548 SFLFlow_sample_element
*elem
= fs
->elements
;
549 for(; elem
!= NULL
; elem
= elem
->nxt
) {
551 putNet32(receiver
, elem
->tag
);
552 putNet32(receiver
, elem
->length
); // length cached in computeFlowSampleSize()
556 putNet32(receiver
, elem
->flowType
.header
.header_protocol
);
557 putNet32(receiver
, elem
->flowType
.header
.frame_length
);
558 putNet32(receiver
, elem
->flowType
.header
.stripped
);
559 putNet32(receiver
, elem
->flowType
.header
.header_length
);
561 memcpy(receiver
->sampleCollector
.datap
, elem
->flowType
.header
.header_bytes
, elem
->flowType
.header
.header_length
);
562 /* round up to multiple of 4 to preserve alignment */
563 receiver
->sampleCollector
.datap
+= ((elem
->flowType
.header
.header_length
+ 3) / 4);
565 case SFLFLOW_ETHERNET
:
566 putNet32(receiver
, elem
->flowType
.ethernet
.eth_len
);
567 putMACAddress(receiver
, elem
->flowType
.ethernet
.src_mac
);
568 putMACAddress(receiver
, elem
->flowType
.ethernet
.dst_mac
);
569 putNet32(receiver
, elem
->flowType
.ethernet
.eth_type
);
572 case SFLFLOW_EX_IPV4_TUNNEL_EGRESS
:
573 case SFLFLOW_EX_IPV4_TUNNEL_INGRESS
:
574 putNet32(receiver
, elem
->flowType
.ipv4
.length
);
575 putNet32(receiver
, elem
->flowType
.ipv4
.protocol
);
576 put32(receiver
, elem
->flowType
.ipv4
.src_ip
.addr
);
577 put32(receiver
, elem
->flowType
.ipv4
.dst_ip
.addr
);
578 putNet32(receiver
, elem
->flowType
.ipv4
.src_port
);
579 putNet32(receiver
, elem
->flowType
.ipv4
.dst_port
);
580 putNet32(receiver
, elem
->flowType
.ipv4
.tcp_flags
);
581 putNet32(receiver
, elem
->flowType
.ipv4
.tos
);
584 putNet32(receiver
, elem
->flowType
.ipv6
.length
);
585 putNet32(receiver
, elem
->flowType
.ipv6
.protocol
);
586 put128(receiver
, elem
->flowType
.ipv6
.src_ip
.addr
);
587 put128(receiver
, elem
->flowType
.ipv6
.dst_ip
.addr
);
588 putNet32(receiver
, elem
->flowType
.ipv6
.src_port
);
589 putNet32(receiver
, elem
->flowType
.ipv6
.dst_port
);
590 putNet32(receiver
, elem
->flowType
.ipv6
.tcp_flags
);
591 putNet32(receiver
, elem
->flowType
.ipv6
.priority
);
593 case SFLFLOW_EX_SWITCH
: putSwitch(receiver
, &elem
->flowType
.sw
); break;
594 case SFLFLOW_EX_ROUTER
: putRouter(receiver
, &elem
->flowType
.router
); break;
595 case SFLFLOW_EX_GATEWAY
: putGateway(receiver
, &elem
->flowType
.gateway
); break;
596 case SFLFLOW_EX_USER
: putUser(receiver
, &elem
->flowType
.user
); break;
597 case SFLFLOW_EX_URL
: putUrl(receiver
, &elem
->flowType
.url
); break;
598 case SFLFLOW_EX_MPLS
: putMpls(receiver
, &elem
->flowType
.mpls
); break;
599 case SFLFLOW_EX_NAT
: putNat(receiver
, &elem
->flowType
.nat
); break;
600 case SFLFLOW_EX_MPLS_TUNNEL
: putMplsTunnel(receiver
, &elem
->flowType
.mpls_tunnel
); break;
601 case SFLFLOW_EX_MPLS_VC
: putMplsVc(receiver
, &elem
->flowType
.mpls_vc
); break;
602 case SFLFLOW_EX_MPLS_FTN
: putMplsFtn(receiver
, &elem
->flowType
.mpls_ftn
); break;
603 case SFLFLOW_EX_MPLS_LDP_FEC
: putMplsLdpFec(receiver
, &elem
->flowType
.mpls_ldp_fec
); break;
604 case SFLFLOW_EX_VLAN_TUNNEL
: putVlanTunnel(receiver
, &elem
->flowType
.vlan_tunnel
); break;
605 case SFLFLOW_EX_VNI_EGRESS
:
606 case SFLFLOW_EX_VNI_INGRESS
:
607 putNet32(receiver
, elem
->flowType
.tunnel_vni
.vni
);
611 sflError(receiver
, "unexpected packet_data_tag");
619 assert(((u_char
*)receiver
->sampleCollector
.datap
620 - (u_char
*)receiver
->sampleCollector
.data
621 - receiver
->sampleCollector
.pktlen
) == (u_int32_t
)packedSize
);
624 receiver
->sampleCollector
.pktlen
= (u_char
*)receiver
->sampleCollector
.datap
- (u_char
*)receiver
->sampleCollector
.data
;
628 /*_________________-----------------------------__________________
629 _________________ computeCountersSampleSize __________________
630 -----------------_____________________________------------------
633 static int computeCountersSampleSize(SFLReceiver
*receiver
, SFL_COUNTERS_SAMPLE_TYPE
*cs
)
635 SFLCounters_sample_element
*elem
= cs
->elements
;
636 #ifdef SFL_USE_32BIT_INDEX
637 u_int siz
= 24; /* tag, length, sequence_number, ds_class, ds_index, number of elements */
639 u_int siz
= 20; /* tag, length, sequence_number, source_id, number of elements */
642 cs
->num_elements
= 0; /* we're going to count them again even if this was set by the client */
643 for(; elem
!= NULL
; elem
= elem
->nxt
) {
646 siz
+= 8; /* tag, length */
648 case SFLCOUNTERS_GENERIC
: elemSiz
= SFL_CTR_GENERIC_XDR_SIZE
; break;
649 case SFLCOUNTERS_ETHERNET
: elemSiz
= SFL_CTR_ETHERNET_XDR_SIZE
; break;
650 case SFLCOUNTERS_TOKENRING
: elemSiz
= sizeof(elem
->counterBlock
.tokenring
); break;
651 case SFLCOUNTERS_VG
: elemSiz
= sizeof(elem
->counterBlock
.vg
); break;
652 case SFLCOUNTERS_VLAN
: elemSiz
= sizeof(elem
->counterBlock
.vlan
); break;
653 case SFLCOUNTERS_LACP
: elemSiz
= SFL_CTR_LACP_XDR_SIZE
; break;
654 case SFLCOUNTERS_OPENFLOWPORT
: elemSiz
= SFL_CTR_OPENFLOWPORT_XDR_SIZE
; break;
655 case SFLCOUNTERS_PORTNAME
: elemSiz
= stringEncodingLength(&elem
->counterBlock
.portName
.portName
); break;
656 case SFLCOUNTERS_APP_RESOURCES
: elemSiz
= SFL_CTR_APP_RESOURCES_XDR_SIZE
; break;
657 case SFLCOUNTERS_OVSDP
: elemSiz
= SFL_CTR_OVSDP_XDR_SIZE
; break;
659 sflError(receiver
, "unexpected counters_tag");
663 // cache the element size, and accumulate it into the overall FlowSample size
664 elem
->length
= elemSiz
;
670 /*_________________----------------------------------__________________
671 _________________ sfl_receiver_writeCountersSample __________________
672 -----------------__________________________________------------------
675 int sfl_receiver_writeCountersSample(SFLReceiver
*receiver
, SFL_COUNTERS_SAMPLE_TYPE
*cs
)
678 if(cs
== NULL
) return -1;
679 // if the sample pkt is full enough so that this sample might put
680 // it over the limit, then we should send it now.
681 if((packedSize
= computeCountersSampleSize(receiver
, cs
)) == -1) return -1;
683 // check in case this one sample alone is too big for the datagram
684 // in fact - if it is even half as big then we should ditch it. Very
685 // important to avoid overruning the packet buffer.
686 if(packedSize
> (int)(receiver
->sFlowRcvrMaximumDatagramSize
/ 2)) {
687 sflError(receiver
, "counters sample too big for datagram");
691 if((receiver
->sampleCollector
.pktlen
+ packedSize
) >= receiver
->sFlowRcvrMaximumDatagramSize
)
692 sendSample(receiver
);
694 receiver
->sampleCollector
.numSamples
++;
696 #ifdef SFL_USE_32BIT_INDEX
697 putNet32(receiver
, SFLCOUNTERS_SAMPLE_EXPANDED
);
699 putNet32(receiver
, SFLCOUNTERS_SAMPLE
);
702 putNet32(receiver
, packedSize
- 8); // tag and length not included
703 putNet32(receiver
, cs
->sequence_number
);
705 #ifdef SFL_USE_32BIT_INDEX
706 putNet32(receiver
, cs
->ds_class
);
707 putNet32(receiver
, cs
->ds_index
);
709 putNet32(receiver
, cs
->source_id
);
712 putNet32(receiver
, cs
->num_elements
);
715 SFLCounters_sample_element
*elem
= cs
->elements
;
716 for(; elem
!= NULL
; elem
= elem
->nxt
) {
718 putNet32(receiver
, elem
->tag
);
719 putNet32(receiver
, elem
->length
); // length cached in computeCountersSampleSize()
722 case SFLCOUNTERS_GENERIC
:
723 putGenericCounters(receiver
, &(elem
->counterBlock
.generic
));
725 case SFLCOUNTERS_ETHERNET
:
726 // all these counters are 32-bit
727 putNet32_run(receiver
, &elem
->counterBlock
.ethernet
, sizeof(elem
->counterBlock
.ethernet
) / 4);
729 case SFLCOUNTERS_TOKENRING
:
730 // all these counters are 32-bit
731 putNet32_run(receiver
, &elem
->counterBlock
.tokenring
, sizeof(elem
->counterBlock
.tokenring
) / 4);
735 putNet32(receiver
, elem
->counterBlock
.vg
.dot12InHighPriorityFrames
);
736 putNet64(receiver
, elem
->counterBlock
.vg
.dot12InHighPriorityOctets
);
737 putNet32(receiver
, elem
->counterBlock
.vg
.dot12InNormPriorityFrames
);
738 putNet64(receiver
, elem
->counterBlock
.vg
.dot12InNormPriorityOctets
);
739 putNet32(receiver
, elem
->counterBlock
.vg
.dot12InIPMErrors
);
740 putNet32(receiver
, elem
->counterBlock
.vg
.dot12InOversizeFrameErrors
);
741 putNet32(receiver
, elem
->counterBlock
.vg
.dot12InDataErrors
);
742 putNet32(receiver
, elem
->counterBlock
.vg
.dot12InNullAddressedFrames
);
743 putNet32(receiver
, elem
->counterBlock
.vg
.dot12OutHighPriorityFrames
);
744 putNet64(receiver
, elem
->counterBlock
.vg
.dot12OutHighPriorityOctets
);
745 putNet32(receiver
, elem
->counterBlock
.vg
.dot12TransitionIntoTrainings
);
746 putNet64(receiver
, elem
->counterBlock
.vg
.dot12HCInHighPriorityOctets
);
747 putNet64(receiver
, elem
->counterBlock
.vg
.dot12HCInNormPriorityOctets
);
748 putNet64(receiver
, elem
->counterBlock
.vg
.dot12HCOutHighPriorityOctets
);
750 case SFLCOUNTERS_VLAN
:
752 putNet32(receiver
, elem
->counterBlock
.vlan
.vlan_id
);
753 putNet64(receiver
, elem
->counterBlock
.vlan
.octets
);
754 putNet32(receiver
, elem
->counterBlock
.vlan
.ucastPkts
);
755 putNet32(receiver
, elem
->counterBlock
.vlan
.multicastPkts
);
756 putNet32(receiver
, elem
->counterBlock
.vlan
.broadcastPkts
);
757 putNet32(receiver
, elem
->counterBlock
.vlan
.discards
);
759 case SFLCOUNTERS_LACP
:
760 putMACAddress(receiver
, elem
->counterBlock
.lacp
.actorSystemID
);
761 putMACAddress(receiver
, elem
->counterBlock
.lacp
.partnerSystemID
);
762 putNet32(receiver
, elem
->counterBlock
.lacp
.attachedAggID
);
763 put32(receiver
, elem
->counterBlock
.lacp
.portState
.all
);
764 putNet32(receiver
, elem
->counterBlock
.lacp
.LACPDUsRx
);
765 putNet32(receiver
, elem
->counterBlock
.lacp
.markerPDUsRx
);
766 putNet32(receiver
, elem
->counterBlock
.lacp
.markerResponsePDUsRx
);
767 putNet32(receiver
, elem
->counterBlock
.lacp
.unknownRx
);
768 putNet32(receiver
, elem
->counterBlock
.lacp
.illegalRx
);
769 putNet32(receiver
, elem
->counterBlock
.lacp
.LACPDUsTx
);
770 putNet32(receiver
, elem
->counterBlock
.lacp
.markerPDUsTx
);
771 putNet32(receiver
, elem
->counterBlock
.lacp
.markerResponsePDUsTx
);
773 case SFLCOUNTERS_OPENFLOWPORT
:
774 putNet64(receiver
, elem
->counterBlock
.ofPort
.datapath_id
);
775 putNet32(receiver
, elem
->counterBlock
.ofPort
.port_no
);
777 case SFLCOUNTERS_PORTNAME
:
778 putString(receiver
, &elem
->counterBlock
.portName
.portName
);
780 case SFLCOUNTERS_APP_RESOURCES
:
781 putNet32(receiver
, elem
->counterBlock
.appResources
.user_time
);
782 putNet32(receiver
, elem
->counterBlock
.appResources
.system_time
);
783 putNet64(receiver
, elem
->counterBlock
.appResources
.mem_used
);
784 putNet64(receiver
, elem
->counterBlock
.appResources
.mem_max
);
785 putNet32(receiver
, elem
->counterBlock
.appResources
.fd_open
);
786 putNet32(receiver
, elem
->counterBlock
.appResources
.fd_max
);
787 putNet32(receiver
, elem
->counterBlock
.appResources
.conn_open
);
788 putNet32(receiver
, elem
->counterBlock
.appResources
.conn_max
);
790 case SFLCOUNTERS_OVSDP
:
791 putNet32(receiver
, elem
->counterBlock
.ovsdp
.n_hit
);
792 putNet32(receiver
, elem
->counterBlock
.ovsdp
.n_missed
);
793 putNet32(receiver
, elem
->counterBlock
.ovsdp
.n_lost
);
794 putNet32(receiver
, elem
->counterBlock
.ovsdp
.n_mask_hit
);
795 putNet32(receiver
, elem
->counterBlock
.ovsdp
.n_flows
);
796 putNet32(receiver
, elem
->counterBlock
.ovsdp
.n_masks
);
799 sflError(receiver
, "unexpected counters_tag");
806 assert(((u_char
*)receiver
->sampleCollector
.datap
807 - (u_char
*)receiver
->sampleCollector
.data
808 - receiver
->sampleCollector
.pktlen
) == (u_int32_t
)packedSize
);
811 receiver
->sampleCollector
.pktlen
= (u_char
*)receiver
->sampleCollector
.datap
- (u_char
*)receiver
->sampleCollector
.data
;
815 /*_________________---------------------------------__________________
816 _________________ sfl_receiver_samplePacketsSent __________________
817 -----------------_________________________________------------------
820 u_int32_t
sfl_receiver_samplePacketsSent(SFLReceiver
*receiver
)
822 return receiver
->sampleCollector
.packetSeqNo
;
825 /*_________________---------------------------__________________
826 _________________ sendSample __________________
827 -----------------___________________________------------------
830 static void sendSample(SFLReceiver
*receiver
)
832 /* construct and send out the sample, then reset for the next one... */
833 /* first fill in the header with the latest values */
834 /* version, agent_address and sub_agent_id were pre-set. */
835 u_int32_t hdrIdx
= (receiver
->agent
->myIP
.type
== SFLADDRESSTYPE_IP_V6
) ? 7 : 4;
836 receiver
->sampleCollector
.data
[hdrIdx
++] = htonl(++receiver
->sampleCollector
.packetSeqNo
); /* seq no */
837 receiver
->sampleCollector
.data
[hdrIdx
++] = htonl((receiver
->agent
->now
- receiver
->agent
->bootTime
) * 1000); /* uptime */
838 receiver
->sampleCollector
.data
[hdrIdx
++] = htonl(receiver
->sampleCollector
.numSamples
); /* num samples */
840 if(receiver
->agent
->sendFn
) (*receiver
->agent
->sendFn
)(receiver
->agent
->magic
,
843 (u_char
*)receiver
->sampleCollector
.data
,
844 receiver
->sampleCollector
.pktlen
);
846 #ifdef SFLOW_DO_SOCKET
848 if (receiver
->sFlowRcvrAddress
.type
== SFLADDRESSTYPE_IP_V6
) {
849 u_int32_t soclen
= sizeof(struct sockaddr_in6
);
850 int result
= sendto(receiver
->agent
->receiverSocket6
,
851 receiver
->sampleCollector
.data
,
852 receiver
->sampleCollector
.pktlen
,
854 (struct sockaddr
*)&receiver
->receiver6
,
856 if(result
== -1 && errno
!= EINTR
) sfl_agent_sysError(receiver
->agent
, "receiver", "IPv6 socket sendto error");
857 if(result
== 0) sfl_agent_error(receiver
->agent
, "receiver", "IPv6 socket sendto returned 0");
860 u_int32_t soclen
= sizeof(struct sockaddr_in
);
861 int result
= sendto(receiver
->agent
->receiverSocket4
,
862 receiver
->sampleCollector
.data
,
863 receiver
->sampleCollector
.pktlen
,
865 (struct sockaddr
*)&receiver
->receiver4
,
867 if(result
== -1 && errno
!= EINTR
) sfl_agent_sysError(receiver
->agent
, "receiver", "socket sendto error");
868 if(result
== 0) sfl_agent_error(receiver
->agent
, "receiver", "socket sendto returned 0");
873 /* reset for the next time */
874 resetSampleCollector(receiver
);
877 /*_________________---------------------------__________________
878 _________________ resetSampleCollector __________________
879 -----------------___________________________------------------
882 static void resetSampleCollector(SFLReceiver
*receiver
)
884 receiver
->sampleCollector
.pktlen
= 0;
885 receiver
->sampleCollector
.numSamples
= 0;
886 /* point the datap to just after the header */
887 receiver
->sampleCollector
.datap
= (receiver
->agent
->myIP
.type
== SFLADDRESSTYPE_IP_V6
) ?
888 (receiver
->sampleCollector
.data
+ 10) : (receiver
->sampleCollector
.data
+ 7);
890 receiver
->sampleCollector
.pktlen
= (u_char
*)receiver
->sampleCollector
.datap
- (u_char
*)receiver
->sampleCollector
.data
;
893 /*_________________---------------------------__________________
894 _________________ sflError __________________
895 -----------------___________________________------------------
898 static void sflError(SFLReceiver
*receiver
, char *msg
)
900 sfl_agent_error(receiver
->agent
, "receiver", msg
);
901 resetSampleCollector(receiver
);
904 #endif /* !__CHECKER__ */