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 uint8_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 /**< Header Split disabled */ 142 .header_split = 0, 143 /**< IP checksum offload disabled */ 144 .hw_ip_checksum = 0, 145 /**< VLAN filtering disabled */ 146 .hw_vlan_filter = 0, 147 /**< Jumbo Frame Support disabled */ 148 .jumbo_frame = 0, 149 /**< CRC stripped by hardware */ 150 .hw_strip_crc = 1, 151 }, 152 .txmode = { 153 .offloads = 154 DEV_TX_OFFLOAD_VLAN_INSERT | 155 DEV_TX_OFFLOAD_IPV4_CKSUM | 156 DEV_TX_OFFLOAD_UDP_CKSUM | 157 DEV_TX_OFFLOAD_TCP_CKSUM | 158 DEV_TX_OFFLOAD_SCTP_CKSUM | 159 DEV_TX_OFFLOAD_TCP_TSO, 160 }, 161 }; 162 struct rte_eth_txconf txq_conf; 163 struct rte_eth_dev_info dev_info; 164 165 printf(":: initializing port: %d\n", port_id); 166 ret = rte_eth_dev_configure(port_id, 167 nr_queues, nr_queues, &port_conf); 168 if (ret < 0) { 169 rte_exit(EXIT_FAILURE, 170 ":: cannot configure device: err=%d, port=%u\n", 171 ret, port_id); 172 } 173 174 /* only set Rx queues: something we care only so far */ 175 for (i = 0; i < nr_queues; i++) { 176 ret = rte_eth_rx_queue_setup(port_id, i, 512, 177 rte_eth_dev_socket_id(port_id), 178 NULL, 179 mbuf_pool); 180 if (ret < 0) { 181 rte_exit(EXIT_FAILURE, 182 ":: Rx queue setup failed: err=%d, port=%u\n", 183 ret, port_id); 184 } 185 } 186 187 rte_eth_dev_info_get(port_id, &dev_info); 188 txq_conf = dev_info.default_txconf; 189 txq_conf.offloads = port_conf.txmode.offloads; 190 191 for (i = 0; i < nr_queues; i++) { 192 ret = rte_eth_tx_queue_setup(port_id, i, 512, 193 rte_eth_dev_socket_id(port_id), 194 &txq_conf); 195 if (ret < 0) { 196 rte_exit(EXIT_FAILURE, 197 ":: Tx queue setup failed: err=%d, port=%u\n", 198 ret, port_id); 199 } 200 } 201 202 rte_eth_promiscuous_enable(port_id); 203 ret = rte_eth_dev_start(port_id); 204 if (ret < 0) { 205 rte_exit(EXIT_FAILURE, 206 "rte_eth_dev_start:err=%d, port=%u\n", 207 ret, port_id); 208 } 209 210 assert_link_status(); 211 212 printf(":: initializing port: %d done\n", port_id); 213 } 214 215 static void 216 signal_handler(int signum) 217 { 218 if (signum == SIGINT || signum == SIGTERM) { 219 printf("\n\nSignal %d received, preparing to exit...\n", 220 signum); 221 force_quit = true; 222 } 223 } 224 225 int 226 main(int argc, char **argv) 227 { 228 int ret; 229 uint8_t nr_ports; 230 struct rte_flow_error error; 231 232 ret = rte_eal_init(argc, argv); 233 if (ret < 0) 234 rte_exit(EXIT_FAILURE, ":: invalid EAL arguments\n"); 235 236 force_quit = false; 237 signal(SIGINT, signal_handler); 238 signal(SIGTERM, signal_handler); 239 240 nr_ports = rte_eth_dev_count(); 241 if (nr_ports == 0) 242 rte_exit(EXIT_FAILURE, ":: no Ethernet ports found\n"); 243 port_id = 0; 244 if (nr_ports != 1) { 245 printf(":: warn: %d ports detected, but we use only one: port %u\n", 246 nr_ports, port_id); 247 } 248 mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", 4096, 128, 0, 249 RTE_MBUF_DEFAULT_BUF_SIZE, 250 rte_socket_id()); 251 if (mbuf_pool == NULL) 252 rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n"); 253 254 init_port(); 255 256 /* create flow for send packet with */ 257 flow = generate_ipv4_flow(port_id, selected_queue, 258 SRC_IP, EMPTY_MASK, 259 DEST_IP, FULL_MASK, &error); 260 if (!flow) { 261 printf("Flow can't be created %d message: %s\n", 262 error.type, 263 error.message ? error.message : "(no stated reason)"); 264 rte_exit(EXIT_FAILURE, "error in creating flow"); 265 } 266 267 main_loop(); 268 269 return 0; 270 } 271