X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;ds=sidebyside;f=examples%2Fipsec-secgw%2Fsp6.c;fp=examples%2Fipsec-secgw%2Fsp6.c;h=62fb492ce4908e111e88650c360fce95abfa2214;hb=6b3e017e5d25f15da73f7700f7f2ac553ef1a2e9;hp=1dda11a44350b5d6294a3d475f91e5cdb04fb33d;hpb=32e04ea00cd159613e04acef75e52bfca6eeff2f;p=deb_dpdk.git diff --git a/examples/ipsec-secgw/sp6.c b/examples/ipsec-secgw/sp6.c index 1dda11a4..62fb492c 100644 --- a/examples/ipsec-secgw/sp6.c +++ b/examples/ipsec-secgw/sp6.c @@ -42,8 +42,9 @@ #include #include "ipsec.h" +#include "parser.h" -#define MAX_ACL_RULE_NUM 1000 +#define MAX_ACL_RULE_NUM 1024 enum { IP6_PROTO, @@ -144,155 +145,363 @@ struct rte_acl_field_def ip6_defs[IP6_NUM] = { RTE_ACL_RULE_DEF(acl6_rules, RTE_DIM(ip6_defs)); -const struct acl6_rules acl6_rules_out[] = { - { - .data = {.userdata = PROTECT(5), .category_mask = 1, .priority = 1}, - /* destination IPv6 */ - .field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,}, - .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,}, - .field[7] = {.value.u32 = 0x55555555, .mask_range.u32 = 32,}, - .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,}, - /* source port */ - .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(6), .category_mask = 1, .priority = 1}, - /* destination IPv6 */ - .field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,}, - .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,}, - .field[7] = {.value.u32 = 0x66666666, .mask_range.u32 = 32,}, - .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,}, - /* source port */ - .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(10), .category_mask = 1, .priority = 1}, - /* destination IPv6 */ - .field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,}, - .field[6] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,}, - .field[7] = {.value.u32 = 0x00000000, .mask_range.u32 = 32,}, - .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,}, - /* source port */ - .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(11), .category_mask = 1, .priority = 1}, - /* destination IPv6 */ - .field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,}, - .field[6] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,}, - .field[7] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,}, - .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,}, - /* source port */ - .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(25), .category_mask = 1, .priority = 1}, - /* destination IPv6 */ - .field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,}, - .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,}, - .field[7] = {.value.u32 = 0xaaaaaaaa, .mask_range.u32 = 32,}, - .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,}, - /* source port */ - .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(26), .category_mask = 1, .priority = 1}, - /* destination IPv6 */ - .field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,}, - .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,}, - .field[7] = {.value.u32 = 0xbbbbbbbb, .mask_range.u32 = 32,}, - .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,}, - /* source port */ - .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} +struct acl6_rules acl6_rules_out[MAX_ACL_RULE_NUM]; +uint32_t nb_acl6_rules_out; + +struct acl6_rules acl6_rules_in[MAX_ACL_RULE_NUM]; +uint32_t nb_acl6_rules_in; + +void +parse_sp6_tokens(char **tokens, uint32_t n_tokens, + struct parse_status *status) +{ + struct acl6_rules *rule_ipv6 = NULL; + + uint32_t *ri = NULL; /* rule index */ + uint32_t ti = 0; /* token index */ + + uint32_t esp_p = 0; + uint32_t protect_p = 0; + uint32_t bypass_p = 0; + uint32_t discard_p = 0; + uint32_t pri_p = 0; + uint32_t src_p = 0; + uint32_t dst_p = 0; + uint32_t proto_p = 0; + uint32_t sport_p = 0; + uint32_t dport_p = 0; + + if (strcmp(tokens[1], "in") == 0) { + ri = &nb_acl6_rules_in; + + APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too " + "many sp rules, abort insertion\n"); + if (status->status < 0) + return; + + rule_ipv6 = &acl6_rules_in[*ri]; + + } else if (strcmp(tokens[1], "out") == 0) { + ri = &nb_acl6_rules_out; + + APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too " + "many sp rules, abort insertion\n"); + if (status->status < 0) + return; + + rule_ipv6 = &acl6_rules_out[*ri]; + + } else { + APP_CHECK(0, status, "unrecognized input \"%s\", expect" + " \"in\" or \"out\"\n", tokens[ti]); + return; } -}; -const struct acl6_rules acl6_rules_in[] = { - { - .data = {.userdata = PROTECT(15), .category_mask = 1, .priority = 1}, - /* destination IPv6 */ - .field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,}, - .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,}, - .field[7] = {.value.u32 = 0x55555555, .mask_range.u32 = 32,}, - .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,}, - /* source port */ - .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(16), .category_mask = 1, .priority = 1}, - /* destination IPv6 */ - .field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,}, - .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,}, - .field[7] = {.value.u32 = 0x66666666, .mask_range.u32 = 32,}, - .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,}, - /* source port */ - .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(110), .category_mask = 1, .priority = 1}, - /* destination IPv6 */ - .field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,}, - .field[6] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,}, - .field[7] = {.value.u32 = 0x00000000, .mask_range.u32 = 32,}, - .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,}, - /* source port */ - .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(111), .category_mask = 1, .priority = 1}, - /* destination IPv6 */ - .field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,}, - .field[6] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,}, - .field[7] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,}, - .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,}, - /* source port */ - .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(125), .category_mask = 1, .priority = 1}, - /* destination IPv6 */ - .field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,}, - .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,}, - .field[7] = {.value.u32 = 0xaaaaaaaa, .mask_range.u32 = 32,}, - .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,}, - /* source port */ - .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(126), .category_mask = 1, .priority = 1}, - /* destination IPv6 */ - .field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,}, - .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,}, - .field[7] = {.value.u32 = 0xbbbbbbbb, .mask_range.u32 = 32,}, - .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,}, - /* source port */ - .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} + rule_ipv6->data.category_mask = 1; + + + for (ti = 2; ti < n_tokens; ti++) { + if (strcmp(tokens[ti], "esp") == 0) { + /* currently do nothing */ + APP_CHECK_PRESENCE(esp_p, tokens[ti], status); + if (status->status < 0) + return; + esp_p = 1; + continue; + } + + if (strcmp(tokens[ti], "protect") == 0) { + APP_CHECK_PRESENCE(protect_p, tokens[ti], status); + if (status->status < 0) + return; + APP_CHECK(bypass_p == 0, status, "conflict item " + "between \"%s\" and \"%s\"", tokens[ti], + "bypass"); + if (status->status < 0) + return; + APP_CHECK(discard_p == 0, status, "conflict item " + "between \"%s\" and \"%s\"", tokens[ti], + "discard"); + if (status->status < 0) + return; + INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; + APP_CHECK_TOKEN_IS_NUM(tokens, ti, status); + if (status->status < 0) + return; + + rule_ipv6->data.userdata = + PROTECT(atoi(tokens[ti])); + + protect_p = 1; + continue; + } + + if (strcmp(tokens[ti], "bypass") == 0) { + APP_CHECK_PRESENCE(bypass_p, tokens[ti], status); + if (status->status < 0) + return; + APP_CHECK(protect_p == 0, status, "conflict item " + "between \"%s\" and \"%s\"", tokens[ti], + "protect"); + if (status->status < 0) + return; + APP_CHECK(discard_p == 0, status, "conflict item " + "between \"%s\" and \"%s\"", tokens[ti], + "discard"); + if (status->status < 0) + return; + + rule_ipv6->data.userdata = BYPASS; + + bypass_p = 1; + continue; + } + + if (strcmp(tokens[ti], "discard") == 0) { + APP_CHECK_PRESENCE(discard_p, tokens[ti], status); + if (status->status < 0) + return; + APP_CHECK(protect_p == 0, status, "conflict item " + "between \"%s\" and \"%s\"", tokens[ti], + "protect"); + if (status->status < 0) + return; + APP_CHECK(bypass_p == 0, status, "conflict item " + "between \"%s\" and \"%s\"", tokens[ti], + "discard"); + if (status->status < 0) + return; + + rule_ipv6->data.userdata = DISCARD; + + discard_p = 1; + continue; + } + + if (strcmp(tokens[ti], "pri") == 0) { + APP_CHECK_PRESENCE(pri_p, tokens[ti], status); + if (status->status < 0) + return; + INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; + APP_CHECK_TOKEN_IS_NUM(tokens, ti, status); + if (status->status < 0) + return; + + rule_ipv6->data.priority = atoi(tokens[ti]); + + pri_p = 1; + continue; + } + + if (strcmp(tokens[ti], "src") == 0) { + struct in6_addr ip; + uint32_t depth; + + APP_CHECK_PRESENCE(src_p, tokens[ti], status); + if (status->status < 0) + return; + INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; + + APP_CHECK(parse_ipv6_addr(tokens[ti], &ip, + &depth) == 0, status, "unrecognized " + "input \"%s\", expect valid ipv6 " + "addr", tokens[ti]); + if (status->status < 0) + return; + + rule_ipv6->field[1].value.u32 = + (uint32_t)ip.s6_addr[0] << 24 | + (uint32_t)ip.s6_addr[1] << 16 | + (uint32_t)ip.s6_addr[2] << 8 | + (uint32_t)ip.s6_addr[3]; + rule_ipv6->field[1].mask_range.u32 = + (depth > 32) ? 32 : depth; + depth = (depth > 32) ? (depth - 32) : 0; + rule_ipv6->field[2].value.u32 = + (uint32_t)ip.s6_addr[4] << 24 | + (uint32_t)ip.s6_addr[5] << 16 | + (uint32_t)ip.s6_addr[6] << 8 | + (uint32_t)ip.s6_addr[7]; + rule_ipv6->field[2].mask_range.u32 = + (depth > 32) ? 32 : depth; + depth = (depth > 32) ? (depth - 32) : 0; + rule_ipv6->field[3].value.u32 = + (uint32_t)ip.s6_addr[8] << 24 | + (uint32_t)ip.s6_addr[9] << 16 | + (uint32_t)ip.s6_addr[10] << 8 | + (uint32_t)ip.s6_addr[11]; + rule_ipv6->field[3].mask_range.u32 = + (depth > 32) ? 32 : depth; + depth = (depth > 32) ? (depth - 32) : 0; + rule_ipv6->field[4].value.u32 = + (uint32_t)ip.s6_addr[12] << 24 | + (uint32_t)ip.s6_addr[13] << 16 | + (uint32_t)ip.s6_addr[14] << 8 | + (uint32_t)ip.s6_addr[15]; + rule_ipv6->field[4].mask_range.u32 = + (depth > 32) ? 32 : depth; + + src_p = 1; + continue; + } + + if (strcmp(tokens[ti], "dst") == 0) { + struct in6_addr ip; + uint32_t depth; + + APP_CHECK_PRESENCE(dst_p, tokens[ti], status); + if (status->status < 0) + return; + INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; + + APP_CHECK(parse_ipv6_addr(tokens[ti], &ip, + &depth) == 0, status, "unrecognized " + "input \"%s\", expect valid ipv6 " + "addr", tokens[ti]); + if (status->status < 0) + return; + + rule_ipv6->field[5].value.u32 = + (uint32_t)ip.s6_addr[0] << 24 | + (uint32_t)ip.s6_addr[1] << 16 | + (uint32_t)ip.s6_addr[2] << 8 | + (uint32_t)ip.s6_addr[3]; + rule_ipv6->field[5].mask_range.u32 = + (depth > 32) ? 32 : depth; + depth = (depth > 32) ? (depth - 32) : 0; + rule_ipv6->field[6].value.u32 = + (uint32_t)ip.s6_addr[4] << 24 | + (uint32_t)ip.s6_addr[5] << 16 | + (uint32_t)ip.s6_addr[6] << 8 | + (uint32_t)ip.s6_addr[7]; + rule_ipv6->field[6].mask_range.u32 = + (depth > 32) ? 32 : depth; + depth = (depth > 32) ? (depth - 32) : 0; + rule_ipv6->field[7].value.u32 = + (uint32_t)ip.s6_addr[8] << 24 | + (uint32_t)ip.s6_addr[9] << 16 | + (uint32_t)ip.s6_addr[10] << 8 | + (uint32_t)ip.s6_addr[11]; + rule_ipv6->field[7].mask_range.u32 = + (depth > 32) ? 32 : depth; + depth = (depth > 32) ? (depth - 32) : 0; + rule_ipv6->field[8].value.u32 = + (uint32_t)ip.s6_addr[12] << 24 | + (uint32_t)ip.s6_addr[13] << 16 | + (uint32_t)ip.s6_addr[14] << 8 | + (uint32_t)ip.s6_addr[15]; + rule_ipv6->field[8].mask_range.u32 = + (depth > 32) ? 32 : depth; + + dst_p = 1; + continue; + } + + if (strcmp(tokens[ti], "proto") == 0) { + uint16_t low, high; + + APP_CHECK_PRESENCE(proto_p, tokens[ti], status); + if (status->status < 0) + return; + INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; + + APP_CHECK(parse_range(tokens[ti], &low, &high) + == 0, status, "unrecognized input \"%s\"" + ", expect \"from:to\"", tokens[ti]); + if (status->status < 0) + return; + APP_CHECK(low <= 0xff, status, "proto low " + "over-limit"); + if (status->status < 0) + return; + APP_CHECK(high <= 0xff, status, "proto high " + "over-limit"); + if (status->status < 0) + return; + + rule_ipv6->field[0].value.u8 = (uint8_t)low; + rule_ipv6->field[0].mask_range.u8 = (uint8_t)high; + + proto_p = 1; + continue; + } + + if (strcmp(tokens[ti], "sport") == 0) { + uint16_t port_low, port_high; + + APP_CHECK_PRESENCE(sport_p, tokens[ti], status); + if (status->status < 0) + return; + INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; + + APP_CHECK(parse_range(tokens[ti], &port_low, + &port_high) == 0, status, "unrecognized " + "input \"%s\", expect \"port_from:" + "port_to\"", tokens[ti]); + if (status->status < 0) + return; + + rule_ipv6->field[9].value.u16 = port_low; + rule_ipv6->field[9].mask_range.u16 = port_high; + + sport_p = 1; + continue; + } + + if (strcmp(tokens[ti], "dport") == 0) { + uint16_t port_low, port_high; + + APP_CHECK_PRESENCE(dport_p, tokens[ti], status); + if (status->status < 0) + return; + INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; + + APP_CHECK(parse_range(tokens[ti], &port_low, + &port_high) == 0, status, "unrecognized " + "input \"%s\", expect \"port_from:" + "port_to\"", tokens[ti]); + if (status->status < 0) + return; + + rule_ipv6->field[10].value.u16 = port_low; + rule_ipv6->field[10].mask_range.u16 = port_high; + + dport_p = 1; + continue; + } + + /* unrecognizeable input */ + APP_CHECK(0, status, "unrecognized input \"%s\"", + tokens[ti]); + return; } -}; + + /* check if argument(s) are missing */ + APP_CHECK(esp_p == 1, status, "missing argument \"esp\""); + if (status->status < 0) + return; + + APP_CHECK(protect_p | bypass_p | discard_p, status, "missing " + "argument \"protect\", \"bypass\", or \"discard\""); + if (status->status < 0) + return; + + *ri = *ri + 1; +} static inline void print_one_ip6_rule(const struct acl6_rules *rule, int32_t extra) @@ -407,11 +616,9 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules, } void -sp6_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep) +sp6_init(struct socket_ctx *ctx, int32_t socket_id) { const char *name; - const struct acl6_rules *rules_out, *rules_in; - uint32_t nb_out_rules, nb_in_rules; if (ctx == NULL) rte_exit(EXIT_FAILURE, "NULL context.\n"); @@ -424,25 +631,19 @@ sp6_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep) rte_exit(EXIT_FAILURE, "Outbound IPv6 SP DB for socket %u " "already initialized\n", socket_id); - if (ep == 0) { - rules_out = acl6_rules_out; - nb_out_rules = RTE_DIM(acl6_rules_out); - rules_in = acl6_rules_in; - nb_in_rules = RTE_DIM(acl6_rules_in); - } else if (ep == 1) { - rules_out = acl6_rules_in; - nb_out_rules = RTE_DIM(acl6_rules_in); - rules_in = acl6_rules_out; - nb_in_rules = RTE_DIM(acl6_rules_out); + if (nb_acl6_rules_in > 0) { + name = "sp_ip6_in"; + ctx->sp_ip6_in = (struct sp_ctx *)acl6_init(name, + socket_id, acl6_rules_in, nb_acl6_rules_in); } else - rte_exit(EXIT_FAILURE, "Invalid EP value %u. " - "Only 0 or 1 supported.\n", ep); + RTE_LOG(WARNING, IPSEC, "No IPv6 SP Inbound rule " + "specified\n"); - name = "sp_ip6_in"; - ctx->sp_ip6_in = (struct sp_ctx *)acl6_init(name, socket_id, - rules_in, nb_in_rules); - - name = "sp_ip6_out"; - ctx->sp_ip6_out = (struct sp_ctx *)acl6_init(name, socket_id, - rules_out, nb_out_rules); + if (nb_acl6_rules_out > 0) { + name = "sp_ip6_out"; + ctx->sp_ip6_out = (struct sp_ctx *)acl6_init(name, + socket_id, acl6_rules_out, nb_acl6_rules_out); + } else + RTE_LOG(WARNING, IPSEC, "No IPv6 SP Outbound rule " + "specified\n"); }