get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 17230,
    "url": "http://patches.dpdk.org/api/patches/17230/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1479977798-13417-6-git-send-email-olivier.matz@6wind.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1479977798-13417-6-git-send-email-olivier.matz@6wind.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1479977798-13417-6-git-send-email-olivier.matz@6wind.com",
    "date": "2016-11-24T08:56:38",
    "name": "[dpdk-dev,5/5] net/virtio: fix Tso when mbuf is shared",
    "commit_ref": null,
    "pull_url": null,
    "state": "rejected",
    "archived": true,
    "hash": "11c69e1405ef346dc4662b93f8a52f2b89a01f30",
    "submitter": {
        "id": 8,
        "url": "http://patches.dpdk.org/api/people/8/?format=api",
        "name": "Olivier Matz",
        "email": "olivier.matz@6wind.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1479977798-13417-6-git-send-email-olivier.matz@6wind.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/17230/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/17230/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 2FF4B56A2;\n\tThu, 24 Nov 2016 09:58:04 +0100 (CET)",
            "from proxy.6wind.com (host.76.145.23.62.rev.coltfrance.com\n\t[62.23.145.76]) by dpdk.org (Postfix) with ESMTP id 9146C4CE6\n\tfor <dev@dpdk.org>; Thu, 24 Nov 2016 09:57:03 +0100 (CET)",
            "from glumotte.dev.6wind.com (unknown [10.16.0.195])\n\tby proxy.6wind.com (Postfix) with ESMTP id C4F7B26D30;\n\tThu, 24 Nov 2016 09:56:52 +0100 (CET)"
        ],
        "From": "Olivier Matz <olivier.matz@6wind.com>",
        "To": "dev@dpdk.org,\n\tyuanhan.liu@linux.intel.com",
        "Cc": "maxime.coquelin@redhat.com, huawei.xie@intel.com,\n\tstephen@networkplumber.org",
        "Date": "Thu, 24 Nov 2016 09:56:38 +0100",
        "Message-Id": "<1479977798-13417-6-git-send-email-olivier.matz@6wind.com>",
        "X-Mailer": "git-send-email 2.8.1",
        "In-Reply-To": "<1479977798-13417-1-git-send-email-olivier.matz@6wind.com>",
        "References": "<1479977798-13417-1-git-send-email-olivier.matz@6wind.com>",
        "Subject": "[dpdk-dev] [PATCH 5/5] net/virtio: fix Tso when mbuf is shared",
        "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": "With virtio, doing tso requires to modify the network\npacket data:\n- the dpdk API requires to set the l4 checksum to an\n  Intel-Nic-like pseudo header checksum that does\n  not include the ip length\n- the virtio peer expects that the l4 checksum is\n  a standard pseudo header checksum.\n\nThis is a problem with shared packets, because they\nshould not be modified.\n\nThis patch fixes this issue by copying the headers into\na linear buffer in that case. This buffer is located in\nthe virtio_tx_region, at the same place where the\nvirtio header is stored.\n\nThe size of this buffer is set to 256, which should\nbe enough in all cases:\n  sizeof(ethernet) + sizeof(vlan) * 2 + sizeof(ip6)\n    sizeof(ip6-ext) + sizeof(tcp) + sizeof(tcp-opts)\n  = 14 + 8 + 40 + sizeof(ip6-ext) + 40 + sizeof(tcp-opts)\n  = 102 + sizeof(ip6-ext) + sizeof(tcp-opts)\n\nFixes: 696573046e9e (\"net/virtio: support TSO\")\n\nSigned-off-by: Olivier Matz <olivier.matz@6wind.com>\n---\n drivers/net/virtio/virtio_rxtx.c | 119 +++++++++++++++++++++++++++------------\n drivers/net/virtio/virtqueue.h   |   2 +\n 2 files changed, 85 insertions(+), 36 deletions(-)",
    "diff": "diff --git a/drivers/net/virtio/virtio_rxtx.c b/drivers/net/virtio/virtio_rxtx.c\nindex 22d97a4..577c775 100644\n--- a/drivers/net/virtio/virtio_rxtx.c\n+++ b/drivers/net/virtio/virtio_rxtx.c\n@@ -211,43 +211,73 @@ virtqueue_enqueue_recv_refill(struct virtqueue *vq, struct rte_mbuf *cookie)\n \n /* When doing TSO, the IP length is not included in the pseudo header\n  * checksum of the packet given to the PMD, but for virtio it is\n- * expected.\n+ * expected. Fix the mbuf or a copy if the mbuf is shared.\n  */\n-static void\n-virtio_tso_fix_cksum(struct rte_mbuf *m)\n+static unsigned int\n+virtio_tso_fix_cksum(struct rte_mbuf *m, char *hdr, size_t hdr_sz)\n {\n-\t/* common case: header is not fragmented */\n-\tif (likely(rte_pktmbuf_data_len(m) >= m->l2_len + m->l3_len +\n-\t\t\tm->l4_len)) {\n-\t\tstruct ipv4_hdr *iph;\n-\t\tstruct ipv6_hdr *ip6h;\n-\t\tstruct tcp_hdr *th;\n-\t\tuint16_t prev_cksum, new_cksum, ip_len, ip_paylen;\n-\t\tuint32_t tmp;\n-\n-\t\tiph = rte_pktmbuf_mtod_offset(m, struct ipv4_hdr *, m->l2_len);\n-\t\tth = RTE_PTR_ADD(iph, m->l3_len);\n-\t\tif ((iph->version_ihl >> 4) == 4) {\n-\t\t\tiph->hdr_checksum = 0;\n-\t\t\tiph->hdr_checksum = rte_ipv4_cksum(iph);\n-\t\t\tip_len = iph->total_length;\n-\t\t\tip_paylen = rte_cpu_to_be_16(rte_be_to_cpu_16(ip_len) -\n-\t\t\t\tm->l3_len);\n-\t\t} else {\n-\t\t\tip6h = (struct ipv6_hdr *)iph;\n-\t\t\tip_paylen = ip6h->payload_len;\n+\tstruct ipv4_hdr *iph, iph_copy;\n+\tstruct ipv6_hdr *ip6h = NULL, ip6h_copy;\n+\tstruct tcp_hdr *th, th_copy;\n+\tsize_t hdrlen = m->l2_len + m->l3_len + m->l4_len;\n+\tuint16_t prev_cksum, new_cksum, ip_len, ip_paylen;\n+\tuint32_t tmp;\n+\tint shared = 0;\n+\n+\t/* mbuf is write-only, we need to copy the headers in a linear buffer */\n+\tif (unlikely(rte_pktmbuf_data_is_shared(m, 0, hdrlen))) {\n+\t\tshared = 1;\n+\n+\t\t/* network headers are too big, there's nothing we can do */\n+\t\tif (hdrlen > hdr_sz)\n+\t\t\treturn 0;\n+\n+\t\trte_pktmbuf_read_copy(m, 0, hdrlen, hdr);\n+\t\tiph = (struct ipv4_hdr *)(hdr + m->l2_len);\n+\t\tip6h = (struct ipv6_hdr *)(hdr + m->l2_len);\n+\t\tth = (struct tcp_hdr *)(hdr + m->l2_len + m->l3_len);\n+\t} else {\n+\t\tiph = rte_pktmbuf_read(m, m->l2_len, sizeof(*iph), &iph_copy);\n+\t\tth = rte_pktmbuf_read(m, m->l2_len + m->l3_len, sizeof(*th),\n+\t\t\t&th_copy);\n+\t}\n+\n+\tif ((iph->version_ihl >> 4) == 4) {\n+\t\tiph->hdr_checksum = 0;\n+\t\tiph->hdr_checksum = rte_ipv4_cksum(iph);\n+\t\tip_len = iph->total_length;\n+\t\tip_paylen = rte_cpu_to_be_16(rte_be_to_cpu_16(ip_len) -\n+\t\t\tm->l3_len);\n+\t} else {\n+\t\tif (!shared) {\n+\t\t\tip6h = rte_pktmbuf_read(m, m->l2_len, sizeof(*ip6h),\n+\t\t\t\t&ip6h_copy);\n \t\t}\n+\t\tip_paylen = ip6h->payload_len;\n+\t}\n \n-\t\t/* calculate the new phdr checksum not including ip_paylen */\n-\t\tprev_cksum = th->cksum;\n-\t\ttmp = prev_cksum;\n-\t\ttmp += ip_paylen;\n-\t\ttmp = (tmp & 0xffff) + (tmp >> 16);\n-\t\tnew_cksum = tmp;\n+\t/* calculate the new phdr checksum not including ip_paylen */\n+\tprev_cksum = th->cksum;\n+\ttmp = prev_cksum;\n+\ttmp += ip_paylen;\n+\ttmp = (tmp & 0xffff) + (tmp >> 16);\n+\tnew_cksum = tmp;\n \n-\t\t/* replace it in the packet */\n-\t\tth->cksum = new_cksum;\n-\t}\n+\t/* replace it in the header */\n+\tth->cksum = new_cksum;\n+\n+\t/* the update was done in the linear buffer, return */\n+\tif (shared)\n+\t\treturn hdrlen;\n+\n+\t/* copy from local buffer into mbuf if required */\n+\tif ((iph->version_ihl >> 4) == 4)\n+\t\trte_pktmbuf_write(m, m->l2_len, sizeof(*iph), iph);\n+\telse\n+\t\trte_pktmbuf_write(m, m->l2_len, sizeof(*ip6h), ip6h);\n+\trte_pktmbuf_write(m, m->l2_len + m->l3_len, sizeof(*th), th);\n+\n+\treturn 0;\n }\n \n static inline int\n@@ -268,7 +298,9 @@ virtqueue_enqueue_xmit(struct virtnet_tx *txvq, struct rte_mbuf *cookie,\n \tstruct vring_desc *start_dp;\n \tuint16_t seg_num = cookie->nb_segs;\n \tuint16_t head_idx, idx;\n+\tuint16_t hdr_idx = 0;\n \tuint16_t head_size = vq->hw->vtnet_hdr_size;\n+\tunsigned int offset = 0;\n \tstruct virtio_net_hdr *hdr;\n \tint offload;\n \n@@ -303,6 +335,8 @@ virtqueue_enqueue_xmit(struct virtnet_tx *txvq, struct rte_mbuf *cookie,\n \n \t\t/* loop below will fill in rest of the indirect elements */\n \t\tstart_dp = txr[idx].tx_indir;\n+\t\thdr_idx = 0;\n+\t\tstart_dp[hdr_idx].len = vq->hw->vtnet_hdr_size;\n \t\tidx = 1;\n \t} else {\n \t\t/* setup first tx ring slot to point to header\n@@ -313,7 +347,7 @@ virtqueue_enqueue_xmit(struct virtnet_tx *txvq, struct rte_mbuf *cookie,\n \t\tstart_dp[idx].len   = vq->hw->vtnet_hdr_size;\n \t\tstart_dp[idx].flags = VRING_DESC_F_NEXT;\n \t\thdr = (struct virtio_net_hdr *)&txr[idx].tx_hdr;\n-\n+\t\thdr_idx = idx;\n \t\tidx = start_dp[idx].next;\n \t}\n \n@@ -345,7 +379,14 @@ virtqueue_enqueue_xmit(struct virtnet_tx *txvq, struct rte_mbuf *cookie,\n \n \t\t/* TCP Segmentation Offload */\n \t\tif (cookie->ol_flags & PKT_TX_TCP_SEG) {\n-\t\t\tvirtio_tso_fix_cksum(cookie);\n+\t\t\toffset = virtio_tso_fix_cksum(cookie,\n+\t\t\t\tRTE_PTR_ADD(hdr, start_dp[hdr_idx].len),\n+\t\t\t\tVIRTIO_MAX_HDR_SZ);\n+\t\t\tif (offset > 0) {\n+\t\t\t\tRTE_ASSERT(can_push != 0);\n+\t\t\t\tstart_dp[hdr_idx].len += offset;\n+\t\t\t}\n+\n \t\t\thdr->gso_type = (cookie->ol_flags & PKT_TX_IPV6) ?\n \t\t\t\tVIRTIO_NET_HDR_GSO_TCPV6 :\n \t\t\t\tVIRTIO_NET_HDR_GSO_TCPV4;\n@@ -362,10 +403,16 @@ virtqueue_enqueue_xmit(struct virtnet_tx *txvq, struct rte_mbuf *cookie,\n \t}\n \n \tdo {\n-\t\tstart_dp[idx].addr  = VIRTIO_MBUF_DATA_DMA_ADDR(cookie, vq);\n-\t\tstart_dp[idx].len   = cookie->data_len;\n+\t\tif (offset > cookie->data_len) {\n+\t\t\toffset -= cookie->data_len;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tstart_dp[idx].addr  = VIRTIO_MBUF_DATA_DMA_ADDR(cookie, vq) +\n+\t\t\toffset;\n+\t\tstart_dp[idx].len   = cookie->data_len - offset;\n \t\tstart_dp[idx].flags = cookie->next ? VRING_DESC_F_NEXT : 0;\n \t\tidx = start_dp[idx].next;\n+\t\toffset = 0;\n \t} while ((cookie = cookie->next) != NULL);\n \n \tif (use_indirect)\ndiff --git a/drivers/net/virtio/virtqueue.h b/drivers/net/virtio/virtqueue.h\nindex f0bb089..edfe0dd 100644\n--- a/drivers/net/virtio/virtqueue.h\n+++ b/drivers/net/virtio/virtqueue.h\n@@ -254,8 +254,10 @@ struct virtio_net_hdr_mrg_rxbuf {\n \n /* Region reserved to allow for transmit header and indirect ring */\n #define VIRTIO_MAX_TX_INDIRECT 8\n+#define VIRTIO_MAX_HDR_SZ 256\n struct virtio_tx_region {\n \tstruct virtio_net_hdr_mrg_rxbuf tx_hdr;\n+\tchar net_headers[VIRTIO_MAX_HDR_SZ]; /* for offload if mbuf is RO */\n \tstruct vring_desc tx_indir[VIRTIO_MAX_TX_INDIRECT]\n \t\t\t   __attribute__((__aligned__(16)));\n };\n",
    "prefixes": [
        "dpdk-dev",
        "5/5"
    ]
}