1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2016 Intel Corporation 3 */ 4 5 /* 6 * Routing Table (RT) 7 */ 8 #include <sys/types.h> 9 #include <rte_lpm.h> 10 #include <rte_lpm6.h> 11 #include <rte_errno.h> 12 #include <rte_ip.h> 13 14 #include "ipsec.h" 15 #include "parser.h" 16 17 #define RT_IPV4_MAX_RULES 1024 18 #define RT_IPV6_MAX_RULES 1024 19 20 struct ip4_route { 21 uint32_t ip; 22 uint8_t depth; 23 uint8_t if_out; 24 }; 25 26 struct ip6_route { 27 uint8_t ip[16]; 28 uint8_t depth; 29 uint8_t if_out; 30 }; 31 32 struct ip4_route rt_ip4[RT_IPV4_MAX_RULES]; 33 uint32_t nb_rt_ip4; 34 35 struct ip6_route rt_ip6[RT_IPV4_MAX_RULES]; 36 uint32_t nb_rt_ip6; 37 38 void 39 parse_rt_tokens(char **tokens, uint32_t n_tokens, 40 struct parse_status *status) 41 { 42 uint32_t ti; 43 uint32_t *n_rts = NULL; 44 struct ip4_route *route_ipv4 = NULL; 45 struct ip6_route *route_ipv6 = NULL; 46 47 if (strcmp(tokens[0], "ipv4") == 0) { 48 n_rts = &nb_rt_ip4; 49 route_ipv4 = &rt_ip4[*n_rts]; 50 51 APP_CHECK(*n_rts <= RT_IPV4_MAX_RULES - 1, status, 52 "too many rt rules, abort insertion\n"); 53 if (status->status < 0) 54 return; 55 56 } else if (strcmp(tokens[0], "ipv6") == 0) { 57 n_rts = &nb_rt_ip6; 58 route_ipv6 = &rt_ip6[*n_rts]; 59 60 APP_CHECK(*n_rts <= RT_IPV6_MAX_RULES - 1, status, 61 "too many rt rules, abort insertion\n"); 62 if (status->status < 0) 63 return; 64 } else { 65 APP_CHECK(0, status, "unrecognized input \"%s\"", 66 tokens[0]); 67 return; 68 } 69 70 for (ti = 1; ti < n_tokens; ti++) { 71 if (strcmp(tokens[ti], "dst") == 0) { 72 INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 73 if (status->status < 0) 74 return; 75 76 if (route_ipv4 != NULL) { 77 struct in_addr ip; 78 uint32_t depth = 0; 79 80 APP_CHECK(parse_ipv4_addr(tokens[ti], 81 &ip, &depth) == 0, status, 82 "unrecognized input \"%s\", " 83 "expect valid ipv4 addr", 84 tokens[ti]); 85 if (status->status < 0) 86 return; 87 route_ipv4->ip = rte_bswap32( 88 (uint32_t)ip.s_addr); 89 route_ipv4->depth = (uint8_t)depth; 90 } else { 91 struct in6_addr ip; 92 uint32_t depth; 93 94 APP_CHECK(parse_ipv6_addr(tokens[ti], 95 &ip, &depth) == 0, status, 96 "unrecognized input \"%s\", " 97 "expect valid ipv6 address", 98 tokens[ti]); 99 if (status->status < 0) 100 return; 101 memcpy(route_ipv6->ip, ip.s6_addr, 16); 102 route_ipv6->depth = (uint8_t)depth; 103 } 104 } 105 106 if (strcmp(tokens[ti], "port") == 0) { 107 INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 108 if (status->status < 0) 109 return; 110 APP_CHECK_TOKEN_IS_NUM(tokens, ti, status); 111 if (status->status < 0) 112 return; 113 if (route_ipv4 != NULL) 114 route_ipv4->if_out = atoi(tokens[ti]); 115 else 116 route_ipv6->if_out = atoi(tokens[ti]); 117 } 118 } 119 120 *n_rts = *n_rts + 1; 121 } 122 123 void 124 rt_init(struct socket_ctx *ctx, int32_t socket_id) 125 { 126 char name[PATH_MAX]; 127 uint32_t i; 128 int32_t ret; 129 struct rte_lpm *lpm; 130 struct rte_lpm6 *lpm6; 131 char a, b, c, d; 132 struct rte_lpm_config conf = { 0 }; 133 struct rte_lpm6_config conf6 = { 0 }; 134 135 if (ctx == NULL) 136 rte_exit(EXIT_FAILURE, "NULL context.\n"); 137 138 if (ctx->rt_ip4 != NULL) 139 rte_exit(EXIT_FAILURE, "IPv4 Routing Table for socket %u " 140 "already initialized\n", socket_id); 141 142 if (ctx->rt_ip6 != NULL) 143 rte_exit(EXIT_FAILURE, "IPv6 Routing Table for socket %u " 144 "already initialized\n", socket_id); 145 146 if (nb_rt_ip4 == 0 && nb_rt_ip6 == 0) 147 RTE_LOG(WARNING, IPSEC, "No Routing rule specified\n"); 148 149 printf("Creating IPv4 Routing Table (RT) context with %u max routes\n", 150 RT_IPV4_MAX_RULES); 151 152 /* create the LPM table */ 153 snprintf(name, sizeof(name), "%s_%u", "rt_ip4", socket_id); 154 conf.max_rules = RT_IPV4_MAX_RULES; 155 conf.number_tbl8s = RTE_LPM_TBL8_NUM_ENTRIES; 156 lpm = rte_lpm_create(name, socket_id, &conf); 157 if (lpm == NULL) 158 rte_exit(EXIT_FAILURE, "Unable to create %s LPM table " 159 "on socket %d\n", name, socket_id); 160 161 /* populate the LPM table */ 162 for (i = 0; i < nb_rt_ip4; i++) { 163 ret = rte_lpm_add(lpm, rt_ip4[i].ip, rt_ip4[i].depth, 164 rt_ip4[i].if_out); 165 if (ret < 0) 166 rte_exit(EXIT_FAILURE, "Fail to add entry num %u to %s " 167 "LPM table on socket %d\n", i, name, socket_id); 168 169 uint32_t_to_char(rt_ip4[i].ip, &a, &b, &c, &d); 170 printf("LPM: Adding route %hhu.%hhu.%hhu.%hhu/%hhu (%hhu)\n", 171 a, b, c, d, rt_ip4[i].depth, 172 rt_ip4[i].if_out); 173 } 174 175 snprintf(name, sizeof(name), "%s_%u", "rt_ip6", socket_id); 176 conf6.max_rules = RT_IPV6_MAX_RULES; 177 conf6.number_tbl8s = RTE_LPM_TBL8_NUM_ENTRIES; 178 lpm6 = rte_lpm6_create(name, socket_id, &conf6); 179 if (lpm6 == NULL) 180 rte_exit(EXIT_FAILURE, "Unable to create %s LPM table " 181 "on socket %d\n", name, socket_id); 182 183 /* populate the LPM table */ 184 for (i = 0; i < nb_rt_ip6; i++) { 185 ret = rte_lpm6_add(lpm6, rt_ip6[i].ip, rt_ip6[i].depth, 186 rt_ip6[i].if_out); 187 if (ret < 0) 188 rte_exit(EXIT_FAILURE, "Fail to add entry num %u to %s " 189 "LPM table on socket %d\n", i, name, socket_id); 190 191 printf("LPM6: Adding route " 192 " %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%hhx (%hhx)\n", 193 (uint16_t)((rt_ip6[i].ip[0] << 8) | rt_ip6[i].ip[1]), 194 (uint16_t)((rt_ip6[i].ip[2] << 8) | rt_ip6[i].ip[3]), 195 (uint16_t)((rt_ip6[i].ip[4] << 8) | rt_ip6[i].ip[5]), 196 (uint16_t)((rt_ip6[i].ip[6] << 8) | rt_ip6[i].ip[7]), 197 (uint16_t)((rt_ip6[i].ip[8] << 8) | rt_ip6[i].ip[9]), 198 (uint16_t)((rt_ip6[i].ip[10] << 8) | rt_ip6[i].ip[11]), 199 (uint16_t)((rt_ip6[i].ip[12] << 8) | rt_ip6[i].ip[13]), 200 (uint16_t)((rt_ip6[i].ip[14] << 8) | rt_ip6[i].ip[15]), 201 rt_ip6[i].depth, rt_ip6[i].if_out); 202 } 203 204 ctx->rt_ip4 = (struct rt_ctx *)lpm; 205 ctx->rt_ip6 = (struct rt_ctx *)lpm6; 206 } 207