and add to TESTS to make example run with 'make check'
Maxim. On 02/21/17 21:18, Bill Fischofer wrote: > Also, it looks like example/ipsec_offload/Makefile.am is incomplete. It's > missing the line: > > bin_PROGRAMS = odp_ipsec_offload$(EXEEXT) > > Without this nothing tries to compile. With this and the earlier m4 add > everything configures properly but then make dies due to Petri's ipsec > stubs not yet being integrated. I'll test again after they are against your > v2 of this patch. > > On Tue, Feb 21, 2017 at 11:42 AM, Bill Fischofer <bill.fischo...@linaro.org> > wrote: > >> You're missing an entry in example/m4/configure.m4 to process the >> Makefile.am to generate the makefile for this new example. As a result >> compile fails. >> >> On Tue, Feb 21, 2017 at 12:23 PM, Nikhil Agarwal < >> nikhil.agar...@linaro.org> wrote: >> >>> Signed-off-by: Nikhil Agarwal <nikhil.agar...@linaro.org> >>> --- >>> example/Makefile.am | 1 + >>> example/ipsec_offload/.gitignore | 1 + >>> example/ipsec_offload/Makefile.am | 18 + >>> example/ipsec_offload/odp_ipsec_offload.c | 871 >>> +++++++++++++++++++++++ >>> example/ipsec_offload/odp_ipsec_offload_cache.c | 148 ++++ >>> example/ipsec_offload/odp_ipsec_offload_cache.h | 78 ++ >>> example/ipsec_offload/odp_ipsec_offload_fwd_db.c | 223 ++++++ >>> example/ipsec_offload/odp_ipsec_offload_fwd_db.h | 198 ++++++ >>> example/ipsec_offload/odp_ipsec_offload_misc.h | 384 ++++++++++ >>> example/ipsec_offload/odp_ipsec_offload_sa_db.c | 361 ++++++++++ >>> example/ipsec_offload/odp_ipsec_offload_sa_db.h | 126 ++++ >>> example/ipsec_offload/odp_ipsec_offload_sp_db.c | 166 +++++ >>> example/ipsec_offload/odp_ipsec_offload_sp_db.h | 72 ++ >>> example/ipsec_offload/run_left | 14 + >>> example/ipsec_offload/run_right | 14 + >>> 15 files changed, 2675 insertions(+) >>> create mode 100644 example/ipsec_offload/.gitignore >>> create mode 100644 example/ipsec_offload/Makefile.am >>> create mode 100644 example/ipsec_offload/odp_ipsec_offload.c >>> create mode 100644 example/ipsec_offload/odp_ipsec_offload_cache.c >>> create mode 100644 example/ipsec_offload/odp_ipsec_offload_cache.h >>> create mode 100644 example/ipsec_offload/odp_ipsec_offload_fwd_db.c >>> create mode 100644 example/ipsec_offload/odp_ipsec_offload_fwd_db.h >>> create mode 100644 example/ipsec_offload/odp_ipsec_offload_misc.h >>> create mode 100644 example/ipsec_offload/odp_ipsec_offload_sa_db.c >>> create mode 100644 example/ipsec_offload/odp_ipsec_offload_sa_db.h >>> create mode 100644 example/ipsec_offload/odp_ipsec_offload_sp_db.c >>> create mode 100644 example/ipsec_offload/odp_ipsec_offload_sp_db.h >>> create mode 100644 example/ipsec_offload/run_left >>> create mode 100644 example/ipsec_offload/run_right >>> >>> diff --git a/example/Makefile.am b/example/Makefile.am >>> index dfc07b6..24b9e52 100644 >>> --- a/example/Makefile.am >>> +++ b/example/Makefile.am >>> @@ -2,6 +2,7 @@ SUBDIRS = classifier \ >>> generator \ >>> hello \ >>> ipsec \ >>> + ipsec_offload \ >>> l2fwd_simple \ >>> l3fwd \ >>> packet \ >>> diff --git a/example/ipsec_offload/.gitignore >>> b/example/ipsec_offload/.gitignore >>> new file mode 100644 >>> index 0000000..2fc73aa >>> --- /dev/null >>> +++ b/example/ipsec_offload/.gitignore >>> @@ -0,0 +1 @@ >>> +odp_ipsec_offload >>> diff --git a/example/ipsec_offload/Makefile.am >>> b/example/ipsec_offload/Makefile.am >>> new file mode 100644 >>> index 0000000..ec66030 >>> --- /dev/null >>> +++ b/example/ipsec_offload/Makefile.am >>> @@ -0,0 +1,18 @@ >>> +include $(top_srcdir)/example/Makefile.inc >>> + >>> +odp_ipsec_offload_LDFLAGS = $(AM_LDFLAGS) -static >>> +odp_ipsec_offload_CFLAGS = $(AM_CFLAGS) -I${top_srcdir}/example >>> + >>> +noinst_HEADERS = \ >>> + $(top_srcdir)/example/ipsec_o >>> ffload/odp_ipsec_offload_cache.h \ >>> + $(top_srcdir)/example/ipsec_o >>> ffload/odp_ipsec_offload_fwd_db.h \ >>> + $(top_srcdir)/example/ipsec_o >>> ffload/odp_ipsec_offload_misc.h \ >>> + $(top_srcdir)/example/ipsec_o >>> ffload/odp_ipsec_offload_sa_db.h \ >>> + $(top_srcdir)/example/ipsec_o >>> ffload/odp_ipsec_offload_sp_db.h \ >>> + $(top_srcdir)/example/example_debug.h >>> + >>> +dist_odp_ipsec_offload_SOURCES = odp_ipsec_offload.c \ >>> + odp_ipsec_offload_sa_db.c \ >>> + odp_ipsec_offload_sp_db.c \ >>> + odp_ipsec_offload_fwd_db.c \ >>> + odp_ipsec_offload_cache.c >>> diff --git a/example/ipsec_offload/odp_ipsec_offload.c >>> b/example/ipsec_offload/odp_ipsec_offload.c >>> new file mode 100644 >>> index 0000000..4a494d0 >>> --- /dev/null >>> +++ b/example/ipsec_offload/odp_ipsec_offload.c >>> @@ -0,0 +1,871 @@ >>> +/* Copyright (c) 2017, Linaro Limited >>> + * Copyright (C) 2017 NXP >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> +/** >>> + * @file >>> + * >>> + * @example odp_ipsec_offload.c ODP basic packet IO cross connect with >>> IPsec >>> + * test application >>> + */ >>> + >>> +#define _DEFAULT_SOURCE >>> +/* enable strtok */ >>> +#define _POSIX_C_SOURCE 200112L >>> +#include <stdlib.h> >>> +#include <getopt.h> >>> +#include <unistd.h> >>> + >>> +#include <example_debug.h> >>> + >>> +#include <odp_api.h> >>> +#include <odp/helper/linux.h> >>> +#include <odp/helper/eth.h> >>> +#include <odp/helper/ip.h> >>> +#include <odp/helper/icmp.h> >>> +#include <odp/helper/udp.h> >>> +#include <odp/helper/ipsec.h> >>> + >>> +#include <stdbool.h> >>> +#include <sys/socket.h> >>> +#include <net/if.h> >>> +#include <sys/ioctl.h> >>> +#include <sys/socket.h> >>> +#include <netpacket/packet.h> >>> +#include <net/ethernet.h> >>> +#include <arpa/inet.h> >>> + >>> +#include <odp_ipsec_offload_misc.h> >>> +#include <odp_ipsec_offload_sa_db.h> >>> +#include <odp_ipsec_offload_sp_db.h> >>> +#include <odp_ipsec_offload_fwd_db.h> >>> +#include <odp_ipsec_offload_cache.h> >>> + >>> +#define MAX_WORKERS 32 /**< maximum number of worker threads */ >>> + >>> +/** >>> + * Parsed command line application arguments >>> + */ >>> +typedef struct { >>> + int cpu_count; >>> + int flows; >>> + int if_count; /**< Number of interfaces to be used */ >>> + char **if_names; /**< Array of pointers to interface names >>> */ >>> + char *if_str; /**< Storage for interface names */ >>> + int queue_type; /**< Queue synchronization type*/ >>> +} appl_args_t; >>> +/** >>> + * Grouping of both parsed CL args and thread specific args - alloc >>> together >>> + */ >>> +typedef struct { >>> + /** Application (parsed) arguments */ >>> + appl_args_t appl; >>> +} args_t; >>> + >>> +/* helper funcs */ >>> +static void parse_args(int argc, char *argv[], appl_args_t *appl_args); >>> +static void print_info(char *progname, appl_args_t *appl_args); >>> +static void usage(char *progname); >>> + >>> +/** Global pointer to args */ >>> +static args_t *args; >>> + >>> +/** >>> + * Buffer pool for packet IO >>> + */ >>> +#define SHM_PKT_POOL_BUF_COUNT 1024 >>> +#define SHM_PKT_POOL_BUF_SIZE 4096 >>> +#define SHM_PKT_POOL_SIZE (SHM_PKT_POOL_BUF_COUNT * >>> SHM_PKT_POOL_BUF_SIZE) >>> + >>> +static odp_pool_t pkt_pool = ODP_POOL_INVALID; >>> + >>> +/** Synchronize threads before packet processing begins */ >>> +static odp_barrier_t sync_barrier; >>> + >>> +/** >>> + * Packet processing result codes >>> + */ >>> +typedef enum { >>> + PKT_CONTINUE, /**< No events posted, keep processing */ >>> + PKT_POSTED, /**< Event posted, stop processing */ >>> + PKT_DROP, /**< Reason to drop detected, stop processing */ >>> + PKT_DONE /**< Finished with packet, stop processing */ >>> +} pkt_disposition_e; >>> + >>> +#define MAX_COMPL_QUEUES 32 >>> +#define GET_THR_QUEUE_ID(x) ((odp_thread_id()-1) % (x)) >>> + >>> +/** Atomic queue IPSEC completion events */ >>> +static odp_queue_t completionq[MAX_COMPL_QUEUES]; >>> + >>> +static int num_compl_queues; >>> +static int num_workers; >>> + >>> + >>> +/** >>> + * Calculate hash value on given 2-tuple i.e. sip, dip >>> + * >>> + * @param ip_src Source IP Address >>> + * @param ip_dst Destination IP Address >>> + * >>> + * @return Resultant hash value >>> + */ >>> +static inline uint64_t calculate_flow_hash(uint32_t ip_src, uint32_t >>> ip_dst) >>> +{ >>> + uint64_t hash = 0; >>> + >>> + ip_dst += JHASH_GOLDEN_RATIO; >>> + ODP_BJ3_MIX(ip_src, ip_dst, hash); >>> + return hash; >>> +} >>> + >>> +/** >>> + * IPsec pre argument processing intialization >>> + */ >>> +static >>> +void ipsec_init_pre(void) >>> +{ >>> + /* Initialize our data bases */ >>> + init_sp_db(); >>> + init_sa_db(); >>> + init_tun_db(); >>> + init_ipsec_cache(); >>> +} >>> + >>> +/** >>> + * IPsec post argument processing intialization >>> + * >>> + * Resolve SP DB with SA DB and create corresponding IPsec cache entries >>> + */ >>> +static >>> +void ipsec_init_post(void) >>> +{ >>> + sp_db_entry_t *entry; >>> + int queue_id = 0; >>> + >>> + /* Attempt to find appropriate SA for each SP */ >>> + for (entry = sp_db->list; NULL != entry; entry = entry->next) { >>> + sa_db_entry_t *cipher_sa = NULL; >>> + sa_db_entry_t *auth_sa = NULL; >>> + tun_db_entry_t *tun = NULL; >>> + queue_id %= num_workers; >>> + if (num_compl_queues < num_workers) >>> + num_compl_queues++; >>> + queue_id++; >>> + if (entry->esp) { >>> + cipher_sa = find_sa_db_entry(&entry->src_subnet, >>> + &entry->dst_subnet, 1); >>> + tun = find_tun_db_entry(cipher_sa->src_ip, >>> + cipher_sa->dst_ip); >>> + } >>> + if (entry->ah) { >>> + auth_sa = find_sa_db_entry(&entry->src_subnet, >>> + &entry->dst_subnet, 0); >>> + tun = find_tun_db_entry(auth_sa->src_ip, >>> + auth_sa->dst_ip); >>> + } >>> + >>> + if (cipher_sa && auth_sa) { >>> + if (create_ipsec_cache_entry(cipher_sa, >>> + auth_sa, >>> + tun, >>> + entry->input, >>> + completionq[queue_id >>> - 1])) { >>> + EXAMPLE_ABORT("Error: IPSec cache entry >>> failed.\n"); >>> + } >>> + } else { >>> + printf(" WARNING: SA not found for SP\n"); >>> + dump_sp_db_entry(entry); >>> + } >>> + } >>> +} >>> + >>> +/** >>> + * Initialize interface >>> + * >>> + * Initialize ODP pktio and queues, query MAC address and update >>> + * forwarding database. >>> + * >>> + * @param intf Interface name string >>> + * @param queue_type Type of queue to configure. >>> + */ >>> +static void initialize_intf(char *intf, int queue_type) >>> +{ >>> + odp_pktio_t pktio; >>> + odp_pktout_queue_t pktout; >>> + int ret; >>> + uint8_t src_mac[ODPH_ETHADDR_LEN]; >>> + odp_pktio_param_t pktio_param; >>> + odp_pktio_capability_t capa; >>> + odp_pktin_queue_param_t pktin_param; >>> + >>> + odp_pktio_param_init(&pktio_param); >>> + >>> + pktio_param.in_mode = ODP_PKTIN_MODE_SCHED; >>> + >>> + /* >>> + * Open a packet IO instance for thread and get default output >>> queue >>> + */ >>> + pktio = odp_pktio_open(intf, pkt_pool, &pktio_param); >>> + if (ODP_PKTIO_INVALID == pktio) { >>> + EXAMPLE_ABORT("Error: pktio create failed for %s\n", >>> intf); >>> + } >>> + >>> + odp_pktin_queue_param_init(&pktin_param); >>> + >>> + ret = odp_pktio_capability(pktio, &capa); >>> + if (ret != 0) >>> + EXAMPLE_ABORT("Error: Unable to get pktio capability >>> %s\n", intf); >>> + >>> + pktin_param.queue_param.type = ODP_QUEUE_TYPE_SCHED; >>> + pktin_param.queue_param.sched.sync = queue_type; >>> + pktin_param.queue_param.sched.prio = ODP_SCHED_PRIO_DEFAULT; >>> + pktin_param.num_queues = capa.max_input_queues; >>> + >>> + if (pktin_param.num_queues > 1) >>> + pktin_param.hash_enable = 1; >>> + >>> + if (odp_pktin_queue_config(pktio, &pktin_param)) >>> + EXAMPLE_ABORT("Error: pktin config failed for %s\n", >>> intf); >>> + >>> + if (odp_pktout_queue_config(pktio, NULL)) >>> + EXAMPLE_ABORT("Error: pktout config failed for %s\n", >>> intf); >>> + >>> + if (odp_pktout_queue(pktio, &pktout, 1) != 1) >>> + EXAMPLE_ABORT("Error: failed to get pktout queue for >>> %s\n", intf); >>> + >>> + ret = odp_pktio_start(pktio); >>> + if (ret) { >>> + EXAMPLE_ABORT("Error: unable to start %s\n", intf); >>> + } >>> + >>> + /* Read the source MAC address for this interface */ >>> + ret = odp_pktio_mac_addr(pktio, src_mac, sizeof(src_mac)); >>> + if (ret < 0) { >>> + EXAMPLE_ABORT("Error: failed during MAC address get for >>> %s\n", >>> + intf); >>> + } >>> + >>> + printf("Created pktio:%02" PRIu64 "\n", odp_pktio_to_u64(pktio)); >>> + >>> + /* Resolve any routes using this interface for output */ >>> + resolve_fwd_db(intf, pktout, src_mac); >>> +} >>> + >>> +/** >>> + * Packet Processing - Input verification >>> + * >>> + * @param pkt Packet to inspect >>> + * >>> + * @return PKT_CONTINUE if good, supported packet else PKT_DROP >>> + */ >>> +static pkt_disposition_e do_input_verify(odp_packet_t pkt) >>> +{ >>> + if (odp_unlikely(odp_packet_has_error(pkt))) { >>> + odp_packet_free(pkt); >>> + return PKT_DROP; >>> + } >>> + >>> + if (!odp_packet_has_eth(pkt)) { >>> + odp_packet_free(pkt); >>> + return PKT_DROP; >>> + } >>> + >>> + if (!odp_packet_has_ipv4(pkt)) { >>> + odp_packet_free(pkt); >>> + return PKT_DROP; >>> + } >>> + >>> + return PKT_CONTINUE; >>> +} >>> + >>> +/** >>> + * Packet Processing - Route lookup in forwarding database >>> + * >>> + * @param pkt Packet to route >>> + * >>> + * @return PKT_CONTINUE if route found else PKT_DROP >>> + */ >>> +static >>> +pkt_disposition_e do_route_fwd_db(odp_packet_t pkt) >>> +{ >>> + odph_ipv4hdr_t *ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, >>> NULL); >>> + fwd_db_entry_t *fwd_entry; >>> + ipsec_cache_entry_t *ipsec_entry; >>> + odp_ipsec_op_param_t params; >>> + uint32_t sip, dip; >>> + uint64_t hash; >>> + odp_flow_entry_t *flow = NULL; >>> + >>> + if (ip->ttl > 1) { >>> + ip->ttl -= 1; >>> + if (ip->chksum >= odp_cpu_to_be_16(0xffff - 0x100)) >>> + ip->chksum += odp_cpu_to_be_16(0x100) + 1; >>> + else >>> + ip->chksum += odp_cpu_to_be_16(0x100); >>> + } else { >>> + odp_packet_free(pkt); >>> + return PKT_DROP; >>> + } >>> + >>> + sip = odp_be_to_cpu_32(ip->src_addr); >>> + dip = odp_be_to_cpu_32(ip->dst_addr); >>> + >>> + hash = calculate_flow_hash(sip, dip); >>> + >>> + flow = odp_route_flow_lookup_in_bucket(sip, dip, >>> + &flow_table[hash & >>> (bucket_count - 1)]); >>> + if (flow) { >>> +do_opt: >>> + odp_packet_user_ptr_set(pkt, &flow->out_port); >>> + if (flow->out_port.sa == ODP_IPSEC_SA_INVALID) >>> + return PKT_CONTINUE; >>> + >>> + /* Initialize parameters block */ >>> + params.sa = &flow->out_port.sa; >>> + params.pkt = &pkt; >>> + params.opt = NULL; >>> + params.num_pkt = 1; >>> + params.num_sa = 1; >>> + params.num_opt = 1; >>> + >>> + /* Issue ipsec request */ >>> + if (odp_unlikely(odp_ipsec_out_enq(¶ms) < 0)) { >>> + EXAMPLE_DBG("Unable to out enqueue\n"); >>> + odp_packet_free(pkt); >>> + return PKT_DROP; >>> + } >>> + return PKT_POSTED; >>> + } else { >>> + /*Check into Routing table*/ >>> + fwd_entry = find_fwd_db_entry(dip); >>> + if (fwd_entry) { >>> + /*Entry found. Updated in Flow table first.*/ >>> + flow = calloc(1, sizeof(odp_flow_entry_t)); >>> + if (!flow) { >>> + EXAMPLE_ABORT("Failure to allocate >>> memory"); >>> + } >>> + flow->l3_src = sip; >>> + flow->l3_dst = dip; >>> + flow->out_port.pktout = fwd_entry->pktout; >>> + memcpy(flow->out_port.addr.addr, >>> fwd_entry->src_mac, ODPH_ETHADDR_LEN); >>> + memcpy(flow->out_port.next_hop_addr.addr, >>> fwd_entry->dst_mac, ODPH_ETHADDR_LEN); >>> + ipsec_entry = find_ipsec_cache_entry_out(sip, >>> dip); >>> + if (ipsec_entry) >>> + flow->out_port.sa = ipsec_entry->sa; >>> + else >>> + flow->out_port.sa = ODP_IPSEC_SA_INVALID; >>> + flow->next = NULL; >>> + /*Insert new flow into flow cache table*/ >>> + odp_route_flow_insert_in_bucket(flow, >>> &flow_table[hash & (bucket_count - 1)]); >>> + goto do_opt; >>> + } else { >>> + EXAMPLE_DBG("No flow match found. Packet is >>> dropped.\n"); >>> + odp_packet_free(pkt); >>> + return PKT_DROP; >>> + >>> + } >>> + } >>> +} >>> + >>> + >>> +/** >>> + * Packet Processing - Input IPsec packet classification >>> + * >>> + * Verify the received packet has IPsec headers, >>> + * if so issue ipsec request else skip. >>> + * >>> + * @param pkt Packet to classify >>> + * >>> + * @return PKT_CONTINUE if done else PKT_POSTED >>> + */ >>> +static >>> +pkt_disposition_e do_ipsec_in_classify(odp_packet_t pkt) >>> +{ >>> + odp_ipsec_op_param_t params; >>> + >>> + if (!odp_packet_has_ipsec(pkt)) >>> + return PKT_CONTINUE; >>> + >>> + /* Initialize parameters block */ >>> + params.pkt = &pkt; >>> + params.num_pkt = 1; >>> + params.num_sa = 0; >>> + params.num_opt = 0; >>> + params.opt = NULL; >>> + >>> + /* Issue ipsec request */ >>> + if (odp_unlikely(odp_ipsec_in_enq(¶ms) < 0)) { >>> + EXAMPLE_DBG("Unable to in enqueue\n"); >>> + odp_packet_free(pkt); >>> + return PKT_DROP; >>> + } >>> + return PKT_POSTED; >>> +} >>> +/** >>> + * Packet IO worker thread >>> + * >>> + * Loop calling odp_schedule to obtain packet from the two sources, >>> + * and continue processing the packet. >>> + * >>> + * - Input interfaces (i.e. new work) >>> + * - Per packet ipsec API completion queue >>> + * >>> + * @param arg Required by "odph_linux_pthread_create", unused >>> + * >>> + * @return NULL (should never return) >>> + */ >>> +static >>> +void *pktio_thread(void *arg EXAMPLE_UNUSED) >>> +{ >>> + int thr; >>> + odp_packet_t pkt; >>> + odp_pktout_queue_t out_queue; >>> + odp_out_entry_t *out_port; >>> + odp_event_t ev = ODP_EVENT_INVALID; >>> + thr = odp_thread_id(); >>> + >>> + printf("Pktio thread [%02i] starts\n", thr); >>> + odp_barrier_wait(&sync_barrier); >>> + >>> + /* Loop packets */ >>> + for (;;) { >>> + pkt_disposition_e rc; >>> + >>> + ev = odp_schedule(NULL, ODP_SCHED_WAIT); >>> + /* Use schedule to get event from any input queue */ >>> + /* Determine new work versus completion */ >>> + if (ODP_EVENT_PACKET == odp_event_type(ev)) { >>> + pkt = odp_packet_from_event(ev); >>> + >>> + rc = do_input_verify(pkt); >>> + if (odp_unlikely(rc)) >>> + continue; >>> + >>> + rc = do_ipsec_in_classify(pkt); >>> + if (rc) >>> + continue; >>> + >>> + rc = do_route_fwd_db(pkt); >>> + if (rc) >>> + continue; >>> + >>> + out_port = (odp_out_entry_t >>> *)odp_packet_user_ptr(pkt); >>> + out_queue = (odp_pktout_queue_t)out_port->pktout; >>> + >>> + if (odp_unlikely(odp_pktout_send(out_queue, >>> &pkt, 1) < 0)) >>> + odp_packet_free(pkt); >>> + >>> + } else if (ODP_EVENT_IPSEC_RESULT == odp_event_type(ev)) { >>> + odp_ipsec_op_result_t result; >>> + odp_ipsec_packet_result_t res; >>> + odph_ethhdr_t *eth; >>> + odp_packet_t out_pkt; >>> + >>> + result.pkt = &out_pkt; >>> + result.res = &res; >>> + >>> + if (odp_unlikely(odp_ipsec_result(&result, ev) < >>> 0)) { >>> + EXAMPLE_DBG("Error Event\n"); >>> + odp_packet_free((odp_packet_t)ev); >>> + continue; >>> + } >>> + >>> + if (odp_unlikely(res.status.all)) { >>> + odp_packet_free((odp_packet_t)ev); >>> + continue; >>> + } >>> + >>> + odph_ipv4hdr_t *ip = (odph_ipv4hdr_t >>> *)odp_packet_l3_ptr(out_pkt, NULL); >>> + >>> + if (ip->proto != IPPROTO_ESP) { >>> + rc = do_route_fwd_db(out_pkt); >>> + if (odp_unlikely(rc)) >>> + continue; >>> + } >>> + >>> + out_port = (odp_out_entry_t >>> *)odp_packet_user_ptr(out_pkt); >>> + out_queue = (odp_pktout_queue_t)out_port->pktout; >>> + >>> + eth = (odph_ethhdr_t *)((void *)ip - >>> sizeof(odph_ethhdr_t)); >>> + eth->dst = out_port->next_hop_addr; >>> + eth->src = out_port->addr; >>> + eth->type = odp_cpu_to_be_16(0x800); >>> + >>> + if (odp_unlikely(odp_pktout_send(out_queue, >>> &out_pkt, 1) < 0)) >>> + odp_packet_free(out_pkt); >>> + } else { >>> + EXAMPLE_DBG("Invalid Event\n"); >>> + odp_packet_free((odp_packet_t)ev); >>> + continue; >>> + } >>> + } >>> + >>> + /* unreachable */ >>> + return NULL; >>> +} >>> + >>> +/** >>> + * ODP ipsec proto example main function >>> + */ >>> +int >>> +main(int argc, char *argv[]) >>> +{ >>> + odph_linux_pthread_t thread_tbl[MAX_WORKERS]; >>> + int i; >>> + odp_shm_t shm; >>> + odp_cpumask_t cpumask; >>> + char cpumaskstr[ODP_CPUMASK_STR_SIZE]; >>> + odp_pool_param_t params; >>> + odp_queue_param_t qparam; >>> + odp_instance_t instance; >>> + odph_linux_thr_params_t thr_params; >>> + odp_ipsec_config_t config; >>> + odp_ipsec_capability_t capa; >>> + >>> + /*Validate if user has passed only help option*/ >>> + if (argc == 2) { >>> + if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) >>> { >>> + usage(argv[0]); >>> + exit(EXIT_SUCCESS); >>> + } >>> + } >>> + >>> + /* Initialize ODP before calling anything else */ >>> + if (odp_init_global(&instance, NULL, NULL)) { >>> + EXAMPLE_ABORT("Error: ODP global init failed.\n"); >>> + } >>> + /* Initialize this thread */ >>> + if (odp_init_local(instance, ODP_THREAD_CONTROL)) { >>> + EXAMPLE_ABORT("Error: ODP local init failed.\n"); >>> + } >>> + /* Reserve memory for arguments from shared memory */ >>> + shm = odp_shm_reserve("shm_args", sizeof(args_t), >>> + ODP_CACHE_LINE_SIZE, 0); >>> + args = odp_shm_addr(shm); >>> + >>> + if (NULL == args) { >>> + EXAMPLE_ABORT("Error: shared mem alloc failed.\n"); >>> + } >>> + memset(args, 0, sizeof(*args)); >>> + >>> + /* Must init our databases before parsing args */ >>> + ipsec_init_pre(); >>> + init_fwd_db(); >>> + >>> + /* Parse and store the application arguments */ >>> + parse_args(argc, argv, &args->appl); >>> + >>> + /*Initialize route table for user given parameter*/ >>> + odp_init_routing_table(); >>> + >>> + /* Print both system and application information */ >>> + print_info(NO_PATH(argv[0]), &args->appl); >>> + >>> + if (odp_ipsec_capability(&capa)) >>> + EXAMPLE_ABORT("Error: Capability not configured.\n"); >>> + >>> + odp_ipsec_config_init(&config); >>> + >>> + if (capa.op_mode_async && (capa.op_mode_async >= >>> capa.op_mode_sync)) >>> + config.op_mode = ODP_IPSEC_OP_MODE_ASYNC; >>> + else >>> + EXAMPLE_ABORT("Error: Sync mode not supported.\n"); >>> + >>> + if (odp_ipsec_config(&config)) >>> + EXAMPLE_ABORT("Error: IPSec not configured.\n"); >>> + >>> + /* Default to system CPU count unless user specified */ >>> + num_workers = MAX_WORKERS; >>> + if (args->appl.cpu_count && args->appl.cpu_count <= MAX_WORKERS) >>> + num_workers = args->appl.cpu_count; >>> + >>> + /* >>> + * By default CPU #0 runs Linux kernel background tasks. >>> + * Start mapping thread from CPU #1 >>> + */ >>> + num_workers = odp_cpumask_default_worker(&cpumask, num_workers); >>> + (void)odp_cpumask_to_str(&cpumask, cpumaskstr, >>> sizeof(cpumaskstr)); >>> + >>> + /* >>> + * Create completion queues >>> + */ >>> + odp_queue_param_init(&qparam); >>> + qparam.type = ODP_QUEUE_TYPE_SCHED; >>> + qparam.sched.prio = ODP_SCHED_PRIO_HIGHEST; >>> + qparam.sched.sync = args->appl.queue_type; >>> + qparam.sched.group = ODP_SCHED_GROUP_ALL; >>> + >>> + for (i = 0; i < num_workers; i++) { >>> + completionq[i] = odp_queue_create("completion", &qparam); >>> + if (ODP_QUEUE_INVALID == completionq[i]) { >>> + EXAMPLE_ABORT("Error: completion queue creation >>> failed\n"); >>> + } >>> + } >>> + printf("num worker threads: %i\n", num_workers); >>> + printf("first CPU: %i\n", odp_cpumask_first(&cpumask)); >>> + printf("cpu mask: %s\n", cpumaskstr); >>> + >>> + /* Create a barrier to synchronize thread startup */ >>> + odp_barrier_init(&sync_barrier, num_workers); >>> + >>> + /* Create packet buffer pool */ >>> + odp_pool_param_init(¶ms); >>> + params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE; >>> + params.pkt.len = SHM_PKT_POOL_BUF_SIZE; >>> + params.pkt.num = SHM_PKT_POOL_BUF_COUNT; >>> + params.type = ODP_POOL_PACKET; >>> + >>> + pkt_pool = odp_pool_create("packet_pool", ¶ms); >>> + >>> + if (ODP_POOL_INVALID == pkt_pool) { >>> + EXAMPLE_ABORT("Error: packet pool create failed.\n"); >>> + } >>> + >>> + ipsec_init_post(); >>> + >>> + /* Initialize interfaces (which resolves FWD DB entries */ >>> + for (i = 0; i < args->appl.if_count; i++) { >>> + initialize_intf(args->appl.if_names[i], >>> args->appl.queue_type); >>> + } >>> + >>> + printf(" Configured queues SYNC type: [%s]\n", >>> (args->appl.queue_type == 0)? >>> + >>> "PARALLEL":(args->appl.queue_type == 1)? >>> + >>> "ATOMIC":"ORDERED"); >>> + memset(&thr_params, 0, sizeof(thr_params)); >>> + thr_params.start = pktio_thread; >>> + thr_params.arg = NULL; >>> + thr_params.thr_type = ODP_THREAD_WORKER; >>> + thr_params.instance = instance; >>> + >>> + /* Create and initialize worker threads */ >>> + odph_linux_pthread_create(thread_tbl, &cpumask, >>> + &thr_params); >>> + odph_linux_pthread_join(thread_tbl, num_workers); >>> + >>> + free(args->appl.if_names); >>> + free(args->appl.if_str); >>> + printf("Exit\n\n"); >>> + return 0; >>> +} >>> + >>> +/** >>> + * Parse and store the command line arguments >>> + * >>> + * @param argc argument count >>> + * @param argv[] argument vector >>> + * @param appl_args Store application arguments here >>> + */ >>> +static void parse_args(int argc, char *argv[], appl_args_t *appl_args) >>> +{ >>> + int opt; >>> + int long_index; >>> + char *token; >>> + size_t len; >>> + int rc = 0; >>> + int i; >>> + >>> + static struct option longopts[] = { >>> + {"count", required_argument, NULL, 'c'}, >>> + {"interface", required_argument, NULL, 'i'}, /* return >>> 'i' */ >>> + {"route", required_argument, NULL, 'r'}, /* return >>> 'r' */ >>> + {"policy", required_argument, NULL, 'p'}, /* return >>> 'p' */ >>> + {"ah", required_argument, NULL, 'a'}, /* return >>> 'a' */ >>> + {"esp", required_argument, NULL, 'e'}, /* return >>> 'e' */ >>> + {"tunnel", required_argument, NULL, 't'}, /* return >>> 't' */ >>> + {"flows", no_argument, NULL, 'f'}, /* return >>> 'f' */ >>> + {"queue type", required_argument, NULL, 'q'}, /* return >>> 'q' */ >>> + {"help", no_argument, NULL, 'h'}, /* return >>> 'h' */ >>> + {NULL, 0, NULL, 0} >>> + }; >>> + >>> + appl_args->flows = 1; >>> + appl_args->queue_type = ODP_SCHED_SYNC_ATOMIC; >>> + >>> + while (!rc) { >>> + opt = getopt_long(argc, argv, "+c:i:h:r:p:a:e:t:s:q:f:", >>> + longopts, &long_index); >>> + if (opt < 0) >>> + break; /* No more options */ >>> + switch (opt) { >>> + case 'f': >>> + appl_args->flows = atoi(optarg); >>> + if (appl_args->flows > 256) { >>> + printf("Maximum acceptable value for -f >>> is 256\n"); >>> + rc = -1; >>> + } >>> + if (optind != 3) { >>> + printf("-f must be the 1st argument of >>> the command\n"); >>> + rc = -1; >>> + } >>> + EXAMPLE_DBG("Bucket count = %d\n", bucket_count); >>> + break; >>> + case 'c': >>> + appl_args->cpu_count = atoi(optarg); >>> + break; >>> + case 'i': >>> + /* parse packet-io interface names */ >>> + len = strlen(optarg); >>> + if (0 == len) { >>> + usage(argv[0]); >>> + exit(EXIT_FAILURE); >>> + } >>> + len += 1; /* add room for '\0' */ >>> + >>> + appl_args->if_str = malloc(len); >>> + if (appl_args->if_str == NULL) { >>> + usage(argv[0]); >>> + exit(EXIT_FAILURE); >>> + } >>> + >>> + /* count the number of tokens separated by ',' */ >>> + strcpy(appl_args->if_str, optarg); >>> + for (token = strtok(appl_args->if_str, ","), i = >>> 0; >>> + token; token = strtok(NULL, ","), i++); >>> + appl_args->if_count = i; >>> + if (!appl_args->if_count) { >>> + usage(argv[0]); >>> + exit(EXIT_FAILURE); >>> + } >>> + /* Allocate storage for the if names */ >>> + appl_args->if_names = >>> + calloc(appl_args->if_count, sizeof(char >>> *)); >>> + if (!appl_args->if_names) { >>> + EXAMPLE_ABORT("Memory allocation >>> failure\n"); >>> + } >>> + /* Store the if names (reset names string) */ >>> + strcpy(appl_args->if_str, optarg); >>> + for (token = strtok(appl_args->if_str, ","), i = >>> 0; >>> + token; token = strtok(NULL, ","), i++) { >>> + appl_args->if_names[i] = token; >>> + } >>> + break; >>> + case 'r': >>> + rc = create_fwd_db_entry(optarg, >>> appl_args->if_names, >>> + appl_args->if_count, >>> appl_args->flows); >>> + break; >>> + case 'p': >>> + rc = create_sp_db_entry(optarg, appl_args->flows); >>> + break; >>> + case 'a': >>> + rc = create_sa_db_entry(optarg, FALSE, >>> appl_args->flows); >>> + break; >>> + case 'e': >>> + rc = create_sa_db_entry(optarg, TRUE, >>> appl_args->flows); >>> + break; >>> + case 't': >>> + rc = create_tun_db_entry(optarg, >>> appl_args->flows); >>> + break; >>> + case 'q': >>> + i = atoi(optarg); >>> + if (i > ODP_SCHED_SYNC_ORDERED || i < >>> ODP_SCHED_SYNC_PARALLEL) { >>> + printf("Invalid queue type: setting >>> default to atomic"); >>> + break; >>> + } >>> + appl_args->queue_type = i; >>> + break; >>> + case 'h': >>> + usage(argv[0]); >>> + exit(EXIT_SUCCESS); >>> + break; >>> + default: >>> + break; >>> + } >>> + } >>> + >>> + if (rc) { >>> + printf("ERROR: failed parsing -%c option\n", opt); >>> + usage(argv[0]); >>> + exit(EXIT_FAILURE); >>> + } >>> + >>> + if (0 == appl_args->if_count) { >>> + usage(argv[0]); >>> + exit(EXIT_FAILURE); >>> + } >>> + >>> + optind = 1; /* reset 'extern optind' from the getopt >>> lib */ >>> +} >>> + >>> +/** >>> + * Print system and application info >>> + */ >>> +static void print_info(char *progname, appl_args_t *appl_args) >>> +{ >>> + int i; >>> + >>> + printf("\n" >>> + "ODP system info\n" >>> + "---------------\n" >>> + "ODP API version: %s\n" >>> + "CPU model: %s\n" >>> + "CPU freq (hz): %"PRIu64"\n" >>> + "Cache line size: %i\n" >>> + "CPU count: %i\n" >>> + "\n", >>> + odp_version_api_str(), odp_cpu_model_str(), >>> odp_cpu_hz_max(), >>> + odp_sys_cache_line_size(), odp_cpu_count()); >>> + printf("Running ODP application: \"%s\"\n" >>> + "------------------------\n" >>> + "IF-count: %i\n" >>> + "Using IFs: ", >>> + progname, appl_args->if_count); >>> + for (i = 0; i < appl_args->if_count; ++i) >>> + printf(" %s", appl_args->if_names[i]); >>> + printf("\n"); >>> + dump_fwd_db(); >>> + dump_sp_db(); >>> + dump_sa_db(); >>> + dump_tun_db(); >>> + printf("\n\n"); >>> + fflush(NULL); >>> +} >>> + >>> +/** >>> + * Prinf usage information >>> + */ >>> +static void usage(char *progname) >>> +{ >>> + printf("\n" >>> + "Usage: %s OPTIONS\n" >>> + " E.g. %s -i eth1,eth2,eth3 -m 0\n" >>> + "\n" >>> + "OpenDataPlane example application.\n" >>> + "\n" >>> + "Mandatory OPTIONS:\n" >>> + " -i, --interface Eth interfaces (comma-separated, no >>> spaces)\n" >>> + "Routing / IPSec OPTIONS:\n" >>> + " -r, --route SubNet:Intf:NextHopMAC\n" >>> + " -p, --policy SrcSubNet:DstSubNet:(in|out):( >>> ah|esp|both)\n" >>> + " -e, --esp SrcIP:DstIP:(3des|null):SPI:Key192\n" >>> + " -a, --ah SrcIP:DstIP:(md5|null):SPI:Key128\n" >>> + " -t, --tun SrcIP:DstIP:TunSrcIP:TunDstIP\n" >>> + "\n" >>> + " Where: NextHopMAC is raw hex/dot notation, i.e. >>> 03.BA.44.9A.CE.02\n" >>> + " IP is decimal/dot notation, i.e. 192.168.1.1\n" >>> + " SubNet is decimal/dot/slash notation, i.e >>> 192.168.0.0/16\n <http://192.168.0.0/16%5Cn>" >>> + " SPI is raw hex, 32 bits\n" >>> + " KeyXXX is raw hex, XXX bits long\n" >>> + "\n" >>> + " Examples:\n" >>> + " -r 192.168.222.0/24:p8p1:08.00.27.F5.8B.DB\n >>> <http://192.168.222.0/24:p8p1:08.00.27.F5.8B.DB%5Cn>" >>> + " -p 192.168.111.0/24:192.168.222.0/24:out:esp\n >>> <http://192.168.111.0/24:192.168.222.0/24:out:esp%5Cn>" >>> + " -e 192.168.111.2:192.168.222.2:3d >>> es:201:656c8523255ccc23a66c1917aa0cf30991fce83532a4b224\n" >>> + " -a 192.168.111.2:192.168.222.2:md >>> 5:201:a731649644c5dee92cbd9c2e7e188ee6\n" >>> + " -t 192.168.111.2:192.168.222.2:192.168.150.1:192 >>> .168.150.2\n" >>> + "\n" >>> + "Optional OPTIONS\n" >>> + " -f, --flows <number> routes count.\n" >>> + " -c, --count <number> CPU count.\n" >>> + " -q specify the queue type\n" >>> + " 0: ODP_SCHED_SYNC_PARALLEL\n" >>> + " 1: ODP_SCHED_SYNC_ATOMIC\n" >>> + " 2: ODP_SCHED_SYNC_ORDERED\n" >>> + " default is >>> ODP_SCHED_SYNC_ATOMIC\n" >>> + " -h, --help Display help and exit.\n" >>> + "\n", NO_PATH(progname), NO_PATH(progname) >>> + ); >>> +} >>> diff --git a/example/ipsec_offload/odp_ipsec_offload_cache.c >>> b/example/ipsec_offload/odp_ipsec_offload_cache.c >>> new file mode 100644 >>> index 0000000..5b6a036 >>> --- /dev/null >>> +++ b/example/ipsec_offload/odp_ipsec_offload_cache.c >>> @@ -0,0 +1,148 @@ >>> +/* >>> + * Copyright (c) 2017 NXP. All rights reserved. >>> + */ >>> +/* Copyright (c) 2017, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> +#include <stdlib.h> >>> +#include <string.h> >>> + >>> +#include <example_debug.h> >>> + >>> +#include <odp.h> >>> + >>> +#include <odp/helper/ipsec.h> >>> +#include <odp/helper/ip.h> >>> + >>> +#include <odp_ipsec_offload_cache.h> >>> + >>> +/** Global pointer to ipsec_cache db */ >>> +ipsec_cache_t *ipsec_cache; >>> + >>> +#define IPDEFTTL 64 >>> + >>> +void init_ipsec_cache(void) >>> +{ >>> + odp_shm_t shm; >>> + >>> + shm = odp_shm_reserve("shm_ipsec_cache", >>> + sizeof(ipsec_cache_t), >>> + ODP_CACHE_LINE_SIZE, >>> + 0); >>> + >>> + ipsec_cache = odp_shm_addr(shm); >>> + >>> + if (ipsec_cache == NULL) { >>> + EXAMPLE_ABORT("Error: shared mem alloc failed.\n"); >>> + } >>> + memset(ipsec_cache, 0, sizeof(*ipsec_cache)); >>> +} >>> + >>> +int create_ipsec_cache_entry(sa_db_entry_t *cipher_sa, >>> + sa_db_entry_t *auth_sa, >>> + tun_db_entry_t *tun, >>> + odp_bool_t in, >>> + odp_queue_t completionq) >>> +{ >>> + odp_ipsec_sa_param_t sa_params; >>> + ipsec_cache_entry_t *entry; >>> + odp_ipsec_sa_t sa; >>> + uint32_t src_ip, dst_ip; >>> + >>> + odp_ipsec_sa_param_init(&sa_params); >>> + >>> + /* Verify we have a good entry */ >>> + entry = &ipsec_cache->array[ipsec_cache->index]; >>> + if (MAX_DB <= ipsec_cache->index) >>> + return -1; >>> + >>> + /* Verify SA mode match in case of cipher&auth */ >>> + if (!tun) { >>> + printf("\n TRANSPORT MODE not supported"); >>> + return -1; >>> + } >>> + >>> + /* Setup parameters and call ipsec library to create sa */ >>> + if (in) { >>> + sa_params.dir = ODP_IPSEC_DIR_INBOUND; >>> + sa_params.lookup_mode = ODP_IPSEC_LOOKUP_IN_UNIQUE_SA; >>> + } else { >>> + sa_params.dir = ODP_IPSEC_DIR_OUTBOUND; >>> + sa_params.lookup_mode = ODP_IPSEC_LOOKUP_DISABLED; >>> + } >>> + >>> + sa_params.dest_queue = completionq; >>> + sa_params.mode = ODP_IPSEC_MODE_TUNNEL; >>> + >>> + /* Cipher */ >>> + if (cipher_sa) { >>> + sa_params.crypto.cipher_alg = cipher_sa->alg.u.cipher; >>> + sa_params.crypto.cipher_key.data = cipher_sa->key.data; >>> + sa_params.crypto.cipher_key.length = >>> cipher_sa->key.length; >>> + sa_params.spi = cipher_sa->spi; >>> + } else { >>> + sa_params.crypto.cipher_alg = ODP_CIPHER_ALG_NULL; >>> + } >>> + >>> + /* Auth */ >>> + if (auth_sa) { >>> + sa_params.crypto.auth_alg = auth_sa->alg.u.auth; >>> + sa_params.crypto.auth_key.data = auth_sa->key.data; >>> + sa_params.crypto.auth_key.length = auth_sa->key.length; >>> + } else { >>> + sa_params.crypto.auth_alg = ODP_AUTH_ALG_NULL; >>> + } >>> + >>> + src_ip = odp_cpu_to_be_32(tun->tun_src_ip); >>> + dst_ip = odp_cpu_to_be_32(tun->tun_dst_ip); >>> + sa_params.tunnel.type = ODP_IPSEC_TUNNEL_IPV4; >>> + sa_params.tunnel.ipv4.src_addr = &src_ip; >>> + sa_params.tunnel.ipv4.dst_addr = &dst_ip; >>> + sa_params.tunnel.ipv4.ttl = IPDEFTTL; >>> + sa_params.tunnel.ipv4.dscp = 0; >>> + sa_params.tunnel.ipv4.df = 1; >>> + >>> + sa = odp_ipsec_sa_create(&sa_params); >>> + if (sa == ODP_IPSEC_SA_INVALID) >>> + return -1; >>> + >>> + /* Copy selector IPs in cache entry*/ >>> + if (cipher_sa) { >>> + entry->src_ip = cipher_sa->src_ip; >>> + entry->dst_ip = cipher_sa->dst_ip; >>> + } else if (auth_sa) { >>> + entry->src_ip = auth_sa->src_ip; >>> + entry->dst_ip = auth_sa->dst_ip; >>> + } >>> + >>> + /* Initialize state */ >>> + entry->sa = sa; >>> + >>> + /* Add entry to the appropriate list */ >>> + ipsec_cache->index++; >>> + if (in) { >>> + entry->next = ipsec_cache->in_list; >>> + ipsec_cache->in_list = entry; >>> + } else { >>> + entry->next = ipsec_cache->out_list; >>> + ipsec_cache->out_list = entry; >>> + } >>> + >>> + return 0; >>> +} >>> + >>> +ipsec_cache_entry_t *find_ipsec_cache_entry_out(uint32_t src_ip, >>> + uint32_t dst_ip) >>> +{ >>> + ipsec_cache_entry_t *entry = ipsec_cache->out_list; >>> + >>> + /* Look for a hit */ >>> + for (; NULL != entry; entry = entry->next) { >>> + if ((entry->src_ip == src_ip) && (entry->dst_ip == >>> dst_ip)) >>> + break; >>> + } >>> + return entry; >>> +} >>> diff --git a/example/ipsec_offload/odp_ipsec_offload_cache.h >>> b/example/ipsec_offload/odp_ipsec_offload_cache.h >>> new file mode 100644 >>> index 0000000..65f4dda >>> --- /dev/null >>> +++ b/example/ipsec_offload/odp_ipsec_offload_cache.h >>> @@ -0,0 +1,78 @@ >>> +/* Copyright (c) 2017, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> +#ifndef ODP_IPSEC_CACHE_H_ >>> +#define ODP_IPSEC_CACHE_H_ >>> + >>> +#ifdef __cplusplus >>> +extern "C" { >>> +#endif >>> + >>> +#include <odp.h> >>> +#include <odp/helper/ipsec.h> >>> + >>> +#include <odp_ipsec_offload_misc.h> >>> +#include <odp_ipsec_offload_sa_db.h> >>> + >>> +/** >>> + * IPsec cache data base entry >>> + */ >>> +typedef struct ipsec_cache_entry_s { >>> + struct ipsec_cache_entry_s *next; /**< Next entry >>> on list */ >>> + uint32_t src_ip; /**< Source v4 >>> address */ >>> + uint32_t dst_ip; /**< Destination >>> v4 address */ >>> + odp_ipsec_sa_t sa; /**< IPSec sa >>> handle */ >>> +} ipsec_cache_entry_t; >>> + >>> +/** >>> + * IPsec cache data base global structure >>> + */ >>> +typedef struct ipsec_cache_s { >>> + uint32_t index; /**< Index of next available >>> entry */ >>> + ipsec_cache_entry_t *in_list; /**< List of active input >>> entries */ >>> + ipsec_cache_entry_t *out_list; /**< List of active output >>> entries */ >>> + ipsec_cache_entry_t array[MAX_DB]; /**< Entry storage */ >>> +} ipsec_cache_t; >>> + >>> +/** Global pointer to ipsec_cache db */ >>> +extern ipsec_cache_t *ipsec_cache; >>> + >>> +/** Initialize IPsec cache */ >>> +void init_ipsec_cache(void); >>> + >>> +/** >>> + * Create an entry in the IPsec cache >>> + * >>> + * @param cipher_sa Cipher SA DB entry pointer >>> + * @param auth_sa Auth SA DB entry pointer >>> + * @param tun Tunnel DB entry pointer >>> + * @param in Direction (input versus output) >>> + * @param completionq Completion queue >>> + * >>> + * @return 0 if successful else -1 >>> + */ >>> +int create_ipsec_cache_entry(sa_db_entry_t *cipher_sa, >>> + sa_db_entry_t *auth_sa, >>> + tun_db_entry_t *tun, >>> + odp_bool_t in, >>> + odp_queue_t completionq); >>> + >>> +/** >>> + * Find a matching IPsec cache entry for output packet >>> + * >>> + * @param src_ip Source IPv4 address >>> + * @param dst_ip Destination IPv4 address >>> + * >>> + * @return pointer to IPsec cache entry else NULL >>> + */ >>> +ipsec_cache_entry_t *find_ipsec_cache_entry_out(uint32_t src_ip, >>> + uint32_t dst_ip); >>> + >>> +#ifdef __cplusplus >>> +} >>> +#endif >>> + >>> +#endif >>> diff --git a/example/ipsec_offload/odp_ipsec_offload_fwd_db.c >>> b/example/ipsec_offload/odp_ipsec_offload_fwd_db.c >>> new file mode 100644 >>> index 0000000..860b3ee >>> --- /dev/null >>> +++ b/example/ipsec_offload/odp_ipsec_offload_fwd_db.c >>> @@ -0,0 +1,223 @@ >>> +/* Copyright (c) 2017, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> +/* enable strtok */ >>> +#define _POSIX_C_SOURCE 200112L >>> + >>> +#include <stdlib.h> >>> +#include <string.h> >>> + >>> +#include <example_debug.h> >>> +#include <odp.h> >>> + >>> +#include <odp_ipsec_offload_fwd_db.h> >>> + >>> +/** >>> + * Pointer to Flow cache table >>> + */ >>> +flow_bucket_t *flow_table; >>> + >>> +/** >>> + * bucket count. It will be updated with user argument if provided >>> + */ >>> +uint32_t bucket_count = ODP_DEFAULT_BUCKET_COUNT; >>> + >>> +/** Global pointer to fwd db */ >>> +fwd_db_t *fwd_db; >>> + >>> +void odp_init_routing_table(void) >>> +{ >>> + odp_shm_t hash_shm; >>> + uint32_t i; >>> + flow_bucket_t *bucket; >>> + >>> + /*Reserve memory for Routing hash table*/ >>> + hash_shm = odp_shm_reserve("route_table", >>> + sizeof(flow_bucket_t) * bucket_count, >>> + ODP_CACHE_LINE_SIZE, 0); >>> + flow_table = odp_shm_addr(hash_shm); >>> + if (!flow_table) { >>> + EXAMPLE_ABORT("Error: shared mem alloc failed.\n"); >>> + } >>> + /*Inialize Locks*/ >>> + for (i = 0; i < bucket_count; i++) { >>> + bucket = &flow_table[i]; >>> + LOCK_INIT(&bucket->lock); >>> + } >>> + >>> + memset(flow_table, 0, bucket_count * sizeof(flow_bucket_t)); >>> +} >>> + >>> +void init_fwd_db(void) >>> +{ >>> + odp_shm_t shm; >>> + >>> + shm = odp_shm_reserve("shm_fwd_db", >>> + sizeof(fwd_db_t), >>> + ODP_CACHE_LINE_SIZE, >>> + 0); >>> + >>> + fwd_db = odp_shm_addr(shm); >>> + >>> + if (fwd_db == NULL) { >>> + EXAMPLE_ABORT("Error: shared mem alloc failed.\n"); >>> + } >>> + memset(fwd_db, 0, sizeof(*fwd_db)); >>> +} >>> + >>> +int create_fwd_db_entry(char *input, char **if_names, int if_count, int >>> entries) >>> +{ >>> + int pos = 0, i, match = 0, count = 0; >>> + char *local; >>> + char *str; >>> + char *save; >>> + char *token; >>> + fwd_db_entry_t *entry = &fwd_db->array[fwd_db->index]; >>> + >>> + /* Verify we haven't run out of space */ >>> + if (MAX_DB <= fwd_db->index) >>> + return -1; >>> + >>> + /* Make a local copy */ >>> + local = malloc(strlen(input) + 1); >>> + if (NULL == local) >>> + return -1; >>> + strcpy(local, input); >>> + >>> + /* Setup for using "strtok_r" to search input string */ >>> + str = local; >>> + save = NULL; >>> + >>> + /* Parse tokens separated by ':' */ >>> + while (NULL != (token = strtok_r(str, ":", &save))) { >>> + str = NULL; /* reset str for subsequent strtok_r calls */ >>> + >>> + /* Parse token based on its position */ >>> + switch (pos) { >>> + case 0: >>> + parse_ipv4_string(token, >>> + &entry->subnet.addr, >>> + &entry->subnet.mask); >>> + break; >>> + case 1: >>> + strncpy(entry->oif, token, OIF_LEN - 1); >>> + entry->oif[OIF_LEN - 1] = 0; >>> + for (i = 0; i < if_count; i++) { >>> + if (!strcmp(if_names[i], entry->oif)) { >>> + match = 1; >>> + break; >>> + } >>> + } >>> + if (!match) { >>> + printf("ERROR: interface name not correct >>> for route\n"); >>> + free(local); >>> + return -1; >>> + } >>> + break; >>> + case 2: >>> + parse_mac_string(token, entry->dst_mac); >>> + break; >>> + default: >>> + printf("ERROR: extra token \"%s\" at position >>> %d\n", >>> + token, pos); >>> + break; >>> + } >>> + >>> + /* Advance to next position */ >>> + pos++; >>> + } >>> + >>> + /* Verify we parsed exactly the number of tokens we expected */ >>> + if (3 != pos) { >>> + printf("ERROR: \"%s\" contains %d tokens, expected 3\n", >>> + input, >>> + pos); >>> + free(local); >>> + return -1; >>> + } >>> + >>> + /* Add route to the list */ >>> + fwd_db->index++; >>> + entry->next = fwd_db->list; >>> + fwd_db->list = entry; >>> + >>> + count++; >>> + >>> + while (count < entries) { >>> + fwd_db_entry_t *new_entry = &fwd_db->array[fwd_db->index]; >>> + >>> + /* Verify we haven't run out of space */ >>> + if (MAX_DB <= fwd_db->index) >>> + return -1; >>> + >>> + new_entry->subnet.addr = entry->subnet.addr + count; >>> + new_entry->subnet.mask = entry->subnet.mask; >>> + strncpy(new_entry->oif, entry->oif, OIF_LEN - 1); >>> + new_entry->oif[OIF_LEN - 1] = 0; >>> + new_entry->dst_mac[0] = entry->dst_mac[0]; >>> + new_entry->dst_mac[1] = entry->dst_mac[1]; >>> + new_entry->dst_mac[2] = entry->dst_mac[2]; >>> + new_entry->dst_mac[3] = entry->dst_mac[3]; >>> + new_entry->dst_mac[4] = entry->dst_mac[4]; >>> + new_entry->dst_mac[5] = entry->dst_mac[5]; >>> + >>> + /* Add route to the list */ >>> + fwd_db->index++; >>> + new_entry->next = fwd_db->list; >>> + fwd_db->list = new_entry; >>> + count++; >>> + } >>> + >>> + free(local); >>> + return 0; >>> +} >>> + >>> +void resolve_fwd_db(char *intf, odp_pktout_queue_t pktout, uint8_t *mac) >>> +{ >>> + fwd_db_entry_t *entry; >>> + >>> + /* Walk the list and attempt to set output queue and MAC */ >>> + for (entry = fwd_db->list; NULL != entry; entry = entry->next) { >>> + if (strcmp(intf, entry->oif)) >>> + continue; >>> + >>> + entry->pktout = pktout; >>> + memcpy(entry->src_mac, mac, ODPH_ETHADDR_LEN); >>> + } >>> +} >>> + >>> +void dump_fwd_db_entry(fwd_db_entry_t *entry) >>> +{ >>> + char subnet_str[MAX_STRING]; >>> + char mac_str[MAX_STRING]; >>> + >>> + printf(" %s %s %s\n", >>> + ipv4_subnet_str(subnet_str, &entry->subnet), >>> + entry->oif, >>> + mac_addr_str(mac_str, entry->dst_mac)); >>> +} >>> + >>> +void dump_fwd_db(void) >>> +{ >>> + fwd_db_entry_t *entry; >>> + >>> + printf("\n" >>> + "Routing table\n" >>> + "-------------\n"); >>> + >>> + for (entry = fwd_db->list; NULL != entry; entry = entry->next) >>> + dump_fwd_db_entry(entry); >>> +} >>> + >>> +fwd_db_entry_t *find_fwd_db_entry(uint32_t dst_ip) >>> +{ >>> + fwd_db_entry_t *entry; >>> + >>> + for (entry = fwd_db->list; NULL != entry; entry = entry->next) >>> + if (entry->subnet.addr == (dst_ip & entry->subnet.mask)) >>> + break; >>> + return entry; >>> +} >>> diff --git a/example/ipsec_offload/odp_ipsec_offload_fwd_db.h >>> b/example/ipsec_offload/odp_ipsec_offload_fwd_db.h >>> new file mode 100644 >>> index 0000000..2f42596 >>> --- /dev/null >>> +++ b/example/ipsec_offload/odp_ipsec_offload_fwd_db.h >>> @@ -0,0 +1,198 @@ >>> +/* Copyright (c) 2017, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> +#ifndef ODP_IPSEC_FWD_DB_H_ >>> +#define ODP_IPSEC_FWD_DB_H_ >>> + >>> +#ifdef __cplusplus >>> +extern "C" { >>> +#endif >>> + >>> +#include <odp.h> >>> +#include <odp/helper/eth.h> >>> +#include <odp_ipsec_offload_misc.h> >>> + >>> +#define OIF_LEN 32 >>> + >>> +/** >>> + * Forwarding data base entry >>> + */ >>> + >>> +typedef struct fwd_db_entry_s { >>> + struct fwd_db_entry_s *next; /**< Next entry on list */ >>> + char oif[OIF_LEN]; /**< Output interface name >>> */ >>> + odp_pktout_queue_t pktout; /**< Output transmit >>> queue */ >>> + uint8_t src_mac[ODPH_ETHADDR_LEN]; /**< Output source MAC */ >>> + uint8_t dst_mac[ODPH_ETHADDR_LEN]; /**< Output destination MAC >>> */ >>> + ip_addr_range_t subnet; /**< Subnet for this router >>> */ >>> +} fwd_db_entry_t; >>> + >>> +/** >>> + * Forwarding data base global structure >>> + */ >>> +typedef struct fwd_db_s { >>> + uint32_t index; /**< Next available entry */ >>> + fwd_db_entry_t *list; /**< List of active routes */ >>> + fwd_db_entry_t array[MAX_DB]; /**< Entry storage */ >>> +} fwd_db_t; >>> + >>> +/** Global pointer to fwd db */ >>> +extern fwd_db_t *fwd_db; >>> + >>> +/** >>> + * Flow cache table entry >>> + */ >>> +typedef struct { >>> + void *next; /**< Pointer to next flow >>> in list*/ >>> + uint32_t l3_src; /**< Source IP Address*/ >>> + uint32_t l3_dst; /**< Destination IP >>> Address*/ >>> + odp_out_entry_t out_port; /**< Out interface of >>> matching flow*/ >>> +} odp_flow_entry_t; >>> + >>> +/** >>> + * Flow cache table bucket >>> + */ >>> +typedef struct { >>> + odp_spinlock_t lock; /**< Bucket lock*/ >>> + odp_flow_entry_t *next; /**< Pointer to first flow entry >>> in bucket*/ >>> +} flow_bucket_t; >>> + >>> +/** >>> +* Pointers to Flow cache tables >>> +*/ >>> +extern flow_bucket_t *flow_table; >>> + >>> +extern flow_bucket_t *ipsec_out_flow_table; >>> + >>> +extern flow_bucket_t *ipsec_in_flow_table; >>> + >>> +/** >>> + * Number of buckets in hash table >>> + */ >>> +extern uint32_t bucket_count; >>> + >>> +/* >>> + * Allocate and Initialize routing table with default Route entries. >>> + * >>> + */ >>> +void odp_init_routing_table(void); >>> + >>> +/* >>> + * Searches flow entry in given hash bucket according to given 5-tuple >>> information >>> + * >>> + * @param sip Source IP Address >>> + * @param dip Destination IP Address >>> + * @param sport Source Port Number >>> + * @param dport Destination Port Number >>> + * @param proto IP protocol >>> + * @param bucket Hash Bucket >>> + * >>> + * @return Matching flow entry >>> + */ >>> +static inline odp_flow_entry_t *odp_route_flow_lookup_in_bucket(uint32_t >>> sip, >>> + uint32_t dip, void >>> *bucket) >>> +{ >>> + odp_flow_entry_t *flow, *head; >>> + >>> + head = ((flow_bucket_t *)bucket)->next; >>> + for (flow = head; flow != NULL; flow = flow->next) { >>> + if ((flow->l3_src == sip) && (flow->l3_dst == dip)) >>> + return flow; >>> + } >>> + return NULL; >>> +} >>> + >>> +/** >>> + * Insert the flow into given hash bucket >>> + * >>> + * @param flow Which is to be inserted >>> + * @param bucket Target Hash Bucket >>> + * >>> + */ >>> +static inline void odp_route_flow_insert_in_bucket(odp_flow_entry_t >>> *flow, >>> + void >>> *bucket) >>> +{ >>> + odp_flow_entry_t *temp; >>> + flow_bucket_t *bkt = (flow_bucket_t *)bucket; >>> + >>> + if (!flow) { >>> + EXAMPLE_ERR("Invalid flow entry passed\n"); >>> + return; >>> + } >>> + >>> + LOCK(&bkt->lock); >>> + /*Check that entry already exist or not*/ >>> + temp = odp_route_flow_lookup_in_bucket(flow->l3_src, >>> flow->l3_dst, bkt); >>> + if (temp) { >>> + UNLOCK(&bkt->lock); >>> + return; >>> + } >>> + >>> + if (!bkt->next) { >>> + bkt->next = flow; >>> + } else { >>> + temp = bkt->next; >>> + flow->next = temp; >>> + bkt->next = flow; >>> + } >>> + UNLOCK(&bkt->lock); >>> +} >>> + >>> +/** Initialize FWD DB */ >>> +void init_fwd_db(void); >>> + >>> +/** >>> + * Create a forwarding database entry >>> + * >>> + * String is of the format "SubNet:Intf:NextHopMAC" >>> + * >>> + * @param input Pointer to string describing route >>> + * >>> + * @param if_names Array of Name of the interfaces available >>> + * >>> + * @param if_count number of interfaces in if_names array >>> + * >>> + * @param entries number of entries >>> + * >>> + * @return 0 if successful else -1 >>> + */ >>> +int create_fwd_db_entry(char *input, char **if_names, int if_count, int >>> entries); >>> + >>> +/** >>> + * Scan FWD DB entries and resolve output queue and source MAC address >>> + * >>> + * @param intf Interface name string >>> + * @param outq Output queue for packet transmit >>> + * @param mac MAC address of this interface >>> + */ >>> +void resolve_fwd_db(char *intf, odp_pktout_queue_t pktout, uint8_t *mac); >>> + >>> +/** >>> + * Display one fowarding database entry >>> + * >>> + * @param entry Pointer to entry to display >>> + */ >>> +void dump_fwd_db_entry(fwd_db_entry_t *entry); >>> + >>> +/** >>> + * Display the forwarding database >>> + */ >>> +void dump_fwd_db(void); >>> + >>> +/** >>> + * Find a matching forwarding database entry >>> + * >>> + * @param dst_ip Destination IPv4 address >>> + * >>> + * @return pointer to forwarding DB entry else NULL >>> + */ >>> +fwd_db_entry_t *find_fwd_db_entry(uint32_t dst_ip); >>> + >>> +#ifdef __cplusplus >>> +} >>> +#endif >>> + >>> +#endif >>> diff --git a/example/ipsec_offload/odp_ipsec_offload_misc.h >>> b/example/ipsec_offload/odp_ipsec_offload_misc.h >>> new file mode 100644 >>> index 0000000..dbe6dc9 >>> --- /dev/null >>> +++ b/example/ipsec_offload/odp_ipsec_offload_misc.h >>> @@ -0,0 +1,384 @@ >>> +/* Copyright (c) 2017, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> +#ifndef ODP_IPSEC_MISC_H_ >>> +#define ODP_IPSEC_MISC_H_ >>> + >>> +#ifdef __cplusplus >>> +extern "C" { >>> +#endif >>> + >>> +#include <odp.h> >>> +#include <odp/helper/eth.h> >>> +#include <odp/helper/ip.h> >>> +#include <odp/helper/ipsec.h> >>> + >>> +#ifndef TRUE >>> +#define TRUE 1 >>> +#endif >>> +#ifndef FALSE >>> +#define FALSE 0 >>> +#endif >>> + >>> +#define MAX_DB 1024 /**< maximum number of data base entries >>> */ >>> +#define MAX_STRING 32 /**< maximum string length */ >>> +#define KEY_BITS_3DES 192 /**< 3DES cipher key length in bits */ >>> +#define KEY_BITS_MD5_96 128 /**< MD5_96 auth key length in bits */ >>> +#define KEY_BITS_AES 128 /**< AES cipher key length in bits */ >>> +#define KEY_BITS_SHA1_96 160 /**< SHA1_96 auth key length in bits */ >>> +#define KEY_BITS_SHA2_256 256 /**< SHA2_256 auth key length in bits */ >>> + >>> +/** >>> + * Number of buckets in hash table >>> + */ >>> +extern uint32_t bucket_count; >>> + >>> +#define LOCK(a) odp_spinlock_lock(a) >>> +#define UNLOCK(a) odp_spinlock_unlock(a) >>> +#define LOCK_INIT(a) odp_spinlock_init(a) >>> + >>> +/** >>> + * Hash calculation utility >>> + */ >>> +#define JHASH_GOLDEN_RATIO 0x9e3779b9 >>> +#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) >>> +#define ODP_BJ3_MIX(a, b, c) \ >>> +{ \ >>> + a -= c; a ^= rot(c, 4); c += b; \ >>> + b -= a; b ^= rot(a, 6); a += c; \ >>> + c -= b; c ^= rot(b, 8); b += a; \ >>> + a -= c; a ^= rot(c, 16); c += b; \ >>> + b -= a; b ^= rot(a, 19); a += c; \ >>> + c -= b; c ^= rot(b, 4); b += a; \ >>> +} >>> + >>> +/** >>> + * Default Hash bucket number >>> + */ >>> +#define ODP_DEFAULT_BUCKET_COUNT 1024 >>> + >>> +/**< Number of bits represnted by a string of hexadecimal characters */ >>> +#define KEY_STR_BITS(str) (4 * strlen(str)) >>> + >>> +/** IPv4 helpers for data length and uint8t pointer */ >>> +#define ipv4_data_p(ip) ((uint8_t *)((odph_ipv4hdr_t *)ip + 1)) >>> + >>> +/** Get rid of path in filename - only for unix-type paths using '/' */ >>> +#define NO_PATH(file_name) (strrchr((file_name), '/') ? \ >>> + strrchr((file_name), '/') + 1 : (file_name)) >>> + >>> +/** >>> + * Actual entries >>> + */ >>> +typedef struct { >>> + odp_pktout_queue_t pktout; /**< queue handle*/ >>> + odph_ethaddr_t addr; /**< pktio MAC Address*/ >>> + odph_ethaddr_t next_hop_addr; /**< Next Hop MAC Address*/ >>> + odp_ipsec_sa_t sa; /**< IPSec sa handle*/ >>> +} odp_out_entry_t; >>> + >>> +/** >>> + * IPsec key >>> + */ >>> +typedef struct { >>> + uint8_t data[32]; /**< Key data */ >>> + uint8_t length; /**< Key length */ >>> +} ipsec_key_t; >>> + >>> +/** >>> + * IPsec algorithm >>> + */ >>> +typedef struct { >>> + odp_bool_t cipher; >>> + union { >>> + odp_cipher_alg_t cipher; >>> + odp_auth_alg_t auth; >>> + } u; >>> +} ipsec_alg_t; >>> + >>> +/** >>> + * IP address range (subnet) >>> + */ >>> +typedef struct ip_addr_range_s { >>> + uint32_t addr; /**< IP address */ >>> + uint32_t mask; /**< mask, 1 indicates bits are valid */ >>> +} ip_addr_range_t; >>> + >>> +/** >>> + * Parse text string representing a key into ODP key structure >>> + * >>> + * @param keystring Pointer to key string to convert >>> + * @param key Pointer to ODP key structure to populate >>> + * @param alg Cipher/authentication algorithm associated with the >>> key >>> + * >>> + * @return 0 if successful else -1 >>> + */ >>> +static inline >>> +int parse_key_string(char *keystring, >>> + ipsec_key_t *key, >>> + ipsec_alg_t *alg) >>> +{ >>> + int idx; >>> + int key_bits_in = KEY_STR_BITS(keystring); >>> + char temp[3]; >>> + >>> + key->length = 0; >>> + >>> + /* Algorithm is either cipher or authentication */ >>> + if (alg->cipher) { >>> + if ((alg->u.cipher == ODP_CIPHER_ALG_3DES_CBC) && >>> + (KEY_BITS_3DES == key_bits_in)) >>> + key->length = key_bits_in / 8; >>> + if ((alg->u.cipher == ODP_CIPHER_ALG_AES128_CBC) && >>> + (KEY_BITS_AES == key_bits_in)) >>> + key->length = key_bits_in / 8; >>> + } else { >>> + if ((alg->u.auth == ODP_AUTH_ALG_MD5_96) && >>> + (KEY_BITS_MD5_96 == key_bits_in)) >>> + key->length = key_bits_in / 8; >>> + if ((alg->u.auth == ODP_AUTH_ALG_SHA1_96) && >>> + (KEY_BITS_SHA1_96 == key_bits_in)) >>> + key->length = key_bits_in / 8; >>> + if ((alg->u.auth == ODP_AUTH_ALG_SHA256_128) && >>> + (KEY_BITS_SHA2_256 == key_bits_in)) >>> + key->length = key_bits_in / 8; >>> + } >>> + >>> + for (idx = 0; idx < key->length; idx++) { >>> + temp[0] = *keystring++; >>> + temp[1] = *keystring++; >>> + temp[2] = 0; >>> + key->data[idx] = strtol(temp, NULL, 16); >>> + } >>> + >>> + return key->length ? 0 : -1; >>> +} >>> + >>> +/** >>> + * Check IPv4 address against a range/subnet >>> + * >>> + * @param addr IPv4 address to check >>> + * @param range Pointer to address range to check against >>> + * >>> + * @return 1 if match else 0 >>> + */ >>> +static inline >>> +int match_ip_range(uint32_t addr, ip_addr_range_t *range) >>> +{ >>> + return (range->addr == (addr & range->mask)); >>> +} >>> + >>> +/** >>> + * Generate text string representing IPv4 address >>> + * >>> + * @param b Pointer to buffer to store string >>> + * @param addr IPv4 address >>> + * >>> + * @return Pointer to supplied buffer >>> + */ >>> +static inline >>> +char *ipv4_addr_str(char *b, uint32_t addr) >>> +{ >>> + sprintf(b, "%03d.%03d.%03d.%03d", >>> + 0xFF & ((addr) >> 24), >>> + 0xFF & ((addr) >> 16), >>> + 0xFF & ((addr) >> 8), >>> + 0xFF & ((addr) >> 0)); >>> + return b; >>> +} >>> + >>> +/** >>> + * Parse text string representing an IPv4 address or subnet >>> + * >>> + * String is of the format "XXX.XXX.XXX.XXX(/W)" where >>> + * "XXX" is decimal value and "/W" is optional subnet length >>> + * >>> + * @param ipaddress Pointer to IP address/subnet string to convert >>> + * @param addr Pointer to return IPv4 address >>> + * @param mask Pointer (optional) to return IPv4 mask >>> + * >>> + * @return 0 if successful else -1 >>> + */ >>> +static inline >>> +int parse_ipv4_string(char *ipaddress, uint32_t *addr, uint32_t *mask) >>> +{ >>> + int b[4]; >>> + int qualifier = 32; >>> + int converted; >>> + >>> + if (strchr(ipaddress, '/')) { >>> + converted = sscanf(ipaddress, "%d.%d.%d.%d/%d", >>> + &b[3], &b[2], &b[1], &b[0], >>> + &qualifier); >>> + if (5 != converted) >>> + return -1; >>> + } else { >>> + converted = sscanf(ipaddress, "%d.%d.%d.%d", >>> + &b[3], &b[2], &b[1], &b[0]); >>> + if (4 != converted) >>> + return -1; >>> + } >>> + >>> + if ((b[0] > 255) || (b[1] > 255) || (b[2] > 255) || (b[3] > 255)) >>> + return -1; >>> + if (!qualifier || (qualifier > 32)) >>> + return -1; >>> + >>> + *addr = b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24; >>> + if (mask) >>> + *mask = ~(0xFFFFFFFF & ((1ULL << (32 - qualifier)) - 1)); >>> + >>> + return 0; >>> +} >>> + >>> +/** >>> + * Generate text string representing IPv4 range/subnet, output >>> + * in "XXX.XXX.XXX.XXX/W" format >>> + * >>> + * @param b Pointer to buffer to store string >>> + * @param range Pointer to IPv4 address range >>> + * >>> + * @return Pointer to supplied buffer >>> + */ >>> +static inline >>> +char *ipv4_subnet_str(char *b, ip_addr_range_t *range) >>> +{ >>> + int idx; >>> + int len; >>> + >>> + for (idx = 0; idx < 32; idx++) >>> + if (range->mask & (1 << idx)) >>> + break; >>> + len = 32 - idx; >>> + >>> + sprintf(b, "%03d.%03d.%03d.%03d/%d", >>> + 0xFF & ((range->addr) >> 24), >>> + 0xFF & ((range->addr) >> 16), >>> + 0xFF & ((range->addr) >> 8), >>> + 0xFF & ((range->addr) >> 0), >>> + len); >>> + return b; >>> +} >>> + >>> +/** >>> + * Generate text string representing MAC address >>> + * >>> + * @param b Pointer to buffer to store string >>> + * @param mac Pointer to MAC address >>> + * >>> + * @return Pointer to supplied buffer >>> + */ >>> +static inline >>> +char *mac_addr_str(char *b, uint8_t *mac) >>> +{ >>> + sprintf(b, "%02X.%02X.%02X.%02X.%02X.%02X", >>> + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); >>> + return b; >>> +} >>> + >>> +/** >>> + * Parse text string representing a MAC address into byte araray >>> + * >>> + * String is of the format "XX.XX.XX.XX.XX.XX" where XX is hexadecimal >>> + * >>> + * @param macaddress Pointer to MAC address string to convert >>> + * @param mac Pointer to MAC address byte array to populate >>> + * >>> + * @return 0 if successful else -1 >>> + */ >>> +static inline >>> +int parse_mac_string(char *macaddress, uint8_t *mac) >>> +{ >>> + int macwords[ODPH_ETHADDR_LEN]; >>> + int converted; >>> + >>> + converted = sscanf(macaddress, >>> + "%x.%x.%x.%x.%x.%x", >>> + &macwords[0], &macwords[1], &macwords[2], >>> + &macwords[3], &macwords[4], &macwords[5]); >>> + if (6 != converted) >>> + return -1; >>> + >>> + mac[0] = macwords[0]; >>> + mac[1] = macwords[1]; >>> + mac[2] = macwords[2]; >>> + mac[3] = macwords[3]; >>> + mac[4] = macwords[4]; >>> + mac[5] = macwords[5]; >>> + >>> + return 0; >>> +} >>> + >>> +/** >>> + * Locate IPsec headers (AH and/or ESP) in packet >>> + * >>> + * @param ip Pointer to packets IPv4 header >>> + * @param ah_p Pointer to location to return AH header pointer >>> + * @param esp_p Pointer to location to return ESP header pointer >>> + * >>> + * @return length of IPsec headers found >>> + */ >>> +static inline >>> +int locate_ipsec_headers(odph_ipv4hdr_t *ip, >>> + odph_ahhdr_t **ah_p, >>> + odph_esphdr_t **esp_p) >>> +{ >>> + uint8_t *in = ipv4_data_p(ip); >>> + odph_ahhdr_t *ah = NULL; >>> + odph_esphdr_t *esp = NULL; >>> + >>> + if (ODPH_IPPROTO_AH == ip->proto) { >>> + ah = (odph_ahhdr_t *)in; >>> + in += ((ah)->ah_len + 2) * 4; >>> + if (ODPH_IPPROTO_ESP == ah->next_header) { >>> + esp = (odph_esphdr_t *)in; >>> + in += sizeof(odph_esphdr_t); >>> + } >>> + } else if (ODPH_IPPROTO_ESP == ip->proto) { >>> + esp = (odph_esphdr_t *)in; >>> + in += sizeof(odph_esphdr_t); >>> + } >>> + >>> + *ah_p = ah; >>> + *esp_p = esp; >>> + return in - (ipv4_data_p(ip)); >>> +} >>> + >>> +/** >>> + * Adjust IPv4 length >>> + * >>> + * @param ip Pointer to IPv4 header >>> + * @param adj Signed adjustment value >>> + */ >>> +static inline >>> +void ipv4_adjust_len(odph_ipv4hdr_t *ip, int adj) >>> +{ >>> + ip->tot_len = odp_cpu_to_be_16(odp_be_to_cpu_16(ip->tot_len) + >>> adj); >>> +} >>> + >>> +/** >>> + * Verify crypto operation completed successfully >>> + * >>> + * @param status Pointer to cryto completion structure >>> + * >>> + * @return TRUE if all OK else FALSE >>> + */ >>> +static inline >>> +odp_bool_t is_crypto_compl_status_ok(odp_crypto_compl_status_t *status) >>> +{ >>> + if (status->alg_err != ODP_CRYPTO_ALG_ERR_NONE) >>> + return FALSE; >>> + if (status->hw_err != ODP_CRYPTO_HW_ERR_NONE) >>> + return FALSE; >>> + return TRUE; >>> +} >>> + >>> + >>> +#ifdef __cplusplus >>> +} >>> +#endif >>> + >>> +#endif >>> diff --git a/example/ipsec_offload/odp_ipsec_offload_sa_db.c >>> b/example/ipsec_offload/odp_ipsec_offload_sa_db.c >>> new file mode 100644 >>> index 0000000..c299daa >>> --- /dev/null >>> +++ b/example/ipsec_offload/odp_ipsec_offload_sa_db.c >>> @@ -0,0 +1,361 @@ >>> +/* Copyright (c) 2017, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> +/* enable strtok */ >>> +#define _POSIX_C_SOURCE 200112L >>> + >>> +#include <stdlib.h> >>> +#include <string.h> >>> + >>> +#include <example_debug.h> >>> + >>> +#include <odp.h> >>> + >>> +#include <odp_ipsec_offload_sa_db.h> >>> + >>> +/** Global pointer to sa db */ >>> +static sa_db_t *sa_db; >>> + >>> +/** Global pointer to tun db */ >>> +static tun_db_t *tun_db; >>> + >>> +void init_sa_db(void) >>> +{ >>> + odp_shm_t shm; >>> + >>> + shm = odp_shm_reserve("shm_sa_db", >>> + sizeof(sa_db_t), >>> + ODP_CACHE_LINE_SIZE, >>> + 0); >>> + >>> + sa_db = odp_shm_addr(shm); >>> + >>> + if (sa_db == NULL) { >>> + EXAMPLE_ABORT("Error: shared mem alloc failed.\n"); >>> + } >>> + memset(sa_db, 0, sizeof(*sa_db)); >>> +} >>> + >>> +void init_tun_db(void) >>> +{ >>> + odp_shm_t shm; >>> + >>> + shm = odp_shm_reserve("shm_tun_db", >>> + sizeof(tun_db_t), >>> + ODP_CACHE_LINE_SIZE, >>> + 0); >>> + tun_db = odp_shm_addr(shm); >>> + >>> + if (!tun_db) { >>> + EXAMPLE_ABORT("Error: shared mem alloc failed.\n"); >>> + } >>> + memset(tun_db, 0, sizeof(*tun_db)); >>> +} >>> + >>> +int create_sa_db_entry(char *input, odp_bool_t cipher, int entries) >>> +{ >>> + int pos = 0, count = 0; >>> + char *local; >>> + char *str; >>> + char *save; >>> + char *token; >>> + sa_db_entry_t *entry = &sa_db->array[sa_db->index]; >>> + >>> + /* Verify we have a good entry */ >>> + if (MAX_DB <= sa_db->index) >>> + return -1; >>> + >>> + /* Make a local copy */ >>> + local = malloc(strlen(input) + 1); >>> + if (NULL == local) >>> + return -1; >>> + strcpy(local, input); >>> + >>> + /* Set cipher versus auth */ >>> + entry->alg.cipher = cipher; >>> + >>> + /* Setup for using "strtok_r" to search input string */ >>> + str = local; >>> + save = NULL; >>> + >>> + /* Parse tokens separated by ':' */ >>> + while (NULL != (token = strtok_r(str, ":", &save))) { >>> + str = NULL; /* reset str for subsequent strtok_r calls */ >>> + >>> + /* Parse token based on its position */ >>> + switch (pos) { >>> + case 0: >>> + parse_ipv4_string(token, &entry->src_ip, NULL); >>> + break; >>> + case 1: >>> + parse_ipv4_string(token, &entry->dst_ip, NULL); >>> + break; >>> + case 2: >>> + if (cipher) { >>> + if (0 == strcmp(token, "3des")) { >>> + entry->alg.u.cipher = >>> + ODP_CIPHER_ALG_3DES_CBC; >>> + } else if (0 == strcmp(token, "aes")) { >>> + entry->alg.u.cipher = >>> + ODP_CIPHER_ALG_AES128_CBC; >>> + } else { >>> + entry->alg.u.cipher = >>> + ODP_CIPHER_ALG_NULL; >>> + } >>> + } else { >>> + if (0 == strcmp(token, "md5")) { >>> + entry->alg.u.auth = >>> + ODP_AUTH_ALG_MD5_96; >>> + } else if (0 == strcmp(token, "sha1")) { >>> + entry->alg.u.auth = >>> + ODP_AUTH_ALG_SHA1_96; >>> + } else if (0 == strcmp(token, "sha256")) { >>> + entry->alg.u.auth = >>> + ODP_AUTH_ALG_SHA256_128; >>> + } else { >>> + entry->alg.u.auth = >>> ODP_AUTH_ALG_NULL; >>> + } >>> + } >>> + break; >>> + case 3: >>> + entry->spi = strtol(token, NULL, 16); >>> + break; >>> + case 4: >>> + parse_key_string(token, >>> + &entry->key, >>> + &entry->alg); >>> + break; >>> + default: >>> + printf("ERROR: extra token \"%s\" at position >>> %d\n", >>> + token, pos); >>> + break; >>> + } >>> + >>> + /* Advance to next position */ >>> + pos++; >>> + } >>> + >>> + /* Verify we parsed exactly the number of tokens we expected */ >>> + if (5 != pos) { >>> + printf("ERROR: \"%s\" contains %d tokens, expected 5\n", >>> + input, >>> + pos); >>> + free(local); >>> + return -1; >>> + } >>> + >>> + /* Add route to the list */ >>> + sa_db->index++; >>> + entry->next = sa_db->list; >>> + sa_db->list = entry; >>> + count++; >>> + >>> + while (count < entries) { >>> + sa_db_entry_t *new_entry = &sa_db->array[sa_db->index]; >>> + >>> + /* Verify we have a good entry */ >>> + if (MAX_DB <= sa_db->index) >>> + return -1; >>> + >>> + new_entry->alg.cipher = entry->alg.cipher; >>> + new_entry->src_ip = entry->src_ip + count; >>> + new_entry->dst_ip = entry->dst_ip + count; >>> + new_entry->alg.u.cipher = entry->alg.u.cipher; >>> + new_entry->alg.u.auth = entry->alg.u.auth; >>> + new_entry->spi = entry->spi + count; >>> + new_entry->key = entry->key; >>> + new_entry->alg = entry->alg; >>> + /* Add route to the list */ >>> + sa_db->index++; >>> + new_entry->next = sa_db->list; >>> + sa_db->list = new_entry; >>> + count++; >>> + } >>> + >>> + free(local); >>> + return 0; >>> +} >>> + >>> +int create_tun_db_entry(char *input, int entries) >>> +{ >>> + int pos = 0, count = 0; >>> + char *local; >>> + char *str; >>> + char *save; >>> + char *token; >>> + tun_db_entry_t *entry = &tun_db->array[tun_db->index]; >>> + >>> + /* Verify we have a good entry */ >>> + if (MAX_DB <= tun_db->index) >>> + return -1; >>> + >>> + /* Make a local copy */ >>> + local = malloc(strlen(input) + 1); >>> + if (NULL == local) >>> + return -1; >>> + strcpy(local, input); >>> + >>> + /* Setup for using "strtok_r" to search input string */ >>> + str = local; >>> + save = NULL; >>> + >>> + /* Parse tokens separated by ':' */ >>> + while (NULL != (token = strtok_r(str, ":", &save))) { >>> + str = NULL; /* reset str for subsequent strtok_r calls */ >>> + >>> + /* Parse token based on its position */ >>> + switch (pos) { >>> + case 0: >>> + parse_ipv4_string(token, &entry->src_ip, NULL); >>> + break; >>> + case 1: >>> + parse_ipv4_string(token, &entry->dst_ip, NULL); >>> + break; >>> + case 2: >>> + parse_ipv4_string(token, &entry->tun_src_ip, >>> NULL); >>> + break; >>> + case 3: >>> + parse_ipv4_string(token, &entry->tun_dst_ip, >>> NULL); >>> + break; >>> + default: >>> + printf("ERROR: extra token \"%s\" at position >>> %d\n", >>> + token, pos); >>> + break; >>> + } >>> + pos++; >>> + } >>> + >>> + /* Verify we parsed exactly the number of tokens we expected */ >>> + if (4 != pos) { >>> + printf("ERROR: \"%s\" contains %d tokens, expected 4\n", >>> + input, >>> + pos); >>> + free(local); >>> + return -1; >>> + } >>> + >>> + /* Add route to the list */ >>> + tun_db->index++; >>> + entry->next = tun_db->list; >>> + tun_db->list = entry; >>> + count++; >>> + >>> + while (count < entries) { >>> + tun_db_entry_t *new_entry = &tun_db->array[tun_db->index]; >>> + >>> + /* Verify we have a good entry */ >>> + if (MAX_DB <= tun_db->index) >>> + return -1; >>> + >>> + new_entry->src_ip = entry->src_ip + count; >>> + new_entry->dst_ip = entry->dst_ip + count; >>> + new_entry->tun_src_ip = entry->tun_src_ip + count; >>> + new_entry->tun_dst_ip = entry->tun_dst_ip + count; >>> + /* Add route to the list */ >>> + tun_db->index++; >>> + new_entry->next = tun_db->list; >>> + tun_db->list = new_entry; >>> + count++; >>> + } >>> + >>> + free(local); >>> + return 0; >>> +} >>> + >>> +tun_db_entry_t *find_tun_db_entry(uint32_t ip_src, >>> + uint32_t ip_dst) >>> +{ >>> + tun_db_entry_t *entry = NULL; >>> + >>> + /* Scan all entries and return first match */ >>> + for (entry = tun_db->list; NULL != entry; entry = entry->next) { >>> + if (entry->src_ip != ip_src) >>> + continue; >>> + if (entry->dst_ip != ip_dst) >>> + continue; >>> + break; >>> + } >>> + return entry; >>> +} >>> + >>> +void dump_sa_db(void) >>> +{ >>> + sa_db_entry_t *entry; >>> + >>> + printf("\n" >>> + "Security association table (ESP Only)\n" >>> + "--------------------------\n"); >>> + >>> + for (entry = sa_db->list; NULL != entry; entry = entry->next) { >>> + uint32_t idx; >>> + char src_ip_str[MAX_STRING]; >>> + char dst_ip_str[MAX_STRING]; >>> + uint8_t *p = entry->key.data; >>> + >>> + if (entry->alg.cipher) { >>> + printf(" %s %s %s %X %d ", >>> + "cipher", >>> + ipv4_addr_str(src_ip_str, entry->src_ip), >>> + ipv4_addr_str(dst_ip_str, entry->dst_ip), >>> + entry->spi, >>> + (int)entry->alg.u.cipher); >>> + } else { >>> + printf(" %s \t\t\t\t\t %X %d ", >>> + "auth", >>> + entry->spi, >>> + (int)entry->alg.u.auth); >>> + } >>> + /* Brute force key display */ >>> + for (idx = 0; idx < entry->key.length; idx++) >>> + printf("%02X", *p++); >>> + >>> + printf("\n"); >>> + } >>> +} >>> + >>> +sa_db_entry_t *find_sa_db_entry(ip_addr_range_t *src, >>> + ip_addr_range_t *dst, >>> + odp_bool_t cipher) >>> +{ >>> + sa_db_entry_t *entry = NULL; >>> + >>> + /* Scan all entries and return first match */ >>> + for (entry = sa_db->list; NULL != entry; entry = entry->next) { >>> + if (cipher != entry->alg.cipher) >>> + continue; >>> + if (!match_ip_range(entry->src_ip, src)) >>> + continue; >>> + if (!match_ip_range(entry->dst_ip, dst)) >>> + continue; >>> + break; >>> + } >>> + return entry; >>> +} >>> + >>> +void dump_tun_db(void) >>> +{ >>> + tun_db_entry_t *entry; >>> + >>> + printf("\n" >>> + "Tunnel table\n" >>> + "--------------------------\n"); >>> + >>> + for (entry = tun_db->list; NULL != entry; entry = entry->next) { >>> + char src_ip_str[MAX_STRING]; >>> + char dst_ip_str[MAX_STRING]; >>> + char tun_src_ip_str[MAX_STRING]; >>> + char tun_dst_ip_str[MAX_STRING]; >>> + >>> + printf(" %s:%s %s:%s ", >>> + ipv4_addr_str(src_ip_str, entry->src_ip), >>> + ipv4_addr_str(dst_ip_str, entry->dst_ip), >>> + ipv4_addr_str(tun_src_ip_str, entry->tun_src_ip), >>> + ipv4_addr_str(tun_dst_ip_str, entry->tun_dst_ip) >>> + ); >>> + >>> + printf("\n"); >>> + } >>> +} >>> diff --git a/example/ipsec_offload/odp_ipsec_offload_sa_db.h >>> b/example/ipsec_offload/odp_ipsec_offload_sa_db.h >>> new file mode 100644 >>> index 0000000..02b49d4 >>> --- /dev/null >>> +++ b/example/ipsec_offload/odp_ipsec_offload_sa_db.h >>> @@ -0,0 +1,126 @@ >>> +/* Copyright (c) 2017, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> +#ifndef ODP_IPSEC_SA_DB_H_ >>> +#define ODP_IPSEC_SA_DB_H_ >>> + >>> +#ifdef __cplusplus >>> +extern "C" { >>> +#endif >>> + >>> +#include <odp_ipsec_offload_misc.h> >>> + >>> +/** >>> + * Security Association (SA) data base entry >>> + */ >>> +typedef struct sa_db_entry_s { >>> + struct sa_db_entry_s *next; /**< Next entry on list */ >>> + uint32_t src_ip; /**< Source IPv4 address */ >>> + uint32_t dst_ip; /**< Desitnation IPv4 address */ >>> + uint32_t spi; /**< Security Parameter Index */ >>> + ipsec_alg_t alg; /**< Cipher/auth algorithm */ >>> + ipsec_key_t key; /**< Cipher/auth key */ >>> + odp_ipsec_mode_t mode; /**< SA mode - transport/tun */ >>> +} sa_db_entry_t; >>> + >>> +/** >>> + * Security Association (SA) data base global structure >>> + */ >>> +typedef struct sa_db_s { >>> + uint32_t index; /**< Index of next available >>> entry */ >>> + sa_db_entry_t *list; /**< List of active entries */ >>> + sa_db_entry_t array[MAX_DB]; /**< Entry storage */ >>> +} sa_db_t; >>> + >>> +/** Initialize SA database global control structure */ >>> +void init_sa_db(void); >>> + >>> +/** >>> + * Create an SA DB entry >>> + * >>> + * String is of the format "SrcIP:DstIP:Alg:SPI:Key" >>> + * >>> + * @param input Pointer to string describing SA >>> + * @param cipher TRUE if cipher else FALSE for auth >>> + * @param entries number of entries >>> + * >>> + * @return 0 if successful else -1 >>> + */ >>> +int create_sa_db_entry(char *input, odp_bool_t cipher, int entries); >>> +/** >>> + * Display the SA DB >>> + */ >>> +void dump_sa_db(void); >>> + >>> +/** >>> + * Find a matching SA DB entry >>> + * >>> + * @param src Pointer to source subnet/range >>> + * @param dst Pointer to destination subnet/range >>> + * @param cipher TRUE if cipher else FALSE for auth >>> + * >>> + * @return pointer to SA DB entry else NULL >>> + */ >>> +sa_db_entry_t *find_sa_db_entry(ip_addr_range_t *src, >>> + ip_addr_range_t *dst, >>> + odp_bool_t cipher); >>> + >>> +/** >>> + * Tunnel entry >>> + */ >>> +typedef struct tun_db_entry_s { >>> + struct tun_db_entry_s *next; >>> + uint32_t src_ip; /**< Inner Source IPv4 address */ >>> + uint32_t dst_ip; /**< Inner Destination IPv4 >>> address */ >>> + uint32_t tun_src_ip; /**< Tunnel Source IPv4 address */ >>> + uint32_t tun_dst_ip; /**< Tunnel Source IPv4 address */ >>> +} tun_db_entry_t; >>> + >>> +/** >>> + * Tunnel database >>> + */ >>> +typedef struct tun_db_s { >>> + uint32_t index; /**< Index of next available >>> entry */ >>> + tun_db_entry_t *list; /**< List of active entries */ >>> + tun_db_entry_t array[MAX_DB]; /**< Entry storage */ >>> +} tun_db_t; >>> + >>> +/** Initialize tun database global control structure */ >>> +void init_tun_db(void); >>> + >>> +/** >>> + * Create an tunnel DB entry >>> + * >>> + * String is of the format "SrcIP:DstIP:TunSrcIp:TunDstIp" >>> + * >>> + * @param input Pointer to string describing tun >>> + * @param entries number of entries >>> + * >>> + * @return 0 if successful else -1 >>> + */ >>> +int create_tun_db_entry(char *input, int entries); >>> + >>> +/** >>> + * Display the tun DB >>> + */ >>> +void dump_tun_db(void); >>> + >>> +/** >>> + * Find a matching tun DB entry >>> + * >>> + * @param ip_src Inner source IP address >>> + * @param ip_dst Inner destination IP address >>> + * >>> + * @return pointer to tun DB entry else NULL >>> + */ >>> +tun_db_entry_t *find_tun_db_entry(uint32_t ip_src, >>> + uint32_t ip_dst); >>> + >>> +#ifdef __cplusplus >>> +} >>> +#endif >>> + >>> +#endif >>> diff --git a/example/ipsec_offload/odp_ipsec_offload_sp_db.c >>> b/example/ipsec_offload/odp_ipsec_offload_sp_db.c >>> new file mode 100644 >>> index 0000000..9fcaaaa >>> --- /dev/null >>> +++ b/example/ipsec_offload/odp_ipsec_offload_sp_db.c >>> @@ -0,0 +1,166 @@ >>> +/* Copyright (c) 2017, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> +/* enable strtok */ >>> +#define _POSIX_C_SOURCE 200112L >>> + >>> +#include <stdlib.h> >>> +#include <string.h> >>> + >>> +#include <example_debug.h> >>> + >>> +#include <odp.h> >>> + >>> +#include <odp_ipsec_offload_sp_db.h> >>> + >>> +/** Global pointer to sp db */ >>> +sp_db_t *sp_db; >>> + >>> +void init_sp_db(void) >>> +{ >>> + odp_shm_t shm; >>> + >>> + shm = odp_shm_reserve("shm_sp_db", >>> + sizeof(sp_db_t), >>> + ODP_CACHE_LINE_SIZE, >>> + 0); >>> + >>> + sp_db = odp_shm_addr(shm); >>> + >>> + if (sp_db == NULL) { >>> + EXAMPLE_ABORT("Error: shared mem alloc failed.\n"); >>> + } >>> + memset(sp_db, 0, sizeof(*sp_db)); >>> +} >>> + >>> +int create_sp_db_entry(char *input, int entries) >>> +{ >>> + int pos = 0, count = 0; >>> + char *local; >>> + char *str; >>> + char *save; >>> + char *token; >>> + sp_db_entry_t *entry = &sp_db->array[sp_db->index]; >>> + >>> + /* Verify we have a good entry */ >>> + if (MAX_DB <= sp_db->index) >>> + return -1; >>> + >>> + /* Make a local copy */ >>> + local = malloc(strlen(input) + 1); >>> + if (NULL == local) >>> + return -1; >>> + strcpy(local, input); >>> + >>> + /* Setup for using "strtok_r" to search input string */ >>> + str = local; >>> + save = NULL; >>> + >>> + /* Parse tokens separated by ':' */ >>> + while (NULL != (token = strtok_r(str, ":", &save))) { >>> + str = NULL; /* reset str for subsequent strtok_r calls */ >>> + >>> + /* Parse token based on its position */ >>> + switch (pos) { >>> + case 0: >>> + parse_ipv4_string(token, >>> + &entry->src_subnet.addr, >>> + &entry->src_subnet.mask); >>> + break; >>> + case 1: >>> + parse_ipv4_string(token, >>> + &entry->dst_subnet.addr, >>> + &entry->dst_subnet.mask); >>> + break; >>> + case 2: >>> + if (0 == strcmp(token, "in")) >>> + entry->input = TRUE; >>> + else >>> + entry->input = FALSE; >>> + break; >>> + case 3: >>> + if (0 == strcmp(token, "esp")) { >>> + entry->esp = TRUE; >>> + } else if (0 == strcmp(token, "ah")) { >>> + entry->ah = TRUE; >>> + } else if (0 == strcmp(token, "both")) { >>> + entry->esp = TRUE; >>> + entry->ah = TRUE; >>> + } >>> + break; >>> + default: >>> + printf("ERROR: extra token \"%s\" at position >>> %d\n", >>> + token, pos); >>> + break; >>> + } >>> + >>> + /* Advance to next position */ >>> + pos++; >>> + } >>> + >>> + /* Verify we parsed exactly the number of tokens we expected */ >>> + if (4 != pos) { >>> + printf("ERROR: \"%s\" contains %d tokens, expected 4\n", >>> + input, >>> + pos); >>> + free(local); >>> + return -1; >>> + } >>> + >>> + /* Add route to the list */ >>> + sp_db->index++; >>> + entry->next = sp_db->list; >>> + sp_db->list = entry; >>> + count++; >>> + while (count < entries) { >>> + sp_db_entry_t *new_entry = &sp_db->array[sp_db->index]; >>> + >>> + /* Verify we have a good entry */ >>> + if (MAX_DB <= sp_db->index) >>> + return -1; >>> + >>> + new_entry->src_subnet.addr = entry->src_subnet.addr + >>> count; >>> + new_entry->src_subnet.mask = entry->src_subnet.mask; >>> + new_entry->dst_subnet.addr = entry->dst_subnet.addr + >>> count; >>> + new_entry->dst_subnet.mask = entry->dst_subnet.mask; >>> + new_entry->input = entry->input; >>> + new_entry->esp = entry->esp; >>> + new_entry->ah = entry->ah; >>> + /* Add route to the list */ >>> + sp_db->index++; >>> + new_entry->next = sp_db->list; >>> + sp_db->list = new_entry; >>> + count++; >>> + } >>> + >>> + free(local); >>> + return 0; >>> +} >>> + >>> +void dump_sp_db_entry(sp_db_entry_t *entry) >>> +{ >>> + char src_subnet_str[MAX_STRING]; >>> + char dst_subnet_str[MAX_STRING]; >>> + >>> + printf(" %s %s %s %s:%s\n", >>> + ipv4_subnet_str(src_subnet_str, &entry->src_subnet), >>> + ipv4_subnet_str(dst_subnet_str, &entry->dst_subnet), >>> + entry->input ? "in" : "out", >>> + entry->esp ? "esp" : "none", >>> + entry->ah ? "ah" : "none"); >>> +} >>> + >>> +void dump_sp_db(void) >>> +{ >>> + sp_db_entry_t *entry; >>> + >>> + printf("\n" >>> + "Security policy table\n" >>> + "---------------------\n"); >>> + >>> + for (entry = sp_db->list; NULL != entry; entry = entry->next) >>> + dump_sp_db_entry(entry); >>> +} >>> diff --git a/example/ipsec_offload/odp_ipsec_offload_sp_db.h >>> b/example/ipsec_offload/odp_ipsec_offload_sp_db.h >>> new file mode 100644 >>> index 0000000..bc6ba1a >>> --- /dev/null >>> +++ b/example/ipsec_offload/odp_ipsec_offload_sp_db.h >>> @@ -0,0 +1,72 @@ >>> +/* Copyright (c) 2017, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> +#ifndef ODP_IPSEC_SP_DB_H_ >>> +#define ODP_IPSEC_SP_DB_H_ >>> + >>> +#ifdef __cplusplus >>> +extern "C" { >>> +#endif >>> + >>> +#include <odp_ipsec_offload_misc.h> >>> + >>> +/** >>> + * Security Policy (SP) data base entry >>> + */ >>> +typedef struct sp_db_entry_s { >>> + struct sp_db_entry_s *next; /**< Next entry on list */ >>> + ip_addr_range_t src_subnet; /**< Source IPv4 subnet/range >>> */ >>> + ip_addr_range_t dst_subnet; /**< Destination IPv4 >>> subnet/range */ >>> + odp_bool_t input; /**< Direction when applied */ >>> + odp_bool_t esp; /**< Enable cipher (ESP) */ >>> + odp_bool_t ah; /**< Enable authentication >>> (AH) */ >>> +} sp_db_entry_t; >>> + >>> +/** >>> + * Security Policy (SP) data base global structure >>> + */ >>> +typedef struct sp_db_s { >>> + uint32_t index; /**< Index of next available >>> entry */ >>> + sp_db_entry_t *list; /**< List of active entries */ >>> + sp_db_entry_t array[MAX_DB]; /**< Entry storage */ >>> +} sp_db_t; >>> + >>> +/** Global pointer to sp db */ >>> +extern sp_db_t *sp_db; >>> + >>> +/** Initialize SP database global control structure */ >>> +void init_sp_db(void); >>> + >>> +/** >>> + * Create an SP DB entry >>> + * >>> + * String is of the format "SrcSubNet:DstSubNet:(in|out):(ah|esp|both)" >>> + * >>> + * @param input Pointer to string describing SP >>> + * >>> + * @param entries number of entries >>> + * >>> + * @return 0 if successful else -1 >>> + */ >>> +int create_sp_db_entry(char *input, int entries); >>> + >>> +/** >>> + * Display one SP DB entry >>> + * >>> + * @param entry Pointer to entry to display >>> + */ >>> +void dump_sp_db_entry(sp_db_entry_t *entry); >>> + >>> +/** >>> + * Display the SP DB >>> + */ >>> +void dump_sp_db(void); >>> + >>> +#ifdef __cplusplus >>> +} >>> +#endif >>> + >>> +#endif >>> diff --git a/example/ipsec_offload/run_left >>> b/example/ipsec_offload/run_left >>> new file mode 100644 >>> index 0000000..58986a2 >>> --- /dev/null >>> +++ b/example/ipsec_offload/run_left >>> @@ -0,0 +1,14 @@ >>> +#!/bin/bash >>> +# >>> + >>> +./odp_ipsec_offload -f 64 -i dpni.1,dpni.2 \ >>> +-r 192.168.111.2/32:dpni.1:00.10.94.00.00.02 \ >>> +-r 192.168.222.2/32:dpni.2:00.00.00.00.00.1 \ >>> +-p 192.168.111.2:192.168.222.2:out:both \ >>> +-e 192.168.111.2:192.168.222.2:aes:201:656c8523255ccc23a66c1917aa0cf309 >>> \ >>> +-a 192.168.111.2:192.168.222.2:sha256:201:a731649644c5dee92cbd9 >>> c2e7e188ee6aa0cf309a731649644c5dee92cbd9c2e \ >>> +-t 192.168.111.2:192.168.222.2:192.168.100.1:192.168.200.1 \ >>> +-p 192.168.222.2:192.168.111.2:in:both \ >>> +-e 192.168.222.2:192.168.111.2:aes:201:656c8523255ccc23a66c1917aa0cf309 >>> \ >>> +-a 192.168.222.2:192.168.111.2:sha256:201:a731649644c5dee92cbd9 >>> c2e7e188ee6aa0cf309a731649644c5dee92cbd9c2e \ >>> +-t 192.168.222.2:192.168.111.2:192.168.200.1:192.168.100.1 & >>> diff --git a/example/ipsec_offload/run_right >>> b/example/ipsec_offload/run_right >>> new file mode 100644 >>> index 0000000..d49aa19 >>> --- /dev/null >>> +++ b/example/ipsec_offload/run_right >>> @@ -0,0 +1,14 @@ >>> +#!/bin/bash >>> +# >>> + >>> +./odp_ipsec_offload -f 64 -i dpni.1,dpni.2 \ >>> +-r 192.168.111.2/32:dpni.1:00.00.00.00.00.2 \ >>> +-r 192.168.222.2/32:dpni.2:00.10.94.00.00.03 \ >>> +-p 192.168.111.2:192.168.222.2:in:both \ >>> +-e 192.168.111.2:192.168.222.2:aes:201:656c8523255ccc23a66c1917aa0cf309 >>> \ >>> +-a 192.168.111.2:192.168.222.2:sha256:201:a731649644c5dee92cbd9 >>> c2e7e188ee6aa0cf309a731649644c5dee92cbd9c2e \ >>> +-t 192.168.111.2:192.168.222.2:192.168.100.1:192.168.200.1 \ >>> +-p 192.168.222.2:192.168.111.2:out:both \ >>> +-e 192.168.222.2:192.168.111.2:aes:201:656c8523255ccc23a66c1917aa0cf309 >>> \ >>> +-a 192.168.222.2:192.168.111.2:sha256:201:a731649644c5dee92cbd9 >>> c2e7e188ee6aa0cf309a731649644c5dee92cbd9c2e \ >>> +-t 192.168.222.2:192.168.111.2:192.168.200.1:192.168.100.1 & >>> -- >>> 2.9.3 >>> >>> >>