1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2016 Intel Corporation 3 */ 4 5 #ifndef __L3_FWD_H__ 6 #define __L3_FWD_H__ 7 8 #include <rte_ethdev.h> 9 #include <rte_vect.h> 10 11 #define DO_RFC_1812_CHECKS 12 13 #define RTE_LOGTYPE_L3FWD RTE_LOGTYPE_USER1 14 15 #if !defined(NO_HASH_MULTI_LOOKUP) && defined(__ARM_NEON) 16 #define NO_HASH_MULTI_LOOKUP 1 17 #endif 18 19 /* 20 * Configurable number of RX/TX ring descriptors 21 */ 22 #define RTE_TEST_RX_DESC_DEFAULT 1024 23 #define RTE_TEST_TX_DESC_DEFAULT 1024 24 25 #define MAX_PKT_BURST 32 26 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ 27 28 #define MEMPOOL_CACHE_SIZE 256 29 #define MAX_RX_QUEUE_PER_LCORE 16 30 31 /* 32 * Try to avoid TX buffering if we have at least MAX_TX_BURST packets to send. 33 */ 34 #define MAX_TX_BURST (MAX_PKT_BURST / 2) 35 36 #define NB_SOCKETS 8 37 38 /* Configure how many packets ahead to prefetch, when reading packets */ 39 #define PREFETCH_OFFSET 3 40 41 /* Used to mark destination port as 'invalid'. */ 42 #define BAD_PORT ((uint16_t)-1) 43 44 #define FWDSTEP 4 45 46 /* replace first 12B of the ethernet header. */ 47 #define MASK_ETH 0x3f 48 49 /* Hash parameters. */ 50 #ifdef RTE_ARCH_64 51 /* default to 4 million hash entries (approx) */ 52 #define L3FWD_HASH_ENTRIES (1024*1024*4) 53 #else 54 /* 32-bit has less address-space for hugepage memory, limit to 1M entries */ 55 #define L3FWD_HASH_ENTRIES (1024*1024*1) 56 #endif 57 #define HASH_ENTRY_NUMBER_DEFAULT 4 58 59 struct mbuf_table { 60 uint16_t len; 61 struct rte_mbuf *m_table[MAX_PKT_BURST]; 62 }; 63 64 struct lcore_rx_queue { 65 uint16_t port_id; 66 uint8_t queue_id; 67 } __rte_cache_aligned; 68 69 struct lcore_conf { 70 uint16_t n_rx_queue; 71 struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE]; 72 uint16_t n_tx_port; 73 uint16_t tx_port_id[RTE_MAX_ETHPORTS]; 74 uint16_t tx_queue_id[RTE_MAX_ETHPORTS]; 75 struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS]; 76 void *ipv4_lookup_struct; 77 void *ipv6_lookup_struct; 78 } __rte_cache_aligned; 79 80 extern volatile bool force_quit; 81 82 /* ethernet addresses of ports */ 83 extern uint64_t dest_eth_addr[RTE_MAX_ETHPORTS]; 84 extern struct rte_ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; 85 86 /* mask of enabled ports */ 87 extern uint32_t enabled_port_mask; 88 89 /* Used only in exact match mode. */ 90 extern int ipv6; /**< ipv6 is false by default. */ 91 extern uint32_t hash_entry_number; 92 93 extern xmm_t val_eth[RTE_MAX_ETHPORTS]; 94 95 extern struct lcore_conf lcore_conf[RTE_MAX_LCORE]; 96 97 /* Send burst of packets on an output interface */ 98 static inline int 99 send_burst(struct lcore_conf *qconf, uint16_t n, uint16_t port) 100 { 101 struct rte_mbuf **m_table; 102 int ret; 103 uint16_t queueid; 104 105 queueid = qconf->tx_queue_id[port]; 106 m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table; 107 108 ret = rte_eth_tx_burst(port, queueid, m_table, n); 109 if (unlikely(ret < n)) { 110 do { 111 rte_pktmbuf_free(m_table[ret]); 112 } while (++ret < n); 113 } 114 115 return 0; 116 } 117 118 /* Enqueue a single packet, and send burst if queue is filled */ 119 static inline int 120 send_single_packet(struct lcore_conf *qconf, 121 struct rte_mbuf *m, uint16_t port) 122 { 123 uint16_t len; 124 125 len = qconf->tx_mbufs[port].len; 126 qconf->tx_mbufs[port].m_table[len] = m; 127 len++; 128 129 /* enough pkts to be sent */ 130 if (unlikely(len == MAX_PKT_BURST)) { 131 send_burst(qconf, MAX_PKT_BURST, port); 132 len = 0; 133 } 134 135 qconf->tx_mbufs[port].len = len; 136 return 0; 137 } 138 139 #ifdef DO_RFC_1812_CHECKS 140 static inline int 141 is_valid_ipv4_pkt(struct rte_ipv4_hdr *pkt, uint32_t link_len) 142 { 143 /* From http://www.rfc-editor.org/rfc/rfc1812.txt section 5.2.2 */ 144 /* 145 * 1. The packet length reported by the Link Layer must be large 146 * enough to hold the minimum length legal IP datagram (20 bytes). 147 */ 148 if (link_len < sizeof(struct rte_ipv4_hdr)) 149 return -1; 150 151 /* 2. The IP checksum must be correct. */ 152 /* this is checked in H/W */ 153 154 /* 155 * 3. The IP version number must be 4. If the version number is not 4 156 * then the packet may be another version of IP, such as IPng or 157 * ST-II. 158 */ 159 if (((pkt->version_ihl) >> 4) != 4) 160 return -3; 161 /* 162 * 4. The IP header length field must be large enough to hold the 163 * minimum length legal IP datagram (20 bytes = 5 words). 164 */ 165 if ((pkt->version_ihl & 0xf) < 5) 166 return -4; 167 168 /* 169 * 5. The IP total length field must be large enough to hold the IP 170 * datagram header, whose length is specified in the IP header length 171 * field. 172 */ 173 if (rte_cpu_to_be_16(pkt->total_length) < sizeof(struct rte_ipv4_hdr)) 174 return -5; 175 176 return 0; 177 } 178 #endif /* DO_RFC_1812_CHECKS */ 179 180 int 181 init_mem(uint16_t portid, unsigned int nb_mbuf); 182 183 /* Function pointers for LPM or EM functionality. */ 184 void 185 setup_lpm(const int socketid); 186 187 void 188 setup_hash(const int socketid); 189 190 int 191 em_check_ptype(int portid); 192 193 int 194 lpm_check_ptype(int portid); 195 196 uint16_t 197 em_cb_parse_ptype(uint16_t port, uint16_t queue, struct rte_mbuf *pkts[], 198 uint16_t nb_pkts, uint16_t max_pkts, void *user_param); 199 200 uint16_t 201 lpm_cb_parse_ptype(uint16_t port, uint16_t queue, struct rte_mbuf *pkts[], 202 uint16_t nb_pkts, uint16_t max_pkts, void *user_param); 203 204 int 205 em_main_loop(__rte_unused void *dummy); 206 207 int 208 lpm_main_loop(__rte_unused void *dummy); 209 210 int 211 lpm_event_main_loop_tx_d(__rte_unused void *dummy); 212 int 213 lpm_event_main_loop_tx_d_burst(__rte_unused void *dummy); 214 int 215 lpm_event_main_loop_tx_q(__rte_unused void *dummy); 216 int 217 lpm_event_main_loop_tx_q_burst(__rte_unused void *dummy); 218 219 int 220 em_event_main_loop_tx_d(__rte_unused void *dummy); 221 int 222 em_event_main_loop_tx_d_burst(__rte_unused void *dummy); 223 int 224 em_event_main_loop_tx_q(__rte_unused void *dummy); 225 int 226 em_event_main_loop_tx_q_burst(__rte_unused void *dummy); 227 228 229 /* Return ipv4/ipv6 fwd lookup struct for LPM or EM. */ 230 void * 231 em_get_ipv4_l3fwd_lookup_struct(const int socketid); 232 233 void * 234 em_get_ipv6_l3fwd_lookup_struct(const int socketid); 235 236 void * 237 lpm_get_ipv4_l3fwd_lookup_struct(const int socketid); 238 239 void * 240 lpm_get_ipv6_l3fwd_lookup_struct(const int socketid); 241 242 #endif /* __L3_FWD_H__ */ 243