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
This commit is contained in:
		
							parent
							
								
									dd5e6304aa
								
							
						
					
					
						commit
						48c643630c
					
				@ -472,7 +472,7 @@ endif #CONFIG_DARWIN_USER
 | 
				
			|||||||
# System emulator target
 | 
					# System emulator target
 | 
				
			||||||
ifndef CONFIG_USER_ONLY
 | 
					ifndef CONFIG_USER_ONLY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o
 | 
					OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o net-checksum.o
 | 
				
			||||||
ifdef CONFIG_WIN32
 | 
					ifdef CONFIG_WIN32
 | 
				
			||||||
OBJS+=block-raw-win32.o
 | 
					OBJS+=block-raw-win32.o
 | 
				
			||||||
else
 | 
					else
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										87
									
								
								net-checksum.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								net-checksum.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,87 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  IP checksumming functions.
 | 
				
			||||||
 | 
					 *  (c) 2008 Gerd Hoffmann <kraxel@redhat.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 *  it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 *  the Free Software Foundation; under version 2 of the License.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 *  GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 *  along with this program; if not, write to the Free Software
 | 
				
			||||||
 | 
					 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "hw/hw.h"
 | 
				
			||||||
 | 
					#include "net.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PROTO_TCP  6
 | 
				
			||||||
 | 
					#define PROTO_UDP 17
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t net_checksum_add(int len, uint8_t *buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t sum = 0;
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < len; i++) {
 | 
				
			||||||
 | 
						if (i & 1)
 | 
				
			||||||
 | 
						    sum += (uint32_t)buf[i];
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						    sum += (uint32_t)buf[i] << 8;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return sum;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint16_t net_checksum_finish(uint32_t sum)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    while (sum>>16)
 | 
				
			||||||
 | 
						sum = (sum & 0xFFFF)+(sum >> 16);
 | 
				
			||||||
 | 
					    return ~sum;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto,
 | 
				
			||||||
 | 
					                             uint8_t *addrs, uint8_t *buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t sum = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sum += net_checksum_add(length, buf);         // payload
 | 
				
			||||||
 | 
					    sum += net_checksum_add(8, addrs);            // src + dst address
 | 
				
			||||||
 | 
					    sum += proto + length;                        // protocol & length
 | 
				
			||||||
 | 
					    return net_checksum_finish(sum);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void net_checksum_calculate(uint8_t *data, int length)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int hlen, plen, proto, csum_offset;
 | 
				
			||||||
 | 
					    uint16_t csum;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((data[14] & 0xf0) != 0x40)
 | 
				
			||||||
 | 
						return; /* not IPv4 */
 | 
				
			||||||
 | 
					    hlen  = (data[14] & 0x0f) * 4;
 | 
				
			||||||
 | 
					    plen  = (data[16] << 8 | data[17]) - hlen;
 | 
				
			||||||
 | 
					    proto = data[23];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (proto) {
 | 
				
			||||||
 | 
					    case PROTO_TCP:
 | 
				
			||||||
 | 
						csum_offset = 16;
 | 
				
			||||||
 | 
						break;
 | 
				
			||||||
 | 
					    case PROTO_UDP:
 | 
				
			||||||
 | 
						csum_offset = 6;
 | 
				
			||||||
 | 
						break;
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (plen < csum_offset+2)
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    data[14+hlen+csum_offset]   = 0;
 | 
				
			||||||
 | 
					    data[14+hlen+csum_offset+1] = 0;
 | 
				
			||||||
 | 
					    csum = net_checksum_tcpudp(plen, proto, data+14+12, data+14+hlen);
 | 
				
			||||||
 | 
					    data[14+hlen+csum_offset]   = csum >> 8;
 | 
				
			||||||
 | 
					    data[14+hlen+csum_offset+1] = csum & 0xff;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										7
									
								
								net.h
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								net.h
									
									
									
									
									
								
							@ -48,4 +48,11 @@ struct NICInfo {
 | 
				
			|||||||
extern int nb_nics;
 | 
					extern int nb_nics;
 | 
				
			||||||
extern NICInfo nd_table[MAX_NICS];
 | 
					extern NICInfo nd_table[MAX_NICS];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* checksumming functions (net-checksum.c) */
 | 
				
			||||||
 | 
					uint32_t net_checksum_add(int len, uint8_t *buf);
 | 
				
			||||||
 | 
					uint16_t net_checksum_finish(uint32_t sum);
 | 
				
			||||||
 | 
					uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto,
 | 
				
			||||||
 | 
					                             uint8_t *addrs, uint8_t *buf);
 | 
				
			||||||
 | 
					void net_checksum_calculate(uint8_t *data, int length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user