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