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 193 if (strcmp(tokens[ti], "queue") == 0) { 194 INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 195 if (status->status < 0) 196 return; 197 APP_CHECK_TOKEN_IS_NUM(tokens, ti, status); 198 if (status->status < 0) 199 return; 200 201 rule->queue = atoi(tokens[ti]); 202 } 203 } 204 205 nb_flow_rule++; 206 } 207 208 #define MAX_RTE_FLOW_PATTERN (3) 209 #define MAX_RTE_FLOW_ACTIONS (2) 210 211 static void 212 flow_init_single(struct flow_rule_entry *rule) 213 { 214 struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN] = {}; 215 struct rte_flow_action action[MAX_RTE_FLOW_ACTIONS] = {}; 216 struct rte_flow_attr attr = {}; 217 struct rte_flow_error err; 218 int ret; 219 220 attr.egress = 0; 221 attr.ingress = 1; 222 223 action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE; 224 action[0].conf = &(struct rte_flow_action_queue) { 225 .index = rule->queue, 226 }; 227 action[1].type = RTE_FLOW_ACTION_TYPE_END; 228 229 pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH; 230 231 if (rule->is_ipv4) { 232 pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4; 233 pattern[1].spec = &rule->ipv4.spec; 234 pattern[1].mask = &rule->ipv4.mask; 235 } else { 236 pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6; 237 pattern[1].spec = &rule->ipv6.spec; 238 pattern[1].mask = &rule->ipv6.mask; 239 } 240 241 pattern[2].type = RTE_FLOW_ITEM_TYPE_END; 242 243 ret = rte_flow_validate(rule->port, &attr, pattern, action, &err); 244 if (ret < 0) { 245 RTE_LOG(ERR, IPSEC, "Flow validation failed %s\n", err.message); 246 return; 247 } 248 249 rule->flow = rte_flow_create(rule->port, &attr, pattern, action, &err); 250 if (rule->flow == NULL) 251 RTE_LOG(ERR, IPSEC, "Flow creation return %s\n", err.message); 252 } 253 254 void 255 flow_init(void) 256 { 257 struct flow_rule_entry *rule; 258 int i; 259 260 for (i = 0; i < nb_flow_rule; i++) { 261 rule = &flow_rule_tbl[i]; 262 flow_init_single(rule); 263 } 264 265 for (i = 0; i < nb_flow_rule; i++) { 266 rule = &flow_rule_tbl[i]; 267 if (rule->is_ipv4) { 268 printf("Flow #%3d: spec ipv4 ", i); 269 ipv4_hdr_print(&rule->ipv4.spec.hdr); 270 printf("\n"); 271 printf(" mask ipv4 "); 272 ipv4_hdr_print(&rule->ipv4.mask.hdr); 273 } else { 274 printf("Flow #%3d: spec ipv6 ", i); 275 ipv6_hdr_print(&rule->ipv6.spec.hdr); 276 printf("\n"); 277 printf(" mask ipv6 "); 278 ipv6_hdr_print(&rule->ipv6.mask.hdr); 279 } 280 281 printf("\tPort: %d, Queue: %d", rule->port, rule->queue); 282 283 if (rule->flow == NULL) 284 printf(" [UNSUPPORTED]"); 285 printf("\n"); 286 } 287 } 288