examples/ipsec-secgw: add default flow for inline Rx
[dpdk.git] / examples / ipsec-secgw / ipsec-secgw.c
index 3b5aaf6..e1ee7c3 100644 (file)
@@ -46,6 +46,7 @@
 
 #include "ipsec.h"
 #include "parser.h"
+#include "sad.h"
 
 #define RTE_LOGTYPE_IPSEC RTE_LOGTYPE_USER1
 
@@ -128,6 +129,8 @@ struct ethaddr_info ethaddr_tbl[RTE_MAX_ETHPORTS] = {
        { 0, ETHADDR(0x00, 0x16, 0x3e, 0x49, 0x9e, 0xdd) }
 };
 
+struct flow_info flow_info_tbl[RTE_MAX_ETHPORTS];
+
 #define CMD_LINE_OPT_CONFIG            "config"
 #define CMD_LINE_OPT_SINGLE_SA         "single-sa"
 #define CMD_LINE_OPT_CRYPTODEV_MASK    "cryptodev_mask"
@@ -192,7 +195,10 @@ static uint32_t mtu_size = RTE_ETHER_MTU;
 static uint64_t frag_ttl_ns = MAX_FRAG_TTL_NS;
 
 /* application wide librte_ipsec/SA parameters */
-struct app_sa_prm app_sa_prm = {.enable = 0};
+struct app_sa_prm app_sa_prm = {
+                       .enable = 0,
+                       .cache_sz = SA_CACHE_SZ
+               };
 static const char *cfgfile;
 
 struct lcore_rx_queue {
@@ -319,6 +325,7 @@ prepare_one_packet(struct rte_mbuf *pkt, struct ipsec_traffic *t)
                }
                pkt->l2_len = 0;
                pkt->l3_len = sizeof(*iph4);
+               pkt->packet_type |= RTE_PTYPE_L3_IPV4;
        } else if (eth->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)) {
                int next_proto;
                size_t l3len, ext_len;
@@ -353,6 +360,7 @@ prepare_one_packet(struct rte_mbuf *pkt, struct ipsec_traffic *t)
                }
                pkt->l2_len = 0;
                pkt->l3_len = l3len;
