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 #include <rte_ip6.h> 15 16 #include "module_api.h" 17 #include "route_priv.h" 18 19 static const char 20 cmd_ipv6_lookup_help[] = "ipv6_lookup route add ipv6 <ip> netmask <mask> via <ip>"; 21 22 struct ip6_route route6 = TAILQ_HEAD_INITIALIZER(route6); 23 24 void 25 route_ip6_list_clean(void) 26 { 27 struct route_ipv6_config *route; 28 29 while (!TAILQ_EMPTY(&route6)) { 30 route = TAILQ_FIRST(&route6); 31 TAILQ_REMOVE(&route6, route, next); 32 } 33 } 34 35 static struct route_ipv6_config * 36 find_route6_entry(struct route_ipv6_config *route) 37 { 38 struct route_ipv6_config *ipv6route; 39 40 TAILQ_FOREACH(ipv6route, &route6, next) { 41 if (!memcmp(ipv6route, route, sizeof(*route))) 42 return ipv6route; 43 } 44 return NULL; 45 } 46 47 static int 48 route6_rewirte_table_update(struct route_ipv6_config *ipv6route) 49 { 50 uint8_t depth; 51 int portid; 52 53 portid = ethdev_portid_by_ip6(&ipv6route->gateway, &ipv6route->mask); 54 if (portid < 0) { 55 printf("Invalid portid found to install the route\n"); 56 return portid; 57 } 58 depth = rte_ipv6_mask_depth(&ipv6route->mask); 59 60 return rte_node_ip6_route_add(&ipv6route->ip, depth, portid, 61 RTE_NODE_IP6_LOOKUP_NEXT_REWRITE); 62 63 } 64 65 static int 66 route_ip6_add(struct route_ipv6_config *route) 67 { 68 struct route_ipv6_config *ipv6route; 69 int rc = -EINVAL; 70 71 ipv6route = find_route6_entry(route); 72 if (!ipv6route) { 73 ipv6route = malloc(sizeof(struct route_ipv6_config)); 74 if (!ipv6route) 75 return -ENOMEM; 76 } else { 77 return 0; 78 } 79 80 ipv6route->ip = route->ip; 81 ipv6route->mask = route->mask; 82 ipv6route->gateway = route->gateway; 83 ipv6route->is_used = true; 84 85 if (!graph_status_get()) 86 goto exit; 87 88 rc = route6_rewirte_table_update(ipv6route); 89 if (rc) 90 goto free; 91 92 exit: 93 TAILQ_INSERT_TAIL(&route6, ipv6route, next); 94 return 0; 95 free: 96 free(ipv6route); 97 return rc; 98 } 99 100 int 101 route_ip6_add_to_lookup(void) 102 { 103 struct route_ipv6_config *route = NULL; 104 int rc = -EINVAL; 105 106 TAILQ_FOREACH(route, &route6, next) { 107 rc = route6_rewirte_table_update(route); 108 if (rc < 0) 109 return rc; 110 } 111 112 return 0; 113 } 114 115 void 116 cmd_help_ipv6_lookup_parsed(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl, 117 __rte_unused void *data) 118 { 119 size_t len; 120 121 len = strlen(conn->msg_out); 122 conn->msg_out += len; 123 snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n", 124 "--------------------------- ipv6_lookup command help ---------------------------", 125 cmd_ipv6_lookup_help); 126 127 len = strlen(conn->msg_out); 128 conn->msg_out_len_max -= len; 129 } 130 131 void 132 cmd_ipv6_lookup_route_add_ipv6_parsed(void *parsed_result, __rte_unused struct cmdline *cl, 133 void *data __rte_unused) 134 { 135 struct cmd_ipv6_lookup_route_add_ipv6_result *res = parsed_result; 136 struct route_ipv6_config config = { 137 .ip = res->ip.addr.ipv6, 138 .mask = res->mask.addr.ipv6, 139 .gateway = res->via_ip.addr.ipv6, 140 }; 141 int rc; 142 143 rc = route_ip6_add(&config); 144 if (rc) 145 printf(MSG_CMD_FAIL, res->ipv6_lookup); 146 } 147