get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/419/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 419,
    "url": "http://patches.dpdk.org/api/patches/419/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1410963713-13837-3-git-send-email-pawelx.wodkowski@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1410963713-13837-3-git-send-email-pawelx.wodkowski@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1410963713-13837-3-git-send-email-pawelx.wodkowski@intel.com",
    "date": "2014-09-17T14:21:53",
    "name": "[dpdk-dev,2/2] bond: add mode 4 support",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "5216c89709457b55640a8a37f988f1536fdbbc29",
    "submitter": {
        "id": 58,
        "url": "http://patches.dpdk.org/api/people/58/?format=api",
        "name": "Wodkowski, PawelX",
        "email": "pawelx.wodkowski@intel.com"
    },
    "delegate": null,
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1410963713-13837-3-git-send-email-pawelx.wodkowski@intel.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/419/comments/",
    "check": "pending",
    "checks": "http://patches.dpdk.org/api/patches/419/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 3E5DDB3C2;\n\tWed, 17 Sep 2014 16:17:01 +0200 (CEST)",
            "from mga01.intel.com (mga01.intel.com [192.55.52.88])\n\tby dpdk.org (Postfix) with ESMTP id 2EBC7B3C2\n\tfor <dev@dpdk.org>; Wed, 17 Sep 2014 16:16:58 +0200 (CEST)",
            "from azsmga001.ch.intel.com ([10.2.17.19])\n\tby fmsmga101.fm.intel.com with ESMTP; 17 Sep 2014 07:22:36 -0700",
            "from irvmail001.ir.intel.com ([163.33.26.43])\n\tby azsmga001.ch.intel.com with ESMTP; 17 Sep 2014 07:22:32 -0700",
            "from sivswdev01.ir.intel.com (sivswdev01.ir.intel.com\n\t[10.237.217.45])\n\tby irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id\n\ts8HEMVFx028222; Wed, 17 Sep 2014 15:22:31 +0100",
            "from sivswdev01.ir.intel.com (localhost [127.0.0.1])\n\tby sivswdev01.ir.intel.com with ESMTP id s8HEMVns013989;\n\tWed, 17 Sep 2014 15:22:31 +0100",
            "(from pwodkowx@localhost)\n\tby sivswdev01.ir.intel.com with  id s8HEMVxQ013984;\n\tWed, 17 Sep 2014 15:22:31 +0100"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.04,540,1406617200\"; d=\"scan'208\";a=\"478138364\"",
        "From": "Pawel Wodkowski <pawelx.wodkowski@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Wed, 17 Sep 2014 15:21:53 +0100",
        "Message-Id": "<1410963713-13837-3-git-send-email-pawelx.wodkowski@intel.com>",
        "X-Mailer": "git-send-email 1.7.4.1",
        "In-Reply-To": "<1410963713-13837-1-git-send-email-pawelx.wodkowski@intel.com>",
        "References": "<1410963713-13837-1-git-send-email-pawelx.wodkowski@intel.com>",
        "Subject": "[dpdk-dev] [PATCH 2/2] bond: add mode 4 support",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Signed-off-by: Pawel Wodkowski <pawelx.wodkowski@intel.com>\nSigned-off-by: Maciej T Gajdzica <maciejx.t.gajdzica@intel.com>\nReviewed-by: Declan Doherty <declan.doherty@intel.com>\n---\n lib/librte_ether/rte_ether.h               |    1 +\n lib/librte_pmd_bond/Makefile               |    1 +\n lib/librte_pmd_bond/rte_eth_bond.h         |    4 +\n lib/librte_pmd_bond/rte_eth_bond_8023ad.c  | 1064 ++++++++++++++++++++++++++++\n lib/librte_pmd_bond/rte_eth_bond_8023ad.h  |  411 +++++++++++\n lib/librte_pmd_bond/rte_eth_bond_api.c     |   28 +-\n lib/librte_pmd_bond/rte_eth_bond_args.c    |    1 +\n lib/librte_pmd_bond/rte_eth_bond_pmd.c     |  179 ++++-\n lib/librte_pmd_bond/rte_eth_bond_private.h |    9 +-\n 9 files changed, 1685 insertions(+), 13 deletions(-)\n create mode 100644 lib/librte_pmd_bond/rte_eth_bond_8023ad.c\n create mode 100644 lib/librte_pmd_bond/rte_eth_bond_8023ad.h",
    "diff": "diff --git a/lib/librte_ether/rte_ether.h b/lib/librte_ether/rte_ether.h\nindex 2e08f23..1a3711b 100644\n--- a/lib/librte_ether/rte_ether.h\n+++ b/lib/librte_ether/rte_ether.h\n@@ -293,6 +293,7 @@ struct vlan_hdr {\n #define ETHER_TYPE_RARP 0x8035 /**< Reverse Arp Protocol. */\n #define ETHER_TYPE_VLAN 0x8100 /**< IEEE 802.1Q VLAN tagging. */\n #define ETHER_TYPE_1588 0x88F7 /**< IEEE 802.1AS 1588 Precise Time Protocol. */\n+#define ETHER_TYPE_SLOW 0x8809 /**< Slow protocols (LACP and Marker). */\n \n #ifdef __cplusplus\n }\ndiff --git a/lib/librte_pmd_bond/Makefile b/lib/librte_pmd_bond/Makefile\nindex 953d75e..c2312c2 100644\n--- a/lib/librte_pmd_bond/Makefile\n+++ b/lib/librte_pmd_bond/Makefile\n@@ -44,6 +44,7 @@ CFLAGS += $(WERROR_FLAGS)\n #\n SRCS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += rte_eth_bond_api.c\n SRCS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += rte_eth_bond_pmd.c\n+SRCS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += rte_eth_bond_8023ad.c\n SRCS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += rte_eth_bond_args.c\n \n #\ndiff --git a/lib/librte_pmd_bond/rte_eth_bond.h b/lib/librte_pmd_bond/rte_eth_bond.h\nindex bd59780..6aac4ec 100644\n--- a/lib/librte_pmd_bond/rte_eth_bond.h\n+++ b/lib/librte_pmd_bond/rte_eth_bond.h\n@@ -75,6 +75,10 @@ extern \"C\" {\n /**< Broadcast (Mode 3).\n  * In this mode all transmitted packets will be transmitted on all available\n  * active slaves of the bonded. */\n+#define BONDING_MODE_8023AD\t\t\t\t(4)\n+/**< 802.3AD (Mode 4).\n+ * In this mode transmission and reception of packets is managed by LACP\n+ * protocol specified in 802.3AD documentation. */\n \n /* Balance Mode Transmit Policies */\n #define BALANCE_XMIT_POLICY_LAYER2\t\t(0)\ndiff --git a/lib/librte_pmd_bond/rte_eth_bond_8023ad.c b/lib/librte_pmd_bond/rte_eth_bond_8023ad.c\nnew file mode 100644\nindex 0000000..6ce6efb\n--- /dev/null\n+++ b/lib/librte_pmd_bond/rte_eth_bond_8023ad.c\n@@ -0,0 +1,1064 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#include <stddef.h>\n+#include <string.h>\n+\n+#include <rte_alarm.h>\n+#include <rte_malloc.h>\n+#include <rte_errno.h>\n+\n+#include \"rte_eth_bond_private.h\"\n+#include \"rte_eth_bond_8023ad.h\"\n+\n+#include <rte_cycles.h>\n+\n+#define RTE_LIBRTE_BOND_DEBUG_8023AX\n+\n+#ifdef RTE_LIBRTE_BOND_DEBUG_8023AX\n+#define BOND_ASSERT(expr) \\\n+\t((expr) ? (void) (0) \\\n+\t: rte_panic(\"%s(%d): assertion failed\" __STRING(expr), __FILE__, __LINE__))\n+#else\n+#define BOND_ASSERT(expr) do { } while (0)\n+#endif\n+\n+#ifdef RTE_LIBRTE_BOND_DEBUG_8023AX\n+#define _PORT_ID internals->active_slaves[port_num]\n+#define BOND_DEBUG(fmt, ...) RTE_LOG(DEBUG, PMD, \"%6u [Port %u: %s] \" fmt, \\\n+\t\t\tbond_dbg_get_time_diff(), _PORT_ID, __FUNCTION__, ##__VA_ARGS__)\n+\n+static unsigned\n+bond_dbg_get_time_diff(void)\n+{\n+\tstatic unsigned ms_start = 0;\n+\tstruct timespec t;\n+\tuint64_t ms;\n+\n+\tclock_gettime(CLOCK_MONOTONIC, &t);\n+\tms = (((long)t.tv_sec * 1000000000L) + t.tv_nsec) / 1000000L;\n+\n+\tif (ms_start == 0)\n+\t\tms_start = ms;\n+\n+\treturn ms - ms_start;\n+}\n+\n+static void\n+bond_print_lacp(struct lacpdu *l)\n+{\n+\tchar a_state[256] = { 0 };\n+\tchar p_state[256] = { 0 };\n+\tstatic const char *state_labels[] = {\n+\t\t\"ACT\", \"TIMEOUT\", \"AGG\", \"SYNC\", \"COL\", \"DIST\", \"DEF\", \"EXP\"\n+\t};\n+\n+\tint a_len = 0;\n+\tint p_len = 0;\n+\tuint8_t i;\n+\n+\tfor (i = 0; i < 8; i++) {\n+\t\tif ((l->actor.state >> i) & 1) {\n+\t\t\ta_len += snprintf(a_state + a_len, sizeof(a_state) - a_len, \"%s \",\n+\t\t\t\tstate_labels[i]);\n+\t\t}\n+\n+\t\tif ((l->partner.state >> i) & 1) {\n+\t\t\tp_len += snprintf(p_state + p_len, sizeof(p_state) - p_len, \"%s \",\n+\t\t\t\tstate_labels[i]);\n+\t\t}\n+\t}\n+\n+\tif (a_len && a_state[a_len-1] == ' ')\n+\t\ta_state[a_len-1] = '\\0';\n+\n+\tif (p_len && p_state[p_len-1] == ' ')\n+\t\t\tp_state[p_len-1] = '\\0';\n+\n+\tRTE_LOG(DEBUG, PMD, \"LACP: {\\n\"\\\n+\t\t\t\"  subtype= %02X\\n\"\\\n+\t\t\t\"  ver_num=%02X\\n\"\\\n+\t\t\t\"  actor={ tlv=%02X, len=%02X\\n\"\\\n+\t\t\t\"    pri=%04X, system=(ADDRESS), key=%04X, p_pri=%04X p_num=%04X\\n\"\\\n+\t\t\t\"       state={ %s }\\n\"\\\n+\t\t\t\"  }\\n\"\\\n+\t\t\t\"  partner={ tlv=%02X, len=%02X\\n\"\\\n+\t\t\t\"    pri=%04X, system=(ADDRESS), key=%04X, p_pri=%04X p_num=%04X\\n\"\\\n+\t\t\t\"       state={ %s }\\n\"\\\n+\t\t\t\"  }\\n\"\\\n+\t\t\t\"  collector={info=%02X, length=%02X, max_delay=%04X\\n, \" \\\n+\t\t\t\t\t\t\t\"type_term=%02X, terminator_length = %02X}\\n\",\\\n+\t\t\tl->subtype,\\\n+\t\t\tl->version_number,\\\n+\t\t\tl->actor.tlv_type_info,\\\n+\t\t\tl->actor.info_length,\\\n+\t\t\tl->actor.port_params.system_priority,\\\n+\t\t\tl->actor.port_params.key,\\\n+\t\t\tl->actor.port_params.port_priority,\\\n+\t\t\tl->actor.port_params.port_number,\\\n+\t\t\ta_state,\\\n+\t\t\tl->partner.tlv_type_info,\\\n+\t\t\tl->partner.info_length,\\\n+\t\t\tl->partner.port_params.system_priority,\\\n+\t\t\tl->partner.port_params.key,\\\n+\t\t\tl->partner.port_params.port_priority,\\\n+\t\t\tl->partner.port_params.port_number,\\\n+\t\t\tp_state,\\\n+\t\t\tl->tlv_type_collector_info,\\\n+\t\t\tl->collector_info_length,\\\n+\t\t\tl->collector_max_delay,\\\n+\t\t\tl->tlv_type_terminator,\\\n+\t\t\tl->terminator_length);\n+\n+}\n+#define BOND_PRINT_LACP(lacpdu) bond_print_lacp(lacpdu)\n+\n+#else\n+#define BOND_PRINT_LACP(lacpdu) do { } while (0)\n+#define BOND_DEBUG(fmt, ...) do { } while (0)\n+#endif\n+\n+static const struct ether_addr lacp_mac_addr = {\n+\t.addr_bytes = {0x01, 0x80, 0xC2, 0x00, 0x00, 0x02}\n+};\n+\n+static void\n+timer_expired_cb(void *arg)\n+{\n+\tenum timer_state *timer = arg;\n+\n+\tBOND_ASSERT(*timer == TIMER_RUNNING);\n+\t*timer = TIMER_EXPIRED;\n+}\n+\n+static void\n+timer_cancel(enum timer_state *timer)\n+{\n+\trte_eal_alarm_cancel(&timer_expired_cb, timer);\n+\t*timer = TIMER_NOT_STARTED;\n+}\n+\n+static void\n+timer_set(enum timer_state *timer, uint64_t timeout)\n+{\n+\trte_eal_alarm_cancel(&timer_expired_cb, timer);\n+\trte_eal_alarm_set(timeout * 1000, &timer_expired_cb, timer);\n+\t*timer = TIMER_RUNNING;\n+}\n+\n+static bool\n+timer_is_expired(enum timer_state *timer)\n+{\n+\treturn *timer == TIMER_EXPIRED;\n+}\n+\n+static void\n+record_default(struct port *port)\n+{\n+\t/* Record default parametes for partner. Partner admin parameters\n+\t * are not implemented so nothing to copy. Only mark actor that parner is\n+\t * in defaulted state. */\n+\tport->partner_state = STATE_LACP_ACTIVE;\n+\tACTOR_STATE_SET(port, DEFAULTED);\n+}\n+\n+/** Function handles rx state machine.\n+ *\n+ * This function implements Receive State Machine from point 5.4.12 in\n+ * 802.1AX documentation. It should be called periodically.\n+ *\n+ * @param lacpdu\t\tLACPDU received.\n+ * @param port\t\t\tPort on which LACPDU was received.\n+ */\n+static void\n+rx_machine(struct bond_dev_private *internals, uint8_t port_num,\n+\tstruct lacpdu *lacp)\n+{\n+\tstruct port *port = &internals->mode4.port_list[port_num];\n+\n+\tif (SM_FLAG(port, BEGIN)) {\n+\t\t/* Initialize stuff */\n+\t\tBOND_DEBUG(\"-> INITIALIZE\\n\");\n+\t\tSM_FLAG_CLR(port, MOVED);\n+\t\tport->selected = UNSELECTED;\n+\n+\t\trecord_default(port);\n+\n+\t\tACTOR_STATE_CLR(port, EXPIRED);\n+\t\ttimer_cancel(&port->current_while_timer);\n+\n+\t\t/* DISABLED: On initialization partner is out of sync */\n+\t\tPARTNER_STATE_CLR(port, SYNCHRONIZATION);\n+\n+\t\t/* LACP DISABLED stuff if LACP not enabled on this port */\n+\t\tif (!SM_FLAG(port, LACP_ENABLED))\n+\t\t\tPARTNER_STATE_CLR(port, AGGREGATION);\n+\t}\n+\n+\tif (!SM_FLAG(port, LACP_ENABLED)) {\n+\t\t/* Update parameters only if state changed */\n+\t\tif (port->current_while_timer) {\n+\t\t\tport->selected = UNSELECTED;\n+\t\t\trecord_default(port);\n+\t\t\tPARTNER_STATE_CLR(port, AGGREGATION);\n+\t\t\tACTOR_STATE_CLR(port, EXPIRED);\n+\t\t\ttimer_cancel(&port->current_while_timer);\n+\t\t}\n+\t\treturn;\n+\t}\n+\n+\tif (lacp) {\n+\t\tBOND_DEBUG(\"LACP -> CURRENT\\n\");\n+\t\tBOND_PRINT_LACP(lacp);\n+\t\t/* Update selected flag. If partner parameters are defaulted assume they\n+\t\t * are match. If not defaulted  compare LACP actor with ports parner\n+\t\t * params. */\n+\t\tif (!(port->actor_state & STATE_DEFAULTED) &&\n+\t\t\t(((port->partner_state ^ lacp->actor.state) & STATE_AGGREGATION) ||\n+\t\t\t\tmemcmp(&port->partner, &lacp->actor.port_params,\n+\t\t\t\t\tsizeof(port->partner)) != 0)) {\n+\t\t\tBOND_DEBUG(\"selected <- UNSELECTED\\n\");\n+\t\t\tport->selected = UNSELECTED;\n+\t\t}\n+\n+\t\t/* Record this PDU actor params as partner params */\n+\t\tmemcpy(&port->partner, &lacp->actor.port_params,\n+\t\t\tsizeof(struct port_params));\n+\t\tport->partner_state = lacp->actor.state;\n+\t\tACTOR_STATE_CLR(port, DEFAULTED);\n+\n+\t\t/* Update NTT if partners information are outdated */\n+\t\tuint8_t state_mask = STATE_LACP_ACTIVE | STATE_LACP_SHORT_TIMEOUT |\n+\t\t\tSTATE_SYNCHRONIZATION | STATE_AGGREGATION;\n+\n+\t\tif (((port->actor_state ^ lacp->partner.state) & state_mask) ||\n+\t\t\t\tmemcmp(&port->actor, &lacp->partner.port_params,\n+\t\t\t\t\tsizeof(struct port_params)) != 0) {\n+\t\t\tport->sm_flags |= SM_FLAGS_NTT;\n+\t\t}\n+\n+\t\t/* If LACP partner params match this port actor params */\n+\t\tif (memcmp(&port->actor, &lacp->partner.port_params,\n+\t\t\t    sizeof(port->actor)) == 0 &&\n+\t\t\t(port->partner_state & STATE_AGGREGATION) == (port->actor_state\n+\t\t\t    & STATE_AGGREGATION))\n+\t\t\tPARTNER_STATE_SET(port, SYNCHRONIZATION);\n+\t\telse if (!(port->partner_state & STATE_AGGREGATION) &&\n+\t\t\t    (port->actor_state & STATE_AGGREGATION))\n+\t\t\tPARTNER_STATE_SET(port, SYNCHRONIZATION);\n+\t\telse\n+\t\t\tPARTNER_STATE_CLR(port, SYNCHRONIZATION);\n+\n+\t\tif (port->actor_state & STATE_LACP_SHORT_TIMEOUT)\n+\t\t\ttimer_set(&port->current_while_timer, BOND_8023AD_SHORT_TIMEOUT_MS);\n+\t\telse\n+\t\t\ttimer_set(&port->current_while_timer, BOND_8023AD_LONG_TIMEOUT_MS);\n+\n+\t\tACTOR_STATE_CLR(port, EXPIRED);\n+\t\treturn; /* No state change */\n+\t}\n+\n+\tif (port->current_while_timer != TIMER_RUNNING) {\n+\t\tACTOR_STATE_SET(port, EXPIRED);\n+\t\tPARTNER_STATE_CLR(port, SYNCHRONIZATION);\n+\t\tPARTNER_STATE_SET(port, LACP_SHORT_TIMEOUT);\n+\t\ttimer_set(&port->current_while_timer, BOND_8023AD_SHORT_TIMEOUT_MS);\n+\t}\n+}\n+\n+/**\n+ * Function handles periodic tx state machine.\n+ *\n+ * Function implements Periodic Transmission state machine from point 5.4.13\n+ * in 802.1AX documentation. It should be called periodically.\n+ *\n+ * @param port\t\t\tPort to handle state machine.\n+ */\n+static void\n+periodic_machine(struct bond_dev_private *internals, uint8_t port_num)\n+{\n+\tstruct port *port = &internals->mode4.port_list[port_num];\n+\t/* Calculate if either site is LACP enabled */\n+\tuint32_t timeout;\n+\tuint16_t sm_flags = port->sm_flags;\n+\tuint8_t active = ACTOR_STATE(port, LACP_ACTIVE) ||\n+\t\tPARTNER_STATE(port, LACP_ACTIVE);\n+\n+\tuint8_t is_partner_fast, was_partner_fast;\n+\t/* No periodic is on BEGIN, LACP DISABLE or when both sides are pasive */\n+\tif ((sm_flags & SM_FLAGS_BEGIN) || !(sm_flags & SM_FLAGS_LACP_ENABLED) ||\n+\t\t    active == 0) {\n+\t\ttimer_cancel(&port->periodic_timer);\n+\t\tport->tx_machine_timer = TIMER_EXPIRED;\n+\t\tsm_flags &= ~SM_FLAGS_PARTNER_SHORT_TIMEOUT;\n+\t\tport->sm_flags = sm_flags;\n+\n+\t\tBOND_DEBUG(\"-> NO_PERIODIC ( %s%s%s)\\n\",\n+\t\t\tSM_FLAG(port, BEGIN) ? \"begind \" : \"\",\n+\t\t\tSM_FLAG(port, LACP_ENABLED) ? \"\" : \"LACP disabled \",\n+\t\t\tactive ? \"LACP active \" : \"LACP pasive \");\n+\t\treturn;\n+\t}\n+\n+\tis_partner_fast = !!(port->partner_state & STATE_LACP_SHORT_TIMEOUT);\n+\twas_partner_fast = !!(port->sm_flags & SM_FLAGS_PARTNER_SHORT_TIMEOUT);\n+\n+\t/* If periodic timer is not started, transit from NO PERIODIC to FAST/SLOW.\n+\t * Other case: check if timer expire or partners settings changed. */\n+\tif (port->periodic_timer != TIMER_NOT_STARTED) {\n+\t\tif (timer_is_expired(&port->periodic_timer))\n+\t\t\tsm_flags |= SM_FLAGS_NTT;\n+\t\telse if (is_partner_fast != was_partner_fast) {\n+\t\t\t/* Partners timeout  was slow and now it is fast -> send LACP.\n+\t\t\t * In other case (was fast and now it is slow) just switch\n+\t\t\t * timeout to slow without forcing send of LACP (because standard\n+\t\t\t * say so)*/\n+\t\t\tif (!is_partner_fast)\n+\t\t\t\tsm_flags |= SM_FLAGS_NTT;\n+\t\t} else\n+\t\t\treturn; /* Nothing changed */\n+\t}\n+\n+\t/* Handle state transition to FAST/SLOW LACP timeout */\n+\tif (is_partner_fast) {\n+\t\ttimeout = BOND_8023AD_FAST_PERIODIC_MS;\n+\t\tsm_flags |= SM_FLAGS_PARTNER_SHORT_TIMEOUT;\n+\t} else {\n+\t\ttimeout = BOND_8023AD_SLOW_PERIODIC_MS;\n+\t\tsm_flags &= ~SM_FLAGS_PARTNER_SHORT_TIMEOUT;\n+\t}\n+\n+\ttimer_set(&port->periodic_timer, timeout);\n+\tport->sm_flags = sm_flags;\n+}\n+\n+/**\n+ * Function handles mux state machine.\n+ *\n+ * Function implements Mux Machine from point 5.4.15 in 802.1AX documentation.\n+ * It should be called periodically.\n+ *\n+ * @param port\t\t\tPort to handle state machine.\n+ */\n+static int\n+mux_machine(struct bond_dev_private *internals, uint8_t port_num)\n+{\n+\tbool ntt = false;\n+\tstruct port *port = &internals->mode4.port_list[port_num];\n+\n+\t/* Save current state for later use */\n+\tconst uint8_t state_mask = STATE_SYNCHRONIZATION | STATE_DISTRIBUTING |\n+\t\tSTATE_COLLECTING;\n+\n+\t/* Enter DETACHED state on BEGIN condition or from any other state if\n+\t * port was unselected */\n+\tif (SM_FLAG(port, BEGIN) ||\n+\t\t\tport->selected == UNSELECTED || (port->selected == STANDBY &&\n+\t\t\t\t(port->actor_state & state_mask) != 0)) {\n+\t\t/* detach mux from aggregator not used */\n+\t\tport->actor_state &= ~state_mask;\n+\t\t/* Set ntt to true if BEGIN condition or transition from any other state\n+\t\t * which is indicated that wait_while_timer was started */\n+\t\tif (SM_FLAG(port, BEGIN) ||\n+\t\t\t\tport->wait_while_timer != TIMER_NOT_STARTED) {\n+\t\t\tSM_FLAG_SET(port, NTT);\n+\t\t\tBOND_DEBUG(\"-> DETACHED\\n\");\n+\t\t}\n+\t\ttimer_cancel(&port->wait_while_timer);\n+\t}\n+\n+\tif (port->wait_while_timer == TIMER_NOT_STARTED) {\n+\t\tif (port->selected == SELECTED || port->selected == STANDBY) {\n+\t\t\ttimer_set(&port->wait_while_timer,\n+\t\t\t\tBOND_8023AD_AGGREGATE_WAIT_TIMEOUT_MS);\n+\n+\t\t\tBOND_DEBUG(\"DETACHED -> WAITING\\n\");\n+\t\t}\n+\t\t/* Waiting state entered */\n+\t\treturn 0;\n+\t}\n+\n+\t/* Transit next state if port is ready */\n+\tif (!timer_is_expired(&port->wait_while_timer))\n+\t\treturn 0;\n+\n+\tif ((ACTOR_STATE(port, DISTRIBUTING) || ACTOR_STATE(port, COLLECTING)) &&\n+\t\t!PARTNER_STATE(port, SYNCHRONIZATION)) {\n+\t\t/* If in COLLECTING or DISTRIBUTING state and partner becomes out of\n+\t\t * sync transit to ATACHED state.  */\n+\t\tACTOR_STATE_CLR(port, DISTRIBUTING);\n+\t\tACTOR_STATE_CLR(port, COLLECTING);\n+\t\t/* Clear actor sync to activate transit ATACHED in condition bellow */\n+\t\tACTOR_STATE_CLR(port, SYNCHRONIZATION);\n+\t\tBOND_DEBUG(\"Out of sync -> ATTACHED\\n\");\n+\t} else if (!ACTOR_STATE(port, SYNCHRONIZATION)) {\n+\t\t/* attach mux to aggregator */\n+\t\tBOND_ASSERT((port->actor_state & (STATE_COLLECTING |\n+\t\t\tSTATE_DISTRIBUTING)) == 0);\n+\t\tACTOR_STATE_SET(port, SYNCHRONIZATION);\n+\t\tntt = true;\n+\t\tBOND_DEBUG(\"ATTACHED Entered\\n\");\n+\t} else if (!ACTOR_STATE(port, COLLECTING)) {\n+\t\t/* Start collecting if in sync */\n+\t\tif (PARTNER_STATE(port, SYNCHRONIZATION)) {\n+\t\t\tBOND_DEBUG(\"ATTACHED -> COLLECTING\\n\");\n+\t\t\tACTOR_STATE_SET(port, COLLECTING);\n+\t\t}\n+\t} else if (ACTOR_STATE(port, COLLECTING)) {\n+\t\t/* Check if partner is in COLLECTING state. If so this port can\n+\t\t * distribute frames to it */\n+\t\tif (!ACTOR_STATE(port, DISTRIBUTING)) {\n+\t\t\tif (PARTNER_STATE(port, COLLECTING)) {\n+\t\t\t\t/* Enable  DISTRIBUTING if partner is collecting */\n+\t\t\t\tACTOR_STATE_SET(port, DISTRIBUTING);\n+\t\t\t\tntt = true;\n+\t\t\t\tBOND_DEBUG(\"COLLECTING -> DISTRIBUTING\\n\");\n+\t\t\t}\n+\t\t} else {\n+\t\t\tif (!PARTNER_STATE(port, COLLECTING)) {\n+\t\t\t\t/* Disable DISTRIBUTING (enter COLLECTING state) if partner\n+\t\t\t\t * is not collecting */\n+\t\t\t\tACTOR_STATE_CLR(port, DISTRIBUTING);\n+\t\t\t\tntt = true;\n+\t\t\t\tBOND_DEBUG(\"DISTRIBUTING -> COLLECTING\\n\");\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tif (ntt != false)\n+\t\tSM_FLAG_SET(port, NTT);\n+\n+\treturn ntt;\n+}\n+\n+\n+/**\n+ * Function handles transmit state machine.\n+ *\n+ * Function implements Transmit Machine from point 5.4.16 in 802.1AX\n+ * documentation.\n+ *\n+ * @param port\n+ */\n+static void\n+tx_machine(struct rte_eth_dev *bond_dev, uint8_t port_num)\n+{\n+\tstruct bond_dev_private *internals = bond_dev->data->dev_private;\n+\tstruct port *port = &internals->mode4.port_list[port_num];\n+\tstruct mode8023ad_data *data = &internals->mode4;\n+\n+\tstruct slow_protocol_msg *msg;\n+\tstruct lacpdu_header *hdr;\n+\tstruct lacpdu *lacpdu;\n+\n+\t/* If periodic timer is not running periodic machine is in NO PERIODIC and\n+\t * acording to 802.3ax standard tx machine should not transmit any frames\n+\t * and set ntt to false. */\n+\tif (port->periodic_timer == TIMER_NOT_STARTED)\n+\t\tSM_FLAG_CLR(port, NTT);\n+\n+\tif (!SM_FLAG(port, NTT) || !timer_is_expired(&port->tx_machine_timer))\n+\t\treturn;\n+\n+\t/* If all conditions are met construct packet to send */\n+\tif (rte_ring_dequeue(data->free_ring, (void **)&msg) == -ENOBUFS) {\n+\t\tBOND_DEBUG(\"tx_machine: no free_lacpdu_ring\\n\");\n+\t\treturn;\n+\t}\n+\n+\tmsg->pkt = rte_pktmbuf_alloc(data->mbuf_pool);\n+\tif (msg->pkt == NULL) {\n+\t\t/* FIXME: temporal workaround, when packets are no freed by driver */\n+\t\tstruct bond_rx_queue *bd_rx_q;\n+\t\tuint8_t i;\n+\n+\t\tfor (i = 0; i < bond_dev->data->nb_rx_queues; i++) {\n+\t\t\tbd_rx_q = (struct bond_rx_queue *)bond_dev->data->rx_queues[i];\n+\t\t\tBOND_ASSERT(bd_rx_q != NULL && bd_rx_q->mb_pool != NULL);\n+\t\t\t/* Do not use SP or SC pools as this is unsafe. */\n+\t\t\tif (bd_rx_q->mb_pool->flags & (MEMPOOL_F_SC_GET | MEMPOOL_F_SP_PUT))\n+\t\t\t\tcontinue;\n+\n+\t\t\tmsg->pkt = rte_pktmbuf_alloc(bd_rx_q->mb_pool);\n+\t\t\tif (msg->pkt) {\n+\t\t\t\tRTE_LOG(WARNING, PMD, \"Failed to allocate LACP from mode4 pool.\"\n+\t\t\t\t\"Packet was allocated from pool of rx queue %u\\n\", i);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (msg->pkt == NULL) {\n+\t\t\trte_ring_enqueue(data->free_ring, msg);\n+\t\t\tRTE_LOG(ERR, PMD, \"Failed to allocate LACP packet from pool\\n\");\n+\t\t\treturn;\n+\t\t}\n+\t}\n+\tmsg->port_id = internals->active_slaves[port_num];\n+\thdr = rte_pktmbuf_mtod(msg->pkt, struct lacpdu_header *);\n+\n+\tmsg->pkt->pkt.data_len = sizeof(*hdr);\n+\tmsg->pkt->pkt.pkt_len = sizeof(*hdr);\n+\t/* Source and destination MAC */\n+\tether_addr_copy(&lacp_mac_addr, &hdr->eth_hdr.d_addr);\n+\tmac_address_get(bond_dev, &hdr->eth_hdr.s_addr);\n+\thdr->eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_SLOW);\n+\n+\tport = &data->port_list[port_num];\n+\tlacpdu = &hdr->lacpdu;\n+\tmemset(lacpdu, 0, sizeof(*lacpdu));\n+\n+\t/* Initialize LACP part */\n+\tlacpdu->subtype = SUBTYPE_LACP;\n+\tlacpdu->version_number = 1;\n+\n+\t/* ACTOR */\n+\tlacpdu->actor.tlv_type_info = TLV_TYPE_ACTOR_INFORMATION;\n+\tlacpdu->actor.info_length = sizeof(struct lacpdu_actor_partner_params);\n+\tmemcpy(&hdr->lacpdu.actor.port_params, &port->actor,\n+\t\t\tsizeof(port->actor));\n+\tlacpdu->actor.state = port->actor_state;\n+\n+\t/* PARTNER */\n+\tlacpdu->partner.tlv_type_info = TLV_TYPE_PARTNER_INFORMATION;\n+\tlacpdu->partner.info_length = sizeof(struct lacpdu_actor_partner_params);\n+\tmemcpy(&lacpdu->partner.port_params, &port->partner,\n+\t\t\tsizeof(struct port_params));\n+\tlacpdu->partner.state = port->partner_state;\n+\n+\t/* Other fields */\n+\tlacpdu->tlv_type_collector_info = TLV_TYPE_COLLECTOR_INFORMATION;\n+\tlacpdu->collector_info_length = 0x10;\n+\tlacpdu->collector_max_delay = 0;\n+\n+\tlacpdu->tlv_type_terminator = TLV_TYPE_TERMINATOR_INFORMATION;\n+\tlacpdu->terminator_length = 0;\n+\n+\tif (rte_ring_enqueue(data->tx_ring, msg) == -ENOBUFS) {\n+\t\t/* If TX ring full, drop packet and free message. Retransmission\n+\t\t * will happen in next function call. */\n+\t\trte_pktmbuf_free(msg->pkt);\n+\t\trte_ring_enqueue(data->free_ring, msg);\n+\n+\t\tRTE_LOG(ERR, PMD, \"Failed to enqueue LACP packet into tx ring\");\n+\t\treturn;\n+\t}\n+\n+\tBOND_DEBUG(\"sending LACP frame\\n\");\n+\tBOND_PRINT_LACP(lacpdu);\n+\n+\tSM_FLAG_CLR(port, NTT);\n+\t/* Add 10% random backoff time to better distrube slow packets\n+\t * between tx bursts. */\n+\ttimer_set(&port->tx_machine_timer, BOND_8023AD_TX_PERIOD_MS +\n+\t\trand() % ((BOND_8023AD_TX_PERIOD_MS * 10) / 100));\n+}\n+\n+/**\n+ * Function assigns port to aggregator.\n+ *\n+ * @param bond_dev_private\tPointer to bond_dev_private structure.\n+ * @param port_pos\t\t\tPort to assign.\n+ */\n+static void\n+selection_logic(struct bond_dev_private *internals, uint8_t port_num)\n+{\n+\tstruct mode8023ad_data *data = &internals->mode4;\n+\tstruct port *agg, *port, *port_list;\n+\tuint8_t ports_count;\n+\tuint8_t i;\n+\n+\tports_count = internals->slave_count;\n+\tport_list = data->port_list;\n+\tport = &port_list[port_num];\n+\n+\t/* Skip port if it is selected */\n+\tif (port->selected == SELECTED)\n+\t\treturn;\n+\n+\t/* Search for aggregator suitable for this port */\n+\tfor (i = 0; i < ports_count; ++i) {\n+\t\tagg = &port_list[i];\n+\t\t/* Skip ports that are not aggreagators */\n+\t\tif (agg->used_agregator_idx != i && i == port_num)\n+\t\t\tcontinue;\n+\n+\t\t/* Actors system ID is not checked since all slave device have the same\n+\t\t * ID (MAC address). */\n+\t\tif ((agg->actor.key == port->actor.key &&\n+\t\t\tagg->partner.system_priority == port->partner.system_priority &&\n+\t\t\tis_same_ether_addr(&agg->partner.system, &port->partner.system) == 1\n+\t\t\t&& (agg->partner.key == port->partner.key)) &&\n+\t\t\tis_zero_ether_addr(&port->partner.system) != 1 &&\n+\t\t\t(agg->actor.key &\n+\t\t\t\trte_cpu_to_be_16(BOND_LINK_FULL_DUPLEX_KEY)) != 0) {\n+\n+\t\t\tport->used_agregator_idx = i;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\t/* By default, port uses it self as agregator */\n+\tif (i == ports_count)\n+\t\tport->used_agregator_idx = port_num;\n+\n+\tport->selected = SELECTED;\n+\n+\tBOND_DEBUG(\"-> SELECTED: ID=%3u pos=%3u\\n\"\n+\t\t\"\\t%s ID=%3u pos=%3u\\n\",\n+\t\tinternals->active_slaves[port_num], port_num,\n+\t\tport->used_agregator_idx == port_num ?\n+\t\t\t\"agregator not found, using default\" : \"agregator found\",\n+\t\tport->used_agregator_idx,\n+\t\tinternals->active_slaves[port->used_agregator_idx]);\n+}\n+\n+/**\n+ * Helper function which updates current port\n+ */\n+static void\n+update_mux_slaves(struct bond_dev_private *internals)\n+{\n+\tstruct mode8023ad_data *data = &internals->mode4;\n+\tstruct port *port;\n+\tuint8_t current[RTE_MAX_ETHPORTS];\n+\tuint8_t count = 0;\n+\tuint8_t i;\n+\n+\tfor (i = 0; i < internals->slave_count; i++) {\n+\t\tport = &data->port_list[i];\n+\t\tif (ACTOR_STATE(port, DISTRIBUTING))\n+\t\t\tcurrent[count++] = i;\n+\t}\n+\n+\tmemcpy(data->distibuting_slaves, current, sizeof(current[0]) * count);\n+\tdata->distibuting_slaves_count = count;\n+}\n+\n+/* Function maps DPDK speed to bonding speed stored in key field */\n+static uint16_t\n+link_speed_key(uint16_t speed) {\n+\tuint16_t key_speed;\n+\n+\tswitch (speed) {\n+\tcase ETH_LINK_SPEED_AUTONEG:\n+\t\tkey_speed = 0x00;\n+\t\tbreak;\n+\tcase ETH_LINK_SPEED_10:\n+\t\tkey_speed = BOND_LINK_SPEED_KEY_10M;\n+\t\tbreak;\n+\tcase ETH_LINK_SPEED_100:\n+\t\tkey_speed = BOND_LINK_SPEED_KEY_100M;\n+\t\tbreak;\n+\tcase ETH_LINK_SPEED_1000:\n+\t\tkey_speed = BOND_LINK_SPEED_KEY_1000M;\n+\t\tbreak;\n+\tcase ETH_LINK_SPEED_10G:\n+\t\tkey_speed = BOND_LINK_SPEED_KEY_10G;\n+\t\tbreak;\n+\tcase ETH_LINK_SPEED_20G:\n+\t\tkey_speed = BOND_LINK_SPEED_KEY_20G;\n+\t\tbreak;\n+\tcase ETH_LINK_SPEED_40G:\n+\t\tkey_speed = BOND_LINK_SPEED_KEY_40G;\n+\t\tbreak;\n+\tdefault:\n+\t\t/* Unknown speed*/\n+\t\tkey_speed = 0xFFFF;\n+\t}\n+\n+\treturn key_speed;\n+}\n+\n+static void\n+bond_mode_8023ad_periodic_cb(void *arg)\n+{\n+\tstruct rte_eth_dev *bond_dev = arg;\n+\tstruct bond_dev_private *internals = bond_dev->data->dev_private;\n+\tstruct mode8023ad_data *data = &internals->mode4;\n+\n+\tstruct slow_protocol_frame *slow_hdr;\n+\tstruct rte_eth_link link_info;\n+\n+\tstruct slow_protocol_msg *msgs[BOND_MODE_8023AX_RX_RING_SIZE];\n+\tuint16_t port_num, j, nb_msgs;\n+\t/* if not 0 collecting/distibuting array need update */\n+\tuint16_t slaves_changed = 0;\n+\tbool machines_invoked;\n+\n+\t/* Update link status on each port */\n+\tfor (port_num = 0; port_num < internals->active_slave_count; port_num++) {\n+\t\tuint8_t key;\n+\n+\t\trte_eth_link_get(internals->active_slaves[port_num], &link_info);\n+\t\tif (link_info.link_status != 0) {\n+\t\t\tkey = link_speed_key(link_info.link_speed) << 1;\n+\t\t\tif (link_info.link_duplex == ETH_LINK_FULL_DUPLEX)\n+\t\t\t\tkey |= BOND_LINK_FULL_DUPLEX_KEY;\n+\t\t} else\n+\t\t\tkey = 0;\n+\n+\t\tdata->port_list[port_num].actor.key = rte_cpu_to_be_16(key);\n+\t}\n+\n+\tnb_msgs = (uint16_t)rte_ring_dequeue_burst(data->rx_ring, (void **) msgs,\n+\t\tBOND_MODE_8023AX_RX_RING_SIZE);\n+\n+\tfor (port_num = 0; port_num < internals->active_slave_count; port_num++) {\n+\t\tstruct port *port = &data->port_list[port_num];\n+\t\tif ((port->actor.key &\n+\t\t\t\trte_cpu_to_be_16(BOND_LINK_FULL_DUPLEX_KEY)) == 0) {\n+\n+\t\t\tSM_FLAG_SET(port, BEGIN);\n+\n+\t\t\t/* LACP is disabled on half duples or link is down */\n+\t\t\tif (SM_FLAG(port, LACP_ENABLED)) {\n+\t\t\t\t/* If port was enabled set it to BEGIN state */\n+\t\t\t\tSM_FLAG_CLR(port, LACP_ENABLED);\n+\t\t\t\tACTOR_STATE_CLR(port, DISTRIBUTING);\n+\t\t\t\tACTOR_STATE_CLR(port, COLLECTING);\n+\t\t\t\tslaves_changed++;\n+\t\t\t}\n+\n+\t\t\tBOND_DEBUG(\"Port %u is not LACP capable!\\n\",\n+\t\t\t\tinternals->active_slaves[port_num]);\n+\t\t\t/* Skip this port processing */\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tSM_FLAG_SET(port, LACP_ENABLED);\n+\t\tmachines_invoked = false;\n+\t\t/* Find LACP packet */\n+\t\tfor (j = 0; j < nb_msgs; j++) {\n+\t\t\tif (msgs[j] == NULL || msgs[j]->port_id !=\n+\t\t\t\t\tinternals->active_slaves[port_num])\n+\t\t\t\tcontinue;\n+\n+\t\t\tslow_hdr = rte_pktmbuf_mtod(msgs[j]->pkt,\n+\t\t\t\t\tstruct slow_protocol_frame *);\n+\n+\t\t\tif (slow_hdr->slow_protocol.subtype == SLOW_SUBTYPE_LACP) {\n+\t\t\t\t/* This is LACP frame so pass it to rx_machine */\n+\t\t\t\tstruct lacpdu *lacp = (struct lacpdu *)&slow_hdr->slow_protocol;\n+\t\t\t\t/* Invoke state machines on every active slave port */\n+\t\t\t\trx_machine(internals, port_num, lacp);\n+\t\t\t\tperiodic_machine(internals, port_num);\n+\t\t\t\tslaves_changed += mux_machine(internals, port_num);\n+\t\t\t\ttx_machine(bond_dev, port_num);\n+\t\t\t\tselection_logic(internals, port_num);\n+\n+\t\t\t\tmachines_invoked = true;\n+\t\t\t} else if (slow_hdr->slow_protocol.subtype == SLOW_SUBTYPE_MARKER) {\n+\t\t\t\tstruct marker *marker;\n+\n+\t\t\t\tmarker = (struct marker *) &slow_hdr->slow_protocol;\n+\t\t\t\tif (marker->tlv_type_marker == MARKER_TLV_TYPE_MARKER_INFO) {\n+\t\t\t\t\t/* Reuse received packet to send frame to Marker Responder\n+\t\t\t\t\t */\n+\t\t\t\t\tmarker->tlv_type_marker = MARKER_TLV_TYPE_MARKER_RESP;\n+\n+\t\t\t\t\t/* Update source MAC, destination MAC is multicast so we\n+\t\t\t\t\t * don't update it */\n+\t\t\t\t\tmac_address_get(bond_dev, &slow_hdr->eth_hdr.s_addr);\n+\n+\t\t\t\t\tif (rte_ring_enqueue(data->tx_ring, msgs[j]) == -ENOBUFS) {\n+\t\t\t\t\t\tRTE_LOG(ERR, PMD,\n+\t\t\t\t\t\t\"Failed to enqueue packet into tx ring\");\n+\t\t\t\t\t\trte_pktmbuf_free(msgs[j]->pkt);\n+\t\t\t\t\t\trte_ring_enqueue(data->free_ring, msgs[j]);\n+\t\t\t\t\t}\n+\n+\t\t\t\t\tmsgs[j] = NULL;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (machines_invoked == false) {\n+\t\t\trx_machine(internals, port_num, NULL);\n+\t\t\tperiodic_machine(internals, port_num);\n+\t\t\tslaves_changed += mux_machine(internals, port_num);\n+\t\t\ttx_machine(bond_dev, port_num);\n+\t\t\tselection_logic(internals, port_num);\n+\t\t\tmachines_invoked = true;\n+\t\t}\n+\n+\t\tSM_FLAG_CLR(port, BEGIN);\n+\t}\n+\n+\t/* Update mux if something changed */\n+\tif (slaves_changed > 0) {\n+\t\tupdate_mux_slaves(internals);\n+\t\tBOND_DEBUG(\"mux count %u [%2u%s%2u%s%2u%s%2u%s%s]\\n\",\n+\t\t\tdata->distibuting_slaves_count,\n+\t\t\tdata->distibuting_slaves[0],\n+\t\t\tdata->distibuting_slaves_count > 0 ? \" \" : \"\\b\\b\",\n+\t\t\tdata->distibuting_slaves[1],\n+\t\t\tdata->distibuting_slaves_count > 1 ? \" \" : \"\\b\\b\",\n+\t\t\tdata->distibuting_slaves[2],\n+\t\t\tdata->distibuting_slaves_count > 2 ? \" \" : \"\\b\\b\",\n+\t\t\tdata->distibuting_slaves[3],\n+\t\t\tdata->distibuting_slaves_count > 3 ? \" \" : \"\\b\\b\",\n+\t\t\tdata->distibuting_slaves_count > 4 ? \"...\" : \"\");\n+\t}\n+\n+\t/* Free packets that was not reused */\n+\tfor (port_num = 0; port_num < nb_msgs; port_num++) {\n+\t\tif (msgs[port_num] != NULL) {\n+\t\t\trte_pktmbuf_free(msgs[port_num]->pkt);\n+\t\t\trte_ring_enqueue(data->free_ring, msgs[port_num]);\n+\t\t}\n+\t}\n+\n+\trte_eal_alarm_set(BOND_MODE_8023AX_UPDATE_TIMEOUT_MS * 1000,\n+\t\t\tbond_mode_8023ad_periodic_cb, arg);\n+}\n+\n+static void\n+bond_mode_8023ad_activate_slave(struct rte_eth_dev *bond_dev, uint8_t num)\n+{\n+\tstruct bond_dev_private *internals = bond_dev->data->dev_private;\n+\tstruct mode8023ad_data *data = &internals->mode4;\n+\n+\tstruct port *port = &data->port_list[internals->active_slave_count];\n+\tstruct port_params initial = {\n+\t\t\t.system = { { 0 } },\n+\t\t\t.system_priority = rte_cpu_to_be_16(0xFFFF),\n+\t\t\t.key = rte_cpu_to_be_16(BOND_LINK_FULL_DUPLEX_KEY),\n+\t\t\t.port_priority = rte_cpu_to_be_16(0x00FF),\n+\t\t\t.port_number = 0,\n+\t};\n+\n+\tmemcpy(&port->actor, &initial, sizeof(struct port_params));\n+\tmac_address_get(bond_dev, &port->actor.system);\n+\tport->actor.port_number =\n+\t\tslave_id_to_port_number(internals->active_slaves[num]);\n+\n+\tmemcpy(&port->partner, &initial, sizeof(struct port_params));\n+\n+\t/* default states */\n+\tport->actor_state = STATE_AGGREGATION | STATE_LACP_ACTIVE | STATE_DEFAULTED;\n+\tport->partner_state = STATE_LACP_ACTIVE;\n+\tport->sm_flags = SM_FLAGS_BEGIN;\n+\n+\t/* use this port as agregator */\n+\tport->used_agregator_idx = num;\n+}\n+\n+void\n+bond_mode_8023ad_slave_append(struct rte_eth_dev *bond_dev)\n+{\n+\tstruct bond_dev_private *internals = bond_dev->data->dev_private;\n+\n+\tbond_mode_8023ad_activate_slave(bond_dev, internals->active_slave_count);\n+}\n+\n+int\n+bond_mode_8023ad_deactivate_slave(struct rte_eth_dev *bond_dev,\n+\t\tuint8_t slave_pos)\n+{\n+\tstruct bond_dev_private *internals = bond_dev->data->dev_private;\n+\tstruct mode8023ad_data *data = &internals->mode4;\n+\tstruct port *port;\n+\tuint8_t i;\n+\n+\tbond_mode_8023ad_stop(bond_dev);\n+\n+\t/* Exclude slave from transmit policy. If this slave is an aggregator\n+\t * make all aggregated slaves unselected to force sellection logic\n+\t * to select suitable aggregator for this port\t */\n+\tfor (i = 0; i < internals->active_slave_count; i++) {\n+\t\tport = &data->port_list[slave_pos];\n+\t\tif (port->used_agregator_idx == slave_pos) {\n+\t\t\tport->selected = UNSELECTED;\n+\t\t\tport->actor_state &= ~(STATE_SYNCHRONIZATION | STATE_DISTRIBUTING |\n+\t\t\t\tSTATE_COLLECTING);\n+\n+\t\t\t/* Use default aggregator */\n+\t\t\tport->used_agregator_idx = i;\n+\t\t}\n+\t}\n+\n+\tport = &data->port_list[slave_pos];\n+\ttimer_cancel(&port->current_while_timer);\n+\ttimer_cancel(&port->periodic_timer);\n+\ttimer_cancel(&port->wait_while_timer);\n+\ttimer_cancel(&port->tx_machine_timer);\n+\n+\tupdate_mux_slaves(internals);\n+\n+\t/* Remove slave port config */\n+\tif (slave_pos + 1 < internals->active_slave_count) {\n+\t\tmemmove(&data->port_list[slave_pos],\n+\t\t\t&data->port_list[slave_pos + 1],\n+\t\t\tsizeof(data->port_list[0]) * internals->active_slave_count -\n+\t\t\t\tslave_pos - 1);\n+\t}\n+\n+\tif (bond_dev->data->dev_started)\n+\t\treturn bond_mode_8023ad_start(bond_dev);\n+\n+\treturn 0;\n+}\n+\n+int\n+bond_mode_8023ad_init(struct rte_eth_dev *bond_dev)\n+{\n+\tstruct bond_dev_private *internals = bond_dev->data->dev_private;\n+\tstruct mode8023ad_data *data = &internals->mode4;\n+\tchar mem_name[RTE_ETH_NAME_MAX_LEN];\n+\tint socket_id = bond_dev->pci_dev->numa_node;\n+\tuint8_t i;\n+\n+\tif (data->mbuf_pool == NULL) {\n+\t\tconst uint16_t element_size = sizeof(struct slow_protocol_frame) +\n+\t\t\tsizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM;\n+\n+\t\tsnprintf(mem_name, sizeof(mem_name), \"%s_POOL\",\tbond_dev->data->name);\n+\t\tdata->mbuf_pool = rte_mempool_create(mem_name,\n+\t\t\t /* FIXME: How big memory pool should be? If driver will not\n+\t\t\t  * fee packets quick enough there will be ENOMEM in tx_machine.\n+\t\t\t  * For now give 512 packets per slave. Hope it will be enough. */\n+\t\t\t(BOND_MODE_8023AX_TX_RING_SIZE + 1) * (RTE_MAX_ETHPORTS * 512),\n+\t\t\telement_size,\n+\t\t\tRTE_MEMPOOL_CACHE_MAX_SIZE >= 32 ? 32 : RTE_MEMPOOL_CACHE_MAX_SIZE,\n+\t\t\tsizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init,\n+\t\t\tNULL, rte_pktmbuf_init, NULL, socket_id, 0);\n+\n+\t\t/* Any memory allocation failure in initalization is critical because\n+\t\t * resources can't be free, so reinitialization is impossible. */\n+\t\tif (data->mbuf_pool == NULL) {\n+\t\t\tRTE_LOG(ERR, PMD, \"%s: Failed to initialize LACP rx ring\\n\",\n+\t\t\t\tbond_dev->data->name);\n+\n+\t\t\trte_panic(\"Failed to alocate memory pool ('%s')\\n\"\n+\t\t\t\t\"for bond device '%s'\\n\", mem_name, bond_dev->data->name);\n+\t\t}\n+\n+\t\t/* Setup ring for free messages that can be used in RX/TX burst */\n+\t\tsnprintf(mem_name, sizeof(mem_name), \"%s_free\",\n+\t\t\tbond_dev->data->name);\n+\n+\t\tuint16_t free_ring_size = BOND_MODE_8023AX_RX_RING_SIZE +\n+\t\t\tBOND_MODE_8023AX_TX_RING_SIZE;\n+\n+\t\tdata->free_ring = rte_ring_create(mem_name,\n+\t\t\tfree_ring_size, socket_id, RING_F_SC_DEQ);\n+\n+\t\tif (data->free_ring == NULL) {\n+\t\t\trte_panic(\"%s: Failed to create slow messages free ring\\n\",\n+\t\t\t\tbond_dev->data->name);\n+\t\t}\n+\n+\t\tfor (i = 0; i < free_ring_size; i++) {\n+\t\t\tstruct slow_protocol_msg *msg;\n+\n+\t\t\tsnprintf(mem_name, sizeof(mem_name), \"%s_slow_msg_%u\",\n+\t\t\t\tbond_dev->data->name, i);\n+\n+\t\t\tmsg = (struct slow_protocol_msg *) rte_malloc_socket(mem_name,\n+\t\t\t\tsizeof(struct slow_protocol_msg), 0, socket_id);\n+\n+\t\t\tif (msg == NULL) {\n+\t\t\t\trte_panic(\"%s: Failed to allocate slow message\\n\",\n+\t\t\t\tbond_dev->data->name);\n+\t\t\t}\n+\n+\t\t\trte_ring_enqueue(data->free_ring, msg);\n+\t\t}\n+\n+\t\t/* Setup rings for usage in rx/tx bursts and machines state call back */\n+\t\tsnprintf(mem_name, sizeof(mem_name), \"%s_rx\", bond_dev->data->name);\n+\t\tdata->rx_ring = rte_ring_create(mem_name, BOND_MODE_8023AX_RX_RING_SIZE,\n+\t\t\tsocket_id, RING_F_SC_DEQ);\n+\n+\t\tif (data->rx_ring == NULL) {\n+\t\t\trte_panic(\"%s: Failed to create slow messages rx ring\\n\",\n+\t\t\t\tbond_dev->data->name);\n+\t\t}\n+\n+\t\tsnprintf(mem_name, sizeof(mem_name), \"%s_tx\", bond_dev->data->name);\n+\t\tdata->tx_ring = rte_ring_create(mem_name, BOND_MODE_8023AX_TX_RING_SIZE,\n+\t\t\tsocket_id, RING_F_SP_ENQ);\n+\n+\t\tif (data->tx_ring == NULL) {\n+\t\t\trte_panic(\"%s: Failed to create slow messages tx ring\\n\",\n+\t\t\t\tbond_dev->data->name);\n+\t\t}\n+\t}\n+\n+\tdata->distibuting_slaves_count = 0;\n+\n+\tfor (i = 0; i < internals->active_slave_count; i++)\n+\t\tbond_mode_8023ad_activate_slave(bond_dev, i);\n+\n+\trte_eth_promiscuous_enable(bond_dev->data->port_id);\n+\treturn 0;\n+}\n+\n+int\n+bond_mode_8023ad_start(struct rte_eth_dev *bond_dev)\n+{\n+\treturn rte_eal_alarm_set(BOND_MODE_8023AX_UPDATE_TIMEOUT_MS * 1000,\n+\t\tbond_mode_8023ad_periodic_cb, bond_dev);\n+}\n+\n+int\n+bond_mode_8023ad_stop(struct rte_eth_dev *bond_dev)\n+{\n+\trte_eal_alarm_cancel(bond_mode_8023ad_periodic_cb, bond_dev);\n+\treturn 0;\n+}\n+\n+void\n+bond_mode_8023ad_handle_slow_pkt(struct bond_dev_private *internals,\n+\tuint8_t slave_pos, struct rte_mbuf *slot_pkt)\n+{\n+\tstruct mode8023ad_data *data;\n+\tstruct slow_protocol_msg *msg = NULL;\n+\n+\tdata = &internals->mode4;\n+\n+\tif (unlikely(rte_ring_dequeue(data->free_ring, (void **)&msg) ==\n+\t\t\t-ENOBUFS)) {\n+\t\trte_pktmbuf_free(slot_pkt);\n+\t\treturn;\n+\t}\n+\n+\tmsg->pkt = slot_pkt;\n+\tmsg->port_id = internals->active_slaves[slave_pos];\n+\n+\tif (unlikely(rte_ring_enqueue(data->rx_ring, msg) == -ENOBUFS)) {\n+\t\t/* If RX fing full free lacpdu message and drop packet */\n+\t\trte_ring_enqueue(data->free_ring, msg);\n+\t\trte_pktmbuf_free(slot_pkt);\n+\t}\n+}\ndiff --git a/lib/librte_pmd_bond/rte_eth_bond_8023ad.h b/lib/librte_pmd_bond/rte_eth_bond_8023ad.h\nnew file mode 100644\nindex 0000000..3c73f65\n--- /dev/null\n+++ b/lib/librte_pmd_bond/rte_eth_bond_8023ad.h\n@@ -0,0 +1,411 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#ifndef RTE_ETH_BOND_8023AD_H_\n+#define RTE_ETH_BOND_8023AD_H_\n+\n+#include <stdint.h>\n+\n+#include <rte_ether.h>\n+#include <rte_byteorder.h>\n+\n+typedef int\tbool;\n+\n+#define true\t1\n+#define false\t0\n+\n+/**\n+ * Constants (5.4.4 in 802.1AX documentation).\n+ */\n+#define BOND_8023AD_FAST_PERIODIC_MS               1000\n+#define BOND_8023AD_SLOW_PERIODIC_MS              30000\n+#define BOND_8023AD_SHORT_TIMEOUT_MS               3000\n+#define BOND_8023AD_LONG_TIMEOUT_MS               90000\n+#define BOND_8023AD_CHURN_DETECTION_TIMEOUT_MS    60000\n+#define BOND_8023AD_AGGREGATE_WAIT_TIMEOUT_MS      2000\n+#define BOND_8023AD_TX_PERIOD_MS                    333\n+/**\n+ * Actor/partner states\n+ */\n+#define STATE_LACP_ACTIVE                   0x01\n+#define STATE_LACP_SHORT_TIMEOUT            0x02\n+#define STATE_AGGREGATION                   0x04\n+#define STATE_SYNCHRONIZATION               0x08\n+#define STATE_COLLECTING                    0x10\n+#define STATE_DISTRIBUTING                  0x20\n+/** Partners parameters are defaulted */\n+#define STATE_DEFAULTED                     0x40\n+#define STATE_EXPIRED                       0x80\n+\n+/**\n+ * State machine flags\n+ */\n+#define SM_FLAGS_BEGIN                      0x0001\n+#define SM_FLAGS_LACP_ENABLED               0x0002\n+#define SM_FLAGS_ACTOR_CHURN                0x0004\n+#define SM_FLAGS_PARTNER_CHURN              0x0008\n+#define SM_FLAGS_MOVED                      0x0100\n+#define SM_FLAGS_PARTNER_SHORT_TIMEOUT      0x0200\n+#define SM_FLAGS_NTT                        0x0400\n+\n+#define BOND_MODE_8023AX_UPDATE_TIMEOUT_MS  100\n+#define BOND_MODE_8023AX_RX_RING_SIZE       (2 * RTE_MAX_ETHPORTS)\n+#define BOND_MODE_8023AX_TX_RING_SIZE       (2 * RTE_MAX_ETHPORTS)\n+\n+#define BOND_LINK_FULL_DUPLEX_KEY           0x01\n+#define BOND_LINK_SPEED_KEY_10M             0x02\n+#define BOND_LINK_SPEED_KEY_100M            0x04\n+#define BOND_LINK_SPEED_KEY_1000M           0x08\n+#define BOND_LINK_SPEED_KEY_10G             0x10\n+#define BOND_LINK_SPEED_KEY_20G             0x11\n+#define BOND_LINK_SPEED_KEY_40G             0x12\n+\n+#define SUBTYPE_LACP                        0x01\n+\n+#define TLV_TYPE_ACTOR_INFORMATION          0x01\n+#define TLV_TYPE_PARTNER_INFORMATION        0x02\n+#define TLV_TYPE_COLLECTOR_INFORMATION      0x03\n+#define TLV_TYPE_TERMINATOR_INFORMATION     0x00\n+\n+#define CHECK_FLAGS(_variable, _flags) ((_variable) & (_flags))\n+#define SET_FLAGS(_variable, _flags) ((_variable) |= (_flags))\n+#define CLEAR_FLAGS(_variable, _flags) ((_variable) &= ~(_flags))\n+\n+#define SM_FLAG(port, flag) (!!CHECK_FLAGS((port)->sm_flags, SM_FLAGS_ ## flag))\n+#define SM_FLAG_SET(port, flag) SET_FLAGS((port)->sm_flags, SM_FLAGS_ ## flag)\n+#define SM_FLAG_CLR(port, flag) CLEAR_FLAGS((port)->sm_flags, SM_FLAGS_ ## flag)\n+\n+#define ACTOR_STATE(port, flag) (!!CHECK_FLAGS((port)->actor_state, STATE_ ## flag))\n+#define ACTOR_STATE_SET(port, flag) SET_FLAGS((port)->actor_state, STATE_ ## flag)\n+#define ACTOR_STATE_CLR(port, flag) CLEAR_FLAGS((port)->actor_state, STATE_ ## flag)\n+\n+#define PARTNER_STATE(port, flag) (!!CHECK_FLAGS((port)->partner_state, STATE_ ## flag))\n+#define PARTNER_STATE_SET(port, flag) SET_FLAGS((port)->partner_state, STATE_ ## flag)\n+#define PARTNER_STATE_CLR(port, flag) CLEAR_FLAGS((port)->partner_state, STATE_ ## flag)\n+\n+/** Slow protocol LACP frame subtype */\n+#define SLOW_SUBTYPE_LACP\t\t\t\t\t0x01\n+\n+/** Slow procotol marker frame subtype */\n+#define SLOW_SUBTYPE_MARKER\t\t\t\t\t0x02\n+\n+/** Marker type info request */\n+#define MARKER_TLV_TYPE_MARKER_INFO\t\t\t0x01\n+\n+/** Marker type info response */\n+#define MARKER_TLV_TYPE_MARKER_RESP\t\t\t0x02\n+\n+/** Generic slow protocol structure */\n+struct slow_protocol {\n+\tuint8_t subtype;\n+\tuint8_t reserved_119[119];\n+} __attribute__((__packed__));\n+\n+/** Generic slow protocol frame type structure */\n+struct slow_protocol_frame {\n+\tstruct ether_hdr eth_hdr;\n+\tstruct slow_protocol slow_protocol;\n+} __attribute__((__packed__));\n+\n+struct port_params {\n+\tuint16_t system_priority;\n+\t/**< System priority (unused in current implementation) */\n+\tstruct ether_addr system;\n+\t/**< System ID - Slave MAC address, same as bonding MAC address */\n+\tuint16_t key;\n+\t/**< Speed information (implementation dependednt) and duplex. */\n+\tuint16_t port_priority;\n+\t/**< Priority of this (unused in current implementation) */\n+\tuint16_t port_number;\n+\t/**< Port number. It corresponds to slave port id. */\n+} __attribute__((__packed__));\n+\n+struct lacpdu_actor_partner_params {\n+\tuint8_t tlv_type_info;\n+\tuint8_t info_length;\n+\tstruct port_params port_params;\n+\tuint8_t state;\n+\tuint8_t reserved_3[3];\n+} __attribute__((__packed__));\n+\n+/** LACPDU structure (5.4.2 in 802.1AX documentation). */\n+struct lacpdu {\n+\tuint8_t subtype;\n+\tuint8_t version_number;\n+\n+\tstruct lacpdu_actor_partner_params actor;\n+\tstruct lacpdu_actor_partner_params partner;\n+\n+\tuint8_t tlv_type_collector_info;\n+\tuint8_t collector_info_length;\n+\tuint16_t collector_max_delay;\n+\tuint8_t reserved_12[12];\n+\n+\tuint8_t tlv_type_terminator;\n+\tuint8_t terminator_length;\n+\tuint8_t reserved_50[50];\n+} __attribute__((__packed__));\n+\n+/** LACPDU frame: Contains ethernet header and LACPDU. */\n+struct lacpdu_header {\n+\tstruct ether_hdr eth_hdr;\n+\tstruct lacpdu lacpdu;\n+} __attribute__((__packed__));\n+\n+struct marker {\n+\tuint8_t subtype;\n+\tuint8_t version_number;\n+\n+\tuint8_t tlv_type_marker;\n+\tuint8_t info_length;\n+\tuint16_t requester_port;\n+\tstruct ether_addr requester_system;\n+\tuint32_t requester_transaction_id;\n+\tuint8_t reserved_2[2];\n+\n+\tuint8_t tlv_type_terminator;\n+\tuint8_t terminator_length;\n+\tuint8_t reserved_90[90];\n+} __attribute__((__packed__));\n+\n+struct marker_header {\n+\tstruct ether_hdr eth_hdr;\n+\tstruct marker marker;\n+} __attribute__((__packed__));\n+\n+/** Variables associated with the system (5.4.5 in 802.1AX documentation). */\n+struct system {\n+\tstruct ether_addr actor_system;\n+\t/**< The MAC address component of the System Identifier of the System */\n+\tuint16_t actor_system_priority;\n+\t/**< The System Priority of the System */\n+};\n+\n+enum selection {\n+\tUNSELECTED,\n+\tSTANDBY,\n+\tSELECTED\n+};\n+\n+enum timer_state {\n+\tTIMER_NOT_STARTED,\n+\tTIMER_RUNNING,\n+\tTIMER_EXPIRED,\n+};\n+\n+/** Variables associated with each port (5.4.7 in 802.1AX documentation). */\n+struct port {\n+\t/**\n+\t * The operational values of the Actor's state parameters. Bitmask\n+\t * of port states.\n+\t */\n+\tuint8_t actor_state;\n+\n+\t/** The operational Actor's port parameters */\n+\tstruct port_params actor;\n+\n+\t/**\n+\t * The operational value of the Actor's view of the current values of\n+\t * the Partner's state parameters. The Actor sets this variable either\n+\t * to the value received from the Partner in an LACPDU, or to the value\n+\t * of Partner_Admin_Port_State. Bitmask of port states.\n+\t */\n+\tuint8_t partner_state;\n+\n+\t/** The operational Partner's port parameters */\n+\tstruct port_params partner;\n+\n+\t/* Additional port parameters not listed in documentation */\n+\t/** State machine flags */\n+\tuint16_t sm_flags;\n+\tenum selection selected;\n+\n+\tenum timer_state current_while_timer;\n+\tenum timer_state periodic_timer;\n+\tenum timer_state wait_while_timer;\n+\tenum timer_state tx_machine_timer;\n+\n+\t/* Agregator parameters */\n+\t/**\n+\t * Index in mode8023ad_data::port_list[] of Aggregator\n+\t * the port is currently attached to.\n+\t */\n+\tuint16_t used_agregator_idx;\n+};\n+\n+\n+/**\n+ * Struct used to comunicate with 8023ad logic.\n+ */\n+struct slow_protocol_msg {\n+\tstruct rte_mbuf *pkt;\n+\tuint8_t port_id;\n+};\n+\n+/** Data specific to mode 802.1AX */\n+struct mode8023ad_data {\n+\t/** Memory pool used to allocated rings */\n+\tstruct rte_mempool *mbuf_pool;\n+\n+\t/** Ring containing free slow_protocol_msg objects. Used to avoid\n+\t * alocating/freeing memory in RX/TX bursts */\n+\tstruct rte_ring *free_ring;\n+\n+\t/** Ring of struct slow_protocol_msg from RX burst function */\n+\tstruct rte_ring *rx_ring;\n+\n+\t/** Ring of struct slow_protocol_msg to RX burst function */\n+\tstruct rte_ring *tx_ring;\n+\n+\t/** list of all enslaved ports in mode 802.1AX */\n+\tstruct port port_list[RTE_MAX_ETHPORTS];\n+\n+\t/** List of slaves ID used to transmiting packets */\n+\tuint8_t distibuting_slaves[RTE_MAX_ETHPORTS];\n+\tuint8_t distibuting_slaves_count;\n+};\n+\n+/* Forward declaration */\n+struct bond_dev_private;\n+\n+/**\n+ * Configures 802.1AX mode and all active slaves on bonded interface.\n+ *\n+ * @param dev Bonded interface\n+ * @return\n+ *  0 on success, negative value otherwise.\n+ */\n+int\n+bond_mode_8023ad_init(struct rte_eth_dev *dev);\n+\n+/**\n+ * Deconfigures 802.1AX mode of the bonded interface and slaves.\n+ *\n+ * @param dev Bonded interface\n+ * @return\n+ *   0 on success, negative value otherwise.\n+ */\n+int bond_mode_8023ad_disable(struct rte_eth_dev *dev);\n+\n+/**\n+ * Starts 802.3AX state machines management logic.\n+ * @param dev Bonded interface\n+ * @return\n+ *   0 on success, negative value otherwise.\n+ */\n+int\n+bond_mode_8023ad_start(struct rte_eth_dev *dev);\n+\n+/**\n+ * Stops 802.3AX state machines management logic.\n+ * @param dev Bonded interface\n+ * @return\n+ *   0 on success, negative value otherwise.\n+ */\n+\n+int\n+bond_mode_8023ad_stop(struct rte_eth_dev *dev);\n+\n+/**\n+ * Passes given slow packet to state machines management logic.\n+ * @param internals Bonded device private data.\n+ * @param slave_pos Possition in active slaves array on which this packet was received.\n+ * @param slot_pkt Slow packet\n+ */\n+void\n+bond_mode_8023ad_handle_slow_pkt(struct bond_dev_private *internals,\n+\tuint8_t slave_pos, struct rte_mbuf *slot_pkt);\n+\n+/**\n+ * Appends and initializes slave active_slaves[slave_num] to use with\n+ * 802.1AX mode.\n+ *\n+ * @pre active_slaves[active_slave_count] must contain valid slave id.\n+ * @post active_slave_count must be incremented.\n+ *\n+ * @param dev       Bonded interface.\n+ *\n+ * @return\n+ *  0 on success, negative value otherwise.\n+ */\n+void\n+bond_mode_8023ad_slave_append(struct rte_eth_dev *dev);\n+\n+/**\n+ * Denitializes and removes given slave from 802.1AX mode.\n+ *\n+ * @pre active_slaves[slave_num] must contain valid slave id corresponding to\n+ * \t\tslave initialized in 802.1AX mode.\n+ * @post active_slaves[slave_num] must be removed.\n+ *\n+ * @param dev       Bonded interface.\n+ * @param slave_num Position of slave in active_slaves array\n+ *\n+ * @return\n+ *  0 on success, negative value otherwise.\n+ *\n+ */\n+int\n+bond_mode_8023ad_deactivate_slave(struct rte_eth_dev *dev, uint8_t slave_pos);\n+\n+/**\n+ * Converts port_number from network byte order to port id.\n+ *\n+ * @param port_number The 8023ad port number to convert.\n+ * @return corresponding slave id\n+ */\n+static inline uint8_t\n+port_number_to_slave_id(uint16_t port_number)\n+{\n+\tuint16_t port_id = rte_be_to_cpu_16(port_number);\n+\t/* Standard requires that port number must be grater than 0.\n+\t * Substract 1 to get corresponding slave id */\n+\treturn port_id - 1;\n+}\n+\n+/**\n+ * Converts port id to mode 8023ad port number.\n+ *\n+ * @param slave_id Id of slave to convert.\n+ * @return corresponding Port number in network byte order.\n+ */\n+static inline uint16_t\n+slave_id_to_port_number(uint8_t slave_id)\n+{\n+\t/* Standard requires that port ID must be grater than 0.\n+\t * Add 1 do get corresponding port_number */\n+\tuint16_t port_number = (uint16_t)slave_id + 1;\n+\treturn rte_cpu_to_be_16(port_number);\n+}\n+\n+#endif /* RTE_ETH_BOND_8023AD_H_ */\ndiff --git a/lib/librte_pmd_bond/rte_eth_bond_api.c b/lib/librte_pmd_bond/rte_eth_bond_api.c\nindex 460df65..264b86e 100644\n--- a/lib/librte_pmd_bond/rte_eth_bond_api.c\n+++ b/lib/librte_pmd_bond/rte_eth_bond_api.c\n@@ -107,24 +107,29 @@ valid_slave_port_id(uint8_t port_id)\n }\n \n void\n-rte_eth_bond_activate_slave(struct rte_eth_dev *eth_dev, uint8_t port_id )\n+rte_eth_bond_activate_slave(struct rte_eth_dev *eth_dev, uint8_t port_id)\n {\n \tstruct bond_dev_private *internals = eth_dev->data->dev_private;\n \tuint8_t active_count = internals->active_slave_count;\n \n \tinternals->active_slaves[active_count] = port_id;\n \n+\tif (internals->mode == BONDING_MODE_8023AD)\n+\t\tbond_mode_8023ad_slave_append(eth_dev);\n \n \tinternals->active_slave_count = active_count + 1;\n }\n \n void\n-rte_eth_bond_deactive_slave(struct rte_eth_dev *eth_dev,\n-\tuint8_t slave_pos )\n+rte_eth_bond_deactivate_slave(struct rte_eth_dev *eth_dev,\n+\tuint8_t slave_pos)\n {\n \tstruct bond_dev_private *internals = eth_dev->data->dev_private;\n \tuint8_t active_count = internals->active_slave_count;\n \n+\tif (internals->mode == BONDING_MODE_8023AD)\n+\t\tbond_mode_8023ad_deactivate_slave(eth_dev, slave_pos);\n+\n \tactive_count--;\n \n \t/* If slave was not at the end of the list\n@@ -252,13 +257,7 @@ rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id)\n \teth_dev->dev_ops = &default_dev_ops;\n \teth_dev->pci_dev = pci_dev;\n \n-\tif (bond_ethdev_mode_set(eth_dev, mode)) {\n-\t\tRTE_LOG(ERR, PMD,\n-\t\t\t\t\"%s: failed to set bonded device %d mode too %d\\n\",\n-\t\t\t\t__func__, eth_dev->data->port_id, mode);\n-\t\tgoto err;\n-\t}\n-\n+\tinternals->mode = BONDING_MODE_INVALID;\n \tinternals->current_primary_port = 0;\n \tinternals->balance_xmit_policy = BALANCE_XMIT_POLICY_LAYER2;\n \tinternals->user_defined_mac = 0;\n@@ -272,6 +271,13 @@ rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id)\n \tmemset(internals->presisted_slaves_conf, 0,\n \t\t\tsizeof(internals->presisted_slaves_conf));\n \n+\tif (bond_ethdev_mode_set(eth_dev, mode)) {\n+\t\tRTE_LOG(ERR, PMD,\n+\t\t\t\t\"%s: failed to set bonded device %d mode too %d\\n\",\n+\t\t\t\t__func__, eth_dev->data->port_id, mode);\n+\t\tgoto err;\n+\t}\n+\n \treturn eth_dev->data->port_id;\n \n err:\n@@ -428,7 +434,7 @@ rte_eth_bond_slave_remove(uint8_t bonded_port_id, uint8_t slave_port_id)\n \t\t\tslave_port_id);\n \n \tif (pos < internals->active_slave_count)\n-\t\trte_eth_bond_deactive_slave(eth_dev, pos);\n+\t\trte_eth_bond_deactivate_slave(eth_dev, pos);\n \n \tpos = -1;\n \t/* now remove from slave list */\ndiff --git a/lib/librte_pmd_bond/rte_eth_bond_args.c b/lib/librte_pmd_bond/rte_eth_bond_args.c\nindex 11d9816..72458b3 100644\n--- a/lib/librte_pmd_bond/rte_eth_bond_args.c\n+++ b/lib/librte_pmd_bond/rte_eth_bond_args.c\n@@ -170,6 +170,7 @@ bond_ethdev_parse_slave_mode_kvarg(const char *key __rte_unused,\n \tcase BONDING_MODE_ACTIVE_BACKUP:\n \tcase BONDING_MODE_BALANCE:\n \tcase BONDING_MODE_BROADCAST:\n+\tcase BONDING_MODE_8023AD:\n \t\treturn 0;\n \tdefault:\n \t\treturn -1;\ndiff --git a/lib/librte_pmd_bond/rte_eth_bond_pmd.c b/lib/librte_pmd_bond/rte_eth_bond_pmd.c\nindex 482ddb8..9c99755 100644\n--- a/lib/librte_pmd_bond/rte_eth_bond_pmd.c\n+++ b/lib/librte_pmd_bond/rte_eth_bond_pmd.c\n@@ -40,9 +40,11 @@\n #include <rte_devargs.h>\n #include <rte_kvargs.h>\n #include <rte_dev.h>\n+#include <rte_log.h>\n \n #include \"rte_eth_bond.h\"\n #include \"rte_eth_bond_private.h\"\n+#include \"rte_eth_bond_8023ad.h\"\n \n static uint16_t\n bond_ethdev_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)\n@@ -167,6 +169,46 @@ bond_ethdev_tx_burst_active_backup(void *queue,\n \t\t\tbufs, nb_pkts);\n }\n \n+static uint16_t\n+bond_ethdev_rx_burst_8023ad(void *queue, struct rte_mbuf **bufs,\n+\t\tuint16_t nb_pkts)\n+{\n+\t/* Cast to structure, containing bonded device's port id and queue id */\n+\tstruct bond_rx_queue *bd_rx_q = (struct bond_rx_queue *)queue;\n+\tstruct bond_dev_private *internals = bd_rx_q->dev_private;\n+\tstruct mode8023ad_data *mode4 = &internals->mode4;\n+\n+\tstruct ether_hdr *hdr;\n+\tstruct rte_mbuf *pkts[nb_pkts + 1]; /* one packet more for slow packet */\n+\n+\tuint16_t num_rx_slave = 0;\t/* Number of packet received on current slave */\n+\tuint16_t num_rx_total = 0;\t/* Total number of received packets */\n+\n+\tuint8_t i, j;\n+\n+\tfor (i = 0; i < internals->active_slave_count && num_rx_total < nb_pkts; i++) {\n+\t\t/* Read packets from this slave */\n+\t\tnum_rx_slave = rte_eth_rx_burst(internals->active_slaves[i],\n+\t\t\t\tbd_rx_q->queue_id, pkts, nb_pkts + 1 - num_rx_total);\n+\n+\t\t/* Separate slow protocol packets from others */\n+\t\tfor (j = 0; j < num_rx_slave; j++) {\n+\t\t\thdr = rte_pktmbuf_mtod(pkts[j], struct ether_hdr *);\n+\n+\t\t\tuint16_t ether_type = rte_be_to_cpu_16(hdr->ether_type);\n+\t\t\tif (likely(ether_type != ETHER_TYPE_SLOW)) {\n+\t\t\t\tif (likely(ACTOR_STATE(&mode4->port_list[i], COLLECTING)))\n+\t\t\t\t\tbufs[num_rx_total++] = pkts[j];\n+\t\t\t\telse\n+\t\t\t\t\trte_pktmbuf_free(pkts[j]);\n+\t\t\t} else\n+\t\t\t\tbond_mode_8023ad_handle_slow_pkt(internals, i, pkts[j]);\n+\t\t}\n+\t}\n+\n+\treturn num_rx_total;\n+}\n+\n static inline uint16_t\n ether_hash(struct ether_hdr *eth_hdr)\n {\n@@ -349,6 +391,125 @@ bond_ethdev_tx_burst_balance(void *queue, struct rte_mbuf **bufs,\n }\n \n static uint16_t\n+bond_ethdev_tx_burst_8023ad(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)\n+{\n+\tstruct bond_dev_private *internals;\n+\tstruct mode8023ad_data *mode4;\n+\tstruct bond_tx_queue *bd_tx_q;\n+\n+\tuint8_t num_of_slaves;\n+\tuint8_t slaves[RTE_MAX_ETHPORTS];\n+\t /* possitions in slaves, not ID */\n+\tuint8_t distributing_slaves[RTE_MAX_ETHPORTS];\n+\tuint8_t distributing_slaves_count;\n+\n+\tuint16_t num_tx_slave, num_tx_total = 0, tx_fail_total = 0;\n+\tuint16_t i, op_slave_id;\n+\n+\t/* Slow packets from 802.3AX state machines. */\n+\tstruct slow_protocol_msg *slow_msg;\n+\n+\t/* Allocate one additional packet in case 8023AD mode.\n+\t * First element if not NULL is slow packet. */\n+\tstruct rte_mbuf *slave_bufs[RTE_MAX_ETHPORTS][nb_pkts + 1];\n+\t/* Total amount of packets in slave_bufs */\n+\tuint16_t slave_nb_pkts[RTE_MAX_ETHPORTS] = { 0 };\n+\t/* Array of slow packets placed in each slave */\n+\tuint8_t slave_slow_packets[RTE_MAX_ETHPORTS] = { 0 };\n+\n+\tbd_tx_q = (struct bond_tx_queue *)queue;\n+\tinternals = bd_tx_q->dev_private;\n+\tmode4 = &internals->mode4;\n+\n+\t/* Copy slave list to protect against slave up/down changes during tx\n+\t * bursting */\n+\tnum_of_slaves = internals->active_slave_count;\n+\tif (num_of_slaves < 1)\n+\t\treturn num_tx_total;\n+\n+\tmemcpy(slaves, internals->active_slaves, sizeof(slaves[0]) * num_of_slaves);\n+\n+\tdistributing_slaves_count = mode4->distibuting_slaves_count;\n+\tmemcpy(distributing_slaves, mode4->distibuting_slaves,\n+\t\t\tsizeof(slaves[0]) * distributing_slaves_count);\n+\n+\tfor (i = 0; i < num_of_slaves; i++)\n+\t\tslave_bufs[i][0] = NULL;\n+\n+\t/* It is likely that tx ring will be empty. If it is not empty, it is\n+\t * likely that there will be only one frame. */\n+\twhile (unlikely(!rte_ring_empty(mode4->tx_ring)) &&\n+\t\t\trte_ring_dequeue(mode4->tx_ring, (void **)&slow_msg) != -ENOENT) {\n+\t\ti = find_slave_by_id(slaves, num_of_slaves, slow_msg->port_id);\n+\n+\t\t/* Assign slow packet to slave or drop it if slave is not in active list\n+\t\t * (ex: link down). */\n+\t\tif (likely(i < num_of_slaves)) {\n+\t\t\t /* If there is more than one slow packet to the same slave, send\n+\t\t\t  * only latest, and drop previouse - tx burst was no called quick\n+\t\t\t  * enough. */\n+\t\t\tif (slave_bufs[i][0] != NULL)\n+\t\t\t\trte_pktmbuf_free(slave_bufs[i][0]);\n+\n+\t\t\tslave_bufs[i][0] = slow_msg->pkt;\n+\t\t\tslave_nb_pkts[i] = 1;\n+\t\t\tslave_slow_packets[i] = 1;\n+\t\t} else\n+\t\t\trte_pktmbuf_free(slow_msg->pkt);\n+\n+\t\trte_ring_enqueue(mode4->free_ring, slow_msg);\n+\t}\n+\n+\tif (likely(distributing_slaves_count > 0)) {\n+\t\t/* Populate slaves mbuf with the packets which are to be sent on it */\n+\t\tfor (i = 0; i < nb_pkts; i++) {\n+\t\t\t/* Select output slave using hash based on xmit policy */\n+\t\t\top_slave_id = xmit_slave_hash(bufs[i], distributing_slaves_count,\n+\t\t\t\t\tinternals->balance_xmit_policy);\n+\n+\t\t\t/* Populate slave mbuf arrays with mbufs for that slave. Use only slaves\n+\t\t\t * that are currently distributing. */\n+\t\t\tuint8_t slave_pos = distributing_slaves[op_slave_id];\n+\t\t\tuint16_t pkt_pos = slave_nb_pkts[op_slave_id];\n+\t\t\tslave_nb_pkts[op_slave_id]++;\n+\n+\t\t\tslave_bufs[slave_pos][pkt_pos] = bufs[i];\n+\t\t}\n+\t}\n+\n+\t/* Send packet burst on each slave device */\n+\tfor (i = 0; i < num_of_slaves; i++) {\n+\t\tif (slave_nb_pkts[i] > 0) {\n+\t\t\tnum_tx_slave = rte_eth_tx_burst(slaves[i], bd_tx_q->queue_id,\n+\t\t\t\t\tslave_bufs[i], slave_nb_pkts[i]);\n+\n+\t\t\t/* if tx burst fails move packets to end of bufs */\n+\t\t\tif (unlikely(num_tx_slave < slave_nb_pkts[i])) {\n+\t\t\t\tuint16_t slave_tx_fail_count = slave_nb_pkts[i] - num_tx_slave;\n+\n+\t\t\t\t/* Free slow packet if it exists and not send. */\n+\t\t\t\tif (slave_slow_packets[i] != 0 && num_tx_slave == 0) {\n+\t\t\t\t\trte_pktmbuf_free(slave_bufs[i][0]);\n+\t\t\t\t\tslave_tx_fail_count--;\n+\t\t\t\t}\n+\n+\t\t\t\ttx_fail_total += slave_tx_fail_count;\n+\t\t\t\tmemcpy(bufs[nb_pkts - tx_fail_total],\n+\t\t\t\t\tslave_bufs[i][num_tx_slave + slave_slow_packets[i]],\n+\t\t\t\t\tslave_tx_fail_count);\n+\t\t\t}\n+\n+\t\t\tif (num_tx_slave > 0)\n+\t\t\t\tnum_tx_slave -= slave_slow_packets[i];\n+\n+\t\t\tnum_tx_total += num_tx_slave;\n+\t\t}\n+\t}\n+\n+\treturn num_tx_total;\n+}\n+\n+static uint16_t\n bond_ethdev_tx_burst_broadcast(void *queue, struct rte_mbuf **bufs,\n \t\tuint16_t nb_pkts)\n {\n@@ -505,6 +666,7 @@ mac_address_slaves_update(struct rte_eth_dev *bonded_eth_dev)\n \tcase BONDING_MODE_ROUND_ROBIN:\n \tcase BONDING_MODE_BALANCE:\n \tcase BONDING_MODE_BROADCAST:\n+\tcase BONDING_MODE_8023AD:\n \t\tfor (i = 0; i < internals->slave_count; i++) {\n \t\t\tif (mac_address_set(&rte_eth_devices[internals->slaves[i]],\n \t\t\t\t\tbonded_eth_dev->data->mac_addrs)) {\n@@ -568,6 +730,13 @@ bond_ethdev_mode_set(struct rte_eth_dev *eth_dev, int mode)\n \t\teth_dev->tx_pkt_burst = bond_ethdev_tx_burst_broadcast;\n \t\teth_dev->rx_pkt_burst = bond_ethdev_rx_burst;\n \t\tbreak;\n+\tcase BONDING_MODE_8023AD:\n+\t\tif (bond_mode_8023ad_init(eth_dev) != 0)\n+\t\t\treturn -1;\n+\n+\t\teth_dev->rx_pkt_burst = bond_ethdev_rx_burst_8023ad;\n+\t\teth_dev->tx_pkt_burst = bond_ethdev_tx_burst_8023ad;\n+\t\tbreak;\n \tdefault:\n \t\treturn -1;\n \t}\n@@ -764,6 +933,9 @@ bond_ethdev_start(struct rte_eth_dev *eth_dev)\n \tif (internals->user_defined_primary_port)\n \t\tbond_ethdev_primary_set(internals, internals->primary_port);\n \n+\tif (internals->mode == BONDING_MODE_8023AD)\n+\t\tbond_mode_8023ad_start(eth_dev);\n+\n \treturn 0;\n }\n \n@@ -772,6 +944,9 @@ bond_ethdev_stop(struct rte_eth_dev *eth_dev)\n {\n \tstruct bond_dev_private *internals = eth_dev->data->dev_private;\n \n+\tif (internals->mode == BONDING_MODE_8023AD)\n+\t\tbond_mode_8023ad_stop(eth_dev);\n+\n \tinternals->active_slave_count = 0;\n \n \teth_dev->data->dev_link.link_status = 0;\n@@ -954,6 +1129,7 @@ bond_ethdev_promiscuous_enable(struct rte_eth_dev *eth_dev)\n \tcase BONDING_MODE_ROUND_ROBIN:\n \tcase BONDING_MODE_BALANCE:\n \tcase BONDING_MODE_BROADCAST:\n+\tcase BONDING_MODE_8023AD:\n \t\tfor (i = 0; i < internals->slave_count; i++)\n \t\t\trte_eth_promiscuous_enable(internals->slaves[i]);\n \t\tbreak;\n@@ -977,6 +1153,7 @@ bond_ethdev_promiscuous_disable(struct rte_eth_dev *dev)\n \tcase BONDING_MODE_ROUND_ROBIN:\n \tcase BONDING_MODE_BALANCE:\n \tcase BONDING_MODE_BROADCAST:\n+\tcase BONDING_MODE_8023AD:\n \t\tfor (i = 0; i < internals->slave_count; i++)\n \t\t\trte_eth_promiscuous_disable(internals->slaves[i]);\n \t\tbreak;\n@@ -1057,7 +1234,7 @@ bond_ethdev_lsc_event_callback(uint8_t port_id, enum rte_eth_event_type type,\n \t\t\treturn;\n \n \t\t/* Remove from active slave list */\n-\t\trte_eth_bond_deactive_slave(bonded_eth_dev, active_pos);\n+\t\trte_eth_bond_deactivate_slave(bonded_eth_dev, active_pos);\n \n \t\t/* No active slaves, change link status to down and reset other\n \t\t * link properties */\ndiff --git a/lib/librte_pmd_bond/rte_eth_bond_private.h b/lib/librte_pmd_bond/rte_eth_bond_private.h\nindex 6742a4c..a615205 100644\n--- a/lib/librte_pmd_bond/rte_eth_bond_private.h\n+++ b/lib/librte_pmd_bond/rte_eth_bond_private.h\n@@ -41,6 +41,7 @@ extern \"C\" {\n #include <rte_ethdev.h>\n \n #include \"rte_eth_bond.h\"\n+#include \"rte_eth_bond_8023ad.h\"\n \n #define PMD_BOND_SLAVE_PORT_KVARG\t\t(\"slave\")\n #define PMD_BOND_PRIMARY_SLAVE_KVARG\t(\"primary\")\n@@ -53,6 +54,8 @@ extern \"C\" {\n #define PMD_BOND_XMIT_POLICY_LAYER23_KVARG\t(\"l23\")\n #define PMD_BOND_XMIT_POLICY_LAYER34_KVARG\t(\"l34\")\n \n+#define BONDING_MODE_INVALID 0xFF\n+\n extern const char *pmd_bond_init_valid_arguments[];\n \n extern const char *driver_name;\n@@ -123,6 +126,8 @@ struct bond_dev_private {\n \n \t/** Persisted configuration of slaves */\n \tstruct slave_conf presisted_slaves_conf[RTE_MAX_ETHPORTS];\n+\n+\tstruct mode8023ad_data mode4;\n };\n \n extern struct eth_dev_ops default_dev_ops;\n@@ -130,6 +135,8 @@ extern struct eth_dev_ops default_dev_ops;\n int\n valid_bonded_ethdev(struct rte_eth_dev *eth_dev);\n \n+/* Search given slave array to find possition of given id.\n+ * Return slave pos or slaves_count if not found. */\n static inline uint8_t\n find_slave_by_id(uint8_t *slaves, uint8_t slaves_count,\n \tuint8_t slave_id ) {\n@@ -153,7 +160,7 @@ int\n valid_slave_port_id(uint8_t port_id);\n \n void\n-rte_eth_bond_deactive_slave(struct rte_eth_dev *eth_dev,\n+rte_eth_bond_deactivate_slave(struct rte_eth_dev *eth_dev,\n \tuint8_t slave_pos );\n \n void\n",
    "prefixes": [
        "dpdk-dev",
        "2/2"
    ]
}