Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


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