dpif-netdev: Delay packets' metadata initialization.
[cascardo/ovs.git] / lib / sflow_receiver.c
index 7fccab3..cde1359 100644 (file)
@@ -1,5 +1,11 @@
-/* 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"
@@ -101,7 +107,7 @@ time_t sfl_receiver_get_sFlowRcvrTimeout(SFLReceiver *receiver) {
 }
 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;
 }
@@ -150,7 +156,7 @@ void sfl_receiver_tick(SFLReceiver *receiver, time_t now)
   _________________   receiver write utilities  __________________
   -----------------_____________________________------------------
 */
+
 inline static void put32(SFLReceiver *receiver, u_int32_t val)
 {
     *receiver->sampleCollector.datap++ = val;
@@ -192,6 +198,10 @@ inline static void putString(SFLReceiver *receiver, SFLString *s)
     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) {
@@ -217,9 +227,10 @@ inline static u_int32_t addressEncodingLength(SFLAddress *addr) {
     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;
 }
 
@@ -265,9 +276,9 @@ inline static void putGateway(SFLReceiver *receiver, SFLExtended_gateway *gw)
 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
@@ -454,6 +465,14 @@ static int computeFlowSampleSize(SFLReceiver *receiver, SFL_FLOW_SAMPLE_TYPE *fs
        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;
@@ -490,7 +509,7 @@ int sfl_receiver_writeFlowSample(SFLReceiver *receiver, SFL_FLOW_SAMPLE_TYPE *fs
     // 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
@@ -528,10 +547,10 @@ int sfl_receiver_writeFlowSample(SFLReceiver *receiver, SFL_FLOW_SAMPLE_TYPE *fs
     {
        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);
@@ -550,6 +569,8 @@ int sfl_receiver_writeFlowSample(SFLReceiver *receiver, SFL_FLOW_SAMPLE_TYPE *fs
                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);
@@ -581,6 +602,11 @@ int sfl_receiver_writeFlowSample(SFLReceiver *receiver, SFL_FLOW_SAMPLE_TYPE *fs
            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;
@@ -619,11 +645,16 @@ static int computeCountersSampleSize(SFLReceiver *receiver, SFL_COUNTERS_SAMPLE_
        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;
@@ -648,7 +679,7 @@ int sfl_receiver_writeCountersSample(SFLReceiver *receiver, SFL_COUNTERS_SAMPLE_
     // 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.
@@ -656,12 +687,12 @@ int sfl_receiver_writeCountersSample(SFLReceiver *receiver, SFL_COUNTERS_SAMPLE_
        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
@@ -679,14 +710,14 @@ int sfl_receiver_writeCountersSample(SFLReceiver *receiver, SFL_COUNTERS_SAMPLE_
 #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));
@@ -725,6 +756,45 @@ int sfl_receiver_writeCountersSample(SFLReceiver *receiver, SFL_COUNTERS_SAMPLE_
                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;
@@ -758,7 +828,7 @@ u_int32_t sfl_receiver_samplePacketsSent(SFLReceiver *receiver)
 */
 
 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. */
@@ -770,7 +840,7 @@ static void sendSample(SFLReceiver *receiver)
     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
@@ -830,3 +900,5 @@ static void sflError(SFLReceiver *receiver, char *msg)
     sfl_agent_error(receiver->agent, "receiver", msg);
     resetSampleCollector(receiver);
 }
+
+#endif  /* !__CHECKER__ */