1*2bfe3f2eSlogwang /*- 2*2bfe3f2eSlogwang * BSD LICENSE 3*2bfe3f2eSlogwang * 4*2bfe3f2eSlogwang * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. 5*2bfe3f2eSlogwang * All rights reserved. 6*2bfe3f2eSlogwang * 7*2bfe3f2eSlogwang * Redistribution and use in source and binary forms, with or without 8*2bfe3f2eSlogwang * modification, are permitted provided that the following conditions 9*2bfe3f2eSlogwang * are met: 10*2bfe3f2eSlogwang * 11*2bfe3f2eSlogwang * * Redistributions of source code must retain the above copyright 12*2bfe3f2eSlogwang * notice, this list of conditions and the following disclaimer. 13*2bfe3f2eSlogwang * * Redistributions in binary form must reproduce the above copyright 14*2bfe3f2eSlogwang * notice, this list of conditions and the following disclaimer in 15*2bfe3f2eSlogwang * the documentation and/or other materials provided with the 16*2bfe3f2eSlogwang * distribution. 17*2bfe3f2eSlogwang * * Neither the name of Intel Corporation nor the names of its 18*2bfe3f2eSlogwang * contributors may be used to endorse or promote products derived 19*2bfe3f2eSlogwang * from this software without specific prior written permission. 20*2bfe3f2eSlogwang * 21*2bfe3f2eSlogwang * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22*2bfe3f2eSlogwang * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23*2bfe3f2eSlogwang * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24*2bfe3f2eSlogwang * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25*2bfe3f2eSlogwang * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26*2bfe3f2eSlogwang * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27*2bfe3f2eSlogwang * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28*2bfe3f2eSlogwang * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29*2bfe3f2eSlogwang * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30*2bfe3f2eSlogwang * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31*2bfe3f2eSlogwang * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32*2bfe3f2eSlogwang */ 33*2bfe3f2eSlogwang 34*2bfe3f2eSlogwang #include <stdio.h> 35*2bfe3f2eSlogwang #include <stdlib.h> 36*2bfe3f2eSlogwang #include <stdint.h> 37*2bfe3f2eSlogwang #include <getopt.h> 38*2bfe3f2eSlogwang #include <stdarg.h> 39*2bfe3f2eSlogwang #include <errno.h> 40*2bfe3f2eSlogwang 41*2bfe3f2eSlogwang #include <rte_memory.h> 42*2bfe3f2eSlogwang #include <rte_string_fns.h> 43*2bfe3f2eSlogwang 44*2bfe3f2eSlogwang #include "common.h" 45*2bfe3f2eSlogwang #include "args.h" 46*2bfe3f2eSlogwang #include "init.h" 47*2bfe3f2eSlogwang 48*2bfe3f2eSlogwang /* 1M flows by default */ 49*2bfe3f2eSlogwang #define DEFAULT_NUM_FLOWS 0x100000 50*2bfe3f2eSlogwang 51*2bfe3f2eSlogwang /* global var for number of nodes - extern in header */ 52*2bfe3f2eSlogwang uint8_t num_nodes; 53*2bfe3f2eSlogwang /* global var for number of flows - extern in header */ 54*2bfe3f2eSlogwang uint32_t num_flows = DEFAULT_NUM_FLOWS; 55*2bfe3f2eSlogwang 56*2bfe3f2eSlogwang static const char *progname; 57*2bfe3f2eSlogwang 58*2bfe3f2eSlogwang /** 59*2bfe3f2eSlogwang * Prints out usage information to stdout 60*2bfe3f2eSlogwang */ 61*2bfe3f2eSlogwang static void 62*2bfe3f2eSlogwang usage(void) 63*2bfe3f2eSlogwang { 64*2bfe3f2eSlogwang printf("%s [EAL options] -- -p PORTMASK -n NUM_NODES -f NUM_FLOWS\n" 65*2bfe3f2eSlogwang " -p PORTMASK: hexadecimal bitmask of ports to use\n" 66*2bfe3f2eSlogwang " -n NUM_NODES: number of node processes to use\n" 67*2bfe3f2eSlogwang " -f NUM_FLOWS: number of flows to be added in the EFD table\n", 68*2bfe3f2eSlogwang progname); 69*2bfe3f2eSlogwang } 70*2bfe3f2eSlogwang 71*2bfe3f2eSlogwang /** 72*2bfe3f2eSlogwang * The ports to be used by the application are passed in 73*2bfe3f2eSlogwang * the form of a bitmask. This function parses the bitmask 74*2bfe3f2eSlogwang * and places the port numbers to be used into the port[] 75*2bfe3f2eSlogwang * array variable 76*2bfe3f2eSlogwang */ 77*2bfe3f2eSlogwang static int 78*2bfe3f2eSlogwang parse_portmask(uint8_t max_ports, const char *portmask) 79*2bfe3f2eSlogwang { 80*2bfe3f2eSlogwang char *end = NULL; 81*2bfe3f2eSlogwang unsigned long pm; 82*2bfe3f2eSlogwang uint8_t count = 0; 83*2bfe3f2eSlogwang 84*2bfe3f2eSlogwang if (portmask == NULL || *portmask == '\0') 85*2bfe3f2eSlogwang return -1; 86*2bfe3f2eSlogwang 87*2bfe3f2eSlogwang /* convert parameter to a number and verify */ 88*2bfe3f2eSlogwang pm = strtoul(portmask, &end, 16); 89*2bfe3f2eSlogwang if (end == NULL || *end != '\0' || pm == 0) 90*2bfe3f2eSlogwang return -1; 91*2bfe3f2eSlogwang 92*2bfe3f2eSlogwang /* loop through bits of the mask and mark ports */ 93*2bfe3f2eSlogwang while (pm != 0) { 94*2bfe3f2eSlogwang if (pm & 0x01) { /* bit is set in mask, use port */ 95*2bfe3f2eSlogwang if (count >= max_ports) 96*2bfe3f2eSlogwang printf("WARNING: requested port %u not present" 97*2bfe3f2eSlogwang " - ignoring\n", (unsigned int)count); 98*2bfe3f2eSlogwang else 99*2bfe3f2eSlogwang info->id[info->num_ports++] = count; 100*2bfe3f2eSlogwang } 101*2bfe3f2eSlogwang pm = (pm >> 1); 102*2bfe3f2eSlogwang count++; 103*2bfe3f2eSlogwang } 104*2bfe3f2eSlogwang 105*2bfe3f2eSlogwang return 0; 106*2bfe3f2eSlogwang } 107*2bfe3f2eSlogwang 108*2bfe3f2eSlogwang /** 109*2bfe3f2eSlogwang * Take the number of nodes parameter passed to the app 110*2bfe3f2eSlogwang * and convert to a number to store in the num_nodes variable 111*2bfe3f2eSlogwang */ 112*2bfe3f2eSlogwang static int 113*2bfe3f2eSlogwang parse_num_nodes(const char *nodes) 114*2bfe3f2eSlogwang { 115*2bfe3f2eSlogwang char *end = NULL; 116*2bfe3f2eSlogwang unsigned long temp; 117*2bfe3f2eSlogwang 118*2bfe3f2eSlogwang if (nodes == NULL || *nodes == '\0') 119*2bfe3f2eSlogwang return -1; 120*2bfe3f2eSlogwang 121*2bfe3f2eSlogwang temp = strtoul(nodes, &end, 10); 122*2bfe3f2eSlogwang if (end == NULL || *end != '\0' || temp == 0) 123*2bfe3f2eSlogwang return -1; 124*2bfe3f2eSlogwang 125*2bfe3f2eSlogwang num_nodes = (uint8_t)temp; 126*2bfe3f2eSlogwang return 0; 127*2bfe3f2eSlogwang } 128*2bfe3f2eSlogwang 129*2bfe3f2eSlogwang static int 130*2bfe3f2eSlogwang parse_num_flows(const char *flows) 131*2bfe3f2eSlogwang { 132*2bfe3f2eSlogwang char *end = NULL; 133*2bfe3f2eSlogwang 134*2bfe3f2eSlogwang /* parse hexadecimal string */ 135*2bfe3f2eSlogwang num_flows = strtoul(flows, &end, 16); 136*2bfe3f2eSlogwang if ((flows[0] == '\0') || (end == NULL) || (*end != '\0')) 137*2bfe3f2eSlogwang return -1; 138*2bfe3f2eSlogwang 139*2bfe3f2eSlogwang if (num_flows == 0) 140*2bfe3f2eSlogwang return -1; 141*2bfe3f2eSlogwang 142*2bfe3f2eSlogwang return 0; 143*2bfe3f2eSlogwang } 144*2bfe3f2eSlogwang 145*2bfe3f2eSlogwang /** 146*2bfe3f2eSlogwang * The application specific arguments follow the DPDK-specific 147*2bfe3f2eSlogwang * arguments which are stripped by the DPDK init. This function 148*2bfe3f2eSlogwang * processes these application arguments, printing usage info 149*2bfe3f2eSlogwang * on error. 150*2bfe3f2eSlogwang */ 151*2bfe3f2eSlogwang int 152*2bfe3f2eSlogwang parse_app_args(uint8_t max_ports, int argc, char *argv[]) 153*2bfe3f2eSlogwang { 154*2bfe3f2eSlogwang int option_index, opt; 155*2bfe3f2eSlogwang char **argvopt = argv; 156*2bfe3f2eSlogwang static struct option lgopts[] = { /* no long options */ 157*2bfe3f2eSlogwang {NULL, 0, 0, 0 } 158*2bfe3f2eSlogwang }; 159*2bfe3f2eSlogwang progname = argv[0]; 160*2bfe3f2eSlogwang 161*2bfe3f2eSlogwang while ((opt = getopt_long(argc, argvopt, "n:f:p:", lgopts, 162*2bfe3f2eSlogwang &option_index)) != EOF) { 163*2bfe3f2eSlogwang switch (opt) { 164*2bfe3f2eSlogwang case 'p': 165*2bfe3f2eSlogwang if (parse_portmask(max_ports, optarg) != 0) { 166*2bfe3f2eSlogwang usage(); 167*2bfe3f2eSlogwang return -1; 168*2bfe3f2eSlogwang } 169*2bfe3f2eSlogwang break; 170*2bfe3f2eSlogwang case 'n': 171*2bfe3f2eSlogwang if (parse_num_nodes(optarg) != 0) { 172*2bfe3f2eSlogwang usage(); 173*2bfe3f2eSlogwang return -1; 174*2bfe3f2eSlogwang } 175*2bfe3f2eSlogwang break; 176*2bfe3f2eSlogwang case 'f': 177*2bfe3f2eSlogwang if (parse_num_flows(optarg) != 0) { 178*2bfe3f2eSlogwang usage(); 179*2bfe3f2eSlogwang return -1; 180*2bfe3f2eSlogwang } 181*2bfe3f2eSlogwang break; 182*2bfe3f2eSlogwang default: 183*2bfe3f2eSlogwang printf("ERROR: Unknown option '%c'\n", opt); 184*2bfe3f2eSlogwang usage(); 185*2bfe3f2eSlogwang return -1; 186*2bfe3f2eSlogwang } 187*2bfe3f2eSlogwang } 188*2bfe3f2eSlogwang 189*2bfe3f2eSlogwang if (info->num_ports == 0 || num_nodes == 0) { 190*2bfe3f2eSlogwang usage(); 191*2bfe3f2eSlogwang return -1; 192*2bfe3f2eSlogwang } 193*2bfe3f2eSlogwang 194*2bfe3f2eSlogwang if (info->num_ports % 2 != 0) { 195*2bfe3f2eSlogwang printf("ERROR: application requires an even " 196*2bfe3f2eSlogwang "number of ports to use\n"); 197*2bfe3f2eSlogwang return -1; 198*2bfe3f2eSlogwang } 199*2bfe3f2eSlogwang return 0; 200*2bfe3f2eSlogwang } 201