diff -ruN vmnet-only-patched/bridge.c vmnet-only-refixed/bridge.c --- vmnet-only-patched/bridge.c 2009-07-08 16:21:02.000000000 +0300 +++ vmnet-only-refixed/bridge.c 2009-04-21 18:30:03.000000000 +0300 @@ -275,11 +275,7 @@ struct net_device *net) // IN: Network device { #ifdef VMW_NETDEV_HAS_NET -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) if (dev_net(net) != dev_net(bridge->internalDev)) { -#else - if (net->nd_net != bridge->internalDev->nd_net) { -#endif return 0; } #endif @@ -857,6 +853,9 @@ static Bool VNetBridgeIsDeviceWireless(struct net_device *dev) //IN: sock { + return FALSE; +} +#if 0 #ifdef CONFIG_WIRELESS_EXT return dev->wireless_handlers != NULL; #elif !defined CONFIG_NET_RADIO && !defined CONFIG_WLAN_80211 @@ -869,7 +868,7 @@ return dev->get_wireless_stats != NULL; #endif } - +#endif /* *---------------------------------------------------------------------- * diff -ruN vmnet-only-patched/bridge.c.orig vmnet-only-refixed/bridge.c.orig --- vmnet-only-patched/bridge.c.orig 1970-01-01 02:00:00.000000000 +0200 +++ vmnet-only-refixed/bridge.c.orig 2007-11-28 12:25:06.000000000 +0200 @@ -0,0 +1,1552 @@ +/* ********************************************************** + * Copyright 1998 VMware, Inc. All rights reserved. -- VMware Confidential + * **********************************************************/ + +#include "driver-config.h" + +#define EXPORT_SYMTAB + +#include +#include +#include +#ifdef KERNEL_2_2 +# include +#else +# include +#endif +#include + +#include +#include +#include +#include "compat_skbuff.h" +#include +#include "compat_sock.h" + +#define __KERNEL_SYSCALLS__ +#include + +#include +#include +#include +#include +#include + +#ifdef CONFIG_NET_RADIO +# include +#endif +#include "vmnetInt.h" +#include "compat_spinlock.h" +#include "compat_netdevice.h" +#include "vnetInt.h" +#include "smac.h" + +#define VNET_BRIDGE_HISTORY 48 + +/* + * Bytes reserved before start of packet. As Ethernet header has 14 bytes, + * to get aligned IP header we must skip 2 bytes before packet. Not that it + * matters a lot for us, but using 2 is compatible with what newer 2.6.x + * kernels do. + */ +#ifndef NET_IP_ALIGN +#define NET_IP_ALIGN 2 +#endif + +#if LOGLEVEL >= 4 +static struct timeval vnetTime; +#endif + +typedef struct VNetBridge VNetBridge; + +struct VNetBridge { + struct notifier_block notifier; // for device state changes + char name[VNET_NAME_LEN]; // name of net device (e.g., "eth0") + struct net_device *dev; // device structure for 'name' + struct sock *sk; // socket associated with skb's + struct packet_type pt; // used to add packet handler + Bool enabledPromisc; // track if promisc enabled + Bool warnPromisc; // tracks if warning has been logged + struct sk_buff *history[VNET_BRIDGE_HISTORY]; // avoid duplicate packets + spinlock_t historyLock; // protects 'history' + VNetPort port; // connection to virtual hub + Bool wirelessAdapter; // connected to wireless adapter? + struct SMACState *smac; // device structure for wireless +#ifdef VMW_NETDEV_HAS_NET + struct net_device *internalDev; +#endif +}; + +typedef PacketStatus (* SMACINT SMACFunc)(struct SMACState *, SMACPackets *); + +static int VNetBridgeUp(VNetBridge *bridge, Bool rtnlLock); +static void VNetBridgeDown(VNetBridge *bridge, Bool rtnlLock); + +static int VNetBridgeNotify(struct notifier_block *this, u_long msg, + void *data); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14) && \ + !defined(VMW_TL10S64_WORKAROUND) +static int VNetBridgeReceiveFromDev(struct sk_buff *skb, + struct net_device *dev, + struct packet_type *pt); +#else +static int VNetBridgeReceiveFromDev(struct sk_buff *skb, + struct net_device *dev, + struct packet_type *pt, + struct net_device *real_dev); +#endif + +static void VNetBridgeFree(VNetJack *this); +static void VNetBridgeReceiveFromVNet(VNetJack *this, struct sk_buff *skb); +static Bool VNetBridgeCycleDetect(VNetJack *this, int generation); +static Bool VNetBridgeIsDeviceWireless(struct net_device *dev); +static void VNetBridgePortsChanged(VNetJack *this); +static int VNetBridgeIsBridged(VNetJack *this); +static int VNetBridgeProcRead(char *page, char **start, off_t off, + int count, int *eof, void *data); + + +/* + *---------------------------------------------------------------------- + * + * VNetBridgeStartPromisc -- + * + * Set IFF_PROMISC on the peer interface. + * + * Results: + * None. + * + * Side effects: + * The peer interface IFF_PROMISC flag may be changed. + * + *---------------------------------------------------------------------- + */ + +static void +VNetBridgeStartPromisc(VNetBridge *bridge, // IN: + Bool rtnlLock) // IN: Acquire RTNL lock +{ + struct net_device *dev = bridge->dev; + + /* + * Disable wireless cards from going into promiscous mode because those + * cards which do support RF monitoring would not be able to function + * correctly i.e. they would not be able to send data packets. + */ + if (rtnlLock) { + rtnl_lock(); + } + if (!bridge->enabledPromisc && !bridge->wirelessAdapter) { + dev_set_promiscuity(dev, 1); + bridge->enabledPromisc = TRUE; + bridge->warnPromisc = FALSE; + LOG(0, (KERN_NOTICE "bridge-%s: enabled promiscuous mode\n", + bridge->name)); + } + if (rtnlLock) { + rtnl_unlock(); + } +} + + +/* + *---------------------------------------------------------------------- + * + * VNetBridgeStopPromisc -- + * + * Restore saved IFF_PROMISC on the peer interface. + * + * Results: + * None. + * + * Side effects: + * The peer interface IFF_PROMISC flag may be changed. + * + *---------------------------------------------------------------------- + */ + +static void +VNetBridgeStopPromisc(VNetBridge *bridge, // IN: + Bool rtnlLock) // IN: Acquire RTNL lock +{ + struct net_device *dev = bridge->dev; + + if (rtnlLock) { + rtnl_lock(); + } + if (bridge->enabledPromisc && !bridge->wirelessAdapter) { + dev_set_promiscuity(dev, -1); + bridge->enabledPromisc = FALSE; + LOG(0, (KERN_NOTICE "bridge-%s: disabled promiscuous mode\n", + bridge->name)); + } + if (rtnlLock) { + rtnl_unlock(); + } +} + + +/* + *---------------------------------------------------------------------- + * + * VNetBridgeCheckPromisc -- + * + * Make sure IFF_PROMISC on the peer interface is set. + * + * This can be called periodically. + * + * Results: + * None. + * + * Side effects: + * Hopefully enables promiscuous mode again if it should have been enabled. + * + *---------------------------------------------------------------------- + */ + +static INLINE_SINGLE_CALLER void +VNetBridgeCheckPromisc(VNetBridge *bridge) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) + if (bridge->enabledPromisc && !bridge->wirelessAdapter) { + struct net_device *dev = bridge->dev; + Bool devPromisc = (dev->flags & IFF_PROMISC) != 0; + + if (!devPromisc) { + if (!bridge->warnPromisc) { + bridge->warnPromisc = TRUE; + LOG(0, (KERN_NOTICE "bridge-%s: someone disabled promiscuous mode\n" + "Your Ethernet driver is not compatible with VMware's bridged networking.\n", + bridge->name)); + } + rtnl_lock(); + dev_set_promiscuity(dev, 0); + rtnl_unlock(); + } + } +#endif +} + + +#ifdef VMW_NETDEV_HAS_NET +/* + *---------------------------------------------------------------------- + * + * VNetBridgeInternalSetup -- + * + * Setup callback for our bridge internal device. Nothing to do, + * generic code sets up everything we expect from device. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +VNetBridgeInternalSetup(struct net_device *net) +{ + /* Do nothing. */ +} +#endif + + +/* + *---------------------------------------------------------------------- + * + * VNetBridgeDevCompatible -- + * + * Check whether bridge and network device are compatible. + * + * Results: + * Non-zero if device is good enough for bridge. Zero otherwise. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static INLINE_SINGLE_CALLER int +VNetBridgeDevCompatible(VNetBridge *bridge, // IN: Bridge + struct net_device *net) // IN: Network device +{ +#ifdef VMW_NETDEV_HAS_NET + if (net->nd_net != bridge->internalDev->nd_net) { + return 0; + } +#endif + return strcmp(net->name, bridge->name) == 0; +} + + +/* + *---------------------------------------------------------------------- + * + * VNetBridge_Create -- + * + * Create a bridge. Allocates/initializes struct, registers + * with kernel for device state changes, connects to virtual + * hub, initializes port/jack, and creates a proc entry. + * + * Results: + * Errno. Also returns an allocated jack to connect to, + * NULL on error. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +VNetBridge_Create(const char *devName, // IN: name of device (e.g., "eth0") + VNetPort **ret) // OUT: port to virtual hub +{ + VNetBridge *bridge = NULL; + static unsigned id = 0; + int retval = 0; + + *ret = NULL; + + /* + * Its an error if device name is empty. + */ + + if (devName[0] == '\0') { + retval = -EINVAL; + goto out; + } + + /* + * Allocate bridge structure + */ + + bridge = kmalloc(sizeof *bridge, GFP_USER); + if (bridge == NULL) { + retval = -ENOMEM; + goto out; + } + memset(bridge, 0, sizeof *bridge); + spin_lock_init(&bridge->historyLock); + memcpy(bridge->name, devName, sizeof bridge->name); + NULL_TERMINATE_STRING(bridge->name); + +#ifdef VMW_NETDEV_HAS_NET + bridge->internalDev = compat_alloc_netdev(0, "vmnetX", VNetBridgeInternalSetup); + if (!bridge->internalDev) { + retval = -ENOMEM; + goto out; + } +#endif + + /* + * Set up notifier for network device state change + */ + + bridge->notifier.notifier_call = VNetBridgeNotify; + bridge->notifier.priority = 0; + register_netdevice_notifier(&bridge->notifier); + + /* + * Try to bring it up + */ + + retval = VNetBridgeUp(bridge, TRUE); + if (retval == -ENODEV) { + LOG(1, (KERN_DEBUG "bridge-%s: peer interface %s not found, " + "will wait for it to come up\n", + bridge->name, devName)); + retval = 0; + } + if (retval != 0) { + goto out; + } + + /* + * Initialize jack + */ + + bridge->port.id = id++; + bridge->port.next = NULL; + + bridge->port.jack.peer = NULL; + bridge->port.jack.numPorts = 1; + VNetSnprintf(bridge->port.jack.name, sizeof bridge->port.jack.name, + "bridge%u", bridge->port.id); + bridge->port.jack.private = bridge; + bridge->port.jack.index = 0; + bridge->port.jack.procEntry = NULL; + bridge->port.jack.free = VNetBridgeFree; + bridge->port.jack.rcv = VNetBridgeReceiveFromVNet; + bridge->port.jack.cycleDetect = VNetBridgeCycleDetect; + bridge->port.jack.portsChanged = VNetBridgePortsChanged; + bridge->port.jack.isBridged = VNetBridgeIsBridged; + + /* + * Make proc entry for this jack. + */ + + retval = VNetProc_MakeEntry(NULL, bridge->port.jack.name, S_IFREG, + &bridge->port.jack.procEntry); + if (retval) { + if (retval == -ENXIO) { + bridge->port.jack.procEntry = NULL; + } else { + goto out; + } + } else { + bridge->port.jack.procEntry->read_proc = VNetBridgeProcRead; + bridge->port.jack.procEntry->data = bridge; + } + + /* + * Rest of fields. + */ + + bridge->port.flags = IFF_RUNNING; + + memset(bridge->port.paddr, 0, sizeof bridge->port.paddr); + memset(bridge->port.ladrf, 0, sizeof bridge->port.ladrf); + + bridge->port.paddr[0] = VMX86_STATIC_OUI0; + bridge->port.paddr[1] = VMX86_STATIC_OUI1; + bridge->port.paddr[2] = VMX86_STATIC_OUI2; + + bridge->port.fileOpRead = NULL; + bridge->port.fileOpWrite = NULL; + bridge->port.fileOpIoctl = NULL; + bridge->port.fileOpPoll = NULL; + + *ret = &bridge->port; + + LOG(1, (KERN_DEBUG "bridge-%s: attached\n", bridge->name)); + return 0; + +out: + if (bridge != NULL) { + if (bridge->notifier.notifier_call != NULL) { + unregister_netdevice_notifier(&bridge->notifier); + } +#ifdef VMW_NETDEV_HAS_NET + if (bridge->internalDev) { + compat_free_netdev(bridge->internalDev); + } +#endif + kfree(bridge); + } + return retval; +} + + +/* + *---------------------------------------------------------------------- + * + * VNetBridgeFree -- + * + * Disconnect the bridge, unregister from device state + * notifications, remove proc entry, and deallocate struct. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +VNetBridgeFree(VNetJack *this) // IN: jack to free +{ + VNetBridge *bridge = (VNetBridge*)this->private; + + if (bridge->dev != NULL) { + VNetBridgeDown(bridge, TRUE); + } + + unregister_netdevice_notifier(&bridge->notifier); + +#ifdef VMW_NETDEV_HAS_NET + if (bridge->internalDev) { + compat_free_netdev(bridge->internalDev); + } +#endif + + if (this->procEntry) { + VNetProc_RemoveEntry(this->procEntry, NULL); + } + + if (bridge->smac){ + SMAC_CleanupState(&(bridge->smac)); + } + + LOG(1, (KERN_DEBUG "bridge-%s: detached\n", bridge->name)); + kfree(bridge); +} + + +/* + *---------------------------------------------------------------------- + * + * VNetCallSMACFunc -- + * + * Wrapper for SMAC functions. + * + * Results: + * Packet Status. + * + * Side effects: + * The skb buffer is freed if not succesfull otherwise it points to + * the clone. + * + *---------------------------------------------------------------------- + */ + +PacketStatus +VNetCallSMACFunc(struct SMACState *state, // IN: pointer to state + struct sk_buff **skb, // IN/OUT: packet to process + void *startOfData, // IN: points to start of data + SMACFunc func) // IN: function to be called +{ + SMACPackets packets = { {0} }; + PacketStatus status; + + packets.orig.skb = *skb; + packets.orig.startOfData = startOfData; + + status = func(state, &packets); + if (status != PacketStatusForwardPacket) { + dev_kfree_skb(*skb); + return status; + } + + if (packets.clone.skb) { + dev_kfree_skb(*skb); + *skb = packets.clone.skb; + } + return status; +} + + +/* + *---------------------------------------------------------------------- + * + * VNetBridgeReceiveFromVNet -- + * + * This jack is receiving a packet from a vnet. This function + * sends down (i.e., out on the host net device) if the packet + * isn't destined for the host, and it sends up (i.e., + * simulates a receive for the host) if the packet + * satisfies the host's packet filter. + * + * When the function sends up it keeps a reference to the + * packet in a history list so that we can avoid handing + * a VM a copy of its own packet. + * + * Results: + * None. + * + * Side effects: + * Frees skb. Checks if host device is still using + * promiscuous mode. + * + *---------------------------------------------------------------------- + */ + +void +VNetBridgeReceiveFromVNet(VNetJack *this, // IN: jack + struct sk_buff *skb) // IN: pkt to receive +{ + VNetBridge *bridge = (VNetBridge*)this->private; + struct net_device *dev = bridge->dev; + uint8 dest[ETH_ALEN]; + struct sk_buff *clone; + + LOG(3, (KERN_DEBUG "bridge-%s: transmit %d\n", + bridge->name, (int) skb->len)); + + if (!dev) { + dev_kfree_skb(skb); + return; + } + + /* + * skb might be freed by wireless code, so need to keep + * a local copy of the MAC rather than a pointer to it. + */ + + memcpy(dest, SKB_2_DESTMAC(skb), ETH_ALEN); + + /* + * Check promiscuous bit periodically + */ + + VNetBridgeCheckPromisc(bridge); + +#ifdef notdef + // xxx; + /* + * We need to send the packet both up to the host and down + * to the interface. + * However, we ignore packets destined only for this hub. + */ + + for (i = 0; i < VNET_PORTS_PER_HUB; i++) { + VNetPort *p = &port->hub->port[i]; + if (UP_AND_RUNNING(p->flags) && MAC_EQ(dest, p->paddr)) { + return; + } + } +#endif + + /* + * Wireless processing + */ + + if (bridge->smac) { + if (VNetCallSMACFunc(bridge->smac, &skb, skb->data, + SMAC_CheckPacketToHost) != + PacketStatusForwardPacket) { + LOG(4, (KERN_NOTICE "bridge-%s: packet dropped .\n", + bridge->name)); + return; + } + } + + /* + * Send down (imitate packet_sendmsg) + * + * Do this only if the packet is not addressed to the peer, + * and the packet size is not too big. + */ + + dev_lock_list(); + if (MAC_EQ(dest, dev->dev_addr) || + skb->len > dev->mtu + dev->hard_header_len + 4) { + dev_unlock_list(); + } else { +# if 0 // XXX we should do header translation + if ((dev->flags & IFF_SOFTHEADERS) != 0) { + if (skb->len > dev->mtu) { + clone = NULL; + } else { + clone = dev_alloc_skb(skb->len + dev->hard_header_len, GFP_ATOMIC); + } + if (clone != NULL) { + skb_reserve(clone, dev->hard_header_len); + if (dev->hard_header != NULL) { + dev->hard_header(clone, dev, ETH_P_IP, NULL, NULL, skb->len); + } + memcpy(skb_put(clone, skb->len), skb->data, skb->len); + } + } +# endif + clone = skb_clone(skb, GFP_ATOMIC); + if (clone == NULL) { + dev_unlock_list(); + } else { + struct sock *sk = bridge->sk; + atomic_add(skb->truesize, &sk->sk_wmem_alloc); + clone->sk = sk; + clone->protocol = ((struct ethhdr *)skb->data)->h_proto; // XXX + if ((dev->flags & IFF_UP) != 0) { + dev_unlock_list(); + DEV_QUEUE_XMIT(clone, dev, 0); + } else { + dev_unlock_list(); + dev_kfree_skb(clone); + } + } + } + + /* + * Send up (imitate Ethernet receive) + * + * Do this if the packet is addressed to the peer (or is broadcast, etc.). + * + * This packet will get back to us, via VNetBridgeReceive. + * We save it so we can recognize it (and its clones) again. + */ + + if (VNetPacketMatch(dest, dev->dev_addr, allMultiFilter, dev->flags)) { + clone = skb_clone(skb, GFP_ATOMIC); + if (clone) { + unsigned long flags; + int i; + + atomic_inc(&clone->users); + + clone->dev = dev; + clone->protocol = eth_type_trans(clone, dev); + spin_lock_irqsave(&bridge->historyLock, flags); + for (i = 0; i < VNET_BRIDGE_HISTORY; i++) { + if (bridge->history[i] == NULL) { + bridge->history[i] = clone; +# if LOGLEVEL >= 3 + { + int j; + int count = 0; + for (j = 0; j < VNET_BRIDGE_HISTORY; j++) { + if (bridge->history[j] != NULL) { + count++; + } + } + LOG(3, (KERN_DEBUG "bridge-%s: host slot %d history %d\n", + bridge->name, i, count)); + } +# endif + break; + } + } + if (i >= VNET_BRIDGE_HISTORY) { + LOG(1, (KERN_NOTICE "bridge-%s: history full\n", + bridge->name)); + + for (i = 0; i < VNET_BRIDGE_HISTORY; i++) { + struct sk_buff *s = bridge->history[i]; + + /* + * We special case 0 to avoid races with another thread on + * another cpu wanting to use the 0 entry. This could happen + * when we release the lock to free the former entry. + * See bug 11231 for details. + */ + if (i == 0) { + bridge->history[0] = clone; + } else { + bridge->history[i] = NULL; + } + if (s) { + spin_unlock_irqrestore(&bridge->historyLock, flags); + dev_kfree_skb(s); + spin_lock_irqsave(&bridge->historyLock, flags); + } + } + } + spin_unlock_irqrestore(&bridge->historyLock, flags); + + /* + * We used to cli() before calling netif_rx() here. It was probably + * unneeded (as we never did it in netif.c, and the code worked). In + * any case, now that we are using netif_rx_ni(), we should certainly + * not do it, or netif_rx_ni() will deadlock on the cli() lock --hpreg + */ + + netif_rx_ni(clone); +# if LOGLEVEL >= 4 + do_gettimeofday(&vnetTime); +# endif + } + } + + // xxx; + dev_kfree_skb(skb); +} + + +/* + *---------------------------------------------------------------------- + * + * VNetBridgeCycleDetect -- + * + * Cycle detection algorithm. + * + * Results: + * TRUE if a cycle was detected, FALSE otherwise. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Bool +VNetBridgeCycleDetect(VNetJack *this, // IN: jack + int generation) // IN: generation +{ + VNetBridge *bridge = (VNetBridge*)this->private; + return VNetCycleDetectIf(bridge->name, generation); +} + + +/* + *---------------------------------------------------------------------- + * + * VNetBridgePortsChanged -- + * + * The number of ports connected to this jack has change, react + * accordingly by starting/stopping promiscuous mode based on + * whether any peers exist. + * + * Results: + * None. + * + * Side effects: + * Promiscuous mode may be started or stopped. + * + *---------------------------------------------------------------------- + */ + +void +VNetBridgePortsChanged(VNetJack *this) // IN: jack +{ + VNetBridge *bridge = (VNetBridge*)this->private; + if (bridge->dev) { + if (VNetGetAttachedPorts(this)) { + VNetBridgeStartPromisc(bridge, TRUE); + } else { + VNetBridgeStopPromisc(bridge, TRUE); + } + } +} + + +/* + *---------------------------------------------------------------------- + * + * VNetBridgeIsBridged -- + * + * Reports if the bridged interface is up or down. + * + * Results: + * 1 - we are bridged but the interface is not up + * 2 - we are bridged and the interface is up + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +VNetBridgeIsBridged(VNetJack *this) // IN: jack +{ + VNetBridge *bridge = (VNetBridge*)this->private; + if (bridge->dev) { + return 2; + } else { + return 1; + } +} + +/* + *---------------------------------------------------------------------- + * + * VNetBridgeIsDeviceWireless -- + * + * Check if the device is a wireless adapter, depending on the version + * of the wireless extension present in the kernel. + * + * Results: + * TRUE if the device is wireless, FALSE otherwise. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static Bool +VNetBridgeIsDeviceWireless(struct net_device *dev) //IN: sock +{ +#ifdef CONFIG_WIRELESS_EXT + return dev->wireless_handlers != NULL; +#elif !defined(CONFIG_NET_RADIO) + return FALSE; +#elif WIRELESS_EXT > 19 + return dev->wireless_handlers != NULL; +#elif WIRELESS_EXT > 12 + return dev->wireless_handlers != NULL || dev->get_wireless_stats != NULL; +#else + return dev->get_wireless_stats != NULL; +#endif +} + +/* + *---------------------------------------------------------------------- + * + * VNetBridgeUp -- + * + * Bring a bridge up. Gets peer's device structure, verifies + * that interface is up, checks the header length, + * allocates a socket, adds a packet handler to the network + * stack, and then places the peer's device in promiscuous + * mode. + * + * Results: + * errno. + * + * Side effects: + * Bridging may be brought up with a peer interface. + * + *---------------------------------------------------------------------- + */ + +int +VNetBridgeUp(VNetBridge *bridge, // IN: bridge struct + Bool rtnlLock) // IN: acquire RTNL lock +{ + int retval = 0; + + if (bridge->dev != NULL) { + LOG(0, (KERN_NOTICE "bridge-%s: already up\n", bridge->name)); + goto out; + } + + /* + * Get peer device structure + */ + + dev_lock_list(); + bridge->dev = DEV_GET(bridge); + LOG(2, (KERN_DEBUG "bridge-%s: got dev %p\n", + bridge->name, bridge->dev)); + if (bridge->dev == NULL) { + dev_unlock_list(); + retval = -ENODEV; + goto out; + } + if (!(bridge->dev->flags & IFF_UP)) { + LOG(2, (KERN_DEBUG "bridge-%s: interface %s is not up\n", + bridge->name, bridge->dev->name)); + dev_unlock_list(); + retval = -ENODEV; + goto out; + } + + /* + * At a minimum, the header size should be the same as ours. + * + * XXX we should either do header translation or ensure this + * is an Ethernet. + */ + + if (bridge->dev->hard_header_len != ETH_HLEN && bridge->dev->hard_header_len != ETH_HLEN + 4) { + LOG(1, (KERN_DEBUG "bridge-%s: can't bridge with %s, bad header length %d\n", + bridge->name, bridge->dev->name, bridge->dev->hard_header_len)); + dev_unlock_list(); + retval = -EINVAL; + goto out; + } + + /* + * Get a socket to play with + * + * We set the dead field so we don't get a call back from dev_kfree_skb(). + * (The alternative is to support the callback.) + */ + + bridge->sk = compat_sk_alloc(bridge, GFP_ATOMIC); + if (bridge->sk == NULL) { + dev_unlock_list(); + retval = -ENOMEM; + goto out; + } + SET_SK_DEAD(bridge->sk, 1); + + bridge->wirelessAdapter = VNetBridgeIsDeviceWireless(bridge->dev); + + /* + * If it is a wireless adapter initialize smac struct. + */ + + if (bridge->wirelessAdapter) { + + LOG(1, (KERN_NOTICE "bridge-%s: is a Wireless Adapter\n", bridge->name)); + SMAC_InitState(&(bridge->smac)); + if (bridge->smac) { + /* + * Store the MAC address of the adapter + */ + + SMAC_SetMac(bridge->smac, bridge->dev->dev_addr); + } + } + + /* + * Link up with the peer device by adding a + * packet handler to the networking stack. + */ + + bridge->pt.func = VNetBridgeReceiveFromDev; + bridge->pt.type = htons(ETH_P_ALL); + bridge->pt.dev = bridge->dev; + + /* + * TurboLinux10 uses 2.6.0-test5, which we do not support, so special case it, + * 2.6.0 with tl_kernel_version_h is 2.6.0-pre5... + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) || \ + (LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 0) && defined(__tl_kernel_version_h__)) + bridge->pt.data = bridge->sk; +#else + bridge->pt.af_packet_priv = bridge->sk; +#endif + bridge->enabledPromisc = FALSE; + bridge->warnPromisc = FALSE; + dev_add_pack(&bridge->pt); + dev_unlock_list(); + + /* + * Put in promiscuous mode if need be. + */ + + down(&vnetStructureSemaphore); + if (VNetGetAttachedPorts(&bridge->port.jack)) { + VNetBridgeStartPromisc(bridge, rtnlLock); + } + up(&vnetStructureSemaphore); + + /* + * Finish up + */ + + LOG(1, (KERN_DEBUG "bridge-%s: up\n", bridge->name)); + + /* + * Return + */ + +out: + if (retval != 0) { + if (bridge->sk != NULL) { + sk_free(bridge->sk); + bridge->sk = NULL; + } + bridge->dev = NULL; + } + return retval; +} + + +/* + *---------------------------------------------------------------------- + * + * VNetBridgeDown -- + * + * Bring a bridge down. Stops promiscuous mode, removes the + * packet handler from the network stack, and frees the + * socket. + * + * Results: + * None. + * + * Side effects: + * Bridging is brought down. + * + *---------------------------------------------------------------------- + */ + +void +VNetBridgeDown(VNetBridge *bridge, // IN: bridge + Bool rtnlLock) // IN: acquire RTNL lock +{ + if (bridge->dev == NULL) { + LOG(0, (KERN_NOTICE "bridge-%s: already down\n", bridge->name)); + return; + } + + VNetBridgeStopPromisc(bridge, rtnlLock); + if (bridge->smac){ + SMAC_SetMac(bridge->smac, NULL); + } + bridge->dev = NULL; + dev_remove_pack(&bridge->pt); + sk_free(bridge->sk); + bridge->sk = NULL; + LOG(1, (KERN_DEBUG "bridge-%s: down\n", bridge->name)); +} + + +/* + *----------------------------------------------------------------------------- + * + * VNetBridgeNotify -- + * + * Callback on peer device state change. The function brings + * the bridge up/down in response to changes in the peer device. + * + * Results: + * NOTIFY_DONE + * + * Side effects: + * Promiscuous mode is changed when bridge brought up/down. + * + *----------------------------------------------------------------------------- + */ + +int +VNetBridgeNotify(struct notifier_block *this, // IN: callback data (bridge) + u_long msg, // IN: type of event + void *data) // IN: device pertaining to event +{ + VNetBridge *bridge = list_entry(this, VNetBridge, notifier); + struct net_device *dev = (struct net_device *) data; + + switch (msg) { + case NETDEV_UNREGISTER: + LOG(2, (KERN_DEBUG "bridge-%s: interface %s is unregistering\n", + bridge->name, dev->name)); + if (dev == bridge->dev) { + /* This should never happen --hpreg */ + LOG(0, (KERN_WARNING "bridge-%s: interface %s unregistered without " + "going down! Disabling the bridge\n", bridge->name, + dev->name)); + VNetBridgeDown(bridge, FALSE); + } + break; + + case NETDEV_DOWN: + LOG(2, (KERN_DEBUG "bridge-%s: interface %s is going down\n", + bridge->name, dev->name)); + if (dev == bridge->dev) { + LOG(1, (KERN_DEBUG "bridge-%s: disabling the bridge\n", + bridge->name)); + VNetBridgeDown(bridge, FALSE); + } + break; + + case NETDEV_UP: + LOG(2, (KERN_DEBUG "bridge-%s: interface %s is going up\n", + bridge->name, dev->name)); + if (bridge->dev == NULL && VNetBridgeDevCompatible(bridge, dev)) { + int errno; + + LOG(1, (KERN_DEBUG "bridge-%s: enabling the bridge\n", bridge->name)); + errno = VNetBridgeUp(bridge, FALSE); + switch (-errno) { + case 0: + break; + + case ENODEV: + LOG(0, (KERN_WARNING "bridge-%s: interface %s not found or not " + "up\n", bridge->name, dev->name)); + break; + + case EINVAL: + LOG(0, (KERN_WARNING "bridge-%s: interface %s is not a valid " + "Ethernet interface\n", bridge->name, dev->name)); + break; + + case ENOMEM: + LOG(0, (KERN_WARNING "bridge-%s: failed to allocate memory\n", + bridge->name)); + break; + + default: + /* This should never happen --hpreg */ + LOG(0, (KERN_WARNING "bridge-%s: failed to enable the bridge to " + "interface %s (error %d)\n", bridge->name, dev->name, + -errno)); + break; + } + } + break; + + default: + LOG(2, (KERN_DEBUG "bridge-%s: interface %s is sending notification " + "0x%lx\n", bridge->name, dev->name, msg)); + break; + } + + return NOTIFY_DONE; +} + + +/* + *---------------------------------------------------------------------- + * + * VNetBridgeComputeHeaderPos -- + * + * Compute correct position for UDP/TCP header. + * + * Results: + * None. + * + * Side effects: + * transport header pointer updated to point to the tcp/udp header. + * + *---------------------------------------------------------------------- + */ + +static INLINE_SINGLE_CALLER void +VNetBridgeComputeHeaderPos(struct sk_buff *skb) // IN: buffer to examine +{ + /* Maybe some kernel gets it right... */ + if (compat_skb_network_header_len(skb)) { + return; + } + switch (be16_to_cpu(skb->protocol)) { + case ETH_P_IP: { + struct iphdr *ipHdr = compat_skb_ip_header(skb); + + compat_skb_set_transport_header(skb, compat_skb_network_offset(skb) + + ipHdr->ihl * 4); + } + return; + default: + LOG(3, (KERN_DEBUG "Unknown EII protocol %04X: csum at %d\n", + be16_to_cpu(skb->protocol), compat_skb_csum_offset(skb))); + break; + } + return; +} + + +/* + * We deal with three types of kernels: + * New kernels: skb_shinfo() has gso_size member, and there is + * skb_gso_segment() helper to split GSO skb into flat ones. + * Older kernels: skb_shinfo() has tso_size member, and there is + * no helper. + * Oldest kernels: without any segmentation offload support. + */ +#if defined(NETIF_F_GSO) || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) +#define VNetBridgeIsGSO(skb) skb_shinfo(skb)->gso_size +#define VNetBridgeGSOSegment(skb) skb_gso_segment(skb, 0) +#elif defined(NETIF_F_TSO) +#define VNetBridgeIsGSO(skb) skb_shinfo(skb)->tso_size + + +/* + *---------------------------------------------------------------------- + * + * VNetBridgeGSOSegment -- + * + * Split a large TCP/IPv4 sk_buff into multiple sk_buffs of + * size skb_shinfo(skb)->tso_size + * Called from VNetBridgeSendLargePacket(). + * + * Results: + * List of skbs created. + * + * Side effects: + * The incoming packet is split into multiple packets. + * + *---------------------------------------------------------------------- + */ + +static struct sk_buff * +VNetBridgeGSOSegment(struct sk_buff *skb) // IN: packet to split +{ + struct sk_buff *segs = NULL; + struct sk_buff **next = &segs; + int bytesPerPacket, bytesLeft; + int macHdrLen, ipHdrLen, tcpHdrLen, allHdrLen; + int curByteOffset; + uint16 ipID; + uint32 seqNo; + + if (((struct ethhdr *)compat_skb_mac_header(skb))->h_proto != htons(ETH_P_IP)) { + return ERR_PTR(-EPFNOSUPPORT); + } + + if (compat_skb_ip_header(skb)->protocol != IPPROTO_TCP) { + return ERR_PTR(-EPROTONOSUPPORT); + } + + macHdrLen = compat_skb_network_header(skb) - compat_skb_mac_header(skb); + ipHdrLen = compat_skb_ip_header(skb)->ihl << 2; + tcpHdrLen = compat_skb_tcp_header(skb)->doff << 2; + allHdrLen = macHdrLen + ipHdrLen + tcpHdrLen; + + ipID = ntohs(compat_skb_ip_header(skb)->id); + seqNo = ntohl(compat_skb_tcp_header(skb)->seq); + + /* Host TCP stack populated this (MSS) for the host NIC driver */ + bytesPerPacket = skb_shinfo(skb)->tso_size; + + bytesLeft = skb->len - allHdrLen; + curByteOffset = allHdrLen; + + while (bytesLeft) { + struct sk_buff *newSkb; + int payloadSize = (bytesLeft < bytesPerPacket) ? bytesLeft : bytesPerPacket; + + newSkb = dev_alloc_skb(payloadSize + allHdrLen + NET_IP_ALIGN); + if (!newSkb) { + while (segs) { + newSkb = segs; + segs = segs->next; + newSkb->next = NULL; + dev_kfree_skb(newSkb); + } + return ERR_PTR(-ENOMEM); + } + skb_reserve(newSkb, NET_IP_ALIGN); + newSkb->dev = skb->dev; + newSkb->protocol = skb->protocol; + newSkb->pkt_type = skb->pkt_type; + newSkb->ip_summed = VM_CHECKSUM_PARTIAL; + + /* + * MAC+IP+TCP copy + * This implies that ALL fields in the IP and TCP headers are copied from + * the original skb. This is convenient: we'll only fix up fields that + * need to be changed below + */ + memcpy(skb_put(newSkb, allHdrLen), skb->data, allHdrLen); + + /* Fix up pointers to different layers */ + compat_skb_reset_mac_header(newSkb); + compat_skb_set_network_header(newSkb, macHdrLen); + compat_skb_set_transport_header(newSkb, macHdrLen + ipHdrLen); + + /* Payload copy */ + skb_copy_bits(skb, curByteOffset, compat_skb_tail_pointer(newSkb), payloadSize); + skb_put(newSkb, payloadSize); + + curByteOffset+=payloadSize; + bytesLeft -= payloadSize; + + /* Fix up IP hdr */ + compat_skb_ip_header(newSkb)->tot_len = htons(payloadSize + tcpHdrLen + ipHdrLen); + compat_skb_ip_header(newSkb)->id = htons(ipID); + compat_skb_ip_header(newSkb)->check = 0; + /* Recompute new IP checksum */ + compat_skb_ip_header(newSkb)->check = + ip_fast_csum(compat_skb_network_header(newSkb), + compat_skb_ip_header(newSkb)->ihl); + + /* Fix up TCP hdr */ + compat_skb_tcp_header(newSkb)->seq = htonl(seqNo); + /* Clear FIN/PSH if not last packet */ + if (bytesLeft > 0) { + compat_skb_tcp_header(newSkb)->fin = 0; + compat_skb_tcp_header(newSkb)->psh = 0; + } + /* Recompute partial TCP checksum */ + compat_skb_tcp_header(newSkb)->check = + ~csum_tcpudp_magic(compat_skb_ip_header(newSkb)->saddr, + compat_skb_ip_header(newSkb)->daddr, + payloadSize+tcpHdrLen, IPPROTO_TCP, 0); + + /* Offset of field */ + newSkb->csum = offsetof(struct tcphdr, check); + + /* Join packet to the list of segments */ + *next = newSkb; + next = &newSkb->next; + + /* Bump up our counters */ + ipID++; + seqNo += payloadSize; + + } + return segs; +} +#else +#define VNetBridgeIsGSO(skb) (0) +#define VNetBridgeGSOSegment(skb) ERR_PTR(-ENOSYS) +#endif + + +/* + *---------------------------------------------------------------------- + * + * VNetBridgeSendLargePacket -- + * + * Split and send a large TCP/IPv4 sk_buff into multiple sk_buffs which + * fits on wire. Called from VNetBridgeReceiveFromDev(), which is a + * protocol handler called from the bottom half, so steady as she + * goes... + * + * skb passed in is deallocated by function. + * + * Results: + * None. + * + * Side effects: + * The incoming packet is split into multiple packets and sent to the + * vnet. + * + *---------------------------------------------------------------------- + */ + +void +VNetBridgeSendLargePacket(struct sk_buff *skb, // IN: packet to split + VNetBridge *bridge) // IN: bridge +{ + struct sk_buff *segs; + + segs = VNetBridgeGSOSegment(skb); + dev_kfree_skb(skb); + if (IS_ERR(segs)) { + LOG(1, (KERN_DEBUG "bridge-%s: cannot segment packet: error %ld\n", + bridge->name, PTR_ERR(segs))); + return; + } + + while (segs) { + struct sk_buff *newSkb; + + newSkb = segs; + segs = newSkb->next; + newSkb->next = NULL; + /* Send it along */ + skb = newSkb; + VNetSend(&bridge->port.jack, newSkb); + } +} + + +/* + *---------------------------------------------------------------------- + * + * VNetBridgeReceiveFromDev -- + * + * Receive a packet from a bridged peer device + * + * This is called from the bottom half. Must be careful. + * + * Results: + * errno. + * + * Side effects: + * A packet may be sent to the vnet. + * + *---------------------------------------------------------------------- + */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14) && \ + !defined(VMW_TL10S64_WORKAROUND) +int +VNetBridgeReceiveFromDev(struct sk_buff *skb, // IN: packet to receive + struct net_device *dev, // IN: unused + struct packet_type *pt) // IN: pt (pointer to bridge) +#else +int +VNetBridgeReceiveFromDev(struct sk_buff *skb, // IN: packet to receive + struct net_device *dev, // IN: unused + struct packet_type *pt, // IN: pt (pointer to bridge) + struct net_device *real_dev) // IN: real device, unused +#endif +{ + VNetBridge *bridge = list_entry(pt, VNetBridge, pt); + int i; + unsigned long flags; + + if (bridge->dev == NULL) { + LOG(3, (KERN_DEBUG "bridge-%s: received %d closed\n", + bridge->name, (int) skb->len)); + dev_kfree_skb(skb); + return -EIO; // value is ignored anyway + } + + /* + * Check is this is a packet that we sent up to the host, and if + * so then don't bother to receive the packet. + */ + + spin_lock_irqsave(&bridge->historyLock, flags); + for (i = 0; i < VNET_BRIDGE_HISTORY; i++) { + struct sk_buff *s = bridge->history[i]; + if (s != NULL && + (s == skb || SKB_IS_CLONE_OF(skb, s))) { + bridge->history[i] = NULL; + spin_unlock_irqrestore(&bridge->historyLock, flags); + dev_kfree_skb(s); + LOG(3, (KERN_DEBUG "bridge-%s: receive %d self %d\n", + bridge->name, (int) skb->len, i)); + dev_kfree_skb(skb); + return 0; + } + } + spin_unlock_irqrestore(&bridge->historyLock, flags); + +# if LOGLEVEL >= 4 + { + struct timeval now; + do_gettimeofday(&now); + LOG(3, (KERN_DEBUG "bridge-%s: time %d\n", + bridge->name, + (int)((now.tv_sec * 1000000 + now.tv_usec) + - (vnetTime.tv_sec * 1000000 + vnetTime.tv_usec)))); + } +# endif + + if (bridge->smac) { + if (VNetCallSMACFunc(bridge->smac, &skb, compat_skb_mac_header(skb), + SMAC_CheckPacketFromHost) != + PacketStatusForwardPacket) { + LOG(4, (KERN_NOTICE "bridge-%s: packet dropped .\n", + bridge->name)); + return 0; + } + } + +#ifdef KERNEL_2_3_15 + skb = skb_share_check(skb, GFP_ATOMIC); + if (!skb) { + return 0; + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 4) + /* + * Unbelievable... Caller sets h.raw = nh.raw before invoking us... + */ + VNetBridgeComputeHeaderPos(skb); +#endif +#endif + + skb_push(skb, skb->data - compat_skb_mac_header(skb)); + LOG(3, (KERN_DEBUG "bridge-%s: receive %d\n", + bridge->name, (int) skb->len)); + + /* + * If this is a large packet, chop chop chop (if supported)... + */ + if (VNetBridgeIsGSO(skb)) { + VNetBridgeSendLargePacket(skb, bridge); + } else { + VNetSend(&bridge->port.jack, skb); + } + + return 0; +} + + +/* + *---------------------------------------------------------------------- + * + * VNetBridgeProcRead -- + * + * Callback for read operation on this bridge entry in vnets proc fs. + * + * Results: + * Length of read operation. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +VNetBridgeProcRead(char *page, // IN/OUT: buffer to write into + char **start, // OUT: 0 if file < 4k, else offset into page + off_t off, // IN: (unused) offset of read into the file + int count, // IN: (unused) maximum number of bytes to read + int *eof, // OUT: TRUE if there is nothing more to read + void *data) // IN: client data - pointer to bridge +{ + VNetBridge *bridge = (VNetBridge*)data; + int len = 0; + + if (!bridge) { + return len; + } + + len += VNetPrintPort(&bridge->port, page+len); + + len += sprintf(page+len, "dev %s ", bridge->name); + + len += sprintf(page+len, "\n"); + + *start = 0; + *eof = 1; + return len; +} diff -ruN vmnet-only-patched/compat_semaphore.h vmnet-only-refixed/compat_semaphore.h --- vmnet-only-patched/compat_semaphore.h 2009-07-08 16:21:02.000000000 +0300 +++ vmnet-only-refixed/compat_semaphore.h 2008-10-20 16:35:18.000000000 +0300 @@ -6,11 +6,7 @@ # define __COMPAT_SEMAPHORE_H__ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) #include -#else -#include -#endif /* diff -ruN vmnet-only-patched/compat_wait.h vmnet-only-refixed/compat_wait.h --- vmnet-only-patched/compat_wait.h 2009-07-08 16:21:02.000000000 +0300 +++ vmnet-only-refixed/compat_wait.h 2009-04-21 18:16:24.000000000 +0300 @@ -37,14 +37,12 @@ * /dev/epoll interface was added. It was backported to the * 2.4.20-wolk4.0s. */ - -#ifdef VMW_HAVE_EPOLL // { +#if VMW_HAVE_EPOLL // { #define compat_poll_wqueues struct poll_wqueues #else // } { #define compat_poll_wqueues poll_table #endif // } - -#ifdef VMW_HAVE_EPOLL // { +#if VMW_HAVE_EPOLL // { /* If prototype does not match, build will abort here */ extern void poll_initwait(compat_poll_wqueues *); diff -ruN vmnet-only-patched/filter.c vmnet-only-refixed/filter.c --- vmnet-only-patched/filter.c 2009-07-08 16:21:02.000000000 +0300 +++ vmnet-only-refixed/filter.c 2008-07-24 18:21:23.000000000 +0300 @@ -13,11 +13,9 @@ #include "compat_skbuff.h" #include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) -# define NF_IP_LOCAL_OUT NF_INET_LOCAL_OUT -# define NF_IP_LOCAL_IN NF_INET_LOCAL_IN -# define NF_IP_POST_ROUTING NF_INET_POST_ROUTING -#endif +#define NF_IP_LOCAL_OUT NF_INET_LOCAL_OUT +#define NF_IP_LOCAL_IN NF_INET_LOCAL_IN +#define NF_IP_POST_ROUTING NF_INET_POST_ROUTING /* * All this makes sense only if NETFILTER support is configured in our kernel. diff -ruN vmnet-only-patched/Makefile vmnet-only-refixed/Makefile --- vmnet-only-patched/Makefile 2009-07-08 16:21:02.000000000 +0300 +++ vmnet-only-refixed/Makefile 2007-11-28 12:19:12.000000000 +0200 @@ -15,7 +15,7 @@ VM_UNAME = $(shell uname -r) # Header directory for the running kernel -HEADER_DIR = ${KERNEL_DIR}/include +HEADER_DIR = /lib/modules/$(VM_UNAME)/build/include BUILD_DIR = $(HEADER_DIR)/.. diff -ruN vmnet-only-patched/Makefile.kernel vmnet-only-refixed/Makefile.kernel --- vmnet-only-patched/Makefile.kernel 2009-07-08 16:21:02.000000000 +0300 +++ vmnet-only-refixed/Makefile.kernel 2009-04-21 18:27:50.000000000 +0300 @@ -12,7 +12,8 @@ INCLUDE := -I$(SRCROOT) EXTRA_CFLAGS := $(CC_OPTS) $(INCLUDE) -EXTRA_CFLAGS += $(call vm_check_build, $(SRCROOT)/epoll.c, -DVMW_HAVE_EPOLL, ) +#EXTRA_CFLAGS += $(call vm_check_build, $(SRCROOT)/epoll.c, -DVMW_HAVE_EPOLL, ) +EXTRA_CFLAGS += -I$(HEADER_DIR) -DVMW_HAVE_EPOLL EXTRA_CFLAGS += $(call vm_check_build, $(SRCROOT)/socket.c, -DVMW_HAVE_SK_WMEM_ALLOC, ) EXTRA_CFLAGS += $(call vm_check_build, $(SRCROOT)/sk_alloc.c,-DVMW_HAVE_SK_ALLOC_WITH_PROTO, ) EXTRA_CFLAGS += $(call vm_check_build, $(SRCROOT)/netdev_has_net.c,-DVMW_NETDEV_HAS_NET, ) diff -ruN vmnet-only-patched/Makefile.normal vmnet-only-refixed/Makefile.normal --- vmnet-only-patched/Makefile.normal 2009-07-08 16:21:02.000000000 +0300 +++ vmnet-only-refixed/Makefile.normal 2009-04-21 18:28:04.000000000 +0300 @@ -37,7 +37,8 @@ | sed -n -e 's!^APATH!-I$(HEADER_DIR)/asm!p') CC_OPTS += -DVME_DEFAULT=$(VMWARE_VER) -CC_OPTS += $(call vm_check_build, $(SRCROOT)/epoll.c, -DVMW_HAVE_EPOLL, ) +#CC_OPTS += $(call vm_check_build, $(SRCROOT)/epoll.c, -DVMW_HAVE_EPOLL, ) +EXTRA_CFLAGS += -I$(HEADER_DIR) -DVMW_HAVE_EPOLL CC_OPTS += $(call vm_check_build, $(SRCROOT)/socket.c, -DVMW_HAVE_SK_WMEM_ALLOC, ) CC_OPTS += $(call vm_check_build, $(SRCROOT)/sk_alloc.c,-DVMW_HAVE_SK_ALLOC_WITH_PROTO, ) CC_OPTS += $(call vm_check_build, $(SRCROOT)/netdev_has_net.c,-DVMW_NETDEV_HAS_NET, ) diff -ruN vmnet-only-patched/Module.markers vmnet-only-refixed/Module.markers --- vmnet-only-patched/Module.markers 1970-01-01 02:00:00.000000000 +0200 +++ vmnet-only-refixed/Module.markers 2008-10-20 16:35:37.000000000 +0300 @@ -0,0 +1,4 @@ +core_marker_format vmlinux name %s format %s +kernel_sched_schedule vmlinux prev_pid %d next_pid %d prev_state %ld ## rq %p prev %p next %p +kernel_sched_wakeup vmlinux pid %d state %ld ## rq %p task %p rq->curr %p +kernel_sched_wakeup_new vmlinux pid %d state %ld ## rq %p task %p rq->curr %p diff -ruN vmnet-only-patched/modules.order vmnet-only-refixed/modules.order --- vmnet-only-patched/modules.order 1970-01-01 02:00:00.000000000 +0200 +++ vmnet-only-refixed/modules.order 2009-04-21 18:30:09.000000000 +0300 @@ -0,0 +1 @@ +kernel//home/kang/tmp/vmware-update-2.6.27-5.5.7-2/vmnet-only/vmnet.ko diff -ruN vmnet-only-patched/netif.c vmnet-only-refixed/netif.c --- vmnet-only-patched/netif.c 2009-07-08 16:21:02.000000000 +0300 +++ vmnet-only-refixed/netif.c 2009-04-21 18:03:24.000000000 +0300 @@ -310,7 +310,7 @@ goto out; } - dev->priv = netIf; + dev->ml_priv = netIf; netIf->dev = dev; memcpy(dev->dev_addr, netIf->port.paddr, sizeof netIf->port.paddr); @@ -552,7 +552,7 @@ VNetNetifStartXmit(struct sk_buff *skb, // IN: struct net_device *dev) // IN: { - VNetNetIF *netIf = (VNetNetIF*)dev->priv; + VNetNetIF *netIf = (VNetNetIF*)dev->ml_priv; if(skb == NULL) { return 0; @@ -604,7 +604,7 @@ VNetNetifSetMAC(struct net_device *dev, // IN: void *p) // IN: { - VNetNetIF *netIf = (VNetNetIF*)dev->priv; + VNetNetIF *netIf = (VNetNetIF*)dev->ml_priv; struct sockaddr const *addr = p; if (!VMX86_IS_STATIC_MAC(addr->sa_data)) { return -EINVAL; @@ -661,7 +661,7 @@ struct net_device_stats * VNetNetifGetStats(struct net_device *dev) // IN: { - VNetNetIF *netIf = (VNetNetIF*)dev->priv; + VNetNetIF *netIf = (VNetNetIF*)dev->ml_priv; return &(netIf->stats); } diff -ruN vmnet-only-patched/vmnetInt.h vmnet-only-refixed/vmnetInt.h --- vmnet-only-patched/vmnetInt.h 2009-07-08 16:21:02.000000000 +0300 +++ vmnet-only-refixed/vmnetInt.h 2008-07-24 18:31:28.000000000 +0300 @@ -63,11 +63,7 @@ # define dev_lock_list() read_lock(&dev_base_lock) # define dev_unlock_list() read_unlock(&dev_base_lock) # ifdef VMW_NETDEV_HAS_NET -# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) -# define DEV_GET(x) __dev_get_by_name((x)->internalDev->nd_net, (x)->name) -# else # define DEV_GET(x) __dev_get_by_name(dev_net((x)->internalDev), (x)->name) -# endif # else # define DEV_GET(x) __dev_get_by_name((x)->name) # endif @@ -91,13 +87,8 @@ #ifdef VMW_NETDEV_HAS_NET extern struct proto vmnet_proto; -# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) # define compat_sk_alloc(_bri, _pri) sk_alloc(dev_net((_bri)->internalDev), \ PF_NETLINK, _pri, &vmnet_proto) -# else -# define compat_sk_alloc(_bri, _pri) sk_alloc((_bri)->internalDev->nd_net, \ - PF_NETLINK, _pri, &vmnet_proto) -# endif #elif defined(VMW_HAVE_SK_ALLOC_WITH_PROTO) extern struct proto vmnet_proto; # define compat_sk_alloc(_bri, _pri) sk_alloc(PF_NETLINK, _pri, &vmnet_proto, 1) diff -ruN vmnet-only-patched/vmnetInt.h.orig vmnet-only-refixed/vmnetInt.h.orig --- vmnet-only-patched/vmnetInt.h.orig 1970-01-01 02:00:00.000000000 +0200 +++ vmnet-only-refixed/vmnetInt.h.orig 2007-11-28 12:25:06.000000000 +0200 @@ -0,0 +1,144 @@ +/* ********************************************************** + * Copyright 1998 VMware, Inc. All rights reserved. -- VMware Confidential + * **********************************************************/ + +#ifndef __VMNETINT_H__ +#define __VMNETINT_H__ + + +#define INCLUDE_ALLOW_MODULE +#include "includeCheck.h" +#include "driver-config.h" + + +/* + * Hide all kernel compatibility stuff in those macros + */ + +/* All kernels above 2.6.23 have net namespaces. */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && !defined(VMW_NETDEV_HAS_NET) +# define VMW_NETDEV_HAS_NET +#endif + +/* All kernels above 2.6.23 have skb argument in nf_hookfn. */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && !defined(VMW_NFHOOK_USES_SKB) +# define VMW_NFHOOK_USES_SKB +#endif + + +#ifdef KERNEL_2_4_0 +# define compat_fop_set_owner(_pFop) do { \ + (_pFop)->owner = THIS_MODULE; \ +} while (0) +# define compat_mod_inc_refcount +# define compat_mod_dec_refcount +#else +# define compat_fop_set_owner(_pFop) +# define compat_mod_inc_refcount do { \ + MOD_INC_USE_COUNT; \ +} while (0) +# define compat_mod_dec_refcount do { \ + MOD_DEC_USE_COUNT; \ +} while (0) +#endif + + +#ifdef skb_shinfo +# define SKB_IS_CLONE_OF(clone, skb) ( \ + skb_shinfo(clone) == skb_shinfo(skb) \ + ) +#else +# define SKB_IS_CLONE_OF(clone, skb) ( \ + skb_datarefp(clone) == skb_datarefp(skb) \ + ) +#endif +#define DEV_QUEUE_XMIT(skb, dev, pri) ( \ + (skb)->dev = (dev), \ + (skb)->priority = (pri), \ + compat_skb_reset_mac_header(skb), \ + compat_skb_set_network_header(skb, sizeof (struct ethhdr)), \ + dev_queue_xmit(skb) \ + ) +#ifdef KERNEL_2_3_15 +# define dev_lock_list() read_lock(&dev_base_lock) +# define dev_unlock_list() read_unlock(&dev_base_lock) +# ifdef VMW_NETDEV_HAS_NET +# define DEV_GET(x) __dev_get_by_name((x)->internalDev->nd_net, (x)->name) +# else +# define DEV_GET(x) __dev_get_by_name((x)->name) +# endif +#else +# define DEV_GET(x) dev_get((x)->name) +#endif + + +/* + * Various fields (including 'dead') of struct sock are replaced with the + * 'flags' bitfield in 2.5.65 --hpreg + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 65) +# define SET_SK_DEAD(_sk, _val) (_sk)->dead = (_val) +#else +# define SET_SK_DEAD(_sk, _val) sock_valbool_flag(_sk, SOCK_DEAD, _val) +#endif + + +#ifdef VMW_NETDEV_HAS_NET +extern struct proto vmnet_proto; +# define compat_sk_alloc(_bri, _pri) sk_alloc((_bri)->internalDev->nd_net, \ + PF_NETLINK, _pri, &vmnet_proto) +#elif defined(VMW_HAVE_SK_ALLOC_WITH_PROTO) +extern struct proto vmnet_proto; +# define compat_sk_alloc(_bri, _pri) sk_alloc(PF_NETLINK, _pri, &vmnet_proto, 1) +#elif defined(KERNEL_2_5_5) +# define compat_sk_alloc(_bri, _pri) sk_alloc(PF_NETLINK, _pri, 1, NULL) +#else +# define compat_sk_alloc(_bri, _pri) sk_alloc(0, _pri, 1) +#endif + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +# define fileTraversalLock(lock) spin_lock(lock) +# define fileTraversalUnLock(lock) spin_unlock(lock) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +# define fileTraversalLock(lock) read_lock(lock) +# define fileTraversalUnLock(lock) read_unlock(lock) +#else //2.2 kernels +# define fileTraversalLock(lock) lock_kernel() +# define fileTraversalUnLock(lock) unlock_kernel() +#endif + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +# define taskLock(lock) task_lock(lock) +# define taskUnLock(lock) task_unlock(lock) +#else //2.2 kernels +# define taskLock(lock) lock_kernel() +# define taskUnLock(lock) unlock_kernel() +#endif + + +/* + * Use CHECKSUM_HW for old kernels, if they have CHECKSUM_HW. Use CHECKSUM_PARTIAL for + * new ones even if CHECKSUM_HW is defined. We do not do decision based on kernel version + * only as CHECKSUM_PARTIAL was in mm tree for some time already, and we do not test + * for CHECKSUM_PARTIAL existence as it may get converted to enum in future. + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) && defined(CHECKSUM_HW) +# define VM_CHECKSUM_PARTIAL CHECKSUM_HW +#else +# define VM_CHECKSUM_PARTIAL CHECKSUM_PARTIAL +#endif + + +/* + * The "owner" field in nf_hook_ops got added in 2.5.69 + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 69) +# define compat_nf_hook_owner .owner = THIS_MODULE, +#else +# define compat_nf_hook_owner +#endif + + +#endif /* __VMNETINT_H__ */