get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 1337,
    "url": "https://patches.dpdk.org/api/patches/1337/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1416328259-23926-2-git-send-email-michalx.k.jastrzebski@intel.com/",
    "project": {
        "id": 1,
        "url": "https://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": "<1416328259-23926-2-git-send-email-michalx.k.jastrzebski@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1416328259-23926-2-git-send-email-michalx.k.jastrzebski@intel.com",
    "date": "2014-11-18T16:30:58",
    "name": "[dpdk-dev,v4,1/2] bond: add mode 4 support",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "d43b41103d3785180c53791a1710f94950efa282",
    "submitter": {
        "id": 74,
        "url": "https://patches.dpdk.org/api/people/74/?format=api",
        "name": "Michal Jastrzebski",
        "email": "michalx.k.jastrzebski@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1416328259-23926-2-git-send-email-michalx.k.jastrzebski@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/1337/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/1337/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 A285B7F30;\n\tTue, 18 Nov 2014 17:21:17 +0100 (CET)",
            "from mga14.intel.com (mga14.intel.com [192.55.52.115])\n\tby dpdk.org (Postfix) with ESMTP id E2AC77F11\n\tfor <dev@dpdk.org>; Tue, 18 Nov 2014 17:21:02 +0100 (CET)",
            "from fmsmga001.fm.intel.com ([10.253.24.23])\n\tby fmsmga103.fm.intel.com with ESMTP; 18 Nov 2014 08:24:35 -0800",
            "from irvmail001.ir.intel.com ([163.33.26.43])\n\tby fmsmga001.fm.intel.com with ESMTP; 18 Nov 2014 08:31:11 -0800",
            "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\tsAIGV4cQ010026; Tue, 18 Nov 2014 16:31:04 GMT",
            "from sivswdev01.ir.intel.com (localhost [127.0.0.1])\n\tby sivswdev01.ir.intel.com with ESMTP id sAIGV4cJ023989;\n\tTue, 18 Nov 2014 16:31:04 GMT",
            "(from mkjastrx@localhost)\n\tby sivswdev01.ir.intel.com with  id sAIGV4A9023985;\n\tTue, 18 Nov 2014 16:31:04 GMT"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.07,410,1413270000\"; d=\"scan'208\";a=\"624316433\"",
        "From": "Michal Jastrzebski <michalx.k.jastrzebski@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Tue, 18 Nov 2014 16:30:58 +0000",
        "Message-Id": "<1416328259-23926-2-git-send-email-michalx.k.jastrzebski@intel.com>",
        "X-Mailer": "git-send-email 1.7.4.1",
        "In-Reply-To": "<1416328259-23926-1-git-send-email-michalx.k.jastrzebski@intel.com>",
        "References": "<1416328259-23926-1-git-send-email-michalx.k.jastrzebski@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v4 1/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": "From: Pawel Wodkowski <pawelx.wodkowski@intel.com>\n\n\nSigned-off-by: Pawel Wodkowski <pawelx.wodkowski@intel.com>\n---\n lib/librte_ether/rte_ether.h                      |    1 +\n lib/librte_pmd_bond/Makefile                      |    2 +\n lib/librte_pmd_bond/rte_eth_bond.h                |    5 +\n lib/librte_pmd_bond/rte_eth_bond_8023ad.c         | 1218 +++++++++++++++++++++\n lib/librte_pmd_bond/rte_eth_bond_8023ad.h         |  214 ++++\n lib/librte_pmd_bond/rte_eth_bond_8023ad_private.h |  308 ++++++\n lib/librte_pmd_bond/rte_eth_bond_api.c            |   91 +-\n lib/librte_pmd_bond/rte_eth_bond_args.c           |    1 +\n lib/librte_pmd_bond/rte_eth_bond_pmd.c            |  262 ++++-\n lib/librte_pmd_bond/rte_eth_bond_private.h        |   31 +-\n 10 files changed, 2085 insertions(+), 48 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\n create mode 100644 lib/librte_pmd_bond/rte_eth_bond_8023ad_private.h",
    "diff": "diff --git a/lib/librte_ether/rte_ether.h b/lib/librte_ether/rte_ether.h\nindex f173509..d1d2675 100644\n--- a/lib/librte_ether/rte_ether.h\n+++ b/lib/librte_ether/rte_ether.h\n@@ -303,6 +303,7 @@ struct vxlan_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 #define ETHER_VXLAN_HLEN (sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr))\n /**< VXLAN tunnel header length. */\ndiff --git a/lib/librte_pmd_bond/Makefile b/lib/librte_pmd_bond/Makefile\nindex d4e10bf..cdff126 100644\n--- a/lib/librte_pmd_bond/Makefile\n+++ b/lib/librte_pmd_bond/Makefile\n@@ -45,6 +45,7 @@ CFLAGS += $(WERROR_FLAGS)\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_args.c\n+SRCS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += rte_eth_bond_8023ad.c\n \n ifeq ($(CONFIG_RTE_MBUF_REFCNT),n)\n $(info WARNING: Link Bonding Broadcast mode is disabled because it needs MBUF_REFCNT.)\n@@ -54,6 +55,7 @@ endif\n # Export include files\n #\n SYMLINK-y-include += rte_eth_bond.h\n+SYMLINK-y-include += rte_eth_bond_8023ad.h\n \n # this lib depends upon:\n DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += lib/librte_mbuf\ndiff --git a/lib/librte_pmd_bond/rte_eth_bond.h b/lib/librte_pmd_bond/rte_eth_bond.h\nindex 2ed4f7c..a9f7eea 100644\n--- a/lib/librte_pmd_bond/rte_eth_bond.h\n+++ b/lib/librte_pmd_bond/rte_eth_bond.h\n@@ -77,6 +77,11 @@ extern \"C\" {\n  * In this mode all transmitted packets will be transmitted on all available\n  * active slaves of the bonded. */\n #endif\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)\n /**< Layer 2 (Ethernet MAC) */\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..14fd698\n--- /dev/null\n+++ b/lib/librte_pmd_bond/rte_eth_bond_8023ad.c\n@@ -0,0 +1,1218 @@\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+#include <stdbool.h>\n+\n+#include <rte_alarm.h>\n+#include <rte_malloc.h>\n+#include <rte_errno.h>\n+#include <rte_cycles.h>\n+\n+#include \"rte_eth_bond_private.h\"\n+\n+#ifdef RTE_LIBRTE_BOND_DEBUG_8023AD\n+#define MODE4_DEBUG(fmt, ...) RTE_LOG(DEBUG, PMD, \"%6u [Port %u: %s] \" fmt, \\\n+\t\t\tbond_dbg_get_time_diff_ms(), slave_id, \\\n+\t\t\t__func__, ##__VA_ARGS__)\n+\n+static uint64_t start_time;\n+\n+static unsigned\n+bond_dbg_get_time_diff_ms(void)\n+{\n+\tuint64_t now;\n+\n+\tnow = rte_rdtsc();\n+\tif (start_time == 0)\n+\t\tstart_time = now;\n+\n+\treturn ((now - start_time) * 1000) / rte_get_tsc_hz();\n+}\n+\n+static void\n+bond_print_lacp(struct lacpdu *l)\n+{\n+\tchar a_address[18];\n+\tchar p_address[18];\n+\tchar a_state[256] = { 0 };\n+\tchar p_state[256] = { 0 };\n+\n+\tstatic const char * const 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+\tuint8_t *addr;\n+\n+\taddr = l->actor.port_params.system.addr_bytes;\n+\tsnprintf(a_address, sizeof(a_address), \"%02X:%02X:%02X:%02X:%02X:%02X\",\n+\t\taddr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);\n+\n+\taddr = l->partner.port_params.system.addr_bytes;\n+\tsnprintf(p_address, sizeof(p_address), \"%02X:%02X:%02X:%02X:%02X:%02X\",\n+\t\taddr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);\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], RTE_DIM(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], RTE_DIM(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\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=%s, 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=%s, 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\ta_address,\\\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\tp_address,\\\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+#else\n+#define BOND_PRINT_LACP(lacpdu) do { } while (0)\n+#define MODE4_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+struct port mode_8023ad_ports[RTE_MAX_ETHPORTS];\n+\n+static void\n+timer_cancel(uint64_t *timer)\n+{\n+\t*timer = 0;\n+}\n+\n+static void\n+timer_set(uint64_t *timer, uint64_t timeout)\n+{\n+\t*timer = rte_rdtsc() + timeout;\n+}\n+\n+/* Forces given timer to be in expired state. */\n+static void\n+timer_force_expired(uint64_t *timer)\n+{\n+\t*timer = rte_rdtsc();\n+}\n+\n+static bool\n+timer_is_stopped(uint64_t *timer)\n+{\n+\treturn *timer == 0;\n+}\n+\n+static bool\n+timer_is_expired(uint64_t *timer)\n+{\n+\treturn *timer < rte_rdtsc();\n+}\n+\n+/* Timer is in running state if it is not stopped nor expired */\n+static bool\n+timer_is_running(uint64_t *timer)\n+{\n+\treturn !timer_is_stopped(timer) && !timer_is_expired(timer);\n+}\n+\n+static void\n+set_warning_flags(struct port *port, uint16_t flags)\n+{\n+\tint retval;\n+\tuint16_t old;\n+\tuint16_t new_flag = 0;\n+\n+\tdo {\n+\t\told = port->warnings_to_show;\n+\t\tnew_flag = old | flags;\n+\t\tretval = rte_atomic16_cmpset(&port->warnings_to_show, old, new_flag);\n+\t} while (unlikely(retval == 0));\n+}\n+\n+static void\n+show_warnings(uint8_t slave_id)\n+{\n+\tstruct port *port = &mode_8023ad_ports[slave_id];\n+\tuint8_t warnings;\n+\n+\tdo {\n+\t\twarnings = port->warnings_to_show;\n+\t} while (rte_atomic16_cmpset(&port->warnings_to_show, warnings, 0) == 0);\n+\n+\tif (!warnings)\n+\t\treturn;\n+\n+\tif (!timer_is_expired(&port->warning_timer))\n+\t\treturn;\n+\n+\n+\ttimer_set(&port->warning_timer, BOND_8023AD_WARNINGS_PERIOD_MS *\n+\t\t\trte_get_tsc_hz() / 1000);\n+\n+\tif (warnings & WRN_RX_QUEUE_FULL) {\n+\t\tRTE_LOG(DEBUG, PMD,\n+\t\t\t\"Slave %u: failed to enqueue LACP packet into RX ring.\\n\"\n+\t\t\t\"Receive and transmit functions must be invoked on bonded\\n\"\n+\t\t\t\"interface at least 10 times per second or LACP will not\\n\"\n+\t\t\t\"work correctly\\n\", slave_id);\n+\t}\n+\n+\tif (warnings & WRN_TX_QUEUE_FULL) {\n+\t\tRTE_LOG(DEBUG, PMD,\n+\t\t\t\"Slave %u: failed to enqueue LACP packet into TX ring.\\n\"\n+\t\t\t\"Receive and transmit functions must be invoked on bonded\\n\"\n+\t\t\t\"interface at least 10 times per second or LACP will not\\n\"\n+\t\t\t\"work correctly\\n\", slave_id);\n+\t}\n+\n+\tif (warnings & WRN_RX_MARKER_TO_FAST)\n+\t\tRTE_LOG(INFO, PMD, \"Slave %u: marker to early - ignoring.\\n\", slave_id);\n+\n+\tif (warnings & WRN_UNKNOWN_SLOW_TYPE) {\n+\t\tRTE_LOG(INFO, PMD,\n+\t\t\t\"Slave %u: ignoring unknown slow protocol frame type\", slave_id);\n+\t}\n+\n+\tif (warnings & WRN_UNKNOWN_MARKER_TYPE)\n+\t\tRTE_LOG(INFO, PMD, \"Slave %u: ignoring unknown marker type\", slave_id);\n+\n+\tif (warnings & WRN_NOT_LACP_CAPABLE)\n+\t\tMODE4_DEBUG(\"Port %u is not LACP capable!\\n\", slave_id);\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 set them to arbitrary default (last known) and\n+\t * mark actor that parner is 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 slave_id,\n+\t\tstruct lacpdu *lacp)\n+{\n+\tstruct port *agg, *port = &mode_8023ad_ports[slave_id];\n+\tuint64_t timeout;\n+\n+\tif (SM_FLAG(port, BEGIN)) {\n+\t\t/* Initialize stuff */\n+\t\tMODE4_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\telse\n+\t\t\tPARTNER_STATE_SET(port, AGGREGATION);\n+\t}\n+\n+\tif (!SM_FLAG(port, LACP_ENABLED)) {\n+\t\t/* Update parameters only if state changed */\n+\t\tif (!timer_is_stopped(&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\tMODE4_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 (!ACTOR_STATE(port, DEFAULTED) &&\n+\t\t\t(ACTOR_STATE(port, AGGREGATION) != PARTNER_STATE(port, AGGREGATION)\n+\t\t\t|| memcmp(&port->partner, &lacp->actor.port_params,\n+\t\t\t\tsizeof(port->partner)) != 0)) {\n+\t\t\tMODE4_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+\n+\t\t/* Partner parameters are not defaulted any more */\n+\t\tACTOR_STATE_CLR(port, DEFAULTED);\n+\n+\t\t/* If LACP partner params match this port actor params */\n+\t\tagg = &mode_8023ad_ports[port->aggregator_port_id];\n+\t\tbool match = port->actor.system_priority ==\n+\t\t\tlacp->partner.port_params.system_priority &&\n+\t\t\tis_same_ether_addr(&agg->actor.system,\n+\t\t\t&lacp->partner.port_params.system) &&\n+\t\t\tport->actor.port_priority ==\n+\t\t\tlacp->partner.port_params.port_priority &&\n+\t\t\tport->actor.port_number ==\n+\t\t\tlacp->partner.port_params.port_number;\n+\n+\t\t/* Update NTT if partners information are outdated (xored and masked\n+\t\t * bits are set)*/\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\tmatch == false) {\n+\t\t\tSM_FLAG_SET(port, NTT);\n+\t\t}\n+\n+\t\t/* If LACP partner params match this port actor params */\n+\t\tif (match == true && ACTOR_STATE(port, AGGREGATION) ==\n+\t\t\t\tPARTNER_STATE(port,\tAGGREGATION))\n+\t\t\tPARTNER_STATE_SET(port, SYNCHRONIZATION);\n+\t\telse if (!PARTNER_STATE(port, AGGREGATION) && ACTOR_STATE(port,\n+\t\t\t\tAGGREGATION))\n+\t\t\tPARTNER_STATE_SET(port, SYNCHRONIZATION);\n+\t\telse\n+\t\t\tPARTNER_STATE_CLR(port, SYNCHRONIZATION);\n+\n+\t\tif (ACTOR_STATE(port, LACP_SHORT_TIMEOUT))\n+\t\t\ttimeout = internals->mode4.short_timeout;\n+\t\telse\n+\t\t\ttimeout = internals->mode4.long_timeout;\n+\n+\t\ttimer_set(&port->current_while_timer, timeout);\n+\t\tACTOR_STATE_CLR(port, EXPIRED);\n+\t\treturn; /* No state change */\n+\t}\n+\n+\t/* If CURRENT state timer is not running (stopped or expired)\n+\t * transit to EXPIRED state from DISABLED or CURRENT */\n+\tif (!timer_is_running(&port->current_while_timer)) {\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, internals->mode4.short_timeout);\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 slave_id)\n+{\n+\tstruct port *port = &mode_8023ad_ports[slave_id];\n+\t/* Calculate if either site is LACP enabled */\n+\tuint64_t timeout;\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_FLAG(port, BEGIN) || !SM_FLAG(port, LACP_ENABLED) || !active) {\n+\t\ttimer_cancel(&port->periodic_timer);\n+\t\ttimer_force_expired(&port->tx_machine_timer);\n+\t\tSM_FLAG_CLR(port, PARTNER_SHORT_TIMEOUT);\n+\n+\t\tMODE4_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 = PARTNER_STATE(port, LACP_SHORT_TIMEOUT);\n+\twas_partner_fast = SM_FLAG(port, 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 (!timer_is_stopped(&port->periodic_timer)) {\n+\t\tif (timer_is_expired(&port->periodic_timer)) {\n+\t\t\tSM_FLAG_SET(port, NTT);\n+\t\t} else 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_FLAG_SET(port, 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 = internals->mode4.fast_periodic_timeout;\n+\t\tSM_FLAG_SET(port, PARTNER_SHORT_TIMEOUT);\n+\t} else {\n+\t\ttimeout = internals->mode4.slow_periodic_timeout;\n+\t\tSM_FLAG_CLR(port, PARTNER_SHORT_TIMEOUT);\n+\t}\n+\n+\ttimer_set(&port->periodic_timer, timeout);\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 void\n+mux_machine(struct bond_dev_private *internals, uint8_t slave_id)\n+{\n+\tstruct port *port = &mode_8023ad_ports[slave_id];\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 */\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\t!timer_is_stopped(&port->wait_while_timer)) {\n+\t\t\tSM_FLAG_SET(port, NTT);\n+\t\t\tMODE4_DEBUG(\"-> DETACHED\\n\");\n+\t\t}\n+\t\ttimer_cancel(&port->wait_while_timer);\n+\t}\n+\n+\tif (timer_is_stopped(&port->wait_while_timer)) {\n+\t\tif (port->selected == SELECTED || port->selected == STANDBY) {\n+\t\t\ttimer_set(&port->wait_while_timer,\n+\t\t\t\tinternals->mode4.aggregate_wait_timeout);\n+\n+\t\t\tMODE4_DEBUG(\"DETACHED -> WAITING\\n\");\n+\t\t}\n+\t\t/* Waiting state entered */\n+\t\treturn;\n+\t}\n+\n+\t/* Transit next state if port is ready */\n+\tif (!timer_is_expired(&port->wait_while_timer))\n+\t\treturn;\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\tMODE4_DEBUG(\"Out of sync -> ATTACHED\\n\");\n+\t}\n+\n+\tif (!ACTOR_STATE(port, SYNCHRONIZATION)) {\n+\t\t/* attach mux to aggregator */\n+\t\tRTE_VERIFY((port->actor_state & (STATE_COLLECTING |\n+\t\t\tSTATE_DISTRIBUTING)) == 0);\n+\n+\t\tACTOR_STATE_SET(port, SYNCHRONIZATION);\n+\t\tSM_FLAG_SET(port, NTT);\n+\t\tMODE4_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\tMODE4_DEBUG(\"ATTACHED -> COLLECTING\\n\");\n+\t\t\tACTOR_STATE_SET(port, COLLECTING);\n+\t\t\tSM_FLAG_SET(port, NTT);\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\tSM_FLAG_SET(port, NTT);\n+\t\t\t\tMODE4_DEBUG(\"COLLECTING -> DISTRIBUTING\\n\");\n+\t\t\t\tRTE_LOG(INFO, PMD,\n+\t\t\t\t\t\"Bond %u: slave id %u distributing started.\\n\",\n+\t\t\t\t\tinternals->port_id, slave_id);\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\tSM_FLAG_SET(port, NTT);\n+\t\t\t\tMODE4_DEBUG(\"DISTRIBUTING -> COLLECTING\\n\");\n+\t\t\t\tRTE_LOG(INFO, PMD,\n+\t\t\t\t\t\"Bond %u: slave id %u distributing stopped.\\n\",\n+\t\t\t\t\tinternals->port_id, slave_id);\n+\t\t\t}\n+\t\t}\n+\t}\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 bond_dev_private *internals, uint8_t slave_id)\n+{\n+\tstruct port *agg, *port = &mode_8023ad_ports[slave_id];\n+\n+\tstruct rte_mbuf *lacp_pkt = NULL;\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 (timer_is_stopped(&port->periodic_timer))\n+\t\tSM_FLAG_CLR(port, NTT);\n+\n+\tif (!SM_FLAG(port, NTT))\n+\t\treturn;\n+\n+\tif (!timer_is_expired(&port->tx_machine_timer))\n+\t\treturn;\n+\n+\tlacp_pkt = rte_pktmbuf_alloc(port->mbuf_pool);\n+\tif (lacp_pkt == NULL) {\n+\t\tRTE_LOG(ERR, PMD, \"Failed to allocate LACP packet from pool\\n\");\n+\t\treturn;\n+\t}\n+\n+\tlacp_pkt->data_len = sizeof(*hdr);\n+\tlacp_pkt->pkt_len = sizeof(*hdr);\n+\n+\thdr = rte_pktmbuf_mtod(lacp_pkt, struct lacpdu_header *);\n+\n+\t/* Source and destination MAC */\n+\tether_addr_copy(&lacp_mac_addr, &hdr->eth_hdr.d_addr);\n+\trte_eth_macaddr_get(slave_id, &hdr->eth_hdr.s_addr);\n+\thdr->eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_SLOW);\n+\n+\tlacpdu = &hdr->lacpdu;\n+\tmemset(lacpdu, 0, sizeof(*lacpdu));\n+\n+\t/* Initialize LACP part */\n+\tlacpdu->subtype = SLOW_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+\t/* FIXME: change agg->actor.system to rte_eth_macaddr_get() to get real\n+\t * address of bonded device */\n+\tagg = &mode_8023ad_ports[port->aggregator_port_id];\n+\tether_addr_copy(&agg->actor.system, &hdr->lacpdu.actor.port_params.system);\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(port->tx_ring, lacp_pkt) == -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(lacp_pkt);\n+\t\tset_warning_flags(port, WRN_TX_QUEUE_FULL);\n+\t\treturn;\n+\t}\n+\n+\tMODE4_DEBUG(\"sending LACP frame\\n\");\n+\tBOND_PRINT_LACP(lacpdu);\n+\n+\ttimer_set(&port->tx_machine_timer, internals->mode4.tx_period_timeout);\n+\tSM_FLAG_CLR(port, NTT);\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 slave_id)\n+{\n+\tstruct port *agg, *port;\n+\tuint8_t slaves_count, new_agg_id, i;\n+\tuint8_t *slaves;\n+\n+\tslaves = internals->active_slaves;\n+\tslaves_count = internals->active_slave_count;\n+\tport = &mode_8023ad_ports[slave_id];\n+\n+\t/* Search for aggregator suitable for this port */\n+\tfor (i = 0; i < slaves_count; ++i) {\n+\t\tagg = &mode_8023ad_ports[slaves[i]];\n+\t\t/* Skip ports that are not aggreagators */\n+\t\tif (agg->aggregator_port_id != slaves[i])\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\tbreak;\n+\t\t}\n+\t}\n+\n+\t/* By default, port uses it self as agregator */\n+\tif (i == slaves_count)\n+\t\tnew_agg_id = slave_id;\n+\telse\n+\t\tnew_agg_id = slaves[i];\n+\n+\tif (new_agg_id != port->aggregator_port_id) {\n+\t\tport->aggregator_port_id = new_agg_id;\n+\n+\t\tMODE4_DEBUG(\"-> SELECTED: ID=%3u\\n\"\n+\t\t\t\"\\t%s aggregator ID=%3u\\n\",\n+\t\t\tport->aggregator_port_id,\n+\t\t\tport->aggregator_port_id == slave_id ?\n+\t\t\t\t\"aggregator not found, using default\" : \"aggregator found\",\n+\t\t\tport->aggregator_port_id);\n+\t}\n+\n+\tport->selected = SELECTED;\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 port *port;\n+\tstruct rte_eth_link link_info;\n+\tstruct ether_addr slave_addr;\n+\n+\tvoid *pkt = NULL;\n+\tuint16_t i, slave_id;\n+\n+\n+\t/* Update link status on each port */\n+\tfor (i = 0; i < internals->active_slave_count; i++) {\n+\t\tuint16_t key;\n+\n+\t\tslave_id = internals->active_slaves[i];\n+\t\trte_eth_link_get(slave_id, &link_info);\n+\t\trte_eth_macaddr_get(slave_id, &slave_addr);\n+\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\tport = &mode_8023ad_ports[slave_id];\n+\n+\t\tkey = rte_cpu_to_be_16(key);\n+\t\tif (key != port->actor.key) {\n+\t\t\tif (!(key & rte_cpu_to_be_16(BOND_LINK_FULL_DUPLEX_KEY)))\n+\t\t\t\tset_warning_flags(port, WRN_NOT_LACP_CAPABLE);\n+\n+\t\t\tport->actor.key = key;\n+\t\t\tSM_FLAG_SET(port, NTT);\n+\t\t}\n+\n+\t\tif (!is_same_ether_addr(&port->actor.system, &slave_addr)) {\n+\t\t\tether_addr_copy(&slave_addr, &port->actor.system);\n+\t\t\tif (port->aggregator_port_id == slave_id)\n+\t\t\t\tSM_FLAG_SET(port, NTT);\n+\t\t}\n+\t}\n+\n+\tfor (i = 0; i < internals->active_slave_count; i++) {\n+\t\tslave_id = internals->active_slaves[i];\n+\t\tport = &mode_8023ad_ports[slave_id];\n+\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}\n+\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+\n+\t\t/* Find LACP packet to this port. Do not check subtype, it is done in\n+\t\t * function that queued packet */\n+\t\tif (rte_ring_dequeue(port->rx_ring, &pkt) == 0) {\n+\t\t\tstruct rte_mbuf *lacp_pkt = pkt;\n+\t\t\tstruct lacpdu_header *lacp;\n+\n+\t\t\tlacp = rte_pktmbuf_mtod(lacp_pkt, struct lacpdu_header *);\n+\t\t\tRTE_VERIFY(lacp->lacpdu.subtype == SLOW_SUBTYPE_LACP);\n+\n+\t\t\t/* This is LACP frame so pass it to rx_machine */\n+\t\t\trx_machine(internals, slave_id, &lacp->lacpdu);\n+\t\t\trte_pktmbuf_free(lacp_pkt);\n+\t\t} else\n+\t\t\trx_machine(internals, slave_id, NULL);\n+\n+\t\tperiodic_machine(internals, slave_id);\n+\t\tmux_machine(internals, slave_id);\n+\t\ttx_machine(internals, slave_id);\n+\t\tselection_logic(internals, slave_id);\n+\n+\t\tSM_FLAG_CLR(port, BEGIN);\n+\t\tshow_warnings(slave_id);\n+\t}\n+\n+\trte_eal_alarm_set(internals->mode4.update_timeout_us,\n+\t\t\tbond_mode_8023ad_periodic_cb, arg);\n+}\n+\n+void\n+bond_mode_8023ad_activate_slave(struct rte_eth_dev *bond_dev, uint8_t slave_id)\n+{\n+\tstruct bond_dev_private *internals = bond_dev->data->dev_private;\n+\n+\tstruct port *port = &mode_8023ad_ports[slave_id];\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+\tchar mem_name[RTE_ETH_NAME_MAX_LEN];\n+\tuint8_t socket_id;\n+\tunsigned element_size;\n+\n+\t/* Given slave mus not be in active list */\n+\tRTE_VERIFY(find_slave_by_id(internals->active_slaves,\n+\tinternals->active_slave_count, slave_id) == internals->active_slave_count);\n+\n+\tmemcpy(&port->actor, &initial, sizeof(struct port_params));\n+\t/* Standard requires that port ID must be grater than 0.\n+\t * Add 1 do get corresponding port_number */\n+\tport->actor.port_number = rte_cpu_to_be_16((uint16_t)slave_id + 1);\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->aggregator_port_id = slave_id;\n+\trte_eth_promiscuous_enable(slave_id);\n+\n+\ttimer_cancel(&port->warning_timer);\n+\n+\tif (port->mbuf_pool != NULL)\n+\t\treturn;\n+\n+\tRTE_VERIFY(port->rx_ring == NULL);\n+\tRTE_VERIFY(port->tx_ring == NULL);\n+\tsocket_id = rte_eth_devices[slave_id].pci_dev->numa_node;\n+\n+\telement_size = sizeof(struct slow_protocol_frame) + sizeof(struct rte_mbuf)\n+\t\t\t\t+ RTE_PKTMBUF_HEADROOM;\n+\n+\t /* How big memory pool should be? If driver will not\n+\t  * free packets quick enough there will be ENOMEM in tx_machine.\n+\t  * For now give 511 pkts * max number of queued TX packets per slave.\n+\t  * Hope it will be enough. */\n+\tsnprintf(mem_name, RTE_DIM(mem_name), \"slave_port%u_pool\", slave_id);\n+\tport->mbuf_pool = rte_mempool_create(mem_name,\n+\t\tBOND_MODE_8023AX_SLAVE_TX_PKTS * 512 - 1,\n+\t\telement_size,\n+\t\tRTE_MEMPOOL_CACHE_MAX_SIZE >= 32 ? 32 : RTE_MEMPOOL_CACHE_MAX_SIZE,\n+\t\tsizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init,\n+\t\tNULL, rte_pktmbuf_init, NULL, socket_id, MEMPOOL_F_NO_SPREAD);\n+\n+\t/* Any memory allocation failure in initalization is critical because\n+\t * resources can't be free, so reinitialization is impossible. */\n+\tif (port->mbuf_pool == NULL) {\n+\t\trte_panic(\"Slave %u: Failed to create memory pool '%s': %s\\n\",\n+\t\t\tslave_id, mem_name, rte_strerror(rte_errno));\n+\t}\n+\n+\tsnprintf(mem_name, RTE_DIM(mem_name), \"slave_%u_rx\", slave_id);\n+\tport->rx_ring = rte_ring_create(mem_name,\n+\t\t\trte_align32pow2(BOND_MODE_8023AX_SLAVE_RX_PKTS), socket_id, 0);\n+\n+\tif (port->rx_ring == NULL) {\n+\t\trte_panic(\"Slave %u: Failed to create rx ring '%s': %s\\n\", slave_id,\n+\t\t\tmem_name, rte_strerror(rte_errno));\n+\t}\n+\n+\t/* TX ring is at least one pkt longer to make room for marker packet. */\n+\tsnprintf(mem_name, RTE_DIM(mem_name), \"slave_%u_tx\", slave_id);\n+\tport->tx_ring = rte_ring_create(mem_name,\n+\t\t\trte_align32pow2(BOND_MODE_8023AX_SLAVE_TX_PKTS + 1), socket_id, 0);\n+\n+\tif (port->tx_ring == NULL) {\n+\t\trte_panic(\"Slave %u: Failed to create tx ring '%s': %s\\n\", slave_id,\n+\t\t\tmem_name, rte_strerror(rte_errno));\n+\t}\n+}\n+\n+int\n+bond_mode_8023ad_deactivate_slave(struct rte_eth_dev *bond_dev,\n+\t\tuint8_t slave_id)\n+{\n+\tstruct bond_dev_private *internals = bond_dev->data->dev_private;\n+\tvoid *pkt = NULL;\n+\tstruct port *port;\n+\tuint8_t i;\n+\n+\t/* Given slave mus be in active list */\n+\tRTE_VERIFY(find_slave_by_id(internals->active_slaves,\n+\tinternals->active_slave_count, slave_id) < internals->active_slave_count);\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. */\n+\tfor (i = 0; i < internals->active_slave_count; i++) {\n+\t\tport = &mode_8023ad_ports[internals->active_slaves[i]];\n+\t\tif (port->aggregator_port_id != slave_id)\n+\t\t\tcontinue;\n+\n+\t\tport->selected = UNSELECTED;\n+\n+\t\t/* Use default aggregator */\n+\t\tport->aggregator_port_id = internals->active_slaves[i];\n+\t}\n+\n+\tport = &mode_8023ad_ports[slave_id];\n+\tport->selected = UNSELECTED;\n+\tport->actor_state &= ~(STATE_SYNCHRONIZATION | STATE_DISTRIBUTING |\n+\t\t\tSTATE_COLLECTING);\n+\n+\twhile (rte_ring_dequeue(port->rx_ring, &pkt) == 0)\n+\t\trte_pktmbuf_free((struct rte_mbuf *)pkt);\n+\n+\twhile (rte_ring_dequeue(port->tx_ring, &pkt) == 0)\n+\t\t\trte_pktmbuf_free((struct rte_mbuf *)pkt);\n+\treturn 0;\n+}\n+\n+void\n+bond_mode_8023ad_mac_address_update(struct rte_eth_dev *bond_dev)\n+{\n+\tstruct bond_dev_private *internals = bond_dev->data->dev_private;\n+\tstruct ether_addr slave_addr;\n+\tstruct port *slave, *agg_slave;\n+\tuint8_t slave_id, i, j;\n+\n+\tbond_mode_8023ad_stop(bond_dev);\n+\n+\tfor (i = 0; i < internals->active_slave_count; i++) {\n+\t\tslave_id = internals->active_slaves[i];\n+\t\tslave = &mode_8023ad_ports[slave_id];\n+\t\trte_eth_macaddr_get(slave_id, &slave_addr);\n+\n+\t\tif (is_same_ether_addr(&slave_addr, &slave->actor.system))\n+\t\t\tcontinue;\n+\n+\t\tether_addr_copy(&slave_addr, &slave->actor.system);\n+\t\t/* Do nothing if this port is not an aggregator. In other case\n+\t\t * Set NTT flag on every port that use this aggregator. */\n+\t\tif (slave->aggregator_port_id != slave_id)\n+\t\t\tcontinue;\n+\n+\t\tfor (j = 0; j < internals->active_slave_count; j++) {\n+\t\t\tagg_slave = &mode_8023ad_ports[internals->active_slaves[j]];\n+\t\t\tif (agg_slave->aggregator_port_id == slave_id)\n+\t\t\t\tSM_FLAG_SET(agg_slave, NTT);\n+\t\t}\n+\t}\n+\n+\tif (bond_dev->data->dev_started)\n+\t\tbond_mode_8023ad_start(bond_dev);\n+}\n+\n+void\n+bond_mode_8023ad_conf_get(struct rte_eth_dev *dev,\n+\t\tstruct rte_eth_bond_8023ad_conf *conf)\n+{\n+\tstruct bond_dev_private *internals = dev->data->dev_private;\n+\tstruct mode8023ad_private *mode4 = &internals->mode4;\n+\tuint64_t ms_ticks = rte_get_tsc_hz() / 1000;\n+\n+\tconf->fast_periodic_ms = mode4->fast_periodic_timeout / ms_ticks;\n+\tconf->slow_periodic_ms = mode4->slow_periodic_timeout / ms_ticks;\n+\tconf->short_timeout_ms = mode4->short_timeout / ms_ticks;\n+\tconf->long_timeout_ms = mode4->long_timeout / ms_ticks;\n+\tconf->aggregate_wait_timeout_ms = mode4->aggregate_wait_timeout / ms_ticks;\n+\tconf->tx_period_ms = mode4->tx_period_timeout / ms_ticks;\n+\tconf->update_timeout_ms = mode4->update_timeout_us / 1000;\n+}\n+\n+void\n+bond_mode_8023ad_setup(struct rte_eth_dev *dev,\n+\t\tstruct rte_eth_bond_8023ad_conf *conf)\n+{\n+\tstruct rte_eth_bond_8023ad_conf def_conf;\n+\tstruct bond_dev_private *internals = dev->data->dev_private;\n+\tstruct mode8023ad_private *mode4 = &internals->mode4;\n+\tuint64_t ms_ticks = rte_get_tsc_hz() / 1000;\n+\n+\tif (conf == NULL) {\n+\t\tconf = &def_conf;\n+\t\tconf->fast_periodic_ms = BOND_8023AD_FAST_PERIODIC_MS;\n+\t\tconf->slow_periodic_ms = BOND_8023AD_SLOW_PERIODIC_MS;\n+\t\tconf->short_timeout_ms = BOND_8023AD_SHORT_TIMEOUT_MS;\n+\t\tconf->long_timeout_ms = BOND_8023AD_LONG_TIMEOUT_MS;\n+\t\tconf->aggregate_wait_timeout_ms = BOND_8023AD_AGGREGATE_WAIT_TIMEOUT_MS;\n+\t\tconf->tx_period_ms = BOND_8023AD_TX_MACHINE_PERIOD_MS;\n+\t\tconf->rx_marker_period_ms = BOND_8023AD_RX_MARKER_PERIOD_MS;\n+\t\tconf->update_timeout_ms = BOND_MODE_8023AX_UPDATE_TIMEOUT_MS;\n+\t}\n+\n+\tmode4->fast_periodic_timeout = conf->fast_periodic_ms * ms_ticks;\n+\tmode4->slow_periodic_timeout = conf->slow_periodic_ms * ms_ticks;\n+\tmode4->short_timeout = conf->short_timeout_ms * ms_ticks;\n+\tmode4->long_timeout = conf->long_timeout_ms * ms_ticks;\n+\tmode4->aggregate_wait_timeout = conf->aggregate_wait_timeout_ms * ms_ticks;\n+\tmode4->tx_period_timeout = conf->tx_period_ms * ms_ticks;\n+\tmode4->rx_marker_timeout = conf->rx_marker_period_ms * ms_ticks;\n+\tmode4->update_timeout_us = conf->update_timeout_ms * 1000;\n+}\n+\n+int\n+bond_mode_8023ad_enable(struct rte_eth_dev *bond_dev)\n+{\n+\tstruct bond_dev_private *internals = bond_dev->data->dev_private;\n+\tuint16_t i;\n+\n+\tfor (i = 0; i < internals->active_slave_count; i++)\n+\t\tbond_mode_8023ad_activate_slave(bond_dev, i);\n+\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\t\t&bond_mode_8023ad_periodic_cb, bond_dev);\n+}\n+\n+void\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+}\n+\n+void\n+bond_mode_8023ad_handle_slow_pkt(struct bond_dev_private *internals,\n+\tuint8_t slave_id, struct rte_mbuf *pkt)\n+{\n+\tstruct mode8023ad_private *mode4 = &internals->mode4;\n+\tstruct port *port = &mode_8023ad_ports[slave_id];\n+\tstruct marker_header *m_hdr;\n+\tuint64_t marker_timer, old_marker_timer;\n+\tint retval;\n+\tuint8_t wrn, subtype;\n+\t/* If packet is a marker, we send response now by reusing given packet\n+\t * and update only source MAC, destination MAC is multicast so don't\n+\t * update it. Other frames will be handled later by state machines */\n+\tsubtype = rte_pktmbuf_mtod(pkt,\n+\t\t\tstruct slow_protocol_frame *)->slow_protocol.subtype;\n+\n+\tif (subtype == SLOW_SUBTYPE_MARKER) {\n+\t\tm_hdr = rte_pktmbuf_mtod(pkt, struct marker_header *);\n+\n+\t\tif (likely(m_hdr->marker.tlv_type_marker != MARKER_TLV_TYPE_INFO)) {\n+\t\t\twrn = WRN_UNKNOWN_MARKER_TYPE;\n+\t\t\tgoto free_out;\n+\t\t}\n+\n+\t\t/* Setup marker timer. Do it in loop in case concurent access. */\n+\t\tdo {\n+\t\t\told_marker_timer = port->rx_marker_timer;\n+\t\t\tif (!timer_is_expired(&old_marker_timer)) {\n+\t\t\t\twrn = WRN_RX_MARKER_TO_FAST;\n+\t\t\t\tgoto free_out;\n+\t\t\t}\n+\n+\t\t\ttimer_set(&marker_timer, mode4->rx_marker_timeout);\n+\t\t\tretval = rte_atomic64_cmpset(&port->rx_marker_timer,\n+\t\t\t\told_marker_timer, marker_timer);\n+\t\t} while (unlikely(retval == 0));\n+\n+\t\tm_hdr->marker.tlv_type_marker = MARKER_TLV_TYPE_RESP;\n+\t\trte_eth_macaddr_get(slave_id, &m_hdr->eth_hdr.s_addr);\n+\n+\t\tif (unlikely(rte_ring_enqueue(port->tx_ring, pkt) == -ENOBUFS)) {\n+\t\t\t/* reset timer */\n+\t\t\tport->rx_marker_timer = 0;\n+\t\t\twrn = WRN_TX_QUEUE_FULL;\n+\t\t\tgoto free_out;\n+\t\t}\n+\t} else if (likely(subtype == SLOW_SUBTYPE_LACP)) {\n+\t\tif (unlikely(rte_ring_enqueue(port->rx_ring, pkt) == -ENOBUFS)) {\n+\t\t\t/* If RX fing full free lacpdu message and drop packet */\n+\t\t\twrn = WRN_RX_QUEUE_FULL;\n+\t\t\tgoto free_out;\n+\t\t}\n+\t} else {\n+\t\twrn = WRN_UNKNOWN_SLOW_TYPE;\n+\t\tgoto free_out;\n+\t}\n+\n+\treturn;\n+\n+free_out:\n+\tset_warning_flags(port, wrn);\n+\trte_pktmbuf_free(pkt);\n+}\n+\n+int\n+rte_eth_bond_8023ad_conf_get(uint8_t port_id,\n+\t\tstruct rte_eth_bond_8023ad_conf *conf)\n+{\n+\tstruct rte_eth_dev *bond_dev;\n+\n+\tif (valid_bonded_port_id(port_id) != 0)\n+\t\treturn -EINVAL;\n+\n+\tif (conf == NULL)\n+\t\treturn -EINVAL;\n+\n+\tbond_dev = &rte_eth_devices[port_id];\n+\tbond_mode_8023ad_conf_get(bond_dev, conf);\n+\treturn 0;\n+}\n+\n+int\n+rte_eth_bond_8023ad_setup(uint8_t port_id,\n+\t\tstruct rte_eth_bond_8023ad_conf *conf)\n+{\n+\tstruct rte_eth_dev *bond_dev;\n+\n+\tif (valid_bonded_port_id(port_id) != 0)\n+\t\treturn -EINVAL;\n+\n+\tif (conf != NULL) {\n+\t\t/* Basic sanity check */\n+\t\tif (conf->slow_periodic_ms == 0 ||\n+\t\t\t\tconf->fast_periodic_ms >= conf->slow_periodic_ms ||\n+\t\t\t\tconf->long_timeout_ms == 0 ||\n+\t\t\t\tconf->short_timeout_ms >= conf->long_timeout_ms ||\n+\t\t\t\tconf->aggregate_wait_timeout_ms == 0 ||\n+\t\t\t\tconf->tx_period_ms == 0 ||\n+\t\t\t\tconf->rx_marker_period_ms == 0 ||\n+\t\t\t\tconf->update_timeout_ms == 0) {\n+\t\t\tRTE_LOG(ERR, PMD, \"given mode 4 configuration is invalid\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n+\tbond_dev = &rte_eth_devices[port_id];\n+\tbond_mode_8023ad_setup(bond_dev, conf);\n+\n+\treturn 0;\n+}\n+\n+int\n+rte_eth_bond_8023ad_slave_info(uint8_t port_id, uint8_t slave_id,\n+\t\tstruct rte_eth_bond_8023ad_slave_info *info)\n+{\n+\tstruct rte_eth_dev *bond_dev;\n+\tstruct bond_dev_private *internals;\n+\tstruct port *port;\n+\n+\tif (info == NULL || valid_bonded_port_id(port_id) != 0 ||\n+\t\t\trte_eth_bond_mode_get(port_id) != BONDING_MODE_8023AD)\n+\t\treturn -EINVAL;\n+\n+\tbond_dev = &rte_eth_devices[port_id];\n+\n+\tinternals = bond_dev->data->dev_private;\n+\tif (find_slave_by_id(internals->active_slaves,\n+\t\t\tinternals->active_slave_count, slave_id) ==\n+\t\t\t\tinternals->active_slave_count)\n+\t\treturn -EINVAL;\n+\n+\tport = &mode_8023ad_ports[slave_id];\n+\tinfo->selected = port->selected;\n+\n+\tinfo->actor_state = port->actor_state;\n+\trte_memcpy(&info->actor, &port->actor, sizeof(port->actor));\n+\n+\tinfo->partner_state = port->partner_state;\n+\trte_memcpy(&info->partner, &port->partner, sizeof(port->partner));\n+\n+\tinfo->agg_port_id = port->aggregator_port_id;\n+\treturn 0;\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..e655036\n--- /dev/null\n+++ b/lib/librte_pmd_bond/rte_eth_bond_8023ad.h\n@@ -0,0 +1,214 @@\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 <rte_ether.h>\n+\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+#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 SLOW_SUBTYPE_LACP                   0x01\n+#define SLOW_SUBTYPE_MARKER                 0x02\n+\n+#define MARKER_TLV_TYPE_INFO                0x01\n+#define MARKER_TLV_TYPE_RESP                0x02\n+\n+enum rte_bond_8023ad_selection {\n+\tUNSELECTED,\n+\tSTANDBY,\n+\tSELECTED\n+};\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+struct rte_eth_bond_8023ad_conf {\n+\tuint32_t fast_periodic_ms;\n+\tuint32_t slow_periodic_ms;\n+\tuint32_t short_timeout_ms;\n+\tuint32_t long_timeout_ms;\n+\tuint32_t aggregate_wait_timeout_ms;\n+\tuint32_t tx_period_ms;\n+\tuint32_t rx_marker_period_ms;\n+\tuint32_t update_timeout_ms;\n+};\n+\n+struct rte_eth_bond_8023ad_slave_info {\n+\tenum rte_bond_8023ad_selection selected;\n+\tuint8_t actor_state;\n+\tstruct port_params actor;\n+\tuint8_t partner_state;\n+\tstruct port_params partner;\n+\tuint8_t agg_port_id;\n+};\n+\n+/**\n+ * @internal\n+ *\n+ * Function returns current configuration of 802.3AX mode.\n+ *\n+ * @param port_id   Bonding device id\n+ * @param conf\t\tPointer to timeout structure.\n+ *\n+ * @return\n+ *   0 - if ok\n+ *   -EINVAL if conf is NULL\n+ */\n+int\n+rte_eth_bond_8023ad_conf_get(uint8_t port_id,\n+\t\tstruct rte_eth_bond_8023ad_conf *conf);\n+\n+/**\n+ * @internal\n+ *\n+ * Function set new configuration of 802.3AX mode.\n+ *\n+ * @param port_id   Bonding device id\n+ * @param conf\t\tConfiguration, if NULL set default configuration.\n+ * @return\n+ *   0 - if ok\n+ *   -EINVAL if configuration is invalid.\n+ */\n+int\n+rte_eth_bond_8023ad_setup(uint8_t port_id,\n+\t\tstruct rte_eth_bond_8023ad_conf *conf);\n+\n+/**\n+ * @internal\n+ *\n+ * Function returns current state of given slave device.\n+ *\n+ * @param slave_id  Port id of valid slave.\n+ * @param conf\t\tbuffer for configuration\n+ * @return\n+ *   0 - if ok\n+ *   -EINVAL if conf is NULL or slave id is invalid (not a slave of given\n+ *   \tbonded device or is not inactive).\n+ */\n+int\n+rte_eth_bond_8023ad_slave_info(uint8_t port_id, uint8_t slave_id,\n+\t\tstruct rte_eth_bond_8023ad_slave_info *conf);\n+\n+#endif /* RTE_ETH_BOND_8023AD_H_ */\ndiff --git a/lib/librte_pmd_bond/rte_eth_bond_8023ad_private.h b/lib/librte_pmd_bond/rte_eth_bond_8023ad_private.h\nnew file mode 100644\nindex 0000000..8adee70\n--- /dev/null\n+++ b/lib/librte_pmd_bond/rte_eth_bond_8023ad_private.h\n@@ -0,0 +1,308 @@\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_PRIVATE_H_\n+#define RTE_ETH_BOND_8023AD_PRIVATE_H_\n+\n+#include <stdint.h>\n+\n+#include <rte_ether.h>\n+#include <rte_byteorder.h>\n+#include <rte_atomic.h>\n+\n+#include \"rte_eth_bond_8023ad.h\"\n+\n+#define BOND_MODE_8023AX_UPDATE_TIMEOUT_MS  100\n+/** Maximum number of packets to one slave queued in TX ring. */\n+#define BOND_MODE_8023AX_SLAVE_RX_PKTS        3\n+/** Maximum number of LACP packets from one slave queued in TX ring. */\n+#define BOND_MODE_8023AX_SLAVE_TX_PKTS        1\n+/**\n+ * Timeouts deffinitions (5.4.4 in 802.1AX documentation).\n+ */\n+#define BOND_8023AD_FAST_PERIODIC_MS                900\n+#define BOND_8023AD_SLOW_PERIODIC_MS              29000\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_MACHINE_PERIOD_MS            500\n+#define BOND_8023AD_RX_MARKER_PERIOD_MS            2000\n+\n+/**\n+ * Interval of showing warning message from state machines. All messages will\n+ * be held (and gathered together) to prevent flooding.\n+ * This is no parto of 802.1AX standard.\n+ */\n+#define BOND_8023AD_WARNINGS_PERIOD_MS             1000\n+\n+\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_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 WRN_RX_MARKER_TO_FAST      0x01\n+#define WRN_UNKNOWN_SLOW_TYPE      0x02\n+#define WRN_UNKNOWN_MARKER_TYPE    0x04\n+#define WRN_NOT_LACP_CAPABLE       0x08\n+#define WRN_RX_QUEUE_FULL       0x10\n+#define WRN_TX_QUEUE_FULL       0x20\n+\n+#define CHECK_FLAGS(_variable, _f) ((_variable) & (_f))\n+#define SET_FLAGS(_variable, _f) ((_variable) |= (_f))\n+#define CLEAR_FLAGS(_variable, _f) ((_variable) &= ~(_f))\n+\n+#define SM_FLAG(_p, _f) (!!CHECK_FLAGS((_p)->sm_flags, SM_FLAGS_ ## _f))\n+#define SM_FLAG_SET(_p, _f) SET_FLAGS((_p)->sm_flags, SM_FLAGS_ ## _f)\n+#define SM_FLAG_CLR(_p, _f) CLEAR_FLAGS((_p)->sm_flags, SM_FLAGS_ ## _f)\n+\n+#define ACTOR_STATE(_p, _f) (!!CHECK_FLAGS((_p)->actor_state, STATE_ ## _f))\n+#define ACTOR_STATE_SET(_p, _f) SET_FLAGS((_p)->actor_state, STATE_ ## _f)\n+#define ACTOR_STATE_CLR(_p, _f) CLEAR_FLAGS((_p)->actor_state, STATE_ ## _f)\n+\n+#define PARTNER_STATE(_p, _f) (!!CHECK_FLAGS((_p)->partner_state, STATE_ ## _f))\n+#define PARTNER_STATE_SET(_p, _f) SET_FLAGS((_p)->partner_state, STATE_ ## _f)\n+#define PARTNER_STATE_CLR(_p, _f) CLEAR_FLAGS((_p)->partner_state, STATE_ ## _f)\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 rte_bond_8023ad_selection selected;\n+\n+\tuint64_t current_while_timer;\n+\tuint64_t periodic_timer;\n+\tuint64_t wait_while_timer;\n+\tuint64_t tx_machine_timer;\n+\tuint64_t tx_marker_timer;\n+\t/* Agregator parameters */\n+\t/** Used aggregator port ID */\n+\tuint16_t aggregator_port_id;\n+\n+\t/** Memory pool used to allocate rings */\n+\tstruct rte_mempool *mbuf_pool;\n+\n+\t/** Ring of LACP packets from RX burst function */\n+\tstruct rte_ring *rx_ring;\n+\n+\t/** Ring of slow protocol packets (LACP and MARKERS) to TX burst function */\n+\tstruct rte_ring *tx_ring;\n+\n+\t/** Timer which is also used as mutex. If is 0 (not running) RX marker\n+\t * packet might be responded. Otherwise shall be dropped. It is zeroed in\n+\t * mode 4 callback function after expire. */\n+\tvolatile uint64_t rx_marker_timer;\n+\n+\tuint64_t warning_timer;\n+\tvolatile uint16_t warnings_to_show;\n+};\n+\n+struct mode8023ad_private {\n+\tuint64_t fast_periodic_timeout;\n+\tuint64_t slow_periodic_timeout;\n+\tuint64_t short_timeout;\n+\tuint64_t long_timeout;\n+\tuint64_t aggregate_wait_timeout;\n+\tuint64_t tx_period_timeout;\n+\tuint64_t rx_marker_timeout;\n+\tuint64_t update_timeout_us;\n+};\n+\n+/**\n+ * @internal\n+ * The pool of *port* structures. The size of the pool\n+ * is configured at compile-time in the <rte_eth_bond_8023ad.c> file.\n+ */\n+extern struct port mode_8023ad_ports[];\n+\n+/* Forward declaration */\n+struct bond_dev_private;\n+\n+/**\n+ * @internal\n+ *\n+ * Get configuration of bonded interface.\n+ *\n+ *\n+ * @param dev Bonded interface\n+ * @param conf returned configuration\n+ */\n+void\n+bond_mode_8023ad_conf_get(struct rte_eth_dev *dev,\n+\t\tstruct rte_eth_bond_8023ad_conf *conf);\n+\n+/**\n+ * @internal\n+ *\n+ * Set mode 4 configuration of bonded interface.\n+ *\n+ * @pre Bonded interface must be stopped.\n+ *\n+ * @param dev Bonded interface\n+ * @param conf new configuration. If NULL set default configuration.\n+ */\n+void\n+bond_mode_8023ad_setup(struct rte_eth_dev *dev,\n+\t\tstruct rte_eth_bond_8023ad_conf *conf);\n+\n+/**\n+ * @internal\n+ *\n+ * Enables 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_enable(struct rte_eth_dev *dev);\n+\n+/**\n+ * @internal\n+ *\n+ * Disables 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+ * @internal\n+ *\n+ * Starts 802.3AX state machines management logic.\n+ * @param dev Bonded interface\n+ * @return\n+ *   0 if machines was started, 1 if machines was already running,\n+ *   negative value otherwise.\n+ */\n+int\n+bond_mode_8023ad_start(struct rte_eth_dev *dev);\n+\n+/**\n+ * @internal\n+ *\n+ * Stops 802.3AX state machines management logic.\n+ * @param dev Bonded interface\n+ * @return\n+ *   0 if this call stopped state machines, -ENOENT if alarm was not set.\n+ */\n+void\n+bond_mode_8023ad_stop(struct rte_eth_dev *dev);\n+\n+/**\n+ * @internal\n+ *\n+ * Passes given slow packet to state machines management logic.\n+ * @param internals Bonded device private data.\n+ * @param slave_id Slave port id.\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_id, struct rte_mbuf *pkt);\n+\n+/**\n+ * @internal\n+ *\n+ * Appends given slave used slave\n+ *\n+ * @param dev       Bonded interface.\n+ * @param port_id   Slave port ID to be added\n+ *\n+ * @return\n+ *  0 on success, negative value otherwise.\n+ */\n+void\n+bond_mode_8023ad_activate_slave(struct rte_eth_dev *dev, uint8_t port_id);\n+\n+/**\n+ * @internal\n+ *\n+ * Denitializes and removes given slave from 802.1AX mode.\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+int\n+bond_mode_8023ad_deactivate_slave(struct rte_eth_dev *dev, uint8_t slave_pos);\n+\n+/**\n+ * Updates state when MAC was changed on bonded device or one of its slaves.\n+ * @param bond_dev Bonded device\n+ */\n+void\n+bond_mode_8023ad_mac_address_update(struct rte_eth_dev *bond_dev);\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 f146bda..c8fb42c 100644\n--- a/lib/librte_pmd_bond/rte_eth_bond_api.c\n+++ b/lib/librte_pmd_bond/rte_eth_bond_api.c\n@@ -31,6 +31,8 @@\n  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n  */\n \n+#include <string.h>\n+\n #include <rte_mbuf.h>\n #include <rte_malloc.h>\n #include <rte_ethdev.h>\n@@ -38,6 +40,7 @@\n \n #include \"rte_eth_bond.h\"\n #include \"rte_eth_bond_private.h\"\n+#include \"rte_eth_bond_8023ad_private.h\"\n \n #define DEFAULT_POLLING_INTERVAL_10_MS (10)\n \n@@ -104,6 +107,49 @@ valid_slave_port_id(uint8_t port_id)\n \treturn 0;\n }\n \n+void\n+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+\n+\tif (internals->mode == BONDING_MODE_8023AD)\n+\t\tbond_mode_8023ad_activate_slave(eth_dev, port_id);\n+\n+\tinternals->active_slaves[internals->active_slave_count] = port_id;\n+\tinternals->active_slave_count++;\n+}\n+\n+void\n+deactivate_slave(struct rte_eth_dev *eth_dev, uint8_t port_id)\n+{\n+\tuint8_t slave_pos;\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_stop(eth_dev);\n+\t\tbond_mode_8023ad_deactivate_slave(eth_dev, port_id);\n+\t}\n+\n+\tslave_pos = find_slave_by_id(internals->active_slaves, active_count,\n+\t\t\tport_id);\n+\n+\t/* If slave was not at the end of the list\n+\t * shift active slaves up active array list */\n+\tif (slave_pos < active_count) {\n+\t\tactive_count--;\n+\t\tmemmove(internals->active_slaves + slave_pos,\n+\t\t\t\tinternals->active_slaves + slave_pos + 1,\n+\t\t\t\t(active_count - slave_pos) *\n+\t\t\t\t\tsizeof(internals->active_slaves[0]));\n+\t}\n+\n+\tinternals->active_slave_count = active_count;\n+\n+\tif (eth_dev->data->dev_started && internals->mode == BONDING_MODE_8023AD)\n+\t\tbond_mode_8023ad_start(eth_dev);\n+}\n+\n uint8_t\n number_of_sockets(void)\n {\n@@ -216,15 +262,10 @@ 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_BOND_LOG(ERR, \"Failed to set bonded device %d mode too %d\",\n-\t\t\t\t eth_dev->data->port_id, mode);\n-\t\tgoto err;\n-\t}\n-\n \trte_spinlock_init(&internals->lock);\n \n \tinternals->port_id = eth_dev->data->port_id;\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@@ -242,6 +283,14 @@ rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id)\n \tmemset(internals->active_slaves, 0, sizeof(internals->active_slaves));\n \tmemset(internals->slaves, 0, sizeof(internals->slaves));\n \n+\t/* Set mode 4 default configuration */\n+\tbond_mode_8023ad_setup(eth_dev, NULL);\n+\tif (bond_ethdev_mode_set(eth_dev, mode)) {\n+\t\tRTE_BOND_LOG(ERR, \"Failed to set bonded device %d mode too %d\",\n+\t\t\t\t eth_dev->data->port_id, mode);\n+\t\tgoto err;\n+\t}\n+\n \treturn eth_dev->data->port_id;\n \n err:\n@@ -349,14 +398,12 @@ __eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id)\n \t\trte_eth_link_get_nowait(slave_port_id, &link_props);\n \n \t\t if (link_props.link_status == 1)\n-\t\t\tinternals->active_slaves[internals->active_slave_count++] =\n-\t\t\t\t\tslave_port_id;\n+\t\t\tactivate_slave(bonded_eth_dev, slave_port_id);\n \t}\n \treturn 0;\n \n }\n \n-\n int\n rte_eth_bond_slave_add(uint8_t bonded_port_id, uint8_t slave_port_id)\n {\n@@ -381,31 +428,26 @@ rte_eth_bond_slave_add(uint8_t bonded_port_id, uint8_t slave_port_id)\n \treturn retval;\n }\n \n-\n static int\n __eth_bond_slave_remove_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id)\n {\n+\tstruct rte_eth_dev *bonded_eth_dev;\n \tstruct bond_dev_private *internals;\n \n-\tint i, slave_idx = -1;\n+\tint i, slave_idx;\n \n \tif (valid_slave_port_id(slave_port_id) != 0)\n \t\treturn -1;\n \n-\tinternals = rte_eth_devices[bonded_port_id].data->dev_private;\n+\tbonded_eth_dev = &rte_eth_devices[bonded_port_id];\n+\tinternals = bonded_eth_dev->data->dev_private;\n \n \t/* first remove from active slave list */\n-\tfor (i = 0; i < internals->active_slave_count; i++) {\n-\t\tif (internals->active_slaves[i] == slave_port_id)\n-\t\t\tslave_idx = i;\n-\n-\t\t/* shift active slaves up active array list */\n-\t\tif (slave_idx >= 0 && i < (internals->active_slave_count - 1))\n-\t\t\tinternals->active_slaves[i] = internals->active_slaves[i+1];\n-\t}\n+\tslave_idx = find_slave_by_id(internals->active_slaves,\n+\t\tinternals->active_slave_count, slave_port_id);\n \n-\tif (slave_idx >= 0)\n-\t\tinternals->active_slave_count--;\n+\tif (slave_idx < internals->active_slave_count)\n+\t\tdeactivate_slave(bonded_eth_dev, slave_port_id);\n \n \tslave_idx = -1;\n \t/* now find in slave list */\n@@ -539,11 +581,12 @@ rte_eth_bond_primary_get(uint8_t bonded_port_id)\n \n \treturn internals->current_primary_port;\n }\n+\n int\n rte_eth_bond_slaves_get(uint8_t bonded_port_id, uint8_t slaves[], uint8_t len)\n {\n \tstruct bond_dev_private *internals;\n-\tint i;\n+\tuint8_t i;\n \n \tif (valid_bonded_port_id(bonded_port_id) != 0)\n \t\treturn -1;\n@@ -675,7 +718,6 @@ rte_eth_bond_xmit_policy_get(uint8_t bonded_port_id)\n \treturn internals->balance_xmit_policy;\n }\n \n-\n int\n rte_eth_bond_link_monitoring_set(uint8_t bonded_port_id, uint32_t internal_ms)\n {\n@@ -731,7 +773,6 @@ rte_eth_bond_link_down_prop_delay_get(uint8_t bonded_port_id)\n \treturn internals->link_down_delay_ms;\n }\n \n-\n int\n rte_eth_bond_link_up_prop_delay_set(uint8_t bonded_port_id, uint32_t delay_ms)\n \ndiff --git a/lib/librte_pmd_bond/rte_eth_bond_args.c b/lib/librte_pmd_bond/rte_eth_bond_args.c\nindex d8ce681..bf7c1bc 100644\n--- a/lib/librte_pmd_bond/rte_eth_bond_args.c\n+++ b/lib/librte_pmd_bond/rte_eth_bond_args.c\n@@ -173,6 +173,7 @@ bond_ethdev_parse_slave_mode_kvarg(const char *key __rte_unused,\n #ifdef RTE_MBUF_REFCNT\n \tcase BONDING_MODE_BROADCAST:\n #endif\n+\tcase BONDING_MODE_8023AD:\n \t\treturn 0;\n \tdefault:\n \t\tRTE_BOND_LOG(ERR, \"Invalid slave mode value (%s) specified\", value);\ndiff --git a/lib/librte_pmd_bond/rte_eth_bond_pmd.c b/lib/librte_pmd_bond/rte_eth_bond_pmd.c\nindex b82a817..702d967 100644\n--- a/lib/librte_pmd_bond/rte_eth_bond_pmd.c\n+++ b/lib/librte_pmd_bond/rte_eth_bond_pmd.c\n@@ -44,6 +44,7 @@\n \n #include \"rte_eth_bond.h\"\n #include \"rte_eth_bond_private.h\"\n+#include \"rte_eth_bond_8023ad_private.h\"\n \n static uint16_t\n bond_ethdev_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)\n@@ -91,6 +92,77 @@ bond_ethdev_rx_burst_active_backup(void *queue, struct rte_mbuf **bufs,\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 ether_addr bond_mac;\n+\n+\tstruct ether_hdr *hdr;\n+\n+\tconst uint16_t ether_type_slow_be = rte_be_to_cpu_16(ETHER_TYPE_SLOW);\n+\tuint16_t num_rx_total = 0;\t/* Total number of received packets */\n+\tuint8_t slaves[RTE_MAX_ETHPORTS];\n+\tuint8_t slave_count;\n+\n+\tuint8_t collecting;  /* current slave collecting status */\n+\tconst uint8_t promisc = internals->promiscuous_en;\n+\tuint8_t i, j, k;\n+\n+\trte_eth_macaddr_get(internals->port_id, &bond_mac);\n+\t/* Copy slave list to protect against slave up/down changes during tx\n+\t * bursting */\n+\tslave_count = internals->active_slave_count;\n+\tmemcpy(slaves, internals->active_slaves,\n+\t\t\tsizeof(internals->active_slaves[0]) * slave_count);\n+\n+\tfor (i = 0; i < slave_count && num_rx_total < nb_pkts; i++) {\n+\t\tj = num_rx_total;\n+\t\tcollecting = ACTOR_STATE(&mode_8023ad_ports[slaves[i]], COLLECTING);\n+\n+\t\t/* Read packets from this slave */\n+\t\tnum_rx_total += rte_eth_rx_burst(slaves[i], bd_rx_q->queue_id,\n+\t\t\t\t&bufs[num_rx_total], nb_pkts - num_rx_total);\n+\n+\t\tfor (k = j; k < 2 && k < num_rx_total; k++)\n+\t\t\trte_prefetch0(rte_pktmbuf_mtod(bufs[k], void *));\n+\n+\t\t/* Handle slow protocol packets. */\n+\t\twhile (j < num_rx_total) {\n+\t\t\tif (j + 3 < num_rx_total)\n+\t\t\t\trte_prefetch0(rte_pktmbuf_mtod(bufs[j + 3], void *));\n+\n+\t\t\thdr = rte_pktmbuf_mtod(bufs[j], struct ether_hdr *);\n+\t\t\t/* Remove packet from array if it is slow packet or slave is not\n+\t\t\t * in collecting state or bondign interface is not in promiscus\n+\t\t\t * mode and packet address does not match. */\n+\t\t\tif (unlikely(hdr->ether_type == ether_type_slow_be ||\n+\t\t\t\t!collecting || (!promisc &&\n+\t\t\t\t\t!is_same_ether_addr(&bond_mac, &hdr->d_addr)))) {\n+\n+\t\t\t\tif (hdr->ether_type == ether_type_slow_be) {\n+\t\t\t\t\tbond_mode_8023ad_handle_slow_pkt(internals, slaves[i],\n+\t\t\t\t\t\tbufs[j]);\n+\t\t\t\t} else\n+\t\t\t\t\trte_pktmbuf_free(bufs[j]);\n+\n+\t\t\t\t/* Packet is managed by mode 4 or dropped, shift the array */\n+\t\t\t\tnum_rx_total--;\n+\t\t\t\tif (j < num_rx_total) {\n+\t\t\t\t\tmemmove(&bufs[j], &bufs[j + 1], sizeof(bufs[0]) *\n+\t\t\t\t\t\t(num_rx_total - j));\n+\t\t\t\t}\n+\t\t\t} else\n+\t\t\t\tj++;\n+\t\t}\n+\t}\n+\n+\treturn num_rx_total;\n+}\n+\n+static uint16_t\n bond_ethdev_tx_burst_round_robin(void *queue, struct rte_mbuf **bufs,\n \t\tuint16_t nb_pkts)\n {\n@@ -143,7 +215,8 @@ bond_ethdev_tx_burst_round_robin(void *queue, struct rte_mbuf **bufs,\n \t\t\t\ttx_fail_total += tx_fail_slave;\n \n \t\t\t\tmemcpy(&bufs[nb_pkts - tx_fail_total],\n-\t\t\t\t\t\t&slave_bufs[i][num_tx_slave], tx_fail_slave * sizeof(bufs[0]));\n+\t\t\t\t\t\t&slave_bufs[i][num_tx_slave],\n+\t\t\t\t\t\ttx_fail_slave * sizeof(bufs[0]));\n \t\t\t}\n \t\t\tnum_tx_total += num_tx_slave;\n \t\t}\n@@ -338,14 +411,107 @@ bond_ethdev_tx_burst_balance(void *queue, struct rte_mbuf **bufs,\n \t\t\t\tint slave_tx_fail_count = slave_nb_pkts[i] - num_tx_slave;\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\t\tslave_bufs[i][num_tx_slave], slave_tx_fail_count);\n+\t\t\t\tmemcpy(&bufs[nb_pkts - tx_fail_total],\n+\t\t\t\t\t\t&slave_bufs[i][num_tx_slave],\n+\t\t\t\t\t\tslave_tx_fail_count * sizeof(bufs[0]));\n \t\t\t}\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_8023ad(void *queue, struct rte_mbuf **bufs,\n+\t\tuint16_t nb_pkts)\n+{\n+\tstruct bond_dev_private *internals;\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_offsets[RTE_MAX_ETHPORTS];\n+\tuint8_t distributing_count;\n+\n+\tuint16_t num_tx_slave, num_tx_total = 0, num_tx_fail_total = 0;\n+\tuint16_t i, j, op_slave_idx;\n+\tconst uint16_t buffs_size = nb_pkts + BOND_MODE_8023AX_SLAVE_TX_PKTS + 1;\n+\n+\t/* Allocate additional packets in case 8023AD mode. */\n+\tstruct rte_mbuf *slave_bufs[RTE_MAX_ETHPORTS][buffs_size];\n+\tvoid *slow_pkts[BOND_MODE_8023AX_SLAVE_TX_PKTS];\n+\n+\t/* Total amount of packets in slave_bufs */\n+\tuint16_t slave_nb_pkts[RTE_MAX_ETHPORTS] = { 0 };\n+\t/* Slow packets placed in each slave */\n+\tuint8_t slave_slow_nb_pkts[RTE_MAX_ETHPORTS] = { 0 };\n+\n+\tbd_tx_q = (struct bond_tx_queue *)queue;\n+\tinternals = bd_tx_q->dev_private;\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_count = 0;\n+\tfor (i = 0; i < num_of_slaves; i++) {\n+\t\tstruct port *port = &mode_8023ad_ports[slaves[i]];\n+\n+\t\tslave_slow_nb_pkts[i] = rte_ring_dequeue_burst(port->tx_ring,\n+\t\t\t\tslow_pkts, BOND_MODE_8023AX_SLAVE_TX_PKTS);\n+\t\tslave_nb_pkts[i] = slave_slow_nb_pkts[i];\n+\n+\t\tfor (j = 0; j < slave_slow_nb_pkts[i]; j++)\n+\t\t\tslave_bufs[i][j] = slow_pkts[j];\n+\n+\t\tif (ACTOR_STATE(port, DISTRIBUTING))\n+\t\t\tdistributing_offsets[distributing_count++] = i;\n+\t}\n+\n+\tif (likely(distributing_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_idx = xmit_slave_hash(bufs[i], distributing_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\n+\t\t\t * slaves that are currently distributing. */\n+\t\t\tuint8_t slave_offset = distributing_offsets[op_slave_idx];\n+\t\t\tslave_bufs[slave_offset][slave_nb_pkts[slave_offset]] = bufs[i];\n+\t\t\tslave_nb_pkts[slave_offset]++;\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\tcontinue;\n+\n+\t\tnum_tx_slave = rte_eth_tx_burst(slaves[i], bd_tx_q->queue_id,\n+\t\t\t\tslave_bufs[i], slave_nb_pkts[i]);\n+\n+\t\t/* If tx burst fails drop slow packets */\n+\t\tfor ( ; num_tx_slave < slave_slow_nb_pkts[i]; num_tx_slave++)\n+\t\t\trte_pktmbuf_free(slave_bufs[i][num_tx_slave]);\n+\n+\t\tnum_tx_total += num_tx_slave - slave_slow_nb_pkts[i];\n+\t\tnum_tx_fail_total += slave_nb_pkts[i] - num_tx_slave;\n+\n+\t\t/* If tx burst fails move packets to end of bufs */\n+\t\tif (unlikely(num_tx_slave < slave_nb_pkts[i])) {\n+\t\t\tuint16_t j = nb_pkts - num_tx_fail_total;\n+\t\t\tfor ( ; num_tx_slave < slave_nb_pkts[i]; j++, num_tx_slave++)\n+\t\t\t\tbufs[j] = slave_bufs[i][num_tx_slave];\n+\t\t}\n+\t}\n \n \treturn num_tx_total;\n }\n@@ -451,6 +617,27 @@ link_properties_valid(struct rte_eth_link *bonded_dev_link,\n }\n \n int\n+mac_address_get(struct rte_eth_dev *eth_dev, struct ether_addr *dst_mac_addr)\n+{\n+\tstruct ether_addr *mac_addr;\n+\n+\tmac_addr = eth_dev->data->mac_addrs;\n+\n+\tif (eth_dev == NULL) {\n+\t\tRTE_LOG(ERR, PMD, \"%s: NULL pointer eth_dev specified\\n\", __func__);\n+\t\treturn -1;\n+\t}\n+\n+\tif (dst_mac_addr == NULL) {\n+\t\tRTE_LOG(ERR, PMD, \"%s: NULL pointer MAC specified\\n\", __func__);\n+\t\treturn -1;\n+\t}\n+\n+\tether_addr_copy(mac_addr, dst_mac_addr);\n+\treturn 0;\n+}\n+\n+int\n mac_address_set(struct rte_eth_dev *eth_dev, struct ether_addr *new_mac_addr)\n {\n \tstruct ether_addr *mac_addr;\n@@ -458,7 +645,7 @@ mac_address_set(struct rte_eth_dev *eth_dev, struct ether_addr *new_mac_addr)\n \tmac_addr = eth_dev->data->mac_addrs;\n \n \tif (eth_dev == NULL) {\n-\t\tRTE_BOND_LOG(ERR,  \"NULL pointer eth_dev specified\");\n+\t\tRTE_BOND_LOG(ERR, \"NULL pointer eth_dev specified\");\n \t\treturn -1;\n \t}\n \n@@ -499,6 +686,9 @@ mac_address_slaves_update(struct rte_eth_dev *bonded_eth_dev)\n \t\t\t}\n \t\t}\n \t\tbreak;\n+\tcase BONDING_MODE_8023AD:\n+\t\tbond_mode_8023ad_mac_address_update(bonded_eth_dev);\n+\t\tbreak;\n \tcase BONDING_MODE_ACTIVE_BACKUP:\n \tdefault:\n \t\tfor (i = 0; i < internals->slave_count; i++) {\n@@ -551,6 +741,13 @@ bond_ethdev_mode_set(struct rte_eth_dev *eth_dev, int mode)\n \t\teth_dev->rx_pkt_burst = bond_ethdev_rx_burst;\n \t\tbreak;\n #endif\n+\tcase BONDING_MODE_8023AD:\n+\t\tif (bond_mode_8023ad_enable(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@@ -762,6 +959,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@@ -769,6 +969,27 @@ static void\n bond_ethdev_stop(struct rte_eth_dev *eth_dev)\n {\n \tstruct bond_dev_private *internals = eth_dev->data->dev_private;\n+\tuint8_t i;\n+\n+\tif (internals->mode == BONDING_MODE_8023AD) {\n+\t\tstruct port *port;\n+\t\tvoid *pkt = NULL;\n+\n+\t\tbond_mode_8023ad_stop(eth_dev);\n+\n+\t\t/* Discard all messages to/from mode 4 state machines */\n+\t\tfor (i = 0; i < internals->slave_count; i++) {\n+\t\t\tport = &mode_8023ad_ports[internals->slaves[i].port_id];\n+\n+\t\t\tRTE_VERIFY(port->rx_ring != NULL);\n+\t\t\twhile (rte_ring_dequeue(port->rx_ring, &pkt) != -ENOENT)\n+\t\t\t\trte_pktmbuf_free(pkt);\n+\n+\t\t\tRTE_VERIFY(port->tx_ring != NULL);\n+\t\t\twhile (rte_ring_dequeue(port->tx_ring, &pkt) != -ENOENT)\n+\t\t\t\trte_pktmbuf_free(pkt);\n+\t\t}\n+\t}\n \n \tinternals->active_slave_count = 0;\n \tinternals->link_status_polling_enabled = 0;\n@@ -834,7 +1055,7 @@ bond_ethdev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,\n \t\t\t\t\t0, dev->pci_dev->numa_node);\n \n \tif (bd_tx_q == NULL)\n-\t\t\treturn -1;\n+\t\treturn -1;\n \n \tbd_tx_q->queue_id = tx_queue_id;\n \tbd_tx_q->dev_private = dev->data->dev_private;\n@@ -865,7 +1086,6 @@ bond_ethdev_tx_queue_release(void *queue)\n \trte_free(queue);\n }\n \n-\n static void\n bond_ethdev_slave_link_status_change_monitor(void *cb_arg)\n {\n@@ -1014,11 +1234,13 @@ bond_ethdev_promiscuous_enable(struct rte_eth_dev *eth_dev)\n \t\tfor (i = 0; i < internals->slave_count; i++)\n \t\t\trte_eth_promiscuous_enable(internals->slaves[i].port_id);\n \t\tbreak;\n+\t/* In mode4 promiscus mode is managed when slave is added/removed */\n+\tcase BONDING_MODE_8023AD:\n+\t\tbreak;\n \t/* Promiscuous mode is propagated only to primary slave */\n \tcase BONDING_MODE_ACTIVE_BACKUP:\n \tdefault:\n \t\trte_eth_promiscuous_enable(internals->current_primary_port);\n-\n \t}\n }\n \n@@ -1040,6 +1262,9 @@ bond_ethdev_promiscuous_disable(struct rte_eth_dev *dev)\n \t\tfor (i = 0; i < internals->slave_count; i++)\n \t\t\trte_eth_promiscuous_disable(internals->slaves[i].port_id);\n \t\tbreak;\n+\t/* In mode4 promiscus mode is set managed when slave is added/removed */\n+\tcase BONDING_MODE_8023AD:\n+\t\tbreak;\n \t/* Promiscuous mode is propagated only to primary slave */\n \tcase BONDING_MODE_ACTIVE_BACKUP:\n \tdefault:\n@@ -1065,7 +1290,8 @@ bond_ethdev_lsc_event_callback(uint8_t port_id, enum rte_eth_event_type type,\n \tstruct bond_dev_private *internals;\n \tstruct rte_eth_link link;\n \n-\tint i, valid_slave = 0, active_pos = -1;\n+\tint i, valid_slave = 0;\n+\tuint8_t active_pos;\n \tuint8_t lsc_flag = 0;\n \n \tif (type != RTE_ETH_EVENT_INTR_LSC || param == NULL)\n@@ -1095,16 +1321,12 @@ bond_ethdev_lsc_event_callback(uint8_t port_id, enum rte_eth_event_type type,\n \t\treturn;\n \n \t/* Search for port in active port list */\n-\tfor (i = 0; i < internals->active_slave_count; i++) {\n-\t\tif (port_id == internals->active_slaves[i]) {\n-\t\t\tactive_pos = i;\n-\t\t\tbreak;\n-\t\t}\n-\t}\n+\tactive_pos = find_slave_by_id(internals->active_slaves,\n+\t\t\tinternals->active_slave_count, port_id);\n \n \trte_eth_link_get_nowait(port_id, &link);\n \tif (link.link_status) {\n-\t\tif (active_pos >= 0)\n+\t\tif (active_pos < internals->active_slave_count)\n \t\t\treturn;\n \n \t\t/* if no active slave ports then set this port to be primary port */\n@@ -1118,21 +1340,19 @@ bond_ethdev_lsc_event_callback(uint8_t port_id, enum rte_eth_event_type type,\n \t\t\tlink_properties_set(bonded_eth_dev,\n \t\t\t\t\t&(slave_eth_dev->data->dev_link));\n \t\t}\n-\t\tinternals->active_slaves[internals->active_slave_count++] = port_id;\n+\n+\t\tactivate_slave(bonded_eth_dev, port_id);\n \n \t\t/* If user has defined the primary port then default to using it */\n \t\tif (internals->user_defined_primary_port &&\n \t\t\t\tinternals->primary_port == port_id)\n \t\t\tbond_ethdev_primary_set(internals, port_id);\n \t} else {\n-\t\tif (active_pos < 0)\n+\t\tif (active_pos == internals->active_slave_count)\n \t\t\treturn;\n \n \t\t/* Remove from active slave list */\n-\t\tfor (i = active_pos; i < (internals->active_slave_count - 1); i++)\n-\t\t\tinternals->active_slaves[i] = internals->active_slaves[i+1];\n-\n-\t\tinternals->active_slave_count--;\n+\t\tdeactivate_slave(bonded_eth_dev, port_id);\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 78f4196..5e1884b 100644\n--- a/lib/librte_pmd_bond/rte_eth_bond_private.h\n+++ b/lib/librte_pmd_bond/rte_eth_bond_private.h\n@@ -42,6 +42,7 @@ extern \"C\" {\n #include <rte_spinlock.h>\n \n #include \"rte_eth_bond.h\"\n+#include \"rte_eth_bond_8023ad_private.h\"\n \n #define PMD_BOND_SLAVE_PORT_KVARG\t\t\t(\"slave\")\n #define PMD_BOND_PRIMARY_SLAVE_KVARG\t\t(\"primary\")\n@@ -60,6 +61,8 @@ extern \"C\" {\n #define RTE_BOND_LOG(lvl, msg, ...) \t\t\\\n \tRTE_LOG(lvl, PMD, \"%s(%d) - \" msg \"\\n\", __func__, __LINE__, ##__VA_ARGS__);\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@@ -89,7 +92,6 @@ struct bond_tx_queue {\n \t/**< Copy of TX configuration structure for queue */\n };\n \n-\n /** Bonded slave devices structure */\n struct bond_ethdev_slave_ports {\n \tuint8_t slaves[RTE_MAX_ETHPORTS];\t/**< Slave port id array */\n@@ -124,7 +126,7 @@ struct bond_dev_private {\n \tuint8_t user_defined_mac;\n \t/**< Flag for whether MAC address is user defined or not */\n \tuint8_t promiscuous_en;\n-\t/**< Enabled/disable promiscuous mode on slave devices */\n+\t/**< Enabled/disable promiscuous mode on bonding device */\n \tuint8_t link_props_set;\n \t/**< flag to denote if the link properties are set */\n \n@@ -144,6 +146,8 @@ struct bond_dev_private {\n \tstruct bond_slave_details slaves[RTE_MAX_ETHPORTS];\n \t/**< Arary of bonded slaves details */\n \n+\tstruct mode8023ad_private mode4;\n+\n \tstruct rte_kvargs *kvlist;\n };\n \n@@ -152,6 +156,20 @@ 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, uint8_t slave_id) {\n+\n+\tuint8_t pos;\n+\tfor (pos = 0; pos < slaves_count; pos++) {\n+\t\tif (slave_id == slaves[pos])\n+\t\t\tbreak;\n+\t}\n+\n+\treturn pos;\n+}\n+\n int\n valid_port_id(uint8_t port_id);\n \n@@ -162,6 +180,12 @@ int\n valid_slave_port_id(uint8_t port_id);\n \n void\n+deactivate_slave(struct rte_eth_dev *eth_dev, uint8_t port_id);\n+\n+void\n+activate_slave(struct rte_eth_dev *eth_dev, uint8_t port_id);\n+\n+void\n link_properties_set(struct rte_eth_dev *bonded_eth_dev,\n \t\tstruct rte_eth_link *slave_dev_link);\n void\n@@ -175,6 +199,9 @@ int\n mac_address_set(struct rte_eth_dev *eth_dev, struct ether_addr *new_mac_addr);\n \n int\n+mac_address_get(struct rte_eth_dev *eth_dev, struct ether_addr *dst_mac_addr);\n+\n+int\n mac_address_slaves_update(struct rte_eth_dev *bonded_eth_dev);\n \n uint8_t\n",
    "prefixes": [
        "dpdk-dev",
        "v4",
        "1/2"
    ]
}