Show a patch.

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

{
    "id": 393,
    "url": "https://patches.dpdk.org/api/patches/393/",
    "web_url": "https://patches.dpdk.org/patch/393/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/",
        "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"
    },
    "msgid": "<1410948060-31098-1-git-send-email-danielx.t.mrzyglod@intel.com>",
    "date": "2014-09-17T10:01:00",
    "name": "[dpdk-dev] ADD mode 5(tlb) to link bonding pmd",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "f8bcb80aeae907e14a80c949d33fcd700ca5c159",
    "submitter": {
        "id": 23,
        "url": "https://patches.dpdk.org/api/people/23/",
        "name": "Daniel Mrzyglod",
        "email": "danielx.t.mrzyglod@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/patch/393/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/393/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/393/checks/",
    "tags": {},
    "headers": {
        "Delivered-To": "patchwork@dpdk.org",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "X-Original-To": "patchwork@dpdk.org",
        "Date": "Wed, 17 Sep 2014 11:01:00 +0100",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailer": "git-send-email 1.7.4.1",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "To": "dev@dpdk.org",
        "Errors-To": "dev-bounces@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 82A53B39F;\n\tWed, 17 Sep 2014 11:56:25 +0200 (CEST)",
            "from mga14.intel.com (mga14.intel.com [192.55.52.115])\n\tby dpdk.org (Postfix) with ESMTP id AC4B3B39C\n\tfor <dev@dpdk.org>; Wed, 17 Sep 2014 11:56:22 +0200 (CEST)",
            "from fmsmga003.fm.intel.com ([10.253.24.29])\n\tby fmsmga103.fm.intel.com with ESMTP; 17 Sep 2014 02:53:10 -0700",
            "from irvmail001.ir.intel.com ([163.33.26.43])\n\tby FMSMGA003.fm.intel.com with ESMTP; 17 Sep 2014 02:56:31 -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\ts8HA20h0017195; Wed, 17 Sep 2014 11:02:00 +0100",
            "from sivswdev01.ir.intel.com (localhost [127.0.0.1])\n\tby sivswdev01.ir.intel.com with ESMTP id s8HA20jo031603;\n\tWed, 17 Sep 2014 11:02:00 +0100",
            "(from dtmrzglx@localhost)\n\tby sivswdev01.ir.intel.com with  id s8HA1xvq031598;\n\tWed, 17 Sep 2014 11:01:59 +0100"
        ],
        "From": "Daniel Mrzyglod <danielx.t.mrzyglod@intel.com>",
        "Precedence": "list",
        "X-ExtLoop1": "1",
        "Message-Id": "<1410948060-31098-1-git-send-email-danielx.t.mrzyglod@intel.com>",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "Subject": "[dpdk-dev] [PATCH] ADD mode 5(tlb) to link bonding pmd",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-IronPort-AV": "E=Sophos;i=\"4.97,862,1389772800\"; d=\"scan'208\";a=\"387314746\"",
        "List-Post": "<mailto:dev@dpdk.org>",
        "X-Mailman-Version": "2.1.15"
    },
    "content": "This patch set adds support of mode 5 to link bonding pmd\n\nThis patchset depend on  Declan Doherty patch set:\nhttp://dpdk.org/ml/archives/dev/2014-September/005069.html\n\nSigned-off-by: Daniel Mrzyglod <danielx.t.mrzyglod@intel.com>\n---\n lib/librte_pmd_bond/rte_eth_bond.h         |   23 ++++\n lib/librte_pmd_bond/rte_eth_bond_args.c    |    1 +\n lib/librte_pmd_bond/rte_eth_bond_pmd.c     |  163 +++++++++++++++++++++++++++-\n lib/librte_pmd_bond/rte_eth_bond_private.h |    5 +-\n 4 files changed, 189 insertions(+), 3 deletions(-)",
    "diff": "diff --git a/lib/librte_pmd_bond/rte_eth_bond.h b/lib/librte_pmd_bond/rte_eth_bond.h\nindex bd59780..1bd76ce 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,29 @@ 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_ADAPTIVE_TRANSMIT_LOAD_BALANCING\t(5)\n+/**< Broadcast (Mode 5)\n+ * Adaptive transmit load balancing: channel bonding that\n+ * does not require any special switch support.  The\n+ * outgoing traffic is distributed according to the\n+ * current load (computed relative to the speed) on each\n+ * slave.  Incoming traffic is received by the current\n+ * slave.  If the receiving slave fails, another slave\n+ * takes over the MAC address of the failed receiving\n+ * slave.*/\n+#define BONDING_MODE_ADAPTIVE_LOAD_BALANCING\t\t\t(6)\n+/**\n+ * Adaptive load balancing: includes balance-tlb plus\n+ * receive load balancing (rlb) for IPV4 traffic, and\n+ * does not require any special switch support.  The\n+ * receive load balancing is achieved by ARP negotiation.\n+ * The bonding driver intercepts the ARP Replies sent by\n+ * the local system on their way out and overwrites the\n+ * source hardware address with the unique hardware\n+ * address of one of the slaves in the bond such that\n+ * different peers use different hardware addresses for\n+ * the server. */\n+\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_args.c b/lib/librte_pmd_bond/rte_eth_bond_args.c\nindex 11d9816..bb1cfae 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_ADAPTIVE_TRANSMIT_LOAD_BALANCING:\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 38cc1ae..9c4c174 100644\n--- a/lib/librte_pmd_bond/rte_eth_bond_pmd.c\n+++ b/lib/librte_pmd_bond/rte_eth_bond_pmd.c\n@@ -30,7 +30,7 @@\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 <stdlib.h>\n #include <rte_mbuf.h>\n #include <rte_malloc.h>\n #include <rte_ethdev.h>\n@@ -40,10 +40,14 @@\n #include <rte_devargs.h>\n #include <rte_kvargs.h>\n #include <rte_dev.h>\n+#include <rte_alarm.h>\n+#include <rte_cycles.h>\n \n #include \"rte_eth_bond.h\"\n #include \"rte_eth_bond_private.h\"\n \n+#define REORDER_PERIOD_MS 10\n+\n static uint16_t\n bond_ethdev_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)\n {\n@@ -286,6 +290,141 @@ xmit_slave_hash(const struct rte_mbuf *buf, uint8_t slave_count, uint8_t policy)\n \treturn hash % slave_count;\n }\n \n+struct bwg_slave {\n+\tuint64_t bwg_left_int;\n+\tuint64_t bwg_left_remainder;\n+\tuint8_t slave;\n+};\n+\n+static int\n+bandwidth_cmp(const void *a, const void *b)\n+{\n+\tconst struct bwg_slave *bwg_a = a;\n+\tconst struct bwg_slave *bwg_b = b;\n+\tint64_t diff = (int64_t)bwg_b->bwg_left_int - (int64_t)bwg_a->bwg_left_int;\n+\tint64_t diff2 = (int64_t)bwg_b->bwg_left_remainder -\n+\t\t\t(int64_t)bwg_a->bwg_left_remainder;\n+\tif (diff > 0)\n+\t\treturn 1;\n+\telse if (diff < 0)\n+\t\treturn -1;\n+\telse if (diff2 > 0)\n+\t\treturn 1;\n+\telse if (diff2 < 0)\n+\t\treturn -1;\n+\telse\n+\t\treturn 0;\n+}\n+\n+static void\n+bandwidth_left(int port_id, uint64_t load, uint8_t update_idx, struct bwg_slave *bwg_slave)\n+{\n+\tstruct rte_eth_link link_status;\n+\n+\trte_eth_link_get(port_id, &link_status);\n+\tuint64_t link_bwg = link_status.link_speed * 1000000ULL / 8;\n+\tif (link_bwg == 0)\n+\t\treturn;\n+\tlink_bwg = (link_bwg * (update_idx+1) * REORDER_PERIOD_MS);\n+\tbwg_slave->bwg_left_int = ((link_bwg - 1000*load)) / link_bwg;\n+\tbwg_slave->bwg_left_remainder = ((link_bwg - 1000*load)) % link_bwg;\n+}\n+\n+static void\n+bond_ethdev_update_tlb_slave_cb(void *arg)\n+{\n+\tstruct bond_dev_private *internals = arg;\n+\tstruct rte_eth_stats slave_stats;\n+\tstruct bwg_slave bwg_array[RTE_MAX_ETHPORTS];\n+\tuint8_t slave_count;\n+\tuint64_t tx_bytes;\n+\tuint8_t update_stats = 0;\n+\tint8_t i;\n+\n+\tinternals->slave_update_idx++;\n+\n+\n+\tif (internals->slave_update_idx >= REORDER_PERIOD_MS)\n+\t\tupdate_stats = 1;\n+\n+\tfor (i = 0; i < internals->active_slave_count; i++) {\n+\t\trte_eth_stats_get(internals->active_slaves[i], &slave_stats);\n+\t\ttx_bytes = slave_stats.obytes -\n+\t\t\t\tinternals->presisted_slaves_conf[i].last_obytes;\n+\t\tbandwidth_left(internals->active_slaves[i], tx_bytes,\n+\t\t\t\tinternals->slave_update_idx, &bwg_array[i]);\n+\t\tbwg_array[i].slave = internals->active_slaves[i];\n+\n+\t\tif (update_stats)\n+\t\t\tinternals->presisted_slaves_conf[i].last_obytes += tx_bytes;\n+\t}\n+\n+\tif (update_stats == 1)\n+\t\tinternals->slave_update_idx = 0;\n+\n+\tslave_count = i;\n+\tqsort(bwg_array, slave_count, sizeof(bwg_array[0]), bandwidth_cmp);\n+\tfor (i = 0; i < slave_count; i++)\n+\t\tinternals->active_slaves[i] = bwg_array[i].slave;\n+\n+\trte_eal_alarm_set(REORDER_PERIOD_MS * 1000, bond_ethdev_update_tlb_slave_cb,\n+\t\t\t(struct bond_dev_private *)internals);\n+}\n+\n+static uint16_t\n+bond_ethdev_tx_burst_tlb(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)\n+{\n+\tstruct bond_tx_queue *bd_tx_q = (struct bond_tx_queue *)queue;\n+\tstruct bond_dev_private *internals = bd_tx_q->dev_private;\n+\n+\tstruct rte_eth_dev *primary_port = &rte_eth_devices[internals->primary_port];\n+\tuint16_t num_tx_total = 0;\n+\tuint8_t i, j;\n+\n+\tuint8_t num_of_slaves = internals->active_slave_count;\n+\tuint8_t slaves[RTE_MAX_ETHPORTS];\n+\n+\tstruct ether_hdr *ether_hdr;\n+\tstruct ether_addr primary_slave_addr;\n+\tstruct ether_addr active_slave_addr;\n+\n+\tif (num_of_slaves < 1)\n+\t\treturn num_tx_total;\n+\n+\tmemcpy(slaves, internals->active_slaves,\n+\t\t\t\tsizeof(internals->active_slaves[0]) * num_of_slaves);\n+\n+\n+\tether_addr_copy(primary_port->data->mac_addrs, &primary_slave_addr);\n+\n+\tif (nb_pkts > 3) {\n+\t\tfor (i = 0; i < 3; i++)\n+\t\t\trte_prefetch0(rte_pktmbuf_mtod(bufs[i], void*));\n+\t}\n+\n+\tfor (i = 0; i < num_of_slaves; i++) {\n+\t\tether_addr_copy(&internals->presisted_slaves_conf[slaves[i]].mac_addr,\n+\t\t\t\t&active_slave_addr);\n+\n+\t\tfor (j = num_tx_total; j < nb_pkts; j++) {\n+\t\t\tif (j + 3 < nb_pkts)\n+\t\t\t\trte_prefetch0(rte_pktmbuf_mtod(bufs[j+3], void*));\n+\n+\t\t\tether_hdr = bufs[j]->pkt.data;\n+\t\t\tif (is_same_ether_addr(&ether_hdr->s_addr, &primary_slave_addr))\n+\t\t\t\tether_addr_copy(&active_slave_addr, &ether_hdr->s_addr);\n+\t\t}\n+\n+\t\tnum_tx_total += rte_eth_tx_burst(slaves[i], bd_tx_q->queue_id,\n+\t\t\t\tbufs + num_tx_total, nb_pkts - num_tx_total);\n+\n+\t\tif (num_tx_total == nb_pkts)\n+\t\t\tbreak;\n+\t}\n+\n+\treturn num_tx_total;\n+}\n+\n static uint16_t\n bond_ethdev_tx_burst_balance(void *queue, struct rte_mbuf **bufs,\n \t\tuint16_t nb_pkts)\n@@ -495,6 +634,7 @@ mac_address_slaves_update(struct rte_eth_dev *bonded_eth_dev)\n \t\t}\n \t\tbreak;\n \tcase BONDING_MODE_ACTIVE_BACKUP:\n+\tcase BONDING_MODE_ADAPTIVE_TRANSMIT_LOAD_BALANCING:\n \tdefault:\n \t\tfor (i = 0; i < internals->slave_count; i++) {\n \t\t\tif (internals->slaves[i] == internals->current_primary_port) {\n@@ -547,6 +687,10 @@ 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_ADAPTIVE_TRANSMIT_LOAD_BALANCING:\n+\t\teth_dev->tx_pkt_burst = bond_ethdev_tx_burst_tlb;\n+\t\teth_dev->rx_pkt_burst = bond_ethdev_rx_burst_active_backup;\n+\t\tbreak;\n \tdefault:\n \t\treturn -1;\n \t}\n@@ -742,7 +886,9 @@ bond_ethdev_start(struct rte_eth_dev *eth_dev)\n \n \tif (internals->user_defined_primary_port)\n \t\tbond_ethdev_primary_set(internals, internals->primary_port);\n-\n+\tif (internals->mode == BONDING_MODE_ADAPTIVE_TRANSMIT_LOAD_BALANCING) {\n+\t\tbond_ethdev_update_tlb_slave_cb(internals);\n+\t}\n \treturn 0;\n }\n \n@@ -751,6 +897,10 @@ 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_ADAPTIVE_TRANSMIT_LOAD_BALANCING) {\n+\t\trte_eal_alarm_cancel(bond_ethdev_update_tlb_slave_cb, internals);\n+\t\trte_delay_ms(REORDER_PERIOD_MS + 1);\n+\t}\n \tinternals->active_slave_count = 0;\n \n \teth_dev->data->dev_link.link_status = 0;\n@@ -760,6 +910,13 @@ bond_ethdev_stop(struct rte_eth_dev *eth_dev)\n static void\n bond_ethdev_close(struct rte_eth_dev *dev __rte_unused)\n {\n+\tstruct bond_dev_private *internals = dev->data->dev_private;\n+\n+\tif (internals->mode == BONDING_MODE_ADAPTIVE_TRANSMIT_LOAD_BALANCING) {\n+\t\trte_eal_alarm_cancel(bond_ethdev_update_tlb_slave_cb, internals);\n+\t\trte_delay_ms(REORDER_PERIOD_MS+1);\n+\t}\n+\tinternals->active_slave_count = 0;\n }\n \n static int\n@@ -938,6 +1095,7 @@ bond_ethdev_promiscuous_enable(struct rte_eth_dev *eth_dev)\n \t\tbreak;\n \t/* Promiscuous mode is propagated only to primary slave */\n \tcase BONDING_MODE_ACTIVE_BACKUP:\n+\tcase BONDING_MODE_ADAPTIVE_TRANSMIT_LOAD_BALANCING:\n \tdefault:\n \t\trte_eth_promiscuous_enable(internals->current_primary_port);\n \n@@ -962,6 +1120,7 @@ bond_ethdev_promiscuous_disable(struct rte_eth_dev *dev)\n \t\tbreak;\n \t/* Promiscuous mode is propagated only to primary slave */\n \tcase BONDING_MODE_ACTIVE_BACKUP:\n+\tcase BONDING_MODE_ADAPTIVE_TRANSMIT_LOAD_BALANCING:\n \tdefault:\n \t\trte_eth_promiscuous_disable(internals->current_primary_port);\n \t}\ndiff --git a/lib/librte_pmd_bond/rte_eth_bond_private.h b/lib/librte_pmd_bond/rte_eth_bond_private.h\nindex 60f1e8d..9cc7915 100644\n--- a/lib/librte_pmd_bond/rte_eth_bond_private.h\n+++ b/lib/librte_pmd_bond/rte_eth_bond_private.h\n@@ -88,6 +88,7 @@ struct slave_conf {\n \t/**< Port Id of slave eth_dev */\n \tstruct ether_addr mac_addr;\n \t/**< Slave eth_dev original MAC address */\n+\tuint64_t last_obytes;\n };\n /** Bonded slave devices structure */\n struct bond_ethdev_slave_ports {\n@@ -120,9 +121,11 @@ struct bond_dev_private {\n \n \tuint8_t active_slaves[RTE_MAX_ETHPORTS];\t/**< Active slave list */\n \tuint8_t slaves[RTE_MAX_ETHPORTS];\t\t\t/**< Slave list */\n-\n+\tuint8_t slaves_order[RTE_MAX_ETHPORTS];\n+\tuint8_t slave_update_idx;\n \t/** Persisted configuration of slaves */\n \tstruct slave_conf presisted_slaves_conf[RTE_MAX_ETHPORTS];\n+\n };\n \n extern struct eth_dev_ops default_dev_ops;\n",
    "prefixes": [
        "dpdk-dev"
    ]
}