13998e2a0SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 23998e2a0SBruce Richardson * Copyright(c) 2016 Intel Corporation 3906257e9SSergio Gonzalez Monroy */ 4906257e9SSergio Gonzalez Monroy 5906257e9SSergio Gonzalez Monroy /* 6906257e9SSergio Gonzalez Monroy * Security Policies 7906257e9SSergio Gonzalez Monroy */ 8906257e9SSergio Gonzalez Monroy #include <sys/types.h> 9906257e9SSergio Gonzalez Monroy #include <netinet/in.h> 10906257e9SSergio Gonzalez Monroy #include <netinet/ip6.h> 11906257e9SSergio Gonzalez Monroy 12906257e9SSergio Gonzalez Monroy #include <rte_acl.h> 13906257e9SSergio Gonzalez Monroy #include <rte_ip.h> 14906257e9SSergio Gonzalez Monroy 15906257e9SSergio Gonzalez Monroy #include "ipsec.h" 160d547ed0SFan Zhang #include "parser.h" 17906257e9SSergio Gonzalez Monroy 18b0806375SVladimir Medvedkin #define INIT_ACL_RULE_NUM 128 19906257e9SSergio Gonzalez Monroy 20906257e9SSergio Gonzalez Monroy enum { 21906257e9SSergio Gonzalez Monroy IP6_PROTO, 22906257e9SSergio Gonzalez Monroy IP6_SRC0, 23906257e9SSergio Gonzalez Monroy IP6_SRC1, 24906257e9SSergio Gonzalez Monroy IP6_SRC2, 25906257e9SSergio Gonzalez Monroy IP6_SRC3, 26906257e9SSergio Gonzalez Monroy IP6_DST0, 27906257e9SSergio Gonzalez Monroy IP6_DST1, 28906257e9SSergio Gonzalez Monroy IP6_DST2, 29906257e9SSergio Gonzalez Monroy IP6_DST3, 30906257e9SSergio Gonzalez Monroy IP6_SRCP, 31906257e9SSergio Gonzalez Monroy IP6_DSTP, 32906257e9SSergio Gonzalez Monroy IP6_NUM 33906257e9SSergio Gonzalez Monroy }; 34906257e9SSergio Gonzalez Monroy 35d92fc70eSKonstantin Ananyev static struct rte_acl_field_def ip6_defs[IP6_NUM] = { 36906257e9SSergio Gonzalez Monroy { 37906257e9SSergio Gonzalez Monroy .type = RTE_ACL_FIELD_TYPE_BITMASK, 38906257e9SSergio Gonzalez Monroy .size = sizeof(uint8_t), 39906257e9SSergio Gonzalez Monroy .field_index = IP6_PROTO, 40906257e9SSergio Gonzalez Monroy .input_index = IP6_PROTO, 41906257e9SSergio Gonzalez Monroy .offset = 0, 42906257e9SSergio Gonzalez Monroy }, 43906257e9SSergio Gonzalez Monroy { 44906257e9SSergio Gonzalez Monroy .type = RTE_ACL_FIELD_TYPE_MASK, 45906257e9SSergio Gonzalez Monroy .size = 4, 46906257e9SSergio Gonzalez Monroy .field_index = IP6_SRC0, 47906257e9SSergio Gonzalez Monroy .input_index = IP6_SRC0, 48906257e9SSergio Gonzalez Monroy .offset = 2 49906257e9SSergio Gonzalez Monroy }, 50906257e9SSergio Gonzalez Monroy { 51906257e9SSergio Gonzalez Monroy .type = RTE_ACL_FIELD_TYPE_MASK, 52906257e9SSergio Gonzalez Monroy .size = 4, 53906257e9SSergio Gonzalez Monroy .field_index = IP6_SRC1, 54906257e9SSergio Gonzalez Monroy .input_index = IP6_SRC1, 55906257e9SSergio Gonzalez Monroy .offset = 6 56906257e9SSergio Gonzalez Monroy }, 57906257e9SSergio Gonzalez Monroy { 58906257e9SSergio Gonzalez Monroy .type = RTE_ACL_FIELD_TYPE_MASK, 59906257e9SSergio Gonzalez Monroy .size = 4, 60906257e9SSergio Gonzalez Monroy .field_index = IP6_SRC2, 61906257e9SSergio Gonzalez Monroy .input_index = IP6_SRC2, 62906257e9SSergio Gonzalez Monroy .offset = 10 63906257e9SSergio Gonzalez Monroy }, 64906257e9SSergio Gonzalez Monroy { 65906257e9SSergio Gonzalez Monroy .type = RTE_ACL_FIELD_TYPE_MASK, 66906257e9SSergio Gonzalez Monroy .size = 4, 67906257e9SSergio Gonzalez Monroy .field_index = IP6_SRC3, 68906257e9SSergio Gonzalez Monroy .input_index = IP6_SRC3, 69906257e9SSergio Gonzalez Monroy .offset = 14 70906257e9SSergio Gonzalez Monroy }, 71906257e9SSergio Gonzalez Monroy { 72906257e9SSergio Gonzalez Monroy .type = RTE_ACL_FIELD_TYPE_MASK, 73906257e9SSergio Gonzalez Monroy .size = 4, 74906257e9SSergio Gonzalez Monroy .field_index = IP6_DST0, 75906257e9SSergio Gonzalez Monroy .input_index = IP6_DST0, 76906257e9SSergio Gonzalez Monroy .offset = 18 77906257e9SSergio Gonzalez Monroy }, 78906257e9SSergio Gonzalez Monroy { 79906257e9SSergio Gonzalez Monroy .type = RTE_ACL_FIELD_TYPE_MASK, 80906257e9SSergio Gonzalez Monroy .size = 4, 81906257e9SSergio Gonzalez Monroy .field_index = IP6_DST1, 82906257e9SSergio Gonzalez Monroy .input_index = IP6_DST1, 83906257e9SSergio Gonzalez Monroy .offset = 22 84906257e9SSergio Gonzalez Monroy }, 85906257e9SSergio Gonzalez Monroy { 86906257e9SSergio Gonzalez Monroy .type = RTE_ACL_FIELD_TYPE_MASK, 87906257e9SSergio Gonzalez Monroy .size = 4, 88906257e9SSergio Gonzalez Monroy .field_index = IP6_DST2, 89906257e9SSergio Gonzalez Monroy .input_index = IP6_DST2, 90906257e9SSergio Gonzalez Monroy .offset = 26 91906257e9SSergio Gonzalez Monroy }, 92906257e9SSergio Gonzalez Monroy { 93906257e9SSergio Gonzalez Monroy .type = RTE_ACL_FIELD_TYPE_MASK, 94906257e9SSergio Gonzalez Monroy .size = 4, 95906257e9SSergio Gonzalez Monroy .field_index = IP6_DST3, 96906257e9SSergio Gonzalez Monroy .input_index = IP6_DST3, 97906257e9SSergio Gonzalez Monroy .offset = 30 98906257e9SSergio Gonzalez Monroy }, 99906257e9SSergio Gonzalez Monroy { 100906257e9SSergio Gonzalez Monroy .type = RTE_ACL_FIELD_TYPE_RANGE, 101906257e9SSergio Gonzalez Monroy .size = sizeof(uint16_t), 102906257e9SSergio Gonzalez Monroy .field_index = IP6_SRCP, 103906257e9SSergio Gonzalez Monroy .input_index = IP6_SRCP, 104906257e9SSergio Gonzalez Monroy .offset = 34 105906257e9SSergio Gonzalez Monroy }, 106906257e9SSergio Gonzalez Monroy { 107906257e9SSergio Gonzalez Monroy .type = RTE_ACL_FIELD_TYPE_RANGE, 108906257e9SSergio Gonzalez Monroy .size = sizeof(uint16_t), 109906257e9SSergio Gonzalez Monroy .field_index = IP6_DSTP, 110906257e9SSergio Gonzalez Monroy .input_index = IP6_SRCP, 111906257e9SSergio Gonzalez Monroy .offset = 36 112906257e9SSergio Gonzalez Monroy } 113906257e9SSergio Gonzalez Monroy }; 114906257e9SSergio Gonzalez Monroy 115906257e9SSergio Gonzalez Monroy RTE_ACL_RULE_DEF(acl6_rules, RTE_DIM(ip6_defs)); 116906257e9SSergio Gonzalez Monroy 117b0806375SVladimir Medvedkin static struct acl6_rules *acl6_rules_out; 118d92fc70eSKonstantin Ananyev static uint32_t nb_acl6_rules_out; 119b0806375SVladimir Medvedkin static uint32_t sp_out_sz; 120906257e9SSergio Gonzalez Monroy 121b0806375SVladimir Medvedkin static struct acl6_rules *acl6_rules_in; 122d92fc70eSKonstantin Ananyev static uint32_t nb_acl6_rules_in; 123b0806375SVladimir Medvedkin static uint32_t sp_in_sz; 124b0806375SVladimir Medvedkin 125*9ac91e2fSRobin Jarry static struct rte_ipv6_addr 126*9ac91e2fSRobin Jarry ipv6_src_from_sp(const struct acl6_rules *rule) 127*9ac91e2fSRobin Jarry { 128*9ac91e2fSRobin Jarry struct rte_ipv6_addr alignas(alignof(rte_be64_t)) addr = RTE_IPV6_ADDR_UNSPEC; 129*9ac91e2fSRobin Jarry rte_be64_t *values = (rte_be64_t *)&addr; 130*9ac91e2fSRobin Jarry 131*9ac91e2fSRobin Jarry values[0] = rte_cpu_to_be_64((uint64_t)rule->field[IP6_SRC0].value.u32 << 32 | 132*9ac91e2fSRobin Jarry rule->field[IP6_SRC1].value.u32); 133*9ac91e2fSRobin Jarry values[1] = rte_cpu_to_be_64((uint64_t)rule->field[IP6_SRC2].value.u32 << 32 | 134*9ac91e2fSRobin Jarry rule->field[IP6_SRC3].value.u32); 135*9ac91e2fSRobin Jarry 136*9ac91e2fSRobin Jarry return addr; 137*9ac91e2fSRobin Jarry } 138*9ac91e2fSRobin Jarry 139*9ac91e2fSRobin Jarry static struct rte_ipv6_addr 140*9ac91e2fSRobin Jarry ipv6_dst_from_sp(const struct acl6_rules *rule) 141*9ac91e2fSRobin Jarry { 142*9ac91e2fSRobin Jarry struct rte_ipv6_addr alignas(alignof(rte_be64_t)) addr = RTE_IPV6_ADDR_UNSPEC; 143*9ac91e2fSRobin Jarry rte_be64_t *values = (rte_be64_t *)&addr; 144*9ac91e2fSRobin Jarry 145*9ac91e2fSRobin Jarry values[0] = rte_cpu_to_be_64((uint64_t)rule->field[IP6_DST0].value.u32 << 32 | 146*9ac91e2fSRobin Jarry rule->field[IP6_DST1].value.u32); 147*9ac91e2fSRobin Jarry values[1] = rte_cpu_to_be_64((uint64_t)rule->field[IP6_DST2].value.u32 << 32 | 148*9ac91e2fSRobin Jarry rule->field[IP6_DST3].value.u32); 149*9ac91e2fSRobin Jarry 150*9ac91e2fSRobin Jarry return addr; 151*9ac91e2fSRobin Jarry } 152*9ac91e2fSRobin Jarry 153*9ac91e2fSRobin Jarry static uint32_t 154*9ac91e2fSRobin Jarry ipv6_src_mask_from_sp(const struct acl6_rules *rule) 155*9ac91e2fSRobin Jarry { 156*9ac91e2fSRobin Jarry return rule->field[IP6_SRC0].mask_range.u32 + 157*9ac91e2fSRobin Jarry rule->field[IP6_SRC1].mask_range.u32 + 158*9ac91e2fSRobin Jarry rule->field[IP6_SRC2].mask_range.u32 + 159*9ac91e2fSRobin Jarry rule->field[IP6_SRC3].mask_range.u32; 160*9ac91e2fSRobin Jarry } 161*9ac91e2fSRobin Jarry 162*9ac91e2fSRobin Jarry static uint32_t 163*9ac91e2fSRobin Jarry ipv6_dst_mask_from_sp(const struct acl6_rules *rule) 164*9ac91e2fSRobin Jarry { 165*9ac91e2fSRobin Jarry return rule->field[IP6_DST0].mask_range.u32 + 166*9ac91e2fSRobin Jarry rule->field[IP6_DST1].mask_range.u32 + 167*9ac91e2fSRobin Jarry rule->field[IP6_DST2].mask_range.u32 + 168*9ac91e2fSRobin Jarry rule->field[IP6_DST3].mask_range.u32; 169*9ac91e2fSRobin Jarry } 170*9ac91e2fSRobin Jarry 171b0806375SVladimir Medvedkin static int 172b0806375SVladimir Medvedkin extend_sp_arr(struct acl6_rules **sp_tbl, uint32_t cur_cnt, uint32_t *cur_sz) 173b0806375SVladimir Medvedkin { 174b0806375SVladimir Medvedkin if (*sp_tbl == NULL) { 175b0806375SVladimir Medvedkin *sp_tbl = calloc(INIT_ACL_RULE_NUM, sizeof(struct acl6_rules)); 176b0806375SVladimir Medvedkin if (*sp_tbl == NULL) 177b0806375SVladimir Medvedkin return -1; 178b0806375SVladimir Medvedkin *cur_sz = INIT_ACL_RULE_NUM; 179b0806375SVladimir Medvedkin return 0; 180b0806375SVladimir Medvedkin } 181b0806375SVladimir Medvedkin 182b0806375SVladimir Medvedkin if (cur_cnt >= *cur_sz) { 183b0806375SVladimir Medvedkin *sp_tbl = realloc(*sp_tbl, 184b0806375SVladimir Medvedkin *cur_sz * sizeof(struct acl6_rules) * 2); 185b0806375SVladimir Medvedkin if (*sp_tbl == NULL) 186b0806375SVladimir Medvedkin return -1; 187b0806375SVladimir Medvedkin /* clean reallocated extra space */ 188b0806375SVladimir Medvedkin memset(&(*sp_tbl)[*cur_sz], 0, 189b0806375SVladimir Medvedkin *cur_sz * sizeof(struct acl6_rules)); 190b0806375SVladimir Medvedkin *cur_sz *= 2; 191b0806375SVladimir Medvedkin } 192b0806375SVladimir Medvedkin 193b0806375SVladimir Medvedkin return 0; 194b0806375SVladimir Medvedkin } 1950d547ed0SFan Zhang 1960d547ed0SFan Zhang void 1970d547ed0SFan Zhang parse_sp6_tokens(char **tokens, uint32_t n_tokens, 1980d547ed0SFan Zhang struct parse_status *status) 199906257e9SSergio Gonzalez Monroy { 2000d547ed0SFan Zhang struct acl6_rules *rule_ipv6 = NULL; 2010d547ed0SFan Zhang 2020d547ed0SFan Zhang uint32_t *ri = NULL; /* rule index */ 2030d547ed0SFan Zhang uint32_t ti = 0; /* token index */ 20449757b68SKonstantin Ananyev uint32_t tv; 2050d547ed0SFan Zhang 2060d547ed0SFan Zhang uint32_t esp_p = 0; 2070d547ed0SFan Zhang uint32_t protect_p = 0; 2080d547ed0SFan Zhang uint32_t bypass_p = 0; 2090d547ed0SFan Zhang uint32_t discard_p = 0; 2100d547ed0SFan Zhang uint32_t pri_p = 0; 2110d547ed0SFan Zhang uint32_t src_p = 0; 2120d547ed0SFan Zhang uint32_t dst_p = 0; 2130d547ed0SFan Zhang uint32_t proto_p = 0; 2140d547ed0SFan Zhang uint32_t sport_p = 0; 2150d547ed0SFan Zhang uint32_t dport_p = 0; 2160d547ed0SFan Zhang 2170d547ed0SFan Zhang if (strcmp(tokens[1], "in") == 0) { 2180d547ed0SFan Zhang ri = &nb_acl6_rules_in; 2190d547ed0SFan Zhang 220b0806375SVladimir Medvedkin if (extend_sp_arr(&acl6_rules_in, nb_acl6_rules_in, 221b0806375SVladimir Medvedkin &sp_in_sz) < 0) 2220d547ed0SFan Zhang return; 2230d547ed0SFan Zhang 2240d547ed0SFan Zhang rule_ipv6 = &acl6_rules_in[*ri]; 2250d547ed0SFan Zhang 2260d547ed0SFan Zhang } else if (strcmp(tokens[1], "out") == 0) { 2270d547ed0SFan Zhang ri = &nb_acl6_rules_out; 2280d547ed0SFan Zhang 229b0806375SVladimir Medvedkin if (extend_sp_arr(&acl6_rules_out, nb_acl6_rules_out, 230b0806375SVladimir Medvedkin &sp_out_sz) < 0) 2310d547ed0SFan Zhang return; 2320d547ed0SFan Zhang 2330d547ed0SFan Zhang rule_ipv6 = &acl6_rules_out[*ri]; 2340d547ed0SFan Zhang 2350d547ed0SFan Zhang } else { 2360d547ed0SFan Zhang APP_CHECK(0, status, "unrecognized input \"%s\", expect" 2370d547ed0SFan Zhang " \"in\" or \"out\"\n", tokens[ti]); 2380d547ed0SFan Zhang return; 239906257e9SSergio Gonzalez Monroy } 2400d547ed0SFan Zhang 2410d547ed0SFan Zhang rule_ipv6->data.category_mask = 1; 2420d547ed0SFan Zhang 2430d547ed0SFan Zhang 2440d547ed0SFan Zhang for (ti = 2; ti < n_tokens; ti++) { 2450d547ed0SFan Zhang if (strcmp(tokens[ti], "esp") == 0) { 2460d547ed0SFan Zhang /* currently do nothing */ 2470d547ed0SFan Zhang APP_CHECK_PRESENCE(esp_p, tokens[ti], status); 2480d547ed0SFan Zhang if (status->status < 0) 2490d547ed0SFan Zhang return; 2500d547ed0SFan Zhang esp_p = 1; 2510d547ed0SFan Zhang continue; 2520d547ed0SFan Zhang } 2530d547ed0SFan Zhang 2540d547ed0SFan Zhang if (strcmp(tokens[ti], "protect") == 0) { 2550d547ed0SFan Zhang APP_CHECK_PRESENCE(protect_p, tokens[ti], status); 2560d547ed0SFan Zhang if (status->status < 0) 2570d547ed0SFan Zhang return; 2580d547ed0SFan Zhang APP_CHECK(bypass_p == 0, status, "conflict item " 2590d547ed0SFan Zhang "between \"%s\" and \"%s\"", tokens[ti], 2600d547ed0SFan Zhang "bypass"); 2610d547ed0SFan Zhang if (status->status < 0) 2620d547ed0SFan Zhang return; 2630d547ed0SFan Zhang APP_CHECK(discard_p == 0, status, "conflict item " 2640d547ed0SFan Zhang "between \"%s\" and \"%s\"", tokens[ti], 2650d547ed0SFan Zhang "discard"); 2660d547ed0SFan Zhang if (status->status < 0) 2670d547ed0SFan Zhang return; 2680d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 2690d547ed0SFan Zhang if (status->status < 0) 2700d547ed0SFan Zhang return; 2710d547ed0SFan Zhang APP_CHECK_TOKEN_IS_NUM(tokens, ti, status); 2720d547ed0SFan Zhang if (status->status < 0) 2730d547ed0SFan Zhang return; 2740d547ed0SFan Zhang 27549757b68SKonstantin Ananyev tv = atoi(tokens[ti]); 27649757b68SKonstantin Ananyev APP_CHECK(tv != DISCARD && tv != BYPASS, status, 27749757b68SKonstantin Ananyev "invalid SPI: %s", tokens[ti]); 27849757b68SKonstantin Ananyev if (status->status < 0) 27949757b68SKonstantin Ananyev return; 28049757b68SKonstantin Ananyev rule_ipv6->data.userdata = tv; 2810d547ed0SFan Zhang 2820d547ed0SFan Zhang protect_p = 1; 2830d547ed0SFan Zhang continue; 2840d547ed0SFan Zhang } 2850d547ed0SFan Zhang 2860d547ed0SFan Zhang if (strcmp(tokens[ti], "bypass") == 0) { 2870d547ed0SFan Zhang APP_CHECK_PRESENCE(bypass_p, tokens[ti], status); 2880d547ed0SFan Zhang if (status->status < 0) 2890d547ed0SFan Zhang return; 2900d547ed0SFan Zhang APP_CHECK(protect_p == 0, status, "conflict item " 2910d547ed0SFan Zhang "between \"%s\" and \"%s\"", tokens[ti], 2920d547ed0SFan Zhang "protect"); 2930d547ed0SFan Zhang if (status->status < 0) 2940d547ed0SFan Zhang return; 2950d547ed0SFan Zhang APP_CHECK(discard_p == 0, status, "conflict item " 2960d547ed0SFan Zhang "between \"%s\" and \"%s\"", tokens[ti], 2970d547ed0SFan Zhang "discard"); 2980d547ed0SFan Zhang if (status->status < 0) 2990d547ed0SFan Zhang return; 3000d547ed0SFan Zhang 3010d547ed0SFan Zhang rule_ipv6->data.userdata = BYPASS; 3020d547ed0SFan Zhang 3030d547ed0SFan Zhang bypass_p = 1; 3040d547ed0SFan Zhang continue; 3050d547ed0SFan Zhang } 3060d547ed0SFan Zhang 3070d547ed0SFan Zhang if (strcmp(tokens[ti], "discard") == 0) { 3080d547ed0SFan Zhang APP_CHECK_PRESENCE(discard_p, tokens[ti], status); 3090d547ed0SFan Zhang if (status->status < 0) 3100d547ed0SFan Zhang return; 3110d547ed0SFan Zhang APP_CHECK(protect_p == 0, status, "conflict item " 3120d547ed0SFan Zhang "between \"%s\" and \"%s\"", tokens[ti], 3130d547ed0SFan Zhang "protect"); 3140d547ed0SFan Zhang if (status->status < 0) 3150d547ed0SFan Zhang return; 3160d547ed0SFan Zhang APP_CHECK(bypass_p == 0, status, "conflict item " 3170d547ed0SFan Zhang "between \"%s\" and \"%s\"", tokens[ti], 3180d547ed0SFan Zhang "discard"); 3190d547ed0SFan Zhang if (status->status < 0) 3200d547ed0SFan Zhang return; 3210d547ed0SFan Zhang 3220d547ed0SFan Zhang rule_ipv6->data.userdata = DISCARD; 3230d547ed0SFan Zhang 3240d547ed0SFan Zhang discard_p = 1; 3250d547ed0SFan Zhang continue; 3260d547ed0SFan Zhang } 3270d547ed0SFan Zhang 3280d547ed0SFan Zhang if (strcmp(tokens[ti], "pri") == 0) { 3290d547ed0SFan Zhang APP_CHECK_PRESENCE(pri_p, tokens[ti], status); 3300d547ed0SFan Zhang if (status->status < 0) 3310d547ed0SFan Zhang return; 3320d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 3330d547ed0SFan Zhang if (status->status < 0) 3340d547ed0SFan Zhang return; 3350d547ed0SFan Zhang APP_CHECK_TOKEN_IS_NUM(tokens, ti, status); 3360d547ed0SFan Zhang if (status->status < 0) 3370d547ed0SFan Zhang return; 3380d547ed0SFan Zhang 3390d547ed0SFan Zhang rule_ipv6->data.priority = atoi(tokens[ti]); 3400d547ed0SFan Zhang 3410d547ed0SFan Zhang pri_p = 1; 3420d547ed0SFan Zhang continue; 3430d547ed0SFan Zhang } 3440d547ed0SFan Zhang 3450d547ed0SFan Zhang if (strcmp(tokens[ti], "src") == 0) { 346*9ac91e2fSRobin Jarry struct rte_ipv6_addr ip; 3470d547ed0SFan Zhang uint32_t depth; 3480d547ed0SFan Zhang 3490d547ed0SFan Zhang APP_CHECK_PRESENCE(src_p, tokens[ti], status); 3500d547ed0SFan Zhang if (status->status < 0) 3510d547ed0SFan Zhang return; 3520d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 3530d547ed0SFan Zhang if (status->status < 0) 3540d547ed0SFan Zhang return; 3550d547ed0SFan Zhang 3560d547ed0SFan Zhang APP_CHECK(parse_ipv6_addr(tokens[ti], &ip, 3570d547ed0SFan Zhang &depth) == 0, status, "unrecognized " 3580d547ed0SFan Zhang "input \"%s\", expect valid ipv6 " 3590d547ed0SFan Zhang "addr", tokens[ti]); 3600d547ed0SFan Zhang if (status->status < 0) 3610d547ed0SFan Zhang return; 3620d547ed0SFan Zhang 3630d547ed0SFan Zhang rule_ipv6->field[1].value.u32 = 364*9ac91e2fSRobin Jarry (uint32_t)ip.a[0] << 24 | 365*9ac91e2fSRobin Jarry (uint32_t)ip.a[1] << 16 | 366*9ac91e2fSRobin Jarry (uint32_t)ip.a[2] << 8 | 367*9ac91e2fSRobin Jarry (uint32_t)ip.a[3]; 3680d547ed0SFan Zhang rule_ipv6->field[1].mask_range.u32 = 3690d547ed0SFan Zhang (depth > 32) ? 32 : depth; 3700d547ed0SFan Zhang depth = (depth > 32) ? (depth - 32) : 0; 3710d547ed0SFan Zhang rule_ipv6->field[2].value.u32 = 372*9ac91e2fSRobin Jarry (uint32_t)ip.a[4] << 24 | 373*9ac91e2fSRobin Jarry (uint32_t)ip.a[5] << 16 | 374*9ac91e2fSRobin Jarry (uint32_t)ip.a[6] << 8 | 375*9ac91e2fSRobin Jarry (uint32_t)ip.a[7]; 3760d547ed0SFan Zhang rule_ipv6->field[2].mask_range.u32 = 3770d547ed0SFan Zhang (depth > 32) ? 32 : depth; 3780d547ed0SFan Zhang depth = (depth > 32) ? (depth - 32) : 0; 3790d547ed0SFan Zhang rule_ipv6->field[3].value.u32 = 380*9ac91e2fSRobin Jarry (uint32_t)ip.a[8] << 24 | 381*9ac91e2fSRobin Jarry (uint32_t)ip.a[9] << 16 | 382*9ac91e2fSRobin Jarry (uint32_t)ip.a[10] << 8 | 383*9ac91e2fSRobin Jarry (uint32_t)ip.a[11]; 3840d547ed0SFan Zhang rule_ipv6->field[3].mask_range.u32 = 3850d547ed0SFan Zhang (depth > 32) ? 32 : depth; 3860d547ed0SFan Zhang depth = (depth > 32) ? (depth - 32) : 0; 3870d547ed0SFan Zhang rule_ipv6->field[4].value.u32 = 388*9ac91e2fSRobin Jarry (uint32_t)ip.a[12] << 24 | 389*9ac91e2fSRobin Jarry (uint32_t)ip.a[13] << 16 | 390*9ac91e2fSRobin Jarry (uint32_t)ip.a[14] << 8 | 391*9ac91e2fSRobin Jarry (uint32_t)ip.a[15]; 3920d547ed0SFan Zhang rule_ipv6->field[4].mask_range.u32 = 3930d547ed0SFan Zhang (depth > 32) ? 32 : depth; 3940d547ed0SFan Zhang 3950d547ed0SFan Zhang src_p = 1; 3960d547ed0SFan Zhang continue; 3970d547ed0SFan Zhang } 3980d547ed0SFan Zhang 3990d547ed0SFan Zhang if (strcmp(tokens[ti], "dst") == 0) { 400*9ac91e2fSRobin Jarry struct rte_ipv6_addr ip; 4010d547ed0SFan Zhang uint32_t depth; 4020d547ed0SFan Zhang 4030d547ed0SFan Zhang APP_CHECK_PRESENCE(dst_p, tokens[ti], status); 4040d547ed0SFan Zhang if (status->status < 0) 4050d547ed0SFan Zhang return; 4060d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 4070d547ed0SFan Zhang if (status->status < 0) 4080d547ed0SFan Zhang return; 4090d547ed0SFan Zhang 4100d547ed0SFan Zhang APP_CHECK(parse_ipv6_addr(tokens[ti], &ip, 4110d547ed0SFan Zhang &depth) == 0, status, "unrecognized " 4120d547ed0SFan Zhang "input \"%s\", expect valid ipv6 " 4130d547ed0SFan Zhang "addr", tokens[ti]); 4140d547ed0SFan Zhang if (status->status < 0) 4150d547ed0SFan Zhang return; 4160d547ed0SFan Zhang 4170d547ed0SFan Zhang rule_ipv6->field[5].value.u32 = 418*9ac91e2fSRobin Jarry (uint32_t)ip.a[0] << 24 | 419*9ac91e2fSRobin Jarry (uint32_t)ip.a[1] << 16 | 420*9ac91e2fSRobin Jarry (uint32_t)ip.a[2] << 8 | 421*9ac91e2fSRobin Jarry (uint32_t)ip.a[3]; 4220d547ed0SFan Zhang rule_ipv6->field[5].mask_range.u32 = 4230d547ed0SFan Zhang (depth > 32) ? 32 : depth; 4240d547ed0SFan Zhang depth = (depth > 32) ? (depth - 32) : 0; 4250d547ed0SFan Zhang rule_ipv6->field[6].value.u32 = 426*9ac91e2fSRobin Jarry (uint32_t)ip.a[4] << 24 | 427*9ac91e2fSRobin Jarry (uint32_t)ip.a[5] << 16 | 428*9ac91e2fSRobin Jarry (uint32_t)ip.a[6] << 8 | 429*9ac91e2fSRobin Jarry (uint32_t)ip.a[7]; 4300d547ed0SFan Zhang rule_ipv6->field[6].mask_range.u32 = 4310d547ed0SFan Zhang (depth > 32) ? 32 : depth; 4320d547ed0SFan Zhang depth = (depth > 32) ? (depth - 32) : 0; 4330d547ed0SFan Zhang rule_ipv6->field[7].value.u32 = 434*9ac91e2fSRobin Jarry (uint32_t)ip.a[8] << 24 | 435*9ac91e2fSRobin Jarry (uint32_t)ip.a[9] << 16 | 436*9ac91e2fSRobin Jarry (uint32_t)ip.a[10] << 8 | 437*9ac91e2fSRobin Jarry (uint32_t)ip.a[11]; 4380d547ed0SFan Zhang rule_ipv6->field[7].mask_range.u32 = 4390d547ed0SFan Zhang (depth > 32) ? 32 : depth; 4400d547ed0SFan Zhang depth = (depth > 32) ? (depth - 32) : 0; 4410d547ed0SFan Zhang rule_ipv6->field[8].value.u32 = 442*9ac91e2fSRobin Jarry (uint32_t)ip.a[12] << 24 | 443*9ac91e2fSRobin Jarry (uint32_t)ip.a[13] << 16 | 444*9ac91e2fSRobin Jarry (uint32_t)ip.a[14] << 8 | 445*9ac91e2fSRobin Jarry (uint32_t)ip.a[15]; 4460d547ed0SFan Zhang rule_ipv6->field[8].mask_range.u32 = 4470d547ed0SFan Zhang (depth > 32) ? 32 : depth; 4480d547ed0SFan Zhang 4490d547ed0SFan Zhang dst_p = 1; 4500d547ed0SFan Zhang continue; 4510d547ed0SFan Zhang } 4520d547ed0SFan Zhang 4530d547ed0SFan Zhang if (strcmp(tokens[ti], "proto") == 0) { 4540d547ed0SFan Zhang uint16_t low, high; 4550d547ed0SFan Zhang 4560d547ed0SFan Zhang APP_CHECK_PRESENCE(proto_p, tokens[ti], status); 4570d547ed0SFan Zhang if (status->status < 0) 4580d547ed0SFan Zhang return; 4590d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 4600d547ed0SFan Zhang if (status->status < 0) 4610d547ed0SFan Zhang return; 4620d547ed0SFan Zhang 4630d547ed0SFan Zhang APP_CHECK(parse_range(tokens[ti], &low, &high) 4640d547ed0SFan Zhang == 0, status, "unrecognized input \"%s\"" 4650d547ed0SFan Zhang ", expect \"from:to\"", tokens[ti]); 4660d547ed0SFan Zhang if (status->status < 0) 4670d547ed0SFan Zhang return; 4680d547ed0SFan Zhang APP_CHECK(low <= 0xff, status, "proto low " 4690d547ed0SFan Zhang "over-limit"); 4700d547ed0SFan Zhang if (status->status < 0) 4710d547ed0SFan Zhang return; 4720d547ed0SFan Zhang APP_CHECK(high <= 0xff, status, "proto high " 4730d547ed0SFan Zhang "over-limit"); 4740d547ed0SFan Zhang if (status->status < 0) 4750d547ed0SFan Zhang return; 4760d547ed0SFan Zhang 4770d547ed0SFan Zhang rule_ipv6->field[0].value.u8 = (uint8_t)low; 4780d547ed0SFan Zhang rule_ipv6->field[0].mask_range.u8 = (uint8_t)high; 4790d547ed0SFan Zhang 4800d547ed0SFan Zhang proto_p = 1; 4810d547ed0SFan Zhang continue; 4820d547ed0SFan Zhang } 4830d547ed0SFan Zhang 4840d547ed0SFan Zhang if (strcmp(tokens[ti], "sport") == 0) { 4850d547ed0SFan Zhang uint16_t port_low, port_high; 4860d547ed0SFan Zhang 4870d547ed0SFan Zhang APP_CHECK_PRESENCE(sport_p, tokens[ti], status); 4880d547ed0SFan Zhang if (status->status < 0) 4890d547ed0SFan Zhang return; 4900d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 4910d547ed0SFan Zhang if (status->status < 0) 4920d547ed0SFan Zhang return; 4930d547ed0SFan Zhang 4940d547ed0SFan Zhang APP_CHECK(parse_range(tokens[ti], &port_low, 4950d547ed0SFan Zhang &port_high) == 0, status, "unrecognized " 4960d547ed0SFan Zhang "input \"%s\", expect \"port_from:" 4970d547ed0SFan Zhang "port_to\"", tokens[ti]); 4980d547ed0SFan Zhang if (status->status < 0) 4990d547ed0SFan Zhang return; 5000d547ed0SFan Zhang 5010d547ed0SFan Zhang rule_ipv6->field[9].value.u16 = port_low; 5020d547ed0SFan Zhang rule_ipv6->field[9].mask_range.u16 = port_high; 5030d547ed0SFan Zhang 5040d547ed0SFan Zhang sport_p = 1; 5050d547ed0SFan Zhang continue; 5060d547ed0SFan Zhang } 5070d547ed0SFan Zhang 5080d547ed0SFan Zhang if (strcmp(tokens[ti], "dport") == 0) { 5090d547ed0SFan Zhang uint16_t port_low, port_high; 5100d547ed0SFan Zhang 5110d547ed0SFan Zhang APP_CHECK_PRESENCE(dport_p, tokens[ti], status); 5120d547ed0SFan Zhang if (status->status < 0) 5130d547ed0SFan Zhang return; 5140d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 5150d547ed0SFan Zhang if (status->status < 0) 5160d547ed0SFan Zhang return; 5170d547ed0SFan Zhang 5180d547ed0SFan Zhang APP_CHECK(parse_range(tokens[ti], &port_low, 5190d547ed0SFan Zhang &port_high) == 0, status, "unrecognized " 5200d547ed0SFan Zhang "input \"%s\", expect \"port_from:" 5210d547ed0SFan Zhang "port_to\"", tokens[ti]); 5220d547ed0SFan Zhang if (status->status < 0) 5230d547ed0SFan Zhang return; 5240d547ed0SFan Zhang 5250d547ed0SFan Zhang rule_ipv6->field[10].value.u16 = port_low; 5260d547ed0SFan Zhang rule_ipv6->field[10].mask_range.u16 = port_high; 5270d547ed0SFan Zhang 5280d547ed0SFan Zhang dport_p = 1; 5290d547ed0SFan Zhang continue; 5300d547ed0SFan Zhang } 5310d547ed0SFan Zhang 5327be78d02SJosh Soref /* unrecognizable input */ 5330d547ed0SFan Zhang APP_CHECK(0, status, "unrecognized input \"%s\"", 5340d547ed0SFan Zhang tokens[ti]); 5350d547ed0SFan Zhang return; 5360d547ed0SFan Zhang } 5370d547ed0SFan Zhang 5380d547ed0SFan Zhang /* check if argument(s) are missing */ 5390d547ed0SFan Zhang APP_CHECK(esp_p == 1, status, "missing argument \"esp\""); 5400d547ed0SFan Zhang if (status->status < 0) 5410d547ed0SFan Zhang return; 5420d547ed0SFan Zhang 5430d547ed0SFan Zhang APP_CHECK(protect_p | bypass_p | discard_p, status, "missing " 5440d547ed0SFan Zhang "argument \"protect\", \"bypass\", or \"discard\""); 5450d547ed0SFan Zhang if (status->status < 0) 5460d547ed0SFan Zhang return; 5470d547ed0SFan Zhang 5480d547ed0SFan Zhang *ri = *ri + 1; 5490d547ed0SFan Zhang } 550906257e9SSergio Gonzalez Monroy 551906257e9SSergio Gonzalez Monroy static inline void 552906257e9SSergio Gonzalez Monroy print_one_ip6_rule(const struct acl6_rules *rule, int32_t extra) 553906257e9SSergio Gonzalez Monroy { 554906257e9SSergio Gonzalez Monroy uint8_t a, b, c, d; 555906257e9SSergio Gonzalez Monroy 556906257e9SSergio Gonzalez Monroy uint32_t_to_char(rule->field[IP6_SRC0].value.u32, 557906257e9SSergio Gonzalez Monroy &a, &b, &c, &d); 558906257e9SSergio Gonzalez Monroy printf("%.2x%.2x:%.2x%.2x", a, b, c, d); 559906257e9SSergio Gonzalez Monroy uint32_t_to_char(rule->field[IP6_SRC1].value.u32, 560906257e9SSergio Gonzalez Monroy &a, &b, &c, &d); 561906257e9SSergio Gonzalez Monroy printf(":%.2x%.2x:%.2x%.2x", a, b, c, d); 562906257e9SSergio Gonzalez Monroy uint32_t_to_char(rule->field[IP6_SRC2].value.u32, 563906257e9SSergio Gonzalez Monroy &a, &b, &c, &d); 564906257e9SSergio Gonzalez Monroy printf(":%.2x%.2x:%.2x%.2x", a, b, c, d); 565906257e9SSergio Gonzalez Monroy uint32_t_to_char(rule->field[IP6_SRC3].value.u32, 566906257e9SSergio Gonzalez Monroy &a, &b, &c, &d); 567906257e9SSergio Gonzalez Monroy printf(":%.2x%.2x:%.2x%.2x/%u ", a, b, c, d, 568906257e9SSergio Gonzalez Monroy rule->field[IP6_SRC0].mask_range.u32 569906257e9SSergio Gonzalez Monroy + rule->field[IP6_SRC1].mask_range.u32 570906257e9SSergio Gonzalez Monroy + rule->field[IP6_SRC2].mask_range.u32 571906257e9SSergio Gonzalez Monroy + rule->field[IP6_SRC3].mask_range.u32); 572906257e9SSergio Gonzalez Monroy 573906257e9SSergio Gonzalez Monroy uint32_t_to_char(rule->field[IP6_DST0].value.u32, 574906257e9SSergio Gonzalez Monroy &a, &b, &c, &d); 575906257e9SSergio Gonzalez Monroy printf("%.2x%.2x:%.2x%.2x", a, b, c, d); 576906257e9SSergio Gonzalez Monroy uint32_t_to_char(rule->field[IP6_DST1].value.u32, 577906257e9SSergio Gonzalez Monroy &a, &b, &c, &d); 578906257e9SSergio Gonzalez Monroy printf(":%.2x%.2x:%.2x%.2x", a, b, c, d); 579906257e9SSergio Gonzalez Monroy uint32_t_to_char(rule->field[IP6_DST2].value.u32, 580906257e9SSergio Gonzalez Monroy &a, &b, &c, &d); 581906257e9SSergio Gonzalez Monroy printf(":%.2x%.2x:%.2x%.2x", a, b, c, d); 582906257e9SSergio Gonzalez Monroy uint32_t_to_char(rule->field[IP6_DST3].value.u32, 583906257e9SSergio Gonzalez Monroy &a, &b, &c, &d); 584906257e9SSergio Gonzalez Monroy printf(":%.2x%.2x:%.2x%.2x/%u ", a, b, c, d, 585906257e9SSergio Gonzalez Monroy rule->field[IP6_DST0].mask_range.u32 586906257e9SSergio Gonzalez Monroy + rule->field[IP6_DST1].mask_range.u32 587906257e9SSergio Gonzalez Monroy + rule->field[IP6_DST2].mask_range.u32 588906257e9SSergio Gonzalez Monroy + rule->field[IP6_DST3].mask_range.u32); 589906257e9SSergio Gonzalez Monroy 590906257e9SSergio Gonzalez Monroy printf("%hu : %hu %hu : %hu 0x%hhx/0x%hhx ", 591906257e9SSergio Gonzalez Monroy rule->field[IP6_SRCP].value.u16, 592906257e9SSergio Gonzalez Monroy rule->field[IP6_SRCP].mask_range.u16, 593906257e9SSergio Gonzalez Monroy rule->field[IP6_DSTP].value.u16, 594906257e9SSergio Gonzalez Monroy rule->field[IP6_DSTP].mask_range.u16, 595906257e9SSergio Gonzalez Monroy rule->field[IP6_PROTO].value.u8, 596906257e9SSergio Gonzalez Monroy rule->field[IP6_PROTO].mask_range.u8); 597906257e9SSergio Gonzalez Monroy if (extra) 598906257e9SSergio Gonzalez Monroy printf("0x%x-0x%x-0x%x ", 599906257e9SSergio Gonzalez Monroy rule->data.category_mask, 600906257e9SSergio Gonzalez Monroy rule->data.priority, 601906257e9SSergio Gonzalez Monroy rule->data.userdata); 602906257e9SSergio Gonzalez Monroy } 603906257e9SSergio Gonzalez Monroy 604906257e9SSergio Gonzalez Monroy static inline void 605906257e9SSergio Gonzalez Monroy dump_ip6_rules(const struct acl6_rules *rule, int32_t num, int32_t extra) 606906257e9SSergio Gonzalez Monroy { 607906257e9SSergio Gonzalez Monroy int32_t i; 608906257e9SSergio Gonzalez Monroy 609906257e9SSergio Gonzalez Monroy for (i = 0; i < num; i++, rule++) { 610906257e9SSergio Gonzalez Monroy printf("\t%d:", i + 1); 611906257e9SSergio Gonzalez Monroy print_one_ip6_rule(rule, extra); 612906257e9SSergio Gonzalez Monroy printf("\n"); 613906257e9SSergio Gonzalez Monroy } 614906257e9SSergio Gonzalez Monroy } 615906257e9SSergio Gonzalez Monroy 616906257e9SSergio Gonzalez Monroy static struct rte_acl_ctx * 617906257e9SSergio Gonzalez Monroy acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules, 618906257e9SSergio Gonzalez Monroy uint32_t rules_nb) 619906257e9SSergio Gonzalez Monroy { 620906257e9SSergio Gonzalez Monroy char s[PATH_MAX]; 621906257e9SSergio Gonzalez Monroy struct rte_acl_param acl_param; 622906257e9SSergio Gonzalez Monroy struct rte_acl_config acl_build_param; 623906257e9SSergio Gonzalez Monroy struct rte_acl_ctx *ctx; 624906257e9SSergio Gonzalez Monroy 625b0806375SVladimir Medvedkin printf("Creating SP context with %u rules\n", rules_nb); 626906257e9SSergio Gonzalez Monroy 627906257e9SSergio Gonzalez Monroy memset(&acl_param, 0, sizeof(acl_param)); 628906257e9SSergio Gonzalez Monroy 629906257e9SSergio Gonzalez Monroy /* Create ACL contexts */ 630906257e9SSergio Gonzalez Monroy snprintf(s, sizeof(s), "%s_%d", name, socketid); 631906257e9SSergio Gonzalez Monroy 632906257e9SSergio Gonzalez Monroy printf("IPv4 %s entries [%u]:\n", s, rules_nb); 633906257e9SSergio Gonzalez Monroy dump_ip6_rules(rules, rules_nb, 1); 634906257e9SSergio Gonzalez Monroy 635906257e9SSergio Gonzalez Monroy acl_param.name = s; 636906257e9SSergio Gonzalez Monroy acl_param.socket_id = socketid; 637906257e9SSergio Gonzalez Monroy acl_param.rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ip6_defs)); 638b0806375SVladimir Medvedkin acl_param.max_rule_num = rules_nb; 639906257e9SSergio Gonzalez Monroy 640906257e9SSergio Gonzalez Monroy ctx = rte_acl_create(&acl_param); 641906257e9SSergio Gonzalez Monroy if (ctx == NULL) 642906257e9SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Failed to create ACL context\n"); 643906257e9SSergio Gonzalez Monroy 644906257e9SSergio Gonzalez Monroy if (rte_acl_add_rules(ctx, (const struct rte_acl_rule *)rules, 645906257e9SSergio Gonzalez Monroy rules_nb) < 0) 646906257e9SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "add rules failed\n"); 647906257e9SSergio Gonzalez Monroy 648906257e9SSergio Gonzalez Monroy /* Perform builds */ 649906257e9SSergio Gonzalez Monroy memset(&acl_build_param, 0, sizeof(acl_build_param)); 650906257e9SSergio Gonzalez Monroy 651906257e9SSergio Gonzalez Monroy acl_build_param.num_categories = DEFAULT_MAX_CATEGORIES; 652906257e9SSergio Gonzalez Monroy acl_build_param.num_fields = RTE_DIM(ip6_defs); 653906257e9SSergio Gonzalez Monroy memcpy(&acl_build_param.defs, ip6_defs, sizeof(ip6_defs)); 654906257e9SSergio Gonzalez Monroy 655906257e9SSergio Gonzalez Monroy if (rte_acl_build(ctx, &acl_build_param) != 0) 656906257e9SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Failed to build ACL trie\n"); 657906257e9SSergio Gonzalez Monroy 658906257e9SSergio Gonzalez Monroy rte_acl_dump(ctx); 659906257e9SSergio Gonzalez Monroy 660906257e9SSergio Gonzalez Monroy return ctx; 661906257e9SSergio Gonzalez Monroy } 662906257e9SSergio Gonzalez Monroy 66349757b68SKonstantin Ananyev /* 66449757b68SKonstantin Ananyev * check that for each rule it's SPI has a correspondent entry in SAD 66549757b68SKonstantin Ananyev */ 66649757b68SKonstantin Ananyev static int 667df3e1d94SVladimir Medvedkin check_spi_value(struct sa_ctx *sa_ctx, int inbound) 66849757b68SKonstantin Ananyev { 66949757b68SKonstantin Ananyev uint32_t i, num, spi; 670df3e1d94SVladimir Medvedkin int32_t spi_idx; 671df3e1d94SVladimir Medvedkin struct acl6_rules *acr; 67249757b68SKonstantin Ananyev 67349757b68SKonstantin Ananyev if (inbound != 0) { 67449757b68SKonstantin Ananyev acr = acl6_rules_in; 67549757b68SKonstantin Ananyev num = nb_acl6_rules_in; 67649757b68SKonstantin Ananyev } else { 67749757b68SKonstantin Ananyev acr = acl6_rules_out; 67849757b68SKonstantin Ananyev num = nb_acl6_rules_out; 67949757b68SKonstantin Ananyev } 68049757b68SKonstantin Ananyev 68149757b68SKonstantin Ananyev for (i = 0; i != num; i++) { 68249757b68SKonstantin Ananyev spi = acr[i].data.userdata; 683df3e1d94SVladimir Medvedkin if (spi != DISCARD && spi != BYPASS) { 684df3e1d94SVladimir Medvedkin spi_idx = sa_spi_present(sa_ctx, spi, inbound); 685df3e1d94SVladimir Medvedkin if (spi_idx < 0) { 686df3e1d94SVladimir Medvedkin RTE_LOG(ERR, IPSEC, 687df3e1d94SVladimir Medvedkin "SPI %u is not present in SAD\n", 68849757b68SKonstantin Ananyev spi); 68949757b68SKonstantin Ananyev return -ENOENT; 69049757b68SKonstantin Ananyev } 691df3e1d94SVladimir Medvedkin /* Update userdata with spi index */ 692df3e1d94SVladimir Medvedkin acr[i].data.userdata = spi_idx + 1; 693df3e1d94SVladimir Medvedkin } 69449757b68SKonstantin Ananyev } 69549757b68SKonstantin Ananyev 69649757b68SKonstantin Ananyev return 0; 69749757b68SKonstantin Ananyev } 69849757b68SKonstantin Ananyev 699906257e9SSergio Gonzalez Monroy void 7000d547ed0SFan Zhang sp6_init(struct socket_ctx *ctx, int32_t socket_id) 701906257e9SSergio Gonzalez Monroy { 702906257e9SSergio Gonzalez Monroy const char *name; 703906257e9SSergio Gonzalez Monroy 704906257e9SSergio Gonzalez Monroy if (ctx == NULL) 705906257e9SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "NULL context.\n"); 706906257e9SSergio Gonzalez Monroy 707906257e9SSergio Gonzalez Monroy if (ctx->sp_ip6_in != NULL) 708906257e9SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Inbound IPv6 SP DB for socket %u " 709906257e9SSergio Gonzalez Monroy "already initialized\n", socket_id); 710906257e9SSergio Gonzalez Monroy 711906257e9SSergio Gonzalez Monroy if (ctx->sp_ip6_out != NULL) 712906257e9SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Outbound IPv6 SP DB for socket %u " 713906257e9SSergio Gonzalez Monroy "already initialized\n", socket_id); 714906257e9SSergio Gonzalez Monroy 715df3e1d94SVladimir Medvedkin if (check_spi_value(ctx->sa_in, 1) < 0) 71649757b68SKonstantin Ananyev rte_exit(EXIT_FAILURE, 71749757b68SKonstantin Ananyev "Inbound IPv6 SP DB has unmatched in SAD SPIs\n"); 71849757b68SKonstantin Ananyev 719df3e1d94SVladimir Medvedkin if (check_spi_value(ctx->sa_out, 0) < 0) 72049757b68SKonstantin Ananyev rte_exit(EXIT_FAILURE, 72149757b68SKonstantin Ananyev "Outbound IPv6 SP DB has unmatched in SAD SPIs\n"); 72249757b68SKonstantin Ananyev 7230d547ed0SFan Zhang if (nb_acl6_rules_in > 0) { 724906257e9SSergio Gonzalez Monroy name = "sp_ip6_in"; 7250d547ed0SFan Zhang ctx->sp_ip6_in = (struct sp_ctx *)acl6_init(name, 7260d547ed0SFan Zhang socket_id, acl6_rules_in, nb_acl6_rules_in); 7270d547ed0SFan Zhang } else 7280d547ed0SFan Zhang RTE_LOG(WARNING, IPSEC, "No IPv6 SP Inbound rule " 7290d547ed0SFan Zhang "specified\n"); 730906257e9SSergio Gonzalez Monroy 7310d547ed0SFan Zhang if (nb_acl6_rules_out > 0) { 732906257e9SSergio Gonzalez Monroy name = "sp_ip6_out"; 7330d547ed0SFan Zhang ctx->sp_ip6_out = (struct sp_ctx *)acl6_init(name, 7340d547ed0SFan Zhang socket_id, acl6_rules_out, nb_acl6_rules_out); 7350d547ed0SFan Zhang } else 7360d547ed0SFan Zhang RTE_LOG(WARNING, IPSEC, "No IPv6 SP Outbound rule " 7370d547ed0SFan Zhang "specified\n"); 738906257e9SSergio Gonzalez Monroy } 7395a032a71SKonstantin Ananyev 740b0806375SVladimir Medvedkin static int 741b0806375SVladimir Medvedkin sp_cmp(const void *p, const void *q) 742b0806375SVladimir Medvedkin { 743b0806375SVladimir Medvedkin uint32_t spi1 = ((const struct acl6_rules *)p)->data.userdata; 744b0806375SVladimir Medvedkin uint32_t spi2 = ((const struct acl6_rules *)q)->data.userdata; 745b0806375SVladimir Medvedkin 746b0806375SVladimir Medvedkin return (int)(spi1 - spi2); 747b0806375SVladimir Medvedkin } 748b0806375SVladimir Medvedkin 7495a032a71SKonstantin Ananyev /* 7505a032a71SKonstantin Ananyev * Search though SP rules for given SPI. 7515a032a71SKonstantin Ananyev */ 7525a032a71SKonstantin Ananyev int 753b1a3ac78SMariusz Drost sp6_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2], 754b1a3ac78SMariusz Drost uint32_t mask[2]) 7555a032a71SKonstantin Ananyev { 756b0806375SVladimir Medvedkin uint32_t num; 757b0806375SVladimir Medvedkin struct acl6_rules *rule; 7585a032a71SKonstantin Ananyev const struct acl6_rules *acr; 759b0806375SVladimir Medvedkin struct acl6_rules tmpl; 7605a032a71SKonstantin Ananyev 7615a032a71SKonstantin Ananyev if (inbound != 0) { 7625a032a71SKonstantin Ananyev acr = acl6_rules_in; 7635a032a71SKonstantin Ananyev num = nb_acl6_rules_in; 7645a032a71SKonstantin Ananyev } else { 7655a032a71SKonstantin Ananyev acr = acl6_rules_out; 7665a032a71SKonstantin Ananyev num = nb_acl6_rules_out; 7675a032a71SKonstantin Ananyev } 7685a032a71SKonstantin Ananyev 769b0806375SVladimir Medvedkin tmpl.data.userdata = spi; 770b0806375SVladimir Medvedkin 771b0806375SVladimir Medvedkin rule = bsearch(&tmpl, acr, num, sizeof(struct acl6_rules), sp_cmp); 772b0806375SVladimir Medvedkin if (rule != NULL) { 773b1a3ac78SMariusz Drost if (NULL != ip_addr && NULL != mask) { 774*9ac91e2fSRobin Jarry ip_addr[0].ip.ip6 = ipv6_src_from_sp(rule); 775*9ac91e2fSRobin Jarry ip_addr[1].ip.ip6 = ipv6_dst_from_sp(rule); 776*9ac91e2fSRobin Jarry mask[0] = ipv6_src_mask_from_sp(rule); 777*9ac91e2fSRobin Jarry mask[1] = ipv6_dst_mask_from_sp(rule); 778b1a3ac78SMariusz Drost } 779b0806375SVladimir Medvedkin return RTE_PTR_DIFF(rule, acr) / sizeof(struct acl6_rules); 780b1a3ac78SMariusz Drost } 7815a032a71SKonstantin Ananyev 7825a032a71SKonstantin Ananyev return -ENOENT; 7835a032a71SKonstantin Ananyev } 784b0806375SVladimir Medvedkin 785b0806375SVladimir Medvedkin void 786b0806375SVladimir Medvedkin sp6_sort_arr(void) 787b0806375SVladimir Medvedkin { 788b0806375SVladimir Medvedkin qsort(acl6_rules_in, nb_acl6_rules_in, sizeof(struct acl6_rules), 789b0806375SVladimir Medvedkin sp_cmp); 790b0806375SVladimir Medvedkin qsort(acl6_rules_out, nb_acl6_rules_out, sizeof(struct acl6_rules), 791b0806375SVladimir Medvedkin sp_cmp); 792b0806375SVladimir Medvedkin } 793