1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2020 Marvell International Ltd. 3 */ 4 5 #include <stdio.h> 6 7 #include <rte_common.h> 8 #include <rte_flow.h> 9 #include <rte_ip.h> 10 11 #include "flow.h" 12 #include "ipsec-secgw.h" 13 #include "parser.h" 14 15 #define FLOW_RULES_MAX 128 16 17 struct flow_rule_entry { 18 uint8_t is_ipv4; 19 RTE_STD_C11 20 union { 21 struct { 22 struct rte_flow_item_ipv4 spec; 23 struct rte_flow_item_ipv4 mask; 24 } ipv4; 25 struct { 26 struct rte_flow_item_ipv6 spec; 27 struct rte_flow_item_ipv6 mask; 28 } ipv6; 29 }; 30 uint16_t port; 31 uint16_t queue; 32 struct rte_flow *flow; 33 } flow_rule_tbl[FLOW_RULES_MAX]; 34 35 int nb_flow_rule; 36 37 static void 38 ipv4_hdr_print(struct rte_ipv4_hdr *hdr) 39 { 40 char a, b, c, d; 41 42 uint32_t_to_char(rte_bswap32(hdr->src_addr), &a, &b, &c, &d); 43 printf("src: %3hhu.%3hhu.%3hhu.%3hhu \t", a, b, c, d); 44 45 uint32_t_to_char(rte_bswap32(hdr->dst_addr), &a, &b, &c, &d); 46 printf("dst: %3hhu.%3hhu.%3hhu.%3hhu", a, b, c, d); 47 } 48 49 static int 50 ipv4_addr_cpy(rte_be32_t *spec, rte_be32_t *mask, char *token, 51 struct parse_status *status) 52 { 53 struct in_addr ip; 54 uint32_t depth; 55 56 APP_CHECK(parse_ipv4_addr(token, &ip, &depth) == 0, status, 57 "unrecognized input \"%s\", expect valid ipv4 addr", token); 58 if (status->status < 0) 59 return -1; 60 61 if (depth > 32) 62 return -1; 63 64 memcpy(mask, &rte_flow_item_ipv4_mask.hdr.src_addr, sizeof(ip)); 65 66 *spec = ip.s_addr; 67 if (depth < 32) 68 *mask = *mask << (32-depth); 69 70 return 0; 71 } 72 73 static void 74 ipv6_hdr_print(struct rte_ipv6_hdr *hdr) 75 { 76 uint8_t *addr; 77 78 addr = hdr->src_addr; 79 printf("src: %4hx:%4hx:%4hx:%4hx:%4hx:%4hx:%4hx:%4hx \t", 80 (uint16_t)((addr[0] << 8) | addr[1]), 81 (uint16_t)((addr[2] << 8) | addr[3]), 82 (uint16_t)((addr[4] << 8) | addr[5]), 83 (uint16_t)((addr[6] << 8) | addr[7]), 84 (uint16_t)((addr[8] << 8) | addr[9]), 85 (uint16_t)((addr[10] << 8) | addr[11]), 86 (uint16_t)((addr[12] << 8) | addr[13]), 87 (uint16_t)((addr[14] << 8) | addr[15])); 88 89 addr = hdr->dst_addr; 90 printf("dst: %4hx:%4hx:%4hx:%4hx:%4hx:%4hx:%4hx:%4hx", 91 (uint16_t)((addr[0] << 8) | addr[1]), 92 (uint16_t)((addr[2] << 8) | addr[3]), 93 (uint16_t)((addr[4] << 8) | addr[5]), 94 (uint16_t)((addr[6] << 8) | addr[7]), 95 (uint16_t)((addr[8] << 8) | addr[9]), 96 (uint16_t)((addr[10] << 8) | addr[11]), 97 (uint16_t)((addr[12] << 8) | addr[13]), 98 (uint16_t)((addr[14] << 8) | addr[15])); 99 } 100 101 static int 102 ipv6_addr_cpy(uint8_t *spec, uint8_t *mask, char *token, 103 struct parse_status *status) 104 { 105 struct in6_addr ip; 106 uint32_t depth, i; 107 108 APP_CHECK(parse_ipv6_addr(token, &ip, &depth) == 0, status, 109 "unrecognized input \"%s\", expect valid ipv6 address", token); 110 if (status->status < 0) 111 return -1; 112 113 memcpy(mask, &rte_flow_item_ipv6_mask.hdr.src_addr, sizeof(ip)); 114 memcpy(spec, ip.s6_addr, sizeof(struct in6_addr)); 115 116 for (i = 0; i < depth && (i%8 <= sizeof(struct in6_addr)); i++) 117 mask[i/8] &= ~(1 << (7-i%8)); 118 119 return 0; 120 } 121 122 void 123 parse_flow_tokens(char **tokens, uint32_t n_tokens, 124 struct parse_status *status) 125 { 126 struct flow_rule_entry *rule; 127 uint32_t ti; 128 129 if (nb_flow_rule >= FLOW_RULES_MAX) { 130 printf("Too many flow rules\n"); 131 return; 132 } 133 134 rule = &flow_rule_tbl[nb_flow_rule]; 135 memset(rule, 0, sizeof(*rule)); 136 137 if (strcmp(tokens[0], "ipv4") == 0) { 138 rule->is_ipv4 = 1; 139 } else if (strcmp(tokens[0], "ipv6") == 0) { 140 rule->is_ipv4 = 0; 141 } else { 142 APP_CHECK(0, status, "unrecognized input \"%s\"", tokens[0]); 143 return; 144 } 145 146 for (ti = 1; ti < n_tokens; ti++) { 147 if (strcmp(tokens[ti], "src") == 0) { 148 INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 149 if (status->status < 0) 150 return; 151 152 if (rule->is_ipv4) { 153 if (ipv4_addr_cpy(&rule->ipv4.spec.hdr.src_addr, 154 &rule->ipv4.mask.hdr.src_addr, 155 tokens[ti], status)) 156 return; 157 } else { 158 if (ipv6_addr_cpy(rule->ipv6.spec.hdr.src_addr, 159 rule->ipv6.mask.hdr.src_addr, 160 tokens[ti], status)) 161 return; 162 } 163 } 164 if (strcmp(tokens[ti], "dst") == 0) { 165 INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 166 if (status->status < 0) 167 return; 168 169 if (rule->is_ipv4) { 170 if (ipv4_addr_cpy(&rule->ipv4.spec.hdr.dst_addr, 171 &rule->ipv4.mask.hdr.dst_addr, 172 tokens[ti], status)) 173 return; 174 } else { 175 if (ipv6_addr_cpy(rule->ipv6.spec.hdr.dst_addr, 176 rule->ipv6.mask.hdr.dst_addr, 177 tokens[ti], status)) 178 return; 179 } 180 } 181 182 if (strcmp(tokens[ti], "port") == 0) { 183 INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 184 if (status->status < 0) 185 return; 186 APP_CHECK_TOKEN_IS_NUM(tokens, ti, status); 187 if (status->status < 0) 188 return; 189 190 rule->port = atoi(tokens[ti]); 191 192 INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 193 if (status->status < 0) 194 return; 195 APP_CHECK_TOKEN_IS_NUM(tokens, ti, status); 196 if (status->status < 0) 197 return; 198 199 rule->queue = atoi(tokens[ti]); 200 } 201 } 202 203 nb_flow_rule++; 204 } 205 206 #define MAX_RTE_FLOW_PATTERN (3) 207 #define MAX_RTE_FLOW_ACTIONS (2) 208 209 static void 210 flow_init_single(struct flow_rule_entry *rule) 211 { 212 struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN] = {}; 213 struct rte_flow_action action[MAX_RTE_FLOW_ACTIONS] = {}; 214 struct rte_flow_attr attr = {}; 215 struct rte_flow_error err; 216 int ret; 217 218 attr.egress = 0; 219 attr.ingress = 1; 220 221 action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE; 222 action[0].conf = &(struct rte_flow_action_queue) { 223 .index = rule->queue, 224 }; 225 action[1].type = RTE_FLOW_ACTION_TYPE_END; 226 227 pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH; 228 229 if (rule->is_ipv4) { 230 pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4; 231 pattern[1].spec = &rule->ipv4.spec; 232 pattern[1].mask = &rule->ipv4.mask; 233 } else { 234 pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6; 235 pattern[1].spec = &rule->ipv6.spec; 236 pattern[1].mask = &rule->ipv6.mask; 237 } 238 239 pattern[2].type = RTE_FLOW_ITEM_TYPE_END; 240 241 ret = rte_flow_validate(rule->port, &attr, pattern, action, &err); 242 if (ret < 0) { 243 RTE_LOG(ERR, IPSEC, "Flow validation failed %s\n", err.message); 244 return; 245 } 246 247 rule->flow = rte_flow_create(rule->port, &attr, pattern, action, &err); 248 if (rule->flow == NULL) 249 RTE_LOG(ERR, IPSEC, "Flow creation return %s\n", err.message); 250 } 251 252 void 253 flow_init(void) 254 { 255 struct flow_rule_entry *rule; 256 int i; 257 258 for (i = 0; i < nb_flow_rule; i++) { 259 rule = &flow_rule_tbl[i]; 260 flow_init_single(rule); 261 } 262 263 for (i = 0; i < nb_flow_rule; i++) { 264 rule = &flow_rule_tbl[i]; 265 if (rule->is_ipv4) { 266 printf("Flow #%3d: spec ipv4 ", i); 267 ipv4_hdr_print(&rule->ipv4.spec.hdr); 268 printf("\n"); 269 printf(" mask ipv4 "); 270 ipv4_hdr_print(&rule->ipv4.mask.hdr); 271 } else { 272 printf("Flow #%3d: spec ipv6 ", i); 273 ipv6_hdr_print(&rule->ipv6.spec.hdr); 274 printf("\n"); 275 printf(" mask ipv6 "); 276 ipv6_hdr_print(&rule->ipv6.mask.hdr); 277 } 278 279 printf("\tPort: %d, Queue: %d", rule->port, rule->queue); 280 281 if (rule->flow == NULL) 282 printf(" [UNSUPPORTED]"); 283 printf("\n"); 284 } 285 } 286