net/bnxt: support 58818 chip family
[dpdk.git] / examples / ipsec-secgw / parser.c
index e2e3429..98dff93 100644 (file)
@@ -1,6 +1,9 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2016 Intel Corporation
  */
+#include <arpa/inet.h>
+#include <sys/socket.h>
+
 #include <rte_common.h>
 #include <rte_crypto.h>
 #include <rte_string_fns.h>
@@ -11,6 +14,7 @@
 #include <cmdline_socket.h>
 #include <cmdline.h>
 
+#include "flow.h"
 #include "ipsec.h"
 #include "parser.h"
 
@@ -39,172 +43,6 @@ parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
        return 0;
 }
 
-#define INADDRSZ 4
-#define IN6ADDRSZ 16
-
-/* int
- * inet_pton4(src, dst)
- *      like inet_aton() but without all the hexadecimal and shorthand.
- * return:
- *      1 if `src' is a valid dotted quad, else 0.
- * notice:
- *      does not touch `dst' unless it's returning 1.
- * author:
- *      Paul Vixie, 1996.
- */
-static int
-inet_pton4(const char *src, unsigned char *dst)
-{
-       static const char digits[] = "0123456789";
-       int saw_digit, octets, ch;
-       unsigned char tmp[INADDRSZ], *tp;
-
-       saw_digit = 0;
-       octets = 0;
-       *(tp = tmp) = 0;
-       while ((ch = *src++) != '\0') {
-               const char *pch;
-
-               pch = strchr(digits, ch);
-               if (pch != NULL) {
-                       unsigned int new = *tp * 10 + (pch - digits);
-
-                       if (new > 255)
-                               return 0;
-                       if (!saw_digit) {
-                               if (++octets > 4)
-                                       return 0;
-                               saw_digit = 1;
-                       }
-                       *tp = (unsigned char)new;
-               } else if (ch == '.' && saw_digit) {
-                       if (octets == 4)
-                               return 0;
-                       *++tp = 0;
-                       saw_digit = 0;
-               } else
-                       return 0;
-       }
-       if (octets < 4)
-               return 0;
-
-       memcpy(dst, tmp, INADDRSZ);
-       return 1;
-}
-
-/* int
- * inet_pton6(src, dst)
- *      convert presentation level address to network order binary form.
- * return:
- *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
- * notice:
- *      (1) does not touch `dst' unless it's returning 1.
- *      (2) :: in a full address is silently ignored.
- * credit:
- *      inspired by Mark Andrews.
- * author:
- *      Paul Vixie, 1996.
- */
-static int
-inet_pton6(const char *src, unsigned char *dst)
-{
-       static const char xdigits_l[] = "0123456789abcdef",
-               xdigits_u[] = "0123456789ABCDEF";
-       unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
-       const char *xdigits = 0, *curtok = 0;
-       int ch = 0, saw_xdigit = 0, count_xdigit = 0;
-       unsigned int val = 0;
-       unsigned dbloct_count = 0;
-
-       memset((tp = tmp), '\0', IN6ADDRSZ);
-       endp = tp + IN6ADDRSZ;
-       colonp = NULL;
-       /* Leading :: requires some special handling. */
-       if (*src == ':')
-               if (*++src != ':')
-                       return 0;
-       curtok = src;
-       saw_xdigit = count_xdigit = 0;
-       val = 0;
-
-       while ((ch = *src++) != '\0') {
-               const char *pch;
-
-               pch = strchr((xdigits = xdigits_l), ch);
-               if (pch == NULL)
-                       pch = strchr((xdigits = xdigits_u), ch);
-               if (pch != NULL) {
-                       if (count_xdigit >= 4)
-                               return 0;
-                       val <<= 4;
-                       val |= (pch - xdigits);
-                       if (val > 0xffff)
-                               return 0;
-                       saw_xdigit = 1;
-                       count_xdigit++;
-                       continue;
-               }
-               if (ch == ':') {
-                       curtok = src;
-                       if (!saw_xdigit) {
-                               if (colonp)
-                                       return 0;
-                               colonp = tp;
-                               continue;
-                       } else if (*src == '\0') {
-                               return 0;
-                       }
-                       if (tp + sizeof(int16_t) > endp)
-                               return 0;
-                       *tp++ = (unsigned char) ((val >> 8) & 0xff);
-                       *tp++ = (unsigned char) (val & 0xff);
-                       saw_xdigit = 0;
-                       count_xdigit = 0;
-                       val = 0;
-                       dbloct_count++;
-                       continue;
-               }
-               if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
-                   inet_pton4(curtok, tp) > 0) {
-                       tp += INADDRSZ;
-                       saw_xdigit = 0;
-                       dbloct_count += 2;
-                       break;  /* '\0' was seen by inet_pton4(). */
-               }
-               return 0;
-       }
-       if (saw_xdigit) {
-               if (tp + sizeof(int16_t) > endp)
-                       return 0;
-               *tp++ = (unsigned char) ((val >> 8) & 0xff);
-               *tp++ = (unsigned char) (val & 0xff);
-               dbloct_count++;
-       }
-       if (colonp != NULL) {
-               /* if we already have 8 double octets, having a colon
-                * means error */
-               if (dbloct_count == 8)
-                       return 0;
-
-               /*
-                * Since some memmove()'s erroneously fail to handle
-                * overlapping regions, we'll do the shift by hand.
-                */
-               const int n = tp - colonp;
-               int i;
-
-               for (i = 1; i <= n; i++) {
-                       endp[-i] = colonp[n - i];
-                       colonp[n - i] = 0;
-               }
-               tp = endp;
-       }
-       if (tp != endp)
-               return 0;
-       memcpy(dst, tmp, IN6ADDRSZ);
-       return 1;
-}
-
 int
 parse_ipv4_addr(const char *token, struct in_addr *ipv4, uint32_t *mask)
 {
@@ -213,8 +51,9 @@ parse_ipv4_addr(const char *token, struct in_addr *ipv4, uint32_t *mask)
 
        pch = strchr(token, '/');
        if (pch != NULL) {
-               strlcpy(ip_str, token, RTE_MIN((unsigned int long)(pch - token),
-                                       sizeof(ip_str)));
+               strlcpy(ip_str, token,
+                       RTE_MIN((unsigned int long)(pch - token + 1),
+                       sizeof(ip_str)));
                pch += 1;
                if (is_str_num(pch) != 0)
                        return -EINVAL;
@@ -225,11 +64,10 @@ parse_ipv4_addr(const char *token, struct in_addr *ipv4, uint32_t *mask)
                if (mask)
                        *mask = 0;
        }
-
        if (strlen(ip_str) >= INET_ADDRSTRLEN)
                return -EINVAL;
 
-       if (inet_pton4(ip_str, (unsigned char *)ipv4) != 1)
+       if (inet_pton(AF_INET, ip_str, ipv4) != 1)
                return -EINVAL;
 
        return 0;
@@ -243,7 +81,8 @@ parse_ipv6_addr(const char *token, struct in6_addr *ipv6, uint32_t *mask)
 
        pch = strchr(token, '/');
        if (pch != NULL) {
-               strlcpy(ip_str, token, RTE_MIN((unsigned int long)(pch - token),
+               strlcpy(ip_str, token,
+                       RTE_MIN((unsigned int long)(pch - token + 1),
                                        sizeof(ip_str)));
                pch += 1;
                if (is_str_num(pch) != 0)
@@ -259,7 +98,7 @@ parse_ipv6_addr(const char *token, struct in6_addr *ipv6, uint32_t *mask)
        if (strlen(ip_str) >= INET6_ADDRSTRLEN)
                return -EINVAL;
 
-       if (inet_pton6(ip_str, (unsigned char *)ipv6) != 1)
+       if (inet_pton(AF_INET6, ip_str, ipv6) != 1)
                return -EINVAL;
 
        return 0;
@@ -305,6 +144,46 @@ parse_range(const char *token, uint16_t *low, uint16_t *high)
        return 0;
 }
 
+/*
+ * helper function for parse_mac, parse one section of the ether addr.
+ */
+static const char *
+parse_uint8x16(const char *s, uint8_t *v, uint8_t ls)
+{
+       char *end;
+       unsigned long t;
+
+       errno = 0;
+       t = strtoul(s, &end, 16);
+       if (errno != 0 || end[0] != ls || t > UINT8_MAX)
+               return NULL;
+       v[0] = t;
+       return end + 1;
+}
+
+static int
+parse_mac(const char *str, struct rte_ether_addr *addr)
+{
+       uint32_t i;
+
+       static const uint8_t stop_sym[RTE_DIM(addr->addr_bytes)] = {
+               [0] = ':',
+               [1] = ':',
+               [2] = ':',
+               [3] = ':',
+               [4] = ':',
+               [5] = 0,
+       };
+
+       for (i = 0; i != RTE_DIM(addr->addr_bytes); i++) {
+               str = parse_uint8x16(str, addr->addr_bytes + i, stop_sym[i]);
+               if (str == NULL)
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
 /** sp add parse */
 struct cfg_sp_add_cfg_item {
        cmdline_fixed_string_t sp_keyword;
@@ -443,11 +322,105 @@ cmdline_parse_inst_t cfg_rt_add_rule = {
        },
 };
 
+/* flow add parse */
+struct cfg_flow_add_cfg_item {
+       cmdline_fixed_string_t flow_keyword;
+       cmdline_multi_string_t multi_string;
+};
+
+static void
+cfg_flow_add_cfg_item_parsed(void *parsed_result,
+       __rte_unused struct cmdline *cl, void *data)
+{
+       struct cfg_flow_add_cfg_item *params = parsed_result;
+       char *tokens[32];
+       uint32_t n_tokens = RTE_DIM(tokens);
+       struct parse_status *status = (struct parse_status *)data;
+
+       APP_CHECK(parse_tokenize_string(
+               params->multi_string, tokens, &n_tokens) == 0,
+               status, "too many arguments\n");
+       if (status->status < 0)
+               return;
+
+       parse_flow_tokens(tokens, n_tokens, status);
+}
+
+static cmdline_parse_token_string_t cfg_flow_add_flow_str =
+       TOKEN_STRING_INITIALIZER(struct cfg_flow_add_cfg_item,
+               flow_keyword, "flow");
+
+static cmdline_parse_token_string_t cfg_flow_add_multi_str =
+       TOKEN_STRING_INITIALIZER(struct cfg_flow_add_cfg_item, multi_string,
+               TOKEN_STRING_MULTI);
+
+cmdline_parse_inst_t cfg_flow_add_rule = {
+       .f = cfg_flow_add_cfg_item_parsed,
+       .data = NULL,
+       .help_str = "",
+       .tokens = {
+               (void *) &cfg_flow_add_flow_str,
+               (void *) &cfg_flow_add_multi_str,
+               NULL,
+       },
+};
+
+/* neigh add parse */
+struct cfg_neigh_add_item {
+       cmdline_fixed_string_t neigh;
+       cmdline_fixed_string_t pstr;
+       uint16_t port;
+       cmdline_fixed_string_t mac;
+};
+
+static void
+cfg_parse_neigh(void *parsed_result, __rte_unused struct cmdline *cl,
+       void *data)
+{
+       int32_t rc;
+       struct cfg_neigh_add_item *res;
+       struct parse_status *st;
+       struct rte_ether_addr mac;
+
+       st = data;
+       res = parsed_result;
+       rc = parse_mac(res->mac, &mac);
+       APP_CHECK(rc == 0, st, "invalid ether addr:%s", res->mac);
+       rc = add_dst_ethaddr(res->port, &mac);
+       APP_CHECK(rc == 0, st, "invalid port numer:%hu", res->port);
+       if (st->status < 0)
+               return;
+}
+
+cmdline_parse_token_string_t cfg_add_neigh_start =
+       TOKEN_STRING_INITIALIZER(struct cfg_neigh_add_item, neigh, "neigh");
+cmdline_parse_token_string_t cfg_add_neigh_pstr =
+       TOKEN_STRING_INITIALIZER(struct cfg_neigh_add_item, pstr, "port");
+cmdline_parse_token_num_t cfg_add_neigh_port =
+       TOKEN_NUM_INITIALIZER(struct cfg_neigh_add_item, port, RTE_UINT16);
+cmdline_parse_token_string_t cfg_add_neigh_mac =
+       TOKEN_STRING_INITIALIZER(struct cfg_neigh_add_item, mac, NULL);
+
+cmdline_parse_inst_t cfg_neigh_add_rule = {
+       .f = cfg_parse_neigh,
+       .data = NULL,
+       .help_str = "",
+       .tokens = {
+               (void *)&cfg_add_neigh_start,
+               (void *)&cfg_add_neigh_pstr,
+               (void *)&cfg_add_neigh_port,
+               (void *)&cfg_add_neigh_mac,
+               NULL,
+       },
+};
+
 /** set of cfg items */
 cmdline_parse_ctx_t ipsec_ctx[] = {
        (cmdline_parse_inst_t *)&cfg_sp_add_rule,
        (cmdline_parse_inst_t *)&cfg_sa_add_rule,
        (cmdline_parse_inst_t *)&cfg_rt_add_rule,
+       (cmdline_parse_inst_t *)&cfg_flow_add_rule,
+       (cmdline_parse_inst_t *)&cfg_neigh_add_rule,
        NULL,
 };
 
@@ -473,6 +446,8 @@ parse_cfg_file(const char *cfg_filename)
        cfg_sp_add_rule.data = &status;
        cfg_sa_add_rule.data = &status;
        cfg_rt_add_rule.data = &status;
+       cfg_flow_add_rule.data = &status;
+       cfg_neigh_add_rule.data = &status;
 
        do {
                char oneline[1024];
@@ -550,6 +525,10 @@ parse_cfg_file(const char *cfg_filename)
        cmdline_stdin_exit(cl);
        fclose(f);
 
+       sa_sort_arr();
+       sp4_sort_arr();
+       sp6_sort_arr();
+
        return 0;
 
 error_exit: