Branch data Line data Source code
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 : : #include <cmdline_parse.h>
9 : : #include <cmdline_parse_num.h>
10 : : #include <cmdline_parse_string.h>
11 : : #include <cmdline_socket.h>
12 : :
13 : : #include <rte_node_ip6_api.h>
14 : :
15 : : #include "module_api.h"
16 : : #include "route_priv.h"
17 : :
18 : : static const char
19 : : cmd_ipv6_lookup_help[] = "ipv6_lookup route add ipv6 <ip> netmask <mask> via <ip>";
20 : :
21 : : struct ip6_route route6 = TAILQ_HEAD_INITIALIZER(route6);
22 : :
23 : : void
24 : 0 : route_ip6_list_clean(void)
25 : : {
26 : : struct route_ipv6_config *route;
27 : :
28 : 0 : while (!TAILQ_EMPTY(&route6)) {
29 : : route = TAILQ_FIRST(&route6);
30 : 0 : TAILQ_REMOVE(&route6, route, next);
31 : : }
32 : 0 : }
33 : :
34 : : static struct route_ipv6_config *
35 : 0 : find_route6_entry(struct route_ipv6_config *route)
36 : : {
37 : : struct route_ipv6_config *ipv6route;
38 : :
39 : 0 : TAILQ_FOREACH(ipv6route, &route6, next) {
40 : 0 : if (!memcmp(ipv6route, route, sizeof(*route)))
41 : 0 : return ipv6route;
42 : : }
43 : : return NULL;
44 : : }
45 : :
46 : : static uint8_t
47 : : convert_ip6_netmask_to_depth(uint8_t *netmask)
48 : : {
49 : : uint8_t setbits = 0;
50 : : uint8_t mask;
51 : : int i;
52 : :
53 : 0 : for (i = 0; i < ETHDEV_IPV6_ADDR_LEN; i++) {
54 : 0 : mask = netmask[i];
55 : 0 : while (mask & 0x80) {
56 : 0 : mask = mask << 1;
57 : 0 : setbits++;
58 : : }
59 : : }
60 : :
61 : : return setbits;
62 : : }
63 : :
64 : : static int
65 : 0 : route6_rewirte_table_update(struct route_ipv6_config *ipv6route)
66 : : {
67 : : uint8_t depth;
68 : : int portid;
69 : :
70 : 0 : portid = ethdev_portid_by_ip6(ipv6route->gateway, ipv6route->mask);
71 : 0 : if (portid < 0) {
72 : : printf("Invalid portid found to install the route\n");
73 : 0 : return portid;
74 : : }
75 : : depth = convert_ip6_netmask_to_depth(ipv6route->mask);
76 : :
77 : 0 : return rte_node_ip6_route_add(ipv6route->ip, depth, portid,
78 : : RTE_NODE_IP6_LOOKUP_NEXT_REWRITE);
79 : :
80 : : }
81 : :
82 : : static int
83 : 0 : route_ip6_add(struct route_ipv6_config *route)
84 : : {
85 : : struct route_ipv6_config *ipv6route;
86 : : int rc = -EINVAL;
87 : : int j;
88 : :
89 : 0 : ipv6route = find_route6_entry(route);
90 : 0 : if (!ipv6route) {
91 : 0 : ipv6route = malloc(sizeof(struct route_ipv6_config));
92 : 0 : if (!ipv6route)
93 : : return -ENOMEM;
94 : : } else {
95 : : return 0;
96 : : }
97 : :
98 : 0 : for (j = 0; j < ETHDEV_IPV6_ADDR_LEN; j++) {
99 : 0 : ipv6route->ip[j] = route->ip[j];
100 : 0 : ipv6route->mask[j] = route->mask[j];
101 : 0 : ipv6route->gateway[j] = route->gateway[j];
102 : : }
103 : 0 : ipv6route->is_used = true;
104 : :
105 : 0 : if (!graph_status_get())
106 : 0 : goto exit;
107 : :
108 : 0 : rc = route6_rewirte_table_update(ipv6route);
109 : 0 : if (rc)
110 : 0 : goto free;
111 : :
112 : 0 : exit:
113 : 0 : TAILQ_INSERT_TAIL(&route6, ipv6route, next);
114 : 0 : return 0;
115 : : free:
116 : 0 : free(ipv6route);
117 : 0 : return rc;
118 : : }
119 : :
120 : : int
121 : 0 : route_ip6_add_to_lookup(void)
122 : : {
123 : : struct route_ipv6_config *route = NULL;
124 : : int rc = -EINVAL;
125 : :
126 : 0 : TAILQ_FOREACH(route, &route6, next) {
127 : 0 : rc = route6_rewirte_table_update(route);
128 : 0 : if (rc < 0)
129 : 0 : return rc;
130 : : }
131 : :
132 : : return 0;
133 : : }
134 : :
135 : : static void
136 : 0 : cli_ipv6_lookup_help(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl,
137 : : __rte_unused void *data)
138 : : {
139 : : size_t len;
140 : :
141 : 0 : len = strlen(conn->msg_out);
142 : 0 : conn->msg_out += len;
143 : 0 : snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n",
144 : : "--------------------------- ipv6_lookup command help ---------------------------",
145 : : cmd_ipv6_lookup_help);
146 : :
147 : 0 : len = strlen(conn->msg_out);
148 : 0 : conn->msg_out_len_max -= len;
149 : 0 : }
150 : :
151 : : static void
152 : 0 : cli_ipv6_lookup(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused)
153 : : {
154 : : struct ip6_lookup_cmd_tokens *res = parsed_result;
155 : : struct route_ipv6_config config;
156 : : int rc = -EINVAL;
157 : :
158 : 0 : if (parser_ip6_read(config.ip, res->ip)) {
159 : : printf(MSG_ARG_INVALID, "ipv6");
160 : 0 : return;
161 : : }
162 : :
163 : 0 : if (parser_ip6_read(config.mask, res->mask)) {
164 : : printf(MSG_ARG_INVALID, "netmask");
165 : 0 : return;
166 : : }
167 : :
168 : 0 : if (parser_ip6_read(config.gateway, res->via_ip)) {
169 : : printf(MSG_ARG_INVALID, "gateway ip");
170 : 0 : return;
171 : : }
172 : :
173 : 0 : rc = route_ip6_add(&config);
174 : 0 : if (rc)
175 : 0 : printf(MSG_CMD_FAIL, res->cmd);
176 : : }
177 : :
178 : : cmdline_parse_token_string_t ip6_lookup_cmd =
179 : : TOKEN_STRING_INITIALIZER(struct ip6_lookup_cmd_tokens, cmd, "ipv6_lookup");
180 : : cmdline_parse_token_string_t ip6_lookup_route =
181 : : TOKEN_STRING_INITIALIZER(struct ip6_lookup_cmd_tokens, route, "route");
182 : : cmdline_parse_token_string_t ip6_lookup_add =
183 : : TOKEN_STRING_INITIALIZER(struct ip6_lookup_cmd_tokens, add, "add");
184 : : cmdline_parse_token_string_t ip6_lookup_ip6 =
185 : : TOKEN_STRING_INITIALIZER(struct ip6_lookup_cmd_tokens, ip6, "ipv6");
186 : : cmdline_parse_token_string_t ip6_lookup_ip =
187 : : TOKEN_STRING_INITIALIZER(struct ip6_lookup_cmd_tokens, ip, NULL);
188 : : cmdline_parse_token_string_t ip6_lookup_netmask =
189 : : TOKEN_STRING_INITIALIZER(struct ip6_lookup_cmd_tokens, netmask, "netmask");
190 : : cmdline_parse_token_string_t ip6_lookup_mask =
191 : : TOKEN_STRING_INITIALIZER(struct ip6_lookup_cmd_tokens, mask, NULL);
192 : : cmdline_parse_token_string_t ip6_lookup_via =
193 : : TOKEN_STRING_INITIALIZER(struct ip6_lookup_cmd_tokens, via, "via");
194 : : cmdline_parse_token_string_t ip6_lookup_via_ip =
195 : : TOKEN_STRING_INITIALIZER(struct ip6_lookup_cmd_tokens, via_ip, NULL);
196 : :
197 : : cmdline_parse_inst_t ipv6_lookup_cmd_ctx = {
198 : : .f = cli_ipv6_lookup,
199 : : .data = NULL,
200 : : .help_str = cmd_ipv6_lookup_help,
201 : : .tokens = {
202 : : (void *)&ip6_lookup_cmd,
203 : : (void *)&ip6_lookup_route,
204 : : (void *)&ip6_lookup_add,
205 : : (void *)&ip6_lookup_ip6,
206 : : (void *)&ip6_lookup_ip,
207 : : (void *)&ip6_lookup_netmask,
208 : : (void *)&ip6_lookup_mask,
209 : : (void *)&ip6_lookup_via,
210 : : (void *)&ip6_lookup_via_ip,
211 : : NULL,
212 : : },
213 : : };
214 : :
215 : : cmdline_parse_token_string_t ipv6_lookup_help_cmd =
216 : : TOKEN_STRING_INITIALIZER(struct ipv6_lookup_help_cmd_tokens, cmd, "help");
217 : : cmdline_parse_token_string_t ipv6_lookup_help_module =
218 : : TOKEN_STRING_INITIALIZER(struct ipv6_lookup_help_cmd_tokens, module, "ipv6_lookup");
219 : :
220 : : cmdline_parse_inst_t ipv6_lookup_help_cmd_ctx = {
221 : : .f = cli_ipv6_lookup_help,
222 : : .data = NULL,
223 : : .help_str = "",
224 : : .tokens = {
225 : : (void *)&ipv6_lookup_help_cmd,
226 : : (void *)&ipv6_lookup_help_module,
227 : : NULL,
228 : : },
229 : : };
|