void reader_pfring_init(char *UNUSED(name)) { int flags = PF_RING_PROMISC | PF_RING_TIMESTAMP; int clusterId = moloch_config_int(NULL, "pfringClusterId", 0, 0, 255); int i; for (i = 0; i < MAX_INTERFACES && config.interface[i]; i++) { rings[i] = pfring_open(config.interface[i], MOLOCH_SNAPLEN, flags); if (config.bpf) { int err = pfring_set_bpf_filter(rings[i], config.bpf); if (err < 0) { LOG("pfring set filter error %d for %s", err, config.bpf); exit (1); } } if (!rings[i]) { LOG("pfring open failed! - %s", config.interface[i]); exit(1); } pfring_set_cluster(rings[i], clusterId, cluster_per_flow_5_tuple); pfring_set_application_name(rings[i], "moloch-capture"); pfring_set_poll_watermark(rings[i], 64); pfring_enable_rss_rehash(rings[i]); } moloch_reader_start = reader_pfring_start; moloch_reader_stop = reader_pfring_stop; moloch_reader_stats = reader_pfring_stats; }
/** * \brief Init function for RecievePfring. * * This is a setup function for recieving packets * via libpfring. * * \param tv pointer to ThreadVars * \param initdata pointer to the interface passed from the user * \param data pointer gets populated with PfringThreadVars * \todo add a config option for setting cluster id * \todo Create a general pfring setup function. * \retval TM_ECODE_OK on success * \retval TM_ECODE_FAILED on error */ TmEcode ReceivePfringThreadInit(ThreadVars *tv, void *initdata, void **data) { int rc; u_int32_t version = 0; PfringIfaceConfig *pfconf = (PfringIfaceConfig *) initdata; unsigned int opflag; if (pfconf == NULL) return TM_ECODE_FAILED; PfringThreadVars *ptv = SCMalloc(sizeof(PfringThreadVars)); if (unlikely(ptv == NULL)) { pfconf->DerefFunc(pfconf); return TM_ECODE_FAILED; } memset(ptv, 0, sizeof(PfringThreadVars)); ptv->tv = tv; ptv->threads = 1; ptv->interface = SCStrdup(pfconf->iface); if (unlikely(ptv->interface == NULL)) { SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate device string"); SCReturnInt(TM_ECODE_FAILED); } ptv->livedev = LiveGetDevice(pfconf->iface); if (ptv->livedev == NULL) { SCLogError(SC_ERR_INVALID_VALUE, "Unable to find Live device"); SCReturnInt(TM_ECODE_FAILED); } ptv->checksum_mode = pfconf->checksum_mode; opflag = PF_RING_REENTRANT | PF_RING_PROMISC; if (ptv->checksum_mode == CHECKSUM_VALIDATION_RXONLY) { if (strncmp(ptv->interface, "dna", 3) == 0) { SCLogWarning(SC_ERR_INVALID_VALUE, "Can't use rxonly checksum-checks on DNA interface," " resetting to auto"); ptv->checksum_mode = CHECKSUM_VALIDATION_AUTO; } else { opflag |= PF_RING_LONG_HEADER; } } #ifdef HAVE_PFRING_OPEN_NEW ptv->pd = pfring_open(ptv->interface, (uint32_t)default_packet_size, opflag); #else ptv->pd = pfring_open(ptv->interface, LIBPFRING_PROMISC, (uint32_t)default_packet_size, LIBPFRING_REENTRANT); #endif if (ptv->pd == NULL) { SCLogError(SC_ERR_PF_RING_OPEN,"Failed to open %s: pfring_open error." " Check if %s exists and pf_ring module is loaded.", ptv->interface, ptv->interface); pfconf->DerefFunc(pfconf); return TM_ECODE_FAILED; } else { pfring_set_application_name(ptv->pd, PROG_NAME); pfring_version(ptv->pd, &version); } /* We only set cluster info if the number of pfring threads is greater than 1 */ ptv->threads = pfconf->threads; ptv->cluster_id = pfconf->cluster_id; if ((ptv->threads == 1) && (strncmp(ptv->interface, "dna", 3) == 0)) { SCLogInfo("DNA interface detected, not adding thread to cluster"); } else { #ifdef HAVE_PFRING_CLUSTER_TYPE ptv->ctype = pfconf->ctype; rc = pfring_set_cluster(ptv->pd, ptv->cluster_id, ptv->ctype); #else rc = pfring_set_cluster(ptv->pd, ptv->cluster_id); #endif /* HAVE_PFRING_CLUSTER_TYPE */ if (rc != 0) { SCLogError(SC_ERR_PF_RING_SET_CLUSTER_FAILED, "pfring_set_cluster " "returned %d for cluster-id: %d", rc, ptv->cluster_id); pfconf->DerefFunc(pfconf); return TM_ECODE_FAILED; } } if (ptv->threads > 1) { SCLogInfo("(%s) Using PF_RING v.%d.%d.%d, interface %s, cluster-id %d", tv->name, (version & 0xFFFF0000) >> 16, (version & 0x0000FF00) >> 8, version & 0x000000FF, ptv->interface, ptv->cluster_id); } else {
/** * \brief Init function for RecievePfring. * * This is a setup function for recieving packets * via libpfring. * * \param tv pointer to ThreadVars * \param initdata pointer to the interface passed from the user * \param data pointer gets populated with PfringThreadVars * \todo add a config option for setting cluster id * \todo Create a general pfring setup function. * \retval TM_ECODE_OK on success * \retval TM_ECODE_FAILED on error */ TmEcode ReceivePfringThreadInit(ThreadVars *tv, void *initdata, void **data) { int rc; u_int32_t version = 0; PfringIfaceConfig *pfconf = (PfringIfaceConfig *) initdata; unsigned int opflag; char const *active_runmode = RunmodeGetActive(); if (pfconf == NULL) return TM_ECODE_FAILED; PfringThreadVars *ptv = SCMalloc(sizeof(PfringThreadVars)); if (unlikely(ptv == NULL)) { pfconf->DerefFunc(pfconf); return TM_ECODE_FAILED; } memset(ptv, 0, sizeof(PfringThreadVars)); ptv->tv = tv; ptv->threads = 1; ptv->interface = SCStrdup(pfconf->iface); if (unlikely(ptv->interface == NULL)) { SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate device string"); SCFree(ptv); SCReturnInt(TM_ECODE_FAILED); } ptv->livedev = LiveGetDevice(pfconf->iface); if (ptv->livedev == NULL) { SCLogError(SC_ERR_INVALID_VALUE, "Unable to find Live device"); SCFree(ptv); SCReturnInt(TM_ECODE_FAILED); } /* enable zero-copy mode for workers runmode */ if (active_runmode && strcmp("workers", active_runmode) == 0) { ptv->flags |= PFRING_FLAGS_ZERO_COPY; SCLogPerf("Enabling zero-copy for %s", ptv->interface); } ptv->checksum_mode = pfconf->checksum_mode; opflag = PF_RING_PROMISC; /* if suri uses VLAN and if we have a recent kernel, we need * to use parsed_pkt to get VLAN info */ if ((! ptv->vlan_disabled) && SCKernelVersionIsAtLeast(3, 0)) { opflag |= PF_RING_LONG_HEADER; } if (ptv->checksum_mode == CHECKSUM_VALIDATION_RXONLY) { if (strncmp(ptv->interface, "dna", 3) == 0) { SCLogWarning(SC_ERR_INVALID_VALUE, "Can't use rxonly checksum-checks on DNA interface," " resetting to auto"); ptv->checksum_mode = CHECKSUM_VALIDATION_AUTO; } else { opflag |= PF_RING_LONG_HEADER; } } ptv->pd = pfring_open(ptv->interface, (uint32_t)default_packet_size, opflag); if (ptv->pd == NULL) { SCLogError(SC_ERR_PF_RING_OPEN,"Failed to open %s: pfring_open error." " Check if %s exists and pf_ring module is loaded.", ptv->interface, ptv->interface); pfconf->DerefFunc(pfconf); SCFree(ptv); return TM_ECODE_FAILED; } pfring_set_application_name(ptv->pd, PROG_NAME); pfring_version(ptv->pd, &version); /* We only set cluster info if the number of pfring threads is greater than 1 */ ptv->threads = pfconf->threads; ptv->cluster_id = pfconf->cluster_id; if ((ptv->threads == 1) && (strncmp(ptv->interface, "dna", 3) == 0)) { SCLogInfo("DNA interface detected, not adding thread to cluster"); } else if (strncmp(ptv->interface, "zc", 2) == 0) { SCLogInfo("ZC interface detected, not adding thread to cluster"); } else { ptv->ctype = pfconf->ctype; rc = pfring_set_cluster(ptv->pd, ptv->cluster_id, ptv->ctype); if (rc != 0) { SCLogError(SC_ERR_PF_RING_SET_CLUSTER_FAILED, "pfring_set_cluster " "returned %d for cluster-id: %d", rc, ptv->cluster_id); if (rc != PF_RING_ERROR_NOT_SUPPORTED || (pfconf->flags & PFRING_CONF_FLAGS_CLUSTER)) { /* cluster is mandatory as explicitly specified in the configuration */ pfconf->DerefFunc(pfconf); return TM_ECODE_FAILED; } } } if (ptv->threads > 1) { SCLogPerf("(%s) Using PF_RING v.%d.%d.%d, interface %s, cluster-id %d", tv->name, (version & 0xFFFF0000) >> 16, (version & 0x0000FF00) >> 8, version & 0x000000FF, ptv->interface, ptv->cluster_id); } else {
static int pfring_daq_open(Pfring_Context_t *context, int id) { uint32_t default_net = 0xFFFFFF00; char *device = context->devices[id]; int pfring_rc; pfring *ring_handle; char buf[32]; if(!device) { DPE(context->errbuf, "%s", "PF_RING a device must be specified"); return -1; } if(device) { if(strncmp(device, "dna", 3) == 0) { DPE(context->errbuf, "DNA is not supported by daq_pfring. Please get daq_pfring_dna from http://shop.ntop.org"); return(-1); } context->pkt_buffer = NULL; ring_handle = pfring_open(device, context->snaplen, PF_RING_LONG_HEADER | (context->promisc_flag ? PF_RING_PROMISC : 0)); if(!ring_handle) { DPE(context->errbuf, "pfring_open(): unable to open device '%s'. Please use -i <device>", device); return -1; } } pfring_get_bound_device_ifindex(ring_handle, &context->ifindexes[id]); /* TODO this is because rules purging is not yet available with hw rules */ pfring_set_filtering_mode(ring_handle, software_only); if (context->mode == DAQ_MODE_INLINE) { /* Default mode: recv_and_send_mode */ pfring_set_direction(ring_handle, rx_only_direction); } else if (context->mode == DAQ_MODE_PASSIVE) { /* Default direction: rx_and_tx_direction */ if(context->num_reflector_devices > id) { /* lowlevelbridge ON */ filtering_rule rule; memset(&rule, 0, sizeof(rule)); rule.rule_id = 1; rule.rule_action = reflect_packet_and_continue_rule_evaluation; snprintf(rule.reflector_device_name, REFLECTOR_NAME_LEN, "%s", context->reflector_devices[id]); if(pfring_add_filtering_rule(ring_handle, &rule) < 0) { DPE(context->errbuf, "unable to set the low level packet reflector %s -> %s", device, rule.reflector_device_name); pfring_close(ring_handle); return -1; } else printf("%s -> %s\n", context->devices[id], context->reflector_devices[id]); pfring_set_direction(ring_handle, rx_only_direction); } pfring_set_socket_mode(ring_handle, recv_only_mode); } if(context->clusterids[id] > 0) { pfring_rc = pfring_set_cluster(ring_handle, context->clusterids[id], context->cluster_mode); if(pfring_rc != 0) { DPE(context->errbuf, "pfring_set_cluster returned %d", pfring_rc); pfring_close(ring_handle); return -1; } snprintf(buf, sizeof(buf), "snort-cluster-%d-socket-%d", context->clusterids[id], id); pfring_set_application_name(ring_handle, buf); } else { snprintf(buf, sizeof(buf), "snort-socket-%d", id); pfring_set_application_name(ring_handle, buf); } pfring_set_poll_watermark(ring_handle, context->watermark); context->netmask = htonl(default_net); context->ring_handles[id] = ring_handle; return(0); }
bool PfRingDevice::openMultiRxChannels(uint8_t numOfRxChannelsToOpen, ChannelDistribution dist) { if (m_DeviceOpened) { LOG_ERROR("Device already opened"); return false; } m_NumOfOpenedRxChannels = 0; if (numOfRxChannelsToOpen > MAX_NUM_RX_CHANNELS) { LOG_ERROR("Cannot open more than [%d] channels", MAX_NUM_RX_CHANNELS); return false; } uint32_t flags = PF_RING_PROMISC | PF_RING_REENTRANT | PF_RING_HW_TIMESTAMP | PF_RING_DNA_SYMMETRIC_RSS; uint8_t numOfRxChannelsOnNIC = getTotalNumOfRxChannels(); LOG_DEBUG("NIC has %d RX channels", numOfRxChannelsOnNIC); uint8_t numOfRingsPerRxChannel = numOfRxChannelsToOpen / numOfRxChannelsOnNIC; uint8_t remainderRings = numOfRxChannelsToOpen % numOfRxChannelsOnNIC; cluster_type clusterType = (dist == RoundRobin) ? cluster_round_robin : cluster_per_flow; int ringsOpen = 0; for (uint8_t channelId = 0; channelId < numOfRxChannelsOnNIC; channelId++) { // no more channels to open if (numOfRingsPerRxChannel == 0 && remainderRings == 0) break; char ringName[32]; snprintf(ringName, sizeof(ringName), "%s@%d", m_DeviceName, channelId); // open numOfRingsPerRxChannel rings per RX channel for (uint8_t ringId = 0; ringId < numOfRingsPerRxChannel; ringId++) { m_PfRingDescriptors[ringsOpen] = pfring_open(ringName, DEFAULT_PF_RING_SNAPLEN, flags); if (m_PfRingDescriptors[ringsOpen] == NULL) { LOG_ERROR("Couldn't open a ring on channel [%d]", channelId); break; } // setting a cluster for all rings in the same channel to enable hashing between them if (pfring_set_cluster(m_PfRingDescriptors[ringsOpen], channelId+1, clusterType) < 0) { LOG_ERROR("Couldn't set ring [%d] in channel [%d] to the cluster [%d]", ringId, channelId, channelId+1); break; } ringsOpen++; } // open one more ring if remainder > 0 if (remainderRings > 0) { m_PfRingDescriptors[ringsOpen] = pfring_open(ringName, DEFAULT_PF_RING_SNAPLEN, flags); if (m_PfRingDescriptors[ringsOpen] == NULL) { LOG_ERROR("Couldn't open a ring on channel [%d]", channelId); break; } // setting a cluster for all rings in the same channel to enable hashing between them if (pfring_set_cluster(m_PfRingDescriptors[ringsOpen], channelId, clusterType) < 0) { LOG_ERROR("Couldn't set ring [%d] in channel [%d] to the cluster [%d]", numOfRingsPerRxChannel+1, channelId, channelId); break; } ringsOpen++; remainderRings--; LOG_DEBUG("Opened %d rings on channel [%d]", numOfRingsPerRxChannel+1, channelId); } else LOG_DEBUG("Opened %d rings on channel [%d]", numOfRingsPerRxChannel, channelId); } if (ringsOpen < numOfRxChannelsToOpen) { for (uint8_t i = 0; i < ringsOpen; i++) pfring_close(m_PfRingDescriptors[i]); return false; } if (getIsHwClockEnable()) { for (int i = 0; i < ringsOpen; i++) { if (setPfRingDeviceClock(m_PfRingDescriptors[i])) LOG_DEBUG("H/W clock set for device [%s]", m_DeviceName); } } // enable all rings for (int i = 0; i < ringsOpen; i++) { if (pfring_enable_rss_rehash(m_PfRingDescriptors[i]) < 0 || pfring_enable_ring(m_PfRingDescriptors[i]) < 0) { LOG_ERROR("Unable to enable ring [%d] for device [%s]", i, m_DeviceName); // close all pfring's that were enabled until now for (int j = 0; j <ringsOpen; j++) pfring_close(m_PfRingDescriptors[j]); return false; } } m_NumOfOpenedRxChannels = ringsOpen; m_DeviceOpened = true; return true; }