xref: /dpdk/app/graph/ip4_route.c (revision 0f32dac4bbf74761972249090523f4581ca13126)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2023 Marvell.
3  */
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 
9 #include <cmdline_parse.h>
10 #include <cmdline_parse_num.h>
11 #include <cmdline_parse_string.h>
12 #include <cmdline_socket.h>
13 #include <rte_node_ip4_api.h>
14 
15 #include "module_api.h"
16 #include "route_priv.h"
17 
18 static const char
19 cmd_ipv4_lookup_help[] = "ipv4_lookup route add ipv4 <ip> netmask <mask> via <ip>";
20 
21 struct ip4_route route4 = TAILQ_HEAD_INITIALIZER(route4);
22 
23 void
route_ip4_list_clean(void)24 route_ip4_list_clean(void)
25 {
26 	struct route_ipv4_config *route;
27 
28 	while (!TAILQ_EMPTY(&route4)) {
29 		route = TAILQ_FIRST(&route4);
30 		TAILQ_REMOVE(&route4, route, next);
31 	}
32 }
33 
34 static struct route_ipv4_config *
find_route4_entry(struct route_ipv4_config * route)35 find_route4_entry(struct route_ipv4_config *route)
36 {
37 	struct route_ipv4_config *ipv4route;
38 
39 	TAILQ_FOREACH(ipv4route, &route4, next) {
40 		if (!memcmp(ipv4route, route, sizeof(*route)))
41 			return ipv4route;
42 	}
43 	return NULL;
44 
45 }
46 
47 static uint8_t
convert_netmask_to_depth(uint32_t netmask)48 convert_netmask_to_depth(uint32_t netmask)
49 {
50 	uint8_t zerobits = 0;
51 
52 	while ((netmask & 0x1) == 0) {
53 		netmask = netmask >> 1;
54 		zerobits++;
55 	}
56 
57 	return (32 - zerobits);
58 }
59 
60 static int
route4_rewirte_table_update(struct route_ipv4_config * ipv4route)61 route4_rewirte_table_update(struct route_ipv4_config *ipv4route)
62 {
63 	uint8_t depth;
64 	int portid;
65 
66 	portid = ethdev_portid_by_ip4(ipv4route->via, ipv4route->netmask);
67 	if (portid < 0) {
68 		printf("Invalid portid found to install the route\n");
69 		return portid;
70 	}
71 
72 	depth = convert_netmask_to_depth(ipv4route->netmask);
73 
74 	return rte_node_ip4_route_add(ipv4route->ip, depth, portid,
75 			RTE_NODE_IP4_LOOKUP_NEXT_REWRITE);
76 }
77 
78 static int
route_ip4_add(struct route_ipv4_config * route)79 route_ip4_add(struct route_ipv4_config *route)
80 {
81 	struct route_ipv4_config *ipv4route;
82 	int rc = -EINVAL;
83 
84 	ipv4route = find_route4_entry(route);
85 
86 	if (!ipv4route) {
87 		ipv4route = malloc(sizeof(struct route_ipv4_config));
88 		if (!ipv4route)
89 			return -ENOMEM;
90 	} else {
91 		return 0;
92 	}
93 
94 	ipv4route->ip = route->ip;
95 	ipv4route->netmask = route->netmask;
96 	ipv4route->via = route->via;
97 	ipv4route->is_used = true;
98 
99 	if (!graph_status_get())
100 		goto exit;
101 
102 	rc = route4_rewirte_table_update(ipv4route);
103 	if (rc)
104 		goto free;
105 
106 exit:
107 	TAILQ_INSERT_TAIL(&route4, ipv4route, next);
108 	return 0;
109 free:
110 	free(ipv4route);
111 	return rc;
112 }
113 
114 int
route_ip4_add_to_lookup(void)115 route_ip4_add_to_lookup(void)
116 {
117 	struct route_ipv4_config *route = NULL;
118 	int rc = -EINVAL;
119 
120 	TAILQ_FOREACH(route, &route4, next) {
121 		rc = route4_rewirte_table_update(route);
122 		if (rc < 0)
123 			return rc;
124 	}
125 
126 	return 0;
127 }
128 
129 void
cmd_help_ipv4_lookup_parsed(__rte_unused void * parsed_result,__rte_unused struct cmdline * cl,__rte_unused void * data)130 cmd_help_ipv4_lookup_parsed(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl,
131 			    __rte_unused void *data)
132 {
133 	size_t len;
134 
135 	len = strlen(conn->msg_out);
136 	conn->msg_out += len;
137 	snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n",
138 		 "--------------------------- ipv4_lookup command help ---------------------------",
139 		 cmd_ipv4_lookup_help);
140 
141 	len = strlen(conn->msg_out);
142 	conn->msg_out_len_max -= len;
143 }
144 
145 void
cmd_ipv4_lookup_route_add_ipv4_parsed(void * parsed_result,__rte_unused struct cmdline * cl,void * data __rte_unused)146 cmd_ipv4_lookup_route_add_ipv4_parsed(void *parsed_result, __rte_unused struct cmdline *cl,
147 				      void *data __rte_unused)
148 {
149 	struct cmd_ipv4_lookup_route_add_ipv4_result *res = parsed_result;
150 	struct route_ipv4_config config;
151 	int rc = -EINVAL;
152 
153 	config.ip = rte_be_to_cpu_32(res->ip.addr.ipv4.s_addr);
154 	config.netmask = rte_be_to_cpu_32(res->mask.addr.ipv4.s_addr);
155 	config.via = rte_be_to_cpu_32(res->via_ip.addr.ipv4.s_addr);
156 
157 	rc = route_ip4_add(&config);
158 	if (rc < 0)
159 		printf(MSG_CMD_FAIL, res->ipv4_lookup);
160 }
161