xref: /dpdk/examples/ipsec-secgw/sp4.c (revision d92fc70e14f43d13be4204c51ed7f3a671c1bcc4)
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 
180d547ed0SFan Zhang #define MAX_ACL_RULE_NUM	1024
19906257e9SSergio Gonzalez Monroy 
20906257e9SSergio Gonzalez Monroy /*
21906257e9SSergio Gonzalez Monroy  * Rule and trace formats definitions.
22906257e9SSergio Gonzalez Monroy  */
23906257e9SSergio Gonzalez Monroy enum {
24906257e9SSergio Gonzalez Monroy 	PROTO_FIELD_IPV4,
25906257e9SSergio Gonzalez Monroy 	SRC_FIELD_IPV4,
26906257e9SSergio Gonzalez Monroy 	DST_FIELD_IPV4,
27906257e9SSergio Gonzalez Monroy 	SRCP_FIELD_IPV4,
28906257e9SSergio Gonzalez Monroy 	DSTP_FIELD_IPV4,
29906257e9SSergio Gonzalez Monroy 	NUM_FIELDS_IPV4
30906257e9SSergio Gonzalez Monroy };
31906257e9SSergio Gonzalez Monroy 
32906257e9SSergio Gonzalez Monroy /*
33906257e9SSergio Gonzalez Monroy  * That effectively defines order of IPV4 classifications:
34906257e9SSergio Gonzalez Monroy  *  - PROTO
35906257e9SSergio Gonzalez Monroy  *  - SRC IP ADDRESS
36906257e9SSergio Gonzalez Monroy  *  - DST IP ADDRESS
37906257e9SSergio Gonzalez Monroy  *  - PORTS (SRC and DST)
38906257e9SSergio Gonzalez Monroy  */
39906257e9SSergio Gonzalez Monroy enum {
40906257e9SSergio Gonzalez Monroy 	RTE_ACL_IPV4_PROTO,
41906257e9SSergio Gonzalez Monroy 	RTE_ACL_IPV4_SRC,
42906257e9SSergio Gonzalez Monroy 	RTE_ACL_IPV4_DST,
43906257e9SSergio Gonzalez Monroy 	RTE_ACL_IPV4_PORTS,
44906257e9SSergio Gonzalez Monroy 	RTE_ACL_IPV4_NUM
45906257e9SSergio Gonzalez Monroy };
46906257e9SSergio Gonzalez Monroy 
47*d92fc70eSKonstantin Ananyev static struct rte_acl_field_def ip4_defs[NUM_FIELDS_IPV4] = {
48906257e9SSergio Gonzalez Monroy 	{
49906257e9SSergio Gonzalez Monroy 	.type = RTE_ACL_FIELD_TYPE_BITMASK,
50906257e9SSergio Gonzalez Monroy 	.size = sizeof(uint8_t),
51906257e9SSergio Gonzalez Monroy 	.field_index = PROTO_FIELD_IPV4,
52906257e9SSergio Gonzalez Monroy 	.input_index = RTE_ACL_IPV4_PROTO,
53906257e9SSergio Gonzalez Monroy 	.offset = 0,
54906257e9SSergio Gonzalez Monroy 	},
55906257e9SSergio Gonzalez Monroy 	{
56906257e9SSergio Gonzalez Monroy 	.type = RTE_ACL_FIELD_TYPE_MASK,
57906257e9SSergio Gonzalez Monroy 	.size = sizeof(uint32_t),
58906257e9SSergio Gonzalez Monroy 	.field_index = SRC_FIELD_IPV4,
59906257e9SSergio Gonzalez Monroy 	.input_index = RTE_ACL_IPV4_SRC,
60906257e9SSergio Gonzalez Monroy 	.offset = offsetof(struct ip, ip_src) -	offsetof(struct ip, ip_p)
61906257e9SSergio Gonzalez Monroy 	},
62906257e9SSergio Gonzalez Monroy 	{
63906257e9SSergio Gonzalez Monroy 	.type = RTE_ACL_FIELD_TYPE_MASK,
64906257e9SSergio Gonzalez Monroy 	.size = sizeof(uint32_t),
65906257e9SSergio Gonzalez Monroy 	.field_index = DST_FIELD_IPV4,
66906257e9SSergio Gonzalez Monroy 	.input_index = RTE_ACL_IPV4_DST,
67906257e9SSergio Gonzalez Monroy 	.offset = offsetof(struct ip, ip_dst) - offsetof(struct ip, ip_p)
68906257e9SSergio Gonzalez Monroy 	},
69906257e9SSergio Gonzalez Monroy 	{
70906257e9SSergio Gonzalez Monroy 	.type = RTE_ACL_FIELD_TYPE_RANGE,
71906257e9SSergio Gonzalez Monroy 	.size = sizeof(uint16_t),
72906257e9SSergio Gonzalez Monroy 	.field_index = SRCP_FIELD_IPV4,
73906257e9SSergio Gonzalez Monroy 	.input_index = RTE_ACL_IPV4_PORTS,
74906257e9SSergio Gonzalez Monroy 	.offset = sizeof(struct ip) - offsetof(struct ip, ip_p)
75906257e9SSergio Gonzalez Monroy 	},
76906257e9SSergio Gonzalez Monroy 	{
77906257e9SSergio Gonzalez Monroy 	.type = RTE_ACL_FIELD_TYPE_RANGE,
78906257e9SSergio Gonzalez Monroy 	.size = sizeof(uint16_t),
79906257e9SSergio Gonzalez Monroy 	.field_index = DSTP_FIELD_IPV4,
80906257e9SSergio Gonzalez Monroy 	.input_index = RTE_ACL_IPV4_PORTS,
81906257e9SSergio Gonzalez Monroy 	.offset = sizeof(struct ip) - offsetof(struct ip, ip_p) +
82906257e9SSergio Gonzalez Monroy 		sizeof(uint16_t)
83906257e9SSergio Gonzalez Monroy 	},
84906257e9SSergio Gonzalez Monroy };
85906257e9SSergio Gonzalez Monroy 
86906257e9SSergio Gonzalez Monroy RTE_ACL_RULE_DEF(acl4_rules, RTE_DIM(ip4_defs));
87906257e9SSergio Gonzalez Monroy 
88*d92fc70eSKonstantin Ananyev static struct acl4_rules acl4_rules_out[MAX_ACL_RULE_NUM];
89*d92fc70eSKonstantin Ananyev static uint32_t nb_acl4_rules_out;
90906257e9SSergio Gonzalez Monroy 
91*d92fc70eSKonstantin Ananyev static struct acl4_rules acl4_rules_in[MAX_ACL_RULE_NUM];
92*d92fc70eSKonstantin Ananyev static uint32_t nb_acl4_rules_in;
930d547ed0SFan Zhang 
940d547ed0SFan Zhang void
950d547ed0SFan Zhang parse_sp4_tokens(char **tokens, uint32_t n_tokens,
960d547ed0SFan Zhang 	struct parse_status *status)
97906257e9SSergio Gonzalez Monroy {
980d547ed0SFan Zhang 	struct acl4_rules *rule_ipv4 = NULL;
990d547ed0SFan Zhang 
1000d547ed0SFan Zhang 	uint32_t *ri = NULL; /* rule index */
1010d547ed0SFan Zhang 	uint32_t ti = 0; /* token index */
1020d547ed0SFan Zhang 
1030d547ed0SFan Zhang 	uint32_t esp_p = 0;
1040d547ed0SFan Zhang 	uint32_t protect_p = 0;
1050d547ed0SFan Zhang 	uint32_t bypass_p = 0;
1060d547ed0SFan Zhang 	uint32_t discard_p = 0;
1070d547ed0SFan Zhang 	uint32_t pri_p = 0;
1080d547ed0SFan Zhang 	uint32_t src_p = 0;
1090d547ed0SFan Zhang 	uint32_t dst_p = 0;
1100d547ed0SFan Zhang 	uint32_t proto_p = 0;
1110d547ed0SFan Zhang 	uint32_t sport_p = 0;
1120d547ed0SFan Zhang 	uint32_t dport_p = 0;
1130d547ed0SFan Zhang 
1140d547ed0SFan Zhang 	if (strcmp(tokens[1], "in") == 0) {
1150d547ed0SFan Zhang 		ri = &nb_acl4_rules_in;
1160d547ed0SFan Zhang 
1170d547ed0SFan Zhang 		APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status,
1180d547ed0SFan Zhang 			"too many sp rules, abort insertion\n");
1190d547ed0SFan Zhang 		if (status->status < 0)
1200d547ed0SFan Zhang 			return;
1210d547ed0SFan Zhang 
1220d547ed0SFan Zhang 		rule_ipv4 = &acl4_rules_in[*ri];
1230d547ed0SFan Zhang 
1240d547ed0SFan Zhang 	} else if (strcmp(tokens[1], "out") == 0) {
1250d547ed0SFan Zhang 		ri = &nb_acl4_rules_out;
1260d547ed0SFan Zhang 
1270d547ed0SFan Zhang 		APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status,
1280d547ed0SFan Zhang 			"too many sp rules, abort insertion\n");
1290d547ed0SFan Zhang 		if (status->status < 0)
1300d547ed0SFan Zhang 			return;
1310d547ed0SFan Zhang 
1320d547ed0SFan Zhang 		rule_ipv4 = &acl4_rules_out[*ri];
1330d547ed0SFan Zhang 	} else {
1340d547ed0SFan Zhang 		APP_CHECK(0, status, "unrecognized input \"%s\", expect"
1350d547ed0SFan Zhang 			" \"in\" or \"out\"\n", tokens[ti]);
1360d547ed0SFan Zhang 		return;
137906257e9SSergio Gonzalez Monroy 	}
1380d547ed0SFan Zhang 
1390d547ed0SFan Zhang 	rule_ipv4->data.category_mask = 1;
1400d547ed0SFan Zhang 
1410d547ed0SFan Zhang 	for (ti = 2; ti < n_tokens; ti++) {
1420d547ed0SFan Zhang 		if (strcmp(tokens[ti], "esp") == 0) {
1430d547ed0SFan Zhang 			/* currently do nothing */
1440d547ed0SFan Zhang 			APP_CHECK_PRESENCE(esp_p, tokens[ti], status);
1450d547ed0SFan Zhang 			if (status->status < 0)
1460d547ed0SFan Zhang 				return;
1470d547ed0SFan Zhang 			esp_p = 1;
1480d547ed0SFan Zhang 			continue;
1490d547ed0SFan Zhang 		}
1500d547ed0SFan Zhang 
1510d547ed0SFan Zhang 		if (strcmp(tokens[ti], "protect") == 0) {
1520d547ed0SFan Zhang 			APP_CHECK_PRESENCE(protect_p, tokens[ti], status);
1530d547ed0SFan Zhang 			if (status->status < 0)
1540d547ed0SFan Zhang 				return;
1550d547ed0SFan Zhang 			APP_CHECK(bypass_p == 0, status, "conflict item "
1560d547ed0SFan Zhang 				"between \"%s\" and \"%s\"", tokens[ti],
1570d547ed0SFan Zhang 				"bypass");
1580d547ed0SFan Zhang 			if (status->status < 0)
1590d547ed0SFan Zhang 				return;
1600d547ed0SFan Zhang 			APP_CHECK(discard_p == 0, status, "conflict item "
1610d547ed0SFan Zhang 				"between \"%s\" and \"%s\"", tokens[ti],
1620d547ed0SFan Zhang 				"discard");
1630d547ed0SFan Zhang 			if (status->status < 0)
1640d547ed0SFan Zhang 				return;
1650d547ed0SFan Zhang 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
1660d547ed0SFan Zhang 			if (status->status < 0)
1670d547ed0SFan Zhang 				return;
1680d547ed0SFan Zhang 			APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
1690d547ed0SFan Zhang 			if (status->status < 0)
1700d547ed0SFan Zhang 				return;
1710d547ed0SFan Zhang 
1720d547ed0SFan Zhang 			rule_ipv4->data.userdata =
1730d547ed0SFan Zhang 				PROTECT(atoi(tokens[ti]));
1740d547ed0SFan Zhang 
1750d547ed0SFan Zhang 			protect_p = 1;
1760d547ed0SFan Zhang 			continue;
1770d547ed0SFan Zhang 		}
1780d547ed0SFan Zhang 
1790d547ed0SFan Zhang 		if (strcmp(tokens[ti], "bypass") == 0) {
1800d547ed0SFan Zhang 			APP_CHECK_PRESENCE(bypass_p, tokens[ti], status);
1810d547ed0SFan Zhang 			if (status->status < 0)
1820d547ed0SFan Zhang 				return;
1830d547ed0SFan Zhang 			APP_CHECK(protect_p == 0, status, "conflict item "
1840d547ed0SFan Zhang 				"between \"%s\" and \"%s\"", tokens[ti],
1850d547ed0SFan Zhang 				"protect");
1860d547ed0SFan Zhang 			if (status->status < 0)
1870d547ed0SFan Zhang 				return;
1880d547ed0SFan Zhang 			APP_CHECK(discard_p == 0, status, "conflict item "
1890d547ed0SFan Zhang 				"between \"%s\" and \"%s\"", tokens[ti],
1900d547ed0SFan Zhang 				"discard");
1910d547ed0SFan Zhang 			if (status->status < 0)
1920d547ed0SFan Zhang 				return;
1930d547ed0SFan Zhang 
1940d547ed0SFan Zhang 			rule_ipv4->data.userdata = BYPASS;
1950d547ed0SFan Zhang 
1960d547ed0SFan Zhang 			bypass_p = 1;
1970d547ed0SFan Zhang 			continue;
1980d547ed0SFan Zhang 		}
1990d547ed0SFan Zhang 
2000d547ed0SFan Zhang 		if (strcmp(tokens[ti], "discard") == 0) {
2010d547ed0SFan Zhang 			APP_CHECK_PRESENCE(discard_p, tokens[ti], status);
2020d547ed0SFan Zhang 			if (status->status < 0)
2030d547ed0SFan Zhang 				return;
2040d547ed0SFan Zhang 			APP_CHECK(protect_p == 0, status, "conflict item "
2050d547ed0SFan Zhang 				"between \"%s\" and \"%s\"", tokens[ti],
2060d547ed0SFan Zhang 				"protect");
2070d547ed0SFan Zhang 			if (status->status < 0)
2080d547ed0SFan Zhang 				return;
2090d547ed0SFan Zhang 			APP_CHECK(bypass_p == 0, status, "conflict item "
2100d547ed0SFan Zhang 				"between \"%s\" and \"%s\"", tokens[ti],
2110d547ed0SFan Zhang 				"discard");
2120d547ed0SFan Zhang 			if (status->status < 0)
2130d547ed0SFan Zhang 				return;
2140d547ed0SFan Zhang 
2150d547ed0SFan Zhang 			rule_ipv4->data.userdata = DISCARD;
2160d547ed0SFan Zhang 
2170d547ed0SFan Zhang 			discard_p = 1;
2180d547ed0SFan Zhang 			continue;
2190d547ed0SFan Zhang 		}
2200d547ed0SFan Zhang 
2210d547ed0SFan Zhang 		if (strcmp(tokens[ti], "pri") == 0) {
2220d547ed0SFan Zhang 			APP_CHECK_PRESENCE(pri_p, tokens[ti], status);
2230d547ed0SFan Zhang 			if (status->status < 0)
2240d547ed0SFan Zhang 				return;
2250d547ed0SFan Zhang 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
2260d547ed0SFan Zhang 			if (status->status < 0)
2270d547ed0SFan Zhang 				return;
2280d547ed0SFan Zhang 			APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
2290d547ed0SFan Zhang 			if (status->status < 0)
2300d547ed0SFan Zhang 				return;
2310d547ed0SFan Zhang 
2320d547ed0SFan Zhang 			rule_ipv4->data.priority = atoi(tokens[ti]);
2330d547ed0SFan Zhang 
2340d547ed0SFan Zhang 			pri_p = 1;
2350d547ed0SFan Zhang 			continue;
2360d547ed0SFan Zhang 		}
2370d547ed0SFan Zhang 
2380d547ed0SFan Zhang 		if (strcmp(tokens[ti], "src") == 0) {
2390d547ed0SFan Zhang 			struct in_addr ip;
2400d547ed0SFan Zhang 			uint32_t depth;
2410d547ed0SFan Zhang 
2420d547ed0SFan Zhang 			APP_CHECK_PRESENCE(src_p, tokens[ti], status);
2430d547ed0SFan Zhang 			if (status->status < 0)
2440d547ed0SFan Zhang 				return;
2450d547ed0SFan Zhang 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
2460d547ed0SFan Zhang 			if (status->status < 0)
2470d547ed0SFan Zhang 				return;
2480d547ed0SFan Zhang 
2490d547ed0SFan Zhang 			APP_CHECK(parse_ipv4_addr(tokens[ti], &ip,
2500d547ed0SFan Zhang 				&depth) == 0, status, "unrecognized "
2510d547ed0SFan Zhang 				"input \"%s\", expect valid ipv4 addr",
2520d547ed0SFan Zhang 				tokens[ti]);
2530d547ed0SFan Zhang 			if (status->status < 0)
2540d547ed0SFan Zhang 				return;
2550d547ed0SFan Zhang 
2560d547ed0SFan Zhang 			rule_ipv4->field[1].value.u32 =
2570d547ed0SFan Zhang 				rte_bswap32(ip.s_addr);
2580d547ed0SFan Zhang 			rule_ipv4->field[1].mask_range.u32 =
2590d547ed0SFan Zhang 				depth;
2600d547ed0SFan Zhang 
2610d547ed0SFan Zhang 			src_p = 1;
2620d547ed0SFan Zhang 			continue;
2630d547ed0SFan Zhang 		}
2640d547ed0SFan Zhang 
2650d547ed0SFan Zhang 		if (strcmp(tokens[ti], "dst") == 0) {
2660d547ed0SFan Zhang 			struct in_addr ip;
2670d547ed0SFan Zhang 			uint32_t depth;
2680d547ed0SFan Zhang 
2690d547ed0SFan Zhang 			APP_CHECK_PRESENCE(dst_p, tokens[ti], status);
2700d547ed0SFan Zhang 			if (status->status < 0)
2710d547ed0SFan Zhang 				return;
2720d547ed0SFan Zhang 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
2730d547ed0SFan Zhang 			if (status->status < 0)
2740d547ed0SFan Zhang 				return;
2750d547ed0SFan Zhang 			APP_CHECK(parse_ipv4_addr(tokens[ti], &ip,
2760d547ed0SFan Zhang 				&depth) == 0, status, "unrecognized "
2770d547ed0SFan Zhang 				"input \"%s\", expect valid ipv4 addr",
2780d547ed0SFan Zhang 				tokens[ti]);
2790d547ed0SFan Zhang 			if (status->status < 0)
2800d547ed0SFan Zhang 				return;
2810d547ed0SFan Zhang 
2820d547ed0SFan Zhang 			rule_ipv4->field[2].value.u32 =
2830d547ed0SFan Zhang 				rte_bswap32(ip.s_addr);
2840d547ed0SFan Zhang 			rule_ipv4->field[2].mask_range.u32 =
2850d547ed0SFan Zhang 				depth;
2860d547ed0SFan Zhang 
2870d547ed0SFan Zhang 			dst_p = 1;
2880d547ed0SFan Zhang 			continue;
2890d547ed0SFan Zhang 		}
2900d547ed0SFan Zhang 
2910d547ed0SFan Zhang 		if (strcmp(tokens[ti], "proto") == 0) {
2920d547ed0SFan Zhang 			uint16_t low, high;
2930d547ed0SFan Zhang 
2940d547ed0SFan Zhang 			APP_CHECK_PRESENCE(proto_p, tokens[ti], status);
2950d547ed0SFan Zhang 			if (status->status < 0)
2960d547ed0SFan Zhang 				return;
2970d547ed0SFan Zhang 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
2980d547ed0SFan Zhang 			if (status->status < 0)
2990d547ed0SFan Zhang 				return;
3000d547ed0SFan Zhang 
3010d547ed0SFan Zhang 			APP_CHECK(parse_range(tokens[ti], &low, &high)
3020d547ed0SFan Zhang 				== 0, status, "unrecognized input \"%s\""
3030d547ed0SFan Zhang 				", expect \"from:to\"", tokens[ti]);
3040d547ed0SFan Zhang 			if (status->status < 0)
3050d547ed0SFan Zhang 				return;
3060d547ed0SFan Zhang 			APP_CHECK(low <= 0xff, status, "proto low "
3070d547ed0SFan Zhang 				"over-limit");
3080d547ed0SFan Zhang 			if (status->status < 0)
3090d547ed0SFan Zhang 				return;
3100d547ed0SFan Zhang 			APP_CHECK(high <= 0xff, status, "proto high "
3110d547ed0SFan Zhang 				"over-limit");
3120d547ed0SFan Zhang 			if (status->status < 0)
3130d547ed0SFan Zhang 				return;
3140d547ed0SFan Zhang 
3150d547ed0SFan Zhang 			rule_ipv4->field[0].value.u8 = (uint8_t)low;
3160d547ed0SFan Zhang 			rule_ipv4->field[0].mask_range.u8 = (uint8_t)high;
3170d547ed0SFan Zhang 
3180d547ed0SFan Zhang 			proto_p = 1;
3190d547ed0SFan Zhang 			continue;
3200d547ed0SFan Zhang 		}
3210d547ed0SFan Zhang 
3220d547ed0SFan Zhang 		if (strcmp(tokens[ti], "sport") == 0) {
3230d547ed0SFan Zhang 			uint16_t port_low, port_high;
3240d547ed0SFan Zhang 
3250d547ed0SFan Zhang 			APP_CHECK_PRESENCE(sport_p, tokens[ti], status);
3260d547ed0SFan Zhang 			if (status->status < 0)
3270d547ed0SFan Zhang 				return;
3280d547ed0SFan Zhang 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
3290d547ed0SFan Zhang 			if (status->status < 0)
3300d547ed0SFan Zhang 				return;
3310d547ed0SFan Zhang 
3320d547ed0SFan Zhang 			APP_CHECK(parse_range(tokens[ti], &port_low,
3330d547ed0SFan Zhang 				&port_high) == 0, status, "unrecognized "
3340d547ed0SFan Zhang 				"input \"%s\", expect \"port_from:"
3350d547ed0SFan Zhang 				"port_to\"", tokens[ti]);
3360d547ed0SFan Zhang 			if (status->status < 0)
3370d547ed0SFan Zhang 				return;
3380d547ed0SFan Zhang 
3390d547ed0SFan Zhang 			rule_ipv4->field[3].value.u16 = port_low;
3400d547ed0SFan Zhang 			rule_ipv4->field[3].mask_range.u16 = port_high;
3410d547ed0SFan Zhang 
3420d547ed0SFan Zhang 			sport_p = 1;
3430d547ed0SFan Zhang 			continue;
3440d547ed0SFan Zhang 		}
3450d547ed0SFan Zhang 
3460d547ed0SFan Zhang 		if (strcmp(tokens[ti], "dport") == 0) {
3470d547ed0SFan Zhang 			uint16_t port_low, port_high;
3480d547ed0SFan Zhang 
3490d547ed0SFan Zhang 			APP_CHECK_PRESENCE(dport_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_range(tokens[ti], &port_low,
3570d547ed0SFan Zhang 				&port_high) == 0, status, "unrecognized "
3580d547ed0SFan Zhang 				"input \"%s\", expect \"port_from:"
3590d547ed0SFan Zhang 				"port_to\"", tokens[ti]);
3600d547ed0SFan Zhang 			if (status->status < 0)
3610d547ed0SFan Zhang 				return;
3620d547ed0SFan Zhang 
3630d547ed0SFan Zhang 			rule_ipv4->field[4].value.u16 = port_low;
3640d547ed0SFan Zhang 			rule_ipv4->field[4].mask_range.u16 = port_high;
3650d547ed0SFan Zhang 
3660d547ed0SFan Zhang 			dport_p = 1;
3670d547ed0SFan Zhang 			continue;
3680d547ed0SFan Zhang 		}
3690d547ed0SFan Zhang 
3700d547ed0SFan Zhang 		/* unrecognizeable input */
3710d547ed0SFan Zhang 		APP_CHECK(0, status, "unrecognized input \"%s\"",
3720d547ed0SFan Zhang 			tokens[ti]);
3730d547ed0SFan Zhang 		return;
3740d547ed0SFan Zhang 	}
3750d547ed0SFan Zhang 
3760d547ed0SFan Zhang 	/* check if argument(s) are missing */
3770d547ed0SFan Zhang 	APP_CHECK(esp_p == 1, status, "missing argument \"esp\"");
3780d547ed0SFan Zhang 	if (status->status < 0)
3790d547ed0SFan Zhang 		return;
3800d547ed0SFan Zhang 
3810d547ed0SFan Zhang 	APP_CHECK(protect_p | bypass_p | discard_p, status, "missing "
3820d547ed0SFan Zhang 		"argument \"protect\", \"bypass\", or \"discard\"");
3830d547ed0SFan Zhang 	if (status->status < 0)
3840d547ed0SFan Zhang 		return;
3850d547ed0SFan Zhang 
3860d547ed0SFan Zhang 	*ri = *ri + 1;
3870d547ed0SFan Zhang }
388906257e9SSergio Gonzalez Monroy 
389906257e9SSergio Gonzalez Monroy static void
390906257e9SSergio Gonzalez Monroy print_one_ip4_rule(const struct acl4_rules *rule, int32_t extra)
391906257e9SSergio Gonzalez Monroy {
392906257e9SSergio Gonzalez Monroy 	uint8_t a, b, c, d;
393906257e9SSergio Gonzalez Monroy 
394906257e9SSergio Gonzalez Monroy 	uint32_t_to_char(rule->field[SRC_FIELD_IPV4].value.u32,
395906257e9SSergio Gonzalez Monroy 			&a, &b, &c, &d);
396906257e9SSergio Gonzalez Monroy 	printf("%hhu.%hhu.%hhu.%hhu/%u ", a, b, c, d,
397906257e9SSergio Gonzalez Monroy 			rule->field[SRC_FIELD_IPV4].mask_range.u32);
398906257e9SSergio Gonzalez Monroy 	uint32_t_to_char(rule->field[DST_FIELD_IPV4].value.u32,
399906257e9SSergio Gonzalez Monroy 			&a, &b, &c, &d);
400906257e9SSergio Gonzalez Monroy 	printf("%hhu.%hhu.%hhu.%hhu/%u ", a, b, c, d,
401906257e9SSergio Gonzalez Monroy 			rule->field[DST_FIELD_IPV4].mask_range.u32);
402906257e9SSergio Gonzalez Monroy 	printf("%hu : %hu %hu : %hu 0x%hhx/0x%hhx ",
403906257e9SSergio Gonzalez Monroy 		rule->field[SRCP_FIELD_IPV4].value.u16,
404906257e9SSergio Gonzalez Monroy 		rule->field[SRCP_FIELD_IPV4].mask_range.u16,
405906257e9SSergio Gonzalez Monroy 		rule->field[DSTP_FIELD_IPV4].value.u16,
406906257e9SSergio Gonzalez Monroy 		rule->field[DSTP_FIELD_IPV4].mask_range.u16,
407906257e9SSergio Gonzalez Monroy 		rule->field[PROTO_FIELD_IPV4].value.u8,
408906257e9SSergio Gonzalez Monroy 		rule->field[PROTO_FIELD_IPV4].mask_range.u8);
409906257e9SSergio Gonzalez Monroy 	if (extra)
410906257e9SSergio Gonzalez Monroy 		printf("0x%x-0x%x-0x%x ",
411906257e9SSergio Gonzalez Monroy 			rule->data.category_mask,
412906257e9SSergio Gonzalez Monroy 			rule->data.priority,
413906257e9SSergio Gonzalez Monroy 			rule->data.userdata);
414906257e9SSergio Gonzalez Monroy }
415906257e9SSergio Gonzalez Monroy 
416906257e9SSergio Gonzalez Monroy static inline void
417906257e9SSergio Gonzalez Monroy dump_ip4_rules(const struct acl4_rules *rule, int32_t num, int32_t extra)
418906257e9SSergio Gonzalez Monroy {
419906257e9SSergio Gonzalez Monroy 	int32_t i;
420906257e9SSergio Gonzalez Monroy 
421906257e9SSergio Gonzalez Monroy 	for (i = 0; i < num; i++, rule++) {
422906257e9SSergio Gonzalez Monroy 		printf("\t%d:", i + 1);
423906257e9SSergio Gonzalez Monroy 		print_one_ip4_rule(rule, extra);
424906257e9SSergio Gonzalez Monroy 		printf("\n");
425906257e9SSergio Gonzalez Monroy 	}
426906257e9SSergio Gonzalez Monroy }
427906257e9SSergio Gonzalez Monroy 
428906257e9SSergio Gonzalez Monroy static struct rte_acl_ctx *
429906257e9SSergio Gonzalez Monroy acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,
430906257e9SSergio Gonzalez Monroy 		uint32_t rules_nb)
431906257e9SSergio Gonzalez Monroy {
432906257e9SSergio Gonzalez Monroy 	char s[PATH_MAX];
433906257e9SSergio Gonzalez Monroy 	struct rte_acl_param acl_param;
434906257e9SSergio Gonzalez Monroy 	struct rte_acl_config acl_build_param;
435906257e9SSergio Gonzalez Monroy 	struct rte_acl_ctx *ctx;
436906257e9SSergio Gonzalez Monroy 
437906257e9SSergio Gonzalez Monroy 	printf("Creating SP context with %u max rules\n", MAX_ACL_RULE_NUM);
438906257e9SSergio Gonzalez Monroy 
439906257e9SSergio Gonzalez Monroy 	memset(&acl_param, 0, sizeof(acl_param));
440906257e9SSergio Gonzalez Monroy 
441906257e9SSergio Gonzalez Monroy 	/* Create ACL contexts */
442906257e9SSergio Gonzalez Monroy 	snprintf(s, sizeof(s), "%s_%d", name, socketid);
443906257e9SSergio Gonzalez Monroy 
444906257e9SSergio Gonzalez Monroy 	printf("IPv4 %s entries [%u]:\n", s, rules_nb);
445906257e9SSergio Gonzalez Monroy 	dump_ip4_rules(rules, rules_nb, 1);
446906257e9SSergio Gonzalez Monroy 
447906257e9SSergio Gonzalez Monroy 	acl_param.name = s;
448906257e9SSergio Gonzalez Monroy 	acl_param.socket_id = socketid;
449906257e9SSergio Gonzalez Monroy 	acl_param.rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ip4_defs));
450906257e9SSergio Gonzalez Monroy 	acl_param.max_rule_num = MAX_ACL_RULE_NUM;
451906257e9SSergio Gonzalez Monroy 
452906257e9SSergio Gonzalez Monroy 	ctx = rte_acl_create(&acl_param);
453906257e9SSergio Gonzalez Monroy 	if (ctx == NULL)
454906257e9SSergio Gonzalez Monroy 		rte_exit(EXIT_FAILURE, "Failed to create ACL context\n");
455906257e9SSergio Gonzalez Monroy 
456906257e9SSergio Gonzalez Monroy 	if (rte_acl_add_rules(ctx, (const struct rte_acl_rule *)rules,
457906257e9SSergio Gonzalez Monroy 				rules_nb) < 0)
458906257e9SSergio Gonzalez Monroy 		rte_exit(EXIT_FAILURE, "add rules failed\n");
459906257e9SSergio Gonzalez Monroy 
460906257e9SSergio Gonzalez Monroy 	/* Perform builds */
461906257e9SSergio Gonzalez Monroy 	memset(&acl_build_param, 0, sizeof(acl_build_param));
462906257e9SSergio Gonzalez Monroy 
463906257e9SSergio Gonzalez Monroy 	acl_build_param.num_categories = DEFAULT_MAX_CATEGORIES;
464906257e9SSergio Gonzalez Monroy 	acl_build_param.num_fields = RTE_DIM(ip4_defs);
465906257e9SSergio Gonzalez Monroy 	memcpy(&acl_build_param.defs, ip4_defs, sizeof(ip4_defs));
466906257e9SSergio Gonzalez Monroy 
467906257e9SSergio Gonzalez Monroy 	if (rte_acl_build(ctx, &acl_build_param) != 0)
468906257e9SSergio Gonzalez Monroy 		rte_exit(EXIT_FAILURE, "Failed to build ACL trie\n");
469906257e9SSergio Gonzalez Monroy 
470906257e9SSergio Gonzalez Monroy 	rte_acl_dump(ctx);
471906257e9SSergio Gonzalez Monroy 
472906257e9SSergio Gonzalez Monroy 	return ctx;
473906257e9SSergio Gonzalez Monroy }
474906257e9SSergio Gonzalez Monroy 
475906257e9SSergio Gonzalez Monroy void
4760d547ed0SFan Zhang sp4_init(struct socket_ctx *ctx, int32_t socket_id)
477906257e9SSergio Gonzalez Monroy {
478906257e9SSergio Gonzalez Monroy 	const char *name;
479906257e9SSergio Gonzalez Monroy 
480906257e9SSergio Gonzalez Monroy 	if (ctx == NULL)
481906257e9SSergio Gonzalez Monroy 		rte_exit(EXIT_FAILURE, "NULL context.\n");
482906257e9SSergio Gonzalez Monroy 
483906257e9SSergio Gonzalez Monroy 	if (ctx->sp_ip4_in != NULL)
484906257e9SSergio Gonzalez Monroy 		rte_exit(EXIT_FAILURE, "Inbound SP DB for socket %u already "
485906257e9SSergio Gonzalez Monroy 				"initialized\n", socket_id);
486906257e9SSergio Gonzalez Monroy 
487906257e9SSergio Gonzalez Monroy 	if (ctx->sp_ip4_out != NULL)
488906257e9SSergio Gonzalez Monroy 		rte_exit(EXIT_FAILURE, "Outbound SP DB for socket %u already "
489906257e9SSergio Gonzalez Monroy 				"initialized\n", socket_id);
490906257e9SSergio Gonzalez Monroy 
4910d547ed0SFan Zhang 	if (nb_acl4_rules_in > 0) {
492906257e9SSergio Gonzalez Monroy 		name = "sp_ip4_in";
4930d547ed0SFan Zhang 		ctx->sp_ip4_in = (struct sp_ctx *)acl4_init(name,
4940d547ed0SFan Zhang 			socket_id, acl4_rules_in, nb_acl4_rules_in);
4950d547ed0SFan Zhang 	} else
4960d547ed0SFan Zhang 		RTE_LOG(WARNING, IPSEC, "No IPv4 SP Inbound rule "
4970d547ed0SFan Zhang 			"specified\n");
498906257e9SSergio Gonzalez Monroy 
4990d547ed0SFan Zhang 	if (nb_acl4_rules_out > 0) {
500906257e9SSergio Gonzalez Monroy 		name = "sp_ip4_out";
5010d547ed0SFan Zhang 		ctx->sp_ip4_out = (struct sp_ctx *)acl4_init(name,
5020d547ed0SFan Zhang 			socket_id, acl4_rules_out, nb_acl4_rules_out);
5030d547ed0SFan Zhang 	} else
5040d547ed0SFan Zhang 		RTE_LOG(WARNING, IPSEC, "No IPv4 SP Outbound rule "
5050d547ed0SFan Zhang 			"specified\n");
506906257e9SSergio Gonzalez Monroy }
507