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; }
static int max_packet_len(Pfring_Context_t *context, char *device, int id, int *card_buffers) { int max_len = 1536, num_slots = 32768 /* max */; pfring *ring; ring = pfring_open(device, 1536, PF_RING_PROMISC); if (ring == NULL) goto error; pfring_get_bound_device_ifindex(ring, &context->ifindexes[id]); if (ring->zc_device) { pfring_card_settings settings; pfring_get_card_settings(ring, &settings); max_len = settings.max_packet_size; num_slots = settings.rx_ring_slots; } else { max_len = pfring_get_mtu_size(ring); if (max_len == 0) max_len = 9000; max_len += 14 + 4; num_slots = 0; } pfring_close(ring); error: *card_buffers = num_slots; return max_len; }
pfring * open_pfring(char *d){ pfring *pd = NULL; char *device = NULL; u_int32_t flags = 0; device = d; if(device == NULL) device = DEFAULT_DEVICE; flags |= PF_RING_PROMISC; flags |= PF_RING_DNA_SYMMETRIC_RSS; pd = pfring_open(device, PFRING_SNAPLEN, flags); if(pd == NULL){ fprintf(stderr,"pfring_open error\n"); return NULL; }else{ u_int32_t version; pfring_version(pd, &version); printf("using PF_RING v.%d.%d.%d\n", (version & 0xFFFF0000)>>16, (version & 0x0000FF00)>>8, version & 0x000000FF); } return pd; }
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; }
void PfRingDevice::setPfRingDeviceAttributes() { if (m_InterfaceIndex > -1) return; pfring* ring = NULL; bool closeRing = false; if (m_NumOfOpenedRxChannels > 0) ring = m_PfRingDescriptors[0]; else { uint32_t flags = PF_RING_PROMISC | PF_RING_DNA_SYMMETRIC_RSS; ring = pfring_open(m_DeviceName, DEFAULT_PF_RING_SNAPLEN, flags); closeRing = true; } if (ring == NULL) { LOG_ERROR("Could not open a pfring for setting device attributes: MAC address, interface index and HW clock"); return; } // set device MAC address uint8_t macAddress[6]; if (pfring_get_bound_device_address(ring, macAddress) < 0) LOG_ERROR("Unable to read the device MAC address for interface '%s'", m_DeviceName); else m_MacAddress = MacAddress(macAddress); // set interface ID if (pfring_get_bound_device_ifindex(ring, &m_InterfaceIndex) < 0) LOG_ERROR("Unable to read interface index of device"); // try to set hardware device clock m_HwClockEnabled = setPfRingDeviceClock(ring); // set interface MTU int mtu = pfring_get_mtu_size(ring); if (mtu < 0) LOG_ERROR("Could not get MTU. pfring_get_mtu_size returned an error: %d", mtu); else m_DeviceMTU = mtu + sizeof(ether_header) + sizeof(vlan_header); if (LoggerPP::getInstance().isDebugEnabled(PcapLogModulePfRingDevice)) { std::string hwEnabled = (m_HwClockEnabled ? "enabled" : "disabled"); LOG_DEBUG("Capturing from %s [%s][ifIndex: %d][MTU: %d], HW clock %s", m_DeviceName, m_MacAddress.toString().c_str(), m_InterfaceIndex, m_DeviceMTU, hwEnabled.c_str()); } if (closeRing) pfring_close(ring); }
u_int8_t pfring_open_multichannel(const char *device_name, u_int32_t caplen, u_int32_t flags, pfring *ring[MAX_NUM_RX_CHANNELS]) { u_int8_t num_channels, i, num = 0; char *at; char base_device_name[32]; snprintf(base_device_name, sizeof(base_device_name), "%s", device_name); at = strchr(base_device_name, '@'); if(at != NULL) at[0] = '\0'; /* Count how many RX channel the specified device supports */ ring[0] = pfring_open(base_device_name, caplen, flags); if(ring[0] == NULL) return(0); else num_channels = pfring_get_num_rx_channels(ring[0]); pfring_close(ring[0]); if(num_channels > MAX_NUM_RX_CHANNELS) num_channels = MAX_NUM_RX_CHANNELS; /* Now do the real job */ for(i=0; i<num_channels; i++) { char dev[32]; snprintf(dev, sizeof(dev), "%s@%d", base_device_name, i); ring[i] = pfring_open(dev, caplen, flags); if(ring[i] == NULL) return(num); else num++; } return(num); }
int pfring_set_reflector_device(pfring *ring, char *device_name) { if((device_name == NULL) || ring->reflector_socket) return(-1); ring->reflector_socket = pfring_open(device_name, ring->caplen, PF_RING_PROMISC); if(ring->reflector_socket != NULL) { pfring_set_socket_mode(ring->reflector_socket, send_only_mode); pfring_enable_ring(ring->reflector_socket); return(0); } else return(-1); }
cluster::cluster(char* name):device_name(name),circle_user_(20000), circle_protocol_(1000),circle_sys_(10),circle_flow_stat_(10), stat_sys_(NULL),stat_flow_(NULL),stat_parser_(OUT_PUT_RATE) { ring = pfring_open(device_name.c_str(), PF_CAP_LEN, PF_RING_PROMISC | PF_RING_TIMESTAMP); if(NULL == ring) { printf("open %s device failed\n", device_name.c_str()); exit(1); } time_out_put = 0; }
int open_rx_ring(char *rx_device) { u_int32_t version; char buf[32]; pd[num_dev] = pfring_open(rx_device, 1500 /* snaplen */, PF_RING_PROMISC | PF_RING_DNA_FIXED_RSS_Q_0 /* if RSS is enabled, steer all to queue 0 */); if(pd[num_dev] == NULL) { printf("pfring_open %s error [%s]\n", rx_device, strerror(errno)); return(-1); } if (num_dev == 0) { pfring_version(pd[num_dev], &version); printf("Using PF_RING v.%d.%d.%d\n", (version & 0xFFFF0000) >> 16, (version & 0x0000FF00) >> 8, version & 0x000000FF); }
uint8_t PfRingDevice::getTotalNumOfRxChannels() { if (m_NumOfOpenedRxChannels > 0) { uint8_t res = pfring_get_num_rx_channels(m_PfRingDescriptors[0]); return res; } else { uint32_t flags = PF_RING_PROMISC | PF_RING_REENTRANT | PF_RING_HW_TIMESTAMP | PF_RING_DNA_SYMMETRIC_RSS; pfring* ring = pfring_open(m_DeviceName, DEFAULT_PF_RING_SNAPLEN, flags); uint8_t res = pfring_get_num_rx_channels(ring); pfring_close(ring); return res; } }
PfRingDeviceList::PfRingDeviceList() { m_PfRingVersion = ""; FILE *fd = popen("lsmod | grep pf_ring", "r"); char buf[16]; if (fread (buf, 1, sizeof (buf), fd) <= 0) // if there is some result the module must be loaded { LOG_ERROR("PF_RING kernel module isn't loaded. Please run: 'sudo insmod <PF_RING_LOCATION>/kernel/pf_ring.ko'"); return; } LOG_DEBUG("PF_RING kernel module is loaded"); pcap_if_t* interfaceList; char errbuf[PCAP_ERRBUF_SIZE]; LOG_DEBUG("PfRingDeviceList init: searching all interfaces on machine"); int err = pcap_findalldevs(&interfaceList, errbuf); if (err < 0) { LOG_ERROR("Error searching for PF_RING devices: %s", errbuf); } pcap_if_t* currInterface = interfaceList; while (currInterface != NULL) { if ((currInterface->flags & 0x1) != PCAP_IF_LOOPBACK) { uint32_t flags = PF_RING_PROMISC | PF_RING_DNA_SYMMETRIC_RSS; pfring* ring = pfring_open(currInterface->name, 128, flags); if (ring != NULL) { if (m_PfRingVersion == "") calcPfRingVersion(ring); pfring_close(ring); PfRingDevice* newDev = new PfRingDevice(currInterface->name); m_PfRingDeviceList.push_back(newDev); LOG_DEBUG("Found interface: %s", currInterface->name); } } currInterface = currInterface->next; } LOG_DEBUG("PfRingDeviceList init end"); pcap_freealldevs(interfaceList); }
pfring *pfring_open_consumer(const char *device_name, u_int32_t caplen, u_int32_t flags, u_int8_t consumer_plugin_id, char* consumer_data, u_int consumer_data_len) { pfring *ring = pfring_open(device_name, caplen, flags); if(ring) { if(consumer_plugin_id > 0) { int rc; ring->kernel_packet_consumer = consumer_plugin_id; rc = pfring_set_packet_consumer_mode(ring, consumer_plugin_id, consumer_data, consumer_data_len); if(rc < 0) { pfring_close(ring); return(NULL); } } } return ring; }
static int max_packet_len(Pfring_Context_t *context, char *device, int id) { int max_len; pfring *ring; ring = pfring_open(device, 1536, PF_RING_PROMISC); if (ring == NULL) return 1536; pfring_get_bound_device_ifindex(ring, &context->ifindexes[id]); if (ring->dna.dna_mapped_device) { max_len = ring->dna.dna_dev.mem_info.rx.packet_memory_slot_len; } else { max_len = pfring_get_mtu_size(ring); if (max_len == 0) max_len = 9000; max_len += 14 + 4; } pfring_close(ring); return max_len; }
int main(int argc, char* argv[]) { pfring *pd; virtual_filtering_device_info info; int rc; pd = pfring_open("none", 0 /* promisc */, 128 /* snaplen */, 0 /* reentrant */); if(pd == NULL) { printf("pfring_open error\n"); return(-1); } else { u_int32_t version; pfring_set_application_name(pd, "vdevice_simulator"); pfring_version(pd, &version); printf("Using PF_RING v.%d.%d.%d\n", (version & 0xFFFF0000) >> 16, (version & 0x0000FF00) >> 8, version & 0x000000FF); } strcpy(info.device_name, "vdef0"); info.device_type = silicom_redirector_family; if((rc = pfring_set_virtual_device(pd, &info)) < 0) { printf("Unable to register virtual device %s [rc=%d]\n", info.device_name, rc); } else { printf("Succefully registered virtual device %s\n", info.device_name); } pfring_close(pd); return(0); }
int main(int argc, char* argv[]) { pfring *pd; char *device, *buffer; u_int buffer_len, num_runs, test_len, i, test_id, j; struct timeval startTime, endTime; double deltaUsec, call_per_sec, thpt, call_duration_usec; device = "eth0"; pd = pfring_open(device, 128, PF_RING_PROMISC); if(pd == NULL) { printf("pfring_open error(%s) [%s]\n", device, strerror(errno)); return(-1); } else { u_int32_t version; pfring_set_application_name(pd, "pfsystest"); pfring_version(pd, &version); printf("Using PF_RING v.%d.%d.%d\n", (version & 0xFFFF0000) >> 16, (version & 0x0000FF00) >> 8, version & 0x000000FF); } if(0) { test_id = 64; buffer_len = test_id*1024; buffer = malloc(buffer_len); if(buffer == NULL) { /* oops, couldn't allocate memory */ fprintf(stderr, "Unable to allocate memory requested (%s)\n", strerror(errno)); return (-1); } num_runs = 10000; for(j=0; j<=test_id; j++) { test_len = j*1024; gettimeofday(&startTime, NULL); for(i=0; i<num_runs; i++) pfring_loopback_test(pd, buffer, buffer_len, test_len); gettimeofday(&endTime, NULL); deltaUsec = delta_time(&endTime, &startTime); call_duration_usec = deltaUsec/((double)num_runs); call_per_sec = ((double)num_runs*1000000)/deltaUsec; thpt = (double)(call_per_sec * test_len * 8) / (double)1000000000; printf("%02d [Test len=%d KB][%.2f calls/sec][%.1f usec/call][Thpt: %.2f Gbps][%s]\n", j, test_len/1024, call_per_sec, call_duration_usec, thpt, (thpt > (double)10) ? "10 Gbit Wire rate" : "No Wire rate"); } free(buffer); /* ************************************** */ test_id = 4; buffer_len = test_id*1024*1024; buffer = malloc(buffer_len); if(buffer == NULL) { /* oops, couldn't allocate memory */ fprintf(stderr, "Unable to allocate memory requested (%s)\n", strerror(errno)); return (-1); } num_runs = 1000; for(j=1; j<=test_id; j++) { test_len = j*1024*1024; gettimeofday(&startTime, NULL); for(i=0; i<num_runs; i++) pfring_loopback_test(pd, buffer, buffer_len, test_len); gettimeofday(&endTime, NULL); deltaUsec = delta_time(&endTime, &startTime); call_duration_usec = deltaUsec/((double)num_runs); call_per_sec = ((double)num_runs*1000000)/deltaUsec; thpt = (double)(call_per_sec * test_len * 8) / (double)1000000000; printf("%02d [Test len=%d KB][%.2f calls/sec][%.1f usec/call][Thpt: %.2f Gbps][%s]\n", j, test_len/1024, call_per_sec, call_duration_usec, thpt, (thpt > (double)10) ? "10 Gbit Wire rate" : "No Wire rate"); } free(buffer); } /* ******************************************** */ test_id = 8; buffer_len = test_id*1024*1024; buffer = malloc(buffer_len); if(buffer == NULL) { /* oops, couldn't allocate memory */ fprintf(stderr, "Unable to allocate memory requested (%s)\n", strerror(errno)); return (-1); } num_runs = 1000; for(j=0; j<=test_id; j++) { test_len = j*1024*1024; gettimeofday(&startTime, NULL); for(i=0; i<num_runs; i++) pfring_loopback_test(pd, buffer, buffer_len, test_len); gettimeofday(&endTime, NULL); deltaUsec = delta_time(&endTime, &startTime); printf("%02d Test len=%d, %.2f calls/sec [%.1f usec/call]\n", j, test_len, ((double)num_runs*1000)/deltaUsec, deltaUsec/num_runs); } free(buffer); pfring_close(pd); return(0); }
/** * \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 {
int main() { char* dev = "zc:eth3"; // We could pool device in multiple threads unsigned int num_threads = 1; bool promisc = true; /* This flag manages packet parser for extended_hdr */ bool use_extended_pkt_header = true; bool enable_hw_timestamp = false; bool dont_strip_timestamps = false; u_int32_t flags = 0; if (num_threads > 1) flags |= PF_RING_REENTRANT; if (use_extended_pkt_header) flags |= PF_RING_LONG_HEADER; if (promisc) flags |= PF_RING_PROMISC; if (enable_hw_timestamp) flags |= PF_RING_HW_TIMESTAMP; if (!dont_strip_timestamps) flags |= PF_RING_STRIP_HW_TIMESTAMP; // if (!we_use_pf_ring_in_kernel_parser) { // flags != PF_RING_DO_NOT_PARSE; //} // flags |= PF_RING_DNA_SYMMETRIC_RSS; /* Note that symmetric RSS is ignored by non-DNA drivers // */ // use default value from pfcount.c unsigned int snaplen = 128; pfring* pf_ring_descr = pfring_open(dev, snaplen, flags); if (pf_ring_descr == NULL) { std::cout << "pfring_open error: " << strerror(errno) << " (pf_ring not loaded or perhaps you use quick mode and have already a socket bound to: " << dev << ")"; return false; } u_int32_t version; // Set spplication name in /proc int pfring_set_application_name_result = pfring_set_application_name(pf_ring_descr, (char*)"fastnetmon"); if (pfring_set_application_name_result != 0) { std::cout << "Can't set programm name for PF_RING: pfring_set_application_name"; } pfring_version(pf_ring_descr, &version); int pfring_set_socket_mode_result = pfring_set_socket_mode(pf_ring_descr, recv_only_mode); // enable ring if (pfring_enable_ring(pf_ring_descr) != 0) { std::cout << "Unable to enable ring :-("; pfring_close(pf_ring_descr); return false; } u_int8_t wait_for_packet = 1; pfring_loop(pf_ring_descr, parse_packet_pf_ring, (u_char*)NULL, wait_for_packet); }
int main(int argc, char *argv[]) { char *dev; // The device to sniff on char errbuf[PCAP_ERRBUF_SIZE]; // Error string if any operation fails struct bpf_program fp; // The compiled filter (not used) char filter_exp[] = "port 23"; // The filter expression (not used) bpf_u_int32 mask; // Our subnet mask bpf_u_int32 net; // Our network ID struct pfring_pkthdr header; // The header that pfring gives us u_char *packet; // The actual packet int flags,num_pkts=0; // Flags to pass for opening pfring instance, number of packets captured memset(&header,0,sizeof(header)); signal(SIGINT,sigproc); dev = argv[1]; // Set the device manually to arg[1] printf("\nCapture device: %s\n", dev); makefilename(); flags = PF_RING_PROMISC; if((handle = pfring_open(dev, 1520, flags)) == NULL) { //MAX_CAPLEN instead of 1520 printf("pfring_open error"); return(-1); } else { pfring_set_application_name(handle, "packetcapture"); } pfring_enable_ring(handle); dumper = pcap_dump_open(pcap_open_dead(DLT_EN10MB, 16384), filename); //16384 is MTU if(dumper == NULL) { printf("Unable to create dump file %s\n", filename); return(-1); } while(1) { if(pfring_recv(handle, &packet, 0, &header, 1 ) > 0) { //wait for packet, blocking call if(num_pkts>=PACKETS_PER_FILE) { num_pkts = 0; pcap_dump_close(dumper); filenumber++; makefilename(); dumper = pcap_dump_open(pcap_open_dead(DLT_EN10MB, 16384), filename); if(dumper == NULL) { printf("Unable to create dump file %s\n", filename); exit(1); } } pcap_dump((u_char*)dumper, (struct pcap_pkthdr*)&header, packet); fprintf(stdout, "."); fflush(stdout); num_pkts++; } } pcap_dump_close(dumper); pfring_close(handle); return 0; }
int main(int argc, char* argv[]) { char c, *pcap_in = NULL; int i, verbose = 0, active_poll = 0, disable_zero_copy = 0; int use_zero_copy_tx = 0; u_int mac_a, mac_b, mac_c, mac_d, mac_e, mac_f; char buffer[9000]; u_int32_t num_to_send = 0; int bind_core = -1; u_int16_t cpu_percentage = 0; double gbit_s = 0, td, pps; ticks tick_start = 0, tick_delta = 0; ticks hz = 0; struct packet *tosend; u_int num_tx_slots = 0; int num_balanced_pkts = 1, watermark = 0; u_int num_pcap_pkts = 0; while((c = getopt(argc,argv,"b:hi:n:g:l:af:r:vm:w:zx:" #if 0 "b:" #endif )) != -1) { switch(c) { case 'b': num_balanced_pkts = atoi(optarg); break; case 'h': printHelp(); break; case 'i': in_dev = strdup(optarg); break; case 'f': pcap_in = strdup(optarg); break; case 'n': num_to_send = atoi(optarg); break; case 'g': bind_core = atoi(optarg); break; case 'l': send_len = atoi(optarg); break; case 'x': if_index = atoi(optarg); break; case 'v': verbose = 1; break; case 'a': active_poll = 1; break; case 'r': sscanf(optarg, "%lf", &gbit_s); break; #if 0 case 'b': cpu_percentage = atoi(optarg); #endif break; case 'm': if(sscanf(optarg, "%02X:%02X:%02X:%02X:%02X:%02X", &mac_a, &mac_b, &mac_c, &mac_d, &mac_e, &mac_f) != 6) { printf("Invalid MAC address format (XX:XX:XX:XX:XX:XX)\n"); return(0); } else { reforge_mac = 1; mac_address[0] = mac_a, mac_address[1] = mac_b, mac_address[2] = mac_c; mac_address[3] = mac_d, mac_address[4] = mac_e, mac_address[5] = mac_f; } break; case 'w': watermark = atoi(optarg); if(watermark < 1) watermark = 1; break; case 'z': disable_zero_copy = 1; break; } } if((in_dev == NULL) || (num_balanced_pkts < 1)) printHelp(); printf("Sending packets on %s\n", in_dev); pd = pfring_open(in_dev, 1500, 0 /* PF_RING_PROMISC */); if(pd == NULL) { printf("pfring_open %s error [%s]\n", in_dev, strerror(errno)); return(-1); } else { u_int32_t version; pfring_set_application_name(pd, "pfdnasend"); pfring_version(pd, &version); printf("Using PF_RING v.%d.%d.%d\n", (version & 0xFFFF0000) >> 16, (version & 0x0000FF00) >> 8, version & 0x000000FF); } if (!pd->send && pd->send_ifindex && if_index == -1) { printf("Please use -x <if index>\n"); return -1; } if(watermark > 0) { int rc; if((rc = pfring_set_tx_watermark(pd, watermark)) < 0) printf("pfring_set_tx_watermark() failed [rc=%d]\n", rc); } signal(SIGINT, sigproc); signal(SIGTERM, sigproc); signal(SIGINT, sigproc); if(send_len < 60) send_len = 60; if(gbit_s != 0) { /* cumputing usleep delay */ tick_start = getticks(); usleep(1); tick_delta = getticks() - tick_start; /* cumputing CPU freq */ tick_start = getticks(); usleep(1001); hz = (getticks() - tick_start - tick_delta) * 1000 /*kHz -> Hz*/; printf("Estimated CPU freq: %lu Hz\n", (long unsigned int)hz); } if(pcap_in) { char ebuf[256]; u_char *pkt; struct pcap_pkthdr *h; pcap_t *pt = pcap_open_offline(pcap_in, ebuf); struct timeval beginning = { 0, 0 }; int avg_send_len = 0; if(pt) { struct packet *last = NULL; while(1) { struct packet *p; int rc = pcap_next_ex(pt, &h, (const u_char**)&pkt); if(rc <= 0) break; if (num_pcap_pkts == 0) { beginning.tv_sec = h->ts.tv_sec; beginning.tv_usec = h->ts.tv_usec; } p = (struct packet*)malloc(sizeof(struct packet)); if(p) { p->len = h->caplen; p->ticks_from_beginning = (((h->ts.tv_sec - beginning.tv_sec) * 1000000) + (h->ts.tv_usec - beginning.tv_usec)) * hz / 1000000; p->next = NULL; p->pkt = (char*)malloc(p->len); if(p->pkt == NULL) { printf("Not enough memory\n"); break; } else { memcpy(p->pkt, pkt, p->len); if(reforge_mac) memcpy(p->pkt, mac_address, 6); } if(last) { last->next = p; last = p; } else pkt_head = p, last = p; } else { printf("Not enough memory\n"); break; } if(verbose) printf("Read %d bytes packet from pcap file %s [%lu.%lu Secs = %lu ticks@%luhz from beginning]\n", p->len, pcap_in, h->ts.tv_sec - beginning.tv_sec, h->ts.tv_usec - beginning.tv_usec, (long unsigned int)p->ticks_from_beginning, (long unsigned int)hz); avg_send_len += p->len; num_pcap_pkts++; } /* while */ avg_send_len /= num_pcap_pkts; pcap_close(pt); printf("Read %d packets from pcap file %s\n", num_pcap_pkts, pcap_in); last->next = pkt_head; /* Loop */ send_len = avg_send_len; } else { printf("Unable to open file %s\n", pcap_in); pfring_close(pd); return(-1); } } else { struct packet *p = NULL, *last = NULL; for (i = 0; i < num_balanced_pkts; i++) { forge_udp_packet(buffer, i); p = (struct packet *) malloc(sizeof(struct packet)); if(p) { if (i == 0) pkt_head = p; p->len = send_len; p->ticks_from_beginning = 0; p->next = pkt_head; p->pkt = (char*)malloc(p->len); if (p->pkt == NULL) { printf("Not enough memory\n"); break; } memcpy(p->pkt, buffer, send_len); if (last != NULL) last->next = p; last = p; } } } if(gbit_s > 0) { /* computing max rate */ pps = ((gbit_s * 1000000000) / 8 /*byte*/) / (8 /*Preamble*/ + send_len + 4 /*CRC*/ + 12 /*IFG*/); td = (double)(hz / pps); tick_delta = (ticks)td; printf("Number of %d-byte Packet Per Second at %.2f Gbit/s: %.2f\n", (send_len + 4 /*CRC*/), gbit_s, pps); } if(bind_core >= 0) bind2core(bind_core); if(wait_for_packet && (cpu_percentage > 0)) { if(cpu_percentage > 99) cpu_percentage = 99; pfring_config(cpu_percentage); } if(!verbose) { signal(SIGALRM, my_sigalarm); alarm(1); } gettimeofday(&startTime, NULL); memcpy(&lastTime, &startTime, sizeof(startTime)); pfring_set_socket_mode(pd, send_only_mode); if(pfring_enable_ring(pd) != 0) { printf("Unable to enable ring :-(\n"); pfring_close(pd); return(-1); } use_zero_copy_tx = 0; if((!disable_zero_copy) && (pd->dna_get_num_tx_slots != NULL) && (pd->dna_get_next_free_tx_slot != NULL) && (pd->dna_copy_tx_packet_into_slot != NULL)) { tosend = pkt_head; num_tx_slots = pd->dna_get_num_tx_slots(pd); if(num_tx_slots > 0 && (((num_to_send > 0) && (num_to_send <= num_tx_slots)) || ( pcap_in && (num_pcap_pkts <= num_tx_slots) && (num_tx_slots % num_pcap_pkts == 0)) || (!pcap_in && (num_balanced_pkts <= num_tx_slots) && (num_tx_slots % num_balanced_pkts == 0)))) { int ret; u_int first_free_slot = pd->dna_get_next_free_tx_slot(pd); for(i=0; i<num_tx_slots; i++) { ret = pfring_copy_tx_packet_into_slot(pd, (first_free_slot+i)%num_tx_slots, tosend->pkt, tosend->len); if(ret < 0) break; tosend = tosend->next; } use_zero_copy_tx = 1; printf("Using zero-copy TX\n"); } else { printf("NOT using zero-copy: TX ring size (%u) is not a multiple of the number of unique packets to send (%u)\n", num_tx_slots, pcap_in ? num_pcap_pkts : num_balanced_pkts); } } else { if (!disable_zero_copy) printf("NOT using zero-copy: not supported by the driver\n"); } tosend = pkt_head; i = 0; if(gbit_s != 0) tick_start = getticks(); while((num_to_send == 0) || (i < num_to_send)) { int rc; redo: if (if_index != -1) rc = pfring_send_ifindex(pd, tosend->pkt, tosend->len, gbit_s < 0 ? 1 : 0 /* Don't flush (it does PF_RING automatically) */, if_index); else if(use_zero_copy_tx) /* We pre-filled the TX slots */ rc = pfring_send(pd, NULL, tosend->len, gbit_s < 0 ? 1 : 0 /* Don't flush (it does PF_RING automatically) */); else rc = pfring_send(pd, tosend->pkt, tosend->len, gbit_s < 0 ? 1 : 0 /* Don't flush (it does PF_RING automatically) */); if(verbose) printf("[%d] pfring_send(%d) returned %d\n", i, tosend->len, rc); if(rc == PF_RING_ERROR_INVALID_ARGUMENT) { printf("Attempting to send invalid packet [len: %u][MTU: %u]%s\n", tosend->len, pd->mtu_len, if_index != -1 ? " or using a wrong interface id" : ""); } else if(rc < 0) { /* Not enough space in buffer */ if(!active_poll) { #if 1 usleep(1); #else if(bind_core >= 0) usleep(1); else pfring_poll(pd, 0); //sched_yield(); #endif } goto redo; } num_pkt_good_sent++; num_bytes_good_sent += tosend->len + 24 /* 8 Preamble + 4 CRC + 12 IFG */; tosend = tosend->next; if (use_zero_copy_tx && (num_pkt_good_sent == num_tx_slots)) tosend = pkt_head; if(gbit_s > 0) { /* rate set */ while((getticks() - tick_start) < (num_pkt_good_sent * tick_delta)) ; } else if (gbit_s < 0) { /* real pcap rate */ if (tosend->ticks_from_beginning == 0) tick_start = getticks(); /* first packet, resetting time */ while((getticks() - tick_start) < tosend->ticks_from_beginning) ; } if(num_to_send > 0) i++; } /* for */ print_stats(0); pfring_close(pd); return(0); }
long stream_pfring_open(struct stream** stptr, const struct ether_addr* addr, const char* iface, size_t buffer_size){ int ret = 0; assert(stptr); /* validate arguments */ if ( !(addr && iface) ){ return EINVAL; } /* get MTU for interface */ const int if_mtu = iface_mtu(iface); if ( if_mtu < 0 ){ return errno; } pfring_config(99); /* open pfring */ char* derp = strdup(iface); pfring* pd = pfring_open(derp, 1, 9000, 0); if ( !pd ){ return errno; } pfring_set_application_name(pd, "libcap_utils"); uint32_t version; pfring_version(pd, &version); fprintf(stderr, "Using PF_RING v.%d.%d.%d\n", (version & 0xFFFF0000) >> 16, (version & 0x0000FF00) >> 8, version & 0x000000FF); if((ret = pfring_set_direction(pd, rx_and_tx_direction)) != 0) fprintf(stderr, "pfring_set_direction returned %d (perhaps you use a direction other than rx only with DNA ?)\n", ret); if((ret = pfring_set_socket_mode(pd, recv_only_mode)) != 0) fprintf(stderr, "pfring_set_socket_mode returned [rc=%d]\n", ret); char bpfFilter[] = "ether proto 0x810"; ret = pfring_set_bpf_filter(pd, bpfFilter); if ( ret != 0 ) { fprintf(stderr, "pfring_set_bpf_filter(%s) returned %d\n", bpfFilter, ret); } else { fprintf(stderr, "Successfully set BPF filter '%s'\n", bpfFilter); } /* default buffer_size of 25*MTU */ if ( buffer_size == 0 ){ buffer_size = 250 * if_mtu; } /* ensure buffer is a multiple of MTU and can hold at least one frame */ if ( buffer_size < if_mtu ){ return ERROR_BUFFER_LENGTH; } else if ( buffer_size % if_mtu != 0 ){ return ERROR_BUFFER_MULTIPLE; } /* additional memory for the frame pointers */ size_t frames = buffer_size / if_mtu; size_t frame_offset = sizeof(char*) * frames; buffer_size += frame_offset; /* Initialize the structure */ if ( (ret = stream_alloc(stptr, PROTOCOL_ETHERNET_MULTICAST, sizeof(struct stream_pfring), buffer_size) != 0) ){ return ret; } struct stream_pfring* st = (struct stream_pfring*)*stptr; st->pd = pd; st->num_address = 0; st->if_mtu = if_mtu; memset(st->seqnum, 0, sizeof(long unsigned int) * MAX_ADDRESS); if (pfring_enable_ring(pd) != 0) { fprintf(stderr, "Unable to enable ring :-(\n"); pfring_close(pd); return(-1); } /* setup buffer pointers (see brief overview at struct declaration) */ st->num_frames = frames; st->num_packets = 0; st->read_ptr = NULL; st->base.readPos = 0; st->base.writePos = 0; for ( unsigned int i = 0; i < frames; i++ ){ st->frame[i] = st->base.buffer + frame_offset + i * if_mtu; } /* add membership to group */ if ( (ret=stream_pfring_add(&st->base, addr)) != 0 ){ return ret; } /* if ( (ret=stream_pfring_init(stptr, addr, iface, ETH_P_ALL, buffer_size)) != 0 ){ return ret; } */ st->base.type = PROTOCOL_ETHERNET_MULTICAST; st->base.FH.comment_size = 0; st->base.comment = NULL; /* callbacks */ st->base.fill_buffer = NULL; st->base.destroy = (destroy_callback)destroy; st->base.write = NULL; st->base.read = (read_callback)stream_pfring_read; return 0; }
int main(int argc, char* argv[]) { pfring *a_ring, *b_ring; char *a_dev = NULL, *b_dev = NULL, c; u_int8_t verbose = 0, use_pfring_send = 0; int a_ifindex, b_ifindex; while((c = getopt(argc,argv, "ha:b:c:fvp")) != -1) { switch(c) { case 'h': printHelp(); return 0; break; case 'a': a_dev = strdup(optarg); break; case 'b': b_dev = strdup(optarg); break; case 'p': use_pfring_send = 1; break; case 'v': verbose = 1; break; } } if ((!a_dev) || (!b_dev)) { printf("You must specify two devices!\n"); return -1; } if(strcmp(a_dev, b_dev) == 0) { printf("Bridge devices must be different!\n"); return -1; } /* open devices */ if((a_ring = pfring_open(a_dev, 1500, PF_RING_PROMISC|PF_RING_LONG_HEADER)) == NULL) { printf("pfring_open error for %s [%s]\n", a_dev, strerror(errno)); return(-1); } else { pfring_set_application_name(a_ring, "pfbridge-a"); pfring_set_direction(a_ring, rx_and_tx_direction); pfring_get_bound_device_ifindex(a_ring, &a_ifindex); } if((b_ring = pfring_open(b_dev, 1500, PF_RING_PROMISC|PF_RING_LONG_HEADER)) == NULL) { printf("pfring_open error for %s [%s]\n", b_dev, strerror(errno)); pfring_close(a_ring); return(-1); } else { pfring_set_application_name(b_ring, "pfbridge-b"); pfring_set_direction(b_ring, rx_and_tx_direction); pfring_get_bound_device_ifindex(b_ring, &b_ifindex); } /* Enable rings */ pfring_enable_ring(a_ring); if(use_pfring_send) pfring_enable_ring(b_ring); else pfring_close(b_ring); signal(SIGALRM, my_sigalarm); alarm(1); while(1) { u_char *buffer; struct pfring_pkthdr hdr; if(pfring_recv(a_ring, &buffer, 0, &hdr, 1) > 0) { int rc; if(use_pfring_send) { rc = pfring_send(b_ring, (char*)buffer, hdr.caplen, 1); if(rc < 0) printf("pfring_send_last_rx_packet() error %d\n", rc); else if(verbose) printf("Forwarded %d bytes packet\n", hdr.len); } else { rc = pfring_send_last_rx_packet(a_ring, b_ifindex); if(rc < 0) printf("pfring_send_last_rx_packet() error %d\n", rc); else if(verbose) printf("Forwarded %d bytes packet\n", hdr.len); } if(rc >= 0) num_sent++; } } pfring_close(a_ring); if(use_pfring_send) pfring_close(b_ring); return(0); }
/** * \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); }
int main(int argc, char* argv[]) { pfring *a_ring, *b_ring; char *a_dev = NULL, *b_dev = NULL, c; u_int8_t verbose = 0, use_pfring_send = 0; int a_ifindex, b_ifindex; int bind_core = -1; u_int16_t watermark = 1; while((c = getopt(argc,argv, "ha:b:c:fvpg:w:")) != -1) { switch(c) { case 'h': printHelp(); return 0; break; case 'a': a_dev = strdup(optarg); break; case 'b': b_dev = strdup(optarg); break; case 'p': use_pfring_send = 1; break; case 'v': verbose = 1; break; case 'g': bind_core = atoi(optarg); break; case 'w': watermark = atoi(optarg); break; } } if ((!a_dev) || (!b_dev)) { printf("You must specify two devices!\n"); return -1; } if(strcmp(a_dev, b_dev) == 0) { printf("Bridge devices must be different!\n"); return -1; } /* Device A */ if((a_ring = pfring_open(a_dev, MAX_PKT_LEN, PF_RING_PROMISC | PF_RING_LONG_HEADER | (use_pfring_send ? 0 : PF_RING_RX_PACKET_BOUNCE)) ) == NULL) { printf("pfring_open error for %s [%s]\n", a_dev, strerror(errno)); return(-1); } pfring_set_application_name(a_ring, "pfbridge-a"); pfring_set_direction(a_ring, rx_only_direction); pfring_set_socket_mode(a_ring, recv_only_mode); pfring_set_poll_watermark(a_ring, watermark); pfring_get_bound_device_ifindex(a_ring, &a_ifindex); /* Device B */ if((b_ring = pfring_open(b_dev, MAX_PKT_LEN, PF_RING_PROMISC|PF_RING_LONG_HEADER)) == NULL) { printf("pfring_open error for %s [%s]\n", b_dev, strerror(errno)); pfring_close(a_ring); return(-1); } pfring_set_application_name(b_ring, "pfbridge-b"); pfring_set_socket_mode(b_ring, send_only_mode); pfring_get_bound_device_ifindex(b_ring, &b_ifindex); /* Enable Sockets */ if (pfring_enable_ring(a_ring) != 0) { printf("Unable enabling ring 'a' :-(\n"); pfring_close(a_ring); pfring_close(b_ring); return(-1); } if(use_pfring_send) { if (pfring_enable_ring(b_ring)) { printf("Unable enabling ring 'b' :-(\n"); pfring_close(a_ring); pfring_close(b_ring); return(-1); } } else { pfring_close(b_ring); } signal(SIGALRM, my_sigalarm); alarm(1); if(bind_core >= 0) bind2core(bind_core); while(1) { u_char *buffer; struct pfring_pkthdr hdr; if(pfring_recv(a_ring, &buffer, 0, &hdr, 1) > 0) { int rc; if(use_pfring_send) { rc = pfring_send(b_ring, (char *) buffer, hdr.caplen, 1); if(rc < 0) printf("pfring_send(caplen=%u <= mtu=%u?) error %d\n", hdr.caplen, b_ring->mtu_len, rc); else if(verbose) printf("Forwarded %d bytes packet\n", hdr.len); } else { rc = pfring_send_last_rx_packet(a_ring, b_ifindex); if(rc < 0) printf("pfring_send_last_rx_packet() error %d\n", rc); else if(verbose) printf("Forwarded %d bytes packet\n", hdr.len); } if(rc >= 0) num_sent++; } } pfring_close(a_ring); if(use_pfring_send) pfring_close(b_ring); return(0); }
int main(int argc, char* argv[]) { char c, *pcap_in = NULL, mac_address[6]; int promisc, i, verbose = 0, active_poll = 0, reforge_mac = 0; u_int mac_a, mac_b, mac_c, mac_d, mac_e, mac_f; char buffer[1500]; int send_len = 60; u_int32_t num = 1; int bind_core = -1; u_int16_t cpu_percentage = 0; double gbit_s = 0, td, pps; ticks tick_start = 0, tick_delta = 0; ticks hz = 0; struct packet *tosend; while((c = getopt(argc,argv,"hi:n:g:l:af:r:vm:" #if 0 "b:" #endif )) != -1) { switch(c) { case 'h': printHelp(); break; case 'i': in_dev = strdup(optarg); break; case 'f': pcap_in = strdup(optarg); break; case 'n': num = atoi(optarg); break; case 'g': bind_core = atoi(optarg); break; case 'l': send_len = atoi(optarg); break; case 'v': verbose = 1; break; case 'a': active_poll = 1; break; case 'r': sscanf(optarg, "%lf", &gbit_s); break; #if 0 case 'b': cpu_percentage = atoi(optarg); #endif break; case 'm': if(sscanf(optarg, "%02X:%02X:%02X:%02X:%02X:%02X", &mac_a, &mac_b, &mac_c, &mac_d, &mac_e, &mac_f) != 6) { printf("Invalid MAC address format (XX:XX:XX:XX:XX:XX)\n"); return(0); } else { reforge_mac = 1; mac_address[0] = mac_a, mac_address[1] = mac_b, mac_address[2] = mac_c; mac_address[3] = mac_d, mac_address[4] = mac_e, mac_address[5] = mac_f; } break; } } if(in_dev == NULL) printHelp(); printf("Sending packets on %s\n", in_dev); /* hardcode: promisc=1, to_ms=500 */ promisc = 1; pd = pfring_open(in_dev, promisc, 1500, 0); if(pd == NULL) { printf("pfring_open %s error\n", in_dev); return(-1); } else { u_int32_t version; pfring_set_application_name(pd, "pfdnasend"); pfring_version(pd, &version); printf("Using PF_RING v.%d.%d.%d\n", (version & 0xFFFF0000) >> 16, (version & 0x0000FF00) >> 8, version & 0x000000FF); } signal(SIGINT, sigproc); signal(SIGTERM, sigproc); signal(SIGINT, sigproc); if(send_len < 60) send_len = 60; if(gbit_s > 0) { /* cumputing usleep delay */ tick_start = getticks(); usleep(1); tick_delta = getticks() - tick_start; /* cumputing CPU freq */ tick_start = getticks(); usleep(1001); hz = (getticks() - tick_start - tick_delta) * 1000 /*kHz -> Hz*/; printf("Estimated CPU freq: %llu Hz\n", hz); /* computing max rate */ pps = ((gbit_s * 1000000000) / 8 /*byte*/) / (8 /*Preamble*/ + send_len + 4 /*CRC*/ + 12 /*IFG*/); td = (double)(hz / pps); tick_delta = (ticks)td; printf("Number of %d-byte Packet Per Second at %.2f Gbit/s: %.2f\n", (send_len + 4 /*CRC*/), gbit_s, pps); } if(pcap_in) { char ebuf[256]; u_char *pkt; struct pcap_pkthdr *h; pcap_t *pt = pcap_open_offline(pcap_in, ebuf); u_int num_pcap_pkts = 0; if(pt) { struct packet *last = NULL; while(1) { struct packet *p; int rc = pcap_next_ex(pt, &h, (const u_char**)&pkt); if(rc <= 0) break; p = (struct packet*)malloc(sizeof(struct packet)); if(p) { p->len = h->caplen; p->next = NULL; p->pkt = (char*)malloc(p->len); if(p->pkt == NULL) { printf("Not enough memory\n"); break; } else { memcpy(p->pkt, pkt, p->len); if(reforge_mac) memcpy(p->pkt, mac_address, 6); } if(last) { last->next = p; last = p; } else pkt_head = p, last = p; } else { printf("Not enough memory\n"); break; } if(verbose) printf("Read %d bytes packet from pcap file %s\n", p->len, pcap_in); num_pcap_pkts++; } /* while */ pcap_close(pt); printf("Read %d packets from pcap file %s\n", num_pcap_pkts, pcap_in); last->next = pkt_head; /* Loop */ num *= num_pcap_pkts; } else { printf("Unable to open file %s\n", pcap_in); pfring_close(pd); return(-1); } } else { struct packet *p; for(i=0; i<send_len; i++) buffer[i] = i; if(reforge_mac) memcpy(buffer, mac_address, 6); p = (struct packet*)malloc(sizeof(struct packet)); if(p) { p->len = send_len; p->next = p; /* Loop */ p->pkt = (char*)malloc(p->len); memcpy(p->pkt, buffer, send_len); pkt_head = p; } } if(bind_core >= 0) bind2core(bind_core); if(wait_for_packet && (cpu_percentage > 0)) { if(cpu_percentage > 99) cpu_percentage = 99; pfring_config(cpu_percentage); } if(!verbose) { signal(SIGALRM, my_sigalarm); alarm(1); } gettimeofday(&startTime, NULL); memcpy(&lastTime, &startTime, sizeof(startTime)); if(gbit_s > 0) tick_start = getticks(); tosend = pkt_head; i = 0; pfring_set_direction(pd, tx_only_direction); if(pfring_enable_ring(pd) != 0) { printf("Unable to enable ring :-(\n"); pfring_close(pd); return(-1); } while(!num || i < num) { int rc; redo: rc = pfring_send(pd, tosend->pkt, tosend->len, 0 /* Don't flush (it does PF_RING automatically) */); if(verbose) printf("[%d] pfring_send(%d) returned %d\n", i, tosend->len, rc); if(rc == -1) { /* Not enough space in buffer */ if(gbit_s == 0) { if(!active_poll) { if(bind_core >= 0) usleep(1); else pfring_poll(pd, 0); } } else { /* Just waste some time */ while((getticks() - tick_start) < (num_pkt_good_sent * tick_delta)) ; } goto redo; } else num_pkt_good_sent++, num_bytes_good_sent += tosend->len+24 /* 8 Preamble + 4 CRC + 12 IFG */, tosend = tosend->next; if(num > 0) i++; } /* for */ print_stats(0); pfring_close(pd); 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; }