int PfRingDevice::openSingleRxChannel(const char* deviceName, pfring** ring) { if (m_DeviceOpened) { LOG_ERROR("Device already opened"); return false; } uint32_t flags = PF_RING_PROMISC | PF_RING_HW_TIMESTAMP | PF_RING_DNA_SYMMETRIC_RSS; *ring = pfring_open(deviceName, DEFAULT_PF_RING_SNAPLEN, flags); if (*ring == NULL) { return 1; } LOG_DEBUG("pfring_open Succeeded for device [%s]", deviceName); if (getIsHwClockEnable()) { setPfRingDeviceClock(*ring); LOG_DEBUG("H/W clock set for device [%s]", deviceName); } if (pfring_enable_rss_rehash(*ring) < 0 || pfring_enable_ring(*ring) < 0) { pfring_close(*ring); return 2; } LOG_DEBUG("pfring enabled for device [%s]", deviceName); return 0; }
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; }
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; }
int main(int argc, char* argv[]) { char *device = NULL, c, *bind_mask = NULL; int snaplen = DEFAULT_SNAPLEN, rc, watermark = 0, rehash_rss = 0; packet_direction direction = rx_only_direction; long i; u_int16_t cpu_percentage = 0, poll_duration = 0; u_int32_t version; u_int32_t flags = 0; startTime.tv_sec = 0; thiszone = gmt2local(0); numCPU = sysconf( _SC_NPROCESSORS_ONLN ); memset(thread_core_affinity, -1, sizeof(thread_core_affinity)); while((c = getopt(argc,argv,"hi:l:mvae:w:b:rp:g:")) != -1) { switch(c) { case 'h': printHelp(); return(0); break; case 'a': wait_for_packet = 0; break; case 'e': switch(atoi(optarg)) { case rx_and_tx_direction: case rx_only_direction: case tx_only_direction: direction = atoi(optarg); break; } break; case 'l': snaplen = atoi(optarg); break; case 'i': device = strdup(optarg); break; case 'm': use_extended_pkt_header = 1; break; case 'v': verbose = 1; break; case 'w': watermark = atoi(optarg); break; case 'b': cpu_percentage = atoi(optarg); break; case 'r': rehash_rss = 1; break; case 'p': poll_duration = atoi(optarg); break; case 'g': bind_mask = strdup(optarg); break; } } if(verbose) watermark = 1; if(device == NULL) device = DEFAULT_DEVICE; printf("Capturing from %s\n", device); flags |= PF_RING_PROMISC; /* hardcode: promisc=1 */ #if 0 flags |= PF_RING_DNA_FIXED_RSS_Q_0; #else flags |= PF_RING_DNA_SYMMETRIC_RSS; /* Note that symmetric RSS is ignored by non-DNA drivers */ #endif if(use_extended_pkt_header) flags |= PF_RING_LONG_HEADER; num_channels = pfring_open_multichannel(device, snaplen, flags, ring); if(num_channels <= 0) { fprintf(stderr, "pfring_open_multichannel() returned %d [%s]\n", num_channels, strerror(errno)); return(-1); } if (num_channels > MAX_NUM_THREADS) { printf("WARNING: Too many channels (%d), using %d channels\n", num_channels, MAX_NUM_THREADS); num_channels = MAX_NUM_THREADS; } else if (num_channels > numCPU) { printf("WARNING: More channels (%d) than available cores (%d), using %d channels\n", num_channels, numCPU, numCPU); num_channels = numCPU; } else { printf("Found %d channels\n", num_channels); } if(bind_mask != NULL) { char *id = strtok(bind_mask, ":"); int idx = 0; while(id != NULL) { thread_core_affinity[idx++] = atoi(id) % numCPU; if(idx >= num_channels) break; id = strtok(NULL, ":"); } } pfring_version(ring[0], &version); printf("Using PF_RING v.%d.%d.%d\n", (version & 0xFFFF0000) >> 16, (version & 0x0000FF00) >> 8, version & 0x000000FF); for(i=0; i<num_channels; i++) { char buf[32]; snprintf(buf, sizeof(buf), "pfcount_multichannel-thread %ld", i); pfring_set_application_name(ring[i], buf); if((rc = pfring_set_direction(ring[i], direction)) != 0) fprintf(stderr, "pfring_set_direction returned %d [direction=%d] (you can't capture TX with DNA)\n", rc, direction); if((rc = pfring_set_socket_mode(ring[i], recv_only_mode)) != 0) fprintf(stderr, "pfring_set_socket_mode returned [rc=%d]\n", rc); if(watermark > 0) { if((rc = pfring_set_poll_watermark(ring[i], watermark)) != 0) fprintf(stderr, "pfring_set_poll_watermark returned [rc=%d][watermark=%d]\n", rc, watermark); } #if 0 setup_steering(ring[0], "192.168.30.207", -1); /* UTDF */ setup_steering(ring[0], "224.0.1.92", 1); setup_steering(ring[0], "224.0.1.94", 1); setup_steering(ring[0], "224.0.1.96", 1); /* BATS */ setup_steering(ring[0], "224.0.62.2", 2); /* default: should go to channel 0 */ #endif if(rehash_rss) pfring_enable_rss_rehash(ring[i]); if(poll_duration > 0) pfring_set_poll_duration(ring[i], poll_duration); pfring_enable_ring(ring[i]); pthread_create(&pd_thread[i], NULL, packet_consumer_thread, (void*)i); usleep(500); } if(cpu_percentage > 0) { if(cpu_percentage > 99) cpu_percentage = 99; pfring_config(cpu_percentage); } signal(SIGINT, sigproc); signal(SIGTERM, sigproc); signal(SIGINT, sigproc); if(!verbose) { signal(SIGALRM, my_sigalarm); alarm(ALARM_SLEEP); } for(i=0; i<num_channels; i++) { pthread_join(pd_thread[i], NULL); pfring_close(ring[i]); } return(0); }