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