diff mbox

[PATCHv5] example:generator:option to supply core mask

Message ID 1439209666-4534-1-git-send-email-balakrishna.garapati@linaro.org
State New
Headers show

Commit Message

Balakrishna Garapati Aug. 10, 2015, 12:27 p.m. UTC
Signed-off-by: Balakrishna.Garapati <balakrishna.garapati@linaro.org>
---
 Updated core mask usage, fixed the cpu limit check with core mask.
 example/generator/odp_generator.c | 65 +++++++++++++++++++++++++++------------
 1 file changed, 45 insertions(+), 20 deletions(-)

Comments

Stuart Haslam Aug. 18, 2015, 2:45 p.m. UTC | #1
On Mon, Aug 10, 2015 at 02:27:46PM +0200, Balakrishna.Garapati wrote:
> Signed-off-by: Balakrishna.Garapati <balakrishna.garapati@linaro.org>
> ---
>  Updated core mask usage, fixed the cpu limit check with core mask.
>  example/generator/odp_generator.c | 65 +++++++++++++++++++++++++++------------
>  1 file changed, 45 insertions(+), 20 deletions(-)
> 
> diff --git a/example/generator/odp_generator.c b/example/generator/odp_generator.c
> index bdee222..9408db1 100644
> --- a/example/generator/odp_generator.c
> +++ b/example/generator/odp_generator.c
> @@ -43,6 +43,7 @@
>   */
>  typedef struct {
>  	int cpu_count;		/**< system CPU count */
> +	const char *mask;	/**< s/core mask/CPU mask */

In my previous comment I was asking to replace the text "core mask" with
"CPU mask".

>  	int if_count;		/**< Number of interfaces to be used */
>  	char **if_names;	/**< Array of pointers to interface names */
>  	char *if_str;		/**< Storage for interface names */
> @@ -645,18 +646,31 @@ int main(int argc, char *argv[])
>  	if (args->appl.cpu_count)
>  		num_workers = args->appl.cpu_count;
>  
> -	/* ping mode need two worker */
> -	if (args->appl.mode == APPL_MODE_PING)
> -		num_workers = 2;
> +	if (args->appl.mask) {
> +		odp_cpumask_from_str(&cpumask, args->appl.mask);
> +		num_workers = odp_cpumask_count(&cpumask);
> +		if (odp_cpumask_last(&cpumask) > odp_cpu_count()) {

odp_cpumask_last() returns the ID of the last set CPU in the mask, which
could well be greater than the number of CPUs as the numbering scheme is
system specific.

> +			num_workers = odp_cpumask_def_worker(&cpumask,
> +							     num_workers);
> +		}

I think we need to clarify a few things in this area as the purpose and
expected usage of the odp_cpumask_def_worker() is not well defined.

For now though, I would omit the check here and just attempt to start
a thread on each CPU in the mask provided on the cmdline, and rely on
the thread creation failing if it's an invalid CPU.. which would mean
checking the return value of odph_linux_pthread_create()

> +	} else {
> +		num_workers = odp_cpumask_def_worker(&cpumask, num_workers);
> +	}
>  
> -	/* Get default worker cpumask */
> -	num_workers = odp_cpumask_def_worker(&cpumask, num_workers);
>  	(void)odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr));
>  
>  	printf("num worker threads: %i\n", num_workers);
>  	printf("first CPU:          %i\n", odp_cpumask_first(&cpumask));
>  	printf("cpu mask:           %s\n", cpumaskstr);
>  
> +	/* ping mode need two workers */
> +	if (args->appl.mode == APPL_MODE_PING) {
> +		if (num_workers < 2) {
> +			EXAMPLE_ERR("Need at least two worker threads\n");
> +			exit(EXIT_FAILURE);
> +		}
> +	}
> +
>  	/* Create packet pool */
>  	memset(&params, 0, sizeof(params));
>  	params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE;
> @@ -704,12 +718,13 @@ int main(int argc, char *argv[])
>  	memset(thread_tbl, 0, sizeof(thread_tbl));
>  
>  	if (args->appl.mode == APPL_MODE_PING) {
> -		odp_cpumask_t cpu0_mask;
> +		odp_cpumask_t cpu_mask;
>  		odp_queue_t tq;
> +		int cpu_first, cpu_next;
>  
> -		/* Previous code forced both threads to CPU 0 */
> -		odp_cpumask_zero(&cpu0_mask);
> -		odp_cpumask_set(&cpu0_mask, 0);
> +		odp_cpumask_zero(&cpu_mask);
> +		cpu_first = odp_cpumask_first(&cpumask);
> +		odp_cpumask_set(&cpu_mask, cpu_first);
>  
>  		tq = odp_queue_create("", ODP_QUEUE_TYPE_POLL, NULL);
>  		if (tq == ODP_QUEUE_INVALID)
> @@ -725,7 +740,7 @@ int main(int argc, char *argv[])
>  		if (args->thread[1].tmo_ev == ODP_TIMEOUT_INVALID)
>  			abort();
>  		args->thread[1].mode = args->appl.mode;
> -		odph_linux_pthread_create(&thread_tbl[1], &cpu0_mask,
> +		odph_linux_pthread_create(&thread_tbl[1], &cpu_mask,
>  					  gen_recv_thread, &args->thread[1]);
>  
>  		tq = odp_queue_create("", ODP_QUEUE_TYPE_POLL, NULL);
> @@ -742,7 +757,10 @@ int main(int argc, char *argv[])
>  		if (args->thread[0].tmo_ev == ODP_TIMEOUT_INVALID)
>  			abort();
>  		args->thread[0].mode = args->appl.mode;
> -		odph_linux_pthread_create(&thread_tbl[0], &cpu0_mask,
> +		cpu_next = odp_cpumask_next(&cpumask, cpu_first);
> +		odp_cpumask_zero(&cpu_mask);
> +		odp_cpumask_set(&cpu_mask, cpu_next);
> +		odph_linux_pthread_create(&thread_tbl[0], &cpu_mask,
>  					  gen_send_thread, &args->thread[0]);
>  
>  		/* only wait send thread to join */
> @@ -824,11 +842,12 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
>  	static struct option longopts[] = {
>  		{"interface", required_argument, NULL, 'I'},
>  		{"workers", required_argument, NULL, 'w'},
> +		{"cpumask", required_argument, NULL, 'c'},
>  		{"srcmac", required_argument, NULL, 'a'},
>  		{"dstmac", required_argument, NULL, 'b'},
> -		{"srcip", required_argument, NULL, 'c'},
> +		{"srcip", required_argument, NULL, 's'},
>  		{"dstip", required_argument, NULL, 'd'},
> -		{"packetsize", required_argument, NULL, 's'},
> +		{"packetsize", required_argument, NULL, 'p'},
>  		{"mode", required_argument, NULL, 'm'},
>  		{"count", required_argument, NULL, 'n'},
>  		{"timeout", required_argument, NULL, 't'},
> @@ -843,8 +862,8 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
>  	appl_args->timeout = -1;
>  
>  	while (1) {
> -		opt = getopt_long(argc, argv, "+I:a:b:c:d:s:i:m:n:t:w:h",
> -					longopts, &long_index);
> +		opt = getopt_long(argc, argv, "+I:a:b:s:d:p:i:m:n:t:w:c:h",
> +				  longopts, &long_index);
>  		if (opt == -1)
>  			break;	/* No more options */
>  
> @@ -852,6 +871,9 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
>  		case 'w':
>  			appl_args->cpu_count = atoi(optarg);
>  			break;
> +		case 'c':
> +			appl_args->mask = optarg;
> +			break;
>  		/* parse packet-io interface names */
>  		case 'I':
>  			len = strlen(optarg);
> @@ -920,7 +942,7 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
>  			}
>  			break;
>  
> -		case 'c':
> +		case 's':
>  			if (scan_ip(optarg, &appl_args->srcip) != 1) {
>  				EXAMPLE_ERR("wrong src ip:%s\n", optarg);
>  				exit(EXIT_FAILURE);
> @@ -934,7 +956,7 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
>  			}
>  			break;
>  
> -		case 's':
> +		case 'p':
>  			appl_args->payload = atoi(optarg);
>  			break;
>  
> @@ -1027,20 +1049,23 @@ static void usage(char *progname)
>  	       "    2.receive udp packets\n"
>  	       "      odp_generator -I eth0 -m r\n"
>  	       "    3.work likes ping\n"
> -	       "      odp_generator -I eth0 --srcmac fe:0f:97:c9:e0:44  --dstmac 32:cb:9b:27:2f:1a --srcip 192.168.0.1 --dstip 192.168.0.2 -m p\n"
> +	       "      odp_generator -I eth0 --srcmac fe:0f:97:c9:e0:44  --dstmac 32:cb:9b:27:2f:1a --srcip 192.168.0.1 --dstip 192.168.0.2 --cpumask 0xc -m p\n"
>  	       "\n"
>  	       "Mandatory OPTIONS:\n"
>  	       "  -I, --interface Eth interfaces (comma-separated, no spaces)\n"
>  	       "  -a, --srcmac src mac address\n"
>  	       "  -b, --dstmac dst mac address\n"
> -	       "  -c, --srcip src ip address\n"
> +	       "  -s, --srcip src ip address\n"
>  	       "  -d, --dstip dst ip address\n"
> -	       "  -s, --packetsize payload length of the packets\n"
> +	       "  -p, --packetsize payload length of the packets\n"
>  	       "  -m, --mode work mode: send udp(u), receive(r), send icmp(p)\n"
>  	       "  -n, --count the number of packets to be send\n"
>  	       "  -t, --timeout only for ping mode, wait ICMP reply timeout seconds\n"
>  	       "  -i, --interval wait interval ms between sending each packet\n"
>  	       "                 default is 1000ms. 0 for flood mode\n"
> +	       "  -w, --workers specify number of workers need to be assigned to application\n"
> +	       "	         default is to assign all\n"
> +	       "  -c, --cpumask to set on cores\n"

These are listed under mandatory options but in fact many of them are
optional.

>  	       "\n"
>  	       "Optional OPTIONS\n"
>  	       "  -h, --help       Display help and exit.\n"
> -- 
> 1.9.1
>
Balakrishna Garapati Aug. 18, 2015, 3:39 p.m. UTC | #2
Stuart, you have reviewed the old patch. please look at the PATCHv7 "
http://patches.opendataplane.org/patch/2723/"

On 18 August 2015 at 16:45, Stuart Haslam <stuart.haslam@linaro.org> wrote:

> On Mon, Aug 10, 2015 at 02:27:46PM +0200, Balakrishna.Garapati wrote:
> > Signed-off-by: Balakrishna.Garapati <balakrishna.garapati@linaro.org>
> > ---
> >  Updated core mask usage, fixed the cpu limit check with core mask.
> >  example/generator/odp_generator.c | 65
> +++++++++++++++++++++++++++------------
> >  1 file changed, 45 insertions(+), 20 deletions(-)
> >
> > diff --git a/example/generator/odp_generator.c
> b/example/generator/odp_generator.c
> > index bdee222..9408db1 100644
> > --- a/example/generator/odp_generator.c
> > +++ b/example/generator/odp_generator.c
> > @@ -43,6 +43,7 @@
> >   */
> >  typedef struct {
> >       int cpu_count;          /**< system CPU count */
> > +     const char *mask;       /**< s/core mask/CPU mask */
>
> In my previous comment I was asking to replace the text "core mask" with
> "CPU mask".
>
> >       int if_count;           /**< Number of interfaces to be used */
> >       char **if_names;        /**< Array of pointers to interface names
> */
> >       char *if_str;           /**< Storage for interface names */
> > @@ -645,18 +646,31 @@ int main(int argc, char *argv[])
> >       if (args->appl.cpu_count)
> >               num_workers = args->appl.cpu_count;
> >
> > -     /* ping mode need two worker */
> > -     if (args->appl.mode == APPL_MODE_PING)
> > -             num_workers = 2;
> > +     if (args->appl.mask) {
> > +             odp_cpumask_from_str(&cpumask, args->appl.mask);
> > +             num_workers = odp_cpumask_count(&cpumask);
> > +             if (odp_cpumask_last(&cpumask) > odp_cpu_count()) {
>
> odp_cpumask_last() returns the ID of the last set CPU in the mask, which
> could well be greater than the number of CPUs as the numbering scheme is
> system specific.
>
> > +                     num_workers = odp_cpumask_def_worker(&cpumask,
> > +                                                          num_workers);
> > +             }
>
> I think we need to clarify a few things in this area as the purpose and
> expected usage of the odp_cpumask_def_worker() is not well defined.
>
> For now though, I would omit the check here and just attempt to start
> a thread on each CPU in the mask provided on the cmdline, and rely on
> the thread creation failing if it's an invalid CPU.. which would mean
> checking the return value of odph_linux_pthread_create()
>
> > +     } else {
> > +             num_workers = odp_cpumask_def_worker(&cpumask,
> num_workers);
> > +     }
> >
> > -     /* Get default worker cpumask */
> > -     num_workers = odp_cpumask_def_worker(&cpumask, num_workers);
> >       (void)odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr));
> >
> >       printf("num worker threads: %i\n", num_workers);
> >       printf("first CPU:          %i\n", odp_cpumask_first(&cpumask));
> >       printf("cpu mask:           %s\n", cpumaskstr);
> >
> > +     /* ping mode need two workers */
> > +     if (args->appl.mode == APPL_MODE_PING) {
> > +             if (num_workers < 2) {
> > +                     EXAMPLE_ERR("Need at least two worker threads\n");
> > +                     exit(EXIT_FAILURE);
> > +             }
> > +     }
> > +
> >       /* Create packet pool */
> >       memset(&params, 0, sizeof(params));
> >       params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE;
> > @@ -704,12 +718,13 @@ int main(int argc, char *argv[])
> >       memset(thread_tbl, 0, sizeof(thread_tbl));
> >
> >       if (args->appl.mode == APPL_MODE_PING) {
> > -             odp_cpumask_t cpu0_mask;
> > +             odp_cpumask_t cpu_mask;
> >               odp_queue_t tq;
> > +             int cpu_first, cpu_next;
> >
> > -             /* Previous code forced both threads to CPU 0 */
> > -             odp_cpumask_zero(&cpu0_mask);
> > -             odp_cpumask_set(&cpu0_mask, 0);
> > +             odp_cpumask_zero(&cpu_mask);
> > +             cpu_first = odp_cpumask_first(&cpumask);
> > +             odp_cpumask_set(&cpu_mask, cpu_first);
> >
> >               tq = odp_queue_create("", ODP_QUEUE_TYPE_POLL, NULL);
> >               if (tq == ODP_QUEUE_INVALID)
> > @@ -725,7 +740,7 @@ int main(int argc, char *argv[])
> >               if (args->thread[1].tmo_ev == ODP_TIMEOUT_INVALID)
> >                       abort();
> >               args->thread[1].mode = args->appl.mode;
> > -             odph_linux_pthread_create(&thread_tbl[1], &cpu0_mask,
> > +             odph_linux_pthread_create(&thread_tbl[1], &cpu_mask,
> >                                         gen_recv_thread,
> &args->thread[1]);
> >
> >               tq = odp_queue_create("", ODP_QUEUE_TYPE_POLL, NULL);
> > @@ -742,7 +757,10 @@ int main(int argc, char *argv[])
> >               if (args->thread[0].tmo_ev == ODP_TIMEOUT_INVALID)
> >                       abort();
> >               args->thread[0].mode = args->appl.mode;
> > -             odph_linux_pthread_create(&thread_tbl[0], &cpu0_mask,
> > +             cpu_next = odp_cpumask_next(&cpumask, cpu_first);
> > +             odp_cpumask_zero(&cpu_mask);
> > +             odp_cpumask_set(&cpu_mask, cpu_next);
> > +             odph_linux_pthread_create(&thread_tbl[0], &cpu_mask,
> >                                         gen_send_thread,
> &args->thread[0]);
> >
> >               /* only wait send thread to join */
> > @@ -824,11 +842,12 @@ static void parse_args(int argc, char *argv[],
> appl_args_t *appl_args)
> >       static struct option longopts[] = {
> >               {"interface", required_argument, NULL, 'I'},
> >               {"workers", required_argument, NULL, 'w'},
> > +             {"cpumask", required_argument, NULL, 'c'},
> >               {"srcmac", required_argument, NULL, 'a'},
> >               {"dstmac", required_argument, NULL, 'b'},
> > -             {"srcip", required_argument, NULL, 'c'},
> > +             {"srcip", required_argument, NULL, 's'},
> >               {"dstip", required_argument, NULL, 'd'},
> > -             {"packetsize", required_argument, NULL, 's'},
> > +             {"packetsize", required_argument, NULL, 'p'},
> >               {"mode", required_argument, NULL, 'm'},
> >               {"count", required_argument, NULL, 'n'},
> >               {"timeout", required_argument, NULL, 't'},
> > @@ -843,8 +862,8 @@ static void parse_args(int argc, char *argv[],
> appl_args_t *appl_args)
> >       appl_args->timeout = -1;
> >
> >       while (1) {
> > -             opt = getopt_long(argc, argv, "+I:a:b:c:d:s:i:m:n:t:w:h",
> > -                                     longopts, &long_index);
> > +             opt = getopt_long(argc, argv, "+I:a:b:s:d:p:i:m:n:t:w:c:h",
> > +                               longopts, &long_index);
> >               if (opt == -1)
> >                       break;  /* No more options */
> >
> > @@ -852,6 +871,9 @@ static void parse_args(int argc, char *argv[],
> appl_args_t *appl_args)
> >               case 'w':
> >                       appl_args->cpu_count = atoi(optarg);
> >                       break;
> > +             case 'c':
> > +                     appl_args->mask = optarg;
> > +                     break;
> >               /* parse packet-io interface names */
> >               case 'I':
> >                       len = strlen(optarg);
> > @@ -920,7 +942,7 @@ static void parse_args(int argc, char *argv[],
> appl_args_t *appl_args)
> >                       }
> >                       break;
> >
> > -             case 'c':
> > +             case 's':
> >                       if (scan_ip(optarg, &appl_args->srcip) != 1) {
> >                               EXAMPLE_ERR("wrong src ip:%s\n", optarg);
> >                               exit(EXIT_FAILURE);
> > @@ -934,7 +956,7 @@ static void parse_args(int argc, char *argv[],
> appl_args_t *appl_args)
> >                       }
> >                       break;
> >
> > -             case 's':
> > +             case 'p':
> >                       appl_args->payload = atoi(optarg);
> >                       break;
> >
> > @@ -1027,20 +1049,23 @@ static void usage(char *progname)
> >              "    2.receive udp packets\n"
> >              "      odp_generator -I eth0 -m r\n"
> >              "    3.work likes ping\n"
> > -            "      odp_generator -I eth0 --srcmac fe:0f:97:c9:e0:44
> --dstmac 32:cb:9b:27:2f:1a --srcip 192.168.0.1 --dstip 192.168.0.2 -m p\n"
> > +            "      odp_generator -I eth0 --srcmac fe:0f:97:c9:e0:44
> --dstmac 32:cb:9b:27:2f:1a --srcip 192.168.0.1 --dstip 192.168.0.2
> --cpumask 0xc -m p\n"
> >              "\n"
> >              "Mandatory OPTIONS:\n"
> >              "  -I, --interface Eth interfaces (comma-separated, no
> spaces)\n"
> >              "  -a, --srcmac src mac address\n"
> >              "  -b, --dstmac dst mac address\n"
> > -            "  -c, --srcip src ip address\n"
> > +            "  -s, --srcip src ip address\n"
> >              "  -d, --dstip dst ip address\n"
> > -            "  -s, --packetsize payload length of the packets\n"
> > +            "  -p, --packetsize payload length of the packets\n"
> >              "  -m, --mode work mode: send udp(u), receive(r), send
> icmp(p)\n"
> >              "  -n, --count the number of packets to be send\n"
> >              "  -t, --timeout only for ping mode, wait ICMP reply
> timeout seconds\n"
> >              "  -i, --interval wait interval ms between sending each
> packet\n"
> >              "                 default is 1000ms. 0 for flood mode\n"
> > +            "  -w, --workers specify number of workers need to be
> assigned to application\n"
> > +            "                 default is to assign all\n"
> > +            "  -c, --cpumask to set on cores\n"
>
> These are listed under mandatory options but in fact many of them are
> optional.
>
> >              "\n"
> >              "Optional OPTIONS\n"
> >              "  -h, --help       Display help and exit.\n"
> > --
> > 1.9.1
> >
>
>
Stuart Haslam Aug. 19, 2015, 9:48 a.m. UTC | #3
On Tue, Aug 18, 2015 at 05:39:59PM +0200, Krishna Garapati wrote:
> Stuart, you have reviewed the old patch. please look at the PATCHv7 "
> http://patches.opendataplane.org/patch/2723/"
> 

Oops missed that, a couple of minor comments still apply so I'll reply to
that patch.
diff mbox

Patch

diff --git a/example/generator/odp_generator.c b/example/generator/odp_generator.c
index bdee222..9408db1 100644
--- a/example/generator/odp_generator.c
+++ b/example/generator/odp_generator.c
@@ -43,6 +43,7 @@ 
  */
 typedef struct {
 	int cpu_count;		/**< system CPU count */
+	const char *mask;	/**< s/core mask/CPU mask */
 	int if_count;		/**< Number of interfaces to be used */
 	char **if_names;	/**< Array of pointers to interface names */
 	char *if_str;		/**< Storage for interface names */
@@ -645,18 +646,31 @@  int main(int argc, char *argv[])
 	if (args->appl.cpu_count)
 		num_workers = args->appl.cpu_count;
 
-	/* ping mode need two worker */
-	if (args->appl.mode == APPL_MODE_PING)
-		num_workers = 2;
+	if (args->appl.mask) {
+		odp_cpumask_from_str(&cpumask, args->appl.mask);
+		num_workers = odp_cpumask_count(&cpumask);
+		if (odp_cpumask_last(&cpumask) > odp_cpu_count()) {
+			num_workers = odp_cpumask_def_worker(&cpumask,
+							     num_workers);
+		}
+	} else {
+		num_workers = odp_cpumask_def_worker(&cpumask, num_workers);
+	}
 
-	/* Get default worker cpumask */
-	num_workers = odp_cpumask_def_worker(&cpumask, num_workers);
 	(void)odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr));
 
 	printf("num worker threads: %i\n", num_workers);
 	printf("first CPU:          %i\n", odp_cpumask_first(&cpumask));
 	printf("cpu mask:           %s\n", cpumaskstr);
 
+	/* ping mode need two workers */
+	if (args->appl.mode == APPL_MODE_PING) {
+		if (num_workers < 2) {
+			EXAMPLE_ERR("Need at least two worker threads\n");
+			exit(EXIT_FAILURE);
+		}
+	}
+
 	/* Create packet pool */
 	memset(&params, 0, sizeof(params));
 	params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE;
@@ -704,12 +718,13 @@  int main(int argc, char *argv[])
 	memset(thread_tbl, 0, sizeof(thread_tbl));
 
 	if (args->appl.mode == APPL_MODE_PING) {
-		odp_cpumask_t cpu0_mask;
+		odp_cpumask_t cpu_mask;
 		odp_queue_t tq;
+		int cpu_first, cpu_next;
 
-		/* Previous code forced both threads to CPU 0 */
-		odp_cpumask_zero(&cpu0_mask);
-		odp_cpumask_set(&cpu0_mask, 0);
+		odp_cpumask_zero(&cpu_mask);
+		cpu_first = odp_cpumask_first(&cpumask);
+		odp_cpumask_set(&cpu_mask, cpu_first);
 
 		tq = odp_queue_create("", ODP_QUEUE_TYPE_POLL, NULL);
 		if (tq == ODP_QUEUE_INVALID)
@@ -725,7 +740,7 @@  int main(int argc, char *argv[])
 		if (args->thread[1].tmo_ev == ODP_TIMEOUT_INVALID)
 			abort();
 		args->thread[1].mode = args->appl.mode;
-		odph_linux_pthread_create(&thread_tbl[1], &cpu0_mask,
+		odph_linux_pthread_create(&thread_tbl[1], &cpu_mask,
 					  gen_recv_thread, &args->thread[1]);
 
 		tq = odp_queue_create("", ODP_QUEUE_TYPE_POLL, NULL);
@@ -742,7 +757,10 @@  int main(int argc, char *argv[])
 		if (args->thread[0].tmo_ev == ODP_TIMEOUT_INVALID)
 			abort();
 		args->thread[0].mode = args->appl.mode;
-		odph_linux_pthread_create(&thread_tbl[0], &cpu0_mask,
+		cpu_next = odp_cpumask_next(&cpumask, cpu_first);
+		odp_cpumask_zero(&cpu_mask);
+		odp_cpumask_set(&cpu_mask, cpu_next);
+		odph_linux_pthread_create(&thread_tbl[0], &cpu_mask,
 					  gen_send_thread, &args->thread[0]);
 
 		/* only wait send thread to join */
@@ -824,11 +842,12 @@  static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
 	static struct option longopts[] = {
 		{"interface", required_argument, NULL, 'I'},
 		{"workers", required_argument, NULL, 'w'},
+		{"cpumask", required_argument, NULL, 'c'},
 		{"srcmac", required_argument, NULL, 'a'},
 		{"dstmac", required_argument, NULL, 'b'},
-		{"srcip", required_argument, NULL, 'c'},
+		{"srcip", required_argument, NULL, 's'},
 		{"dstip", required_argument, NULL, 'd'},
-		{"packetsize", required_argument, NULL, 's'},
+		{"packetsize", required_argument, NULL, 'p'},
 		{"mode", required_argument, NULL, 'm'},
 		{"count", required_argument, NULL, 'n'},
 		{"timeout", required_argument, NULL, 't'},
@@ -843,8 +862,8 @@  static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
 	appl_args->timeout = -1;
 
 	while (1) {
-		opt = getopt_long(argc, argv, "+I:a:b:c:d:s:i:m:n:t:w:h",
-					longopts, &long_index);
+		opt = getopt_long(argc, argv, "+I:a:b:s:d:p:i:m:n:t:w:c:h",
+				  longopts, &long_index);
 		if (opt == -1)
 			break;	/* No more options */
 
@@ -852,6 +871,9 @@  static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
 		case 'w':
 			appl_args->cpu_count = atoi(optarg);
 			break;
+		case 'c':
+			appl_args->mask = optarg;
+			break;
 		/* parse packet-io interface names */
 		case 'I':
 			len = strlen(optarg);
@@ -920,7 +942,7 @@  static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
 			}
 			break;
 
-		case 'c':
+		case 's':
 			if (scan_ip(optarg, &appl_args->srcip) != 1) {
 				EXAMPLE_ERR("wrong src ip:%s\n", optarg);
 				exit(EXIT_FAILURE);
@@ -934,7 +956,7 @@  static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
 			}
 			break;
 
-		case 's':
+		case 'p':
 			appl_args->payload = atoi(optarg);
 			break;
 
@@ -1027,20 +1049,23 @@  static void usage(char *progname)
 	       "    2.receive udp packets\n"
 	       "      odp_generator -I eth0 -m r\n"
 	       "    3.work likes ping\n"
-	       "      odp_generator -I eth0 --srcmac fe:0f:97:c9:e0:44  --dstmac 32:cb:9b:27:2f:1a --srcip 192.168.0.1 --dstip 192.168.0.2 -m p\n"
+	       "      odp_generator -I eth0 --srcmac fe:0f:97:c9:e0:44  --dstmac 32:cb:9b:27:2f:1a --srcip 192.168.0.1 --dstip 192.168.0.2 --cpumask 0xc -m p\n"
 	       "\n"
 	       "Mandatory OPTIONS:\n"
 	       "  -I, --interface Eth interfaces (comma-separated, no spaces)\n"
 	       "  -a, --srcmac src mac address\n"
 	       "  -b, --dstmac dst mac address\n"
-	       "  -c, --srcip src ip address\n"
+	       "  -s, --srcip src ip address\n"
 	       "  -d, --dstip dst ip address\n"
-	       "  -s, --packetsize payload length of the packets\n"
+	       "  -p, --packetsize payload length of the packets\n"
 	       "  -m, --mode work mode: send udp(u), receive(r), send icmp(p)\n"
 	       "  -n, --count the number of packets to be send\n"
 	       "  -t, --timeout only for ping mode, wait ICMP reply timeout seconds\n"
 	       "  -i, --interval wait interval ms between sending each packet\n"
 	       "                 default is 1000ms. 0 for flood mode\n"
+	       "  -w, --workers specify number of workers need to be assigned to application\n"
+	       "	         default is to assign all\n"
+	       "  -c, --cpumask to set on cores\n"
 	       "\n"
 	       "Optional OPTIONS\n"
 	       "  -h, --help       Display help and exit.\n"