+               pkt->packet_type |= RTE_PTYPE_L3_IPV6;
        } else {
                /* Unknown/Unsupported type, drop the packet */
                RTE_LOG(ERR, IPSEC, "Unsupported packet type 0x%x\n",
@@ -601,7 +609,7 @@ inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
                        continue;
                }
 
-               sa_idx = SPI2IDX(res);
+               sa_idx = res - 1;
                if (!inbound_sa_check(sa, m, sa_idx)) {
                        rte_pktmbuf_free(m);
                        continue;
@@ -688,7 +696,7 @@ outbound_sp(struct sp_ctx *sp, struct traffic_type *ip,
        j = 0;
        for (i = 0; i < ip->num; i++) {
                m = ip->pkts[i];
-               sa_idx = SPI2IDX(ip->res[i]);
+               sa_idx = ip->res[i] - 1;
                if (ip->res[i] == DISCARD)
                        rte_pktmbuf_free(m);
                else if (ip->res[i] == BYPASS)
@@ -1102,7 +1110,7 @@ main_loop(__attribute__((unused)) void *dummy)
        uint16_t portid;
        uint8_t queueid;
        struct lcore_conf *qconf;
-       int32_t socket_id;
+       int32_t rc, socket_id;
        const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1)
                        / US_PER_S * BURST_TX_DRAIN_US;
        struct lcore_rx_queue *rxql;
@@ -1132,6 +1140,14 @@ main_loop(__attribute__((unused)) void *dummy)
        qconf->frag.pool_dir = socket_ctx[socket_id].mbuf_pool;
        qconf->frag.pool_indir = socket_ctx[socket_id].mbuf_pool_indir;
 
+       rc = ipsec_sad_lcore_cache_init(app_sa_prm.cache_sz);
+       if (rc != 0) {
+               RTE_LOG(ERR, IPSEC,
+                       "SAD cache init on lcore %u, failed with code: %d\n",
+                       lcore_id, rc);
+               return rc;
+       }
+
        if (qconf->nb_rx_queue == 0) {
                RTE_LOG(DEBUG, IPSEC, "lcore %u has nothing to do\n",
                        lcore_id);
@@ -1271,6 +1287,7 @@ print_usage(const char *prgname)
                " [-w REPLAY_WINDOW_SIZE]"
                " [-e]"
                " [-a]"
+               " [-c]"
                " -f CONFIG_FILE"
                " --config (port,queue,lcore)[,(port,queue,lcore)]"
                " [--single-sa SAIDX]"
@@ -1290,6 +1307,8 @@ print_usage(const char *prgname)
                "     size for each SA\n"
                "  -e enables ESN\n"
                "  -a enables SA SQN atomic behaviour\n"
+               "  -c specifies inbound SAD cache size,\n"
+               "     zero value disables the cache (default value: 128)\n"
                "  -f CONFIG_FILE: Configuration file\n"
                "  --config (port,queue,lcore): Rx queue configuration\n"
                "  --single-sa SAIDX: Use single SA index for outbound traffic,\n"
@@ -1442,7 +1461,7 @@ parse_args(int32_t argc, char **argv)
 
        argvopt = argv;
 
-       while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:",
+       while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:c:",
                                lgopts, &option_index)) != EOF) {
 
                switch (opt) {
@@ -1501,6 +1520,15 @@ parse_args(int32_t argc, char **argv)
                        app_sa_prm.enable = 1;
                        app_sa_prm.flags |= RTE_IPSEC_SAFLAG_SQN_ATOM;
                        break;
+               case 'c':
+                       ret = parse_decimal(optarg);
+                       if (ret < 0) {
+                               printf("Invalid SA cache size: %s\n", optarg);
+                               print_usage(prgname);
+                               return -1;
+                       }
+                       app_sa_prm.cache_sz = ret;
+                       break;
                case CMD_LINE_OPT_CONFIG_NUM:
                        ret = parse_config(optarg);
                        if (ret) {
@@ -2406,6 +2434,48 @@ reassemble_init(void)
        return rc;
 }
 
+static void
+create_default_ipsec_flow(uint16_t port_id, uint64_t rx_offloads)
+{
+       struct rte_flow_action action[2];
+       struct rte_flow_item pattern[2];
+       struct rte_flow_attr attr = {0};
+       struct rte_flow_error err;
+       struct rte_flow *flow;
+       int ret;
+
+       if (!(rx_offloads & DEV_RX_OFFLOAD_SECURITY))
+               return;
+
+       /* Add the default rte_flow to enable SECURITY for all ESP packets */
+
+       pattern[0].type = RTE_FLOW_ITEM_TYPE_ESP;
+       pattern[0].spec = NULL;
+       pattern[0].mask = NULL;
+       pattern[0].last = NULL;
+       pattern[1].type = RTE_FLOW_ITEM_TYPE_END;
+
+       action[0].type = RTE_FLOW_ACTION_TYPE_SECURITY;
+       action[0].conf = NULL;
+       action[1].type = RTE_FLOW_ACTION_TYPE_END;
+       action[1].conf = NULL;
+
+       attr.ingress = 1;
+
+       ret = rte_flow_validate(port_id, &attr, pattern, action, &err);
+       if (ret)
+               return;
+
+       flow = rte_flow_create(port_id, &attr, pattern, action, &err);
+       if (flow == NULL)
+               return;
+
+       flow_info_tbl[port_id].rx_def_flow = flow;
+       RTE_LOG(INFO, IPSEC,
+               "Created default flow enabling SECURITY for all ESP traffic on port %d\n",
+               port_id);
+}
+
 int32_t
 main(int32_t argc, char **argv)
 {
@@ -2414,7 +2484,8 @@ main(int32_t argc, char **argv)
        uint32_t i;
        uint8_t socket_id;
        uint16_t portid;
-       uint64_t req_rx_offloads, req_tx_offloads;
+       uint64_t req_rx_offloads[RTE_MAX_ETHPORTS];
+       uint64_t req_tx_offloads[RTE_MAX_ETHPORTS];
        size_t sess_sz;
 
        /* init EAL */
@@ -2476,8 +2547,10 @@ main(int32_t argc, char **argv)
                if ((enabled_port_mask & (1 << portid)) == 0)
                        continue;
 
-               sa_check_offloads(portid, &req_rx_offloads, &req_tx_offloads);
-               port_init(portid, req_rx_offloads, req_tx_offloads);
+               sa_check_offloads(portid, &req_rx_offloads[portid],
+                               &req_tx_offloads[portid]);
+               port_init(portid, req_rx_offloads[portid],
+                               req_tx_offloads[portid]);
        }
 
        cryptodevs_init();
@@ -2487,11 +2560,9 @@ main(int32_t argc, char **argv)
                if ((enabled_port_mask & (1 << portid)) == 0)
                        continue;
 
-               /*
-                * Start device
-                * note: device must be started before a flow rule
-                * can be installed.
-                */
+               /* Create flow before starting the device */
+               create_default_ipsec_flow(portid, req_rx_offloads[portid]);
+
                ret = rte_eth_dev_start(portid);
                if (ret < 0)
                        rte_exit(EXIT_FAILURE, "rte_eth_dev_start: "