Commit 48c643630c5e994e4885dceb45a5da1c403a678a

Authored by aliguori
1 parent dd5e6304

Add IP checksumming functions to qemu (Gerd Hoffmann)

This can be shared between the e1000, virtio-net, and xennet.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4971 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
... ... @@ -472,7 +472,7 @@ endif #CONFIG_DARWIN_USER
472 472 # System emulator target
473 473 ifndef CONFIG_USER_ONLY
474 474  
475   -OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o
  475 +OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o net-checksum.o
476 476 ifdef CONFIG_WIN32
477 477 OBJS+=block-raw-win32.o
478 478 else
... ...
net-checksum.c 0 → 100644
  1 +/*
  2 + * IP checksumming functions.
  3 + * (c) 2008 Gerd Hoffmann <kraxel@redhat.com>
  4 + *
  5 + * This program is free software; you can redistribute it and/or modify
  6 + * it under the terms of the GNU General Public License as published by
  7 + * the Free Software Foundation; under version 2 of the License.
  8 + *
  9 + * This program is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 + * GNU General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU General Public License
  15 + * along with this program; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +#include "hw/hw.h"
  20 +#include "net.h"
  21 +
  22 +#define PROTO_TCP 6
  23 +#define PROTO_UDP 17
  24 +
  25 +uint32_t net_checksum_add(int len, uint8_t *buf)
  26 +{
  27 + uint32_t sum = 0;
  28 + int i;
  29 +
  30 + for (i = 0; i < len; i++) {
  31 + if (i & 1)
  32 + sum += (uint32_t)buf[i];
  33 + else
  34 + sum += (uint32_t)buf[i] << 8;
  35 + }
  36 + return sum;
  37 +}
  38 +
  39 +uint16_t net_checksum_finish(uint32_t sum)
  40 +{
  41 + while (sum>>16)
  42 + sum = (sum & 0xFFFF)+(sum >> 16);
  43 + return ~sum;
  44 +}
  45 +
  46 +uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto,
  47 + uint8_t *addrs, uint8_t *buf)
  48 +{
  49 + uint32_t sum = 0;
  50 +
  51 + sum += net_checksum_add(length, buf); // payload
  52 + sum += net_checksum_add(8, addrs); // src + dst address
  53 + sum += proto + length; // protocol & length
  54 + return net_checksum_finish(sum);
  55 +}
  56 +
  57 +void net_checksum_calculate(uint8_t *data, int length)
  58 +{
  59 + int hlen, plen, proto, csum_offset;
  60 + uint16_t csum;
  61 +
  62 + if ((data[14] & 0xf0) != 0x40)
  63 + return; /* not IPv4 */
  64 + hlen = (data[14] & 0x0f) * 4;
  65 + plen = (data[16] << 8 | data[17]) - hlen;
  66 + proto = data[23];
  67 +
  68 + switch (proto) {
  69 + case PROTO_TCP:
  70 + csum_offset = 16;
  71 + break;
  72 + case PROTO_UDP:
  73 + csum_offset = 6;
  74 + break;
  75 + default:
  76 + return;
  77 + }
  78 +
  79 + if (plen < csum_offset+2)
  80 + return;
  81 +
  82 + data[14+hlen+csum_offset] = 0;
  83 + data[14+hlen+csum_offset+1] = 0;
  84 + csum = net_checksum_tcpudp(plen, proto, data+14+12, data+14+hlen);
  85 + data[14+hlen+csum_offset] = csum >> 8;
  86 + data[14+hlen+csum_offset+1] = csum & 0xff;
  87 +}
... ...
... ... @@ -48,4 +48,11 @@ struct NICInfo {
48 48 extern int nb_nics;
49 49 extern NICInfo nd_table[MAX_NICS];
50 50  
  51 +/* checksumming functions (net-checksum.c) */
  52 +uint32_t net_checksum_add(int len, uint8_t *buf);
  53 +uint16_t net_checksum_finish(uint32_t sum);
  54 +uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto,
  55 + uint8_t *addrs, uint8_t *buf);
  56 +void net_checksum_calculate(uint8_t *data, int length);
  57 +
51 58 #endif
... ...