Ejemplo n.º 1
0
/**
 * 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());
	}
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
/**
 * 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);
	}
}