xref: /dpdk/examples/l3fwd/l3fwd_common.h (revision ebab0e8b2257aa049dd35dedc7efd230b0f45b88)
18f4127e4SGavin Hu /* SPDX-License-Identifier: BSD-3-Clause
28f4127e4SGavin Hu  * Copyright(c) 2016-2018 Intel Corporation.
38f4127e4SGavin Hu  * Copyright(c) 2017-2018 Linaro Limited.
466d8bc00SJianbo Liu  */
566d8bc00SJianbo Liu 
666d8bc00SJianbo Liu 
766d8bc00SJianbo Liu #ifndef _L3FWD_COMMON_H_
866d8bc00SJianbo Liu #define _L3FWD_COMMON_H_
966d8bc00SJianbo Liu 
10732115ceSRahul Bhansali #include "pkt_group.h"
11732115ceSRahul Bhansali 
1266d8bc00SJianbo Liu #ifdef DO_RFC_1812_CHECKS
1366d8bc00SJianbo Liu 
1466d8bc00SJianbo Liu #define	IPV4_MIN_VER_IHL	0x45
1566d8bc00SJianbo Liu #define	IPV4_MAX_VER_IHL	0x4f
1666d8bc00SJianbo Liu #define	IPV4_MAX_VER_IHL_DIFF	(IPV4_MAX_VER_IHL - IPV4_MIN_VER_IHL)
1766d8bc00SJianbo Liu 
1866d8bc00SJianbo Liu /* Minimum value of IPV4 total length (20B) in network byte order. */
19a7c528e5SOlivier Matz #define	IPV4_MIN_LEN_BE	(sizeof(struct rte_ipv4_hdr) << 8)
2066d8bc00SJianbo Liu 
2166d8bc00SJianbo Liu /*
22*ebab0e8bSKonstantin Ananyev  * send_packet_multi() specific number of dest ports
23*ebab0e8bSKonstantin Ananyev  * due to implementation we need to allocate array bigger then
24*ebab0e8bSKonstantin Ananyev  * actual max number of elements in the array.
25*ebab0e8bSKonstantin Ananyev  */
26*ebab0e8bSKonstantin Ananyev #define SENDM_PORT_OVERHEAD(x) (x)
27*ebab0e8bSKonstantin Ananyev 
28*ebab0e8bSKonstantin Ananyev /*
2966d8bc00SJianbo Liu  * From http://www.rfc-editor.org/rfc/rfc1812.txt section 5.2.2:
3066d8bc00SJianbo Liu  * - The IP version number must be 4.
3166d8bc00SJianbo Liu  * - The IP header length field must be large enough to hold the
3266d8bc00SJianbo Liu  *    minimum length legal IP datagram (20 bytes = 5 words).
3366d8bc00SJianbo Liu  * - The IP total length field must be large enough to hold the IP
3466d8bc00SJianbo Liu  *   datagram header, whose length is specified in the IP header length
3566d8bc00SJianbo Liu  *   field.
3666d8bc00SJianbo Liu  * If we encounter invalid IPV4 packet, then set destination port for it
3766d8bc00SJianbo Liu  * to BAD_PORT value.
3866d8bc00SJianbo Liu  */
3966d8bc00SJianbo Liu static __rte_always_inline void
40a7c528e5SOlivier Matz rfc1812_process(struct rte_ipv4_hdr *ipv4_hdr, uint16_t *dp, uint32_t ptype)
4166d8bc00SJianbo Liu {
4266d8bc00SJianbo Liu 	uint8_t ihl;
4366d8bc00SJianbo Liu 
4466d8bc00SJianbo Liu 	if (RTE_ETH_IS_IPV4_HDR(ptype)) {
4566d8bc00SJianbo Liu 		ihl = ipv4_hdr->version_ihl - IPV4_MIN_VER_IHL;
4666d8bc00SJianbo Liu 
4766d8bc00SJianbo Liu 		ipv4_hdr->time_to_live--;
4866d8bc00SJianbo Liu 		ipv4_hdr->hdr_checksum++;
4966d8bc00SJianbo Liu 
5066d8bc00SJianbo Liu 		if (ihl > IPV4_MAX_VER_IHL_DIFF ||
5166d8bc00SJianbo Liu 				((uint8_t)ipv4_hdr->total_length == 0 &&
5266d8bc00SJianbo Liu 				ipv4_hdr->total_length < IPV4_MIN_LEN_BE))
5366d8bc00SJianbo Liu 			dp[0] = BAD_PORT;
5466d8bc00SJianbo Liu 
5566d8bc00SJianbo Liu 	}
5666d8bc00SJianbo Liu }
5766d8bc00SJianbo Liu 
5866d8bc00SJianbo Liu #else
5966d8bc00SJianbo Liu #define	rfc1812_process(mb, dp, ptype)	do { } while (0)
6066d8bc00SJianbo Liu #endif /* DO_RFC_1812_CHECKS */
6166d8bc00SJianbo Liu 
6266d8bc00SJianbo Liu static __rte_always_inline void
63f8244c63SZhiyong Yang send_packetsx4(struct lcore_conf *qconf, uint16_t port, struct rte_mbuf *m[],
6466d8bc00SJianbo Liu 		uint32_t num)
6566d8bc00SJianbo Liu {
6666d8bc00SJianbo Liu 	uint32_t len, j, n;
6766d8bc00SJianbo Liu 
6866d8bc00SJianbo Liu 	len = qconf->tx_mbufs[port].len;
6966d8bc00SJianbo Liu 
7066d8bc00SJianbo Liu 	/*
7166d8bc00SJianbo Liu 	 * If TX buffer for that queue is empty, and we have enough packets,
7266d8bc00SJianbo Liu 	 * then send them straightway.
7366d8bc00SJianbo Liu 	 */
7466d8bc00SJianbo Liu 	if (num >= MAX_TX_BURST && len == 0) {
7566d8bc00SJianbo Liu 		n = rte_eth_tx_burst(port, qconf->tx_queue_id[port], m, num);
7666d8bc00SJianbo Liu 		if (unlikely(n < num)) {
7766d8bc00SJianbo Liu 			do {
7866d8bc00SJianbo Liu 				rte_pktmbuf_free(m[n]);
7966d8bc00SJianbo Liu 			} while (++n < num);
8066d8bc00SJianbo Liu 		}
8166d8bc00SJianbo Liu 		return;
8266d8bc00SJianbo Liu 	}
8366d8bc00SJianbo Liu 
8466d8bc00SJianbo Liu 	/*
8566d8bc00SJianbo Liu 	 * Put packets into TX buffer for that queue.
8666d8bc00SJianbo Liu 	 */
8766d8bc00SJianbo Liu 
8866d8bc00SJianbo Liu 	n = len + num;
8966d8bc00SJianbo Liu 	n = (n > MAX_PKT_BURST) ? MAX_PKT_BURST - len : num;
9066d8bc00SJianbo Liu 
9166d8bc00SJianbo Liu 	j = 0;
9266d8bc00SJianbo Liu 	switch (n % FWDSTEP) {
9366d8bc00SJianbo Liu 	while (j < n) {
9466d8bc00SJianbo Liu 	case 0:
9566d8bc00SJianbo Liu 		qconf->tx_mbufs[port].m_table[len + j] = m[j];
9666d8bc00SJianbo Liu 		j++;
9766d8bc00SJianbo Liu 		/* fallthrough */
9866d8bc00SJianbo Liu 	case 3:
9966d8bc00SJianbo Liu 		qconf->tx_mbufs[port].m_table[len + j] = m[j];
10066d8bc00SJianbo Liu 		j++;
10166d8bc00SJianbo Liu 		/* fallthrough */
10266d8bc00SJianbo Liu 	case 2:
10366d8bc00SJianbo Liu 		qconf->tx_mbufs[port].m_table[len + j] = m[j];
10466d8bc00SJianbo Liu 		j++;
10566d8bc00SJianbo Liu 		/* fallthrough */
10666d8bc00SJianbo Liu 	case 1:
10766d8bc00SJianbo Liu 		qconf->tx_mbufs[port].m_table[len + j] = m[j];
10866d8bc00SJianbo Liu 		j++;
10966d8bc00SJianbo Liu 	}
11066d8bc00SJianbo Liu 	}
11166d8bc00SJianbo Liu 
11266d8bc00SJianbo Liu 	len += n;
11366d8bc00SJianbo Liu 
11466d8bc00SJianbo Liu 	/* enough pkts to be sent */
11566d8bc00SJianbo Liu 	if (unlikely(len == MAX_PKT_BURST)) {
11666d8bc00SJianbo Liu 
11766d8bc00SJianbo Liu 		send_burst(qconf, MAX_PKT_BURST, port);
11866d8bc00SJianbo Liu 
11966d8bc00SJianbo Liu 		/* copy rest of the packets into the TX buffer. */
12066d8bc00SJianbo Liu 		len = num - n;
1210490d69dSRahul Bhansali 		if (len == 0)
1220490d69dSRahul Bhansali 			goto exit;
1230490d69dSRahul Bhansali 
12466d8bc00SJianbo Liu 		j = 0;
12566d8bc00SJianbo Liu 		switch (len % FWDSTEP) {
12666d8bc00SJianbo Liu 		while (j < len) {
12766d8bc00SJianbo Liu 		case 0:
12866d8bc00SJianbo Liu 			qconf->tx_mbufs[port].m_table[j] = m[n + j];
12966d8bc00SJianbo Liu 			j++;
13066d8bc00SJianbo Liu 			/* fallthrough */
13166d8bc00SJianbo Liu 		case 3:
13266d8bc00SJianbo Liu 			qconf->tx_mbufs[port].m_table[j] = m[n + j];
13366d8bc00SJianbo Liu 			j++;
13466d8bc00SJianbo Liu 			/* fallthrough */
13566d8bc00SJianbo Liu 		case 2:
13666d8bc00SJianbo Liu 			qconf->tx_mbufs[port].m_table[j] = m[n + j];
13766d8bc00SJianbo Liu 			j++;
13866d8bc00SJianbo Liu 			/* fallthrough */
13966d8bc00SJianbo Liu 		case 1:
14066d8bc00SJianbo Liu 			qconf->tx_mbufs[port].m_table[j] = m[n + j];
14166d8bc00SJianbo Liu 			j++;
14266d8bc00SJianbo Liu 		}
14366d8bc00SJianbo Liu 		}
14466d8bc00SJianbo Liu 	}
14566d8bc00SJianbo Liu 
1460490d69dSRahul Bhansali exit:
14766d8bc00SJianbo Liu 	qconf->tx_mbufs[port].len = len;
14866d8bc00SJianbo Liu }
14966d8bc00SJianbo Liu 
15066d8bc00SJianbo Liu #endif /* _L3FWD_COMMON_H_ */
151