From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by dpdk.org (Postfix) with ESMTP id 98302255 for ; Fri, 30 Jan 2015 12:27:17 +0100 (CET) Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga102.jf.intel.com with ESMTP; 30 Jan 2015 03:23:57 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.09,491,1418112000"; d="scan'208";a="520155688" Received: from irsmsx108.ger.corp.intel.com ([163.33.3.3]) by orsmga003.jf.intel.com with ESMTP; 30 Jan 2015 03:19:57 -0800 Received: from irsmsx109.ger.corp.intel.com ([169.254.13.11]) by IRSMSX108.ger.corp.intel.com ([169.254.11.64]) with mapi id 14.03.0195.001; Fri, 30 Jan 2015 11:27:13 +0000 From: "Jastrzebski, MichalX K" To: "dev@dpdk.org" Thread-Topic: [dpdk-dev] [PATCH 4/4] bond: added example application for link bonding mode 6. Thread-Index: AQHQPHv8XxktZtRwV0a/jUd9Oh0qB5zYgrLg Date: Fri, 30 Jan 2015 11:27:12 +0000 Message-ID: <60ABE07DBB3A454EB7FAD707B4BB1582138D65A1@IRSMSX109.ger.corp.intel.com> References: <1422615464-4432-1-git-send-email-michalx.k.jastrzebski@intel.com> <1422615464-4432-5-git-send-email-michalx.k.jastrzebski@intel.com> In-Reply-To: <1422615464-4432-5-git-send-email-michalx.k.jastrzebski@intel.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [163.33.239.180] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: Re: [dpdk-dev] [PATCH 4/4] bond: added example application for link bonding mode 6. X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 30 Jan 2015 11:27:18 -0000 > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Michal Jastrzebski > Sent: Friday, January 30, 2015 11:58 AM > To: dev@dpdk.org > Subject: [dpdk-dev] [PATCH 4/4] bond: added example application for link > bonding mode 6. >=20 >=20 > Signed-off-by: Michal Jastrzebski > Signed-off-by: Maciej Gajdzica > --- > examples/bond/Makefile | 57 ++++ > examples/bond/main.c | 790 > ++++++++++++++++++++++++++++++++++++++++++++++++ > examples/bond/main.h | 46 +++ > 3 files changed, 893 insertions(+) > create mode 100644 examples/bond/Makefile > create mode 100644 examples/bond/main.c > create mode 100644 examples/bond/main.h >=20 > diff --git a/examples/bond/Makefile b/examples/bond/Makefile > new file mode 100644 > index 0000000..9262249 > --- /dev/null > +++ b/examples/bond/Makefile > @@ -0,0 +1,57 @@ > +# BSD LICENSE > +# > +# Copyright(c) 2010-2014 Intel Corporation. All rights reserved. > +# All rights reserved. > +# > +# Redistribution and use in source and binary forms, with or without > +# modification, are permitted provided that the following conditions > +# are met: > +# > +# * Redistributions of source code must retain the above copyright > +# notice, this list of conditions and the following disclaimer. > +# * Redistributions in binary form must reproduce the above copyrigh= t > +# notice, this list of conditions and the following disclaimer in > +# the documentation and/or other materials provided with the > +# distribution. > +# * Neither the name of Intel Corporation nor the names of its > +# contributors may be used to endorse or promote products derived > +# from this software without specific prior written permission. > +# > +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > CONTRIBUTORS > +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT > NOT > +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND > FITNESS FOR > +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE > COPYRIGHT > +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, > INCIDENTAL, > +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > NOT > +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS > OF USE, > +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED > AND ON ANY > +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR > TORT > +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF > THE USE > +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH > DAMAGE. > + > +ifeq ($(RTE_SDK),) > +$(error "Please define RTE_SDK environment variable") > +endif > + > +# Default target, can be overriden by command line or environment > +RTE_TARGET ?=3D x86_64-native-linuxapp-gcc > + > +include $(RTE_SDK)/mk/rte.vars.mk > + > +# binary name > +APP =3D bond_app > + > +# all source are stored in SRCS-y > +SRCS-y :=3D main.c > + > +CFLAGS +=3D $(WERROR_FLAGS) > + > +# workaround for a gcc bug with noreturn attribute > +# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D12603 > +ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) > +CFLAGS_main.o +=3D -Wno-return-type > +endif > + > +CFLAGS +=3D -O3 > + > +include $(RTE_SDK)/mk/rte.extapp.mk > diff --git a/examples/bond/main.c b/examples/bond/main.c > new file mode 100644 > index 0000000..57cc672 > --- /dev/null > +++ b/examples/bond/main.c > @@ -0,0 +1,790 @@ > +/*- > + * BSD LICENSE > + * > + * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * > + * * Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * * Redistributions in binary form must reproduce the above copyrig= ht > + * notice, this list of conditions and the following disclaimer in > + * the documentation and/or other materials provided with the > + * distribution. > + * * Neither the name of Intel Corporation nor the names of its > + * contributors may be used to endorse or promote products derived > + * from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > CONTRIBUTORS > + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT > NOT > + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND > FITNESS FOR > + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE > COPYRIGHT > + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, > INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > NOT > + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS > OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED > AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR > TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF > THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH > DAMAGE. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "main.h" > + > +#include > + > + > +#include "rte_byteorder.h" > +#include "rte_cpuflags.h" > +#include "rte_eth_bond.h" > + > +#define RTE_LOGTYPE_DCB RTE_LOGTYPE_USER1 > + > +#define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + > RTE_PKTMBUF_HEADROOM) > +#define NB_MBUF (1024*8) > + > +#define MAX_PKT_BURST 32 > +#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ > +#define BURST_RX_INTERVAL_NS (10) /* RX poll interval ~100ns */ > + > +/* > + * RX and TX Prefetch, Host, and Write-back threshold values should be > + * carefully set for optimal performance. Consult the network > + * controller's datasheet and supporting DPDK documentation for guidance > + * on how these parameters should be set. > + */ > +#define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. *= / > +#define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */ > +#define RX_WTHRESH 4 /**< Default values of RX write-back threshold reg. > */ > +#define RX_FTHRESH (MAX_PKT_BURST * 2)/**< Default values of RX free > threshold reg. */ > + > +/* > + * These default values are optimized for use with the Intel(R) 82599 10= GbE > + * Controller and the DPDK ixgbe PMD. Consider using other values for ot= her > + * network controllers and/or network drivers. > + */ > +#define TX_PTHRESH 36 /**< Default values of TX prefetch threshold reg. = */ > +#define TX_HTHRESH 0 /**< Default values of TX host threshold reg. */ > +#define TX_WTHRESH 0 /**< Default values of TX write-back threshold reg= . > */ > + > +/* > + * Configurable number of RX/TX ring descriptors > + */ > +#define RTE_RX_DESC_DEFAULT 128 > +#define RTE_TX_DESC_DEFAULT 512 > + > +#define BOND_IP_1 7 > +#define BOND_IP_2 0 > +#define BOND_IP_3 0 > +#define BOND_IP_4 10 > + > +/* not defined under linux */ > +#ifndef NIPQUAD > +#define NIPQUAD_FMT "%u.%u.%u.%u" > +#define NIPQUAD(addr) \ > + (unsigned)((unsigned char *)&addr)[0], \ > + (unsigned)((unsigned char *)&addr)[1], \ > + (unsigned)((unsigned char *)&addr)[2], \ > + (unsigned)((unsigned char *)&addr)[3] > +#endif > + > +#define MAX_PORTS 4 > +#define PRINT_MAC(addr) > printf("%02"PRIx8":%02"PRIx8":%02"PRIx8 \ > + ":%02"PRIx8":%02"PRIx8":%02"PRIx8, \ > + addr.addr_bytes[0], addr.addr_bytes[1], addr.addr_bytes[2], \ > + addr.addr_bytes[3], addr.addr_bytes[4], addr.addr_bytes[5]) > + > +uint8_t slaves[RTE_MAX_ETHPORTS]; > +uint8_t slaves_count; > + > +static uint8_t BOND_PORT =3D 0xff; > + > +static struct rte_mempool *mbuf_pool; > + > +/* > + * RX and TX Prefetch, Host, and Write-back threshold values should be > + * carefully set for optimal performance. Consult the network > + * controller's datasheet and supporting DPDK documentation for guidance > + * on how these parameters should be set. > + */ > +/* Default configuration for rx and tx thresholds etc. */ > +static const struct rte_eth_rxconf rx_conf_default =3D { > + .rx_thresh =3D { > + .pthresh =3D RX_PTHRESH, > + .hthresh =3D RX_HTHRESH, > + .wthresh =3D RX_WTHRESH, > + > + }, > + .rx_free_thresh =3D RX_FTHRESH, > +}; > + > +/* > + * These default values are optimized for use with the Intel(R) 82599 10= GbE > + * Controller and the DPDK ixgbe PMD. Consider using other values for ot= her > + * network controllers and/or network drivers. > + */ > +static const struct rte_eth_txconf tx_conf_default =3D { > + .tx_thresh =3D { > + .pthresh =3D TX_PTHRESH, > + .hthresh =3D TX_HTHRESH, > + .wthresh =3D TX_WTHRESH, > + }, > + .tx_free_thresh =3D 0, /* Use PMD default values */ > + .tx_rs_thresh =3D 0, /* Use PMD default values */ > + .txq_flags =3D ETH_TXQ_FLAGS_NOMULTSEGS | > ETH_TXQ_FLAGS_NOOFFLOADS, > +}; > + > +static struct rte_eth_conf port_conf =3D { > + .rxmode =3D { > + .mq_mode =3D ETH_MQ_RX_NONE, > + .max_rx_pkt_len =3D ETHER_MAX_LEN, > + .split_hdr_size =3D 0, > + .header_split =3D 0, /**< Header Split disabled */ > + .hw_ip_checksum =3D 0, /**< IP checksum offload enabled */ > + .hw_vlan_filter =3D 0, /**< VLAN filtering disabled */ > + .jumbo_frame =3D 0, /**< Jumbo Frame Support disabled */ > + .hw_strip_crc =3D 0, /**< CRC stripped by hardware */ > + }, > + .rx_adv_conf =3D { > + .rss_conf =3D { > + .rss_key =3D NULL, > + .rss_hf =3D ETH_RSS_IP, > + }, > + }, > + .txmode =3D { > + .mq_mode =3D ETH_MQ_TX_NONE, > + }, > +}; > + > +static void > +slave_port_init(uint8_t portid, struct rte_mempool *mbuf_pool) > +{ > + int retval; > + > + if (portid >=3D rte_eth_dev_count()) > + rte_exit(EXIT_FAILURE, "Invalid port\n"); > + > + retval =3D rte_eth_dev_configure(portid, 1, 1, &port_conf); > + if (retval !=3D 0) > + rte_exit(EXIT_FAILURE, "port %u: configuration failed > (res=3D%d)\n", \ > + portid, retval); > + > + /* RX setup */ > + retval =3D rte_eth_rx_queue_setup(portid, 0, RTE_RX_DESC_DEFAULT, > + rte_eth_dev_socket_id(portid), > &rx_conf_default, > + mbuf_pool); > + if (retval < 0) > + rte_exit(retval, " port %u: RX queue 0 setup failed (res=3D%d)", > \ > + portid, retval); > + > + /* TX setup */ > + retval =3D rte_eth_tx_queue_setup(portid, 0, RTE_TX_DESC_DEFAULT, > + rte_eth_dev_socket_id(portid), > &tx_conf_default); > + > + if (retval < 0) > + rte_exit(retval, "port %u: TX queue 0 setup failed (res=3D%d)", \ > + portid, retval); > + > + retval =3D rte_eth_dev_start(portid); > + if (retval < 0) > + rte_exit(retval, \ > + "Start port %d failed (res=3D%d)", \ > + portid, retval); > + > + struct ether_addr addr; > + rte_eth_macaddr_get(portid, &addr); > + printf("Port %u MAC: ", (unsigned)portid); > + PRINT_MAC(addr); > + printf("\n"); > +} > + > +static void > +bond_port_init(struct rte_mempool *mbuf_pool) > +{ > + int retval; > + uint8_t i; > + > + retval =3D rte_eth_bond_create("bond0", BONDING_MODE_ALB, 0 > /*SOCKET_ID_ANY*/); > + if (retval < 0) > + rte_exit(EXIT_FAILURE, \ > + "Faled to create bond port\n"); > + > + BOND_PORT =3D (uint8_t)retval; > + > + retval =3D rte_eth_dev_configure(BOND_PORT, 1, 1, &port_conf); > + if (retval !=3D 0) > + rte_exit(EXIT_FAILURE, "port %u: configuration failed > (res=3D%d)\n", \ > + BOND_PORT, retval); > + > + /* RX setup */ > + retval =3D rte_eth_rx_queue_setup(BOND_PORT, 0, > RTE_RX_DESC_DEFAULT, > + rte_eth_dev_socket_id(BOND_PORT), > &rx_conf_default, > + mbuf_pool); > + if (retval < 0) > + rte_exit(retval, " port %u: RX queue 0 setup failed (res=3D%d)", > \ > + BOND_PORT, retval); > + > + /* TX setup */ > + retval =3D rte_eth_tx_queue_setup(BOND_PORT, 0, > RTE_TX_DESC_DEFAULT, > + rte_eth_dev_socket_id(BOND_PORT), > &tx_conf_default); > + > + if (retval < 0) > + rte_exit(retval, "port %u: TX queue 0 setup failed (res=3D%d)", \ > + BOND_PORT, retval); > + > + for (i =3D 0; i < slaves_count; i++) { > + if (rte_eth_bond_slave_add(BOND_PORT, slaves[i]) =3D=3D -1) > + rte_exit(-1, "Oooops! adding slave (%u) to bond (%u) > failed!\n", \ > + slaves[i], BOND_PORT); > + > + } > + > + retval =3D rte_eth_dev_start(BOND_PORT); > + if (retval < 0) > + rte_exit(retval, "Start port %d failed (res=3D%d)", BOND_PORT, > retval); > + > + rte_eth_promiscuous_enable(BOND_PORT); > + > + struct ether_addr addr; > + rte_eth_macaddr_get(BOND_PORT, &addr); > + printf("Port %u MAC: ", (unsigned)BOND_PORT); > + PRINT_MAC(addr); > + printf("\n"); > +} > + > +struct global_flag_stru_t { > + int LcoreMainIsRunning; > + int LcoreMainCore; > + uint32_t port_packets[4]; > + rte_spinlock_t lock; > +}; > +struct global_flag_stru_t global_flag_stru; > +struct global_flag_stru_t *global_flag_stru_p =3D &global_flag_stru; > + > +/* > + * Main thread that does the work, reading from INPUT_PORT > + * and writing to OUTPUT_PORT > + */ > +static int lcore_main(__attribute__((unused)) void *arg1) > +{ > + struct rte_mbuf *pkts[MAX_PKT_BURST] __rte_cache_aligned; > + struct ether_addr d_addr; > + > + struct ether_hdr *eth_hdr; > + struct arp_hdr *arp_hdr; > + > + uint16_t rx_cnt; > + uint32_t bond_ip; > + int i =3D 0; > + uint8_t is_free; > + > + bond_ip =3D BOND_IP_1 | (BOND_IP_2 << 8) | > + (BOND_IP_3 << 16) | (BOND_IP_4 << 24); > + > + rte_spinlock_trylock(&global_flag_stru_p->lock); > + > + while (global_flag_stru_p->LcoreMainIsRunning) { > + rte_spinlock_unlock(&global_flag_stru_p->lock); > + rx_cnt =3D rte_eth_rx_burst(BOND_PORT, 0, pkts, > MAX_PKT_BURST); > + is_free =3D 0; > + > + /* If didn't receive any packets, wait and go to next iteration > */ > + if (rx_cnt =3D=3D 0) { > + rte_delay_us(50); > + continue; > + } > + > + /* Search incoming data for ARP packets and prepare > response */ > + for (i =3D 0; i < rx_cnt; i++) { > + if (rte_spinlock_trylock(&global_flag_stru_p->lock) =3D=3D > 1) { > + global_flag_stru_p->port_packets[0]++; > + rte_spinlock_unlock(&global_flag_stru_p- > >lock); > + } > + eth_hdr =3D rte_pktmbuf_mtod(pkts[i], struct > ether_hdr *); > + if (eth_hdr->ether_type =3D=3D > rte_cpu_to_be_16(ETHER_TYPE_ARP)) { > + if (rte_spinlock_trylock(&global_flag_stru_p- > >lock) =3D=3D 1) { > + > global_flag_stru_p->port_packets[1]++; > + > rte_spinlock_unlock(&global_flag_stru_p->lock); > + } > + arp_hdr =3D (struct arp_hdr *)((char *)eth_hdr > + sizeof(struct ether_hdr)); > + if (arp_hdr->arp_data.arp_tip =3D=3D bond_ip) { > + if (arp_hdr->arp_op =3D=3D > rte_cpu_to_be_16(ARP_OP_REQUEST)) { > + arp_hdr->arp_op =3D > rte_cpu_to_be_16(ARP_OP_REPLY); > + > + /* Switch src and dst data > and set bonding MAC */ > + ether_addr_copy(ð_hdr- > >s_addr, ð_hdr->d_addr); > + > rte_eth_macaddr_get(BOND_PORT, ð_hdr->s_addr); > + ether_addr_copy(&arp_hdr- > >arp_data.arp_sha, &arp_hdr->arp_data.arp_tha); > + arp_hdr->arp_data.arp_tip =3D > arp_hdr->arp_data.arp_sip; > + > rte_eth_macaddr_get(BOND_PORT, &d_addr); > + ether_addr_copy(&d_addr, > &arp_hdr->arp_data.arp_sha); > + arp_hdr->arp_data.arp_sip =3D > bond_ip; > + > rte_eth_tx_burst(BOND_PORT, 0, &pkts[i], 1); > + is_free =3D 1; > + } else { > + > rte_eth_tx_burst(BOND_PORT, 0, NULL, 0); > + } > + } > + } > + > + /* Free processed packets */ > + if (is_free =3D=3D 0) > + rte_pktmbuf_free(pkts[i]); > + } > + rte_spinlock_trylock(&global_flag_stru_p->lock); > + } > + rte_spinlock_unlock(&global_flag_stru_p->lock); > + printf("BYE lcore_main\n"); > + return 0; > +} > + > +/**********************************************************/ > +/**********************************************************/ > +struct cmd_obj_send_result { > + cmdline_fixed_string_t action; > + uint32_t count; > + cmdline_ipaddr_t ip; > +}; > + > +static void cmd_obj_send_parsed(void *parsed_result, > + __attribute__((unused)) struct cmdline *cl, > + __attribute__((unused)) void *data) > +{ > + > + struct cmd_obj_send_result *res =3D parsed_result; > + char ip_str[INET6_ADDRSTRLEN]; > + > + struct rte_mbuf *created_pkt; > + struct ether_hdr *eth_hdr; > + struct arp_hdr *arp_hdr; > + > + uint32_t bond_ip; > + size_t pkt_size; > + > + if (res->ip.family =3D=3D AF_INET) > + snprintf(ip_str, sizeof(ip_str), NIPQUAD_FMT, > + NIPQUAD(res->ip.addr.ipv4)); > + else > + cmdline_printf(cl, "Wrong IP format. Only IPv4 is > supported\n"); > + > + bond_ip =3D BOND_IP_1 | (BOND_IP_2 << 8) | > + (BOND_IP_3 << 16) | (BOND_IP_4 << 24); > + > + created_pkt =3D rte_pktmbuf_alloc(mbuf_pool); > + while (created_pkt =3D=3D NULL); > + > + pkt_size =3D sizeof(struct ether_hdr) + sizeof(struct arp_hdr); > + created_pkt->data_len =3D pkt_size; > + created_pkt->pkt_len =3D pkt_size; > + > + eth_hdr =3D rte_pktmbuf_mtod(created_pkt, struct ether_hdr *); > + rte_eth_macaddr_get(BOND_PORT, ð_hdr->s_addr); > + memset(ð_hdr->d_addr, 0xFF, ETHER_ADDR_LEN); > + eth_hdr->ether_type =3D rte_cpu_to_be_16(ETHER_TYPE_ARP); > + > + arp_hdr =3D (struct arp_hdr *)((char *)eth_hdr + sizeof(struct > ether_hdr)); > + arp_hdr->arp_hrd =3D rte_cpu_to_be_16(ARP_HRD_ETHER); > + arp_hdr->arp_pro =3D rte_cpu_to_be_16(ETHER_TYPE_IPv4); > + arp_hdr->arp_hln =3D ETHER_ADDR_LEN; > + arp_hdr->arp_pln =3D sizeof(uint32_t); > + arp_hdr->arp_op =3D rte_cpu_to_be_16(ARP_OP_REQUEST); > + > + rte_eth_macaddr_get(BOND_PORT, &arp_hdr->arp_data.arp_sha); > + arp_hdr->arp_data.arp_sip =3D bond_ip; > + memset(&arp_hdr->arp_data.arp_tha, 0, ETHER_ADDR_LEN); > + arp_hdr->arp_data.arp_tip =3D > + ((unsigned char *)&res->ip.addr.ipv4)[0] | > + (((unsigned char *)&res->ip.addr.ipv4)[1] << 8) | > + (((unsigned char *)&res->ip.addr.ipv4)[2] << 16) | > + (((unsigned char *)&res->ip.addr.ipv4)[3] << 24); > + rte_eth_tx_burst(BOND_PORT, 0, &created_pkt, 1); > + > + rte_delay_ms(500); > + cmdline_printf(cl, "\n"); > +} > + > +cmdline_parse_token_string_t cmd_obj_action_send =3D > + TOKEN_STRING_INITIALIZER(struct cmd_obj_send_result, action, > "send"); > +cmdline_parse_token_num_t cmd_obj_count =3D > + TOKEN_NUM_INITIALIZER(struct cmd_obj_send_result, count, > UINT32); > +cmdline_parse_token_ipaddr_t cmd_obj_ip =3D > + TOKEN_IPADDR_INITIALIZER(struct cmd_obj_send_result, ip); > + > +cmdline_parse_inst_t cmd_obj_send =3D { > + .f =3D cmd_obj_send_parsed, /* function to call */ > + .data =3D NULL, /* 2nd arg of func */ > + .help_str =3D "send arp", > + .tokens =3D { /* token list, NULL terminated */ > + (void *)&cmd_obj_action_send, > + (void *)&cmd_obj_count, > + (void *)&cmd_obj_ip, > + NULL, > + }, > +}; > + > +/**********************************************************/ > + > + > +/**********************************************************/ > +struct cmd_start_result { > + cmdline_fixed_string_t start; > +}; > + > +static void cmd_start_parsed(__attribute__((unused)) void *parsed_result= , > + struct cmdline *cl, > + __attribute__((unused)) void *data) > +{ > + int slave_core_id =3D rte_lcore_id(); > + > + rte_spinlock_trylock(&global_flag_stru_p->lock); > + if (global_flag_stru_p->LcoreMainIsRunning =3D=3D 0) { > + if (lcore_config[global_flag_stru_p->LcoreMainCore].state !=3D > WAIT) { > + rte_spinlock_unlock(&global_flag_stru_p->lock); > + return; > + } > + rte_spinlock_unlock(&global_flag_stru_p->lock); > + } else { > + cmdline_printf(cl, "lcore_main already running on > core:%d\n", > + global_flag_stru_p->LcoreMainCore); > + rte_spinlock_unlock(&global_flag_stru_p->lock); > + return; > + } > + > + /* start lcore main on core !=3D master_core - ARP response thread */ > + slave_core_id =3D rte_get_next_lcore(rte_lcore_id(), 1, 0); > + if ((slave_core_id >=3D RTE_MAX_LCORE) || (slave_core_id =3D=3D 0)) > + return; > + > + rte_spinlock_trylock(&global_flag_stru_p->lock); > + global_flag_stru_p->LcoreMainIsRunning =3D 1; > + rte_spinlock_unlock(&global_flag_stru_p->lock); > + cmdline_printf(cl, "Starting lcore_main on core %d:%d " > + "Our IP:%d.%d.%d.%d\n", > + slave_core_id, > + rte_eal_remote_launch(lcore_main, NULL, > slave_core_id), > + BOND_IP_1, > + BOND_IP_2, > + BOND_IP_3, > + BOND_IP_4 > + ); > +} > + > +cmdline_parse_token_string_t cmd_start_start =3D > + TOKEN_STRING_INITIALIZER(struct cmd_start_result, start, "start"); > + > +cmdline_parse_inst_t cmd_start =3D { > + .f =3D cmd_start_parsed, /* function to call */ > + .data =3D NULL, /* 2nd arg of func */ > + .help_str =3D "starts listening if not started at startup", > + .tokens =3D { /* token list, NULL terminated */ > + (void *)&cmd_start_start, > + NULL, > + }, > +}; > + > +/**********************************************************/ > + > +struct cmd_help_result { > + cmdline_fixed_string_t help; > +}; > + > +static void cmd_help_parsed(__attribute__((unused)) void *parsed_result, > + struct cmdline *cl, > + __attribute__((unused)) void *data) > +{ > + cmdline_printf(cl, > + "ALB - link bonding mode 6 example\n" > + "send COUNT IP - sends COUNT ARPrequests thru > bonding for IP.\n" > + "start - starts listening ARPs.\n" > + "stop - stops lcore_main.\n" > + "show - shows some bond info: ex. active > slaves etc.\n" > + "help - prints help.\n" > + "quit - terminate all threads and quit.\n" > + ); > +} > + > +cmdline_parse_token_string_t cmd_help_help =3D > + TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, "help"); > + > +cmdline_parse_inst_t cmd_help =3D { > + .f =3D cmd_help_parsed, /* function to call */ > + .data =3D NULL, /* 2nd arg of func */ > + .help_str =3D "show help", > + .tokens =3D { /* token list, NULL terminated */ > + (void *)&cmd_help_help, > + NULL, > + }, > +}; > + > +/**********************************************************/ > +struct cmd_stop_result { > + cmdline_fixed_string_t stop; > +}; > + > +static void cmd_stop_parsed(__attribute__((unused)) void *parsed_result, > + struct cmdline *cl, > + __attribute__((unused)) void *data) > +{ > + rte_spinlock_trylock(&global_flag_stru_p->lock); > + if (global_flag_stru_p->LcoreMainIsRunning =3D=3D 0) { > + cmdline_printf(cl, > + "lcore_main not running on > core:%d\n", > + global_flag_stru_p->LcoreMainCore); > + rte_spinlock_unlock(&global_flag_stru_p->lock); > + return; > + } > + global_flag_stru_p->LcoreMainIsRunning =3D 0; > + rte_eal_wait_lcore(global_flag_stru_p->LcoreMainCore); > + cmdline_printf(cl, > + "lcore_main stopped on core:%d\n", > + global_flag_stru_p->LcoreMainCore); > + rte_spinlock_unlock(&global_flag_stru_p->lock); > +} > + > +cmdline_parse_token_string_t cmd_stop_stop =3D > + TOKEN_STRING_INITIALIZER(struct cmd_stop_result, stop, "stop"); > + > +cmdline_parse_inst_t cmd_stop =3D { > + .f =3D cmd_stop_parsed, /* function to call */ > + .data =3D NULL, /* 2nd arg of func */ > + .help_str =3D "this command do not handle any arguments", > + .tokens =3D { /* token list, NULL terminated */ > + (void *)&cmd_stop_stop, > + NULL, > + }, > +}; > +/**********************************************************/ > + > +/**********************************************************/ > +struct cmd_quit_result { > + cmdline_fixed_string_t quit; > +}; > + > +static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result, > + struct cmdline *cl, > + __attribute__((unused)) void *data) > +{ > + cmdline_printf(cl, > + "quit - for quit just do ctrl+d\n" > + ); > + exit(EXIT_SUCCESS); > +} > + > +cmdline_parse_token_string_t cmd_quit_quit =3D > + TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit"); > + > +cmdline_parse_inst_t cmd_quit =3D { > + .f =3D cmd_quit_parsed, /* function to call */ > + .data =3D NULL, /* 2nd arg of func */ > + .help_str =3D "this command do not handle any arguments", > + .tokens =3D { /* token list, NULL terminated */ > + (void *)&cmd_quit_quit, > + NULL, > + }, > +}; > +/**********************************************************/ > + > +/**********************************************************/ > +struct cmd_show_result { > + cmdline_fixed_string_t show; > +}; > + > +static void cmd_show_parsed(__attribute__((unused)) void *parsed_result, > + struct cmdline *cl, > + __attribute__((unused)) void *data) > +{ > + uint8_t slaves[16] =3D {0}; > + uint8_t len =3D 16; > + struct ether_addr addr; > + uint8_t i =3D 0; > + > + while (i < slaves_count) { > + rte_eth_macaddr_get(i, &addr); > + PRINT_MAC(addr); > + if (i =3D=3D BOND_PORT) > + printf(" - current primary slave"); > + printf("\n"); > + i++; > + } > + rte_eth_macaddr_get(i, &addr); > + PRINT_MAC(addr); > + if (i =3D=3D BOND_PORT) > + printf(" - current primary slave"); > + printf("\n"); > + rte_spinlock_trylock(&global_flag_stru_p->lock); > + cmdline_printf(cl, > + "Active_slaves:%d " > + "packets received:Tot:%d Arp:%d\n", > + rte_eth_bond_active_slaves_get(BOND_PORT, slaves, > len), > + global_flag_stru_p->port_packets[0], > + global_flag_stru_p->port_packets[1]); > + rte_spinlock_unlock(&global_flag_stru_p->lock); > +} > + > +cmdline_parse_token_string_t cmd_show_show =3D > + TOKEN_STRING_INITIALIZER(struct cmd_show_result, show, "show"); > + > +cmdline_parse_inst_t cmd_show =3D { > + .f =3D cmd_show_parsed, /* function to call */ > + .data =3D NULL, /* 2nd arg of func */ > + .help_str =3D "this command do not handle any arguments", > + .tokens =3D { /* token list, NULL terminated */ > + (void *)&cmd_show_show, > + NULL, > + }, > +}; > +/**********************************************************/ > + > +/**********************************************************/ > +/****** CONTEXT (list of instruction) */ > + > +cmdline_parse_ctx_t main_ctx[] =3D { > + (cmdline_parse_inst_t *)&cmd_start, > + (cmdline_parse_inst_t *)&cmd_obj_send, > + (cmdline_parse_inst_t *)&cmd_stop, > + (cmdline_parse_inst_t *)&cmd_show, > + (cmdline_parse_inst_t *)&cmd_quit, > + (cmdline_parse_inst_t *)&cmd_help, > + NULL, > +}; > + > +/* prompt function, called from main on MASTER lcore */ > +static void *prompt(__attribute__((unused)) void *arg1) > +{ > + struct cmdline *cl; > + > + cl =3D cmdline_stdin_new(main_ctx, "bond6>"); > + if (cl !=3D NULL) { > + cmdline_interact(cl); > + cmdline_stdin_exit(cl); > + } > +} > + > +/* Main function, does initialisation and calls the per-lcore functions = */ > +int > +MAIN(int argc, char *argv[]) > +{ > + int ret; > + uint8_t nb_ports, i; > + > + /* init EAL */ > + ret =3D rte_eal_init(argc, argv); > + rte_eal_devargs_dump(stdout); > + if (ret < 0) > + rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); > + argc -=3D ret; > + argv +=3D ret; > + > + nb_ports =3D rte_eth_dev_count(); > + if (nb_ports =3D=3D 0) > + rte_exit(EXIT_FAILURE, "Give at least one port\n"); > + else if (nb_ports > MAX_PORTS) > + rte_exit(EXIT_FAILURE, "You can have max 4 ports\n"); > + > + mbuf_pool =3D rte_mempool_create("MBUF_POOL", NB_MBUF, > + MBUF_SIZE, 32, > + sizeof(struct rte_pktmbuf_pool_private), > + rte_pktmbuf_pool_init, NULL, > + rte_pktmbuf_init, NULL, > + rte_socket_id(), 0); > + if (mbuf_pool =3D=3D NULL) > + rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); > + > + /* initialize all ports */ > + slaves_count =3D nb_ports; > + for (i =3D 0; i < nb_ports; i++) { > + slave_port_init(i, mbuf_pool); > + slaves[i] =3D i; > + } > + > + bond_port_init(mbuf_pool); > + > + rte_spinlock_init(&global_flag_stru_p->lock); > + int slave_core_id =3D rte_lcore_id(); > + > + /* check state of lcores */ > + RTE_LCORE_FOREACH_SLAVE(slave_core_id) { > + if (lcore_config[slave_core_id].state !=3D WAIT) > + return -EBUSY; > + } > + /* start lcore main on core !=3D master_core - ARP response thread */ > + slave_core_id =3D rte_get_next_lcore(rte_lcore_id(), 1, 0); > + if ((slave_core_id >=3D RTE_MAX_LCORE) || (slave_core_id =3D=3D 0)) > + return -EPERM; > + > + global_flag_stru_p->LcoreMainIsRunning =3D 1; > + global_flag_stru_p->LcoreMainCore =3D slave_core_id; > + printf("Starting lcore_main on core %d:%d Our IP:%d.%d.%d.%d\n", > + slave_core_id, > + rte_eal_remote_launch((lcore_function_t > *)lcore_main, > + NULL, > + slave_core_id), > + BOND_IP_1, > + BOND_IP_2, > + BOND_IP_3, > + BOND_IP_4 > + ); > + > + /* Start prompt for user interact */ > + prompt(NULL); > + > + > + return 0; > +} > diff --git a/examples/bond/main.h b/examples/bond/main.h > new file mode 100644 > index 0000000..2682d15 > --- /dev/null > +++ b/examples/bond/main.h > @@ -0,0 +1,46 @@ > +/*- > + * BSD LICENSE > + * > + * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * > + * * Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * * Redistributions in binary form must reproduce the above copyrig= ht > + * notice, this list of conditions and the following disclaimer in > + * the documentation and/or other materials provided with the > + * distribution. > + * * Neither the name of Intel Corporation nor the names of its > + * contributors may be used to endorse or promote products derived > + * from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > CONTRIBUTORS > + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT > NOT > + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND > FITNESS FOR > + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE > COPYRIGHT > + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, > INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > NOT > + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS > OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED > AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR > TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF > THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH > DAMAGE. > + */ > + > +#ifndef _MAIN_H_ > +#define _MAIN_H_ > + > + > +#ifdef RTE_EXEC_ENV_BAREMETAL > +#define MAIN _main > +#else > +#define MAIN main > +#endif > + > +int MAIN(int argc, char *argv[]); > + > +#endif /* ifndef _MAIN_H_ */ > -- > 1.7.9.5 This patch contains an example for link bonding mode 6. It interact with user by a command prompt. Available commands are: Start - starts ARP_thread which respond to ARP_requests and sends ARP_updat= es (this Is enabled by default after startup), Stop -stops ARP_thread, Send count ip - send count ARP requests for IP, Show - prints basic bond information, Help, Quit. The best way to test mode 6 is to use this example together with previous p= atch: [PATCH 3/4] bond: add debug info for mode 6 link bonding. Connect clients thru switch to bonding machine and send: arping -c 1 bond_ip or telnet bond_ip (IPv4 traffic from different clients should be then balanced= on slaves in round robin manner). Best regards Michal