Exemple #1
0
static int
clean_suite(void)
{
	ofp_arp_term_local();
	ofp_term_local();
	ofp_term_global();
	odp_term_local();
	odp_term_global();
	return 0;
}
Exemple #2
0
/**
 * main() Application entry point
 *
 * This is the main function of the FPM application, it's a minimalistic
 * example, see 'usage' function for available arguments and usage.
 *
 * Using the number of available cores as input, this example sets up
 * ODP dispatcher threads executing OFP VLAN processesing and starts
 * a CLI function on a managment core.
 *
 * @param argc int
 * @param argv[] char*
 * @return int
 *
 */
int main(int argc, char *argv[])
{
	odph_linux_pthread_t thread_tbl[MAX_WORKERS];
	appl_args_t params;
	int core_count, num_workers, ret_val;
	odp_cpumask_t cpumask;
	char cpumaskstr[64];
	odph_linux_thr_params_t thr_params;
	odp_instance_t instance;

	/* Parse and store the application arguments */
	if (parse_args(argc, argv, &params) != EXIT_SUCCESS)
		return EXIT_FAILURE;

	if (ofp_sigactions_set(ofp_sig_func_stop)) {
		printf("Error: failed to set signal actions.\n");
		return EXIT_FAILURE;
	}

	/*
	 * Before any ODP API functions can be called, we must first init the ODP
	 * globals, e.g. availale accelerators or software implementations for
	 * shared memory, threads, pool, qeueus, sheduler, pktio, timer, crypto
	 * and classification.
	 */
	if (odp_init_global(&instance, NULL, NULL)) {
		printf("Error: ODP global init failed.\n");
		return EXIT_FAILURE;
	}

	/*
	 * When the gloabel ODP level init has been done, we can now issue a
	 * local init per thread. This must also be done before any other ODP API
	 * calls may be made. Local inits are made here for shared memory,
	 * threads, pktio and scheduler.
	 */
	if (odp_init_local(instance, ODP_THREAD_CONTROL) != 0) {
		printf("Error: ODP local init failed.\n");
		odp_term_global(instance);
		return EXIT_FAILURE;
	}

	/* Print both system and application information */
	print_info(NO_PATH(argv[0]), &params);

	/*
	 * Get the number of cores available to ODP, one run-to-completion thread
	 * will be created per core.
	 */
	core_count = odp_cpu_count();
	num_workers = core_count;

	if (params.core_count)
		num_workers = params.core_count;
	if (num_workers > MAX_WORKERS)
		num_workers = MAX_WORKERS;

	/*
	 * This example assumes that core #0 runs Linux kernel background tasks.
	 * By default, cores #1 and beyond will be populated with a OFP
	 * processing thread each.
	 */
	memset(&app_init_params, 0, sizeof(app_init_params));

	app_init_params.linux_core_id = 0;

	if (core_count > 1)
		num_workers--;

	/*
	 * Initializes cpumask with CPUs available for worker threads.
	 * Sets up to 'num' CPUs and returns the count actually set.
	 * Use zero for all available CPUs.
	 */
	num_workers = odp_cpumask_default_worker(&cpumask, num_workers);
	if (odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr)) < 0) {
		printf("Error: Too small buffer provided to "
			"odp_cpumask_to_str\n");
		odp_term_local();
		odp_term_global(instance);
		return EXIT_FAILURE;
	}

	printf("Num worker threads: %i\n", num_workers);
	printf("first CPU:          %i\n", odp_cpumask_first(&cpumask));
	printf("cpu mask:           %s\n", cpumaskstr);

	app_init_params.if_count = params.if_count;
	app_init_params.if_names = params.if_names;
	app_init_params.pkt_hook[OFP_HOOK_LOCAL] = fastpath_local_hook;

	/*
	 * Now that ODP has been initalized, we can initialize OFP. This will
	 * open a pktio instance for each interface supplied as argument by the
	 * user.
	 *
	 * General configuration will be to pktio and schedluer queues here in
	 * addition will fast path interface configuration.
	 */
	if (ofp_init_global(instance, &app_init_params) != 0) {
		printf("Error: OFP global init failed.\n");
		ofp_term_global();
		odp_term_local();
		odp_term_global(instance);
		return EXIT_FAILURE;
	}

	if (ofp_init_local() != 0) {
		printf("Error: OFP local init failed.\n");
		ofp_term_local();
		ofp_term_global();
		odp_term_local();
		odp_term_global(instance);
		return EXIT_FAILURE;
	}

	/*
	 * Create and launch dataplane dispatcher worker threads to be placed
	 * according to the cpumask, thread_tbl will be populated with the
	 * created pthread IDs.
	 *
	 * In this case, all threads will run the default_event_dispatcher
	 * function with ofp_eth_vlan_processing as argument.
	 *
	 * If different dispatchers should run, or the same be run with differnt
	 * input arguments, the cpumask is used to control this.
	 */
	memset(thread_tbl, 0, sizeof(thread_tbl));
	thr_params.start = default_event_dispatcher;
	thr_params.arg = ofp_eth_vlan_processing;
	thr_params.thr_type = ODP_THREAD_WORKER;
	thr_params.instance = instance;
	ret_val = odph_linux_pthread_create(thread_tbl,
					    &cpumask,
					    &thr_params);
	if (ret_val != num_workers) {
		OFP_ERR("Error: Failed to create worker threads, "
			"expected %d, got %d",
			num_workers, ret_val);
		ofp_stop_processing();
		odph_linux_pthread_join(thread_tbl, num_workers);
		ofp_term_local();
		ofp_term_global();
		odp_term_local();
		odp_term_global(instance);
		return EXIT_FAILURE;
	}

	/*
	 * Now when the ODP dispatcher threads are running, further applications
	 * can be launched, in this case, we will start the OFP CLI thread on
	 * the management core, i.e. not competing for cpu cycles with the
	 * worker threads
	 */
	if (ofp_start_cli_thread(instance, app_init_params.linux_core_id,
		params.conf_file) < 0) {
		OFP_ERR("Error: Failed to init CLI thread");
		ofp_stop_processing();
		odph_linux_pthread_join(thread_tbl, num_workers);
		ofp_term_local();
		ofp_term_global();
		odp_term_local();
		odp_term_global(instance);
		return EXIT_FAILURE;
	}

	/*
	 * If we choose to check performance, a performance monitoring client
	 * will be started on the management core. Once every second it will
	 * read the statistics from the workers from a shared memory region.
	 * Using this has negligible performance impact (<<0.01%).
	 */
	if (params.perf_stat) {
		if (start_performance(instance,
			app_init_params.linux_core_id) <= 0) {
			OFP_ERR("Error: Failed to init performance monitor");
			ofp_stop_processing();
			odph_linux_pthread_join(thread_tbl, num_workers);
			ofp_term_local();
			ofp_term_global();
			odp_term_local();
			odp_term_global(instance);
			return EXIT_FAILURE;
		}
	}

	/*
	 * Wait here until all worker threads have terminated, then free up all
	 * resources allocated by odp_init_global().
	 */
	odph_linux_pthread_join(thread_tbl, num_workers);

	if (ofp_term_local() < 0)
		printf("Error: ofp_term_local failed\n");

	if (ofp_term_global() < 0)
		printf("Error: ofp_term_global failed\n");

	if (odp_term_local() < 0)
		printf("Error: odp_term_local failed\n");

	if (odp_term_global(instance) < 0)
		printf("Error: odp_term_global failed\n");

	printf("FPM End Main()\n");

	return EXIT_SUCCESS;
}
static int ofp_lib_start(void)
{
	ofp_init_global_t app_init_params;

	odph_linux_pthread_t thread_tbl[32];
	int ret_val, num_workers = 1;
	odp_cpumask_t cpumask;
	char cpumaskstr[64];

	if (ofp_init_global_called)
		return EXIT_FAILURE;

	/*
	 * Before any ODP API functions can be called, we must first init the ODP
	 * globals, e.g. availale accelerators or software implementations for
	 * shared memory, threads, pool, qeueus, sheduler, pktio, timer, crypto
	 * and classification.
	 */
	if (odp_init_global(NULL, NULL)) {
		OFP_ERR("ODP global init failed.");
		return EXIT_FAILURE;
	}

	/*
	 * When the gloabel ODP level init has been done, we can now issue a
	 * local init per thread. This must also be done before any other ODP API
	 * calls may be made. Local inits are made here for shared memory,
	 * threads, pktio and scheduler.
	 */
	if (odp_init_local(ODP_THREAD_CONTROL) != 0) {
		OFP_ERR("ODP local init failed.");
		odp_term_global();
		return EXIT_FAILURE;
	}

	/*
	 * Initializes cpumask with CPUs available for worker threads.
	 * Sets up to 'num' CPUs and returns the count actually set.
	 * Use zero for all available CPUs.
	 */
	num_workers = odp_cpumask_default_worker(&cpumask, num_workers);
	if (odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr)) < 0) {
		OFP_ERR("Error: Too small buffer provided to "
			"odp_cpumask_to_str");
		odp_term_local();
		odp_term_global();
		return EXIT_FAILURE;
	}

	printf("Num worker threads: %i\n", num_workers);
	printf("first CPU: %i\n", odp_cpumask_first(&cpumask));
	printf("cpu mask:  %s\n", cpumaskstr);

	/*
	 * Now that ODP has been initalized, we can initialize OFP. This will
	 * open a pktio instance for each interface supplied as argument by the
	 * user.
	 *
	 * General configuration will be to pktio and schedluer queues here in
	 * addition will fast path interface configuration.
	 */
	memset(&app_init_params, 0, sizeof(app_init_params));
	if (ofp_init_global(&app_init_params) != 0) {
		OFP_ERR("OFP global init failed.");
		ofp_term_global();
		odp_term_local();
		odp_term_global();
		return EXIT_FAILURE;
	}

	if (ofp_init_local() != 0) {
		OFP_ERR("Error: OFP local init failed.");
		ofp_term_local();
		ofp_term_global();
		odp_term_local();
		odp_term_global();
		return EXIT_FAILURE;
	}


	/*
	 * Create and launch dataplane dispatcher worker threads to be placed
	 * according to the cpumask, thread_tbl will be populated with the
	 * created pthread IDs.
	 *
	 * In this case, all threads will run the default_event_dispatcher
	 * function with ofp_eth_vlan_processing as argument.
	 *
	 * If different dispatchers should run, or the same be run with differnt
	 * input arguments, the cpumask is used to control this.
	 */
	memset(thread_tbl, 0, sizeof(thread_tbl));
	ret_val = ofp_linux_pthread_create(thread_tbl,
			&cpumask,
			default_event_dispatcher,
			ofp_eth_vlan_processing,
			ODP_THREAD_CONTROL);

	if (ret_val != num_workers) {
		OFP_ERR("Error: Failed to create worker threads, "
			"expected %d, got %d",
			num_workers, ret_val);
		ofp_stop_processing();
		odph_linux_pthread_join(thread_tbl, num_workers);
		ofp_term_local();
		ofp_term_global();
		odp_term_local();
		odp_term_global();
		return EXIT_FAILURE;
	}

	ofp_ifconfig();

	return EXIT_SUCCESS;
}