1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2016 Intel Corporation 3 */ 4 5 #ifndef __L3FWD_EM_SEQUENTIAL_H__ 6 #define __L3FWD_EM_SEQUENTIAL_H__ 7 8 #include <rte_common.h> 9 10 /** 11 * @file 12 * This is an optional implementation of packet classification in Exact-Match 13 * path using sequential packet classification method. 14 * While hash lookup multi seems to provide better performance, it's disabled 15 * by default and can be enabled with NO_HASH_LOOKUP_MULTI global define in 16 * compilation time. 17 */ 18 19 #if defined RTE_ARCH_X86 20 #include "l3fwd_sse.h" 21 #elif defined __ARM_NEON 22 #include "l3fwd_neon.h" 23 #endif 24 25 static __rte_always_inline uint16_t 26 em_get_dst_port(const struct lcore_conf *qconf, struct rte_mbuf *pkt, 27 uint16_t portid) 28 { 29 uint8_t next_hop; 30 struct rte_ipv4_hdr *ipv4_hdr; 31 struct rte_ipv6_hdr *ipv6_hdr; 32 uint32_t tcp_or_udp; 33 uint32_t l3_ptypes; 34 35 tcp_or_udp = pkt->packet_type & (RTE_PTYPE_L4_TCP | RTE_PTYPE_L4_UDP); 36 l3_ptypes = pkt->packet_type & RTE_PTYPE_L3_MASK; 37 38 if (tcp_or_udp && (l3_ptypes == RTE_PTYPE_L3_IPV4)) { 39 40 /* Handle IPv4 headers.*/ 41 ipv4_hdr = rte_pktmbuf_mtod_offset(pkt, struct rte_ipv4_hdr *, 42 sizeof(struct rte_ether_hdr)); 43 44 next_hop = em_get_ipv4_dst_port(ipv4_hdr, portid, 45 qconf->ipv4_lookup_struct); 46 47 if (next_hop >= RTE_MAX_ETHPORTS || 48 (enabled_port_mask & 1 << next_hop) == 0) 49 next_hop = portid; 50 51 return next_hop; 52 53 } else if (tcp_or_udp && (l3_ptypes == RTE_PTYPE_L3_IPV6)) { 54 55 /* Handle IPv6 headers.*/ 56 ipv6_hdr = rte_pktmbuf_mtod_offset(pkt, struct rte_ipv6_hdr *, 57 sizeof(struct rte_ether_hdr)); 58 59 next_hop = em_get_ipv6_dst_port(ipv6_hdr, portid, 60 qconf->ipv6_lookup_struct); 61 62 if (next_hop >= RTE_MAX_ETHPORTS || 63 (enabled_port_mask & 1 << next_hop) == 0) 64 next_hop = portid; 65 66 return next_hop; 67 68 } 69 70 return portid; 71 } 72 73 /* 74 * Buffer optimized handling of packets, invoked 75 * from main_loop. 76 */ 77 static inline void 78 l3fwd_em_send_packets(int nb_rx, struct rte_mbuf **pkts_burst, 79 uint16_t portid, struct lcore_conf *qconf) 80 { 81 int32_t i, j; 82 uint16_t dst_port[SENDM_PORT_OVERHEAD(MAX_PKT_BURST)]; 83 84 if (nb_rx > 0) { 85 rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[0], 86 struct rte_ether_hdr *) + 1); 87 } 88 89 for (i = 1, j = 0; j < nb_rx; i++, j++) { 90 if (i < nb_rx) { 91 rte_prefetch0(rte_pktmbuf_mtod( 92 pkts_burst[i], 93 struct rte_ether_hdr *) + 1); 94 } 95 dst_port[j] = em_get_dst_port(qconf, pkts_burst[j], portid); 96 } 97 98 send_packets_multi(qconf, pkts_burst, dst_port, nb_rx); 99 } 100 101 /* 102 * Buffer optimized handling of events, invoked 103 * from main_loop. 104 */ 105 static inline void 106 l3fwd_em_process_events(int nb_rx, struct rte_event **events, 107 struct lcore_conf *qconf) 108 { 109 int32_t i, j; 110 111 rte_prefetch0(rte_pktmbuf_mtod(events[0]->mbuf, 112 struct rte_ether_hdr *) + 1); 113 114 for (i = 1, j = 0; j < nb_rx; i++, j++) { 115 struct rte_mbuf *mbuf = events[j]->mbuf; 116 uint16_t port; 117 118 if (i < nb_rx) { 119 rte_prefetch0(rte_pktmbuf_mtod( 120 events[i]->mbuf, 121 struct rte_ether_hdr *) + 1); 122 } 123 port = mbuf->port; 124 mbuf->port = em_get_dst_port(qconf, mbuf, mbuf->port); 125 process_packet(mbuf, &mbuf->port); 126 if (mbuf->port == BAD_PORT) 127 mbuf->port = port; 128 } 129 } 130 131 static inline void 132 l3fwd_em_process_event_vector(struct rte_event_vector *vec, 133 struct lcore_conf *qconf, uint16_t *dst_ports) 134 { 135 const uint8_t attr_valid = vec->attr_valid; 136 struct rte_mbuf **mbufs = vec->mbufs; 137 int32_t i, j; 138 139 rte_prefetch0(rte_pktmbuf_mtod(mbufs[0], struct rte_ether_hdr *) + 1); 140 141 for (i = 0, j = 1; i < vec->nb_elem; i++, j++) { 142 if (j < vec->nb_elem) 143 rte_prefetch0(rte_pktmbuf_mtod(mbufs[j], 144 struct rte_ether_hdr *) + 145 1); 146 dst_ports[i] = em_get_dst_port(qconf, mbufs[i], 147 attr_valid ? vec->port : 148 mbufs[i]->port); 149 } 150 j = RTE_ALIGN_FLOOR(vec->nb_elem, FWDSTEP); 151 152 for (i = 0; i != j; i += FWDSTEP) 153 processx4_step3(&vec->mbufs[i], &dst_ports[i]); 154 for (; i < vec->nb_elem; i++) 155 process_packet(vec->mbufs[i], &dst_ports[i]); 156 157 process_event_vector(vec, dst_ports); 158 } 159 160 #endif /* __L3FWD_EM_SEQUENTIAL_H__ */ 161