Esempio n. 1
0
SFLSampler *sfl_agent_addSampler(SFLAgent *agent, SFLDataSource_instance *pdsi)
{
    /* Keep the list sorted. */
    SFLSampler *prev = NULL, *sm = agent->samplers;
    for(; sm != NULL; prev = sm, sm = sm->nxt) {
	int64_t cmp = sfl_dsi_compare(pdsi, &sm->dsi);
	if(cmp == 0) return sm;  /* found - return existing one */
	if(cmp < 0) break;       /* insert here */
    }
    /* either we found the insert point, or reached the end of the list...*/

    {
	SFLSampler *newsm = (SFLSampler *)sflAlloc(agent, sizeof(SFLSampler));
	sfl_sampler_init(newsm, agent, pdsi);
	if(prev) prev->nxt = newsm;
	else agent->samplers = newsm;
	newsm->nxt = sm;

	/* see if we should go in the ifIndex jumpTable */
	if(SFL_DS_CLASS(newsm->dsi) == 0) {
	    SFLSampler *test = sfl_agent_getSamplerByIfIndex(agent, SFL_DS_INDEX(newsm->dsi));
	    if(test && (SFL_DS_INSTANCE(newsm->dsi) < SFL_DS_INSTANCE(test->dsi))) {
		/* replace with this new one because it has a lower ds_instance number */
		sfl_agent_jumpTableRemove(agent, test);
		test = NULL;
	    }
	    if(test == NULL) sfl_agent_jumpTableAdd(agent, newsm);
	}
	return newsm;
    }
}
Esempio n. 2
0
static void sfl_agent_jumpTableRemove(SFLAgent *agent, SFLSampler *sampler)
{
    u_int32_t hashIndex = SFL_DS_INDEX(sampler->dsi) % SFL_HASHTABLE_SIZ;
    SFLSampler *search = agent->jumpTable[hashIndex], *prev = NULL;
    for( ; search != NULL; prev = search, search = search->hash_nxt) if(search == sampler) break;
    if(search) {
	// found - unlink
	if(prev) prev->hash_nxt = search->hash_nxt;
	else agent->jumpTable[hashIndex] = search->hash_nxt;
	search->hash_nxt = NULL;
    }
}
Esempio n. 3
0
void sfl_poller_writeCountersSample(SFLPoller *poller, SFL_COUNTERS_SAMPLE_TYPE *cs)
{
  /* fill in the rest of the header fields, and send to the receiver */
  cs->sequence_number = ++poller->countersSampleSeqNo;
#ifdef SFL_USE_32BIT_INDEX
  cs->ds_class = SFL_DS_CLASS(poller->dsi);
  cs->ds_index = SFL_DS_INDEX(poller->dsi);
#else
  cs->source_id = SFL_DS_DATASOURCE(poller->dsi);
#endif
  /* sent to my receiver */
  if(poller->myReceiver) sfl_receiver_writeCountersSample(poller->myReceiver, cs);
}
Esempio n. 4
0
void sfl_sampler_writeFlowSample(SFLSampler *sampler, SFL_FLOW_SAMPLE_TYPE *fs)
{
  if(fs == NULL) return;
  sampler->samplesThisTick++;
  /* increment the sequence number */
  fs->sequence_number = ++sampler->flowSampleSeqNo;
  /* copy the other header fields in */
#ifdef SFL_USE_32BIT_INDEX
  fs->ds_class = SFL_DS_CLASS(sampler->dsi);
  fs->ds_index = SFL_DS_INDEX(sampler->dsi);
#else
  fs->source_id = SFL_DS_DATASOURCE(sampler->dsi);
#endif
  /* the sampling rate may have been set already. */
  if(fs->sampling_rate == 0) fs->sampling_rate = sampler->sFlowFsPacketSamplingRate;
  /* the samplePool may be maintained upstream too. */
  if( fs->sample_pool == 0) fs->sample_pool = sampler->samplePool;
  /* sent to my receiver */
  if(sampler->myReceiver) sfl_receiver_writeFlowSample(sampler->myReceiver, fs);
}
Esempio n. 5
0
SFLSampler *sfl_agent_getSamplerByIfIndex(SFLAgent *agent, u_int32_t ifIndex)
{
    SFLSampler *search = agent->jumpTable[ifIndex % SFL_HASHTABLE_SIZ];
    for( ; search != NULL; search = search->hash_nxt) if(SFL_DS_INDEX(search->dsi) == ifIndex) break;
    return search;
}
Esempio n. 6
0
static void sfl_agent_jumpTableAdd(SFLAgent *agent, SFLSampler *sampler)
{
    u_int32_t hashIndex = SFL_DS_INDEX(sampler->dsi) % SFL_HASHTABLE_SIZ;
    sampler->hash_nxt = agent->jumpTable[hashIndex];
    agent->jumpTable[hashIndex] = sampler;
}
Esempio n. 7
0
  void agentCB_getCountersVM(void *magic, SFLPoller *poller, SFL_COUNTERS_SAMPLE_TYPE *cs)
  {
#ifdef HSF_XEN
    assert(poller->magic);
    HSP *sp = (HSP *)poller->magic;
    HSPVMState *state = (HSPVMState *)poller->userData;

    if(state && xenHandlesOK(sp)) {
      
      uint32_t dom_id = SFL_DS_INDEX(poller->dsi);
      xc_domaininfo_t domaininfo;
      int32_t n = xc_domain_getinfolist(sp->xc_handle, state->vm_index, 1, &domaininfo);
      if(n < 0 || domaininfo.domain != dom_id) {
	// Assume something changed under our feet.
	// Request a reload of the VM information and bail.
	// We'll try again next time.
	myLog(LOG_INFO, "request for vm_index %u (dom_id=%u) returned %d (with dom_id=%u)",
	      state->vm_index,
	      dom_id,
	      n,
	      domaininfo.domain);
	sp->refreshVMList = YES;
	return;
      }
      
      // host ID
      SFLCounters_sample_element hidElem = { 0 };
      memset(&hidElem, 0, sizeof(hidElem));
      hidElem.tag = SFLCOUNTERS_HOST_HID;
      char query[255];
      char hname[255];
      snprintf(query, sizeof(query), "/local/domain/%u/name", dom_id);
      char *xshname = (char *)xs_read(sp->xs_handle, XBT_NULL, query, NULL);
      if(xshname) {
	// copy the name out here so we can free it straight away
	strncpy(hname, xshname, 255);
	free(xshname);
	hidElem.counterBlock.host_hid.hostname.str = hname;
	hidElem.counterBlock.host_hid.hostname.len = strlen(hname);
	memcpy(hidElem.counterBlock.host_hid.uuid, &domaininfo.handle, 16);
	hidElem.counterBlock.host_hid.machine_type = SFLMT_unknown;
	hidElem.counterBlock.host_hid.os_name = SFLOS_unknown;
	//hidElem.counterBlock.host_hid.os_release.str = NULL;
	//hidElem.counterBlock.host_hid.os_release.len = 0;
	SFLADD_ELEMENT(cs, &hidElem);
      }
      
      // host parent
      SFLCounters_sample_element parElem = { 0 };
      parElem.tag = SFLCOUNTERS_HOST_PAR;
      parElem.counterBlock.host_par.dsClass = SFL_DSCLASS_PHYSICAL_ENTITY;
      parElem.counterBlock.host_par.dsIndex = 1;
      SFLADD_ELEMENT(cs, &parElem);

      // VM Net I/O
      SFLCounters_sample_element nioElem = { 0 };
      nioElem.tag = SFLCOUNTERS_HOST_VRT_NIO;
      char devFilter[20];
      snprintf(devFilter, 20, "vif%u.", dom_id);
      uint32_t network_count = readNioCounters((SFLHost_nio_counters *)&nioElem.counterBlock.host_vrt_nio, devFilter);
      if(state->network_count != network_count) {
	// request a refresh if the number of VIFs changed. Not a perfect test
	// (e.g. if one was removed and another was added at the same time then
	// we would miss it). I guess we should keep the whole list of network ids,
	// or just force a refresh every few minutes?
	myLog(LOG_INFO, "vif count changed from %u to %u (dom_id=%u). Setting refreshAdaptorList=YES",
	      state->network_count,
	      network_count,
	      dom_id);
	state->network_count = network_count;
	sp->refreshAdaptorList = YES;
      }
      SFLADD_ELEMENT(cs, &nioElem);

      // VM cpu counters [ref xenstat.c]
      SFLCounters_sample_element cpuElem = { 0 };
      cpuElem.tag = SFLCOUNTERS_HOST_VRT_CPU;
      u_int64_t vcpu_ns = 0;
      for(uint32_t c = 0; c <= domaininfo.max_vcpu_id; c++) {
	xc_vcpuinfo_t info;
	if(xc_vcpu_getinfo(sp->xc_handle, dom_id, c, &info) != 0) {
	  // error or domain is in transition.  Just bail.
	  myLog(LOG_INFO, "vcpu list in transition (dom_id=%u)", dom_id);
	  return;
	}
	else {
	  if(info.online) {
	    vcpu_ns += info.cpu_time;
	  }
	}
      }
      uint32_t st = domaininfo.flags;
      // first 8 bits (b7-b0) are a mask of flags (see tools/libxc/xen/domctl.h)
      // next 8 bits (b15-b8) indentify the CPU to which the domain is bound
      // next 8 bits (b23-b16) indentify the the user-supplied shutdown code
      cpuElem.counterBlock.host_vrt_cpu.state = SFL_VIR_DOMAIN_NOSTATE;
      if(st & XEN_DOMINF_shutdown) {
	cpuElem.counterBlock.host_vrt_cpu.state = SFL_VIR_DOMAIN_SHUTDOWN;
	if(((st >> XEN_DOMINF_shutdownshift) & XEN_DOMINF_shutdownmask) == SHUTDOWN_crash) {
	  cpuElem.counterBlock.host_vrt_cpu.state = SFL_VIR_DOMAIN_CRASHED;
	}
      }
Esempio n. 8
0
/**
 * Reads a sampled packet header and associated information from
 * the buffer creates a packet sample.
 * Includes looking up the sampler from the ingress and egress
 * port information, and creating a new sampler (and poller) if
 * one does not already exist.
 */
void readPackets(HSP *sp, PUCHAR buffer)
{
	PSFlowSample sample = (PSFlowSample)buffer;
	if (sample->version != 1) {
		myLog(LOG_INFO, "readPackets: unknown filter sample version: %u", 
			  sample->version);
		return;
	}

	SFL_FLOW_SAMPLE_TYPE fs = { 0 };
	char *sampler_dev = NULL;
	uint32_t sampler_ifIndex = 0;
	// set the ingress and egress ifIndex numbers.
	// Can be "INTERNAL" (0x3FFFFFFF) or "UNKNOWN" (0).
	// mimic ingress sampling by using the ingress interface as the data source
	SFLAdaptor *in = getVAdaptorByIds(sp->vAdaptorList, sample->switchID, sample->srcPort);
	if (in) {
		fs.input = in->ifIndex;
		sampler_dev = in->deviceName;
		sampler_ifIndex = in->ifIndex;
	} 
	SFLAdaptor *out = getVAdaptorByIds(sp->vAdaptorList, sample->switchID, sample->destPort);
	if (out) {
		fs.output = out->ifIndex;
	} else {
		fs.output = 0;
	}
	// must have an ifIndex to generate a sample
	if (sampler_ifIndex) {
		SFLSampler *sampler = getSampler(sp, sampler_dev, sampler_ifIndex);
		if (sampler) {
			// 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.
			fs.sampling_rate = sample->sampleRate;
			// estimate the sample pool from the samples. Could maybe do this
			// above with the (possibly more granular) samplingRate, but then
			// we would have to look up the sampler object every time, which
			// might be too expensive in the case where samplingRate==1.
			sampler->samplePool += sample->sampleRate;

			fs.drops = sample->drops;

			PSFlowRecord currRecord = &sample->firstRecord;
			SFLFlow_sample_element hdrElem = { 0 };
			SFLFlow_sample_element extSwElem = { 0 };
			while (currRecord->recordType != NULL_RECORD_TYPE) {
				switch(currRecord->recordType) {
				case SAMPLED_HEADER_RECORD_TYPE: {
					PSFlowSampledHeader sampledHeader = 
						GET_OPAQUE_DATA_ADDR(currRecord, PSFlowSampledHeader);
					hdrElem.tag = SFLFLOW_HEADER;
					hdrElem.flowType.header.frame_length = 
						sampledHeader->frameLength;
                    hdrElem.flowType.header.stripped = sampledHeader->stripped;
					hdrElem.flowType.header.header_protocol = SFLOW_HEADER_PROTOCOL;
					hdrElem.flowType.header.header_length = 
						currRecord->dataLength - sizeof(SFlowSampledHeader);
					hdrElem.flowType.header.header_bytes = GET_OPAQUE_DATA_ADDR(sampledHeader, PUCHAR);
					SFLADD_ELEMENT(&fs, &hdrElem);
					if (LOG_INFO <= debug) {
						 /*u_char pkt[HSP_MAX_HEADER_BYTES*2 +1]; //2 chars/byte + null
						printHex(GET_OPAQUE_DATA_ADDR(sampledHeader, PUCHAR), 
								 hdrElem.flowType.header.header_length, pkt, 
								 HSP_MAX_HEADER_BYTES*2+1, NO);*/
						myLog(LOG_INFO, "readPackets: sampler: %s index: %u headerLength: %u, frameLength: %u dropped: %u", 
							  sampler->userData, SFL_DS_INDEX(sampler->dsi), 
							  hdrElem.flowType.header.header_length, 
							  hdrElem.flowType.header.frame_length,
							  fs.drops);
					}
					break; }
				case EXTENDED_SWITCH_RECORD_TYPE: {
					PSFlowExtendedSwitch extendedSwitch =
						GET_OPAQUE_DATA_ADDR(currRecord, PSFlowExtendedSwitch);
					extSwElem.tag = SFLFLOW_EX_SWITCH;
					extSwElem.flowType.sw.src_vlan = extendedSwitch->sourceVLAN;
					extSwElem.flowType.sw.src_priority = extendedSwitch->sourcePriority;
					extSwElem.flowType.sw.dst_vlan = extendedSwitch->destVLAN;
					extSwElem.flowType.sw.dst_priority = extendedSwitch->destPriority;
					SFLADD_ELEMENT(&fs, &extSwElem);
					if (LOG_INFO <= debug) {
						myLog(LOG_INFO, "readPackets: sampler %s index %u srcVlan: %u srcPriority: %u dstVlan: %u dstPriority: %u",
							sampler->userData, SFL_DS_INDEX(sampler->dsi), 
							extSwElem.flowType.sw.src_vlan, extSwElem.flowType.sw.src_priority,
							extSwElem.flowType.sw.dst_vlan, extSwElem.flowType.sw.dst_priority);
					}
					break; }
                case EXTENDED_TUNNEL_RECORD_TYPE: {
                    PSFlowExtendedTunnel extendedTunnel =
                        GET_OPAQUE_DATA_ADDR(currRecord, PSFlowExtendedTunnel);
					if (LOG_INFO <= debug) {
						myLog(LOG_INFO, "readPackets: sampler %s index %u VSID: %u",
							sampler->userData, SFL_DS_INDEX(sampler->dsi), 
							extendedTunnel->vsid);
					}
                    break; }
				default: {
					myLog(LOG_INFO, "readPackets: unknown filter record type: %u", 
						currRecord->recordType); }
				}
				currRecord = GET_NEXT_SFLOW_RECORD(currRecord);
			}
			sfl_sampler_writeFlowSample(sampler, &fs);
		}
	}
}