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