diff mbox

[RFC,v2,06/10] virtio-net rsc: IPv4 checksum

Message ID 1454264009-24094-7-git-send-email-wexu@redhat.com
State New
Headers show

Commit Message

Wei Xu Jan. 31, 2016, 6:13 p.m. UTC
From: Wei Xu <wei@wei-thinkpad.nay.redhat.com>

If a field in the IPv4 header is modified, then the checksum
have to be recalculated before sending it out.

Signed-off-by: Wei Xu <wexu@redhat.com>
---
 hw/net/virtio-net.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

Comments

Jason Wang Feb. 1, 2016, 6:31 a.m. UTC | #1
On 02/01/2016 02:13 AM, wexu@redhat.com wrote:
> From: Wei Xu <wei@wei-thinkpad.nay.redhat.com>
>
> If a field in the IPv4 header is modified, then the checksum
> have to be recalculated before sending it out.

This in fact breaks bisection. I think you need either squash this into
previous patch or introduce virtio_net_rsc_ipv4_checksum() as a helper
before the patch of ipv4 coalescing.

>
> Signed-off-by: Wei Xu <wexu@redhat.com>
> ---
>  hw/net/virtio-net.c | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
>
> diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
> index 93df0d5..88fc4f8 100644
> --- a/hw/net/virtio-net.c
> +++ b/hw/net/virtio-net.c
> @@ -1630,6 +1630,18 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
>      return 0;
>  }
>  
> +static void virtio_net_rsc_ipv4_checksum(NetRscSeg *seg)
> +{
> +    uint32_t sum;
> +    struct ip_header *ip;
> +
> +    ip = (struct ip_header *)(seg->buf + IP_OFFSET);
> +
> +    ip->ip_sum = 0;
> +    sum = net_checksum_add_cont(sizeof(struct ip_header), (uint8_t *)ip, 0);
> +    ip->ip_sum = cpu_to_be16(net_checksum_finish(sum));
> +}
> +
>  static void virtio_net_rsc_purge(void *opq)
>  {
>      int ret = 0;
> @@ -1643,6 +1655,10 @@ static void virtio_net_rsc_purge(void *opq)
>              continue;
>          }
>  
> +        if ((chain->proto == ETH_P_IP) && seg->is_coalesced) {
> +            virtio_net_rsc_ipv4_checksum(seg);
> +        }
> +
>          ret = virtio_net_do_receive(seg->nc, seg->buf, seg->size);
>          QTAILQ_REMOVE(&chain->buffers, seg, next);
>          g_free(seg->buf);
> @@ -1853,6 +1869,9 @@ static size_t virtio_net_rsc_callback(NetRscChain *chain, NetClientState *nc,
>      QTAILQ_FOREACH_SAFE(seg, &chain->buffers, next, nseg) {
>          ret = coalesce(chain, seg, buf, size);
>          if (RSC_FINAL == ret) {
> +            if ((chain->proto == ETH_P_IP) && seg->is_coalesced) {
> +                virtio_net_rsc_ipv4_checksum(seg);
> +            }
>              ret = virtio_net_do_receive(seg->nc, seg->buf, seg->size);
>              QTAILQ_REMOVE(&chain->buffers, seg, next);
>              g_free(seg->buf);
Wei Xu Feb. 1, 2016, 8:40 a.m. UTC | #2
On 02/01/2016 02:31 PM, Jason Wang wrote:
>
> On 02/01/2016 02:13 AM, wexu@redhat.com wrote:
>> From: Wei Xu <wei@wei-thinkpad.nay.redhat.com>
>>
>> If a field in the IPv4 header is modified, then the checksum
>> have to be recalculated before sending it out.
> This in fact breaks bisection. I think you need either squash this into
> previous patch or introduce virtio_net_rsc_ipv4_checksum() as a helper
> before the patch of ipv4 coalescing.
OK.
>> Signed-off-by: Wei Xu <wexu@redhat.com>
>> ---
>>   hw/net/virtio-net.c | 19 +++++++++++++++++++
>>   1 file changed, 19 insertions(+)
>>
>> diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
>> index 93df0d5..88fc4f8 100644
>> --- a/hw/net/virtio-net.c
>> +++ b/hw/net/virtio-net.c
>> @@ -1630,6 +1630,18 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
>>       return 0;
>>   }
>>   
>> +static void virtio_net_rsc_ipv4_checksum(NetRscSeg *seg)
>> +{
>> +    uint32_t sum;
>> +    struct ip_header *ip;
>> +
>> +    ip = (struct ip_header *)(seg->buf + IP_OFFSET);
>> +
>> +    ip->ip_sum = 0;
>> +    sum = net_checksum_add_cont(sizeof(struct ip_header), (uint8_t *)ip, 0);
>> +    ip->ip_sum = cpu_to_be16(net_checksum_finish(sum));
>> +}
>> +
>>   static void virtio_net_rsc_purge(void *opq)
>>   {
>>       int ret = 0;
>> @@ -1643,6 +1655,10 @@ static void virtio_net_rsc_purge(void *opq)
>>               continue;
>>           }
>>   
>> +        if ((chain->proto == ETH_P_IP) && seg->is_coalesced) {
>> +            virtio_net_rsc_ipv4_checksum(seg);
>> +        }
>> +
>>           ret = virtio_net_do_receive(seg->nc, seg->buf, seg->size);
>>           QTAILQ_REMOVE(&chain->buffers, seg, next);
>>           g_free(seg->buf);
>> @@ -1853,6 +1869,9 @@ static size_t virtio_net_rsc_callback(NetRscChain *chain, NetClientState *nc,
>>       QTAILQ_FOREACH_SAFE(seg, &chain->buffers, next, nseg) {
>>           ret = coalesce(chain, seg, buf, size);
>>           if (RSC_FINAL == ret) {
>> +            if ((chain->proto == ETH_P_IP) && seg->is_coalesced) {
>> +                virtio_net_rsc_ipv4_checksum(seg);
>> +            }
>>               ret = virtio_net_do_receive(seg->nc, seg->buf, seg->size);
>>               QTAILQ_REMOVE(&chain->buffers, seg, next);
>>               g_free(seg->buf);
>
diff mbox

Patch

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 93df0d5..88fc4f8 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1630,6 +1630,18 @@  static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
     return 0;
 }
 
+static void virtio_net_rsc_ipv4_checksum(NetRscSeg *seg)
+{
+    uint32_t sum;
+    struct ip_header *ip;
+
+    ip = (struct ip_header *)(seg->buf + IP_OFFSET);
+
+    ip->ip_sum = 0;
+    sum = net_checksum_add_cont(sizeof(struct ip_header), (uint8_t *)ip, 0);
+    ip->ip_sum = cpu_to_be16(net_checksum_finish(sum));
+}
+
 static void virtio_net_rsc_purge(void *opq)
 {
     int ret = 0;
@@ -1643,6 +1655,10 @@  static void virtio_net_rsc_purge(void *opq)
             continue;
         }
 
+        if ((chain->proto == ETH_P_IP) && seg->is_coalesced) {
+            virtio_net_rsc_ipv4_checksum(seg);
+        }
+
         ret = virtio_net_do_receive(seg->nc, seg->buf, seg->size);
         QTAILQ_REMOVE(&chain->buffers, seg, next);
         g_free(seg->buf);
@@ -1853,6 +1869,9 @@  static size_t virtio_net_rsc_callback(NetRscChain *chain, NetClientState *nc,
     QTAILQ_FOREACH_SAFE(seg, &chain->buffers, next, nseg) {
         ret = coalesce(chain, seg, buf, size);
         if (RSC_FINAL == ret) {
+            if ((chain->proto == ETH_P_IP) && seg->is_coalesced) {
+                virtio_net_rsc_ipv4_checksum(seg);
+            }
             ret = virtio_net_do_receive(seg->nc, seg->buf, seg->size);
             QTAILQ_REMOVE(&chain->buffers, seg, next);
             g_free(seg->buf);