13998e2a0SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
23998e2a0SBruce Richardson * Copyright(c) 2010-2016 Intel Corporation
3268888b5SRavi Kerur */
4268888b5SRavi Kerur
5268888b5SRavi Kerur #ifndef __L3FWD_EM_H__
6268888b5SRavi Kerur #define __L3FWD_EM_H__
7268888b5SRavi Kerur
8c9d54b82SBruce Richardson #include <rte_common.h>
9c9d54b82SBruce Richardson
10a434a02dSPavan Nikhilesh static __rte_always_inline uint16_t
l3fwd_em_handle_ipv4(struct rte_mbuf * m,uint16_t portid,struct rte_ether_hdr * eth_hdr,struct lcore_conf * qconf)11a434a02dSPavan Nikhilesh l3fwd_em_handle_ipv4(struct rte_mbuf *m, uint16_t portid,
12a434a02dSPavan Nikhilesh struct rte_ether_hdr *eth_hdr, struct lcore_conf *qconf)
1394c54b41STomasz Kulasek {
14a7c528e5SOlivier Matz struct rte_ipv4_hdr *ipv4_hdr;
15f8244c63SZhiyong Yang uint16_t dst_port;
1694c54b41STomasz Kulasek
1794c54b41STomasz Kulasek /* Handle IPv4 headers.*/
18a7c528e5SOlivier Matz ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *,
196d13ea8eSOlivier Matz sizeof(struct rte_ether_hdr));
2094c54b41STomasz Kulasek
2194c54b41STomasz Kulasek #ifdef DO_RFC_1812_CHECKS
2294c54b41STomasz Kulasek /* Check to make sure the packet is valid (RFC1812) */
23*4b01cabfSTrevor Tao if (is_valid_ipv4_pkt(ipv4_hdr, m->pkt_len, m->ol_flags) < 0) {
2494c54b41STomasz Kulasek rte_pktmbuf_free(m);
25a434a02dSPavan Nikhilesh return BAD_PORT;
2694c54b41STomasz Kulasek }
2794c54b41STomasz Kulasek #endif
2894c54b41STomasz Kulasek dst_port = em_get_ipv4_dst_port(ipv4_hdr, portid,
2994c54b41STomasz Kulasek qconf->ipv4_lookup_struct);
3094c54b41STomasz Kulasek
3194c54b41STomasz Kulasek if (dst_port >= RTE_MAX_ETHPORTS ||
3294c54b41STomasz Kulasek (enabled_port_mask & 1 << dst_port) == 0)
3394c54b41STomasz Kulasek dst_port = portid;
3494c54b41STomasz Kulasek
3594c54b41STomasz Kulasek #ifdef DO_RFC_1812_CHECKS
3694c54b41STomasz Kulasek /* Update time to live and header checksum */
3794c54b41STomasz Kulasek --(ipv4_hdr->time_to_live);
3894c54b41STomasz Kulasek ++(ipv4_hdr->hdr_checksum);
3994c54b41STomasz Kulasek #endif
4094c54b41STomasz Kulasek /* dst addr */
4104d43857SDmitry Kozlyuk *(uint64_t *)ð_hdr->dst_addr = dest_eth_addr[dst_port];
4294c54b41STomasz Kulasek
4394c54b41STomasz Kulasek /* src addr */
44538da7a1SOlivier Matz rte_ether_addr_copy(&ports_eth_addr[dst_port],
4504d43857SDmitry Kozlyuk ð_hdr->src_addr);
4694c54b41STomasz Kulasek
47a434a02dSPavan Nikhilesh return dst_port;
48a434a02dSPavan Nikhilesh }
49a434a02dSPavan Nikhilesh
50a434a02dSPavan Nikhilesh static __rte_always_inline uint16_t
l3fwd_em_handle_ipv6(struct rte_mbuf * m,uint16_t portid,struct rte_ether_hdr * eth_hdr,struct lcore_conf * qconf)51a434a02dSPavan Nikhilesh l3fwd_em_handle_ipv6(struct rte_mbuf *m, uint16_t portid,
52a434a02dSPavan Nikhilesh struct rte_ether_hdr *eth_hdr, struct lcore_conf *qconf)
53a434a02dSPavan Nikhilesh {
5494c54b41STomasz Kulasek /* Handle IPv6 headers.*/
55a7c528e5SOlivier Matz struct rte_ipv6_hdr *ipv6_hdr;
56a434a02dSPavan Nikhilesh uint16_t dst_port;
5794c54b41STomasz Kulasek
58a7c528e5SOlivier Matz ipv6_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv6_hdr *,
596d13ea8eSOlivier Matz sizeof(struct rte_ether_hdr));
6094c54b41STomasz Kulasek
6194c54b41STomasz Kulasek dst_port = em_get_ipv6_dst_port(ipv6_hdr, portid,
6294c54b41STomasz Kulasek qconf->ipv6_lookup_struct);
6394c54b41STomasz Kulasek
6494c54b41STomasz Kulasek if (dst_port >= RTE_MAX_ETHPORTS ||
6594c54b41STomasz Kulasek (enabled_port_mask & 1 << dst_port) == 0)
6694c54b41STomasz Kulasek dst_port = portid;
6794c54b41STomasz Kulasek
6894c54b41STomasz Kulasek /* dst addr */
6904d43857SDmitry Kozlyuk *(uint64_t *)ð_hdr->dst_addr = dest_eth_addr[dst_port];
7094c54b41STomasz Kulasek
7194c54b41STomasz Kulasek /* src addr */
72538da7a1SOlivier Matz rte_ether_addr_copy(&ports_eth_addr[dst_port],
7304d43857SDmitry Kozlyuk ð_hdr->src_addr);
7494c54b41STomasz Kulasek
75a434a02dSPavan Nikhilesh return dst_port;
76a434a02dSPavan Nikhilesh }
77a434a02dSPavan Nikhilesh
78a434a02dSPavan Nikhilesh static __rte_always_inline void
l3fwd_em_simple_forward(struct rte_mbuf * m,uint16_t portid,struct lcore_conf * qconf)79a434a02dSPavan Nikhilesh l3fwd_em_simple_forward(struct rte_mbuf *m, uint16_t portid,
80a434a02dSPavan Nikhilesh struct lcore_conf *qconf)
81a434a02dSPavan Nikhilesh {
82a434a02dSPavan Nikhilesh struct rte_ether_hdr *eth_hdr;
83a434a02dSPavan Nikhilesh uint16_t dst_port;
84a434a02dSPavan Nikhilesh uint32_t tcp_or_udp;
85a434a02dSPavan Nikhilesh uint32_t l3_ptypes;
86a434a02dSPavan Nikhilesh
87a434a02dSPavan Nikhilesh eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
88a434a02dSPavan Nikhilesh tcp_or_udp = m->packet_type & (RTE_PTYPE_L4_TCP | RTE_PTYPE_L4_UDP);
89a434a02dSPavan Nikhilesh l3_ptypes = m->packet_type & RTE_PTYPE_L3_MASK;
90a434a02dSPavan Nikhilesh
91a434a02dSPavan Nikhilesh if (tcp_or_udp && (l3_ptypes == RTE_PTYPE_L3_IPV4)) {
92a434a02dSPavan Nikhilesh dst_port = l3fwd_em_handle_ipv4(m, portid, eth_hdr, qconf);
93a434a02dSPavan Nikhilesh send_single_packet(qconf, m, dst_port);
94a434a02dSPavan Nikhilesh } else if (tcp_or_udp && (l3_ptypes == RTE_PTYPE_L3_IPV6)) {
95a434a02dSPavan Nikhilesh dst_port = l3fwd_em_handle_ipv6(m, portid, eth_hdr, qconf);
9694c54b41STomasz Kulasek send_single_packet(qconf, m, dst_port);
9794c54b41STomasz Kulasek } else {
9894c54b41STomasz Kulasek /* Free the mbuf that contains non-IPV4/IPV6 packet */
9994c54b41STomasz Kulasek rte_pktmbuf_free(m);
10094c54b41STomasz Kulasek }
10194c54b41STomasz Kulasek }
10294c54b41STomasz Kulasek
103450356b2SPavan Nikhilesh static __rte_always_inline uint16_t
l3fwd_em_simple_process(struct rte_mbuf * m,struct lcore_conf * qconf)104a434a02dSPavan Nikhilesh l3fwd_em_simple_process(struct rte_mbuf *m, struct lcore_conf *qconf)
105a434a02dSPavan Nikhilesh {
106a434a02dSPavan Nikhilesh struct rte_ether_hdr *eth_hdr;
107a434a02dSPavan Nikhilesh uint32_t tcp_or_udp;
108a434a02dSPavan Nikhilesh uint32_t l3_ptypes;
109a434a02dSPavan Nikhilesh
110a434a02dSPavan Nikhilesh eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
111a434a02dSPavan Nikhilesh tcp_or_udp = m->packet_type & (RTE_PTYPE_L4_TCP | RTE_PTYPE_L4_UDP);
112a434a02dSPavan Nikhilesh l3_ptypes = m->packet_type & RTE_PTYPE_L3_MASK;
113a434a02dSPavan Nikhilesh
114a434a02dSPavan Nikhilesh if (tcp_or_udp && (l3_ptypes == RTE_PTYPE_L3_IPV4))
115a434a02dSPavan Nikhilesh m->port = l3fwd_em_handle_ipv4(m, m->port, eth_hdr, qconf);
116a434a02dSPavan Nikhilesh else if (tcp_or_udp && (l3_ptypes == RTE_PTYPE_L3_IPV6))
117a434a02dSPavan Nikhilesh m->port = l3fwd_em_handle_ipv6(m, m->port, eth_hdr, qconf);
118a434a02dSPavan Nikhilesh else
119a434a02dSPavan Nikhilesh m->port = BAD_PORT;
120450356b2SPavan Nikhilesh
121450356b2SPavan Nikhilesh return m->port;
122a434a02dSPavan Nikhilesh }
123a434a02dSPavan Nikhilesh
124268888b5SRavi Kerur /*
125268888b5SRavi Kerur * Buffer non-optimized handling of packets, invoked
126268888b5SRavi Kerur * from main_loop.
127268888b5SRavi Kerur */
128268888b5SRavi Kerur static inline void
l3fwd_em_no_opt_send_packets(int nb_rx,struct rte_mbuf ** pkts_burst,uint16_t portid,struct lcore_conf * qconf)129268888b5SRavi Kerur l3fwd_em_no_opt_send_packets(int nb_rx, struct rte_mbuf **pkts_burst,
130f8244c63SZhiyong Yang uint16_t portid, struct lcore_conf *qconf)
131268888b5SRavi Kerur {
132268888b5SRavi Kerur int32_t j;
133268888b5SRavi Kerur
134268888b5SRavi Kerur /* Prefetch first packets */
135268888b5SRavi Kerur for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++)
136268888b5SRavi Kerur rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[j], void *));
137268888b5SRavi Kerur
138268888b5SRavi Kerur /*
139268888b5SRavi Kerur * Prefetch and forward already prefetched
140268888b5SRavi Kerur * packets.
141268888b5SRavi Kerur */
142268888b5SRavi Kerur for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) {
143268888b5SRavi Kerur rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[
144268888b5SRavi Kerur j + PREFETCH_OFFSET], void *));
145268888b5SRavi Kerur l3fwd_em_simple_forward(pkts_burst[j], portid, qconf);
146268888b5SRavi Kerur }
147268888b5SRavi Kerur
148268888b5SRavi Kerur /* Forward remaining prefetched packets */
149268888b5SRavi Kerur for (; j < nb_rx; j++)
150268888b5SRavi Kerur l3fwd_em_simple_forward(pkts_burst[j], portid, qconf);
151268888b5SRavi Kerur }
152268888b5SRavi Kerur
153a434a02dSPavan Nikhilesh /*
154a434a02dSPavan Nikhilesh * Buffer non-optimized handling of events, invoked
155a434a02dSPavan Nikhilesh * from main_loop.
156a434a02dSPavan Nikhilesh */
157a434a02dSPavan Nikhilesh static inline void
l3fwd_em_no_opt_process_events(int nb_rx,struct rte_event ** events,struct lcore_conf * qconf)158a434a02dSPavan Nikhilesh l3fwd_em_no_opt_process_events(int nb_rx, struct rte_event **events,
159a434a02dSPavan Nikhilesh struct lcore_conf *qconf)
160a434a02dSPavan Nikhilesh {
161a434a02dSPavan Nikhilesh int32_t j;
162a434a02dSPavan Nikhilesh
163a434a02dSPavan Nikhilesh /* Prefetch first packets */
164a434a02dSPavan Nikhilesh for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++)
165a434a02dSPavan Nikhilesh rte_prefetch0(rte_pktmbuf_mtod(events[j]->mbuf, void *));
166a434a02dSPavan Nikhilesh
167a434a02dSPavan Nikhilesh /*
168a434a02dSPavan Nikhilesh * Prefetch and forward already prefetched
169a434a02dSPavan Nikhilesh * packets.
170a434a02dSPavan Nikhilesh */
171a434a02dSPavan Nikhilesh for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) {
172a434a02dSPavan Nikhilesh rte_prefetch0(rte_pktmbuf_mtod(events[
173a434a02dSPavan Nikhilesh j + PREFETCH_OFFSET]->mbuf, void *));
174a434a02dSPavan Nikhilesh l3fwd_em_simple_process(events[j]->mbuf, qconf);
175a434a02dSPavan Nikhilesh }
176a434a02dSPavan Nikhilesh
177a434a02dSPavan Nikhilesh /* Forward remaining prefetched packets */
178a434a02dSPavan Nikhilesh for (; j < nb_rx; j++)
179a434a02dSPavan Nikhilesh l3fwd_em_simple_process(events[j]->mbuf, qconf);
180a434a02dSPavan Nikhilesh }
181a434a02dSPavan Nikhilesh
182e8adca19SShijith Thotton static inline void
l3fwd_em_no_opt_process_event_vector(struct rte_event_vector * vec,struct lcore_conf * qconf,uint16_t * dst_ports)183e8adca19SShijith Thotton l3fwd_em_no_opt_process_event_vector(struct rte_event_vector *vec,
184450356b2SPavan Nikhilesh struct lcore_conf *qconf,
185450356b2SPavan Nikhilesh uint16_t *dst_ports)
186e8adca19SShijith Thotton {
187e8adca19SShijith Thotton struct rte_mbuf **mbufs = vec->mbufs;
188e8adca19SShijith Thotton int32_t i;
189e8adca19SShijith Thotton
190e8adca19SShijith Thotton /* Prefetch first packets */
191e8adca19SShijith Thotton for (i = 0; i < PREFETCH_OFFSET && i < vec->nb_elem; i++)
192e8adca19SShijith Thotton rte_prefetch0(rte_pktmbuf_mtod(mbufs[i], void *));
193e8adca19SShijith Thotton
194e8adca19SShijith Thotton /*
195e8adca19SShijith Thotton * Prefetch and forward already prefetched packets.
196e8adca19SShijith Thotton */
197450356b2SPavan Nikhilesh for (i = 0; i < (vec->nb_elem - PREFETCH_OFFSET); i++) {
198e8adca19SShijith Thotton rte_prefetch0(
199e8adca19SShijith Thotton rte_pktmbuf_mtod(mbufs[i + PREFETCH_OFFSET], void *));
200450356b2SPavan Nikhilesh dst_ports[i] = l3fwd_em_simple_process(mbufs[i], qconf);
201e8adca19SShijith Thotton }
202e8adca19SShijith Thotton
203e8adca19SShijith Thotton /* Forward remaining prefetched packets */
204450356b2SPavan Nikhilesh for (; i < vec->nb_elem; i++)
205450356b2SPavan Nikhilesh dst_ports[i] = l3fwd_em_simple_process(mbufs[i], qconf);
206450356b2SPavan Nikhilesh
207450356b2SPavan Nikhilesh process_event_vector(vec, dst_ports);
208e8adca19SShijith Thotton }
209e8adca19SShijith Thotton
210268888b5SRavi Kerur #endif /* __L3FWD_EM_H__ */
211