xref: /dpdk/examples/l3fwd/l3fwd_em.h (revision 68a03efeed657e6e05f281479b33b51102797e15)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2016 Intel Corporation
3  */
4 
5 #ifndef __L3FWD_EM_H__
6 #define __L3FWD_EM_H__
7 
8 static __rte_always_inline uint16_t
9 l3fwd_em_handle_ipv4(struct rte_mbuf *m, uint16_t portid,
10 		     struct rte_ether_hdr *eth_hdr, struct lcore_conf *qconf)
11 {
12 	struct rte_ipv4_hdr *ipv4_hdr;
13 	uint16_t dst_port;
14 
15 	/* Handle IPv4 headers.*/
16 	ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *,
17 			sizeof(struct rte_ether_hdr));
18 
19 #ifdef DO_RFC_1812_CHECKS
20 	/* Check to make sure the packet is valid (RFC1812) */
21 	if (is_valid_ipv4_pkt(ipv4_hdr, m->pkt_len) < 0) {
22 		rte_pktmbuf_free(m);
23 		return BAD_PORT;
24 	}
25 #endif
26 	dst_port = em_get_ipv4_dst_port(ipv4_hdr, portid,
27 			qconf->ipv4_lookup_struct);
28 
29 	if (dst_port >= RTE_MAX_ETHPORTS ||
30 			(enabled_port_mask & 1 << dst_port) == 0)
31 		dst_port = portid;
32 
33 #ifdef DO_RFC_1812_CHECKS
34 	/* Update time to live and header checksum */
35 	--(ipv4_hdr->time_to_live);
36 	++(ipv4_hdr->hdr_checksum);
37 #endif
38 	/* dst addr */
39 	*(uint64_t *)&eth_hdr->d_addr = dest_eth_addr[dst_port];
40 
41 	/* src addr */
42 	rte_ether_addr_copy(&ports_eth_addr[dst_port],
43 			&eth_hdr->s_addr);
44 
45 	return dst_port;
46 }
47 
48 static __rte_always_inline uint16_t
49 l3fwd_em_handle_ipv6(struct rte_mbuf *m, uint16_t portid,
50 		struct rte_ether_hdr *eth_hdr, struct lcore_conf *qconf)
51 {
52 	/* Handle IPv6 headers.*/
53 	struct rte_ipv6_hdr *ipv6_hdr;
54 	uint16_t dst_port;
55 
56 	ipv6_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv6_hdr *,
57 			sizeof(struct rte_ether_hdr));
58 
59 	dst_port = em_get_ipv6_dst_port(ipv6_hdr, portid,
60 			qconf->ipv6_lookup_struct);
61 
62 	if (dst_port >= RTE_MAX_ETHPORTS ||
63 			(enabled_port_mask & 1 << dst_port) == 0)
64 		dst_port = portid;
65 
66 	/* dst addr */
67 	*(uint64_t *)&eth_hdr->d_addr = dest_eth_addr[dst_port];
68 
69 	/* src addr */
70 	rte_ether_addr_copy(&ports_eth_addr[dst_port],
71 			&eth_hdr->s_addr);
72 
73 	return dst_port;
74 }
75 
76 static __rte_always_inline void
77 l3fwd_em_simple_forward(struct rte_mbuf *m, uint16_t portid,
78 		struct lcore_conf *qconf)
79 {
80 	struct rte_ether_hdr *eth_hdr;
81 	uint16_t dst_port;
82 	uint32_t tcp_or_udp;
83 	uint32_t l3_ptypes;
84 
85 	eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
86 	tcp_or_udp = m->packet_type & (RTE_PTYPE_L4_TCP | RTE_PTYPE_L4_UDP);
87 	l3_ptypes = m->packet_type & RTE_PTYPE_L3_MASK;
88 
89 	if (tcp_or_udp && (l3_ptypes == RTE_PTYPE_L3_IPV4)) {
90 		dst_port = l3fwd_em_handle_ipv4(m, portid, eth_hdr, qconf);
91 		send_single_packet(qconf, m, dst_port);
92 	} else if (tcp_or_udp && (l3_ptypes == RTE_PTYPE_L3_IPV6)) {
93 		dst_port = l3fwd_em_handle_ipv6(m, portid, eth_hdr, qconf);
94 		send_single_packet(qconf, m, dst_port);
95 	} else {
96 		/* Free the mbuf that contains non-IPV4/IPV6 packet */
97 		rte_pktmbuf_free(m);
98 	}
99 }
100 
101 static __rte_always_inline void
102 l3fwd_em_simple_process(struct rte_mbuf *m, struct lcore_conf *qconf)
103 {
104 	struct rte_ether_hdr *eth_hdr;
105 	uint32_t tcp_or_udp;
106 	uint32_t l3_ptypes;
107 
108 	eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
109 	tcp_or_udp = m->packet_type & (RTE_PTYPE_L4_TCP | RTE_PTYPE_L4_UDP);
110 	l3_ptypes = m->packet_type & RTE_PTYPE_L3_MASK;
111 
112 	if (tcp_or_udp && (l3_ptypes == RTE_PTYPE_L3_IPV4))
113 		m->port = l3fwd_em_handle_ipv4(m, m->port, eth_hdr, qconf);
114 	else if (tcp_or_udp && (l3_ptypes == RTE_PTYPE_L3_IPV6))
115 		m->port = l3fwd_em_handle_ipv6(m, m->port, eth_hdr, qconf);
116 	else
117 		m->port = BAD_PORT;
118 }
119 
120 /*
121  * Buffer non-optimized handling of packets, invoked
122  * from main_loop.
123  */
124 static inline void
125 l3fwd_em_no_opt_send_packets(int nb_rx, struct rte_mbuf **pkts_burst,
126 			uint16_t portid, struct lcore_conf *qconf)
127 {
128 	int32_t j;
129 
130 	/* Prefetch first packets */
131 	for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++)
132 		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[j], void *));
133 
134 	/*
135 	 * Prefetch and forward already prefetched
136 	 * packets.
137 	 */
138 	for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) {
139 		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[
140 				j + PREFETCH_OFFSET], void *));
141 		l3fwd_em_simple_forward(pkts_burst[j], portid, qconf);
142 	}
143 
144 	/* Forward remaining prefetched packets */
145 	for (; j < nb_rx; j++)
146 		l3fwd_em_simple_forward(pkts_burst[j], portid, qconf);
147 }
148 
149 /*
150  * Buffer non-optimized handling of events, invoked
151  * from main_loop.
152  */
153 static inline void
154 l3fwd_em_no_opt_process_events(int nb_rx, struct rte_event **events,
155 			       struct lcore_conf *qconf)
156 {
157 	int32_t j;
158 
159 	/* Prefetch first packets */
160 	for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++)
161 		rte_prefetch0(rte_pktmbuf_mtod(events[j]->mbuf, void *));
162 
163 	/*
164 	 * Prefetch and forward already prefetched
165 	 * packets.
166 	 */
167 	for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) {
168 		rte_prefetch0(rte_pktmbuf_mtod(events[
169 				j + PREFETCH_OFFSET]->mbuf, void *));
170 		l3fwd_em_simple_process(events[j]->mbuf, qconf);
171 	}
172 
173 	/* Forward remaining prefetched packets */
174 	for (; j < nb_rx; j++)
175 		l3fwd_em_simple_process(events[j]->mbuf, qconf);
176 }
177 
178 #endif /* __L3FWD_EM_H__ */
179