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