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/ip.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
20b1a3ac78SMariusz Drost #define IPV4_DST_FROM_SP(acr) \
21b1a3ac78SMariusz Drost (rte_cpu_to_be_32((acr).field[DST_FIELD_IPV4].value.u32))
22b1a3ac78SMariusz Drost
23b1a3ac78SMariusz Drost #define IPV4_SRC_FROM_SP(acr) \
24b1a3ac78SMariusz Drost (rte_cpu_to_be_32((acr).field[SRC_FIELD_IPV4].value.u32))
25b1a3ac78SMariusz Drost
26b1a3ac78SMariusz Drost #define IPV4_DST_MASK_FROM_SP(acr) \
27b1a3ac78SMariusz Drost ((acr).field[DST_FIELD_IPV4].mask_range.u32)
28b1a3ac78SMariusz Drost
29b1a3ac78SMariusz Drost #define IPV4_SRC_MASK_FROM_SP(acr) \
30b1a3ac78SMariusz Drost ((acr).field[SRC_FIELD_IPV4].mask_range.u32)
31b1a3ac78SMariusz Drost
32906257e9SSergio Gonzalez Monroy /*
33906257e9SSergio Gonzalez Monroy * Rule and trace formats definitions.
34906257e9SSergio Gonzalez Monroy */
35906257e9SSergio Gonzalez Monroy enum {
36906257e9SSergio Gonzalez Monroy PROTO_FIELD_IPV4,
37906257e9SSergio Gonzalez Monroy SRC_FIELD_IPV4,
38906257e9SSergio Gonzalez Monroy DST_FIELD_IPV4,
39906257e9SSergio Gonzalez Monroy SRCP_FIELD_IPV4,
40906257e9SSergio Gonzalez Monroy DSTP_FIELD_IPV4,
41906257e9SSergio Gonzalez Monroy NUM_FIELDS_IPV4
42906257e9SSergio Gonzalez Monroy };
43906257e9SSergio Gonzalez Monroy
44906257e9SSergio Gonzalez Monroy /*
45906257e9SSergio Gonzalez Monroy * That effectively defines order of IPV4 classifications:
46906257e9SSergio Gonzalez Monroy * - PROTO
47906257e9SSergio Gonzalez Monroy * - SRC IP ADDRESS
48906257e9SSergio Gonzalez Monroy * - DST IP ADDRESS
49906257e9SSergio Gonzalez Monroy * - PORTS (SRC and DST)
50906257e9SSergio Gonzalez Monroy */
51906257e9SSergio Gonzalez Monroy enum {
52906257e9SSergio Gonzalez Monroy RTE_ACL_IPV4_PROTO,
53906257e9SSergio Gonzalez Monroy RTE_ACL_IPV4_SRC,
54906257e9SSergio Gonzalez Monroy RTE_ACL_IPV4_DST,
55906257e9SSergio Gonzalez Monroy RTE_ACL_IPV4_PORTS,
56906257e9SSergio Gonzalez Monroy RTE_ACL_IPV4_NUM
57906257e9SSergio Gonzalez Monroy };
58906257e9SSergio Gonzalez Monroy
59d92fc70eSKonstantin Ananyev static struct rte_acl_field_def ip4_defs[NUM_FIELDS_IPV4] = {
60906257e9SSergio Gonzalez Monroy {
61906257e9SSergio Gonzalez Monroy .type = RTE_ACL_FIELD_TYPE_BITMASK,
62906257e9SSergio Gonzalez Monroy .size = sizeof(uint8_t),
63906257e9SSergio Gonzalez Monroy .field_index = PROTO_FIELD_IPV4,
64906257e9SSergio Gonzalez Monroy .input_index = RTE_ACL_IPV4_PROTO,
65906257e9SSergio Gonzalez Monroy .offset = 0,
66906257e9SSergio Gonzalez Monroy },
67906257e9SSergio Gonzalez Monroy {
68906257e9SSergio Gonzalez Monroy .type = RTE_ACL_FIELD_TYPE_MASK,
69906257e9SSergio Gonzalez Monroy .size = sizeof(uint32_t),
70906257e9SSergio Gonzalez Monroy .field_index = SRC_FIELD_IPV4,
71906257e9SSergio Gonzalez Monroy .input_index = RTE_ACL_IPV4_SRC,
72906257e9SSergio Gonzalez Monroy .offset = offsetof(struct ip, ip_src) - offsetof(struct ip, ip_p)
73906257e9SSergio Gonzalez Monroy },
74906257e9SSergio Gonzalez Monroy {
75906257e9SSergio Gonzalez Monroy .type = RTE_ACL_FIELD_TYPE_MASK,
76906257e9SSergio Gonzalez Monroy .size = sizeof(uint32_t),
77906257e9SSergio Gonzalez Monroy .field_index = DST_FIELD_IPV4,
78906257e9SSergio Gonzalez Monroy .input_index = RTE_ACL_IPV4_DST,
79906257e9SSergio Gonzalez Monroy .offset = offsetof(struct ip, ip_dst) - offsetof(struct ip, ip_p)
80906257e9SSergio Gonzalez Monroy },
81906257e9SSergio Gonzalez Monroy {
82906257e9SSergio Gonzalez Monroy .type = RTE_ACL_FIELD_TYPE_RANGE,
83906257e9SSergio Gonzalez Monroy .size = sizeof(uint16_t),
84906257e9SSergio Gonzalez Monroy .field_index = SRCP_FIELD_IPV4,
85906257e9SSergio Gonzalez Monroy .input_index = RTE_ACL_IPV4_PORTS,
86906257e9SSergio Gonzalez Monroy .offset = sizeof(struct ip) - offsetof(struct ip, ip_p)
87906257e9SSergio Gonzalez Monroy },
88906257e9SSergio Gonzalez Monroy {
89906257e9SSergio Gonzalez Monroy .type = RTE_ACL_FIELD_TYPE_RANGE,
90906257e9SSergio Gonzalez Monroy .size = sizeof(uint16_t),
91906257e9SSergio Gonzalez Monroy .field_index = DSTP_FIELD_IPV4,
92906257e9SSergio Gonzalez Monroy .input_index = RTE_ACL_IPV4_PORTS,
93906257e9SSergio Gonzalez Monroy .offset = sizeof(struct ip) - offsetof(struct ip, ip_p) +
94906257e9SSergio Gonzalez Monroy sizeof(uint16_t)
95906257e9SSergio Gonzalez Monroy },
96906257e9SSergio Gonzalez Monroy };
97906257e9SSergio Gonzalez Monroy
98906257e9SSergio Gonzalez Monroy RTE_ACL_RULE_DEF(acl4_rules, RTE_DIM(ip4_defs));
99906257e9SSergio Gonzalez Monroy
100b0806375SVladimir Medvedkin static struct acl4_rules *acl4_rules_out;
101d92fc70eSKonstantin Ananyev static uint32_t nb_acl4_rules_out;
102b0806375SVladimir Medvedkin static uint32_t sp_out_sz;
103906257e9SSergio Gonzalez Monroy
104b0806375SVladimir Medvedkin static struct acl4_rules *acl4_rules_in;
105d92fc70eSKonstantin Ananyev static uint32_t nb_acl4_rules_in;
106b0806375SVladimir Medvedkin static uint32_t sp_in_sz;
107b0806375SVladimir Medvedkin
108b0806375SVladimir Medvedkin static int
extend_sp_arr(struct acl4_rules ** sp_tbl,uint32_t cur_cnt,uint32_t * cur_sz)109b0806375SVladimir Medvedkin extend_sp_arr(struct acl4_rules **sp_tbl, uint32_t cur_cnt, uint32_t *cur_sz)
110b0806375SVladimir Medvedkin {
111b0806375SVladimir Medvedkin if (*sp_tbl == NULL) {
112b0806375SVladimir Medvedkin *sp_tbl = calloc(INIT_ACL_RULE_NUM, sizeof(struct acl4_rules));
113b0806375SVladimir Medvedkin if (*sp_tbl == NULL)
114b0806375SVladimir Medvedkin return -1;
115b0806375SVladimir Medvedkin *cur_sz = INIT_ACL_RULE_NUM;
116b0806375SVladimir Medvedkin return 0;
117b0806375SVladimir Medvedkin }
118b0806375SVladimir Medvedkin
119b0806375SVladimir Medvedkin if (cur_cnt >= *cur_sz) {
120b0806375SVladimir Medvedkin *sp_tbl = realloc(*sp_tbl,
121b0806375SVladimir Medvedkin *cur_sz * sizeof(struct acl4_rules) * 2);
122b0806375SVladimir Medvedkin if (*sp_tbl == NULL)
123b0806375SVladimir Medvedkin return -1;
124b0806375SVladimir Medvedkin /* clean reallocated extra space */
125b0806375SVladimir Medvedkin memset(&(*sp_tbl)[*cur_sz], 0,
126b0806375SVladimir Medvedkin *cur_sz * sizeof(struct acl4_rules));
127b0806375SVladimir Medvedkin *cur_sz *= 2;
128b0806375SVladimir Medvedkin }
129b0806375SVladimir Medvedkin
130b0806375SVladimir Medvedkin return 0;
131b0806375SVladimir Medvedkin }
132b0806375SVladimir Medvedkin
1330d547ed0SFan Zhang
1340d547ed0SFan Zhang void
parse_sp4_tokens(char ** tokens,uint32_t n_tokens,struct parse_status * status)1350d547ed0SFan Zhang parse_sp4_tokens(char **tokens, uint32_t n_tokens,
1360d547ed0SFan Zhang struct parse_status *status)
137906257e9SSergio Gonzalez Monroy {
1380d547ed0SFan Zhang struct acl4_rules *rule_ipv4 = NULL;
1390d547ed0SFan Zhang
1400d547ed0SFan Zhang uint32_t *ri = NULL; /* rule index */
1410d547ed0SFan Zhang uint32_t ti = 0; /* token index */
14249757b68SKonstantin Ananyev uint32_t tv;
1430d547ed0SFan Zhang
1440d547ed0SFan Zhang uint32_t esp_p = 0;
1450d547ed0SFan Zhang uint32_t protect_p = 0;
1460d547ed0SFan Zhang uint32_t bypass_p = 0;
1470d547ed0SFan Zhang uint32_t discard_p = 0;
1480d547ed0SFan Zhang uint32_t pri_p = 0;
1490d547ed0SFan Zhang uint32_t src_p = 0;
1500d547ed0SFan Zhang uint32_t dst_p = 0;
1510d547ed0SFan Zhang uint32_t proto_p = 0;
1520d547ed0SFan Zhang uint32_t sport_p = 0;
1530d547ed0SFan Zhang uint32_t dport_p = 0;
1540d547ed0SFan Zhang
1550d547ed0SFan Zhang if (strcmp(tokens[1], "in") == 0) {
1560d547ed0SFan Zhang ri = &nb_acl4_rules_in;
1570d547ed0SFan Zhang
158b0806375SVladimir Medvedkin if (extend_sp_arr(&acl4_rules_in, nb_acl4_rules_in,
159b0806375SVladimir Medvedkin &sp_in_sz) < 0)
1600d547ed0SFan Zhang return;
1610d547ed0SFan Zhang
1620d547ed0SFan Zhang rule_ipv4 = &acl4_rules_in[*ri];
1630d547ed0SFan Zhang
1640d547ed0SFan Zhang } else if (strcmp(tokens[1], "out") == 0) {
1650d547ed0SFan Zhang ri = &nb_acl4_rules_out;
1660d547ed0SFan Zhang
167b0806375SVladimir Medvedkin if (extend_sp_arr(&acl4_rules_out, nb_acl4_rules_out,
168b0806375SVladimir Medvedkin &sp_out_sz) < 0)
1690d547ed0SFan Zhang return;
1700d547ed0SFan Zhang
1710d547ed0SFan Zhang rule_ipv4 = &acl4_rules_out[*ri];
1720d547ed0SFan Zhang } else {
1730d547ed0SFan Zhang APP_CHECK(0, status, "unrecognized input \"%s\", expect"
1740d547ed0SFan Zhang " \"in\" or \"out\"\n", tokens[ti]);
1750d547ed0SFan Zhang return;
176906257e9SSergio Gonzalez Monroy }
1770d547ed0SFan Zhang
1780d547ed0SFan Zhang rule_ipv4->data.category_mask = 1;
1790d547ed0SFan Zhang
1800d547ed0SFan Zhang for (ti = 2; ti < n_tokens; ti++) {
1810d547ed0SFan Zhang if (strcmp(tokens[ti], "esp") == 0) {
1820d547ed0SFan Zhang /* currently do nothing */
1830d547ed0SFan Zhang APP_CHECK_PRESENCE(esp_p, tokens[ti], status);
1840d547ed0SFan Zhang if (status->status < 0)
1850d547ed0SFan Zhang return;
1860d547ed0SFan Zhang esp_p = 1;
1870d547ed0SFan Zhang continue;
1880d547ed0SFan Zhang }
1890d547ed0SFan Zhang
1900d547ed0SFan Zhang if (strcmp(tokens[ti], "protect") == 0) {
1910d547ed0SFan Zhang APP_CHECK_PRESENCE(protect_p, tokens[ti], status);
1920d547ed0SFan Zhang if (status->status < 0)
1930d547ed0SFan Zhang return;
1940d547ed0SFan Zhang APP_CHECK(bypass_p == 0, status, "conflict item "
1950d547ed0SFan Zhang "between \"%s\" and \"%s\"", tokens[ti],
1960d547ed0SFan Zhang "bypass");
1970d547ed0SFan Zhang if (status->status < 0)
1980d547ed0SFan Zhang return;
1990d547ed0SFan Zhang APP_CHECK(discard_p == 0, status, "conflict item "
2000d547ed0SFan Zhang "between \"%s\" and \"%s\"", tokens[ti],
2010d547ed0SFan Zhang "discard");
2020d547ed0SFan Zhang if (status->status < 0)
2030d547ed0SFan Zhang return;
2040d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
2050d547ed0SFan Zhang if (status->status < 0)
2060d547ed0SFan Zhang return;
2070d547ed0SFan Zhang APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
2080d547ed0SFan Zhang if (status->status < 0)
2090d547ed0SFan Zhang return;
2100d547ed0SFan Zhang
21149757b68SKonstantin Ananyev tv = atoi(tokens[ti]);
21249757b68SKonstantin Ananyev APP_CHECK(tv != DISCARD && tv != BYPASS, status,
21349757b68SKonstantin Ananyev "invalid SPI: %s", tokens[ti]);
21449757b68SKonstantin Ananyev if (status->status < 0)
21549757b68SKonstantin Ananyev return;
21649757b68SKonstantin Ananyev rule_ipv4->data.userdata = tv;
2170d547ed0SFan Zhang
2180d547ed0SFan Zhang protect_p = 1;
2190d547ed0SFan Zhang continue;
2200d547ed0SFan Zhang }
2210d547ed0SFan Zhang
2220d547ed0SFan Zhang if (strcmp(tokens[ti], "bypass") == 0) {
2230d547ed0SFan Zhang APP_CHECK_PRESENCE(bypass_p, tokens[ti], status);
2240d547ed0SFan Zhang if (status->status < 0)
2250d547ed0SFan Zhang return;
2260d547ed0SFan Zhang APP_CHECK(protect_p == 0, status, "conflict item "
2270d547ed0SFan Zhang "between \"%s\" and \"%s\"", tokens[ti],
2280d547ed0SFan Zhang "protect");
2290d547ed0SFan Zhang if (status->status < 0)
2300d547ed0SFan Zhang return;
2310d547ed0SFan Zhang APP_CHECK(discard_p == 0, status, "conflict item "
2320d547ed0SFan Zhang "between \"%s\" and \"%s\"", tokens[ti],
2330d547ed0SFan Zhang "discard");
2340d547ed0SFan Zhang if (status->status < 0)
2350d547ed0SFan Zhang return;
2360d547ed0SFan Zhang
2370d547ed0SFan Zhang rule_ipv4->data.userdata = BYPASS;
2380d547ed0SFan Zhang
2390d547ed0SFan Zhang bypass_p = 1;
2400d547ed0SFan Zhang continue;
2410d547ed0SFan Zhang }
2420d547ed0SFan Zhang
2430d547ed0SFan Zhang if (strcmp(tokens[ti], "discard") == 0) {
2440d547ed0SFan Zhang APP_CHECK_PRESENCE(discard_p, tokens[ti], status);
2450d547ed0SFan Zhang if (status->status < 0)
2460d547ed0SFan Zhang return;
2470d547ed0SFan Zhang APP_CHECK(protect_p == 0, status, "conflict item "
2480d547ed0SFan Zhang "between \"%s\" and \"%s\"", tokens[ti],
2490d547ed0SFan Zhang "protect");
2500d547ed0SFan Zhang if (status->status < 0)
2510d547ed0SFan Zhang return;
2520d547ed0SFan Zhang APP_CHECK(bypass_p == 0, status, "conflict item "
2530d547ed0SFan Zhang "between \"%s\" and \"%s\"", tokens[ti],
2540d547ed0SFan Zhang "discard");
2550d547ed0SFan Zhang if (status->status < 0)
2560d547ed0SFan Zhang return;
2570d547ed0SFan Zhang
2580d547ed0SFan Zhang rule_ipv4->data.userdata = DISCARD;
2590d547ed0SFan Zhang
2600d547ed0SFan Zhang discard_p = 1;
2610d547ed0SFan Zhang continue;
2620d547ed0SFan Zhang }
2630d547ed0SFan Zhang
2640d547ed0SFan Zhang if (strcmp(tokens[ti], "pri") == 0) {
2650d547ed0SFan Zhang APP_CHECK_PRESENCE(pri_p, tokens[ti], status);
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
2750d547ed0SFan Zhang rule_ipv4->data.priority = atoi(tokens[ti]);
2760d547ed0SFan Zhang
2770d547ed0SFan Zhang pri_p = 1;
2780d547ed0SFan Zhang continue;
2790d547ed0SFan Zhang }
2800d547ed0SFan Zhang
2810d547ed0SFan Zhang if (strcmp(tokens[ti], "src") == 0) {
2820d547ed0SFan Zhang struct in_addr ip;
2830d547ed0SFan Zhang uint32_t depth;
2840d547ed0SFan Zhang
2850d547ed0SFan Zhang APP_CHECK_PRESENCE(src_p, tokens[ti], status);
2860d547ed0SFan Zhang if (status->status < 0)
2870d547ed0SFan Zhang return;
2880d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
2890d547ed0SFan Zhang if (status->status < 0)
2900d547ed0SFan Zhang return;
2910d547ed0SFan Zhang
2920d547ed0SFan Zhang APP_CHECK(parse_ipv4_addr(tokens[ti], &ip,
2930d547ed0SFan Zhang &depth) == 0, status, "unrecognized "
2940d547ed0SFan Zhang "input \"%s\", expect valid ipv4 addr",
2950d547ed0SFan Zhang tokens[ti]);
2960d547ed0SFan Zhang if (status->status < 0)
2970d547ed0SFan Zhang return;
2980d547ed0SFan Zhang
2990d547ed0SFan Zhang rule_ipv4->field[1].value.u32 =
3000d547ed0SFan Zhang rte_bswap32(ip.s_addr);
3010d547ed0SFan Zhang rule_ipv4->field[1].mask_range.u32 =
3020d547ed0SFan Zhang depth;
3030d547ed0SFan Zhang
3040d547ed0SFan Zhang src_p = 1;
3050d547ed0SFan Zhang continue;
3060d547ed0SFan Zhang }
3070d547ed0SFan Zhang
3080d547ed0SFan Zhang if (strcmp(tokens[ti], "dst") == 0) {
3090d547ed0SFan Zhang struct in_addr ip;
3100d547ed0SFan Zhang uint32_t depth;
3110d547ed0SFan Zhang
3120d547ed0SFan Zhang APP_CHECK_PRESENCE(dst_p, tokens[ti], status);
3130d547ed0SFan Zhang if (status->status < 0)
3140d547ed0SFan Zhang return;
3150d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
3160d547ed0SFan Zhang if (status->status < 0)
3170d547ed0SFan Zhang return;
3180d547ed0SFan Zhang APP_CHECK(parse_ipv4_addr(tokens[ti], &ip,
3190d547ed0SFan Zhang &depth) == 0, status, "unrecognized "
3200d547ed0SFan Zhang "input \"%s\", expect valid ipv4 addr",
3210d547ed0SFan Zhang tokens[ti]);
3220d547ed0SFan Zhang if (status->status < 0)
3230d547ed0SFan Zhang return;
3240d547ed0SFan Zhang
3250d547ed0SFan Zhang rule_ipv4->field[2].value.u32 =
3260d547ed0SFan Zhang rte_bswap32(ip.s_addr);
3270d547ed0SFan Zhang rule_ipv4->field[2].mask_range.u32 =
3280d547ed0SFan Zhang depth;
3290d547ed0SFan Zhang
3300d547ed0SFan Zhang dst_p = 1;
3310d547ed0SFan Zhang continue;
3320d547ed0SFan Zhang }
3330d547ed0SFan Zhang
3340d547ed0SFan Zhang if (strcmp(tokens[ti], "proto") == 0) {
3350d547ed0SFan Zhang uint16_t low, high;
3360d547ed0SFan Zhang
3370d547ed0SFan Zhang APP_CHECK_PRESENCE(proto_p, tokens[ti], status);
3380d547ed0SFan Zhang if (status->status < 0)
3390d547ed0SFan Zhang return;
3400d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
3410d547ed0SFan Zhang if (status->status < 0)
3420d547ed0SFan Zhang return;
3430d547ed0SFan Zhang
3440d547ed0SFan Zhang APP_CHECK(parse_range(tokens[ti], &low, &high)
3450d547ed0SFan Zhang == 0, status, "unrecognized input \"%s\""
3460d547ed0SFan Zhang ", expect \"from:to\"", tokens[ti]);
3470d547ed0SFan Zhang if (status->status < 0)
3480d547ed0SFan Zhang return;
3490d547ed0SFan Zhang APP_CHECK(low <= 0xff, status, "proto low "
3500d547ed0SFan Zhang "over-limit");
3510d547ed0SFan Zhang if (status->status < 0)
3520d547ed0SFan Zhang return;
3530d547ed0SFan Zhang APP_CHECK(high <= 0xff, status, "proto high "
3540d547ed0SFan Zhang "over-limit");
3550d547ed0SFan Zhang if (status->status < 0)
3560d547ed0SFan Zhang return;
3570d547ed0SFan Zhang
3580d547ed0SFan Zhang rule_ipv4->field[0].value.u8 = (uint8_t)low;
3590d547ed0SFan Zhang rule_ipv4->field[0].mask_range.u8 = (uint8_t)high;
3600d547ed0SFan Zhang
3610d547ed0SFan Zhang proto_p = 1;
3620d547ed0SFan Zhang continue;
3630d547ed0SFan Zhang }
3640d547ed0SFan Zhang
3650d547ed0SFan Zhang if (strcmp(tokens[ti], "sport") == 0) {
3660d547ed0SFan Zhang uint16_t port_low, port_high;
3670d547ed0SFan Zhang
3680d547ed0SFan Zhang APP_CHECK_PRESENCE(sport_p, tokens[ti], status);
3690d547ed0SFan Zhang if (status->status < 0)
3700d547ed0SFan Zhang return;
3710d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
3720d547ed0SFan Zhang if (status->status < 0)
3730d547ed0SFan Zhang return;
3740d547ed0SFan Zhang
3750d547ed0SFan Zhang APP_CHECK(parse_range(tokens[ti], &port_low,
3760d547ed0SFan Zhang &port_high) == 0, status, "unrecognized "
3770d547ed0SFan Zhang "input \"%s\", expect \"port_from:"
3780d547ed0SFan Zhang "port_to\"", tokens[ti]);
3790d547ed0SFan Zhang if (status->status < 0)
3800d547ed0SFan Zhang return;
3810d547ed0SFan Zhang
3820d547ed0SFan Zhang rule_ipv4->field[3].value.u16 = port_low;
3830d547ed0SFan Zhang rule_ipv4->field[3].mask_range.u16 = port_high;
3840d547ed0SFan Zhang
3850d547ed0SFan Zhang sport_p = 1;
3860d547ed0SFan Zhang continue;
3870d547ed0SFan Zhang }
3880d547ed0SFan Zhang
3890d547ed0SFan Zhang if (strcmp(tokens[ti], "dport") == 0) {
3900d547ed0SFan Zhang uint16_t port_low, port_high;
3910d547ed0SFan Zhang
3920d547ed0SFan Zhang APP_CHECK_PRESENCE(dport_p, tokens[ti], status);
3930d547ed0SFan Zhang if (status->status < 0)
3940d547ed0SFan Zhang return;
3950d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
3960d547ed0SFan Zhang if (status->status < 0)
3970d547ed0SFan Zhang return;
3980d547ed0SFan Zhang
3990d547ed0SFan Zhang APP_CHECK(parse_range(tokens[ti], &port_low,
4000d547ed0SFan Zhang &port_high) == 0, status, "unrecognized "
4010d547ed0SFan Zhang "input \"%s\", expect \"port_from:"
4020d547ed0SFan Zhang "port_to\"", tokens[ti]);
4030d547ed0SFan Zhang if (status->status < 0)
4040d547ed0SFan Zhang return;
4050d547ed0SFan Zhang
4060d547ed0SFan Zhang rule_ipv4->field[4].value.u16 = port_low;
4070d547ed0SFan Zhang rule_ipv4->field[4].mask_range.u16 = port_high;
4080d547ed0SFan Zhang
4090d547ed0SFan Zhang dport_p = 1;
4100d547ed0SFan Zhang continue;
4110d547ed0SFan Zhang }
4120d547ed0SFan Zhang
413*7be78d02SJosh Soref /* unrecognizable input */
4140d547ed0SFan Zhang APP_CHECK(0, status, "unrecognized input \"%s\"",
4150d547ed0SFan Zhang tokens[ti]);
4160d547ed0SFan Zhang return;
4170d547ed0SFan Zhang }
4180d547ed0SFan Zhang
4190d547ed0SFan Zhang /* check if argument(s) are missing */
4200d547ed0SFan Zhang APP_CHECK(esp_p == 1, status, "missing argument \"esp\"");
4210d547ed0SFan Zhang if (status->status < 0)
4220d547ed0SFan Zhang return;
4230d547ed0SFan Zhang
4240d547ed0SFan Zhang APP_CHECK(protect_p | bypass_p | discard_p, status, "missing "
4250d547ed0SFan Zhang "argument \"protect\", \"bypass\", or \"discard\"");
4260d547ed0SFan Zhang if (status->status < 0)
4270d547ed0SFan Zhang return;
4280d547ed0SFan Zhang
4290d547ed0SFan Zhang *ri = *ri + 1;
4300d547ed0SFan Zhang }
431906257e9SSergio Gonzalez Monroy
432906257e9SSergio Gonzalez Monroy static void
print_one_ip4_rule(const struct acl4_rules * rule,int32_t extra)433906257e9SSergio Gonzalez Monroy print_one_ip4_rule(const struct acl4_rules *rule, int32_t extra)
434906257e9SSergio Gonzalez Monroy {
435906257e9SSergio Gonzalez Monroy uint8_t a, b, c, d;
436906257e9SSergio Gonzalez Monroy
437906257e9SSergio Gonzalez Monroy uint32_t_to_char(rule->field[SRC_FIELD_IPV4].value.u32,
438906257e9SSergio Gonzalez Monroy &a, &b, &c, &d);
439906257e9SSergio Gonzalez Monroy printf("%hhu.%hhu.%hhu.%hhu/%u ", a, b, c, d,
440906257e9SSergio Gonzalez Monroy rule->field[SRC_FIELD_IPV4].mask_range.u32);
441906257e9SSergio Gonzalez Monroy uint32_t_to_char(rule->field[DST_FIELD_IPV4].value.u32,
442906257e9SSergio Gonzalez Monroy &a, &b, &c, &d);
443906257e9SSergio Gonzalez Monroy printf("%hhu.%hhu.%hhu.%hhu/%u ", a, b, c, d,
444906257e9SSergio Gonzalez Monroy rule->field[DST_FIELD_IPV4].mask_range.u32);
445906257e9SSergio Gonzalez Monroy printf("%hu : %hu %hu : %hu 0x%hhx/0x%hhx ",
446906257e9SSergio Gonzalez Monroy rule->field[SRCP_FIELD_IPV4].value.u16,
447906257e9SSergio Gonzalez Monroy rule->field[SRCP_FIELD_IPV4].mask_range.u16,
448906257e9SSergio Gonzalez Monroy rule->field[DSTP_FIELD_IPV4].value.u16,
449906257e9SSergio Gonzalez Monroy rule->field[DSTP_FIELD_IPV4].mask_range.u16,
450906257e9SSergio Gonzalez Monroy rule->field[PROTO_FIELD_IPV4].value.u8,
451906257e9SSergio Gonzalez Monroy rule->field[PROTO_FIELD_IPV4].mask_range.u8);
452906257e9SSergio Gonzalez Monroy if (extra)
453906257e9SSergio Gonzalez Monroy printf("0x%x-0x%x-0x%x ",
454906257e9SSergio Gonzalez Monroy rule->data.category_mask,
455906257e9SSergio Gonzalez Monroy rule->data.priority,
456906257e9SSergio Gonzalez Monroy rule->data.userdata);
457906257e9SSergio Gonzalez Monroy }
458906257e9SSergio Gonzalez Monroy
459906257e9SSergio Gonzalez Monroy static inline void
dump_ip4_rules(const struct acl4_rules * rule,int32_t num,int32_t extra)460906257e9SSergio Gonzalez Monroy dump_ip4_rules(const struct acl4_rules *rule, int32_t num, int32_t extra)
461906257e9SSergio Gonzalez Monroy {
462906257e9SSergio Gonzalez Monroy int32_t i;
463906257e9SSergio Gonzalez Monroy
464906257e9SSergio Gonzalez Monroy for (i = 0; i < num; i++, rule++) {
465906257e9SSergio Gonzalez Monroy printf("\t%d:", i + 1);
466906257e9SSergio Gonzalez Monroy print_one_ip4_rule(rule, extra);
467906257e9SSergio Gonzalez Monroy printf("\n");
468906257e9SSergio Gonzalez Monroy }
469906257e9SSergio Gonzalez Monroy }
470906257e9SSergio Gonzalez Monroy
471906257e9SSergio Gonzalez Monroy static struct rte_acl_ctx *
acl4_init(const char * name,int32_t socketid,const struct acl4_rules * rules,uint32_t rules_nb)472906257e9SSergio Gonzalez Monroy acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,
473906257e9SSergio Gonzalez Monroy uint32_t rules_nb)
474906257e9SSergio Gonzalez Monroy {
475906257e9SSergio Gonzalez Monroy char s[PATH_MAX];
476906257e9SSergio Gonzalez Monroy struct rte_acl_param acl_param;
477906257e9SSergio Gonzalez Monroy struct rte_acl_config acl_build_param;
478906257e9SSergio Gonzalez Monroy struct rte_acl_ctx *ctx;
479906257e9SSergio Gonzalez Monroy
480b0806375SVladimir Medvedkin printf("Creating SP context with %u rules\n", rules_nb);
481906257e9SSergio Gonzalez Monroy
482906257e9SSergio Gonzalez Monroy memset(&acl_param, 0, sizeof(acl_param));
483906257e9SSergio Gonzalez Monroy
484906257e9SSergio Gonzalez Monroy /* Create ACL contexts */
485906257e9SSergio Gonzalez Monroy snprintf(s, sizeof(s), "%s_%d", name, socketid);
486906257e9SSergio Gonzalez Monroy
487906257e9SSergio Gonzalez Monroy printf("IPv4 %s entries [%u]:\n", s, rules_nb);
488906257e9SSergio Gonzalez Monroy dump_ip4_rules(rules, rules_nb, 1);
489906257e9SSergio Gonzalez Monroy
490906257e9SSergio Gonzalez Monroy acl_param.name = s;
491906257e9SSergio Gonzalez Monroy acl_param.socket_id = socketid;
492906257e9SSergio Gonzalez Monroy acl_param.rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ip4_defs));
493b0806375SVladimir Medvedkin acl_param.max_rule_num = rules_nb;
494906257e9SSergio Gonzalez Monroy
495906257e9SSergio Gonzalez Monroy ctx = rte_acl_create(&acl_param);
496906257e9SSergio Gonzalez Monroy if (ctx == NULL)
497906257e9SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Failed to create ACL context\n");
498906257e9SSergio Gonzalez Monroy
499906257e9SSergio Gonzalez Monroy if (rte_acl_add_rules(ctx, (const struct rte_acl_rule *)rules,
500906257e9SSergio Gonzalez Monroy rules_nb) < 0)
501906257e9SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "add rules failed\n");
502906257e9SSergio Gonzalez Monroy
503906257e9SSergio Gonzalez Monroy /* Perform builds */
504906257e9SSergio Gonzalez Monroy memset(&acl_build_param, 0, sizeof(acl_build_param));
505906257e9SSergio Gonzalez Monroy
506906257e9SSergio Gonzalez Monroy acl_build_param.num_categories = DEFAULT_MAX_CATEGORIES;
507906257e9SSergio Gonzalez Monroy acl_build_param.num_fields = RTE_DIM(ip4_defs);
508906257e9SSergio Gonzalez Monroy memcpy(&acl_build_param.defs, ip4_defs, sizeof(ip4_defs));
509906257e9SSergio Gonzalez Monroy
510906257e9SSergio Gonzalez Monroy if (rte_acl_build(ctx, &acl_build_param) != 0)
511906257e9SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Failed to build ACL trie\n");
512906257e9SSergio Gonzalez Monroy
513906257e9SSergio Gonzalez Monroy rte_acl_dump(ctx);
514906257e9SSergio Gonzalez Monroy
515906257e9SSergio Gonzalez Monroy return ctx;
516906257e9SSergio Gonzalez Monroy }
517906257e9SSergio Gonzalez Monroy
51849757b68SKonstantin Ananyev /*
51949757b68SKonstantin Ananyev * check that for each rule it's SPI has a correspondent entry in SAD
52049757b68SKonstantin Ananyev */
52149757b68SKonstantin Ananyev static int
check_spi_value(struct sa_ctx * sa_ctx,int inbound)522df3e1d94SVladimir Medvedkin check_spi_value(struct sa_ctx *sa_ctx, int inbound)
52349757b68SKonstantin Ananyev {
52449757b68SKonstantin Ananyev uint32_t i, num, spi;
525df3e1d94SVladimir Medvedkin int32_t spi_idx;
526df3e1d94SVladimir Medvedkin struct acl4_rules *acr;
52749757b68SKonstantin Ananyev
52849757b68SKonstantin Ananyev if (inbound != 0) {
52949757b68SKonstantin Ananyev acr = acl4_rules_in;
53049757b68SKonstantin Ananyev num = nb_acl4_rules_in;
53149757b68SKonstantin Ananyev } else {
53249757b68SKonstantin Ananyev acr = acl4_rules_out;
53349757b68SKonstantin Ananyev num = nb_acl4_rules_out;
53449757b68SKonstantin Ananyev }
53549757b68SKonstantin Ananyev
53649757b68SKonstantin Ananyev for (i = 0; i != num; i++) {
53749757b68SKonstantin Ananyev spi = acr[i].data.userdata;
538df3e1d94SVladimir Medvedkin if (spi != DISCARD && spi != BYPASS) {
539df3e1d94SVladimir Medvedkin spi_idx = sa_spi_present(sa_ctx, spi, inbound);
540df3e1d94SVladimir Medvedkin if (spi_idx < 0) {
541df3e1d94SVladimir Medvedkin RTE_LOG(ERR, IPSEC,
542df3e1d94SVladimir Medvedkin "SPI %u is not present in SAD\n",
54349757b68SKonstantin Ananyev spi);
54449757b68SKonstantin Ananyev return -ENOENT;
54549757b68SKonstantin Ananyev }
546df3e1d94SVladimir Medvedkin /* Update userdata with spi index */
547df3e1d94SVladimir Medvedkin acr[i].data.userdata = spi_idx + 1;
548df3e1d94SVladimir Medvedkin }
54949757b68SKonstantin Ananyev }
55049757b68SKonstantin Ananyev
55149757b68SKonstantin Ananyev return 0;
55249757b68SKonstantin Ananyev }
55349757b68SKonstantin Ananyev
554906257e9SSergio Gonzalez Monroy void
sp4_init(struct socket_ctx * ctx,int32_t socket_id)5550d547ed0SFan Zhang sp4_init(struct socket_ctx *ctx, int32_t socket_id)
556906257e9SSergio Gonzalez Monroy {
557906257e9SSergio Gonzalez Monroy const char *name;
558906257e9SSergio Gonzalez Monroy
559906257e9SSergio Gonzalez Monroy if (ctx == NULL)
560906257e9SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "NULL context.\n");
561906257e9SSergio Gonzalez Monroy
562906257e9SSergio Gonzalez Monroy if (ctx->sp_ip4_in != NULL)
563906257e9SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Inbound SP DB for socket %u already "
564906257e9SSergio Gonzalez Monroy "initialized\n", socket_id);
565906257e9SSergio Gonzalez Monroy
566906257e9SSergio Gonzalez Monroy if (ctx->sp_ip4_out != NULL)
567906257e9SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Outbound SP DB for socket %u already "
568906257e9SSergio Gonzalez Monroy "initialized\n", socket_id);
569906257e9SSergio Gonzalez Monroy
570df3e1d94SVladimir Medvedkin if (check_spi_value(ctx->sa_in, 1) < 0)
57149757b68SKonstantin Ananyev rte_exit(EXIT_FAILURE,
57249757b68SKonstantin Ananyev "Inbound IPv4 SP DB has unmatched in SAD SPIs\n");
57349757b68SKonstantin Ananyev
574df3e1d94SVladimir Medvedkin if (check_spi_value(ctx->sa_out, 0) < 0)
57549757b68SKonstantin Ananyev rte_exit(EXIT_FAILURE,
57649757b68SKonstantin Ananyev "Outbound IPv4 SP DB has unmatched in SAD SPIs\n");
57749757b68SKonstantin Ananyev
5780d547ed0SFan Zhang if (nb_acl4_rules_in > 0) {
579906257e9SSergio Gonzalez Monroy name = "sp_ip4_in";
5800d547ed0SFan Zhang ctx->sp_ip4_in = (struct sp_ctx *)acl4_init(name,
5810d547ed0SFan Zhang socket_id, acl4_rules_in, nb_acl4_rules_in);
5820d547ed0SFan Zhang } else
5830d547ed0SFan Zhang RTE_LOG(WARNING, IPSEC, "No IPv4 SP Inbound rule "
5840d547ed0SFan Zhang "specified\n");
585906257e9SSergio Gonzalez Monroy
5860d547ed0SFan Zhang if (nb_acl4_rules_out > 0) {
587906257e9SSergio Gonzalez Monroy name = "sp_ip4_out";
5880d547ed0SFan Zhang ctx->sp_ip4_out = (struct sp_ctx *)acl4_init(name,
5890d547ed0SFan Zhang socket_id, acl4_rules_out, nb_acl4_rules_out);
5900d547ed0SFan Zhang } else
5910d547ed0SFan Zhang RTE_LOG(WARNING, IPSEC, "No IPv4 SP Outbound rule "
5920d547ed0SFan Zhang "specified\n");
593906257e9SSergio Gonzalez Monroy }
5945a032a71SKonstantin Ananyev
595b0806375SVladimir Medvedkin static int
sp_cmp(const void * p,const void * q)596b0806375SVladimir Medvedkin sp_cmp(const void *p, const void *q)
597b0806375SVladimir Medvedkin {
598b0806375SVladimir Medvedkin uint32_t spi1 = ((const struct acl4_rules *)p)->data.userdata;
599b0806375SVladimir Medvedkin uint32_t spi2 = ((const struct acl4_rules *)q)->data.userdata;
600b0806375SVladimir Medvedkin
601b0806375SVladimir Medvedkin return (int)(spi1 - spi2);
602b0806375SVladimir Medvedkin }
603b0806375SVladimir Medvedkin
604b0806375SVladimir Medvedkin
6055a032a71SKonstantin Ananyev /*
6065a032a71SKonstantin Ananyev * Search though SP rules for given SPI.
6075a032a71SKonstantin Ananyev */
6085a032a71SKonstantin Ananyev int
sp4_spi_present(uint32_t spi,int inbound,struct ip_addr ip_addr[2],uint32_t mask[2])609b1a3ac78SMariusz Drost sp4_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
610b1a3ac78SMariusz Drost uint32_t mask[2])
6115a032a71SKonstantin Ananyev {
612b0806375SVladimir Medvedkin uint32_t num;
613b0806375SVladimir Medvedkin struct acl4_rules *rule;
6145a032a71SKonstantin Ananyev const struct acl4_rules *acr;
615b0806375SVladimir Medvedkin struct acl4_rules tmpl;
6165a032a71SKonstantin Ananyev
6175a032a71SKonstantin Ananyev if (inbound != 0) {
6185a032a71SKonstantin Ananyev acr = acl4_rules_in;
6195a032a71SKonstantin Ananyev num = nb_acl4_rules_in;
6205a032a71SKonstantin Ananyev } else {
6215a032a71SKonstantin Ananyev acr = acl4_rules_out;
6225a032a71SKonstantin Ananyev num = nb_acl4_rules_out;
6235a032a71SKonstantin Ananyev }
6245a032a71SKonstantin Ananyev
625b0806375SVladimir Medvedkin tmpl.data.userdata = spi;
626b0806375SVladimir Medvedkin
627b0806375SVladimir Medvedkin rule = bsearch(&tmpl, acr, num, sizeof(struct acl4_rules), sp_cmp);
628b0806375SVladimir Medvedkin if (rule != NULL) {
629b1a3ac78SMariusz Drost if (NULL != ip_addr && NULL != mask) {
630b0806375SVladimir Medvedkin ip_addr[0].ip.ip4 = IPV4_SRC_FROM_SP(*rule);
631b0806375SVladimir Medvedkin ip_addr[1].ip.ip4 = IPV4_DST_FROM_SP(*rule);
632b0806375SVladimir Medvedkin mask[0] = IPV4_SRC_MASK_FROM_SP(*rule);
633b0806375SVladimir Medvedkin mask[1] = IPV4_DST_MASK_FROM_SP(*rule);
634b1a3ac78SMariusz Drost }
635b0806375SVladimir Medvedkin return RTE_PTR_DIFF(rule, acr) / sizeof(struct acl4_rules);
636b1a3ac78SMariusz Drost }
6375a032a71SKonstantin Ananyev
6385a032a71SKonstantin Ananyev return -ENOENT;
6395a032a71SKonstantin Ananyev }
640b0806375SVladimir Medvedkin
641b0806375SVladimir Medvedkin void
sp4_sort_arr(void)642b0806375SVladimir Medvedkin sp4_sort_arr(void)
643b0806375SVladimir Medvedkin {
644b0806375SVladimir Medvedkin qsort(acl4_rules_in, nb_acl4_rules_in, sizeof(struct acl4_rules),
645b0806375SVladimir Medvedkin sp_cmp);
646b0806375SVladimir Medvedkin qsort(acl4_rules_out, nb_acl4_rules_out, sizeof(struct acl4_rules),
647b0806375SVladimir Medvedkin sp_cmp);
648b0806375SVladimir Medvedkin }
649