xref: /dpdk/examples/l3fwd/l3fwd_em.h (revision 4b01cabfb09b3284826c0134a5f1356c59dea24b)
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 *)&eth_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 			&eth_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 *)&eth_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 			&eth_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