From aa97dd1ce910b839fed46ad55d1e70e403f5a930 Mon Sep 17 00:00:00 2001 From: Konstantin Ananyev Date: Tue, 21 Feb 2017 18:12:20 +0000 Subject: Introduce first version of TCP code. Supported functionality: - open/close - listen/accept/connect - send/recv In order to achieve that libtle_udp library was reworked into libtle_l4p library that supports both TCP and UDP protocols. New libtle_timer library was introduced (thanks to Cisco guys and Dave Barach for sharing their timer code with us). Sample application was also reworked significantly to support both TCP and UDP traffic handling. New UT were introduced. Change-Id: I806b05011f521e89b58db403cfdd484a37beb775 Signed-off-by: Mohammad Abdul Awal Signed-off-by: Karol Latecki Signed-off-by: Daniel Mrzyglod Signed-off-by: Konstantin Ananyev --- examples/udpfwd/Makefile | 46 - examples/udpfwd/README | 141 --- examples/udpfwd/be.cfg | 5 - examples/udpfwd/dpdk_version.h | 33 - examples/udpfwd/fe.cfg | 24 - examples/udpfwd/fwdtbl.h | 117 -- examples/udpfwd/gen_fe_cfg.py | 199 ---- examples/udpfwd/main.c | 2134 ------------------------------------ examples/udpfwd/main_dpdk_legacy.h | 176 --- examples/udpfwd/netbe.h | 266 ----- examples/udpfwd/parse.c | 638 ----------- examples/udpfwd/parse.h | 81 -- examples/udpfwd/pkt.c | 509 --------- examples/udpfwd/pkt_dpdk_legacy.h | 145 --- 14 files changed, 4514 deletions(-) delete mode 100644 examples/udpfwd/Makefile delete mode 100644 examples/udpfwd/README delete mode 100644 examples/udpfwd/be.cfg delete mode 100644 examples/udpfwd/dpdk_version.h delete mode 100644 examples/udpfwd/fe.cfg delete mode 100644 examples/udpfwd/fwdtbl.h delete mode 100755 examples/udpfwd/gen_fe_cfg.py delete mode 100644 examples/udpfwd/main.c delete mode 100644 examples/udpfwd/main_dpdk_legacy.h delete mode 100644 examples/udpfwd/netbe.h delete mode 100644 examples/udpfwd/parse.c delete mode 100644 examples/udpfwd/parse.h delete mode 100644 examples/udpfwd/pkt.c delete mode 100644 examples/udpfwd/pkt_dpdk_legacy.h (limited to 'examples/udpfwd') diff --git a/examples/udpfwd/Makefile b/examples/udpfwd/Makefile deleted file mode 100644 index fae1c34..0000000 --- a/examples/udpfwd/Makefile +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) 2016 Intel Corporation. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -ifeq ($(RTE_SDK),) -$(error "Please define RTE_SDK environment variable") -endif - -ifeq ($(RTE_TARGET),) -$(error "Please define RTE_TARGET environment variable") -endif - -ifeq ($(TLDK_ROOT),) -$(error "Please define TLDK_ROOT environment variable") -endif - -include $(RTE_SDK)/mk/rte.vars.mk - -# binary name -APP = udpfwd - -# all source are stored in SRCS-y -SRCS-y += parse.c -SRCS-y += pkt.c -SRCS-y += main.c - -CFLAGS += $(WERROR_FLAGS) -CFLAGS += -I$(RTE_OUTPUT)/include - -LDLIBS += -L$(RTE_OUTPUT)/lib -LDLIBS += -ltle_udp - -EXTRA_CFLAGS += -O3 -CFLAGS_parse.o += -D_GNU_SOURCE -CFLAGS_main.o += -D_GNU_SOURCE - -include $(TLDK_ROOT)/mk/tle.app.mk diff --git a/examples/udpfwd/README b/examples/udpfwd/README deleted file mode 100644 index 91b6e76..0000000 --- a/examples/udpfwd/README +++ /dev/null @@ -1,141 +0,0 @@ -Introduction -============ - -udpfwd is a sample application to demonstrate and test libtle_udp. -Depending on configuration it can do simple send/recv or both over -opened udp streams. Also it implements ability to do UDP datagram -forwarding between different streams, so it is possible to use that -application as some sort of 'UDP proxy'. -The application can reassemble input fragmented IP packets, -and fragment outgoing IP packets (if destination MTU is less then packet size). -To build and run the application DPDK and TLDK libraries are required. - -Logically the application is divided into two parts: - -- Back End (BE) -BE is responsible for: - - RX over DPDK ports and feed them into UDP TLDK context(s) - (via tle_udp_rx_bulk). - - retrieve packets ready to be send out from UDP TLDK context(s) - and TX them over destined DPDK port. -Multiple RX/TX queues per port are supported by RSS. Right now the number of -TX is same as the number of RX queue. -Each BE lcore can serve multiple DPDK ports, TLDK UDP contexts. - -- Front End (FE) -FE responsibility is to open configured UDP streams and perform -send/recv over them. These streams can belong to different UDP contexts. - -Right now each lcore can act as BE and/or FE. - -Usage -===== - -udpfwd -- \ - -P | --promisc /* promiscuous mode enabled. */ \ - -R | --rbufs /* max recv buffers per stream. */ \ - -S | --sbufs /* max send buffers per stream. */ \ - -s | --streams /* streams to open per context. */ \ - -b | --becfg /* backend configuration file. */ \ - -f | --fecfg /* frontend configuration file. */ \ - ... - -port_params: port=,lcore=[-],\ -[rx_offload=,tx_offload=,mtu=,ipv4=,ipv6=] - -port_params are used to configure the particular DPDK device (rte_ethdev port), -and specify BE lcore that will do RX/TX from/to the device and manage -BE part of corresponding UDP context. Multiple BE lcore can be specified. - -port - DPDK port id (multiple queues are supported when multiple lcore - is specified for a port). -lcore - EAL lcore id to do IO over that port (rx_burst/tx_burst). - several ports can be managed by the same lcore, and same port can - belong to more than one lcore. -rx_offload - RX HW offload capabilities to enable/use on this port. - (bitmask of DEV_RX_OFFLOAD_* values). -tx_offload - TX HW offload capabilities to enable/use on this port. - (bitmask of DEV_TX_OFFLOAD_* values). -mtu - MTU to be used on that port - ( = UDP data size + L2/L3/L4 headers sizes, default=1514). -ipv4 - ipv4 address to assign to that port. -ipv6 - ipv6 address to assign to that port. - -At least one of ipv4/ipv6 values have to be specified for each port. - -As an example: -udpfwd --lcores='3,6,8' -w 01:00.0 -- \ ---promisc --rbufs 0x1000 --sbufs 0x1000 --streams 0x100 \ ---fecfg ./fe.cfg --becfg ./be.cfg \ -port=0,lcore=6,lcore=8,rx_offload=0xf,tx_offload=0,\ -ipv4=192.168.1.233,ipv6=2001:4860:b002::28 - -Will create TLDK UDP context on lcore=6 and lcore=8 (BE lcore) to manage -DPDK port 0. Will assign IPv4 address 192.168.1.233 and IPv6 address -2001:4860:b002::28 to that port. -The following supported by DPDK RX HW offloads: - DEV_RX_OFFLOAD_VLAN_STRIP, - DEV_RX_OFFLOAD_IPV4_CKSUM, - DEV_RX_OFFLOAD_UDP_CKSUM, - DEV_RX_OFFLOAD_TCP_CKSUM -will be enabled on that port. -No HW TX offloads will be enabled. - -If multiple lcore is specified per DPDK port, the following RSS hash will -be enabled on that port: - ETH_RSS_UDP - - -Fornt-End (FE) and Back-End (BE) configuration files format: ------------------------------------------------------------- - - each record on a separate line. - - lines started with '#' are treated as comments. - - empty lines (containing whitespace chars only) are ignored. - - kvargs style format for each record. - - each FE record correspond to at least one stream to be opened - (could be multiple streams in case of op="fwd"). - - each BE record define a ipv4/ipv6 destination. - -FE config record format: ------------------------- - -lcore=,op=<"rx|tx|echo|fwd">,\ -laddr=,lport=,raddr=,rport=,\ -[txlen=,fwladdr=,fwlport=,fwraddr=,fwrport=,\ -belcore=] - -lcore - EAL lcore to manage that stream(s) in the FE. -op - operation to perform on that stream: - "rx" - do receive only on that stream. - "tx" - do send only on that stream. - "echo" - mimic recvfrom(..., &addr);sendto(..., &addr); - on that stream. - "fwd" - forward packets between streams. -laddr - local address for the stream to open. -lport - local port for the stream to open. -raddr - remote address for the stream to open. -rport - remote port for the stream to open. -txlen - data length to send with each packet ("tx" mode only). -fwladdr - local address for the forwarding stream(s) to open - ("fwd mode only). -fwlport - local port for the forwarding stream(s) to open - ("fwd mode only). -fwraddr - remote address for the forwarding stream(s) to open - ("fwd mode only). -fwrport - remote port for the forwarding stream(s) to open - ("fwd mode only). -belcore - EAL lcore to manage that stream(s) in the BE. - -Refer to fe.cfg for an example. - -BE config record format: ------------------------- - -port=,addr=,masklen=,mac= - -port - port number to be used to send packets to the destination. -addr - destionation network address. -masklen - desitantion network prefix length. -mac - destination ethernet address. - -Refer to fe.cfg for an example. diff --git a/examples/udpfwd/be.cfg b/examples/udpfwd/be.cfg deleted file mode 100644 index 5c1d173..0000000 --- a/examples/udpfwd/be.cfg +++ /dev/null @@ -1,5 +0,0 @@ -# -# udpfwd BE cconfig file exaple -# -port=0,masklen=16,addr=192.168.0.0,mac=01:de:ad:be:ef:01 -port=0,addr=2001:4860:b002::,masklen=64,mac=01:de:ad:be:ef:01 diff --git a/examples/udpfwd/dpdk_version.h b/examples/udpfwd/dpdk_version.h deleted file mode 100644 index 4f6bdfb..0000000 --- a/examples/udpfwd/dpdk_version.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2016 Intel Corporation. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef DPDK_VERSION_H_ -#define DPDK_VERSION_H_ - -#include - -#ifdef RTE_VER_MAJOR -#if RTE_VER_MAJOR >= 16 && RTE_VER_MINOR >= 4 -#define DPDK_VERSION_GE_1604 -#endif -#elif defined(RTE_VER_YEAR) -#if RTE_VERSION >= RTE_VERSION_NUM(16,4,0,0) -#define DPDK_VERSION_GE_1604 -#endif -#else -#error "RTE_VER_MAJOR and RTE_VER_YEAR are undefined!" -#endif - -#endif /* DPDK_VERSION_H_ */ diff --git a/examples/udpfwd/fe.cfg b/examples/udpfwd/fe.cfg deleted file mode 100644 index 2706323..0000000 --- a/examples/udpfwd/fe.cfg +++ /dev/null @@ -1,24 +0,0 @@ -# -# udpfwd FE config file example -# - -# open IPv4 stream with local_addr=192.168.1.233:32768, -# and remote_addr as wildcard (any remote addressi/port allowed). -# use it echo mode - for any received packet - send it back to the source -lcore=3,op=echo,laddr=192.168.1.233,lport=0x8000,raddr=0.0.0.0,rport=0 - -# open IPv4 stream with specified local/remote address/port and -# do send only over that stream. -lcore=3,op=tx,laddr=192.168.1.233,lport=0x8001,raddr=192.168.1.56,rport=0x200,txlen=72 - -# open IPv6 stream with specified local port (512) probably over multiple -# eth ports, and do recv only over that stream. -lcore=3,op=rx,laddr=::,lport=0x200,raddr=::,rport=0,txlen=72 - -# fwd mode example. -# open IPv4 stream on local port 11211 (memcached) over all possible ports. -# for each new flow, sort of tunnel will be created, i.e: -# new stream will be opend to communcate with forwarding remote address, -# so all packets with will be forwarded to -# and visa-versa. -lcore=3,op=fwd,laddr=0.0.0.0,lport=11211,raddr=0.0.0.0,rport=0,fwladdr=::,fwlport=0,fwraddr=2001:4860:b002::56,fwrport=11211 diff --git a/examples/udpfwd/fwdtbl.h b/examples/udpfwd/fwdtbl.h deleted file mode 100644 index 1c4265e..0000000 --- a/examples/udpfwd/fwdtbl.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2016 Intel Corporation. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __FWDTBL_H__ -#define __FWDTBL_H__ - -struct fwd4_key { - uint32_t port; - struct in_addr addr; -} __attribute__((__packed__)); - -struct fwd6_key { - uint32_t port; - struct in6_addr addr; -} __attribute__((__packed__)); - -union fwd_key { - struct fwd4_key k4; - struct fwd6_key k6; -}; - -static struct rte_hash * -fwd_tbl_key_prep(const struct netfe_lcore *fe, uint16_t family, - const struct sockaddr *sa, union fwd_key *key) -{ - struct rte_hash *h; - const struct sockaddr_in *sin4; - const struct sockaddr_in6 *sin6; - - if (family == AF_INET) { - h = fe->fw4h; - sin4 = (const struct sockaddr_in *)sa; - key->k4.port = sin4->sin_port; - key->k4.addr = sin4->sin_addr; - } else { - h = fe->fw6h; - sin6 = (const struct sockaddr_in6 *)sa; - key->k6.port = sin6->sin6_port; - key->k6.addr = sin6->sin6_addr; - } - - return h; -} - -static int -fwd_tbl_add(struct netfe_lcore *fe, uint16_t family, const struct sockaddr *sa, - struct netfe_stream *data) -{ - int32_t rc; - struct rte_hash *h; - union fwd_key key; - - h = fwd_tbl_key_prep(fe, family, sa, &key); - rc = rte_hash_add_key_data(h, &key, data); - return rc; -} - -static struct netfe_stream * -fwd_tbl_lkp(struct netfe_lcore *fe, uint16_t family, const struct sockaddr *sa) -{ - int rc; - void *d; - struct rte_hash *h; - union fwd_key key; - - h = fwd_tbl_key_prep(fe, family, sa, &key); - rc = rte_hash_lookup_data(h, &key, &d); - if (rc < 0) - d = NULL; - return d; -} - -static int -fwd_tbl_init(struct netfe_lcore *fe, uint16_t family, uint32_t lcore) -{ - int32_t rc; - struct rte_hash **h; - struct rte_hash_parameters hprm; - char buf[RTE_HASH_NAMESIZE]; - - if (family == AF_INET) { - snprintf(buf, sizeof(buf), "fwd4tbl@%u", lcore); - h = &fe->fw4h; - hprm.key_len = sizeof(struct fwd4_key); - } else { - snprintf(buf, sizeof(buf), "fwd6tbl@%u", lcore); - h = &fe->fw6h; - hprm.key_len = sizeof(struct fwd6_key); - } - - hprm.name = buf; - hprm.entries = RTE_MAX(2 * fe->snum, 0x10U); - hprm.socket_id = rte_lcore_to_socket_id(lcore); - hprm.hash_func = NULL; - hprm.hash_func_init_val = 0; - - *h = rte_hash_create(&hprm); - if (*h == NULL) - rc = (rte_errno != 0) ? -rte_errno : -ENOMEM; - else - rc = 0; - return rc; -} - -#endif /* __FWDTBL_H__ */ diff --git a/examples/udpfwd/gen_fe_cfg.py b/examples/udpfwd/gen_fe_cfg.py deleted file mode 100755 index dbb500b..0000000 --- a/examples/udpfwd/gen_fe_cfg.py +++ /dev/null @@ -1,199 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) 2016 Intel Corporation. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# -# generate FE config script -# - -import sys, optparse, math - -def print_usage (): - print "Usage: " + sys.argv[0] + " [-f fe_lcore_list] [-b be_lcore_list]" - print " [-p start_port] [-n number_of_streams]" - print " [-m mode] [-q local_address] [-r remote_address]" - print " [-s fwd_local_address] [-t fwd_remote_address]" - print " [-l txlen] [-4/-6] [-H]" - print - print "Options" - print " -f, --fe_lcore_list: list of lcores used for FE. Multiple " \ - "lcores are comma-separated, within double quote" - print " -b, --be_lcore_list: list of lcores used for BE. Multiple " \ - "lcores are comma-separated, within double quote" - print " -p, --start_port: starting UDP port number" - print " -n, --number_of_streams: number of streams to be generated" - print " -m, --mode: mode of the application. [echo, rx, tx, fwd]" - print " -q, --local_address: local address of the stream" - print " -r, --remote_address: remote address of the stream" - print " -s, --fwd_local_address: forwarding local address of the stream" - print " -t, --fwd_remote_address: forwarding remote address of the " \ - "stream" - print " -l, --txlen: transmission length for rx/tx mode" - print " -H: if port number to printed in hex format" - print " -4/-6: if default ip addresses to be printed in ipv4/ipv6 format" - -def align_power_of_2(x): - return 2**(x-1).bit_length() - -def print_stream(mode, la, ra, fwd_la, fwd_ra, lcore, belcore, lport, - fwrport, txlen): - if support_hex != 0: - lport_str = str(format(lport, '#x')) - fwrport_str = str(format(fwrport, '#x')) - else: - lport_str = str(lport) - fwrport_str = str(fwrport) - - stream = "lcore=" + str(lcore) + ",belcore=" + str(belcore) + ",op=" + mode - stream += ",laddr=" + la + ",lport=" + lport_str - stream += ",raddr=" + ra + ",rport=0" - - if mode == 'fwd': - stream += ",fwladdr=" + fwd_la + ",fwlport=0,fwraddr=" + fwd_ra - stream += ",fwrport=" + fwrport_str - - if mode == 'rx' or mode == 'tx': - stream += ",txlen=" + str(txlen) - - print stream - -parser = optparse.OptionParser() -parser.add_option("-b", "--be_lcore_list", dest = "be_lcore_list", - help = "BE lcore lists.") -parser.add_option("-f", "--fe_lcore_list", dest = "fe_lcore_list", - help = "FE lcore lists.") -parser.add_option("-p", "--start_port", dest = "start_port", - help = "start port.") -parser.add_option("-n", "--number_of_streams", dest = "number_of_streams", - help = "number of streams.") -parser.add_option("-m", "--mode", dest = "mode", - help = "mode (op, rx, tx, fwd).") -parser.add_option("-q", "--local_address", dest = "local_address", - help = "local_address.") -parser.add_option("-r", "--remote_address", dest = "remote_address", - help = "remote_address.") -parser.add_option("-s", "--fwd_local_address", dest = "fwd_local_address", - help = "fwd_local_address.") -parser.add_option("-t", "--fwd_remote_address", dest = "fwd_remote_address", - help = "fwd_remote_address.") -parser.add_option("-l", "--txlen", dest = "txlen", help = "txlen.") -parser.add_option("-4", action = "store_false", dest = "ipv6", - help = "IPv4/IPv6") -parser.add_option("-6", action = "store_true", dest = "ipv6", - help = "IPv4/IPv6") -parser.add_option("-H", action = "store_true", dest = "support_hex", - help = "print ports in hexa format") - -(options, args) = parser.parse_args() - -if len(sys.argv) == 1: - print - print_usage() - print - sys.exit() - -supported_modes = ['echo', 'rx', 'tx', 'fwd'] -support_hex = 0 -txlen = 72 - -if options.ipv6 == True: - la = '::' - ra = '::' - fwd_la = '::' - fwd_ra = '::' -else: - la = '0.0.0.0' - ra = '0.0.0.0' - fwd_la = '0.0.0.0' - fwd_ra = '0.0.0.0' - -if options.support_hex == True: - support_hex = 1 - -if options.txlen != None: - txlen = options.txlen - -if options.fe_lcore_list != None: - felcore_list = list(map(int, options.fe_lcore_list.split(","))) - felcore_list.sort() -else: - felcore_list = [] - -if options.be_lcore_list != None: - belcore_list = list(map(int, options.be_lcore_list.split(","))) - belcore_list.sort() -else: - print "default BE lcore list = [ 1 ]" - belcore_list = [1] - -if options.mode != None: - mode = options.mode - if mode not in supported_modes: - print "Supported modes: " + str(supported_modes) - print "Provided mode \"" + mode + "\" is not supported. Terminating..." - sys.exit() -else: - print "default mode = echo" - mode = "echo" - -if options.start_port != None: - start_port = int(options.start_port) -else: - print "default start_port = 32768" - start_port = 32768 - -if options.number_of_streams != None: - number_of_streams = int(options.number_of_streams) -else: - print "default number_of_streams = 1" - number_of_streams = 1 - -fwd_start_port = 53248 - -if options.local_address != None: - la = options.local_address - -if options.remote_address != None: - ra = options.remote_address - -if options.fwd_local_address != None: - fwd_la = options.fwd_local_address - -if options.fwd_remote_address != None: - fwd_ra = options.fwd_remote_address - -belcore_count = len(belcore_list) -align_belcore_count = align_power_of_2(belcore_count) -nb_bits = int(math.log(align_belcore_count, 2)) - -felcore_count = len(felcore_list) -if felcore_count != 0: - if number_of_streams % felcore_count == 0: - nb_stream_per_flc = number_of_streams / felcore_count - else: - nb_stream_per_flc = (number_of_streams / felcore_count) + 1 - -for i in range(start_port, start_port + number_of_streams): - k = i - start_port - align_belcore_count = align_power_of_2(belcore_count) - blc_indx = (i % align_belcore_count) % belcore_count - belcore = belcore_list[blc_indx] - if felcore_count != 0: - flc_indx = k / nb_stream_per_flc - felcore = felcore_list[flc_indx] - else: - felcore = belcore - - print_stream(mode, la, ra, fwd_la, fwd_ra, felcore, belcore, i, - fwd_start_port + k, txlen) diff --git a/examples/udpfwd/main.c b/examples/udpfwd/main.c deleted file mode 100644 index 0463588..0000000 --- a/examples/udpfwd/main.c +++ /dev/null @@ -1,2134 +0,0 @@ -/* - * Copyright (c) 2016 Intel Corporation. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "netbe.h" -#include "parse.h" - -#define MAX_RULES 0x100 -#define MAX_TBL8 0x800 - -#define RX_RING_SIZE 0x400 -#define TX_RING_SIZE 0x800 - -#define MPOOL_CACHE_SIZE 0x100 -#define MPOOL_NB_BUF 0x20000 - -#define FRAG_MBUF_BUF_SIZE (RTE_PKTMBUF_HEADROOM + TLE_UDP_MAX_HDR) -#define FRAG_TTL MS_PER_S -#define FRAG_TBL_BUCKET_ENTRIES 16 - -#define FIRST_PORT 0x8000 - -#define RX_CSUM_OFFLOAD (DEV_RX_OFFLOAD_IPV4_CKSUM | DEV_RX_OFFLOAD_UDP_CKSUM) -#define TX_CSUM_OFFLOAD (DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM) - -#define OPT_SHORT_SBULK 'B' -#define OPT_LONG_SBULK "sburst" - -#define OPT_SHORT_PROMISC 'P' -#define OPT_LONG_PROMISC "promisc" - -#define OPT_SHORT_RBUFS 'R' -#define OPT_LONG_RBUFS "rbufs" - -#define OPT_SHORT_SBUFS 'S' -#define OPT_LONG_SBUFS "sbufs" - -#define OPT_SHORT_STREAMS 's' -#define OPT_LONG_STREAMS "streams" - -#define OPT_SHORT_FECFG 'f' -#define OPT_LONG_FECFG "fecfg" - -#define OPT_SHORT_BECFG 'b' -#define OPT_LONG_BECFG "becfg" - -RTE_DEFINE_PER_LCORE(struct netbe_lcore *, _be); -RTE_DEFINE_PER_LCORE(struct netfe_lcore *, _fe); - -#include "fwdtbl.h" - -static const struct option long_opt[] = { - {OPT_LONG_BECFG, 1, 0, OPT_SHORT_BECFG}, - {OPT_LONG_FECFG, 1, 0, OPT_SHORT_FECFG}, - {OPT_LONG_PROMISC, 0, 0, OPT_SHORT_PROMISC}, - {OPT_LONG_RBUFS, 1, 0, OPT_SHORT_RBUFS}, - {OPT_LONG_SBUFS, 1, 0, OPT_SHORT_SBUFS}, - {OPT_LONG_SBULK, 1, 0, OPT_SHORT_SBULK}, - {OPT_LONG_STREAMS, 1, 0, OPT_SHORT_STREAMS}, - {NULL, 0, 0, 0} -}; - -/** - * IPv4 Input size in bytes for RSS hash key calculation. - * source address, destination address, source port, and destination port. - */ -#define IPV4_TUPLE_SIZE 12 - -/** - * IPv6 Input size in bytes for RSS hash key calculation. - * source address, destination address, source port, and destination port. - */ -#define IPV6_TUPLE_SIZE 36 - -/** - * Location to be modified to create the IPv4 hash key which helps - * to distribute packets based on the destination UDP port. - */ -#define RSS_HASH_KEY_DEST_PORT_LOC_IPV4 15 - -/* - * Location to be modified to create the IPv6 hash key which helps - * to distribute packets based on the destination UDP port. - */ -#define RSS_HASH_KEY_DEST_PORT_LOC_IPV6 39 - -/** - * Size of the rte_eth_rss_reta_entry64 array to update through - * rte_eth_dev_rss_reta_update. - */ -#define RSS_RETA_CONF_ARRAY_SIZE (ETH_RSS_RETA_SIZE_512/RTE_RETA_GROUP_SIZE) - -#define NETBE_REALLOC(loc, n) do { \ - (loc) = rte_realloc((loc), sizeof(*(loc)) * (n), RTE_CACHE_LINE_SIZE); \ - if ((loc) == NULL) { \ - RTE_LOG(ERR, USER1, \ - "%s: failed to reallocate memory\n", \ - __func__); \ - return -ENOMEM; \ - } \ -} while (0) - -static volatile int force_quit; - -static struct netbe_cfg becfg; -static struct rte_mempool *mpool[RTE_MAX_NUMA_NODES + 1]; -static struct rte_mempool *frag_mpool[RTE_MAX_NUMA_NODES + 1]; - -static const struct rte_eth_conf port_conf_default = { - .rxmode = { - .max_rx_pkt_len = ETHER_MAX_VLAN_FRAME_LEN, - .hw_vlan_strip = 1, - .jumbo_frame = 1, - }, -}; - -#include "parse.h" -#include "main_dpdk_legacy.h" - -static void -sig_handle(int signum) -{ - RTE_LOG(ERR, USER1, "%s(%d)\n", __func__, signum); - force_quit = 1; -} - -static void -prepare_hash_key(struct netbe_port *uprt, uint8_t key_size, uint16_t family) -{ - uint32_t align_nb_q; - - align_nb_q = rte_align32pow2(uprt->nb_lcore); - memset(uprt->hash_key, 0, RSS_HASH_KEY_LENGTH); - uprt->hash_key_size = key_size; - if (family == AF_INET) - uprt->hash_key[RSS_HASH_KEY_DEST_PORT_LOC_IPV4] = align_nb_q; - else - uprt->hash_key[RSS_HASH_KEY_DEST_PORT_LOC_IPV6] = align_nb_q; -} - -static uint32_t -qidx_from_hash_index(uint32_t hash, uint32_t align_nb_q) -{ - uint32_t i, nb_bit, q; - - nb_bit = (sizeof(uint32_t) * CHAR_BIT) - __builtin_clz(align_nb_q - 1); - q = (hash & 1); - for (i = 1; i < nb_bit; i++) { - hash >>= 1; - q <<= 1; - q |= (hash & 1); - } - - return q; -} - -static int -update_rss_conf(struct netbe_port *uprt, - const struct rte_eth_dev_info *dev_info, - struct rte_eth_conf *port_conf) -{ - uint8_t hash_key_size; - - if (uprt->nb_lcore > 1) { - if (dev_info->hash_key_size > 0) - hash_key_size = dev_info->hash_key_size; - else { - RTE_LOG(ERR, USER1, - "%s: dev_info did not provide a valid hash key size\n", - __func__); - return -EINVAL; - } - - if (uprt->ipv4 != INADDR_ANY && - memcmp(&uprt->ipv6, &in6addr_any, - sizeof(uprt->ipv6)) != 0) { - RTE_LOG(ERR, USER1, - "%s: RSS for both IPv4 and IPv6 not supported!\n", - __func__); - return -EINVAL; - } else if (uprt->ipv4 != INADDR_ANY) { - prepare_hash_key(uprt, hash_key_size, AF_INET); - } else if (memcmp(&uprt->ipv6, &in6addr_any, sizeof(uprt->ipv6)) - != 0) { - prepare_hash_key(uprt, hash_key_size, AF_INET6); - } else { - RTE_LOG(ERR, USER1, - "%s: No IPv4 or IPv6 address is found!\n", - __func__); - return -EINVAL; - } - port_conf->rxmode.mq_mode = ETH_MQ_RX_RSS; - port_conf->rx_adv_conf.rss_conf.rss_hf = ETH_RSS_UDP; - port_conf->rx_adv_conf.rss_conf.rss_key_len = hash_key_size; - port_conf->rx_adv_conf.rss_conf.rss_key = uprt->hash_key; - } - - return 0; -} - -static int -update_rss_reta(struct netbe_port *uprt, - const struct rte_eth_dev_info *dev_info) -{ - struct rte_eth_rss_reta_entry64 reta_conf[RSS_RETA_CONF_ARRAY_SIZE]; - int32_t i, rc, align_nb_q; - int32_t q_index, idx, shift; - - if (uprt->nb_lcore > 1) { - if (dev_info->reta_size == 0) { - RTE_LOG(ERR, USER1, - "%s: Redirection table size 0 is invalid for RSS\n", - __func__); - return -EINVAL; - } - RTE_LOG(NOTICE, USER1, - "%s: The reta size of port %d is %u\n", - __func__, uprt->id, dev_info->reta_size); - - if (dev_info->reta_size > ETH_RSS_RETA_SIZE_512) { - RTE_LOG(ERR, USER1, - "%s: More than %u entries of Reta not supported\n", - __func__, ETH_RSS_RETA_SIZE_512); - return -EINVAL; - } - - memset(reta_conf, 0, sizeof(reta_conf)); - align_nb_q = rte_align32pow2(uprt->nb_lcore); - for (i = 0; i < align_nb_q; i++) { - q_index = qidx_from_hash_index(i, align_nb_q) % - uprt->nb_lcore; - - idx = i / RTE_RETA_GROUP_SIZE; - shift = i % RTE_RETA_GROUP_SIZE; - reta_conf[idx].mask |= (1ULL << shift); - reta_conf[idx].reta[shift] = q_index; - RTE_LOG(NOTICE, USER1, - "%s: port=%u RSS reta conf: hash=%u, q=%u\n", - __func__, uprt->id, i, q_index); - } - - rc = rte_eth_dev_rss_reta_update(uprt->id, - reta_conf, dev_info->reta_size); - if (rc != 0) { - RTE_LOG(ERR, USER1, - "%s: Bad redirection table parameter, rc = %d\n", - __func__, rc); - return rc; - } - } - - return 0; -} - -/* - * Initilise DPDK port. - * In current version, multi-queue per port is used. - */ -static int -port_init(struct netbe_port *uprt) -{ - int32_t rc; - struct rte_eth_conf port_conf; - struct rte_eth_dev_info dev_info; - - rte_eth_dev_info_get(uprt->id, &dev_info); - if ((dev_info.rx_offload_capa & uprt->rx_offload) != uprt->rx_offload) { - RTE_LOG(ERR, USER1, - "port#%u supported/requested RX offloads don't match, " - "supported: %#x, requested: %#x;\n", - uprt->id, dev_info.rx_offload_capa, uprt->rx_offload); - return -EINVAL; - } - if ((dev_info.tx_offload_capa & uprt->tx_offload) != uprt->tx_offload) { - RTE_LOG(ERR, USER1, - "port#%u supported/requested TX offloads don't match, " - "supported: %#x, requested: %#x;\n", - uprt->id, dev_info.tx_offload_capa, uprt->tx_offload); - return -EINVAL; - } - - port_conf = port_conf_default; - if ((uprt->rx_offload & RX_CSUM_OFFLOAD) != 0) { - RTE_LOG(ERR, USER1, "%s(%u): enabling RX csum offload;\n", - __func__, uprt->id); - port_conf.rxmode.hw_ip_checksum = 1; - } - port_conf.rxmode.max_rx_pkt_len = uprt->mtu + ETHER_CRC_LEN; - - rc = update_rss_conf(uprt, &dev_info, &port_conf); - if (rc != 0) - return rc; - - rc = rte_eth_dev_configure(uprt->id, uprt->nb_lcore, uprt->nb_lcore, - &port_conf); - RTE_LOG(NOTICE, USER1, - "%s: rte_eth_dev_configure(prt_id=%u, nb_rxq=%u, nb_txq=%u) " - "returns %d;\n", __func__, uprt->id, uprt->nb_lcore, - uprt->nb_lcore, rc); - if (rc != 0) - return rc; - - return 0; -} - -static int -queue_init(struct netbe_port *uprt, struct rte_mempool *mp) -{ - int32_t socket, rc; - uint16_t q; - struct rte_eth_dev_info dev_info; - - rte_eth_dev_info_get(uprt->id, &dev_info); - - socket = rte_eth_dev_socket_id(uprt->id); - - dev_info.default_rxconf.rx_drop_en = 1; - - dev_info.default_txconf.tx_free_thresh = TX_RING_SIZE / 2; - if (uprt->tx_offload != 0) { - RTE_LOG(ERR, USER1, "%s(%u): enabling full featured TX;\n", - __func__, uprt->id); - dev_info.default_txconf.txq_flags = 0; - } - - for (q = 0; q < uprt->nb_lcore; q++) { - rc = rte_eth_rx_queue_setup(uprt->id, q, RX_RING_SIZE, - socket, &dev_info.default_rxconf, mp); - if (rc < 0) { - RTE_LOG(ERR, USER1, - "%s: rx queue=%u setup failed with error code: %d\n", - __func__, q, rc); - return rc; - } - } - - for (q = 0; q < uprt->nb_lcore; q++) { - rc = rte_eth_tx_queue_setup(uprt->id, q, TX_RING_SIZE, - socket, &dev_info.default_txconf); - if (rc < 0) { - RTE_LOG(ERR, USER1, - "%s: tx queue=%u setup failed with error code: %d\n", - __func__, q, rc); - return rc; - } - } - return 0; -} - -/* - * Check that lcore is enabled, not master, and not in use already. - */ -static int -check_lcore(uint32_t lc) -{ - if (rte_lcore_is_enabled(lc) == 0) { - RTE_LOG(ERR, USER1, "lcore %u is not enabled\n", lc); - return -EINVAL; - } - if (rte_eal_get_lcore_state(lc) == RUNNING) { - RTE_LOG(ERR, USER1, "lcore %u already running %p\n", - lc, lcore_config[lc].f); - return -EINVAL; - } - return 0; -} - -static void -log_netbe_prt(const struct netbe_port *uprt) -{ - uint32_t i; - char corelist[2 * RTE_MAX_LCORE + 1]; - char hashkey[2 * RSS_HASH_KEY_LENGTH]; - - memset(corelist, 0, sizeof(corelist)); - memset(hashkey, 0, sizeof(hashkey)); - for (i = 0; i < uprt->nb_lcore; i++) - if (i < uprt->nb_lcore - 1) - sprintf(corelist + (2 * i), "%u,", uprt->lcore[i]); - else - sprintf(corelist + (2 * i), "%u", uprt->lcore[i]); - - for (i = 0; i < uprt->hash_key_size; i++) - sprintf(hashkey + (2 * i), "%02x", uprt->hash_key[i]); - - RTE_LOG(NOTICE, USER1, - "uprt %p = , mtu = %u, " - "rx_offload = %u, tx_offload = %u,\n" - "ipv4 = %#x, " - "ipv6 = %04hx:%04hx:%04hx:%04hx:%04hx:%04hx:%04hx:%04hx, " - "mac = %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx>;\n" - "hashkey = %s;\n", - uprt, uprt->id, corelist, - uprt->mtu, uprt->rx_offload, uprt->tx_offload, - uprt->ipv4, - uprt->ipv6.s6_addr16[0], uprt->ipv6.s6_addr16[1], - uprt->ipv6.s6_addr16[2], uprt->ipv6.s6_addr16[3], - uprt->ipv6.s6_addr16[4], uprt->ipv6.s6_addr16[5], - uprt->ipv6.s6_addr16[6], uprt->ipv6.s6_addr16[7], - uprt->mac.addr_bytes[0], uprt->mac.addr_bytes[1], - uprt->mac.addr_bytes[2], uprt->mac.addr_bytes[3], - uprt->mac.addr_bytes[4], uprt->mac.addr_bytes[5], - hashkey); -} - -static void -log_netbe_cfg(const struct netbe_cfg *ucfg) -{ - uint32_t i; - - RTE_LOG(NOTICE, USER1, - "ucfg @ %p, prt_num = %u\n", ucfg, ucfg->prt_num); - - for (i = 0; i != ucfg->prt_num; i++) - log_netbe_prt(ucfg->prt + i); -} - -static int -pool_init(uint32_t sid) -{ - int32_t rc; - struct rte_mempool *mp; - char name[RTE_MEMPOOL_NAMESIZE]; - - snprintf(name, sizeof(name), "MP%u", sid); - mp = rte_pktmbuf_pool_create(name, MPOOL_NB_BUF, MPOOL_CACHE_SIZE, 0, - RTE_MBUF_DEFAULT_BUF_SIZE, sid - 1); - if (mp == NULL) { - rc = -rte_errno; - RTE_LOG(ERR, USER1, "%s(%d) failed with error code: %d\n", - __func__, sid - 1, rc); - return rc; - } - - mpool[sid] = mp; - return 0; -} - -static int -frag_pool_init(uint32_t sid) -{ - int32_t rc; - struct rte_mempool *frag_mp; - char frag_name[RTE_MEMPOOL_NAMESIZE]; - - snprintf(frag_name, sizeof(frag_name), "frag_MP%u", sid); - frag_mp = rte_pktmbuf_pool_create(frag_name, MPOOL_NB_BUF, - MPOOL_CACHE_SIZE, 0, FRAG_MBUF_BUF_SIZE, sid - 1); - if (frag_mp == NULL) { - rc = -rte_errno; - RTE_LOG(ERR, USER1, "%s(%d) failed with error code: %d\n", - __func__, sid - 1, rc); - return rc; - } - - frag_mpool[sid] = frag_mp; - return 0; -} - -static struct netbe_lcore * -find_initilized_lcore(struct netbe_cfg *cfg, uint32_t lc_num) -{ - uint32_t i; - - for (i = 0; i < cfg->cpu_num; i++) - if (cfg->cpu[i].id == lc_num) - return &cfg->cpu[i]; - - return NULL; -} - -/* - * Setup all enabled ports. - */ -static int -netbe_port_init(struct netbe_cfg *cfg, int argc, char *argv[]) -{ - int32_t rc; - uint32_t i, n, sid, j; - struct netbe_port *prt; - rte_cpuset_t cpuset; - uint32_t nc; - struct netbe_lcore *lc; - - n = (uint32_t)argc; - cfg->prt = rte_zmalloc(NULL, sizeof(struct netbe_port) * n, - RTE_CACHE_LINE_SIZE); - cfg->prt_num = n; - - rc = 0; - for (i = 0; i != n; i++) { - rc = parse_netbe_arg(cfg->prt + i, argv[i], &cpuset); - if (rc != 0) { - RTE_LOG(ERR, USER1, - "%s: processing of \"%s\" failed with error code: %d\n", - __func__, argv[i], rc); - return rc; - } - } - - for (i = 0, nc = 0; i < RTE_MAX_LCORE; i++) - nc += CPU_ISSET(i, &cpuset); - cfg->cpu = rte_zmalloc(NULL, sizeof(struct netbe_lcore) * nc, - RTE_CACHE_LINE_SIZE); - - for (i = 0; i != cfg->prt_num; i++) { - prt = cfg->prt + i; - rc = port_init(prt); - if (rc != 0) { - RTE_LOG(ERR, USER1, - "%s: port=%u init failed with error code: %d\n", - __func__, prt->id, rc); - return rc; - } - rte_eth_macaddr_get(prt->id, &prt->mac); - if (cfg->promisc) - rte_eth_promiscuous_enable(prt->id); - - for (j = 0; j < prt->nb_lcore; j++) { - rc = check_lcore(prt->lcore[j]); - if (rc != 0) - return rc; - - sid = rte_lcore_to_socket_id(prt->lcore[j]) + 1; - assert(sid < RTE_DIM(mpool)); - - if (mpool[sid] == NULL) { - rc = pool_init(sid); - if (rc != 0) - return rc; - } - - if (frag_mpool[sid] == NULL) { - rc = frag_pool_init(sid); - if (rc != 0) - return rc; - } - - rc = queue_init(prt, mpool[sid]); - if (rc != 0) { - RTE_LOG(ERR, USER1, - "%s: lcore=%u queue init failed with err: %d\n", - __func__, prt->lcore[j], rc); - return rc; - } - - /* calculate number of queues and assign queue id per lcore. */ - lc = find_initilized_lcore(cfg, prt->lcore[j]); - if (lc == NULL) { - lc = &cfg->cpu[cfg->cpu_num]; - lc->id = prt->lcore[j]; - cfg->cpu_num++; - } - - NETBE_REALLOC(lc->prtq, lc->prtq_num + 1); - lc->prtq[lc->prtq_num].rxqid = j; - lc->prtq[lc->prtq_num].txqid = j; - lc->prtq[lc->prtq_num].port = *prt; - lc->prtq_num++; - } - } - log_netbe_cfg(cfg); - - return 0; -} - -/* - * UDP IPv6 destination lookup callback. - */ -static int -lpm6_dst_lookup(void *data, const struct in6_addr *addr, - struct tle_udp_dest *res) -{ - int32_t rc; - uint8_t idx; - struct netbe_lcore *lc; - struct tle_udp_dest *dst; - uintptr_t p; - - lc = data; - p = (uintptr_t)addr->s6_addr; - - rc = rte_lpm6_lookup(lc->lpm6, (uint8_t *)p, &idx); - if (rc == 0) { - dst = &lc->dst6[idx]; - rte_memcpy(res, dst, dst->l2_len + dst->l3_len + - offsetof(struct tle_udp_dest, hdr)); - } - return rc; -} - -static int -netbe_add_ipv4_route(struct netbe_lcore *lc, const struct netbe_dest *dst, - uint8_t idx) -{ - int32_t rc; - uint32_t addr, depth; - char str[INET_ADDRSTRLEN]; - - depth = dst->prfx; - addr = rte_be_to_cpu_32(dst->ipv4.s_addr); - - inet_ntop(AF_INET, &dst->ipv4, str, sizeof(str)); - rc = rte_lpm_add(lc->lpm4, addr, depth, idx); - RTE_LOG(NOTICE, USER1, "%s(lcore=%u,port=%u,dev=%p," - "ipv4=%s/%u,mtu=%u," - "mac=%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx) " - "returns %d;\n", - __func__, lc->id, dst->port, lc->dst4[idx].dev, - str, depth, lc->dst4[idx].mtu, - dst->mac.addr_bytes[0], dst->mac.addr_bytes[1], - dst->mac.addr_bytes[2], dst->mac.addr_bytes[3], - dst->mac.addr_bytes[4], dst->mac.addr_bytes[5], - rc); - return rc; -} - -static int -netbe_add_ipv6_route(struct netbe_lcore *lc, const struct netbe_dest *dst, - uint8_t idx) -{ - int32_t rc; - uint32_t depth; - char str[INET6_ADDRSTRLEN]; - - depth = dst->prfx; - - rc = rte_lpm6_add(lc->lpm6, (uint8_t *)(uintptr_t)dst->ipv6.s6_addr, - depth, idx); - - inet_ntop(AF_INET6, &dst->ipv6, str, sizeof(str)); - RTE_LOG(NOTICE, USER1, "%s(lcore=%u,port=%u,dev=%p," - "ipv6=%s/%u,mtu=%u," - "mac=%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx) " - "returns %d;\n", - __func__, lc->id, dst->port, lc->dst6[idx].dev, - str, depth, lc->dst4[idx].mtu, - dst->mac.addr_bytes[0], dst->mac.addr_bytes[1], - dst->mac.addr_bytes[2], dst->mac.addr_bytes[3], - dst->mac.addr_bytes[4], dst->mac.addr_bytes[5], - rc); - return rc; -} - -static void -fill_dst(struct tle_udp_dest *dst, struct netbe_dev *bed, - const struct netbe_dest *bdp, uint16_t l3_type, int32_t sid) -{ - struct ether_hdr *eth; - struct ipv4_hdr *ip4h; - struct ipv6_hdr *ip6h; - - static const struct ipv4_hdr ipv4_tmpl = { - .version_ihl = 4 << 4 | sizeof(*ip4h) / IPV4_IHL_MULTIPLIER, - .time_to_live = 64, - .next_proto_id = IPPROTO_UDP, - }; - - static const struct ipv6_hdr ipv6_tmpl = { - .vtc_flow = 6 << 4, - .proto = IPPROTO_UDP, - .hop_limits = 64, - }; - - dst->dev = bed->dev; - dst->head_mp = frag_mpool[sid + 1]; - dst->mtu = RTE_MIN(bdp->mtu, bed->port.mtu); - dst->l2_len = sizeof(*eth); - - eth = (struct ether_hdr *)dst->hdr; - - ether_addr_copy(&bed->port.mac, ð->s_addr); - ether_addr_copy(&bdp->mac, ð->d_addr); - eth->ether_type = rte_cpu_to_be_16(l3_type); - - if (l3_type == ETHER_TYPE_IPv4) { - dst->l3_len = sizeof(*ip4h); - ip4h = (struct ipv4_hdr *)(eth + 1); - ip4h[0] = ipv4_tmpl; - } else if (l3_type == ETHER_TYPE_IPv6) { - dst->l3_len = sizeof(*ip6h); - ip6h = (struct ipv6_hdr *)(eth + 1); - ip6h[0] = ipv6_tmpl; - } -} - -static int -create_context(struct netbe_lcore *lc, const struct tle_udp_ctx_param *ctx_prm) -{ - uint32_t rc = 0, sid; - uint64_t frag_cycles; - struct tle_udp_ctx_param cprm; - - if (lc->ctx == NULL) { - sid = rte_lcore_to_socket_id(lc->id); - - rc = lcore_lpm_init(lc); - if (rc != 0) - return rc; - - cprm = *ctx_prm; - cprm.socket_id = sid; - cprm.lookup4 = lpm4_dst_lookup; - cprm.lookup4_data = lc; - cprm.lookup6 = lpm6_dst_lookup; - cprm.lookup6_data = lc; - - /* to facilitate both IPv4 and IPv6. */ - cprm.max_streams *= 2; - - frag_cycles = (rte_get_tsc_hz() + MS_PER_S - 1) / - MS_PER_S * FRAG_TTL; - - lc->ftbl = rte_ip_frag_table_create(cprm.max_streams, - FRAG_TBL_BUCKET_ENTRIES, cprm.max_streams, - frag_cycles, sid); - - RTE_LOG(NOTICE, USER1, "%s(lcore=%u): frag_tbl=%p;\n", - __func__, lc->id, lc->ftbl); - - lc->ctx = tle_udp_create(&cprm); - - RTE_LOG(NOTICE, USER1, "%s(lcore=%u): udp_ctx=%p;\n", - __func__, lc->id, lc->ctx); - - if (lc->ctx == NULL || lc->ftbl == NULL) - rc = ENOMEM; - } - - return rc; -} - -/* - * BE lcore setup routine. - */ -static int -lcore_init(struct netbe_lcore *lc, const struct tle_udp_ctx_param *ctx_prm, - const uint32_t prtqid, const uint16_t *bl_ports, uint32_t nb_bl_ports) -{ - int32_t rc = 0; - struct tle_udp_dev_param dprm; - - rc = create_context(lc, ctx_prm); - - if (lc->ctx != NULL) { - memset(&dprm, 0, sizeof(dprm)); - dprm.rx_offload = lc->prtq[prtqid].port.rx_offload; - dprm.tx_offload = lc->prtq[prtqid].port.tx_offload; - dprm.local_addr4.s_addr = lc->prtq[prtqid].port.ipv4; - memcpy(&dprm.local_addr6, &lc->prtq[prtqid].port.ipv6, - sizeof(lc->prtq[prtqid].port.ipv6)); - dprm.bl4.nb_port = nb_bl_ports; - dprm.bl4.port = bl_ports; - dprm.bl6.nb_port = nb_bl_ports; - dprm.bl6.port = bl_ports; - - lc->prtq[prtqid].dev = tle_udp_add_dev(lc->ctx, &dprm); - - RTE_LOG(NOTICE, USER1, - "%s(lcore=%u, port=%u, qid=%u), udp_dev: %p\n", - __func__, lc->id, lc->prtq[prtqid].port.id, - lc->prtq[prtqid].rxqid, lc->prtq[prtqid].dev); - - if (lc->prtq[prtqid].dev == NULL) - rc = -rte_errno; - - if (rc != 0) { - RTE_LOG(ERR, USER1, - "%s(lcore=%u) failed with error code: %d\n", - __func__, lc->id, rc); - tle_udp_destroy(lc->ctx); - rte_ip_frag_table_destroy(lc->ftbl); - rte_lpm_free(lc->lpm4); - rte_lpm6_free(lc->lpm6); - rte_free(lc->prtq[prtqid].port.lcore); - lc->prtq[prtqid].port.nb_lcore = 0; - rte_free(lc->prtq); - lc->prtq_num = 0; - return rc; - } - } - - return rc; -} - -static uint16_t -create_blocklist(const struct netbe_port *beprt, uint16_t *bl_ports, - uint32_t q) -{ - uint32_t i, j, qid, align_nb_q; - - align_nb_q = rte_align32pow2(beprt->nb_lcore); - for (i = 0, j = 0; i < (UINT16_MAX + 1); i++) { - qid = (i % align_nb_q) % beprt->nb_lcore; - if (qid != q) - bl_ports[j++] = i; - } - - return j; -} - -static int -netbe_lcore_init(struct netbe_cfg *cfg, - const struct tle_udp_ctx_param *ctx_prm) -{ - int32_t rc; - uint32_t i, j, nb_bl_ports = 0, sz; - struct netbe_lcore *lc; - static uint16_t *bl_ports; - - /* Create the udp context and attached queue for each lcore. */ - rc = 0; - sz = sizeof(uint16_t) * UINT16_MAX; - bl_ports = rte_zmalloc(NULL, sz, RTE_CACHE_LINE_SIZE); - for (i = 0; i < cfg->cpu_num; i++) { - lc = &cfg->cpu[i]; - for (j = 0; j < lc->prtq_num; j++) { - memset((uint8_t *)bl_ports, 0, sz); - /* create list of blocked ports based on q */ - nb_bl_ports = create_blocklist(&lc->prtq[j].port, - bl_ports, lc->prtq[j].rxqid); - RTE_LOG(NOTICE, USER1, - "lc=%u, q=%u, nb_bl_ports=%u\n", - lc->id, lc->prtq[j].rxqid, nb_bl_ports); - - rc = lcore_init(lc, ctx_prm, j, bl_ports, nb_bl_ports); - if (rc != 0) { - RTE_LOG(ERR, USER1, - "%s: failed with error code: %d\n", - __func__, rc); - rte_free(bl_ports); - return rc; - } - } - } - rte_free(bl_ports); - - return 0; -} - -static void -netbe_lcore_fini(struct netbe_cfg *cfg) -{ - uint32_t i; - - for (i = 0; i != cfg->cpu_num; i++) { - tle_udp_destroy(cfg->cpu[i].ctx); - rte_ip_frag_table_destroy(cfg->cpu[i].ftbl); - rte_lpm_free(cfg->cpu[i].lpm4); - rte_lpm6_free(cfg->cpu[i].lpm6); - - rte_free(cfg->cpu[i].prtq); - cfg->cpu[i].prtq_num = 0; - } - - rte_free(cfg->cpu); - cfg->cpu_num = 0; - for (i = 0; i != cfg->prt_num; i++) { - rte_free(cfg->prt[i].lcore); - cfg->prt[i].nb_lcore = 0; - } - rte_free(cfg->prt); - cfg->prt_num = 0; -} - -static int -netbe_add_dest(struct netbe_lcore *lc, uint32_t dev_idx, uint16_t family, - const struct netbe_dest *dst, uint32_t dnum) -{ - int32_t rc, sid; - uint16_t l3_type; - uint32_t i, n, m; - struct tle_udp_dest *dp; - - if (family == AF_INET) { - n = lc->dst4_num; - dp = lc->dst4 + n; - m = RTE_DIM(lc->dst4); - l3_type = ETHER_TYPE_IPv4; - } else { - n = lc->dst6_num; - dp = lc->dst6 + n; - m = RTE_DIM(lc->dst6); - l3_type = ETHER_TYPE_IPv6; - } - - if (n + dnum >= m) { - RTE_LOG(ERR, USER1, "%s(lcore=%u, family=%hu, dnum=%u) exceeds " - "maximum allowed number of destinations(%u);\n", - __func__, lc->id, family, dnum, m); - return -ENOSPC; - } - - sid = rte_lcore_to_socket_id(lc->id); - rc = 0; - - for (i = 0; i != dnum && rc == 0; i++) { - fill_dst(dp + i, lc->prtq + dev_idx, dst + i, l3_type, sid); - if (family == AF_INET) - rc = netbe_add_ipv4_route(lc, dst + i, n + i); - else - rc = netbe_add_ipv6_route(lc, dst + i, n + i); - } - - if (family == AF_INET) - lc->dst4_num = n + i; - else - lc->dst6_num = n + i; - - return rc; -} - -static int -netbe_dest_init(const char *fname, struct netbe_cfg *cfg) -{ - int32_t rc; - uint32_t f, i, p; - uint32_t k, l, cnt; - struct netbe_lcore *lc; - struct netbe_dest_prm prm; - - rc = netbe_parse_dest(fname, &prm); - if (rc != 0) - return rc; - - rc = 0; - for (i = 0; i != prm.nb_dest; i++) { - - p = prm.dest[i].port; - f = prm.dest[i].family; - - cnt = 0; - for (k = 0; k != cfg->cpu_num; k++) { - lc = cfg->cpu + k; - for (l = 0; l != lc->prtq_num; l++) - if (lc->prtq[l].port.id == p) { - rc = netbe_add_dest(lc, l, f, - prm.dest + i, 1); - if (rc != 0) { - RTE_LOG(ERR, USER1, - "%s(lcore=%u, family=%u) could not " - "add destinations(%u);\n", - __func__, lc->id, f, i); - return -ENOSPC; - } - cnt++; - } - } - - if (cnt == 0) { - RTE_LOG(ERR, USER1, "%s(%s) error at line %u: " - "port %u not managed by any lcore;\n", - __func__, fname, prm.dest[i].line, p); - break; - } - } - - free(prm.dest); - return rc; -} - -static void -netfe_stream_close(struct netfe_lcore *fe, uint32_t dec) -{ - uint32_t sidx; - - fe->sidx -= dec; - sidx = fe->sidx; - tle_event_free(fe->fs[sidx].txev); - tle_event_free(fe->fs[sidx].rxev); - tle_udp_stream_close(fe->fs[sidx].s); - memset(&fe->fs[sidx], 0, sizeof(fe->fs[sidx])); -} - -static void -netfe_stream_dump(const struct netfe_stream *fes) -{ - struct sockaddr_in *l4, *r4; - struct sockaddr_in6 *l6, *r6; - uint16_t lport, rport; - struct tle_udp_stream_param sprm; - char laddr[INET6_ADDRSTRLEN]; - char raddr[INET6_ADDRSTRLEN]; - - tle_udp_stream_get_param(fes->s, &sprm); - - if (sprm.local_addr.ss_family == AF_INET) { - - l4 = (struct sockaddr_in *)&sprm.local_addr; - r4 = (struct sockaddr_in *)&sprm.remote_addr; - - lport = l4->sin_port; - rport = r4->sin_port; - - } else if (sprm.local_addr.ss_family == AF_INET6) { - - l6 = (struct sockaddr_in6 *)&sprm.local_addr; - r6 = (struct sockaddr_in6 *)&sprm.remote_addr; - - lport = l6->sin6_port; - rport = r6->sin6_port; - - } else { - RTE_LOG(ERR, USER1, "stream@%p - unknown family=%hu\n", - fes->s, sprm.local_addr.ss_family); - return; - } - - format_addr(&sprm.local_addr, laddr, sizeof(laddr)); - format_addr(&sprm.remote_addr, raddr, sizeof(raddr)); - - RTE_LOG(INFO, USER1, - "stream@%p={" - "family=%hu,laddr=%s,lport=%hu,raddr=%s,rport=%hu," - "stats={" - "rxp=%" PRIu64 ",txp=%" PRIu64 ",drops=%" PRIu64 "," - "rxev[IDLE, DOWN, UP]=[%" PRIu64 ", %" PRIu64 ", %" PRIu64 "]," - "txev[IDLE, DOWN, UP]=[%" PRIu64 ", %" PRIu64 ", %" PRIu64 "]," - "}};\n", - fes->s, - sprm.local_addr.ss_family, - laddr, ntohs(lport), raddr, ntohs(rport), - fes->stat.rxp, fes->stat.txp, fes->stat.drops, - fes->stat.rxev[TLE_SEV_IDLE], - fes->stat.rxev[TLE_SEV_DOWN], - fes->stat.rxev[TLE_SEV_UP], - fes->stat.txev[TLE_SEV_IDLE], - fes->stat.txev[TLE_SEV_DOWN], - fes->stat.txev[TLE_SEV_UP]); -} - -/* - * helper function: opens IPv4 and IPv6 streams for selected port. - */ -static struct netfe_stream * -netfe_stream_open(struct netfe_lcore *fe, struct tle_udp_stream_param *sprm, - uint32_t lcore, uint16_t op, uint32_t bidx) -{ - int32_t rc; - uint32_t sidx; - struct netfe_stream *fes; - struct sockaddr_in *l4; - struct sockaddr_in6 *l6; - uint16_t errport; - - sidx = fe->sidx; - fes = fe->fs + sidx; - if (sidx >= fe->snum) { - rte_errno = ENOBUFS; - return NULL; - } - - fes->rxev = tle_event_alloc(fe->rxeq, &fe->fs[sidx]); - fes->txev = tle_event_alloc(fe->txeq, &fe->fs[sidx]); - sprm->recv_ev = fes->rxev; - if (op != FWD) - sprm->send_ev = fes->txev; - - RTE_LOG(ERR, USER1, - "%s(%u) [%u]={op=%hu, rxev=%p, txev=%p}, be_lc=%u\n", - __func__, lcore, sidx, op, fes->rxev, fes->txev, - becfg.cpu[bidx].id); - if (fes->rxev == NULL || fes->txev == NULL) { - netfe_stream_close(fe, 0); - rte_errno = ENOMEM; - return NULL; - } - - if (op == TXONLY || op == FWD) { - tle_event_active(fes->txev, TLE_SEV_DOWN); - fes->stat.txev[TLE_SEV_DOWN]++; - } - - if (op != TXONLY) { - tle_event_active(fes->rxev, TLE_SEV_DOWN); - fes->stat.rxev[TLE_SEV_DOWN]++; - } - - fes->s = tle_udp_stream_open(becfg.cpu[bidx].ctx, sprm); - if (fes->s == NULL) { - rc = rte_errno; - netfe_stream_close(fe, 0); - rte_errno = rc; - - if (sprm->local_addr.ss_family == AF_INET) { - l4 = (struct sockaddr_in *) &sprm->local_addr; - errport = ntohs(l4->sin_port); - } else { - l6 = (struct sockaddr_in6 *) &sprm->local_addr; - errport = ntohs(l6->sin6_port); - } - RTE_LOG(ERR, USER1, "stream open failed for port %u with error " - "code=%u, bidx=%u, lc=%u\n", - errport, rc, bidx, becfg.cpu[bidx].id); - return NULL; - } - - fes->op = op; - fes->family = sprm->local_addr.ss_family; - - fe->sidx = sidx + 1; - return fes; -} - -static inline int -netfe_addr_eq(struct sockaddr_storage *l, struct sockaddr_storage *r, - uint16_t family) -{ - struct sockaddr_in *l4, *r4; - struct sockaddr_in6 *l6, *r6; - - if (family == AF_INET) { - l4 = (struct sockaddr_in *)l; - r4 = (struct sockaddr_in *)r; - return (l4->sin_port == r4->sin_port && - l4->sin_addr.s_addr == r4->sin_addr.s_addr); - } else { - l6 = (struct sockaddr_in6 *)l; - r6 = (struct sockaddr_in6 *)r; - return (l6->sin6_port == r6->sin6_port && - memcmp(&l6->sin6_addr, &r6->sin6_addr, - sizeof(l6->sin6_addr))); - } -} - -static inline void -netfe_pkt_addr(const struct rte_mbuf *m, struct sockaddr_storage *ps, - uint16_t family) -{ - const struct ipv4_hdr *ip4h; - const struct ipv6_hdr *ip6h; - const struct udp_hdr *udph; - struct sockaddr_in *in4; - struct sockaddr_in6 *in6; - - NETFE_PKT_DUMP(m); - - udph = rte_pktmbuf_mtod_offset(m, struct udp_hdr *, -m->l4_len); - - if (family == AF_INET) { - in4 = (struct sockaddr_in *)ps; - ip4h = rte_pktmbuf_mtod_offset(m, struct ipv4_hdr *, - -(m->l4_len + m->l3_len)); - in4->sin_port = udph->src_port; - in4->sin_addr.s_addr = ip4h->src_addr; - } else { - in6 = (struct sockaddr_in6 *)ps; - ip6h = rte_pktmbuf_mtod_offset(m, struct ipv6_hdr *, - -(m->l4_len + m->l3_len)); - in6->sin6_port = udph->src_port; - rte_memcpy(&in6->sin6_addr, ip6h->src_addr, - sizeof(in6->sin6_addr)); - } -} - -static inline uint32_t -pkt_eq_addr(struct rte_mbuf *pkt[], uint32_t num, uint16_t family, - struct sockaddr_storage *cur, struct sockaddr_storage *nxt) -{ - uint32_t i; - - for (i = 0; i != num; i++) { - netfe_pkt_addr(pkt[i], nxt, family); - if (netfe_addr_eq(cur, nxt, family) == 0) - break; - } - - return i; -} - -static inline void -pkt_buf_empty(struct pkt_buf *pb) -{ - uint32_t i; - - for (i = 0; i != pb->num; i++) - rte_pktmbuf_free(pb->pkt[i]); - - pb->num = 0; -} - -static inline void -pkt_buf_fill(uint32_t lcore, struct pkt_buf *pb, uint32_t dlen) -{ - uint32_t i; - int32_t sid; - - sid = rte_lcore_to_socket_id(lcore) + 1; - - for (i = pb->num; i != RTE_DIM(pb->pkt); i++) { - pb->pkt[i] = rte_pktmbuf_alloc(mpool[sid]); - if (pb->pkt[i] == NULL) - break; - rte_pktmbuf_append(pb->pkt[i], dlen); - } - - pb->num = i; -} - -static struct netfe_stream * -find_fwd_dst(uint32_t lcore, struct netfe_stream *fes, - const struct sockaddr *sa) -{ - uint32_t rc; - struct netfe_stream *fed; - struct netfe_lcore *fe; - struct tle_udp_stream_param sprm; - - fe = RTE_PER_LCORE(_fe); - - fed = fwd_tbl_lkp(fe, fes->family, sa); - if (fed != NULL) - return fed; - - /* create a new stream and put it into the fwd table. */ - - sprm = fes->fwdprm.prm; - - /* open forward stream with wildcard remote addr. */ - memset(&sprm.remote_addr.ss_family + 1, 0, - sizeof(sprm.remote_addr) - sizeof(sprm.remote_addr.ss_family)); - fed = netfe_stream_open(fe, &sprm, lcore, FWD, fes->fwdprm.bidx); - if (fed == NULL) - return NULL; - - rc = fwd_tbl_add(fe, fes->family, sa, fed); - if (rc != 0) { - netfe_stream_close(fe, 1); - fed = NULL; - } - - fed->fwdprm.prm.remote_addr = *(const struct sockaddr_storage *)sa; - return fed; -} - -static inline void -netfe_tx_process(uint32_t lcore, struct netfe_stream *fes) -{ - uint32_t i, k, n; - - /* refill with new mbufs. */ - pkt_buf_fill(lcore, &fes->pbuf, fes->txlen); - - n = fes->pbuf.num; - if (n == 0) - return; - - k = tle_udp_stream_send(fes->s, fes->pbuf.pkt, n, NULL); - NETFE_TRACE("%s(%u): tle_udp_stream_send(%p, %u) returns %u\n", - __func__, lcore, fes->s, n, k); - fes->stat.txp += k; - fes->stat.drops += n - k; - - if (k == 0) - return; - - /* adjust pbuf array. */ - fes->pbuf.num = n - k; - for (i = k; i != n; i++) - fes->pbuf.pkt[i - k] = fes->pbuf.pkt[i]; -} - -static inline void -netfe_fwd(uint32_t lcore, struct netfe_stream *fes) -{ - uint32_t i, j, k, n, x; - uint16_t family; - void *pi0, *pi1, *pt; - struct rte_mbuf **pkt; - struct netfe_stream *fed; - struct sockaddr_storage in[2]; - - family = fes->family; - n = fes->pbuf.num; - pkt = fes->pbuf.pkt; - - if (n == 0) - return; - - in[0].ss_family = family; - in[1].ss_family = family; - pi0 = &in[0]; - pi1 = &in[1]; - - netfe_pkt_addr(pkt[0], pi0, family); - - x = 0; - for (i = 0; i != n; i = j) { - - j = i + pkt_eq_addr(&pkt[i + 1], - n - i - 1, family, pi0, pi1) + 1; - - fed = find_fwd_dst(lcore, fes, (const struct sockaddr *)pi0); - if (fed != NULL) { - - k = tle_udp_stream_send(fed->s, pkt + i, j - i, - (const struct sockaddr *) - &fes->fwdprm.prm.remote_addr); - - NETFE_TRACE("%s(%u): tle_udp_stream_send(%p, %u) " - "returns %u\n", - __func__, lcore, fed->s, j - i, k); - fed->stat.txp += k; - fed->stat.drops += j - i - k; - fes->stat.fwp += k; - - } else { - NETFE_TRACE("%s(%u, %p): no fwd stream for %u pkts;\n", - __func__, lcore, fes->s, j - i); - for (k = i; k != j; k++) { - NETFE_TRACE("%s(%u, %p): free(%p);\n", - __func__, lcore, fes->s, pkt[k]); - rte_pktmbuf_free(pkt[j]); - } - fes->stat.drops += j - i; - } - - /* copy unforwarded mbufs. */ - for (i += k; i != j; i++, x++) - pkt[x] = pkt[i]; - - /* swap the pointers */ - pt = pi0; - pi0 = pi1; - pi1 = pt; - } - - fes->pbuf.num = x; - - if (x != 0) { - tle_event_raise(fes->txev); - fes->stat.txev[TLE_SEV_UP]++; - } - - if (n == RTE_DIM(fes->pbuf.pkt)) { - tle_event_active(fes->rxev, TLE_SEV_UP); - fes->stat.rxev[TLE_SEV_UP]++; - } -} - -static inline void -netfe_rx_process(__rte_unused uint32_t lcore, struct netfe_stream *fes) -{ - uint32_t k, n; - - n = fes->pbuf.num; - k = RTE_DIM(fes->pbuf.pkt) - n; - - /* packet buffer is full, can't receive any new packets. */ - if (k == 0) { - tle_event_idle(fes->rxev); - fes->stat.rxev[TLE_SEV_IDLE]++; - return; - } - - n = tle_udp_stream_recv(fes->s, fes->pbuf.pkt + n, k); - if (n == 0) - return; - - NETFE_TRACE("%s(%u): tle_udp_stream_recv(%p, %u) returns %u\n", - __func__, lcore, fes->s, k, n); - - fes->pbuf.num += n; - fes->stat.rxp += n; - - /* free all received mbufs. */ - if (fes->op == RXONLY) - pkt_buf_empty(&fes->pbuf); - /* mark stream as writable */ - else if (k == RTE_DIM(fes->pbuf.pkt)) { - if (fes->op == RXTX) { - tle_event_active(fes->txev, TLE_SEV_UP); - fes->stat.txev[TLE_SEV_UP]++; - } else if (fes->op == FWD) { - tle_event_raise(fes->txev); - fes->stat.txev[TLE_SEV_UP]++; - } - } -} - -static inline void -netfe_rxtx_process(__rte_unused uint32_t lcore, struct netfe_stream *fes) -{ - uint32_t i, j, k, n; - uint16_t family; - void *pi0, *pi1, *pt; - struct rte_mbuf **pkt; - struct sockaddr_storage in[2]; - - family = fes->family; - n = fes->pbuf.num; - pkt = fes->pbuf.pkt; - - /* there is nothing to send. */ - if (n == 0) { - tle_event_idle(fes->txev); - fes->stat.txev[TLE_SEV_IDLE]++; - return; - } - - in[0].ss_family = family; - in[1].ss_family = family; - pi0 = &in[0]; - pi1 = &in[1]; - - netfe_pkt_addr(pkt[0], pi0, family); - - for (i = 0; i != n; i = j) { - - j = i + pkt_eq_addr(&pkt[i + 1], - n - i - 1, family, pi0, pi1) + 1; - - k = tle_udp_stream_send(fes->s, pkt + i, j - i, - (const struct sockaddr *)pi0); - - NETFE_TRACE("%s(%u): tle_udp_stream_send(%p, %u) returns %u\n", - __func__, lcore, fes->s, j - i, k); - fes->stat.txp += k; - fes->stat.drops += j - i - k; - - i += k; - - /* stream send buffer is full */ - if (i != j) - break; - - /* swap the pointers */ - pt = pi0; - pi0 = pi1; - pi1 = pt; - } - - /* not able to send anything. */ - if (i == 0) - return; - - if (n == RTE_DIM(fes->pbuf.pkt)) { - /* mark stream as readable */ - tle_event_active(fes->rxev, TLE_SEV_UP); - fes->stat.rxev[TLE_SEV_UP]++; - } - - /* adjust pbuf array. */ - fes->pbuf.num = n - i; - for (j = i; j != n; j++) - pkt[j - i] = pkt[j]; -} - -static int -netfe_lcore_init(const struct netfe_lcore_prm *prm) -{ - size_t sz; - int32_t rc; - uint32_t i, lcore, snum; - struct netfe_lcore *fe; - struct tle_evq_param eprm; - struct tle_udp_stream_param sprm; - struct netfe_stream *fes; - - lcore = rte_lcore_id(); - - snum = prm->max_streams; - RTE_LOG(NOTICE, USER1, "%s(lcore=%u, nb_streams=%u, max_streams=%u)\n", - __func__, lcore, prm->nb_streams, snum); - - memset(&eprm, 0, sizeof(eprm)); - eprm.socket_id = rte_lcore_to_socket_id(lcore); - eprm.max_events = snum; - - sz = sizeof(*fe) + snum * sizeof(fe->fs[0]); - fe = rte_zmalloc_socket(NULL, sz, RTE_CACHE_LINE_SIZE, - rte_lcore_to_socket_id(lcore)); - - if (fe == NULL) { - RTE_LOG(ERR, USER1, "%s:%d failed to allocate %zu bytes\n", - __func__, __LINE__, sz); - return -ENOMEM; - } - - RTE_PER_LCORE(_fe) = fe; - - fe->snum = snum; - fe->fs = (struct netfe_stream *)(fe + 1); - - fe->rxeq = tle_evq_create(&eprm); - fe->txeq = tle_evq_create(&eprm); - - RTE_LOG(INFO, USER1, "%s(%u) rx evq=%p, tx evq=%p\n", - __func__, lcore, fe->rxeq, fe->txeq); - if (fe->rxeq == NULL || fe->txeq == NULL) - return -ENOMEM; - - rc = fwd_tbl_init(fe, AF_INET, lcore); - RTE_LOG(ERR, USER1, "%s(%u) fwd_tbl_init(%u) returns %d\n", - __func__, lcore, AF_INET, rc); - if (rc != 0) - return rc; - - rc = fwd_tbl_init(fe, AF_INET6, lcore); - RTE_LOG(ERR, USER1, "%s(%u) fwd_tbl_init(%u) returns %d\n", - __func__, lcore, AF_INET6, rc); - if (rc != 0) - return rc; - - /* open all requested streams. */ - for (i = 0; i != prm->nb_streams; i++) { - sprm = prm->stream[i].sprm.prm; - fes = netfe_stream_open(fe, &sprm, lcore, prm->stream[i].op, - prm->stream[i].sprm.bidx); - if (fes == NULL) { - rc = -rte_errno; - break; - } - - netfe_stream_dump(fes); - - if (prm->stream[i].op == FWD) { - fes->fwdprm = prm->stream[i].fprm; - rc = fwd_tbl_add(fe, - prm->stream[i].fprm.prm.remote_addr.ss_family, - (const struct sockaddr *) - &prm->stream[i].fprm.prm.remote_addr, - fes); - if (rc != 0) { - netfe_stream_close(fe, 1); - break; - } - } else if (prm->stream[i].op == TXONLY) { - fes->txlen = prm->stream[i].txlen; - fes->raddr = sprm.remote_addr; - } - } - - return rc; -} - -static inline void -netfe_lcore(void) -{ - struct netfe_lcore *fe; - uint32_t j, n, lcore; - struct netfe_stream *fs[MAX_PKT_BURST]; - - fe = RTE_PER_LCORE(_fe); - if (fe == NULL) - return; - - lcore = rte_lcore_id(); - - n = tle_evq_get(fe->rxeq, (const void **)(uintptr_t)fs, RTE_DIM(fs)); - - if (n != 0) { - NETFE_TRACE("%s(%u): tle_evq_get(rxevq=%p) returns %u\n", - __func__, lcore, fe->rxeq, n); - for (j = 0; j != n; j++) - netfe_rx_process(lcore, fs[j]); - } - - n = tle_evq_get(fe->txeq, (const void **)(uintptr_t)fs, RTE_DIM(fs)); - - if (n != 0) { - NETFE_TRACE("%s(%u): tle_evq_get(txevq=%p) returns %u\n", - __func__, lcore, fe->txeq, n); - for (j = 0; j != n; j++) { - if (fs[j]->op == RXTX) - netfe_rxtx_process(lcore, fs[j]); - else if (fs[j]->op == FWD) - netfe_fwd(lcore, fs[j]); - else if (fs[j]->op == TXONLY) - netfe_tx_process(lcore, fs[j]); - } - } -} - -static void -netfe_lcore_fini(void) -{ - struct netfe_lcore *fe; - uint32_t i; - - fe = RTE_PER_LCORE(_fe); - if (fe == NULL) - return; - - while (fe->sidx != 0) { - i = fe->sidx - 1; - netfe_stream_dump(fe->fs + i); - netfe_stream_close(fe, 1); - } - - tle_evq_destroy(fe->txeq); - tle_evq_destroy(fe->rxeq); - RTE_PER_LCORE(_fe) = NULL; - rte_free(fe); -} - -static inline void -netbe_rx(struct netbe_lcore *lc, uint32_t pidx) -{ - uint32_t j, k, n; - struct rte_mbuf *pkt[MAX_PKT_BURST]; - struct rte_mbuf *rp[MAX_PKT_BURST]; - int32_t rc[MAX_PKT_BURST]; - - n = rte_eth_rx_burst(lc->prtq[pidx].port.id, - lc->prtq[pidx].rxqid, pkt, RTE_DIM(pkt)); - if (n == 0) - return; - - lc->prtq[pidx].rx_stat.in += n; - NETBE_TRACE("%s(%u): rte_eth_rx_burst(%u, %u) returns %u\n", - __func__, lc->id, lc->prtq[pidx].port.id, lc->prtq[pidx].rxqid, - n); - - k = tle_udp_rx_bulk(lc->prtq[pidx].dev, pkt, rp, rc, n); - - lc->prtq[pidx].rx_stat.up += k; - lc->prtq[pidx].rx_stat.drop += n - k; - NETBE_TRACE("%s(%u): tle_udp_rx_bulk(%p, %u) returns %u\n", - __func__, lc->id, lc->prtq[pidx].dev, n, k); - - for (j = 0; j != n - k; j++) { - NETBE_TRACE("%s:%d(port=%u) rp[%u]={%p, %d};\n", - __func__, __LINE__, lc->prtq[pidx].port.id, - j, rp[j], rc[j]); - rte_pktmbuf_free(rp[j]); - } -} - -static inline void -netbe_tx(struct netbe_lcore *lc, uint32_t pidx) -{ - uint32_t j, k, n; - struct rte_mbuf **mb; - - n = lc->prtq[pidx].tx_buf.num; - k = RTE_DIM(lc->prtq[pidx].tx_buf.pkt) - n; - mb = lc->prtq[pidx].tx_buf.pkt; - - if (k >= RTE_DIM(lc->prtq[pidx].tx_buf.pkt) / 2) { - j = tle_udp_tx_bulk(lc->prtq[pidx].dev, mb + n, k); - n += j; - lc->prtq[pidx].tx_stat.down += j; - } - - if (n == 0) - return; - - NETBE_TRACE("%s(%u): tle_udp_tx_bulk(%p) returns %u,\n" - "total pkts to send: %u\n", - __func__, lc->id, lc->prtq[pidx].dev, j, n); - - for (j = 0; j != n; j++) - NETBE_PKT_DUMP(mb[j]); - - k = rte_eth_tx_burst(lc->prtq[pidx].port.id, - lc->prtq[pidx].txqid, mb, n); - - lc->prtq[pidx].tx_stat.out += k; - lc->prtq[pidx].tx_stat.drop += n - k; - NETBE_TRACE("%s(%u): rte_eth_tx_burst(%u, %u, %u) returns %u\n", - __func__, lc->id, lc->prtq[pidx].port.id, lc->prtq[pidx].txqid, - n, k); - - lc->prtq[pidx].tx_buf.num = n - k; - if (k != 0) - for (j = k; j != n; j++) - mb[j - k] = mb[j]; -} - -static int -netbe_lcore_setup(struct netbe_lcore *lc) -{ - uint32_t i; - int32_t rc; - - RTE_LOG(NOTICE, USER1, "%s(lcore=%u, udp_ctx: %p) start\n", - __func__, lc->id, lc->ctx); - - /* - * ??????? - * wait for FE lcores to start, so BE dont' drop any packets - * because corresponding streams not opened yet by FE. - * useful when used with pcap PMDS. - * think better way, or should this timeout be a cmdlien parameter. - * ??????? - */ - rte_delay_ms(10); - - rc = 0; - for (i = 0; i != lc->prtq_num && rc == 0; i++) { - RTE_LOG(NOTICE, USER1, "%s:%u(port=%u, udp_dev: %p)\n", - __func__, i, lc->prtq[i].port.id, lc->prtq[i].dev); - rc = setup_rx_cb(&lc->prtq[i].port, lc, lc->prtq[i].rxqid); - if (rc < 0) - return rc; - } - - if (rc == 0) - RTE_PER_LCORE(_be) = lc; - return rc; -} - -static inline void -netbe_lcore(void) -{ - uint32_t i; - struct netbe_lcore *lc; - - lc = RTE_PER_LCORE(_be); - if (lc == NULL) - return; - - for (i = 0; i != lc->prtq_num; i++) { - netbe_rx(lc, i); - netbe_tx(lc, i); - } -} - -static void -netbe_lcore_clear(void) -{ - uint32_t i, j; - struct netbe_lcore *lc; - - lc = RTE_PER_LCORE(_be); - if (lc == NULL) - return; - - RTE_LOG(NOTICE, USER1, "%s(lcore=%u, udp_ctx: %p) finish\n", - __func__, lc->id, lc->ctx); - for (i = 0; i != lc->prtq_num; i++) { - RTE_LOG(NOTICE, USER1, "%s:%u(port=%u, lcore=%u, q=%u, dev=%p) " - "rx_stats={" - "in=%" PRIu64 ",up=%" PRIu64 ",drop=%" PRIu64 "}, " - "tx_stats={" - "in=%" PRIu64 ",up=%" PRIu64 ",drop=%" PRIu64 "};\n", - __func__, i, lc->prtq[i].port.id, lc->id, - lc->prtq[i].rxqid, - lc->prtq[i].dev, - lc->prtq[i].rx_stat.in, - lc->prtq[i].rx_stat.up, - lc->prtq[i].rx_stat.drop, - lc->prtq[i].tx_stat.down, - lc->prtq[i].tx_stat.out, - lc->prtq[i].tx_stat.drop); - } - - for (i = 0; i != lc->prtq_num; i++) - for (j = 0; j != lc->prtq[i].tx_buf.num; j++) - rte_pktmbuf_free(lc->prtq[i].tx_buf.pkt[j]); - - RTE_PER_LCORE(_be) = NULL; -} - -static int -lcore_main(void *arg) -{ - int32_t rc; - uint32_t lcore; - struct lcore_prm *prm; - - prm = arg; - lcore = rte_lcore_id(); - - RTE_LOG(NOTICE, USER1, "%s(lcore=%u) start\n", - __func__, lcore); - - rc = 0; - - /* lcore FE init. */ - if (prm->fe.max_streams != 0) - rc = netfe_lcore_init(&prm->fe); - - /* lcore FE init. */ - if (rc == 0 && prm->be.lc != NULL) - rc = netbe_lcore_setup(prm->be.lc); - - if (rc != 0) - sig_handle(SIGQUIT); - - while (force_quit == 0) { - netfe_lcore(); - netbe_lcore(); - } - - RTE_LOG(NOTICE, USER1, "%s(lcore=%u) finish\n", - __func__, lcore); - - netfe_lcore_fini(); - netbe_lcore_clear(); - - return rc; -} - -static int -netfe_lcore_cmp(const void *s1, const void *s2) -{ - const struct netfe_stream_prm *p1, *p2; - - p1 = s1; - p2 = s2; - return p1->lcore - p2->lcore; -} - -static int -netbe_find6(const struct in6_addr *laddr, uint16_t lport, - const struct in6_addr *raddr, uint32_t be_lc) -{ - uint32_t i, j; - uint8_t idx; - struct netbe_lcore *bc; - - /* we have exactly one BE, use it for all traffic */ - if (becfg.cpu_num == 1) - return 0; - - /* search by provided be_lcore */ - if (be_lc != LCORE_ID_ANY) { - for (i = 0; i != becfg.cpu_num; i++) { - bc = becfg.cpu + i; - if (be_lc == bc->id) - return i; - } - RTE_LOG(NOTICE, USER1, "%s: no stream with be_lcore=%u\n", - __func__, be_lc); - return -ENOENT; - } - - /* search by local address */ - if (memcmp(laddr, &in6addr_any, sizeof(*laddr)) != 0) { - for (i = 0; i != becfg.cpu_num; i++) { - bc = becfg.cpu + i; - /* search by queue for the local port */ - for (j = 0; j != bc->prtq_num; j++) { - if (memcmp(laddr, &bc->prtq[j].port.ipv6, - sizeof(*laddr)) == 0) { - - if (lport == 0) - return i; - - if (verify_queue_for_port(bc->prtq + j, - lport) != 0) - return i; - } - } - } - } - - /* search by remote address */ - if (memcmp(raddr, &in6addr_any, sizeof(*raddr)) == 0) { - for (i = 0; i != becfg.cpu_num; i++) { - bc = becfg.cpu + i; - if (rte_lpm6_lookup(bc->lpm6, - (uint8_t *)(uintptr_t)raddr->s6_addr, - &idx) == 0) { - - if (lport == 0) - return i; - - /* search by queue for the local port */ - for (j = 0; j != bc->prtq_num; j++) - if (verify_queue_for_port(bc->prtq + j, - lport) != 0) - return i; - } - } - } - - return -ENOENT; -} - -static int -netbe_find(const struct tle_udp_stream_param *p, uint32_t be_lc) -{ - const struct sockaddr_in *l4, *r4; - const struct sockaddr_in6 *l6, *r6; - - if (p->local_addr.ss_family == AF_INET) { - l4 = (const struct sockaddr_in *)&p->local_addr; - r4 = (const struct sockaddr_in *)&p->remote_addr; - return netbe_find4(&l4->sin_addr, ntohs(l4->sin_port), - &r4->sin_addr, be_lc); - } else if (p->local_addr.ss_family == AF_INET6) { - l6 = (const struct sockaddr_in6 *)&p->local_addr; - r6 = (const struct sockaddr_in6 *)&p->remote_addr; - return netbe_find6(&l6->sin6_addr, ntohs(l6->sin6_port), - &r6->sin6_addr, be_lc); - } - return -EINVAL; -} - -static int -netfe_sprm_flll_be(struct netfe_sprm *sp, uint32_t line, uint32_t be_lc) -{ - int32_t bidx; - - bidx = netbe_find(&sp->prm, be_lc); - if (bidx < 0) { - RTE_LOG(ERR, USER1, "%s(line=%u): no BE for that stream\n", - __func__, line); - return -EINVAL; - } - sp->bidx = bidx; - return 0; -} - -/* start front-end processing. */ -static int -netfe_lcore_fill(struct lcore_prm prm[RTE_MAX_LCORE], - struct netfe_lcore_prm *lprm) -{ - uint32_t be_lc; - uint32_t i, j, lc, ln; - - /* determine on what BE each stream should be open. */ - for (i = 0; i != lprm->nb_streams; i++) { - lc = lprm->stream[i].lcore; - ln = lprm->stream[i].line; - be_lc = lprm->stream[i].be_lcore; - if (netfe_sprm_flll_be(&lprm->stream[i].sprm, ln, - be_lc) != 0 || - (lprm->stream[i].op == FWD && - netfe_sprm_flll_be(&lprm->stream[i].fprm, ln, - be_lc) != 0)) - return -EINVAL; - } - - /* group all fe parameters by lcore. */ - - qsort(lprm->stream, lprm->nb_streams, sizeof(lprm->stream[0]), - netfe_lcore_cmp); - - for (i = 0; i != lprm->nb_streams; i = j) { - - lc = lprm->stream[i].lcore; - ln = lprm->stream[i].line; - - if (rte_lcore_is_enabled(lc) == 0) { - RTE_LOG(ERR, USER1, - "%s(line=%u): lcore %u is not enabled\n", - __func__, ln, lc); - return -EINVAL; - } - - if (rte_get_master_lcore() != lc && - rte_eal_get_lcore_state(lc) == RUNNING) { - RTE_LOG(ERR, USER1, - "%s(line=%u): lcore %u already in use\n", - __func__, ln, lc); - return -EINVAL; - } - - for (j = i + 1; j != lprm->nb_streams && - lc == lprm->stream[j].lcore; - j++) - ; - - prm[lc].fe.max_streams = lprm->max_streams; - prm[lc].fe.nb_streams = j - i; - prm[lc].fe.stream = lprm->stream + i; - } - - return 0; -} - -int -main(int argc, char *argv[]) -{ - int32_t opt, opt_idx, rc; - uint32_t i; - uint64_t v; - struct tle_udp_ctx_param ctx_prm; - struct netfe_lcore_prm feprm; - struct rte_eth_stats stats; - char fecfg_fname[PATH_MAX + 1]; - char becfg_fname[PATH_MAX + 1]; - struct lcore_prm prm[RTE_MAX_LCORE]; - struct rte_eth_dev_info dev_info; - - fecfg_fname[0] = 0; - becfg_fname[0] = 0; - memset(prm, 0, sizeof(prm)); - - rc = rte_eal_init(argc, argv); - if (rc < 0) - rte_exit(EXIT_FAILURE, - "%s: rte_eal_init failed with error code: %d\n", - __func__, rc); - - memset(&ctx_prm, 0, sizeof(ctx_prm)); - - argc -= rc; - argv += rc; - - optind = 0; - optarg = NULL; - while ((opt = getopt_long(argc, argv, "B:PR:S:b:f:s:", long_opt, - &opt_idx)) != EOF) { - if (opt == OPT_SHORT_SBULK) { - rc = parse_uint_val(NULL, optarg, &v); - if (rc < 0) - rte_exit(EXIT_FAILURE, "%s: invalid value: %s " - "for option: \'%c\'\n", - __func__, optarg, opt); - ctx_prm.send_bulk_size = v; - } else if (opt == OPT_SHORT_PROMISC) { - becfg.promisc = 1; - } else if (opt == OPT_SHORT_RBUFS) { - rc = parse_uint_val(NULL, optarg, &v); - if (rc < 0) - rte_exit(EXIT_FAILURE, "%s: invalid value: %s " - "for option: \'%c\'\n", - __func__, optarg, opt); - ctx_prm.max_stream_rbufs = v; - } else if (opt == OPT_SHORT_SBUFS) { - rc = parse_uint_val(NULL, optarg, &v); - if (rc < 0) - rte_exit(EXIT_FAILURE, "%s: invalid value: %s " - "for option: \'%c\'\n", - __func__, optarg, opt); - ctx_prm.max_stream_sbufs = v; - } else if (opt == OPT_SHORT_STREAMS) { - rc = parse_uint_val(NULL, optarg, &v); - if (rc < 0) - rte_exit(EXIT_FAILURE, "%s: invalid value: %s " - "for option: \'%c\'\n", - __func__, optarg, opt); - ctx_prm.max_streams = v; - } else if (opt == OPT_SHORT_BECFG) { - snprintf(becfg_fname, sizeof(becfg_fname), "%s", - optarg); - } else if (opt == OPT_SHORT_FECFG) { - snprintf(fecfg_fname, sizeof(fecfg_fname), "%s", - optarg); - } else { - rte_exit(EXIT_FAILURE, - "%s: unknown option: \'%c\'\n", - __func__, opt); - } - } - - signal(SIGINT, sig_handle); - - rc = netbe_port_init(&becfg, argc - optind, argv + optind); - if (rc != 0) - rte_exit(EXIT_FAILURE, - "%s: netbe_port_init failed with error code: %d\n", - __func__, rc); - - rc = netbe_lcore_init(&becfg, &ctx_prm); - if (rc != 0) - sig_handle(SIGQUIT); - - if ((rc = netbe_dest_init(becfg_fname, &becfg)) != 0) - sig_handle(SIGQUIT); - - for (i = 0; i != becfg.prt_num && rc == 0; i++) { - RTE_LOG(NOTICE, USER1, "%s: starting port %u\n", - __func__, becfg.prt[i].id); - rc = rte_eth_dev_start(becfg.prt[i].id); - if (rc != 0) { - RTE_LOG(ERR, USER1, - "%s: rte_eth_dev_start(%u) returned " - "error code: %d\n", - __func__, becfg.prt[i].id, rc); - sig_handle(SIGQUIT); - } - rte_eth_dev_info_get(becfg.prt[i].id, &dev_info); - rc = update_rss_reta(&becfg.prt[i], &dev_info); - if (rc != 0) - sig_handle(SIGQUIT); - } - - feprm.max_streams = ctx_prm.max_streams * becfg.cpu_num; - if (rc == 0 && (rc = netfe_parse_cfg(fecfg_fname, &feprm)) != 0) - sig_handle(SIGQUIT); - - for (i = 0; rc == 0 && i != becfg.cpu_num; i++) - prm[becfg.cpu[i].id].be.lc = becfg.cpu + i; - - if (rc == 0 && (rc = netfe_lcore_fill(prm, &feprm)) != 0) - sig_handle(SIGQUIT); - - /* launch all slave lcores. */ - RTE_LCORE_FOREACH_SLAVE(i) { - if (prm[i].be.lc != NULL || prm[i].fe.max_streams != 0) - rte_eal_remote_launch(lcore_main, prm + i, i); - } - - /* launch master lcore. */ - i = rte_get_master_lcore(); - if (prm[i].be.lc != NULL || prm[i].fe.max_streams != 0) - lcore_main(prm + i); - - rte_eal_mp_wait_lcore(); - - for (i = 0; i != becfg.prt_num; i++) { - RTE_LOG(NOTICE, USER1, "%s: stoping port %u\n", - __func__, becfg.prt[i].id); - rte_eth_stats_get(becfg.prt[i].id, &stats); - RTE_LOG(NOTICE, USER1, "port %u stats={\n" - "ipackets=%" PRIu64 ";" - "ibytes=%" PRIu64 ";" - "ierrors=%" PRIu64 ";\n" - "opackets=%" PRIu64 ";" - "obytes=%" PRIu64 ";" - "oerrors=%" PRIu64 ";\n" - "}\n", - becfg.prt[i].id, - stats.ipackets, - stats.ibytes, - stats.ierrors, - stats.opackets, - stats.obytes, - stats.oerrors); - rte_eth_dev_stop(becfg.prt[i].id); - } - - netbe_lcore_fini(&becfg); - - return 0; -} diff --git a/examples/udpfwd/main_dpdk_legacy.h b/examples/udpfwd/main_dpdk_legacy.h deleted file mode 100644 index e4bff24..0000000 --- a/examples/udpfwd/main_dpdk_legacy.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2016 Intel Corporation. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef MAIN_DPDK_LEGACY_H_ -#define MAIN_DPDK_LEGACY_H_ - -#include "dpdk_version.h" - -/* - * Helper functions, verify the queue for corresponding UDP port. - */ -static uint8_t -verify_queue_for_port(const struct netbe_dev *prtq, const uint16_t lport) -{ - uint32_t align_nb_q, qid; - - align_nb_q = rte_align32pow2(prtq->port.nb_lcore); - qid = (lport % align_nb_q) % prtq->port.nb_lcore; - if (prtq->rxqid == qid) - return 1; - - return 0; -} - -/* - * UDP IPv4 destination lookup callback. - */ -static int -lpm4_dst_lookup(void *data, const struct in_addr *addr, - struct tle_udp_dest *res) -{ - int32_t rc; -#ifdef DPDK_VERSION_GE_1604 - uint32_t idx; -#else - uint8_t idx; -#endif - struct netbe_lcore *lc; - struct tle_udp_dest *dst; - - lc = data; - - rc = rte_lpm_lookup(lc->lpm4, rte_be_to_cpu_32(addr->s_addr), &idx); - if (rc == 0) { - dst = &lc->dst4[idx]; - rte_memcpy(res, dst, dst->l2_len + dst->l3_len + - offsetof(struct tle_udp_dest, hdr)); - } - return rc; -} - -static int -lcore_lpm_init(struct netbe_lcore *lc) -{ - int32_t sid; - char str[RTE_LPM_NAMESIZE]; -#ifdef DPDK_VERSION_GE_1604 - const struct rte_lpm_config lpm4_cfg = { - .max_rules = MAX_RULES, - .number_tbl8s = MAX_TBL8, - }; -#endif - const struct rte_lpm6_config lpm6_cfg = { - .max_rules = MAX_RULES, - .number_tbl8s = MAX_TBL8, - }; - - sid = rte_lcore_to_socket_id(lc->id); - - snprintf(str, sizeof(str), "LPM4%u\n", lc->id); -#ifdef DPDK_VERSION_GE_1604 - lc->lpm4 = rte_lpm_create(str, sid, &lpm4_cfg); -#else - lc->lpm4 = rte_lpm_create(str, sid, MAX_RULES, 0); -#endif - RTE_LOG(NOTICE, USER1, "%s(lcore=%u): lpm4=%p;\n", - __func__, lc->id, lc->lpm4); - if (lc->lpm4 == NULL) - return -ENOMEM; - - snprintf(str, sizeof(str), "LPM6%u\n", lc->id); - lc->lpm6 = rte_lpm6_create(str, sid, &lpm6_cfg); - RTE_LOG(NOTICE, USER1, "%s(lcore=%u): lpm6=%p;\n", - __func__, lc->id, lc->lpm6); - if (lc->lpm6 == NULL) - return -ENOMEM; - - return 0; -} - -/* - * Helper functions, finds BE by given local and remote addresses. - */ -static int -netbe_find4(const struct in_addr *laddr, const uint16_t lport, - const struct in_addr *raddr, const uint32_t be_lc) -{ - uint32_t i, j; -#ifdef DPDK_VERSION_GE_1604 - uint32_t idx; -#else - uint8_t idx; -#endif - struct netbe_lcore *bc; - - /* we have exactly one BE, use it for all traffic */ - if (becfg.cpu_num == 1) - return 0; - - /* search by provided be_lcore */ - if (be_lc != LCORE_ID_ANY) { - for (i = 0; i != becfg.cpu_num; i++) { - bc = becfg.cpu + i; - if (be_lc == bc->id) - return i; - } - RTE_LOG(NOTICE, USER1, "%s: no stream with be_lcore=%u\n", - __func__, be_lc); - return -ENOENT; - } - - /* search by local address */ - if (laddr->s_addr != INADDR_ANY) { - for (i = 0; i != becfg.cpu_num; i++) { - bc = becfg.cpu + i; - /* search by queue for the local port */ - for (j = 0; j != bc->prtq_num; j++) { - if (laddr->s_addr == bc->prtq[j].port.ipv4) { - - if (lport == 0) - return i; - - if (verify_queue_for_port(bc->prtq + j, - lport) != 0) - return i; - } - } - } - } - - /* search by remote address */ - if (raddr->s_addr != INADDR_ANY) { - for (i = 0; i != becfg.cpu_num; i++) { - bc = becfg.cpu + i; - if (rte_lpm_lookup(bc->lpm4, - rte_be_to_cpu_32(raddr->s_addr), - &idx) == 0) { - - if (lport == 0) - return i; - - /* search by queue for the local port */ - for (j = 0; j != bc->prtq_num; j++) - if (verify_queue_for_port(bc->prtq + j, - lport) != 0) - return i; - } - } - } - - return -ENOENT; -} - -#endif /* MAIN_DPDK_LEGACY_H_ */ diff --git a/examples/udpfwd/netbe.h b/examples/udpfwd/netbe.h deleted file mode 100644 index 1e5d9a7..0000000 --- a/examples/udpfwd/netbe.h +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (c) 2016 Intel Corporation. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __NETBE_H__ -#define __NETBE_H__ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAX_PKT_BURST 0x20 - -/* Used to allocate the memory for hash key. */ -#define RSS_HASH_KEY_LENGTH 64 - -/* - * BE related structures. - */ - -struct netbe_port { - uint32_t id; - uint32_t nb_lcore; - uint32_t *lcore; - uint32_t mtu; - uint32_t rx_offload; - uint32_t tx_offload; - uint32_t ipv4; - struct in6_addr ipv6; - struct ether_addr mac; - uint32_t hash_key_size; - uint8_t hash_key[RSS_HASH_KEY_LENGTH]; -}; - -struct netbe_dest { - uint32_t line; - uint32_t port; - uint32_t mtu; - uint32_t prfx; - uint16_t family; - union { - struct in_addr ipv4; - struct in6_addr ipv6; - }; - struct ether_addr mac; -}; - -struct netbe_dest_prm { - uint32_t nb_dest; - struct netbe_dest *dest; -}; - -struct pkt_buf { - uint32_t num; - struct rte_mbuf *pkt[2 * MAX_PKT_BURST]; -}; - -struct netbe_dev { - uint16_t rxqid; - uint16_t txqid; - struct netbe_port port; - struct tle_udp_dev *dev; - struct { - uint64_t in; - uint64_t up; - uint64_t drop; - } rx_stat; - struct { - uint64_t down; - uint64_t out; - uint64_t drop; - } tx_stat; - struct pkt_buf tx_buf; -}; - -/* 8 bit LPM user data. */ -#define LCORE_MAX_DST (UINT8_MAX + 1) - -struct netbe_lcore { - uint32_t id; - struct rte_lpm *lpm4; - struct rte_lpm6 *lpm6; - struct rte_ip_frag_tbl *ftbl; - struct tle_udp_ctx *ctx; - uint32_t prtq_num; - uint32_t dst4_num; - uint32_t dst6_num; - struct netbe_dev *prtq; - struct tle_udp_dest dst4[LCORE_MAX_DST]; - struct tle_udp_dest dst6[LCORE_MAX_DST]; - struct rte_ip_frag_death_row death_row; -}; - -struct netbe_cfg { - uint32_t promisc; - uint32_t prt_num; - uint32_t cpu_num; - struct netbe_port *prt; - struct netbe_lcore *cpu; -}; - -/* - * FE related structures. - */ - -enum { - RXONLY, - TXONLY, - RXTX, - FWD, -}; - -struct netfe_sprm { - uint32_t bidx; /* BE index to use. */ - struct tle_udp_stream_param prm; -}; - -struct netfe_stream_prm { - uint32_t lcore; - uint32_t be_lcore; - uint32_t line; - uint16_t op; - uint16_t txlen; /* valid/used only for TXONLY op. */ - struct netfe_sprm sprm; - struct netfe_sprm fprm; /* valid/used only for FWD op. */ -}; - -struct netfe_lcore_prm { - uint32_t max_streams; - uint32_t nb_streams; - struct netfe_stream_prm *stream; -}; - -struct netfe_stream { - struct tle_udp_stream *s; - struct tle_event *rxev; - struct tle_event *txev; - uint16_t op; - uint16_t family; - uint16_t txlen; - struct { - uint64_t rxp; - uint64_t txp; - uint64_t fwp; - uint64_t drops; - uint64_t rxev[TLE_SEV_NUM]; - uint64_t txev[TLE_SEV_NUM]; - } stat; - struct pkt_buf pbuf; - struct sockaddr_storage raddr; - struct netfe_sprm fwdprm; -}; - -struct netfe_lcore { - uint32_t snum; /* max number of streams */ - uint32_t sidx; /* last open stream index */ - struct tle_evq *rxeq; - struct tle_evq *txeq; - struct rte_hash *fw4h; - struct rte_hash *fw6h; - struct netfe_stream *fs; -}; - -struct lcore_prm { - struct { - struct netbe_lcore *lc; - } be; - struct netfe_lcore_prm fe; -}; - -/* - * debug/trace macros. - */ - -#define DUMMY_MACRO do {} while (0) - -#ifdef NETFE_DEBUG -#define NETFE_TRACE(fmt, arg...) printf(fmt, ##arg) -#define NETFE_PKT_DUMP(p) rte_pktmbuf_dump(stdout, (p), 64) -#else -#define NETFE_TRACE(fmt, arg...) DUMMY_MACRO -#define NETFE_PKT_DUMP(p) DUMMY_MACRO -#endif - -#ifdef NETBE_DEBUG -#define NETBE_TRACE(fmt, arg...) printf(fmt, ##arg) -#define NETBE_PKT_DUMP(p) rte_pktmbuf_dump(stdout, (p), 64) -#else -#define NETBE_TRACE(fmt, arg...) DUMMY_MACRO -#define NETBE_PKT_DUMP(p) DUMMY_MACRO -#endif - -#define FUNC_STAT(v, c) do { \ - static uint64_t nb_call, nb_data; \ - nb_call++; \ - nb_data += (v); \ - if ((nb_call & ((c) - 1)) == 0) { \ - printf("%s#%d@%u: nb_call=%lu, avg(" #v ")=%#Lf\n", \ - __func__, __LINE__, rte_lcore_id(), nb_call, \ - (long double)nb_data / nb_call); \ - nb_call = 0; \ - nb_data = 0; \ - } \ -} while (0) - -#define FUNC_TM_STAT(v, c) do { \ - static uint64_t nb_call, nb_data; \ - static uint64_t cts, pts, sts; \ - cts = rte_rdtsc(); \ - if (pts != 0) \ - sts += cts - pts; \ - pts = cts; \ - nb_call++; \ - nb_data += (v); \ - if ((nb_call & ((c) - 1)) == 0) { \ - printf("%s#%d@%u: nb_call=%lu, " \ - "avg(" #v ")=%#Lf, " \ - "avg(cycles)=%#Lf, " \ - "avg(cycles/" #v ")=%#Lf\n", \ - __func__, __LINE__, rte_lcore_id(), nb_call, \ - (long double)nb_data / nb_call, \ - (long double)sts / nb_call, \ - (long double)sts / nb_data); \ - nb_call = 0; \ - nb_data = 0; \ - sts = 0; \ - } \ -} while (0) - -int setup_rx_cb(const struct netbe_port *uprt, struct netbe_lcore *lc, - uint16_t qid); - -#endif /* __NETBE_H__ */ diff --git a/examples/udpfwd/parse.c b/examples/udpfwd/parse.c deleted file mode 100644 index f46c7df..0000000 --- a/examples/udpfwd/parse.c +++ /dev/null @@ -1,638 +0,0 @@ -/* - * Copyright (c) 2016 Intel Corporation. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "netbe.h" -#include "parse.h" - -#define DEF_LINE_NUM 0x400 - -static const struct { - const char *name; - uint16_t op; -} name2feop[] = { - { .name = "rx", .op = RXONLY,}, - { .name = "tx", .op = TXONLY,}, - { .name = "echo", .op = RXTX,}, - { .name = "fwd", .op = FWD,}, -}; - -static int -parse_ipv4_val(__rte_unused const char *key, const char *val, void *prm) -{ - union parse_val *rv; - - rv = prm; - if (inet_pton(AF_INET, val, &rv->in.addr4) != 1) - return -EINVAL; - rv->in.family = AF_INET; - return 0; -} - -static int -parse_ipv6_val(__rte_unused const char *key, const char *val, void *prm) -{ - union parse_val *rv; - - rv = prm; - if (inet_pton(AF_INET6, val, &rv->in.addr6) != 1) - return -EINVAL; - rv->in.family = AF_INET6; - return 0; -} - -static int -parse_ip_val(__rte_unused const char *key, const char *val, void *prm) -{ - if (parse_ipv6_val(key, val, prm) != 0 && - parse_ipv4_val(key, val, prm) != 0) - return -EINVAL; - return 0; -} - -#define PARSE_UINT8x16(s, v, l) \ -do { \ - char *end; \ - unsigned long t; \ - errno = 0; \ - t = strtoul((s), &end, 16); \ - if (errno != 0 || end[0] != (l) || t > UINT8_MAX) \ - return -EINVAL; \ - (s) = end + 1; \ - (v) = t; \ -} while (0) - -static int -parse_mac_val(__rte_unused const char *key, const char *val, void *prm) -{ - union parse_val *rv; - const char *s; - - rv = prm; - s = val; - - PARSE_UINT8x16(s, rv->mac.addr_bytes[0], ':'); - PARSE_UINT8x16(s, rv->mac.addr_bytes[1], ':'); - PARSE_UINT8x16(s, rv->mac.addr_bytes[2], ':'); - PARSE_UINT8x16(s, rv->mac.addr_bytes[3], ':'); - PARSE_UINT8x16(s, rv->mac.addr_bytes[4], ':'); - PARSE_UINT8x16(s, rv->mac.addr_bytes[5], 0); - return 0; -} - -static int -parse_feop_val(__rte_unused const char *key, const char *val, void *prm) -{ - uint32_t i; - union parse_val *rv; - - rv = prm; - for (i = 0; i != RTE_DIM(name2feop); i++) { - if (strcmp(val, name2feop[i].name) == 0) { - rv->u64 = name2feop[i].op; - return 0; - } - } - - return -EINVAL; -} - -static int -parse_lcore_list_val(__rte_unused const char *key, const char *val, void *prm) -{ - union parse_val *rv; - unsigned long a, b; - uint32_t i; - char *end; - - rv = prm; - errno = 0; - a = strtoul(val, &end, 0); - if (errno != 0 || (end[0] != 0 && end[0] != '-') || a > UINT32_MAX) - return -EINVAL; - - if (end[0] == '-') { - val = end + 1; - errno = 0; - b = strtoul(val, &end, 0); - if (errno != 0 || end[0] != 0 || b > UINT32_MAX) - return -EINVAL; - } else - b = a; - - if (a <= b) { - for (i = a; i <= b; i++) - CPU_SET(i, &rv->cpuset); - } else { - RTE_LOG(ERR, USER1, - "%s: lcores not in ascending order\n", __func__); - return -EINVAL; - } - - return 0; -} - -static int -parse_kvargs(const char *arg, const char *keys_man[], uint32_t nb_man, - const char *keys_opt[], uint32_t nb_opt, - const arg_handler_t hndl[], union parse_val val[]) -{ - uint32_t j, k; - struct rte_kvargs *kvl; - - kvl = rte_kvargs_parse(arg, NULL); - if (kvl == NULL) { - RTE_LOG(ERR, USER1, - "%s: invalid parameter: %s\n", - __func__, arg); - return -EINVAL; - } - - for (j = 0; j != nb_man; j++) { - if (rte_kvargs_count(kvl, keys_man[j]) == 0) { - RTE_LOG(ERR, USER1, - "%s: %s missing mandatory key: %s\n", - __func__, arg, keys_man[j]); - rte_kvargs_free(kvl); - return -EINVAL; - } - } - - for (j = 0; j != nb_man; j++) { - if (rte_kvargs_process(kvl, keys_man[j], hndl[j], - val + j) != 0) { - RTE_LOG(ERR, USER1, - "%s: %s invalid value for man key: %s\n", - __func__, arg, keys_man[j]); - rte_kvargs_free(kvl); - return -EINVAL; - } - } - - for (j = 0; j != nb_opt; j++) { - k = j + nb_man; - if (rte_kvargs_process(kvl, keys_opt[j], hndl[k], - val + k) != 0) { - RTE_LOG(ERR, USER1, - "%s: %s invalid value for opt key: %s\n", - __func__, arg, keys_opt[j]); - rte_kvargs_free(kvl); - return -EINVAL; - } - } - - rte_kvargs_free(kvl); - return 0; -} - -int -parse_netbe_arg(struct netbe_port *prt, const char *arg, rte_cpuset_t *cpuset) -{ - int32_t rc; - uint32_t i, j, nc; - - static const char *keys_man[] = { - "port", - "lcore", - }; - - static const char *keys_opt[] = { - "mtu", - "rx_offload", - "tx_offload", - "ipv4", - "ipv6", - }; - - static const arg_handler_t hndl[] = { - parse_uint_val, - parse_lcore_list_val, - parse_uint_val, - parse_uint_val, - parse_uint_val, - parse_ipv4_val, - parse_ipv6_val, - }; - - union parse_val val[RTE_DIM(hndl)]; - - memset(val, 0, sizeof(val)); - val[2].u64 = ETHER_MAX_VLAN_FRAME_LEN - ETHER_CRC_LEN; - - rc = parse_kvargs(arg, keys_man, RTE_DIM(keys_man), - keys_opt, RTE_DIM(keys_opt), hndl, val); - if (rc != 0) - return rc; - - prt->id = val[0].u64; - - for (i = 0, nc = 0; i < RTE_MAX_LCORE; i++) - nc += CPU_ISSET(i, &val[1].cpuset); - prt->lcore = rte_zmalloc(NULL, nc * sizeof(prt->lcore[0]), - RTE_CACHE_LINE_SIZE); - prt->nb_lcore = nc; - - for (i = 0, j = 0; i < RTE_MAX_LCORE; i++) - if (CPU_ISSET(i, &val[1].cpuset)) - prt->lcore[j++] = i; - CPU_OR(cpuset, cpuset, &val[1].cpuset); - - prt->mtu = val[2].u64; - prt->rx_offload = val[3].u64; - prt->tx_offload = val[4].u64; - prt->ipv4 = val[5].in.addr4.s_addr; - prt->ipv6 = val[6].in.addr6; - - return 0; -} - -static int -check_netbe_dest(const struct netbe_dest *dst) -{ - if (dst->port >= RTE_MAX_ETHPORTS) { - RTE_LOG(ERR, USER1, "%s(line=%u) invalid port=%u", - __func__, dst->line, dst->port); - return -EINVAL; - } else if ((dst->family == AF_INET && - dst->prfx > sizeof(struct in_addr) * CHAR_BIT) || - (dst->family == AF_INET6 && - dst->prfx > sizeof(struct in6_addr) * CHAR_BIT)) { - RTE_LOG(ERR, USER1, "%s(line=%u) invalid masklen=%u", - __func__, dst->line, dst->prfx); - return -EINVAL; - } else if (dst->mtu > ETHER_MAX_JUMBO_FRAME_LEN - ETHER_CRC_LEN) { - RTE_LOG(ERR, USER1, "%s(line=%u) invalid mtu=%u", - __func__, dst->line, dst->mtu); - return -EINVAL; - } - return 0; -} - -static int -parse_netbe_dest(struct netbe_dest *dst, const char *arg) -{ - int32_t rc; - - static const char *keys_man[] = { - "port", - "addr", - "masklen", - "mac", - }; - - static const char *keys_opt[] = { - "mtu", - }; - - static const arg_handler_t hndl[] = { - parse_uint_val, - parse_ip_val, - parse_uint_val, - parse_mac_val, - parse_uint_val, - }; - - union parse_val val[RTE_DIM(hndl)]; - - /* set default values. */ - memset(val, 0, sizeof(val)); - val[4].u64 = ETHER_MAX_JUMBO_FRAME_LEN - ETHER_CRC_LEN; - - rc = parse_kvargs(arg, keys_man, RTE_DIM(keys_man), - keys_opt, RTE_DIM(keys_opt), hndl, val); - if (rc != 0) - return rc; - - dst->port = val[0].u64; - dst->family = val[1].in.family; - if (val[1].in.family == AF_INET) - dst->ipv4 = val[1].in.addr4; - else - dst->ipv6 = val[1].in.addr6; - dst->prfx = val[2].u64; - memcpy(&dst->mac, &val[3].mac, sizeof(dst->mac)); - dst->mtu = val[4].u64; - - return 0; -} - -int -netbe_parse_dest(const char *fname, struct netbe_dest_prm *prm) -{ - uint32_t i, ln, n, num; - int32_t rc; - size_t sz; - char *s; - FILE *f; - struct netbe_dest *dp; - char line[LINE_MAX]; - - f = fopen(fname, "r"); - if (f == NULL) { - RTE_LOG(ERR, USER1, "%s failed to open file \"%s\"\n", - __func__, fname); - return -EINVAL; - } - - n = 0; - num = 0; - dp = NULL; - - for (ln = 0; fgets(line, sizeof(line), f) != NULL; ln++) { - - /* skip spaces at the start. */ - for (s = line; isspace(s[0]); s++) - ; - - /* skip comment line. */ - if (s[0] == '#' || s[0] == 0) - continue; - - /* skip spaces at the end. */ - for (i = strlen(s); i-- != 0 && isspace(s[i]); s[i] = 0) - ; - - if (n == num) { - num += DEF_LINE_NUM; - sz = sizeof(dp[0]) * num; - dp = realloc(dp, sizeof(dp[0]) * num); - if (dp == NULL) { - RTE_LOG(ERR, USER1, - "%s(%s) allocation of %zu bytes " - "failed\n", - __func__, fname, sz); - rc = -ENOMEM; - break; - } - memset(&dp[n], 0, sizeof(dp[0]) * (num - n)); - } - - dp[n].line = ln + 1; - if ((rc = parse_netbe_dest(dp + n, s)) != 0 || - (rc = check_netbe_dest(dp + n)) != 0) { - RTE_LOG(ERR, USER1, "%s(%s) failed to parse line %u\n", - __func__, fname, dp[n].line); - break; - } - n++; - } - - fclose(f); - - if (rc != 0) { - free(dp); - dp = NULL; - n = 0; - } - - prm->dest = dp; - prm->nb_dest = n; - return rc; -} - -static void -pv2saddr(struct sockaddr_storage *ss, const union parse_val *pva, - const union parse_val *pvp) -{ - ss->ss_family = pva->in.family; - if (pva->in.family == AF_INET) { - struct sockaddr_in *si = (struct sockaddr_in *)ss; - si->sin_addr = pva->in.addr4; - si->sin_port = rte_cpu_to_be_16((uint16_t)pvp->u64); - } else { - struct sockaddr_in6 *si = (struct sockaddr_in6 *)ss; - si->sin6_addr = pva->in.addr6; - si->sin6_port = rte_cpu_to_be_16((uint16_t)pvp->u64); - } -} - -static int -parse_netfe_arg(struct netfe_stream_prm *sp, const char *arg) -{ - int32_t rc; - - static const char *keys_man[] = { - "lcore", - "op", - "laddr", - "lport", - "raddr", - "rport", - }; - - static const char *keys_opt[] = { - "txlen", - "fwladdr", - "fwlport", - "fwraddr", - "fwrport", - "belcore", - }; - - static const arg_handler_t hndl[] = { - parse_uint_val, - parse_feop_val, - parse_ip_val, - parse_uint_val, - parse_ip_val, - parse_uint_val, - parse_uint_val, - parse_ip_val, - parse_uint_val, - parse_ip_val, - parse_uint_val, - parse_uint_val, - }; - - union parse_val val[RTE_DIM(hndl)]; - - memset(val, 0, sizeof(val)); - val[11].u64 = LCORE_ID_ANY; - rc = parse_kvargs(arg, keys_man, RTE_DIM(keys_man), - keys_opt, RTE_DIM(keys_opt), hndl, val); - if (rc != 0) - return rc; - sp->lcore = val[0].u64; - sp->op = val[1].u64; - pv2saddr(&sp->sprm.prm.local_addr, val + 2, val + 3); - pv2saddr(&sp->sprm.prm.remote_addr, val + 4, val + 5); - sp->txlen = val[6].u64; - pv2saddr(&sp->fprm.prm.local_addr, val + 7, val + 8); - pv2saddr(&sp->fprm.prm.remote_addr, val + 9, val + 10); - sp->be_lcore = val[11].u64; - - return 0; -} - -static const char * -format_feop(uint16_t op) -{ - uint32_t i; - - for (i = 0; i != RTE_DIM(name2feop); i++) { - if (name2feop[i].op == op) - return name2feop[i].name; - } - - return NULL; -} - -static int -is_addr_wc(const struct sockaddr_storage *sp) -{ - const struct sockaddr_in *i4; - const struct sockaddr_in6 *i6; - - if (sp->ss_family == AF_INET) { - i4 = (const struct sockaddr_in *)sp; - return (i4->sin_addr.s_addr == INADDR_ANY); - } else if (sp->ss_family == AF_INET6) { - i6 = (const struct sockaddr_in6 *)sp; - return (memcmp(&i6->sin6_addr, &in6addr_any, - sizeof(i6->sin6_addr)) == 0); - } - return 0; -} - -static int -check_netfe_arg(const struct netfe_stream_prm *sp) -{ - char buf[INET6_ADDRSTRLEN]; - - if (sp->sprm.prm.local_addr.ss_family != - sp->sprm.prm.remote_addr.ss_family) { - RTE_LOG(ERR, USER1, "invalid arg at line %u: " - "laddr and raddr for different protocols\n", - sp->line); - return -EINVAL; - } - - if (sp->op == TXONLY) { - if (sp->txlen > RTE_MBUF_DEFAULT_DATAROOM || sp->txlen == 0) { - RTE_LOG(ERR, USER1, "invalid arg at line %u: txlen=%u " - "exceeds allowed values: (0, %u]\n", - sp->line, sp->txlen, RTE_MBUF_DEFAULT_DATAROOM); - return -EINVAL; - } else if (is_addr_wc(&sp->sprm.prm.remote_addr)) { - RTE_LOG(ERR, USER1, "invalid arg at line %u: " - "raddr=%s are not allowed for op=%s;\n", - sp->line, - format_addr(&sp->sprm.prm.remote_addr, - buf, sizeof(buf)), - format_feop(sp->op)); - return -EINVAL; - } - } else if (sp->op == FWD) { - if (sp->fprm.prm.local_addr.ss_family != - sp->fprm.prm.remote_addr.ss_family) { - RTE_LOG(ERR, USER1, "invalid arg at line %u: " - "fwladdr and fwraddr for different protocols\n", - sp->line); - return -EINVAL; - } else if (is_addr_wc(&sp->fprm.prm.remote_addr)) { - RTE_LOG(ERR, USER1, "invalid arg at line %u: " - "fwaddr=%s are not allowed for op=%s;\n", - sp->line, - format_addr(&sp->fprm.prm.remote_addr, - buf, sizeof(buf)), - format_feop(sp->op)); - return -EINVAL; - } - } - - return 0; -} - -int -netfe_parse_cfg(const char *fname, struct netfe_lcore_prm *lp) -{ - uint32_t i, ln, n, num; - int32_t rc; - size_t sz; - char *s; - FILE *f; - struct netfe_stream_prm *sp; - char line[LINE_MAX]; - - f = fopen(fname, "r"); - if (f == NULL) { - RTE_LOG(ERR, USER1, "%s failed to open file \"%s\"\n", - __func__, fname); - return -EINVAL; - } - - n = 0; - num = 0; - sp = NULL; - - for (ln = 0; fgets(line, sizeof(line), f) != NULL; ln++) { - - /* skip spaces at the start. */ - for (s = line; isspace(s[0]); s++) - ; - - /* skip comment line. */ - if (s[0] == '#' || s[0] == 0) - continue; - - /* skip spaces at the end. */ - for (i = strlen(s); i-- != 0 && isspace(s[i]); s[i] = 0) - ; - - if (n == lp->max_streams) { - RTE_LOG(ERR, USER1, - "%s(%s) number of entries exceed max streams " - "value: %u\n", - __func__, fname, n); - rc = -EINVAL; - break; - } - - if (n == num) { - num += DEF_LINE_NUM; - sz = sizeof(sp[0]) * num; - sp = realloc(sp, sizeof(sp[0]) * num); - if (sp == NULL) { - RTE_LOG(ERR, USER1, - "%s(%s) allocation of %zu bytes " - "failed\n", - __func__, fname, sz); - rc = -ENOMEM; - break; - } - memset(&sp[n], 0, sizeof(sp[0]) * (num - n)); - } - - sp[n].line = ln + 1; - if ((rc = parse_netfe_arg(sp + n, s)) != 0 || - (rc = check_netfe_arg(sp + n)) != 0) { - RTE_LOG(ERR, USER1, "%s(%s) failed to parse line %u\n", - __func__, fname, sp[n].line); - break; - } - n++; - } - - fclose(f); - - if (rc != 0) { - free(sp); - sp = NULL; - n = 0; - } - - lp->stream = sp; - lp->nb_streams = n; - return rc; -} diff --git a/examples/udpfwd/parse.h b/examples/udpfwd/parse.h deleted file mode 100644 index 7df7671..0000000 --- a/examples/udpfwd/parse.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2016 Intel Corporation. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __PARSE_H__ -#define __PARSE_H__ - -#include - -#define PARSE_LIST_DELIM "-" - -union parse_val { - uint64_t u64; - struct { - uint16_t family; - union { - struct in_addr addr4; - struct in6_addr addr6; - }; - } in; - struct ether_addr mac; - rte_cpuset_t cpuset; -}; - -static int -parse_uint_val(__rte_unused const char *key, const char *val, void *prm) -{ - union parse_val *rv; - unsigned long v; - char *end; - - rv = prm; - errno = 0; - v = strtoul(val, &end, 0); - if (errno != 0 || end[0] != 0 || v > UINT32_MAX) - return -EINVAL; - - rv->u64 = v; - return 0; -} - -static const char * -format_addr(const struct sockaddr_storage *sp, char buf[], size_t len) -{ - const struct sockaddr_in *i4; - const struct sockaddr_in6 *i6; - const void *addr; - - if (sp->ss_family == AF_INET) { - i4 = (const struct sockaddr_in *)sp; - addr = &i4->sin_addr; - } else if (sp->ss_family == AF_INET6) { - i6 = (const struct sockaddr_in6 *)sp; - addr = &i6->sin6_addr; - } else - return NULL; - - - return inet_ntop(sp->ss_family, addr, buf, len); -} - -int parse_netbe_arg(struct netbe_port *prt, const char *arg, - rte_cpuset_t *cpuset); - -int netbe_parse_dest(const char *fname, struct netbe_dest_prm *prm); - -int netfe_parse_cfg(const char *fname, struct netfe_lcore_prm *lp); - -#endif /* __PARSE_H__ */ - diff --git a/examples/udpfwd/pkt.c b/examples/udpfwd/pkt.c deleted file mode 100644 index a68e428..0000000 --- a/examples/udpfwd/pkt.c +++ /dev/null @@ -1,509 +0,0 @@ -/* - * Copyright (c) 2016 Intel Corporation. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "netbe.h" -#include - -static inline uint64_t -_mbuf_tx_offload(uint64_t il2, uint64_t il3, uint64_t il4, uint64_t tso, - uint64_t ol3, uint64_t ol2) -{ - return il2 | il3 << 7 | il4 << 16 | tso << 24 | ol3 << 40 | ol2 << 49; -} - -static inline void -fill_pkt_hdr_len(struct rte_mbuf *m, uint32_t l2, uint32_t l3, uint32_t l4) -{ - m->tx_offload = _mbuf_tx_offload(l2, l3, l4, 0, 0, 0); -} - -static inline int -is_ipv4_frag(const struct ipv4_hdr *iph) -{ - const uint16_t mask = rte_cpu_to_be_16(~IPV4_HDR_DF_FLAG); - - return ((mask & iph->fragment_offset) != 0); -} - -static inline void -fill_ipv4_hdr_len(struct rte_mbuf *m, uint32_t l2, uint32_t proto, - uint32_t frag) -{ - const struct ipv4_hdr *iph; - int32_t dlen, len; - - dlen = rte_pktmbuf_data_len(m); - dlen -= l2 + sizeof(struct udp_hdr); - - iph = rte_pktmbuf_mtod_offset(m, const struct ipv4_hdr *, l2); - len = (iph->version_ihl & IPV4_HDR_IHL_MASK) * IPV4_IHL_MULTIPLIER; - - if (frag != 0 && is_ipv4_frag(iph)) { - m->packet_type &= ~RTE_PTYPE_L4_MASK; - m->packet_type |= RTE_PTYPE_L4_FRAG; - } - - if (len > dlen || (proto <= IPPROTO_MAX && iph->next_proto_id != proto)) - m->packet_type = RTE_PTYPE_UNKNOWN; - else - fill_pkt_hdr_len(m, l2, len, sizeof(struct udp_hdr)); -} - -static inline int -ipv6x_hdr(uint32_t proto) -{ - return (proto == IPPROTO_HOPOPTS || - proto == IPPROTO_ROUTING || - proto == IPPROTO_FRAGMENT || - proto == IPPROTO_AH || - proto == IPPROTO_NONE || - proto == IPPROTO_DSTOPTS); -} - -static inline void -fill_ipv6x_hdr_len(struct rte_mbuf *m, uint32_t l2, uint32_t nproto, - uint32_t fproto) -{ - const struct ip6_ext *ipx; - int32_t dlen, len, ofs; - - len = sizeof(struct ipv6_hdr); - - dlen = rte_pktmbuf_data_len(m); - dlen -= l2 + sizeof(struct udp_hdr); - - ofs = l2 + len; - ipx = rte_pktmbuf_mtod_offset(m, const struct ip6_ext *, ofs); - - while (ofs > 0 && len < dlen) { - - switch (nproto) { - case IPPROTO_HOPOPTS: - case IPPROTO_ROUTING: - case IPPROTO_DSTOPTS: - ofs = (ipx->ip6e_len + 1) << 3; - break; - case IPPROTO_AH: - ofs = (ipx->ip6e_len + 2) << 2; - break; - case IPPROTO_FRAGMENT: - /* - * tso_segsz is not used by RX, so suse it as temporary - * buffer to store the fragment offset. - */ - m->tso_segsz = ofs; - ofs = sizeof(struct ip6_frag); - m->packet_type &= ~RTE_PTYPE_L4_MASK; - m->packet_type |= RTE_PTYPE_L4_FRAG; - break; - default: - ofs = 0; - } - - if (ofs > 0) { - nproto = ipx->ip6e_nxt; - len += ofs; - ipx += ofs / sizeof(*ipx); - } - } - - /* undercognised or invalid packet. */ - if ((ofs == 0 && nproto != fproto) || len > dlen) - m->packet_type = RTE_PTYPE_UNKNOWN; - else - fill_pkt_hdr_len(m, l2, len, sizeof(struct udp_hdr)); -} - -static inline void -fill_ipv6_hdr_len(struct rte_mbuf *m, uint32_t l2, uint32_t fproto) -{ - const struct ipv6_hdr *iph; - - iph = rte_pktmbuf_mtod_offset(m, const struct ipv6_hdr *, - sizeof(struct ether_hdr)); - - if (iph->proto == fproto) - fill_pkt_hdr_len(m, l2, sizeof(struct ipv6_hdr), - sizeof(struct udp_hdr)); - else if (ipv6x_hdr(iph->proto) != 0) - fill_ipv6x_hdr_len(m, l2, iph->proto, fproto); -} - -static inline void -fill_eth_hdr_len(struct rte_mbuf *m) -{ - uint32_t dlen, l2; - uint16_t etp; - const struct ether_hdr *eth; - - dlen = rte_pktmbuf_data_len(m); - - /* check that first segment is at least 42B long. */ - if (dlen < sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) + - sizeof(struct udp_hdr)) { - m->packet_type = RTE_PTYPE_UNKNOWN; - return; - } - - l2 = sizeof(*eth); - - eth = rte_pktmbuf_mtod(m, const struct ether_hdr *); - etp = eth->ether_type; - if (etp == rte_be_to_cpu_16(ETHER_TYPE_VLAN)) - l2 += sizeof(struct vlan_hdr); - - if (etp == rte_be_to_cpu_16(ETHER_TYPE_IPv4)) { - m->packet_type = RTE_PTYPE_L4_UDP | - RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | - RTE_PTYPE_L2_ETHER; - fill_ipv4_hdr_len(m, l2, IPPROTO_UDP, 1); - } else if (etp == rte_be_to_cpu_16(ETHER_TYPE_IPv6) && - dlen >= l2 + sizeof(struct ipv6_hdr) + - sizeof(struct udp_hdr)) { - m->packet_type = RTE_PTYPE_L4_UDP | - RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | - RTE_PTYPE_L2_ETHER; - fill_ipv6_hdr_len(m, l2, IPPROTO_UDP); - } else - m->packet_type = RTE_PTYPE_UNKNOWN; -} - -static inline uint16_t -ipv4x_cksum(const void *iph, size_t len) -{ - uint16_t cksum; - - cksum = rte_raw_cksum(iph, len); - return (cksum == 0xffff) ? cksum : ~cksum; -} - -static inline void -fix_reassembled(struct rte_mbuf *m, int32_t hwcsum) -{ - struct ipv4_hdr *iph; - - /* update packet type. */ - m->packet_type &= ~RTE_PTYPE_L4_MASK; - m->packet_type |= RTE_PTYPE_L4_UDP; - - /* fix reassemble setting TX flags. */ - m->ol_flags &= ~PKT_TX_IP_CKSUM; - - /* fix l3_len after reassemble. */ - if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) - m->l3_len = m->l3_len - sizeof(struct ipv6_extension_fragment); - - /* recalculate ipv4 cksum after reassemble. */ - else if (hwcsum == 0 && RTE_ETH_IS_IPV4_HDR(m->packet_type)) { - iph = rte_pktmbuf_mtod_offset(m, struct ipv4_hdr *, m->l2_len); - iph->hdr_checksum = ipv4x_cksum(iph, m->l3_len); - } -} - -static struct rte_mbuf * -reassemble(struct rte_mbuf *m, struct netbe_lcore *lc, uint64_t tms, - uint8_t port) -{ - uint32_t l3cs; - struct rte_ip_frag_tbl *tbl; - struct rte_ip_frag_death_row *dr; - - tbl = lc->ftbl; - dr = &lc->death_row; - l3cs = lc->prtq[port].port.rx_offload & DEV_RX_OFFLOAD_IPV4_CKSUM; - - if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) { - - struct ipv4_hdr *iph; - - iph = rte_pktmbuf_mtod_offset(m, struct ipv4_hdr *, m->l2_len); - - /* process this fragment. */ - m = rte_ipv4_frag_reassemble_packet(tbl, dr, m, tms, iph); - - } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) { - - struct ipv6_hdr *iph; - struct ipv6_extension_fragment *fhdr; - - iph = rte_pktmbuf_mtod_offset(m, struct ipv6_hdr *, m->l2_len); - - /* - * we store fragment header offset in tso_segsz before - * temporary, just to avoid another scan of ipv6 header. - */ - fhdr = rte_pktmbuf_mtod_offset(m, - struct ipv6_extension_fragment *, m->tso_segsz); - m->tso_segsz = 0; - - /* process this fragment. */ - m = rte_ipv6_frag_reassemble_packet(tbl, dr, m, tms, iph, fhdr); - - } else { - rte_pktmbuf_free(m); - m = NULL; - } - - /* got reassembled packet. */ - if (m != NULL) - fix_reassembled(m, l3cs); - - return m; -} - -/* exclude NULLs from the final list of packets. */ -static inline uint32_t -compress_pkt_list(struct rte_mbuf *pkt[], uint32_t nb_pkt, uint32_t nb_zero) -{ - uint32_t i, j, k, l; - - for (j = nb_pkt; nb_zero != 0 && j-- != 0; ) { - - /* found a hole. */ - if (pkt[j] == NULL) { - - /* find how big is it. */ - for (i = j; i-- != 0 && pkt[i] == NULL; ) - ; - /* fill the hole. */ - for (k = j + 1, l = i + 1; k != nb_pkt; k++, l++) - pkt[l] = pkt[k]; - - nb_pkt -= j - i; - nb_zero -= j - i; - j = i + 1; - } - } - - return nb_pkt; -} - -/* - * HW can recognise L2/L3 with/without extentions/L4 (ixgbe/igb/fm10k) - */ -static uint16_t __rte_unused -type0_rx_callback(uint8_t port, __rte_unused uint16_t queue, - struct rte_mbuf *pkt[], uint16_t nb_pkts, - __rte_unused uint16_t max_pkts, void *user_param) -{ - uint32_t j, tp, x; - uint64_t cts; - struct netbe_lcore *lc; - - lc = user_param; - cts = 0; - - x = 0; - for (j = 0; j != nb_pkts; j++) { - - NETBE_PKT_DUMP(pkt[j]); - - tp = pkt[j]->packet_type & (RTE_PTYPE_L4_MASK | - RTE_PTYPE_L3_MASK | RTE_PTYPE_L2_MASK); - - switch (tp) { - /* non fragmented udp packets. */ - case (RTE_PTYPE_L4_UDP | RTE_PTYPE_L3_IPV4 | - RTE_PTYPE_L2_ETHER): - fill_pkt_hdr_len(pkt[j], sizeof(struct ether_hdr), - sizeof(struct ipv4_hdr), - sizeof(struct udp_hdr)); - break; - case (RTE_PTYPE_L4_UDP | RTE_PTYPE_L3_IPV6 | - RTE_PTYPE_L2_ETHER): - fill_pkt_hdr_len(pkt[j], sizeof(struct ether_hdr), - sizeof(struct ipv6_hdr), - sizeof(struct udp_hdr)); - break; - case (RTE_PTYPE_L4_UDP | RTE_PTYPE_L3_IPV4_EXT | - RTE_PTYPE_L2_ETHER): - fill_ipv4_hdr_len(pkt[j], sizeof(struct ether_hdr), - UINT32_MAX, 0); - break; - case (RTE_PTYPE_L4_UDP | RTE_PTYPE_L3_IPV6_EXT | - RTE_PTYPE_L2_ETHER): - fill_ipv6_hdr_len(pkt[j], sizeof(struct ether_hdr), - IPPROTO_UDP); - break; - /* possibly fragmented udp packets. */ - case (RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L2_ETHER): - case (RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_L2_ETHER): - fill_ipv4_hdr_len(pkt[j], sizeof(struct ether_hdr), - IPPROTO_UDP, 1); - break; - case (RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L2_ETHER): - case (RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L2_ETHER): - fill_ipv6_hdr_len(pkt[j], sizeof(struct ether_hdr), - IPPROTO_UDP); - break; - default: - /* treat packet types as invalid. */ - pkt[j]->packet_type = RTE_PTYPE_UNKNOWN; - break; - } - - /* - * if it is a fragment, try to reassemble it, - * if by some reason it can't be done, then - * set pkt[] entry to NULL. - */ - if ((pkt[j]->packet_type & RTE_PTYPE_L4_MASK) == - RTE_PTYPE_L4_FRAG) { - cts = (cts == 0) ? rte_rdtsc() : cts; - pkt[j] = reassemble(pkt[j], lc, cts, port); - x += (pkt[j] == NULL); - } - } - - /* reassemble was invoked, cleanup its death-row. */ - if (cts != 0) - rte_ip_frag_free_death_row(&lc->death_row, 0); - - if (x == 0) - return nb_pkts; - - NETBE_TRACE("%s(port=%u, queue=%u, nb_pkts=%u): " - "%u non-reassembled fragments;\n", - __func__, port, queue, nb_pkts, x); - - return compress_pkt_list(pkt, nb_pkts, x); -} - -/* - * HW can recognise L2/L3/L4 and fragments (i40e). - */ -static uint16_t __rte_unused -type1_rx_callback(uint8_t port, __rte_unused uint16_t queue, - struct rte_mbuf *pkt[], uint16_t nb_pkts, - __rte_unused uint16_t max_pkts, void *user_param) -{ - uint32_t j, tp, x; - uint64_t cts; - struct netbe_lcore *lc; - - lc = user_param; - cts = 0; - - x = 0; - for (j = 0; j != nb_pkts; j++) { - - NETBE_PKT_DUMP(pkt[j]); - - tp = pkt[j]->packet_type & (RTE_PTYPE_L4_MASK | - RTE_PTYPE_L3_MASK | RTE_PTYPE_L2_MASK); - - switch (tp) { - case (RTE_PTYPE_L4_UDP | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | - RTE_PTYPE_L2_ETHER): - fill_ipv4_hdr_len(pkt[j], sizeof(struct ether_hdr), - UINT32_MAX, 0); - break; - case (RTE_PTYPE_L4_UDP | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | - RTE_PTYPE_L2_ETHER): - fill_ipv6_hdr_len(pkt[j], sizeof(struct ether_hdr), - IPPROTO_UDP); - break; - case (RTE_PTYPE_L4_FRAG | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | - RTE_PTYPE_L2_ETHER): - fill_ipv4_hdr_len(pkt[j], sizeof(struct ether_hdr), - IPPROTO_UDP, 0); - break; - case (RTE_PTYPE_L4_FRAG | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | - RTE_PTYPE_L2_ETHER): - fill_ipv6_hdr_len(pkt[j], sizeof(struct ether_hdr), - IPPROTO_UDP); - break; - default: - /* treat packet types as invalid. */ - pkt[j]->packet_type = RTE_PTYPE_UNKNOWN; - break; - } - - /* - * if it is a fragment, try to reassemble it, - * if by some reason it can't be done, then - * set pkt[] entry to NULL. - */ - if ((pkt[j]->packet_type & RTE_PTYPE_L4_MASK) == - RTE_PTYPE_L4_FRAG) { - cts = (cts == 0) ? rte_rdtsc() : cts; - pkt[j] = reassemble(pkt[j], lc, cts, port); - x += (pkt[j] == NULL); - } - } - - /* reassemble was invoked, cleanup its death-row. */ - if (cts != 0) - rte_ip_frag_free_death_row(&lc->death_row, 0); - - if (x == 0) - return nb_pkts; - - NETBE_TRACE("%s(port=%u, queue=%u, nb_pkts=%u): " - "%u non-reassembled fragments;\n", - __func__, port, queue, nb_pkts, x); - - return compress_pkt_list(pkt, nb_pkts, x); -} - -/* - * generic, assumes HW doesn't recognise any packet type. - */ -static uint16_t -typen_rx_callback(uint8_t port, __rte_unused uint16_t queue, - struct rte_mbuf *pkt[], uint16_t nb_pkts, - __rte_unused uint16_t max_pkts, void *user_param) -{ - uint32_t j, x; - uint64_t cts; - struct netbe_lcore *lc; - - lc = user_param; - cts = 0; - - x = 0; - for (j = 0; j != nb_pkts; j++) { - - NETBE_PKT_DUMP(pkt[j]); - fill_eth_hdr_len(pkt[j]); - - /* - * if it is a fragment, try to reassemble it, - * if by some reason it can't be done, then - * set pkt[] entry to NULL. - */ - if ((pkt[j]->packet_type & RTE_PTYPE_L4_MASK) == - RTE_PTYPE_L4_FRAG) { - cts = (cts == 0) ? rte_rdtsc() : cts; - pkt[j] = reassemble(pkt[j], lc, cts, port); - x += (pkt[j] == NULL); - } - } - - /* reassemble was invoked, cleanup its death-row. */ - if (cts != 0) - rte_ip_frag_free_death_row(&lc->death_row, 0); - - if (x == 0) - return nb_pkts; - - NETBE_TRACE("%s(port=%u, queue=%u, nb_pkts=%u): " - "%u non-reassembled fragments;\n", - __func__, port, queue, nb_pkts, x); - - return compress_pkt_list(pkt, nb_pkts, x); -} - -#include "pkt_dpdk_legacy.h" diff --git a/examples/udpfwd/pkt_dpdk_legacy.h b/examples/udpfwd/pkt_dpdk_legacy.h deleted file mode 100644 index c32f044..0000000 --- a/examples/udpfwd/pkt_dpdk_legacy.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2016 Intel Corporation. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef PKT_DPDK_LEGACY_H_ -#define PKT_DPDK_LEGACY_H_ - -#include "dpdk_version.h" - -#ifdef DPDK_VERSION_GE_1604 - -int -setup_rx_cb(const struct netbe_port *uprt, struct netbe_lcore *lc, - uint16_t qid) -{ - int32_t i, rc; - uint32_t smask; - void *cb; - - const uint32_t pmask = RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK | - RTE_PTYPE_L4_MASK; - - enum { - ETHER_PTYPE = 0x1, - IPV4_PTYPE = 0x2, - IPV4_EXT_PTYPE = 0x4, - IPV6_PTYPE = 0x8, - IPV6_EXT_PTYPE = 0x10, - UDP_PTYPE = 0x20, - }; - - static const struct { - uint32_t mask; - const char *name; - rte_rx_callback_fn fn; - } ptype2cb[] = { - { - .mask = ETHER_PTYPE | IPV4_PTYPE | IPV4_EXT_PTYPE | - IPV6_PTYPE | IPV6_EXT_PTYPE | UDP_PTYPE, - .name = "HW l2/l3x/l4 ptype", - .fn = type0_rx_callback, - }, - { - .mask = ETHER_PTYPE | IPV4_PTYPE | IPV6_PTYPE | - UDP_PTYPE, - .name = "HW l2/l3/l4 ptype", - .fn = type1_rx_callback, - }, - { - .mask = 0, - .name = "no HW ptype", - .fn = typen_rx_callback, - }, - }; - - smask = 0; - rc = rte_eth_dev_get_supported_ptypes(uprt->id, pmask, NULL, 0); - if (rc < 0) { - RTE_LOG(ERR, USER1, - "%s(port=%u) failed to get supported ptypes;\n", - __func__, uprt->id); - return rc; - } - - uint32_t ptype[rc]; - rc = rte_eth_dev_get_supported_ptypes(uprt->id, pmask, ptype, rc); - - for (i = 0; i != rc; i++) { - switch (ptype[i]) { - case RTE_PTYPE_L2_ETHER: - smask |= ETHER_PTYPE; - break; - case RTE_PTYPE_L3_IPV4: - case RTE_PTYPE_L3_IPV4_EXT_UNKNOWN: - smask |= IPV4_PTYPE; - break; - case RTE_PTYPE_L3_IPV4_EXT: - smask |= IPV4_EXT_PTYPE; - break; - case RTE_PTYPE_L3_IPV6: - case RTE_PTYPE_L3_IPV6_EXT_UNKNOWN: - smask |= IPV6_PTYPE; - break; - case RTE_PTYPE_L3_IPV6_EXT: - smask |= IPV6_EXT_PTYPE; - break; - case RTE_PTYPE_L4_UDP: - smask |= UDP_PTYPE; - break; - } - } - - for (i = 0; i != RTE_DIM(ptype2cb); i++) { - if ((smask & ptype2cb[i].mask) == ptype2cb[i].mask) { - cb = rte_eth_add_rx_callback(uprt->id, qid, - ptype2cb[i].fn, lc); - rc = -rte_errno; - RTE_LOG(ERR, USER1, - "%s(port=%u), setup RX callback \"%s\" " - "returns %p;\n", - __func__, uprt->id, ptype2cb[i].name, cb); - return ((cb == NULL) ? rc : 0); - } - } - - /* no proper callback found. */ - RTE_LOG(ERR, USER1, - "%s(port=%u) failed to find an appropriate callback;\n", - __func__, uprt->id); - return -ENOENT; -} - -#else - -int -setup_rx_cb(const struct netbe_port *uprt, struct netbe_lcore *lc, - uint16_t qid) -{ - void *cb; - int32_t rc; - - cb = rte_eth_add_rx_callback(uprt->id, qid, typen_rx_callback, lc); - rc = -rte_errno; - RTE_LOG(ERR, USER1, - "%s(port=%u), setup RX callback \"%s\" " - "returns %p;\n", - __func__, uprt->id, "no HW ptype", cb); - - return ((cb == NULL) ? rc : 0); -} - -#endif /* DPDK_VERSION_GE_1604 */ - -#endif /* PKT_DPDK_LEGACY_H_ */ -- cgit 1.2.3-korg