Beispiel #1
0
void sfl_poller_set_sFlowCpInterval(SFLPoller *poller, uint32_t sFlowCpInterval) {
  poller->sFlowCpInterval = sFlowCpInterval;
  /* Set the countersCountdown to be a randomly selected value between 1 and
     sFlowCpInterval. That way the counter polling would be desynchronised
     (on a 200-port switch, polling all the counters in one second could be harmful). */
  poller->countersCountdown = sfl_random(sFlowCpInterval);
}
Beispiel #2
0
int sfl_sampler_takeSample(SFLSampler *sampler)
{
  // increment the samplePool
  sampler->samplePool++;

  if(--sampler->skip == 0) {
    /* reached zero. Set the next skip and return true. */
    sampler->skip = sfl_random((2 * sampler->sFlowFsPacketSamplingRate) - 1);
    return 1;
  }
  return 0;
}
Beispiel #3
0
  int readPackets(HSP *sp)
  {
    int batch = 0;
    static uint32_t MySkipCount=1;
    if(sp->sFlow->sFlowSettings->ulogSubSamplingRate == 0) {
      // packet sampling was disabled by setting desired rate to 0
      return 0;
    }
    if(sp->ulog_soc) {
      for( ; batch < HSP_READPACKET_BATCH; batch++) {
	char buf[HSP_MAX_MSG_BYTES];
	socklen_t peerlen = sizeof(sp->ulog_peer);
	int len = recvfrom(sp->ulog_soc,
			   buf,
			   HSP_MAX_MSG_BYTES,
			   0,
			   (struct sockaddr *)&sp->ulog_peer,
			   &peerlen);
	if(len <= 0) break;
	if(debug > 1) myLog(LOG_INFO, "got ULOG msg: %u bytes", len);
	for(struct nlmsghdr *msg = (struct nlmsghdr *)buf; NLMSG_OK(msg, len); msg=NLMSG_NEXT(msg, len)) {

	  if(debug > 1) {
	    myLog(LOG_INFO, "netlink (%u bytes left) msg [len=%u type=%u flags=0x%x seq=%u pid=%u]",
		  len,
		  msg->nlmsg_len,
		  msg->nlmsg_type,
		  msg->nlmsg_flags,
		  msg->nlmsg_seq,
		  msg->nlmsg_pid);
	  }

	  switch(msg->nlmsg_type) {
	  case NLMSG_NOOP:
	  case NLMSG_ERROR:
	  case NLMSG_OVERRUN:
	    // ignore these
	    break;
	  case NLMSG_DONE: // last in multi-part
	  default:
	    {

	      if(--MySkipCount == 0) {
		/* reached zero. Set the next skip */
		MySkipCount = sfl_random((2 * sp->sFlow->sFlowSettings->ulogSubSamplingRate) - 1);

		/* and take a sample */

		// we're seeing type==111 on Fedora14
		//if(msg->nlmsg_flags & NLM_F_REQUEST) { }
		//if(msg->nlmsg_flags & NLM_F_MULTI) { }
		//if(msg->nlmsg_flags & NLM_F_ACK) { }
		//if(msg->nlmsg_flags & NLM_F_ECHO) { }
		ulog_packet_msg_t *pkt = NLMSG_DATA(msg);
		
		if(debug > 1) {
		  myLog(LOG_INFO, "mark=%u ts=%s hook=%u in=%s out=%s len=%u prefix=%s maclen=%u\n",
			pkt->mark,
			ctime(&pkt->timestamp_sec),
			pkt->hook,
			pkt->indev_name,
			pkt->outdev_name,
			pkt->data_len,
			pkt->prefix,
			pkt->mac_len);
		  if(pkt->mac_len == 14) {
		    u_char macdst[12], macsrc[12];
		    printHex(pkt->mac+6,6,macsrc,12,NO);
		    printHex(pkt->mac+0,6,macdst,12,NO);
		    uint16_t ethtype = (pkt->mac[12] << 8) + pkt->mac[13];
		    myLog(LOG_INFO, "%s -> %s (ethertype=0x%04X)", macsrc, macdst, ethtype);
		  }
		}

		
		SFL_FLOW_SAMPLE_TYPE fs = { 0 };
	
		SFLSampler *sampler = NULL;

		// set the ingress and egress ifIndex numbers.
		// Can be "INTERNAL" (0x3FFFFFFF) or "UNKNOWN" (0).
		if(pkt->indev_name[0]) {
		  SFLAdaptor *in = adaptorListGet(sp->adaptorList, pkt->indev_name);
		  if(in && in->ifIndex) {
		    fs.input = in->ifIndex;
		    sampler = getSampler(sp, pkt->indev_name, in->ifIndex);
		  }
		}
		else {
		  fs.input = SFL_INTERNAL_INTERFACE;
		}
		if(pkt->outdev_name[0]) {
		  SFLAdaptor *out = adaptorListGet(sp->adaptorList, pkt->outdev_name);
		  if(out && out->ifIndex) {
		    fs.output = out->ifIndex;
		    sampler = getSampler(sp, pkt->outdev_name, out->ifIndex);
		  }
		}
		else {
		  fs.output = SFL_INTERNAL_INTERFACE;
		}

		if(sampler == NULL) {
		  // maybe ULOG sent us a packet on device lo(?)
		  if(debug > 1) myLog(LOG_INFO, "dropped sample with no ifIndex\n");
		}
		else {
		  SFLFlow_sample_element hdrElem = { 0 };
		  hdrElem.tag = SFLFLOW_HEADER;
		  uint32_t FCS_bytes = 4;
		  uint32_t maxHdrLen = sampler->sFlowFsMaximumHeaderSize;
		  hdrElem.flowType.header.frame_length = pkt->data_len + FCS_bytes;
		  hdrElem.flowType.header.stripped = FCS_bytes;
		
		  u_char hdr[HSP_MAX_HEADER_BYTES];
		
		  if(pkt->mac_len == 14) {
		    // set the header_protocol to ethernet and
		    // reunite the mac header and payload in one buffer
		    hdrElem.flowType.header.header_protocol = SFLHEADER_ETHERNET_ISO8023;
		    memcpy(hdr, pkt->mac, 14);
		    maxHdrLen -= 14;
		    uint32_t payloadBytes = (pkt->data_len < maxHdrLen) ? pkt->data_len : maxHdrLen;
		    memcpy(hdr+14, pkt->payload, payloadBytes);
		    hdrElem.flowType.header.header_length = payloadBytes + 14;
		    hdrElem.flowType.header.header_bytes = hdr;
		    hdrElem.flowType.header.frame_length += 14;
		  }
		  else {
		    // no need to copy - just point at the payload
		    u_char ipversion = pkt->payload[0] >> 4;
		    if(ipversion != 4 && ipversion != 6) {
		      if(debug) myLog(LOG_ERR, "received non-IP packet. Encapsulation is unknown");
		    }
		    else {
		      hdrElem.flowType.header.header_protocol = (ipversion == 4) ? SFLHEADER_IPv4 : SFLHEADER_IPv6;
		      hdrElem.flowType.header.stripped += 14; // assume ethernet was (or will be) the framing
		      hdrElem.flowType.header.header_length = (pkt->data_len < maxHdrLen) ? pkt->data_len : maxHdrLen;
		      hdrElem.flowType.header.header_bytes = pkt->payload;
		    }
		  }
		
		  SFLADD_ELEMENT(&fs, &hdrElem);
		  // submit the actual sampling rate so it goes out with the sFlow feed
		  // otherwise the sampler object would fill in his own (sub-sampling) rate.
		  uint32_t actualSamplingRate = sp->sFlow->sFlowSettings->ulogActualSamplingRate;
		  fs.sampling_rate = actualSamplingRate;

		  // estimate the sample pool from the samples.  Could maybe do this
		  // above with the (possibly more granular) ulogSamplingRate, but then
		  // we would have to look up the sampler object every time, which
		  // might be too expensive in the case where ulogSamplingRate==1.
		  sampler->samplePool += actualSamplingRate;

		  sfl_sampler_writeFlowSample(sampler, &fs);
		}
	      }
	    }
	  } 
	}
      }
    }
Beispiel #4
0
void sfl_sampler_set_sFlowFsPacketSamplingRate(SFLSampler *sampler, uint32_t sFlowFsPacketSamplingRate) {
  sampler->sFlowFsPacketSamplingRate = sFlowFsPacketSamplingRate;
  // initialize the skip count too
  sampler->skip = sfl_random(sFlowFsPacketSamplingRate);
}
Beispiel #5
0
int readPackets_ulog(EVMod *mod, EVBus *bus, int fd, void *data)
{
    HSP_mod_ULOG *mdata = (HSP_mod_ULOG *)mod->data;
    HSP *sp = (HSP *)EVROOTDATA(mod);

    int batch = 0;
    static uint32_t MySkipCount=1;

    if(sp->sFlowSettings == NULL) {
        // config was turned off
        return 0;
    }

    if(mdata->subSamplingRate == 0) {
        // packet sampling was disabled by setting desired rate to 0
        return 0;
    }

    for( ; batch < HSP_READPACKET_BATCH_ULOG; batch++) {
        char buf[HSP_MAX_ULOG_MSG_BYTES];
        int len = recvfrom(mdata->ulog_soc, buf, HSP_MAX_ULOG_MSG_BYTES, 0, NULL, NULL);
        if(len <= 0) break;
        myDebug(1, "got ULOG msg: %u bytes", len);
        for(struct nlmsghdr *msg = (struct nlmsghdr *)buf; NLMSG_OK(msg, len); msg=NLMSG_NEXT(msg, len)) {

            myDebug(1, "netlink (%u bytes left) msg [len=%u type=%u flags=0x%x seq=%u pid=%u]",
                    len,
                    msg->nlmsg_len,
                    msg->nlmsg_type,
                    msg->nlmsg_flags,
                    msg->nlmsg_seq,
                    msg->nlmsg_pid);

            // check for drops indicated by sequence no
            uint32_t droppedSamples = 0;
            if(mdata->ulog_seqno) {
                droppedSamples = msg->nlmsg_seq - mdata->ulog_seqno - 1;
                if(droppedSamples) {
                    mdata->ulog_drops += droppedSamples;
                }
            }
            mdata->ulog_seqno = msg->nlmsg_seq;

            switch(msg->nlmsg_type) {
            case NLMSG_NOOP:
            case NLMSG_ERROR:
            case NLMSG_OVERRUN:
                // ignore these
                break;
            case NLMSG_DONE: // last in multi-part
            default:
            {

                if(--MySkipCount == 0) {
                    /* reached zero. Set the next skip */
                    uint32_t sr = mdata->subSamplingRate;
                    MySkipCount = sr == 1 ? 1 : sfl_random((2 * sr) - 1);

                    /* and take a sample */

                    // we're seeing type==111 on Fedora14
                    //if(msg->nlmsg_flags & NLM_F_REQUEST) { }
                    //if(msg->nlmsg_flags & NLM_F_MULTI) { }
                    //if(msg->nlmsg_flags & NLM_F_ACK) { }
                    //if(msg->nlmsg_flags & NLM_F_ECHO) { }
                    ulog_packet_msg_t *pkt = NLMSG_DATA(msg);

                    myDebug(LOG_INFO, "ULOG mark=%u ts=%s prefix=%s",
                            pkt->mark,
                            ctime(&pkt->timestamp_sec),
                            pkt->prefix);


                    SFLAdaptor *dev_in = NULL;
                    SFLAdaptor *dev_out = NULL;

                    if(pkt->indev_name[0]) {
                        dev_in = adaptorByName(sp, pkt->indev_name);
                    }
                    if(pkt->outdev_name[0]) {
                        dev_out = adaptorByName(sp, pkt->outdev_name);
                    }

                    takeSample(sp,
                               dev_in,
                               dev_out,
                               NULL,
                               NO,
                               pkt->hook,
                               pkt->mac,
                               pkt->mac_len,
                               pkt->payload,
                               pkt->data_len, /* length of captured payload */
                               pkt->data_len, /* length of packet (pdu) */
                               droppedSamples,
                               mdata->actualSamplingRate);
                }
            }
            }
        }
    }
    return batch;
}
Beispiel #6
0
  int readPackets(HSP *sp)
  {
    int batch = 0;
    static uint32_t MySkipCount=1;

    if(sp->sFlow->sFlowSettings == NULL) {
      // config was turned off
      return 0;
    }

    if(sp->sFlow->sFlowSettings->ulogSubSamplingRate == 0) {
      // packet sampling was disabled by setting desired rate to 0
      return 0;
    }

    if(sp->ulog_soc) {
      for( ; batch < HSP_READPACKET_BATCH; batch++) {
	char buf[HSP_MAX_ULOG_MSG_BYTES];
	socklen_t peerlen = sizeof(sp->ulog_peer);
	int len = recvfrom(sp->ulog_soc,
			   buf,
			   HSP_MAX_ULOG_MSG_BYTES,
			   0,
			   (struct sockaddr *)&sp->ulog_peer,
			   &peerlen);
	if(len <= 0) break;
	if(debug > 1) myLog(LOG_INFO, "got ULOG msg: %u bytes", len);
	for(struct nlmsghdr *msg = (struct nlmsghdr *)buf; NLMSG_OK(msg, len); msg=NLMSG_NEXT(msg, len)) {

	  if(debug > 1) {
	    myLog(LOG_INFO, "netlink (%u bytes left) msg [len=%u type=%u flags=0x%x seq=%u pid=%u]",
		  len,
		  msg->nlmsg_len,
		  msg->nlmsg_type,
		  msg->nlmsg_flags,
		  msg->nlmsg_seq,
		  msg->nlmsg_pid);
	  }

          // check for drops indicated by sequence no
          uint32_t droppedSamples = 0;
          if(sp->ulog_seqno) {
            droppedSamples = msg->nlmsg_seq - sp->ulog_seqno - 1;
            if(droppedSamples) {
              sp->ulog_drops += droppedSamples;
            }
          }
          sp->ulog_seqno = msg->nlmsg_seq;

	  switch(msg->nlmsg_type) {
	  case NLMSG_NOOP:
	  case NLMSG_ERROR:
	  case NLMSG_OVERRUN:
	    // ignore these
	    break;
	  case NLMSG_DONE: // last in multi-part
	  default:
	    {

	      if(--MySkipCount == 0) {
		/* reached zero. Set the next skip */
		MySkipCount = sfl_random((2 * sp->sFlow->sFlowSettings->ulogSubSamplingRate) - 1);

		/* and take a sample */

		// we're seeing type==111 on Fedora14
		//if(msg->nlmsg_flags & NLM_F_REQUEST) { }
		//if(msg->nlmsg_flags & NLM_F_MULTI) { }
		//if(msg->nlmsg_flags & NLM_F_ACK) { }
		//if(msg->nlmsg_flags & NLM_F_ECHO) { }
		ulog_packet_msg_t *pkt = NLMSG_DATA(msg);
		
		if(debug > 1) {
		  myLog(LOG_INFO, "mark=%u ts=%s hook=%u in=%s out=%s len=%u prefix=%s maclen=%u",
			pkt->mark,
			ctime(&pkt->timestamp_sec),
			pkt->hook,
			pkt->indev_name,
			pkt->outdev_name,
			pkt->data_len,
			pkt->prefix,
			pkt->mac_len);
		  if(pkt->mac_len == 14) {
		    u_char macdst[12], macsrc[12];
		    printHex(pkt->mac+6,6,macsrc,12,NO);
		    printHex(pkt->mac+0,6,macdst,12,NO);
		    uint16_t ethtype = (pkt->mac[12] << 8) + pkt->mac[13];
		    myLog(LOG_INFO, "%s -> %s (ethertype=0x%04X)", macsrc, macdst, ethtype);
		  }
		}

		
		SFL_FLOW_SAMPLE_TYPE fs = { 0 };
	
		SFLAdaptor *sampler_dev = NULL;
                int inIsLoopback=0, outIsLoopback=0;
 
		// set the ingress and egress ifIndex numbers.
		// Can be "INTERNAL" (0x3FFFFFFF) or "UNKNOWN" (0).
		if(pkt->indev_name[0]) {
		  SFLAdaptor *in = adaptorListGet(sp->adaptorList, pkt->indev_name);
		  if(in) {
		    fs.input = in->ifIndex;
                    // record whether this was a loopback or not - used below
                    HSPAdaptorNIO *inNIO = (HSPAdaptorNIO *)in->userData;
                    inIsLoopback = inNIO->loopback;
#ifdef HSF_CUMULUS
                    // On Cumulus Linux the sampling direction is indicated in the low
                    // bit of the pkt->hook field: 0==ingress,1==egress
                    if((pkt->hook & 1) == 0) {
                      sampler_dev = in;
                    }
#else
                    // set this provisionally - may be overidden below
	            sampler_dev = in;
#endif
		  }
		}
		else {
		  fs.input = SFL_INTERNAL_INTERFACE;
		}
		if(pkt->outdev_name[0]) {
		  SFLAdaptor *out = adaptorListGet(sp->adaptorList, pkt->outdev_name);
		  if(out && out->ifIndex) {
		    fs.output = out->ifIndex;
                    HSPAdaptorNIO *outNIO = (HSPAdaptorNIO *)out->userData;
                    outIsLoopback = outNIO->loopback;
#ifdef HSF_CUMULUS
                    // On Cumulus Linux the sampling direction is indicated in the low
                    // bit of the pkt->hook field: 0==ingress,1==egress
                    if((pkt->hook & 1) == 1) {
                      sampler_dev = out;
                    }
#else
                    // If one of them is not a loopback interface, then assume the
                    // sample was taken there.  In a typical scenario most samples
	            // will be "lo" -> "eth0" or "eth0" -> "lo", so this ensures that
                    // that we make that look like bidirectional sampling on eth0.
                    if(sampler_dev == NULL
                       || (inIsLoopback && !outIsLoopback)) {
		      sampler_dev = out;
                    }
#endif
		  }
		}
		else {
		  fs.output = SFL_INTERNAL_INTERFACE;
		}

		// must have a sampler_dev with an ifIndex
		if(sampler_dev && sampler_dev->ifIndex) {
                  HSPAdaptorNIO *samplerNIO = (HSPAdaptorNIO *)sampler_dev->userData;

                  if(debug > 2) {
                    myLog(LOG_INFO, "selected sampler %s (loopback in=%d out=%d)",
                          sampler_dev->deviceName, 
                          inIsLoopback,
                          outIsLoopback);
                  }

		  SFLSampler *sampler = getSampler(sp, sampler_dev);
		  
		  if(sampler) {
		    SFLFlow_sample_element hdrElem = { 0 };
		    hdrElem.tag = SFLFLOW_HEADER;
		    uint32_t FCS_bytes = 4;
		    uint32_t maxHdrLen = sampler->sFlowFsMaximumHeaderSize;
		    hdrElem.flowType.header.frame_length = pkt->data_len + FCS_bytes;
		    hdrElem.flowType.header.stripped = FCS_bytes;
		    
		    u_char hdr[HSP_MAX_HEADER_BYTES];
		    
		    if(pkt->mac_len == 14) {
		      // set the header_protocol to ethernet and
		      // reunite the mac header and payload in one buffer
		      hdrElem.flowType.header.header_protocol = SFLHEADER_ETHERNET_ISO8023;
		      memcpy(hdr, pkt->mac, 14);
		      maxHdrLen -= 14;
		      uint32_t payloadBytes = (pkt->data_len < maxHdrLen) ? pkt->data_len : maxHdrLen;
		      memcpy(hdr+14, pkt->payload, payloadBytes);
		      hdrElem.flowType.header.header_length = payloadBytes + 14;
		      hdrElem.flowType.header.header_bytes = hdr;
		      hdrElem.flowType.header.frame_length += 14;
		    }
		    else {
		      // no need to copy - just point at the payload
		      u_char ipversion = pkt->payload[0] >> 4;
		      if(ipversion != 4 && ipversion != 6) {
			if(debug) myLog(LOG_ERR, "received non-IP packet. Encapsulation is unknown");
		      }
		      else {
			hdrElem.flowType.header.header_protocol = (ipversion == 4) ? SFLHEADER_IPv4 : SFLHEADER_IPv6;
			hdrElem.flowType.header.stripped += 14; // assume ethernet was (or will be) the framing
			hdrElem.flowType.header.header_length = (pkt->data_len < maxHdrLen) ? pkt->data_len : maxHdrLen;
			hdrElem.flowType.header.header_bytes = pkt->payload;
		      }
		    }
		    
		    SFLADD_ELEMENT(&fs, &hdrElem);
		    // submit the actual sampling rate so it goes out with the sFlow feed
		    // otherwise the sampler object would fill in his own (sub-sampling) rate.
		    // If it's a switch port then samplerNIO->sampling_n will be set, so that
		    // takes precendence (allows different ports to have different sampling
		    // settings).
		    uint32_t actualSamplingRate = samplerNIO->sampling_n ?: sp->sFlow->sFlowSettings->ulogActualSamplingRate;
		    fs.sampling_rate = actualSamplingRate;
		    
		    // estimate the sample pool from the samples.  Could maybe do this
		    // above with the (possibly more granular) ulogSamplingRate, but then
		    // we would have to look up the sampler object every time, which
		    // might be too expensive in the case where ulogSamplingRate==1.
		    sampler->samplePool += actualSamplingRate;
		    
                    // accumulate any dropped-samples we detected against whichever sampler
                    // sends the next sample. This is not perfect,  but is likely to accrue
                    // drops against the point whose sampling-rate needs to be adjusted.
                    samplerNIO->ulog_drops += droppedSamples;
                    fs.drops = samplerNIO->ulog_drops;
		    sfl_sampler_writeFlowSample(sampler, &fs);
		  }
		}
	      }
	    }
	  } 
	}
      }