2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2011, Lei Xia <lxia@northwestern.edu>
11 * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Lei Xia <lxia@northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 #ifndef __ETHERNET_H__
21 #define __ETHERNET_H__
23 #include <palacios/vmm.h>
25 #define ETHERNET_HEADER_LEN 14
26 #define ETHERNET_MTU 1500
27 #define ETHERNET_PACKET_LEN (ETHERNET_HEADER_LEN + ETHERNET_MTU)
33 #define MAX_PACKET_LEN (MAX_MTU + ETHERNET_HEADER_LEN)
39 struct nic_statistics {
48 uint32_t tx_interrupts;
49 uint32_t rx_interrupts;
54 #include <palacios/vmm.h>
56 #define V3_Net_Print(level, fmt, args...) \
58 if(level <= net_debug) { \
59 V3_Print(VM_NONE, VCORE_NONE, fmt, ##args); \
64 static inline int is_multicast_ethaddr(const uint8_t * addr)
66 V3_ASSERT(VM_NONE, VCORE_NONE, ETH_ALEN == 6);
68 return (0x01 & addr[0]);
71 static inline int is_broadcast_ethaddr(const uint8_t * addr)
73 V3_ASSERT(VM_NONE, VCORE_NONE, ETH_ALEN == 6);
75 return (addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) == 0xff;
79 static inline int compare_ethaddr(const uint8_t * addr1, const uint8_t * addr2)
81 const uint16_t *a = (const uint16_t *) addr1;
82 const uint16_t *b = (const uint16_t *) addr2;
84 V3_ASSERT(VM_NONE, VCORE_NONE, ETH_ALEN == 6);
85 return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0;
89 static inline int compare_ether_hdr(const uint8_t * hdr1, const uint8_t * hdr2)
91 uint32_t *a32 = (uint32_t *)(hdr1 + 2);
92 uint32_t *b32 = (uint32_t *)(hdr2 + 2);
94 V3_ASSERT(VM_NONE, VCORE_NONE, ETHERNET_HEADER_LEN == 14);
96 return (*(uint16_t *)hdr1 ^ *(uint16_t *)hdr2) | (a32[0] ^ b32[0]) |
97 (a32[1] ^ b32[1]) | (a32[2] ^ b32[2]);
100 /* AA:BB:CC:DD:EE:FF */
101 static inline int str2mac(char * macstr, uint8_t * mac){
102 char hex[3], *s = macstr;
108 mac[i++] = (char)atox(hex);
109 if (i == ETH_ALEN) return 0;
118 /* generate random ethernet address */
119 static inline void random_ethaddr(uint8_t * addr)
123 /* using current rdtsc as random number */
125 *(uint64_t *)addr = val;
127 addr [0] &= 0xfe; /* clear multicast bit */
128 addr [0] |= 0x02; /* set local assignment bit (IEEE802) */
132 * CRC32 code derived from work by Gary S. Brown.
135 * First, the polynomial itself and its table of feedback terms. The
137 * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
139 * Note that we take it "backwards" and put the highest-order term in
140 * the lowest-order bit. The X^32 term is "implied"; the LSB is the
141 * X^31 term, etc. The X^0 term (usually shown as "+1") results in
144 * Note that the usual hardware shift register implementation, which
145 * is what we're using (we're merely optimizing it by doing eight-bit
146 * chunks at a time) shifts bits into the lowest-order term. In our
147 * implementation, that means shifting towards the right. Why do we
148 * do it this way? Because the calculated CRC must be transmitted in
149 * order from highest-order term to lowest-order term. UARTs transmit
150 * characters in order from LSB to MSB. By storing the CRC this way
151 * we hand it to the UART in the order low-byte to high-byte; the UART
152 * sends each low-bit to hight-bit; and the result is transmission bit
153 * by bit from highest- to lowest-order term without requiring any bit
154 * shuffling on our part. Reception works similarly
156 * The feedback terms table consists of 256, 32-bit entries. Notes
158 * The table can be generated at runtime if desired; code to do so
159 * is shown later. It might not be obvious, but the feedback
160 * terms simply represent the results of eight shift/xor opera
161 * tions for all combinations of data and CRC register values
163 * The values must be right-shifted by eight bits by the "updcrc
164 * logic; the shift must be unsigned (bring in zeroes). On some
165 * hardware you could probably optimize the shift in assembler by
166 * using byte-swap instructions
167 * polynomial $edb88320
171 static uint32_t crc32_tab[] = {
172 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
173 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
174 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
175 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
176 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
177 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
178 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
179 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
180 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
181 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
182 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
183 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
184 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
185 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
186 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
187 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
188 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
189 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
190 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
191 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
192 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
193 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
194 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
195 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
196 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
197 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
198 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
199 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
200 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
201 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
202 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
203 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
204 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
205 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
206 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
207 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
208 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
209 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
210 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
211 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
212 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
213 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
214 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
217 static inline uint32_t v3_crc32(uint32_t crc, uint8_t *buf, int size)
225 crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);