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 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 * 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 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 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 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 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 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 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