1 /*- 2 * BSD LICENSE 3 * 4 * Copyright 2017 Mellanox. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided with the 15 * distribution. 16 * * Neither the name of Mellanox. nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <stdint.h> 37 #include <inttypes.h> 38 #include <sys/types.h> 39 #include <sys/queue.h> 40 #include <netinet/in.h> 41 #include <setjmp.h> 42 #include <stdarg.h> 43 #include <ctype.h> 44 #include <errno.h> 45 #include <getopt.h> 46 #include <signal.h> 47 #include <stdbool.h> 48 49 #include <rte_eal.h> 50 #include <rte_common.h> 51 #include <rte_malloc.h> 52 #include <rte_ether.h> 53 #include <rte_ethdev.h> 54 #include <rte_mempool.h> 55 #include <rte_mbuf.h> 56 #include <rte_net.h> 57 #include <rte_flow.h> 58 59 static volatile bool force_quit; 60 61 static uint16_t port_id; 62 static uint16_t nr_queues = 5; 63 static uint8_t selected_queue = 1; 64 struct rte_mempool *mbuf_pool; 65 struct rte_flow *flow; 66 67 #define SRC_IP ((0<<24) + (0<<16) + (0<<8) + 0) /* src ip = 0.0.0.0 */ 68 #define DEST_IP ((192<<24) + (168<<16) + (1<<8) + 1) /* dest ip = 192.168.1.1 */ 69 #define FULL_MASK 0xffffffff /* full mask */ 70 #define EMPTY_MASK 0x0 /* empty mask */ 71 72 #include "flow_blocks.c" 73 74 static inline void 75 print_ether_addr(const char *what, struct ether_addr *eth_addr) 76 { 77 char buf[ETHER_ADDR_FMT_SIZE]; 78 ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, eth_addr); 79 printf("%s%s", what, buf); 80 } 81 82 static void 83 main_loop(void) 84 { 85 struct rte_mbuf *mbufs[32]; 86 struct ether_hdr *eth_hdr; 87 struct rte_flow_error error; 88 uint16_t nb_rx; 89 uint16_t i; 90 uint16_t j; 91 92 while (!force_quit) { 93 for (i = 0; i < nr_queues; i++) { 94 nb_rx = rte_eth_rx_burst(port_id, 95 i, mbufs, 32); 96 if (nb_rx) { 97 for (j = 0; j < nb_rx; j++) { 98 struct rte_mbuf *m = mbufs[j]; 99 100 eth_hdr = rte_pktmbuf_mtod(m, 101 struct ether_hdr *); 102 print_ether_addr("src=", 103 ð_hdr->s_addr); 104 print_ether_addr(" - dst=", 105 ð_hdr->d_addr); 106 printf(" - queue=0x%x", 107 (unsigned int)i); 108 printf("\n"); 109 110 rte_pktmbuf_free(m); 111 } 112 } 113 } 114 } 115 116 /* closing and releasing resources */ 117 rte_flow_flush(port_id, &error); 118 rte_eth_dev_stop(port_id); 119 rte_eth_dev_close(port_id); 120 } 121 122 static void 123 assert_link_status(void) 124 { 125 struct rte_eth_link link; 126 127 memset(&link, 0, sizeof(link)); 128 rte_eth_link_get(port_id, &link); 129 if (link.link_status == ETH_LINK_DOWN) 130 rte_exit(EXIT_FAILURE, ":: error: link is still down\n"); 131 } 132 133 static void 134 init_port(void) 135 { 136 int ret; 137 uint16_t i; 138 struct rte_eth_conf port_conf = { 139 .rxmode = { 140 .split_hdr_size = 0, 141 .ignore_offload_bitfield = 1, 142 .offloads = DEV_RX_OFFLOAD_CRC_STRIP, 143 }, 144 .txmode = { 145 .offloads = 146 DEV_TX_OFFLOAD_VLAN_INSERT | 147 DEV_TX_OFFLOAD_IPV4_CKSUM | 148 DEV_TX_OFFLOAD_UDP_CKSUM | 149 DEV_TX_OFFLOAD_TCP_CKSUM | 150 DEV_TX_OFFLOAD_SCTP_CKSUM | 151 DEV_TX_OFFLOAD_TCP_TSO, 152 }, 153 }; 154 struct rte_eth_txconf txq_conf; 155 struct rte_eth_rxconf rxq_conf; 156 struct rte_eth_dev_info dev_info; 157 158 printf(":: initializing port: %d\n", port_id); 159 ret = rte_eth_dev_configure(port_id, 160 nr_queues, nr_queues, &port_conf); 161 if (ret < 0) { 162 rte_exit(EXIT_FAILURE, 163 ":: cannot configure device: err=%d, port=%u\n", 164 ret, port_id); 165 } 166 167 rte_eth_dev_info_get(port_id, &dev_info); 168 rxq_conf = dev_info.default_rxconf; 169 rxq_conf.offloads = port_conf.rxmode.offloads; 170 /* only set Rx queues: something we care only so far */ 171 for (i = 0; i < nr_queues; i++) { 172 ret = rte_eth_rx_queue_setup(port_id, i, 512, 173 rte_eth_dev_socket_id(port_id), 174 &rxq_conf, 175 mbuf_pool); 176 if (ret < 0) { 177 rte_exit(EXIT_FAILURE, 178 ":: Rx queue setup failed: err=%d, port=%u\n", 179 ret, port_id); 180 } 181 } 182 183 txq_conf = dev_info.default_txconf; 184 txq_conf.offloads = port_conf.txmode.offloads; 185 186 for (i = 0; i < nr_queues; i++) { 187 ret = rte_eth_tx_queue_setup(port_id, i, 512, 188 rte_eth_dev_socket_id(port_id), 189 &txq_conf); 190 if (ret < 0) { 191 rte_exit(EXIT_FAILURE, 192 ":: Tx queue setup failed: err=%d, port=%u\n", 193 ret, port_id); 194 } 195 } 196 197 rte_eth_promiscuous_enable(port_id); 198 ret = rte_eth_dev_start(port_id); 199 if (ret < 0) { 200 rte_exit(EXIT_FAILURE, 201 "rte_eth_dev_start:err=%d, port=%u\n", 202 ret, port_id); 203 } 204 205 assert_link_status(); 206 207 printf(":: initializing port: %d done\n", port_id); 208 } 209 210 static void 211 signal_handler(int signum) 212 { 213 if (signum == SIGINT || signum == SIGTERM) { 214 printf("\n\nSignal %d received, preparing to exit...\n", 215 signum); 216 force_quit = true; 217 } 218 } 219 220 int 221 main(int argc, char **argv) 222 { 223 int ret; 224 uint8_t nr_ports; 225 struct rte_flow_error error; 226 227 ret = rte_eal_init(argc, argv); 228 if (ret < 0) 229 rte_exit(EXIT_FAILURE, ":: invalid EAL arguments\n"); 230 231 force_quit = false; 232 signal(SIGINT, signal_handler); 233 signal(SIGTERM, signal_handler); 234 235 nr_ports = rte_eth_dev_count(); 236 if (nr_ports == 0) 237 rte_exit(EXIT_FAILURE, ":: no Ethernet ports found\n"); 238 port_id = 0; 239 if (nr_ports != 1) { 240 printf(":: warn: %d ports detected, but we use only one: port %u\n", 241 nr_ports, port_id); 242 } 243 mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", 4096, 128, 0, 244 RTE_MBUF_DEFAULT_BUF_SIZE, 245 rte_socket_id()); 246 if (mbuf_pool == NULL) 247 rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n"); 248 249 init_port(); 250 251 /* create flow for send packet with */ 252 flow = generate_ipv4_flow(port_id, selected_queue, 253 SRC_IP, EMPTY_MASK, 254 DEST_IP, FULL_MASK, &error); 255 if (!flow) { 256 printf("Flow can't be created %d message: %s\n", 257 error.type, 258 error.message ? error.message : "(no stated reason)"); 259 rte_exit(EXIT_FAILURE, "error in creating flow"); 260 } 261 262 main_loop(); 263 264 return 0; 265 } 266