xref: /dpdk/lib/node/ip4_rewrite.c (revision a2bc05846c5bdd839ba9d13e65b02b981ea98130)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(C) 2020 Marvell International Ltd.
399a2dd95SBruce Richardson  */
499a2dd95SBruce Richardson 
599a2dd95SBruce Richardson #include <rte_ethdev.h>
699a2dd95SBruce Richardson #include <rte_ether.h>
799a2dd95SBruce Richardson #include <rte_graph.h>
8*a2bc0584SZhirun Yan #include <rte_graph_worker.h>
999a2dd95SBruce Richardson #include <rte_ip.h>
1099a2dd95SBruce Richardson #include <rte_malloc.h>
1199a2dd95SBruce Richardson #include <rte_vect.h>
1299a2dd95SBruce Richardson 
1399a2dd95SBruce Richardson #include "rte_node_ip4_api.h"
1499a2dd95SBruce Richardson 
1599a2dd95SBruce Richardson #include "ip4_rewrite_priv.h"
1699a2dd95SBruce Richardson #include "node_private.h"
1799a2dd95SBruce Richardson 
1899a2dd95SBruce Richardson struct ip4_rewrite_node_ctx {
1999a2dd95SBruce Richardson 	/* Dynamic offset to mbuf priv1 */
2099a2dd95SBruce Richardson 	int mbuf_priv1_off;
2199a2dd95SBruce Richardson 	/* Cached next index */
2299a2dd95SBruce Richardson 	uint16_t next_index;
2399a2dd95SBruce Richardson };
2499a2dd95SBruce Richardson 
2599a2dd95SBruce Richardson static struct ip4_rewrite_node_main *ip4_rewrite_nm;
2699a2dd95SBruce Richardson 
2799a2dd95SBruce Richardson #define IP4_REWRITE_NODE_LAST_NEXT(ctx) \
2899a2dd95SBruce Richardson 	(((struct ip4_rewrite_node_ctx *)ctx)->next_index)
2999a2dd95SBruce Richardson 
3099a2dd95SBruce Richardson #define IP4_REWRITE_NODE_PRIV1_OFF(ctx) \
3199a2dd95SBruce Richardson 	(((struct ip4_rewrite_node_ctx *)ctx)->mbuf_priv1_off)
3299a2dd95SBruce Richardson 
3399a2dd95SBruce Richardson static uint16_t
ip4_rewrite_node_process(struct rte_graph * graph,struct rte_node * node,void ** objs,uint16_t nb_objs)3499a2dd95SBruce Richardson ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node,
3599a2dd95SBruce Richardson 			 void **objs, uint16_t nb_objs)
3699a2dd95SBruce Richardson {
3799a2dd95SBruce Richardson 	struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts;
3899a2dd95SBruce Richardson 	struct ip4_rewrite_nh_header *nh = ip4_rewrite_nm->nh;
3999a2dd95SBruce Richardson 	const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx);
4099a2dd95SBruce Richardson 	uint16_t next0, next1, next2, next3, next_index;
4199a2dd95SBruce Richardson 	struct rte_ipv4_hdr *ip0, *ip1, *ip2, *ip3;
4299a2dd95SBruce Richardson 	uint16_t n_left_from, held = 0, last_spec = 0;
4399a2dd95SBruce Richardson 	void *d0, *d1, *d2, *d3;
4499a2dd95SBruce Richardson 	void **to_next, **from;
4599a2dd95SBruce Richardson 	rte_xmm_t priv01;
4699a2dd95SBruce Richardson 	rte_xmm_t priv23;
4799a2dd95SBruce Richardson 	int i;
4899a2dd95SBruce Richardson 
4999a2dd95SBruce Richardson 	/* Speculative next as last next */
5099a2dd95SBruce Richardson 	next_index = IP4_REWRITE_NODE_LAST_NEXT(node->ctx);
5199a2dd95SBruce Richardson 	rte_prefetch0(nh);
5299a2dd95SBruce Richardson 
5399a2dd95SBruce Richardson 	pkts = (struct rte_mbuf **)objs;
5499a2dd95SBruce Richardson 	from = objs;
5599a2dd95SBruce Richardson 	n_left_from = nb_objs;
5699a2dd95SBruce Richardson 
5799a2dd95SBruce Richardson 	for (i = 0; i < 4 && i < n_left_from; i++)
5899a2dd95SBruce Richardson 		rte_prefetch0(pkts[i]);
5999a2dd95SBruce Richardson 
6099a2dd95SBruce Richardson 	/* Get stream for the speculated next node */
6199a2dd95SBruce Richardson 	to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs);
6299a2dd95SBruce Richardson 	/* Update Ethernet header of pkts */
6399a2dd95SBruce Richardson 	while (n_left_from >= 4) {
6499a2dd95SBruce Richardson 		if (likely(n_left_from > 7)) {
6599a2dd95SBruce Richardson 			/* Prefetch only next-mbuf struct and priv area.
6699a2dd95SBruce Richardson 			 * Data need not be prefetched as we only write.
6799a2dd95SBruce Richardson 			 */
6899a2dd95SBruce Richardson 			rte_prefetch0(pkts[4]);
6999a2dd95SBruce Richardson 			rte_prefetch0(pkts[5]);
7099a2dd95SBruce Richardson 			rte_prefetch0(pkts[6]);
7199a2dd95SBruce Richardson 			rte_prefetch0(pkts[7]);
7299a2dd95SBruce Richardson 		}
7399a2dd95SBruce Richardson 
7499a2dd95SBruce Richardson 		mbuf0 = pkts[0];
7599a2dd95SBruce Richardson 		mbuf1 = pkts[1];
7699a2dd95SBruce Richardson 		mbuf2 = pkts[2];
7799a2dd95SBruce Richardson 		mbuf3 = pkts[3];
7899a2dd95SBruce Richardson 
7999a2dd95SBruce Richardson 		pkts += 4;
8099a2dd95SBruce Richardson 		n_left_from -= 4;
8199a2dd95SBruce Richardson 		priv01.u64[0] = node_mbuf_priv1(mbuf0, dyn)->u;
8299a2dd95SBruce Richardson 		priv01.u64[1] = node_mbuf_priv1(mbuf1, dyn)->u;
8399a2dd95SBruce Richardson 		priv23.u64[0] = node_mbuf_priv1(mbuf2, dyn)->u;
8499a2dd95SBruce Richardson 		priv23.u64[1] = node_mbuf_priv1(mbuf3, dyn)->u;
8599a2dd95SBruce Richardson 
8699a2dd95SBruce Richardson 		/* Increment checksum by one. */
8799a2dd95SBruce Richardson 		priv01.u32[1] += rte_cpu_to_be_16(0x0100);
8899a2dd95SBruce Richardson 		priv01.u32[3] += rte_cpu_to_be_16(0x0100);
8999a2dd95SBruce Richardson 		priv23.u32[1] += rte_cpu_to_be_16(0x0100);
9099a2dd95SBruce Richardson 		priv23.u32[3] += rte_cpu_to_be_16(0x0100);
9199a2dd95SBruce Richardson 
9299a2dd95SBruce Richardson 		/* Update ttl,cksum rewrite ethernet hdr on mbuf0 */
9399a2dd95SBruce Richardson 		d0 = rte_pktmbuf_mtod(mbuf0, void *);
9499a2dd95SBruce Richardson 		rte_memcpy(d0, nh[priv01.u16[0]].rewrite_data,
9599a2dd95SBruce Richardson 			   nh[priv01.u16[0]].rewrite_len);
9699a2dd95SBruce Richardson 
9799a2dd95SBruce Richardson 		next0 = nh[priv01.u16[0]].tx_node;
9899a2dd95SBruce Richardson 		ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 +
9999a2dd95SBruce Richardson 					      sizeof(struct rte_ether_hdr));
10099a2dd95SBruce Richardson 		ip0->time_to_live = priv01.u16[1] - 1;
10199a2dd95SBruce Richardson 		ip0->hdr_checksum = priv01.u16[2] + priv01.u16[3];
10299a2dd95SBruce Richardson 
10399a2dd95SBruce Richardson 		/* Update ttl,cksum rewrite ethernet hdr on mbuf1 */
10499a2dd95SBruce Richardson 		d1 = rte_pktmbuf_mtod(mbuf1, void *);
10599a2dd95SBruce Richardson 		rte_memcpy(d1, nh[priv01.u16[4]].rewrite_data,
10699a2dd95SBruce Richardson 			   nh[priv01.u16[4]].rewrite_len);
10799a2dd95SBruce Richardson 
10899a2dd95SBruce Richardson 		next1 = nh[priv01.u16[4]].tx_node;
10999a2dd95SBruce Richardson 		ip1 = (struct rte_ipv4_hdr *)((uint8_t *)d1 +
11099a2dd95SBruce Richardson 					      sizeof(struct rte_ether_hdr));
11199a2dd95SBruce Richardson 		ip1->time_to_live = priv01.u16[5] - 1;
11299a2dd95SBruce Richardson 		ip1->hdr_checksum = priv01.u16[6] + priv01.u16[7];
11399a2dd95SBruce Richardson 
11499a2dd95SBruce Richardson 		/* Update ttl,cksum rewrite ethernet hdr on mbuf2 */
11599a2dd95SBruce Richardson 		d2 = rte_pktmbuf_mtod(mbuf2, void *);
11699a2dd95SBruce Richardson 		rte_memcpy(d2, nh[priv23.u16[0]].rewrite_data,
11799a2dd95SBruce Richardson 			   nh[priv23.u16[0]].rewrite_len);
11899a2dd95SBruce Richardson 		next2 = nh[priv23.u16[0]].tx_node;
11999a2dd95SBruce Richardson 		ip2 = (struct rte_ipv4_hdr *)((uint8_t *)d2 +
12099a2dd95SBruce Richardson 					      sizeof(struct rte_ether_hdr));
12199a2dd95SBruce Richardson 		ip2->time_to_live = priv23.u16[1] - 1;
12299a2dd95SBruce Richardson 		ip2->hdr_checksum = priv23.u16[2] + priv23.u16[3];
12399a2dd95SBruce Richardson 
12499a2dd95SBruce Richardson 		/* Update ttl,cksum rewrite ethernet hdr on mbuf3 */
12599a2dd95SBruce Richardson 		d3 = rte_pktmbuf_mtod(mbuf3, void *);
12699a2dd95SBruce Richardson 		rte_memcpy(d3, nh[priv23.u16[4]].rewrite_data,
12799a2dd95SBruce Richardson 			   nh[priv23.u16[4]].rewrite_len);
12899a2dd95SBruce Richardson 
12999a2dd95SBruce Richardson 		next3 = nh[priv23.u16[4]].tx_node;
13099a2dd95SBruce Richardson 		ip3 = (struct rte_ipv4_hdr *)((uint8_t *)d3 +
13199a2dd95SBruce Richardson 					      sizeof(struct rte_ether_hdr));
13299a2dd95SBruce Richardson 		ip3->time_to_live = priv23.u16[5] - 1;
13399a2dd95SBruce Richardson 		ip3->hdr_checksum = priv23.u16[6] + priv23.u16[7];
13499a2dd95SBruce Richardson 
13599a2dd95SBruce Richardson 		/* Enqueue four to next node */
13699a2dd95SBruce Richardson 		rte_edge_t fix_spec =
13799a2dd95SBruce Richardson 			((next_index == next0) && (next0 == next1) &&
13899a2dd95SBruce Richardson 			 (next1 == next2) && (next2 == next3));
13999a2dd95SBruce Richardson 
14099a2dd95SBruce Richardson 		if (unlikely(fix_spec == 0)) {
14199a2dd95SBruce Richardson 			/* Copy things successfully speculated till now */
14299a2dd95SBruce Richardson 			rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
14399a2dd95SBruce Richardson 			from += last_spec;
14499a2dd95SBruce Richardson 			to_next += last_spec;
14599a2dd95SBruce Richardson 			held += last_spec;
14699a2dd95SBruce Richardson 			last_spec = 0;
14799a2dd95SBruce Richardson 
14899a2dd95SBruce Richardson 			/* next0 */
14999a2dd95SBruce Richardson 			if (next_index == next0) {
15099a2dd95SBruce Richardson 				to_next[0] = from[0];
15199a2dd95SBruce Richardson 				to_next++;
15299a2dd95SBruce Richardson 				held++;
15399a2dd95SBruce Richardson 			} else {
15499a2dd95SBruce Richardson 				rte_node_enqueue_x1(graph, node, next0,
15599a2dd95SBruce Richardson 						    from[0]);
15699a2dd95SBruce Richardson 			}
15799a2dd95SBruce Richardson 
15899a2dd95SBruce Richardson 			/* next1 */
15999a2dd95SBruce Richardson 			if (next_index == next1) {
16099a2dd95SBruce Richardson 				to_next[0] = from[1];
16199a2dd95SBruce Richardson 				to_next++;
16299a2dd95SBruce Richardson 				held++;
16399a2dd95SBruce Richardson 			} else {
16499a2dd95SBruce Richardson 				rte_node_enqueue_x1(graph, node, next1,
16599a2dd95SBruce Richardson 						    from[1]);
16699a2dd95SBruce Richardson 			}
16799a2dd95SBruce Richardson 
16899a2dd95SBruce Richardson 			/* next2 */
16999a2dd95SBruce Richardson 			if (next_index == next2) {
17099a2dd95SBruce Richardson 				to_next[0] = from[2];
17199a2dd95SBruce Richardson 				to_next++;
17299a2dd95SBruce Richardson 				held++;
17399a2dd95SBruce Richardson 			} else {
17499a2dd95SBruce Richardson 				rte_node_enqueue_x1(graph, node, next2,
17599a2dd95SBruce Richardson 						    from[2]);
17699a2dd95SBruce Richardson 			}
17799a2dd95SBruce Richardson 
17899a2dd95SBruce Richardson 			/* next3 */
17999a2dd95SBruce Richardson 			if (next_index == next3) {
18099a2dd95SBruce Richardson 				to_next[0] = from[3];
18199a2dd95SBruce Richardson 				to_next++;
18299a2dd95SBruce Richardson 				held++;
18399a2dd95SBruce Richardson 			} else {
18499a2dd95SBruce Richardson 				rte_node_enqueue_x1(graph, node, next3,
18599a2dd95SBruce Richardson 						    from[3]);
18699a2dd95SBruce Richardson 			}
18799a2dd95SBruce Richardson 
18899a2dd95SBruce Richardson 			from += 4;
18999a2dd95SBruce Richardson 
19099a2dd95SBruce Richardson 			/* Change speculation if last two are same */
19199a2dd95SBruce Richardson 			if ((next_index != next3) && (next2 == next3)) {
19299a2dd95SBruce Richardson 				/* Put the current speculated node */
19399a2dd95SBruce Richardson 				rte_node_next_stream_put(graph, node,
19499a2dd95SBruce Richardson 							 next_index, held);
19599a2dd95SBruce Richardson 				held = 0;
19699a2dd95SBruce Richardson 
19799a2dd95SBruce Richardson 				/* Get next speculated stream */
19899a2dd95SBruce Richardson 				next_index = next3;
19999a2dd95SBruce Richardson 				to_next = rte_node_next_stream_get(
20099a2dd95SBruce Richardson 					graph, node, next_index, nb_objs);
20199a2dd95SBruce Richardson 			}
20299a2dd95SBruce Richardson 		} else {
20399a2dd95SBruce Richardson 			last_spec += 4;
20499a2dd95SBruce Richardson 		}
20599a2dd95SBruce Richardson 	}
20699a2dd95SBruce Richardson 
20799a2dd95SBruce Richardson 	while (n_left_from > 0) {
20899a2dd95SBruce Richardson 		uint16_t chksum;
20999a2dd95SBruce Richardson 
21099a2dd95SBruce Richardson 		mbuf0 = pkts[0];
21199a2dd95SBruce Richardson 
21299a2dd95SBruce Richardson 		pkts += 1;
21399a2dd95SBruce Richardson 		n_left_from -= 1;
21499a2dd95SBruce Richardson 
21599a2dd95SBruce Richardson 		d0 = rte_pktmbuf_mtod(mbuf0, void *);
21699a2dd95SBruce Richardson 		rte_memcpy(d0, nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_data,
21799a2dd95SBruce Richardson 			   nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_len);
21899a2dd95SBruce Richardson 
21999a2dd95SBruce Richardson 		next0 = nh[node_mbuf_priv1(mbuf0, dyn)->nh].tx_node;
22099a2dd95SBruce Richardson 		ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 +
22199a2dd95SBruce Richardson 					      sizeof(struct rte_ether_hdr));
22299a2dd95SBruce Richardson 		chksum = node_mbuf_priv1(mbuf0, dyn)->cksum +
22399a2dd95SBruce Richardson 			 rte_cpu_to_be_16(0x0100);
22499a2dd95SBruce Richardson 		chksum += chksum >= 0xffff;
22599a2dd95SBruce Richardson 		ip0->hdr_checksum = chksum;
22699a2dd95SBruce Richardson 		ip0->time_to_live = node_mbuf_priv1(mbuf0, dyn)->ttl - 1;
22799a2dd95SBruce Richardson 
22899a2dd95SBruce Richardson 		if (unlikely(next_index ^ next0)) {
22999a2dd95SBruce Richardson 			/* Copy things successfully speculated till now */
23099a2dd95SBruce Richardson 			rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
23199a2dd95SBruce Richardson 			from += last_spec;
23299a2dd95SBruce Richardson 			to_next += last_spec;
23399a2dd95SBruce Richardson 			held += last_spec;
23499a2dd95SBruce Richardson 			last_spec = 0;
23599a2dd95SBruce Richardson 
23699a2dd95SBruce Richardson 			rte_node_enqueue_x1(graph, node, next0, from[0]);
23799a2dd95SBruce Richardson 			from += 1;
23899a2dd95SBruce Richardson 		} else {
23999a2dd95SBruce Richardson 			last_spec += 1;
24099a2dd95SBruce Richardson 		}
24199a2dd95SBruce Richardson 	}
24299a2dd95SBruce Richardson 
24399a2dd95SBruce Richardson 	/* !!! Home run !!! */
24499a2dd95SBruce Richardson 	if (likely(last_spec == nb_objs)) {
24599a2dd95SBruce Richardson 		rte_node_next_stream_move(graph, node, next_index);
24699a2dd95SBruce Richardson 		return nb_objs;
24799a2dd95SBruce Richardson 	}
24899a2dd95SBruce Richardson 
24999a2dd95SBruce Richardson 	held += last_spec;
25099a2dd95SBruce Richardson 	rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
25199a2dd95SBruce Richardson 	rte_node_next_stream_put(graph, node, next_index, held);
25299a2dd95SBruce Richardson 	/* Save the last next used */
25399a2dd95SBruce Richardson 	IP4_REWRITE_NODE_LAST_NEXT(node->ctx) = next_index;
25499a2dd95SBruce Richardson 
25599a2dd95SBruce Richardson 	return nb_objs;
25699a2dd95SBruce Richardson }
25799a2dd95SBruce Richardson 
25899a2dd95SBruce Richardson static int
ip4_rewrite_node_init(const struct rte_graph * graph,struct rte_node * node)25999a2dd95SBruce Richardson ip4_rewrite_node_init(const struct rte_graph *graph, struct rte_node *node)
26099a2dd95SBruce Richardson {
26199a2dd95SBruce Richardson 	static bool init_once;
26299a2dd95SBruce Richardson 
26399a2dd95SBruce Richardson 	RTE_SET_USED(graph);
26499a2dd95SBruce Richardson 	RTE_BUILD_BUG_ON(sizeof(struct ip4_rewrite_node_ctx) > RTE_NODE_CTX_SZ);
26599a2dd95SBruce Richardson 
26699a2dd95SBruce Richardson 	if (!init_once) {
26799a2dd95SBruce Richardson 		node_mbuf_priv1_dynfield_offset = rte_mbuf_dynfield_register(
26899a2dd95SBruce Richardson 				&node_mbuf_priv1_dynfield_desc);
26999a2dd95SBruce Richardson 		if (node_mbuf_priv1_dynfield_offset < 0)
27099a2dd95SBruce Richardson 			return -rte_errno;
27199a2dd95SBruce Richardson 		init_once = true;
27299a2dd95SBruce Richardson 	}
27399a2dd95SBruce Richardson 	IP4_REWRITE_NODE_PRIV1_OFF(node->ctx) = node_mbuf_priv1_dynfield_offset;
27499a2dd95SBruce Richardson 
27599a2dd95SBruce Richardson 	node_dbg("ip4_rewrite", "Initialized ip4_rewrite node initialized");
27699a2dd95SBruce Richardson 
27799a2dd95SBruce Richardson 	return 0;
27899a2dd95SBruce Richardson }
27999a2dd95SBruce Richardson 
28099a2dd95SBruce Richardson int
ip4_rewrite_set_next(uint16_t port_id,uint16_t next_index)28199a2dd95SBruce Richardson ip4_rewrite_set_next(uint16_t port_id, uint16_t next_index)
28299a2dd95SBruce Richardson {
28399a2dd95SBruce Richardson 	if (ip4_rewrite_nm == NULL) {
28499a2dd95SBruce Richardson 		ip4_rewrite_nm = rte_zmalloc(
28599a2dd95SBruce Richardson 			"ip4_rewrite", sizeof(struct ip4_rewrite_node_main),
28699a2dd95SBruce Richardson 			RTE_CACHE_LINE_SIZE);
28799a2dd95SBruce Richardson 		if (ip4_rewrite_nm == NULL)
28899a2dd95SBruce Richardson 			return -ENOMEM;
28999a2dd95SBruce Richardson 	}
29099a2dd95SBruce Richardson 	ip4_rewrite_nm->next_index[port_id] = next_index;
29199a2dd95SBruce Richardson 
29299a2dd95SBruce Richardson 	return 0;
29399a2dd95SBruce Richardson }
29499a2dd95SBruce Richardson 
29599a2dd95SBruce Richardson int
rte_node_ip4_rewrite_add(uint16_t next_hop,uint8_t * rewrite_data,uint8_t rewrite_len,uint16_t dst_port)29699a2dd95SBruce Richardson rte_node_ip4_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data,
29799a2dd95SBruce Richardson 			 uint8_t rewrite_len, uint16_t dst_port)
29899a2dd95SBruce Richardson {
29999a2dd95SBruce Richardson 	struct ip4_rewrite_nh_header *nh;
30099a2dd95SBruce Richardson 
30199a2dd95SBruce Richardson 	if (next_hop >= RTE_GRAPH_IP4_REWRITE_MAX_NH)
30299a2dd95SBruce Richardson 		return -EINVAL;
30399a2dd95SBruce Richardson 
30499a2dd95SBruce Richardson 	if (rewrite_len > RTE_GRAPH_IP4_REWRITE_MAX_LEN)
30599a2dd95SBruce Richardson 		return -EINVAL;
30699a2dd95SBruce Richardson 
30799a2dd95SBruce Richardson 	if (ip4_rewrite_nm == NULL) {
30899a2dd95SBruce Richardson 		ip4_rewrite_nm = rte_zmalloc(
30999a2dd95SBruce Richardson 			"ip4_rewrite", sizeof(struct ip4_rewrite_node_main),
31099a2dd95SBruce Richardson 			RTE_CACHE_LINE_SIZE);
31199a2dd95SBruce Richardson 		if (ip4_rewrite_nm == NULL)
31299a2dd95SBruce Richardson 			return -ENOMEM;
31399a2dd95SBruce Richardson 	}
31499a2dd95SBruce Richardson 
31599a2dd95SBruce Richardson 	/* Check if dst port doesn't exist as edge */
31699a2dd95SBruce Richardson 	if (!ip4_rewrite_nm->next_index[dst_port])
31799a2dd95SBruce Richardson 		return -EINVAL;
31899a2dd95SBruce Richardson 
31999a2dd95SBruce Richardson 	/* Update next hop */
32099a2dd95SBruce Richardson 	nh = &ip4_rewrite_nm->nh[next_hop];
32199a2dd95SBruce Richardson 
32299a2dd95SBruce Richardson 	memcpy(nh->rewrite_data, rewrite_data, rewrite_len);
32399a2dd95SBruce Richardson 	nh->tx_node = ip4_rewrite_nm->next_index[dst_port];
32499a2dd95SBruce Richardson 	nh->rewrite_len = rewrite_len;
32599a2dd95SBruce Richardson 	nh->enabled = true;
32699a2dd95SBruce Richardson 
32799a2dd95SBruce Richardson 	return 0;
32899a2dd95SBruce Richardson }
32999a2dd95SBruce Richardson 
33099a2dd95SBruce Richardson static struct rte_node_register ip4_rewrite_node = {
33199a2dd95SBruce Richardson 	.process = ip4_rewrite_node_process,
33299a2dd95SBruce Richardson 	.name = "ip4_rewrite",
33399a2dd95SBruce Richardson 	/* Default edge i.e '0' is pkt drop */
33499a2dd95SBruce Richardson 	.nb_edges = 1,
33599a2dd95SBruce Richardson 	.next_nodes = {
33699a2dd95SBruce Richardson 		[0] = "pkt_drop",
33799a2dd95SBruce Richardson 	},
33899a2dd95SBruce Richardson 	.init = ip4_rewrite_node_init,
33999a2dd95SBruce Richardson };
34099a2dd95SBruce Richardson 
34199a2dd95SBruce Richardson struct rte_node_register *
ip4_rewrite_node_get(void)34299a2dd95SBruce Richardson ip4_rewrite_node_get(void)
34399a2dd95SBruce Richardson {
34499a2dd95SBruce Richardson 	return &ip4_rewrite_node;
34599a2dd95SBruce Richardson }
34699a2dd95SBruce Richardson 
34799a2dd95SBruce Richardson RTE_NODE_REGISTER(ip4_rewrite_node);
348