/** * Print to console all available DPDK ports. Used by the -l switch */ void listDpdkPorts() { CoreMask coreMaskToUse = getCoreMaskForAllMachineCores(); // initialize DPDK if (!DpdkDeviceList::initDpdk(coreMaskToUse, DEFAULT_MBUF_POOL_SIZE)) { EXIT_WITH_ERROR("couldn't initialize DPDK"); } printf("DPDK port list:\n"); // go over all available DPDK devices and print info for each one vector<DpdkDevice*> deviceList = DpdkDeviceList::getInstance().getDpdkDeviceList(); for (vector<DpdkDevice*>::iterator iter = deviceList.begin(); iter != deviceList.end(); iter++) { DpdkDevice* dev = *iter; printf(" Port #%d: MAC address='%s'; PCI address='%s'; PMD='%s'\n", dev->getDeviceId(), dev->getMacAddress().toString().c_str(), dev->getPciAddress().toString().c_str(), dev->getPMDName().c_str()); } }
bool DpdkDeviceList::initDpdkDevices(uint32_t mBufPoolSizePerDevice) { if (!m_IsDpdkInitialized) { LOG_ERROR("DPDK is not initialized!! Please call DpdkDeviceList::initDpdk(coreMask, mBufPoolSizePerDevice) before start using DPDK devices"); return false; } if (m_IsInitialized) return true; int numOfPorts = rte_eth_dev_count(); if (numOfPorts <= 0) { LOG_ERROR("Zero DPDK ports are initialized. Something went wrong while initializing DPDK"); return false; } LOG_DEBUG("Found %d DPDK ports. Constructing DpdkDevice for each one", numOfPorts); // Initialize a DpdkDevice per port for (int i = 0; i < numOfPorts; i++) { DpdkDevice* newDevice = new DpdkDevice(i, mBufPoolSizePerDevice); LOG_DEBUG("DpdkDevice #%d: Name='%s', PCI-slot='%s', PMD='%s', MAC Addr='%s'", i, newDevice->getDeviceName().c_str(), newDevice->getPciAddress().toString().c_str(), newDevice->getPMDName().c_str(), newDevice->getMacAddress().toString().c_str()); m_DpdkDeviceList.push_back(newDevice); } m_IsInitialized = true; return true; }
/** * main method of the application. Responsible for parsing user args, preparing worker thread configuration, creating the worker threads and activate them. * At program termination worker threads are stopped, statistics are collected from them and printed to console */ int main(int argc, char* argv[]) { std::vector<int> dpdkPortVec; bool writePacketsToDisk = false; string packetFilePath = ""; CoreMask coreMaskToUse = getCoreMaskForAllMachineCores(); int sendPacketsToPort = -1; int optionIndex = 0; char opt = 0; uint32_t mBufPoolSize = DEFAULT_MBUF_POOL_SIZE; IPv4Address srcIPToMatch = IPv4Address::Zero; IPv4Address dstIPToMatch = IPv4Address::Zero; uint16_t srcPortToMatch = 0; uint16_t dstPortToMatch = 0; ProtocolType protocolToMatch = Unknown; while((opt = getopt_long (argc, argv, "d:c:s:f:m:i:I:p:P:r:hl", FilterTrafficOptions, &optionIndex)) != -1) { switch (opt) { case 0: { break; } case 'd': { string portListAsString = string(optarg); stringstream stream(portListAsString); string portAsString; int port; // break comma-separated string into string list while(getline(stream, portAsString, ',')) { char c; std::stringstream stream2(portAsString); stream2 >> port; if (stream2.fail() || stream2.get(c)) { // not an integer EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK ports list is invalid"); } dpdkPortVec.push_back(port); } // verify list is not empty if (dpdkPortVec.empty()) { EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK ports list is empty"); } break; } case 's': { sendPacketsToPort = atoi(optarg); break; } case 'c': { coreMaskToUse = atoi(optarg); break; } case 'f': { packetFilePath = string(optarg); writePacketsToDisk = true; if (packetFilePath.empty()) { EXIT_WITH_ERROR_AND_PRINT_USAGE("Filename to write packets is empty"); } break; } case 'm': { mBufPoolSize = atoi(optarg); break; } case 'i': { srcIPToMatch = IPv4Address(optarg); if (!srcIPToMatch.isValid()) { EXIT_WITH_ERROR_AND_PRINT_USAGE("Source IP to match isn't a valid IP address"); } break; } case 'I': { dstIPToMatch = IPv4Address(optarg); if (!dstIPToMatch.isValid()) { EXIT_WITH_ERROR_AND_PRINT_USAGE("Destination IP to match isn't a valid IP address"); } break; } case 'p': { srcPortToMatch = atoi(optarg); if (srcPortToMatch <= 0) { EXIT_WITH_ERROR_AND_PRINT_USAGE("Source port to match isn't a valid TCP/UDP port"); } break; } case 'P': { dstPortToMatch = atoi(optarg); if (dstPortToMatch <= 0) { EXIT_WITH_ERROR_AND_PRINT_USAGE("Destination port to match isn't a valid TCP/UDP port"); } break; } case 'r': { string protocol = string(optarg); if (protocol == "TCP") protocolToMatch = TCP; else if (protocol == "UDP") protocolToMatch = UDP; else { EXIT_WITH_ERROR_AND_PRINT_USAGE("Protocol to match isn't TCP or UDP"); } break; } case 'h': { printUsage(); exit(0); } case 'l': { listDpdkPorts(); exit(0); } default: { printUsage(); exit(0); } } } // verify list is not empty if (dpdkPortVec.empty()) { EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK ports list is empty. Please use the -d switch"); } // initialize DPDK if (!DpdkDeviceList::initDpdk(coreMaskToUse, mBufPoolSize)) { EXIT_WITH_ERROR("couldn't initialize DPDK"); } // removing DPDK master core from core mask because DPDK worker threads cannot run on master core coreMaskToUse = coreMaskToUse & ~(DpdkDeviceList::getInstance().getDpdkMasterCore().Mask); // extract core vector from core mask vector<SystemCore> coresToUse; createCoreVectorFromCoreMask(coreMaskToUse, coresToUse); // collect the list of DPDK devices vector<DpdkDevice*> dpdkDevicesToUse; for (vector<int>::iterator iter = dpdkPortVec.begin(); iter != dpdkPortVec.end(); iter++) { DpdkDevice* dev = DpdkDeviceList::getInstance().getDeviceByPort(*iter); if (dev == NULL) { EXIT_WITH_ERROR("DPDK device for port %d doesn't exist", *iter); } dpdkDevicesToUse.push_back(dev); } // get DPDK device to send packets to (or NULL if doesn't exist) DpdkDevice* sendPacketsTo = DpdkDeviceList::getInstance().getDeviceByPort(sendPacketsToPort); if (sendPacketsTo != NULL && !sendPacketsTo->open()) { EXIT_WITH_ERROR("Could not open port#%d for sending matched packets", sendPacketsToPort); } // go over all devices and open them for (vector<DpdkDevice*>::iterator iter = dpdkDevicesToUse.begin(); iter != dpdkDevicesToUse.end(); iter++) { if (!(*iter)->openMultiQueues((*iter)->getTotalNumOfRxQueues(), (*iter)->getTotalNumOfTxQueues())) { EXIT_WITH_ERROR("Couldn't open DPDK device #%d, PMD '%s'", (*iter)->getDeviceId(), (*iter)->getPMDName().c_str()); } } // prepare configuration for every core AppWorkerConfig workerConfigArr[coresToUse.size()]; prepareCoreConfiguration(dpdkDevicesToUse, coresToUse, writePacketsToDisk, packetFilePath, sendPacketsTo, workerConfigArr, coresToUse.size()); PacketMatchingEngine matchingEngine(srcIPToMatch, dstIPToMatch, srcPortToMatch, dstPortToMatch, protocolToMatch); // create worker thread for every core vector<DpdkWorkerThread*> workerThreadVec; int i = 0; for (vector<SystemCore>::iterator iter = coresToUse.begin(); iter != coresToUse.end(); iter++) { AppWorkerThread* newWorker = new AppWorkerThread(workerConfigArr[i], matchingEngine); workerThreadVec.push_back(newWorker); i++; } // start all worker threads if (!DpdkDeviceList::getInstance().startDpdkWorkerThreads(coreMaskToUse, workerThreadVec)) { EXIT_WITH_ERROR("Couldn't start worker threads"); } // register the on app close event to print summary stats on app termination FiltetTrafficArgs args; args.workerThreadsVector = &workerThreadVec; ApplicationEventHandler::getInstance().onApplicationInterrupted(onApplicationInterrupted, &args); // infinite loop (until program is terminated) while (!args.shouldStop) { sleep(5); } }