1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <stdint.h> 8 #include <getopt.h> 9 #include <stdarg.h> 10 #include <errno.h> 11 12 #include <rte_memory.h> 13 #include <rte_string_fns.h> 14 15 #include "common.h" 16 #include "args.h" 17 #include "init.h" 18 19 /* global var for number of clients - extern in header */ 20 uint8_t num_clients; 21 22 static const char *progname; 23 24 /** 25 * Prints out usage information to stdout 26 */ 27 static void 28 usage(void) 29 { 30 printf( 31 "%s [EAL options] -- -p PORTMASK -n NUM_CLIENTS [-s NUM_SOCKETS]\n" 32 " -p PORTMASK: hexadecimal bitmask of ports to use\n" 33 " -n NUM_CLIENTS: number of client processes to use\n" 34 , progname); 35 } 36 37 /** 38 * The ports to be used by the application are passed in 39 * the form of a bitmask. This function parses the bitmask 40 * and places the port numbers to be used into the port[] 41 * array variable 42 */ 43 static int 44 parse_portmask(uint8_t max_ports, const char *portmask) 45 { 46 char *end = NULL; 47 unsigned long pm; 48 uint16_t count = 0; 49 50 if (portmask == NULL || *portmask == '\0') 51 return -1; 52 53 /* convert parameter to a number and verify */ 54 pm = strtoul(portmask, &end, 16); 55 if (end == NULL || *end != '\0' || pm == 0) 56 return -1; 57 58 /* loop through bits of the mask and mark ports */ 59 while (pm != 0){ 60 if (pm & 0x01){ /* bit is set in mask, use port */ 61 if (count >= max_ports) 62 printf("WARNING: requested port %u not present" 63 " - ignoring\n", (unsigned)count); 64 else 65 ports->id[ports->num_ports++] = count; 66 } 67 pm = (pm >> 1); 68 count++; 69 } 70 71 return 0; 72 } 73 74 /** 75 * Take the number of clients parameter passed to the app 76 * and convert to a number to store in the num_clients variable 77 */ 78 static int 79 parse_num_clients(const char *clients) 80 { 81 char *end = NULL; 82 unsigned long temp; 83 84 if (clients == NULL || *clients == '\0') 85 return -1; 86 87 temp = strtoul(clients, &end, 10); 88 if (end == NULL || *end != '\0' || temp == 0) 89 return -1; 90 91 num_clients = (uint8_t)temp; 92 return 0; 93 } 94 95 /** 96 * The application specific arguments follow the DPDK-specific 97 * arguments which are stripped by the DPDK init. This function 98 * processes these application arguments, printing usage info 99 * on error. 100 */ 101 int 102 parse_app_args(uint16_t max_ports, int argc, char *argv[]) 103 { 104 int option_index, opt; 105 char **argvopt = argv; 106 static struct option lgopts[] = { /* no long options */ 107 {NULL, 0, 0, 0 } 108 }; 109 progname = argv[0]; 110 111 while ((opt = getopt_long(argc, argvopt, "n:p:", lgopts, 112 &option_index)) != EOF){ 113 switch (opt){ 114 case 'p': 115 if (parse_portmask(max_ports, optarg) != 0){ 116 usage(); 117 return -1; 118 } 119 break; 120 case 'n': 121 if (parse_num_clients(optarg) != 0){ 122 usage(); 123 return -1; 124 } 125 break; 126 default: 127 printf("ERROR: Unknown option '%c'\n", opt); 128 usage(); 129 return -1; 130 } 131 } 132 133 if (ports->num_ports == 0 || num_clients == 0){ 134 usage(); 135 return -1; 136 } 137 138 if (ports->num_ports % 2 != 0){ 139 printf("ERROR: application requires an even number of ports to use\n"); 140 return -1; 141 } 142 return 0; 143 } 144