diff options
author | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2003-05-13 11:31:46 +0000 |
---|---|---|
committer | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2003-05-13 11:31:46 +0000 |
commit | 08874b8ef46153c23673d8e86bb461519b9ff09d (patch) | |
tree | 9898cdb361853dc60dbd81b501ce2821f721d3fb | |
parent | 4cb5c054fcae57ddabc7cd91d39a9b4b1f41b2ed (diff) | |
download | xen-08874b8ef46153c23673d8e86bb461519b9ff09d.tar.gz xen-08874b8ef46153c23673d8e86bb461519b9ff09d.tar.bz2 xen-08874b8ef46153c23673d8e86bb461519b9ff09d.zip |
bitkeeper revision 1.225 (3ec0d7a2BpgJXl0j-8Y1KilL1argzw)
lib.h, network.c, lib.c, kernel.c:
A better method for calculating virtual MAC addresses. Dom0/VIF0 (the boot VIF) can be forced to use the physical MAC address by specifying 'phys_bootmac' on Xen's command line.
-rw-r--r-- | xen/common/kernel.c | 20 | ||||
-rw-r--r-- | xen/common/lib.c | 64 | ||||
-rw-r--r-- | xen/common/network.c | 45 | ||||
-rw-r--r-- | xen/include/xeno/lib.h | 3 |
4 files changed, 115 insertions, 17 deletions
diff --git a/xen/common/kernel.c b/xen/common/kernel.c index 0b8e693e97..5b1d0f9804 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -40,21 +40,23 @@ unsigned int opt_ser_baud = 9600; /* default baud for COM1 */ unsigned int opt_dom0_mem = 16000; /* default kbytes for DOM0 */ unsigned int opt_ne_base = 0; /* NE2k NICs cannot be probed */ unsigned char opt_ifname[10] = "eth0"; -int opt_noht=0, opt_noacpi=0, opt_nosmp; +int opt_noht=0, opt_noacpi=0, opt_nosmp=0; +int opt_phys_bootmac=0; /* Is DOM0/VIF0 allocated the physical MAC address? */ enum { OPT_IP, OPT_STR, OPT_UINT, OPT_BOOL }; static struct { unsigned char *name; int type; void *var; } opts[] = { - { "console", OPT_UINT, &opt_console }, - { "ser_baud", OPT_UINT, &opt_ser_baud }, - { "dom0_mem", OPT_UINT, &opt_dom0_mem }, - { "ne_base", OPT_UINT, &opt_ne_base }, - { "ifname", OPT_STR, &opt_ifname }, - { "noht", OPT_BOOL, &opt_noht }, - { "noacpi", OPT_BOOL, &opt_noacpi }, - { "nosmp", OPT_BOOL, &opt_nosmp }, + { "console", OPT_UINT, &opt_console }, + { "ser_baud", OPT_UINT, &opt_ser_baud }, + { "dom0_mem", OPT_UINT, &opt_dom0_mem }, + { "ne_base", OPT_UINT, &opt_ne_base }, + { "ifname", OPT_STR, &opt_ifname }, + { "noht", OPT_BOOL, &opt_noht }, + { "noacpi", OPT_BOOL, &opt_noacpi }, + { "nosmp", OPT_BOOL, &opt_nosmp }, + { "phys_bootmac", OPT_BOOL, &opt_phys_bootmac }, { NULL, 0, NULL } }; diff --git a/xen/common/lib.c b/xen/common/lib.c index c871341b7f..3d7cc8c00e 100644 --- a/xen/common/lib.c +++ b/xen/common/lib.c @@ -525,3 +525,67 @@ __udivdi3(a, b) return (__qdivrem(a, b, (u64 *)0)); } + + + + +/* HASH/RANDOMISATION FUNCTION + * Based on lookup2.c, by Bob Jenkins, December 1996, Public Domain. + * You can use this free for any purpose. It has no warranty. + * See http://burlteburtle.net/bob/hash/evahash.html + */ + +typedef unsigned long ub4; + +#define mix(a,b,c) \ + do { \ + a -= b; a -= c; a ^= (c>>13); \ + b -= c; b -= a; b ^= (a<< 8); \ + c -= a; c -= b; c ^= ((b&0xffffffff)>>13); \ + a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \ + b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \ + c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \ + a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \ + b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \ + c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \ + } while ( 0 ) + +unsigned long hash(unsigned char *k, unsigned long len) +{ + unsigned long a, b, c, l; + + l = len; + a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */ + c = 0xa5a5a5a5; /* another arbitrary value (KAF, 13/5/03) */ + + while ( l >= 12 ) + { + a += (k[0] + ((ub4)k[1]<<8) + ((ub4)k[2]<<16) + ((ub4)k[3]<<24)); + b += (k[4] + ((ub4)k[5]<<8) + ((ub4)k[6]<<16) + ((ub4)k[7]<<24)); + c += (k[8] + ((ub4)k[9]<<8) + ((ub4)k[10]<<16) + ((ub4)k[11]<<24)); + mix(a,b,c); + k += 12; l -= 12; + } + + c += len; + switch ( l ) + { + case 11: c+=((ub4)k[10]<<24); + case 10: c+=((ub4)k[9]<<16); + case 9 : c+=((ub4)k[8]<<8); + /* the first byte of c is reserved for the length */ + case 8 : b+=((ub4)k[7]<<24); + case 7 : b+=((ub4)k[6]<<16); + case 6 : b+=((ub4)k[5]<<8); + case 5 : b+=k[4]; + case 4 : a+=((ub4)k[3]<<24); + case 3 : a+=((ub4)k[2]<<16); + case 2 : a+=((ub4)k[1]<<8); + case 1 : a+=k[0]; + /* case 0: nothing left to add */ + } + + mix(a,b,c); + + return c; +} diff --git a/xen/common/network.c b/xen/common/network.c index f7c5f3b7c2..9a2d5eef8a 100644 --- a/xen/common/network.c +++ b/xen/common/network.c @@ -69,7 +69,9 @@ net_vif_t *create_net_vif(int domain) net_vif_t *new_vif = NULL; net_ring_t *new_ring = NULL; struct task_struct *p = NULL; - unsigned long flags; + unsigned long flags, vmac_hash; + unsigned char vmac_key[ETH_ALEN + 4 + 2]; + extern int opt_phys_bootmac; if ( !(p = find_domain_by_id(domain)) ) return NULL; @@ -104,13 +106,40 @@ net_vif_t *create_net_vif(int domain) spin_lock_init(&new_vif->rx_lock); spin_lock_init(&new_vif->tx_lock); - /* - * Virtual MAC is a hash of the real physical MAC. Chosen so that the - * first vif of domain 0 gets the physical MAC address. - */ - memcpy(new_vif->vmac, the_dev->dev_addr, ETH_ALEN); - ((unsigned short *)new_vif->vmac)[1] ^= htons(p->domain); - ((unsigned short *)new_vif->vmac)[2] ^= htons(dom_vif_idx); + if ( opt_phys_bootmac && (p->domain == 0) && (dom_vif_idx == 0) ) + { + /* + * DOM0/VIF0 may get the real physical MAC address, so that + * users can easily get a Xenoserver up and running by using an + * existing DHCP entry. + */ + memcpy(new_vif->vmac, the_dev->dev_addr, ETH_ALEN); + } + else + { + /* + * Most VIFs get a random MAC address with a "special" vendor id. + * We try to get MAC addresses to be unique across multiple servers + * by including the physical MAC address in the hash. + * However, the same machine with the same dom_id and vif_id should + * always get the same virtual MAC address. + * + * NB. The vendor is currently an "obsolete" one that used to belong + * to DEC (AA-00-00). Using it is probably a bit rude :-) + * + * NB2. The first bit of the first random octet is set to zero for + * all dynamic MAC addresses. This may allow us to manually specify + * MAC addresses for some VIFs with no fear of clashes. + */ + memcpy(&vmac_key[0], the_dev->dev_addr, ETH_ALEN); + *(__u32 *)(&vmac_key[ETH_ALEN+0]) = htonl(p->domain); + *(__u16 *)(&vmac_key[ETH_ALEN+4]) = htons(dom_vif_idx); + vmac_hash = hash(vmac_key, ETH_ALEN+4+2); + memcpy(new_vif->vmac, "\xaa\x00\x00", 3); + new_vif->vmac[3] = (vmac_hash >> 16) & 0xef; /* First bit is zero. */ + new_vif->vmac[4] = (vmac_hash >> 8) & 0xff; + new_vif->vmac[5] = (vmac_hash >> 0) & 0xff; + } p->net_vif_list[dom_vif_idx] = new_vif; diff --git a/xen/include/xeno/lib.h b/xen/include/xeno/lib.h index a9eeda6716..9f97ad9530 100644 --- a/xen/include/xeno/lib.h +++ b/xen/include/xeno/lib.h @@ -54,4 +54,7 @@ long simple_strtol(const char *cp,char **endp,unsigned int base); unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base); long long simple_strtoll(const char *cp,char **endp,unsigned int base); +/* Produce a 32-bit hash from a key string 'k' of length 'len' bytes. */ +unsigned long hash(unsigned char *k, unsigned long len); + #endif /* __LIB_H__ */ |