get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 10218,
    "url": "https://patches.dpdk.org/api/patches/10218/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1454043483-24579-7-git-send-email-yuanhan.liu@linux.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": "<1454043483-24579-7-git-send-email-yuanhan.liu@linux.intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1454043483-24579-7-git-send-email-yuanhan.liu@linux.intel.com",
    "date": "2016-01-29T04:58:01",
    "name": "[dpdk-dev,v3,6/8] vhost: handle VHOST_USER_SEND_RARP request",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "ffe12ef55c196e168d104e302768a9fa686f648e",
    "submitter": {
        "id": 307,
        "url": "https://patches.dpdk.org/api/people/307/?format=api",
        "name": "Yuanhan Liu",
        "email": "yuanhan.liu@linux.intel.com"
    },
    "delegate": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1454043483-24579-7-git-send-email-yuanhan.liu@linux.intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/10218/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/10218/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 BE7DAC56E;\n\tFri, 29 Jan 2016 05:57:34 +0100 (CET)",
            "from mga09.intel.com (mga09.intel.com [134.134.136.24])\n\tby dpdk.org (Postfix) with ESMTP id 244E4C568\n\tfor <dev@dpdk.org>; Fri, 29 Jan 2016 05:57:30 +0100 (CET)",
            "from fmsmga001.fm.intel.com ([10.253.24.23])\n\tby orsmga102.jf.intel.com with ESMTP; 28 Jan 2016 20:57:30 -0800",
            "from yliu-dev.sh.intel.com ([10.239.66.49])\n\tby fmsmga001.fm.intel.com with ESMTP; 28 Jan 2016 20:57:30 -0800"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.22,362,1449561600\"; d=\"scan'208\";a=\"891622475\"",
        "From": "Yuanhan Liu <yuanhan.liu@linux.intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Fri, 29 Jan 2016 12:58:01 +0800",
        "Message-Id": "<1454043483-24579-7-git-send-email-yuanhan.liu@linux.intel.com>",
        "X-Mailer": "git-send-email 1.9.0",
        "In-Reply-To": "<1454043483-24579-1-git-send-email-yuanhan.liu@linux.intel.com>",
        "References": "<1450321921-27799-1-git-send-email-yuanhan.liu@linux.intel.com>\n\t<1454043483-24579-1-git-send-email-yuanhan.liu@linux.intel.com>",
        "Cc": "\"Michael S. Tsirkin\" <mst@redhat.com>,\n\tVictor Kaplansky <vkaplans@redhat.com>",
        "Subject": "[dpdk-dev] [PATCH v3 6/8] vhost: handle VHOST_USER_SEND_RARP request",
        "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": "While in former patch we enabled GUEST_ANNOUNCE feature, so that the\nguest OS will broadcast a GARP message after migration to notify the\nswitch about the new location of migrated VM, the thing is that\nGUEST_ANNOUNCE is enabled since kernel v3.5 only. For older kernel,\nVHOST_USER_SEND_RARP request comes to rescue.\n\nThe payload of this new request is the mac address of the migrated VM,\nwith that, we could construct a RARP message, and then broadcast it\nto host interfaces.\n\nThat's how this patch works:\n\n- list all interfaces, with the help of SIOCGIFCONF ioctl command\n\n- construct an RARP message and broadcast it\n\nCc: Thibaut Collet <thibaut.collet@6wind.com>\nSigned-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>\n---\n\n  Note that this patch did take effect in my test:\n\n  - it indeed updated target vswitch's mac learning table. (with\n    the \"ovs fdb/show bridge\" command)\n\n  - the ping request packets after migration were indeeded flowed\n    to the target (but not the source) host's vswitch. (with tcpdump\n    command)\n\n  However, I still saw ping lost. I asked help from Thibaut, the\n  original author of the VHOST_USER_SEND_RARP request, he suggested\n  that it might be an issue of my network topo, or ovs settings, which\n  is likely, regarding to what I observed above.\n\n  Anyway, I'd like to send this out, hopefully someone knows what's\n  wrong there if there any.  In the meantime, I will do more debugs.\n---\n lib/librte_vhost/vhost_user/vhost-net-user.c  |   4 +\n lib/librte_vhost/vhost_user/vhost-net-user.h  |   1 +\n lib/librte_vhost/vhost_user/virtio-net-user.c | 125 ++++++++++++++++++++++++++\n lib/librte_vhost/vhost_user/virtio-net-user.h |   5 +-\n 4 files changed, 134 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/lib/librte_vhost/vhost_user/vhost-net-user.c b/lib/librte_vhost/vhost_user/vhost-net-user.c\nindex 32ad6f6..cb18396 100644\n--- a/lib/librte_vhost/vhost_user/vhost-net-user.c\n+++ b/lib/librte_vhost/vhost_user/vhost-net-user.c\n@@ -100,6 +100,7 @@ static const char *vhost_message_str[VHOST_USER_MAX] = {\n \t[VHOST_USER_SET_PROTOCOL_FEATURES]  = \"VHOST_USER_SET_PROTOCOL_FEATURES\",\n \t[VHOST_USER_GET_QUEUE_NUM]  = \"VHOST_USER_GET_QUEUE_NUM\",\n \t[VHOST_USER_SET_VRING_ENABLE]  = \"VHOST_USER_SET_VRING_ENABLE\",\n+\t[VHOST_USER_SEND_RARP]  = \"VHOST_USER_SEND_RARP\",\n };\n \n /**\n@@ -437,6 +438,9 @@ vserver_message_handler(int connfd, void *dat, int *remove)\n \tcase VHOST_USER_SET_VRING_ENABLE:\n \t\tuser_set_vring_enable(ctx, &msg.payload.state);\n \t\tbreak;\n+\tcase VHOST_USER_SEND_RARP:\n+\t\tuser_send_rarp(&msg);\n+\t\tbreak;\n \n \tdefault:\n \t\tbreak;\ndiff --git a/lib/librte_vhost/vhost_user/vhost-net-user.h b/lib/librte_vhost/vhost_user/vhost-net-user.h\nindex 6d252a3..e3bb413 100644\n--- a/lib/librte_vhost/vhost_user/vhost-net-user.h\n+++ b/lib/librte_vhost/vhost_user/vhost-net-user.h\n@@ -67,6 +67,7 @@ typedef enum VhostUserRequest {\n \tVHOST_USER_SET_PROTOCOL_FEATURES = 16,\n \tVHOST_USER_GET_QUEUE_NUM = 17,\n \tVHOST_USER_SET_VRING_ENABLE = 18,\n+\tVHOST_USER_SEND_RARP = 19,\n \tVHOST_USER_MAX\n } VhostUserRequest;\n \ndiff --git a/lib/librte_vhost/vhost_user/virtio-net-user.c b/lib/librte_vhost/vhost_user/virtio-net-user.c\nindex 0f3b163..cda330d 100644\n--- a/lib/librte_vhost/vhost_user/virtio-net-user.c\n+++ b/lib/librte_vhost/vhost_user/virtio-net-user.c\n@@ -34,11 +34,18 @@\n #include <stdint.h>\n #include <stdio.h>\n #include <stdlib.h>\n+#include <string.h>\n #include <unistd.h>\n #include <sys/mman.h>\n #include <sys/types.h>\n #include <sys/stat.h>\n #include <unistd.h>\n+#include <sys/ioctl.h>\n+#include <sys/socket.h>\n+#include <net/ethernet.h>\n+#include <netinet/in.h>\n+#include <netinet/if_ether.h>\n+#include <linux/if_packet.h>\n \n #include <rte_common.h>\n #include <rte_log.h>\n@@ -413,3 +420,121 @@ user_set_log_base(struct vhost_device_ctx ctx,\n \n \treturn 0;\n }\n+\n+#define RARP_BUF_SIZE\t64\n+\n+static void\n+make_rarp_packet(uint8_t *buf, uint8_t *mac)\n+{\n+\tstruct ether_header *eth_hdr;\n+\tstruct ether_arp *rarp;\n+\n+\t/* Ethernet header. */\n+\teth_hdr = (struct ether_header *)buf;\n+\tmemset(&eth_hdr->ether_dhost, 0xff, ETH_ALEN);\n+\tmemcpy(&eth_hdr->ether_shost, mac,  ETH_ALEN);\n+\teth_hdr->ether_type = htons(ETH_P_RARP);\n+\n+\t/* RARP header. */\n+\trarp = (struct ether_arp *)(eth_hdr + 1);\n+\trarp->ea_hdr.ar_hrd = htons(ARPHRD_ETHER);\n+\trarp->ea_hdr.ar_pro = htons(ETHERTYPE_IP);\n+\trarp->ea_hdr.ar_hln = ETH_ALEN;\n+\trarp->ea_hdr.ar_pln = 4;\n+\trarp->ea_hdr.ar_op  = htons(ARPOP_RREQUEST);\n+\n+\tmemcpy(&rarp->arp_sha, mac, ETH_ALEN);\n+\tmemset(&rarp->arp_spa, 0x00, 4);\n+\tmemcpy(&rarp->arp_tha, mac, 6);\n+\tmemset(&rarp->arp_tpa, 0x00, 4);\n+}\n+\n+\n+static void\n+send_rarp(const char *ifname, uint8_t *rarp)\n+{\n+\tint fd;\n+\tstruct ifreq ifr;\n+\tstruct sockaddr_ll addr;\n+\n+\tfd = socket(AF_PACKET, SOCK_RAW, 0);\n+\tif (fd < 0) {\n+\t\tperror(\"socket failed\");\n+\t\treturn;\n+\t}\n+\n+\tmemset(&ifr, 0, sizeof(struct ifreq));\n+\tstrncpy(ifr.ifr_name, ifname, IFNAMSIZ);\n+\tif (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {\n+\t\tperror(\"failed to get interface index\");\n+\t\tclose(fd);\n+\t\treturn;\n+\t}\n+\n+\taddr.sll_ifindex = ifr.ifr_ifindex;\n+\taddr.sll_halen   = ETH_ALEN;\n+\n+\tif (sendto(fd, rarp, RARP_BUF_SIZE, 0,\n+\t\t   (const struct sockaddr*)&addr, sizeof(addr)) < 0) {\n+\t\tperror(\"send rarp packet failed\");\n+\t}\n+}\n+\n+\n+/*\n+ * Broadcast a RARP message to all interfaces, to update\n+ * switch's mac table\n+ */\n+int\n+user_send_rarp(struct VhostUserMsg *msg)\n+{\n+\tuint8_t *mac = (uint8_t *)&msg->payload.u64;\n+\tuint8_t rarp[RARP_BUF_SIZE];\n+\tstruct ifconf ifc = {0, };\n+\tstruct ifreq *ifr;\n+\tint nr = 16;\n+\tint fd;\n+\tuint32_t i;\n+\n+\tRTE_LOG(DEBUG, VHOST_CONFIG,\n+\t\t\":: mac: %02x:%02x:%02x:%02x:%02x:%02x\\n\",\n+\t\tmac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);\n+\n+\tmake_rarp_packet(rarp, mac);\n+\n+\t/*\n+\t * Get all interfaces\n+\t */\n+\tfd = socket(AF_INET, SOCK_DGRAM, 0);\n+\tif (fd < 0) {\n+\t\tperror(\"failed to create AF_INET socket\");\n+\t\treturn -1;\n+\t}\n+\n+again:\n+\tifc.ifc_len = sizeof(*ifr) * nr;\n+\tifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len);\n+\n+\tif (ioctl(fd, SIOCGIFCONF, &ifc) < 0) {\n+\t\tperror(\"failed at SIOCGIFCONF\");\n+\t\tclose(fd);\n+\t\treturn -1;\n+\t}\n+\n+\tif (ifc.ifc_len == (int)sizeof(struct ifreq) * nr) {\n+\t\t/*\n+\t\t * current ifc_buf is not big enough to hold\n+\t\t * all interfaces; double it and try again.\n+\t\t */\n+\t\tnr *= 2;\n+\t\tgoto again;\n+\t}\n+\n+\tifr = (struct ifreq *)ifc.ifc_buf;\n+\tfor (i = 0; i < ifc.ifc_len / sizeof(struct ifreq); i++)\n+\t\tsend_rarp(ifr[i].ifr_name, rarp);\n+\n+\tclose(fd);\n+\n+\treturn 0;\n+}\ndiff --git a/lib/librte_vhost/vhost_user/virtio-net-user.h b/lib/librte_vhost/vhost_user/virtio-net-user.h\nindex 013cf38..1e9ff9a 100644\n--- a/lib/librte_vhost/vhost_user/virtio-net-user.h\n+++ b/lib/librte_vhost/vhost_user/virtio-net-user.h\n@@ -38,8 +38,10 @@\n #include \"vhost-net-user.h\"\n \n #define VHOST_USER_PROTOCOL_F_MQ\t0\n+#define VHOST_USER_PROTOCOL_F_RARP\t2\n \n-#define VHOST_USER_PROTOCOL_FEATURES\t(1ULL << VHOST_USER_PROTOCOL_F_MQ)\n+#define VHOST_USER_PROTOCOL_FEATURES\t((1ULL << VHOST_USER_PROTOCOL_F_MQ) | \\\n+\t\t\t\t\t (1ULL << VHOST_USER_PROTOCOL_F_RARP))\n \n int user_set_mem_table(struct vhost_device_ctx, struct VhostUserMsg *);\n \n@@ -50,6 +52,7 @@ void user_set_vring_kick(struct vhost_device_ctx, struct VhostUserMsg *);\n void user_set_protocol_features(struct vhost_device_ctx ctx,\n \t\t\t\tuint64_t protocol_features);\n int user_set_log_base(struct vhost_device_ctx ctx, struct VhostUserMsg *);\n+int user_send_rarp(struct VhostUserMsg *);\n \n int user_get_vring_base(struct vhost_device_ctx, struct vhost_vring_state *);\n \n",
    "prefixes": [
        "dpdk-dev",
        "v3",
        "6/8"
    ]
}