Hi Apologies for this size of this posting.
I'm trying to get vmplayer installed, its failing to build just one of it
modules, vmnet
any ideas where to look ?
2012-01-26T16:52:42.943Z| vthread-3| I120: Trying to find a suitable PBM set
for kernel 3.2.0-1-amd64.
2012-01-26T16:52:42.943Z| vthread-3| I120: Validating path
/lib/modules/3.2.0-1-amd64/build/include for
kernel release 3.2.0-1-amd64 2012-01-26T16:52:42.946Z| vthread-3| I120: Your
GCC version: 4.6
2012-01-26T16:52:42.960Z| vthread-3| I120: Your GCC version: 4.6
2012-01-26T16:52:42.989Z| vthread-3| I120: Header path
/lib/modules/3.2.0-1-amd64/build/include for
kernel release 3.2.0-1-amd64 is valid. 2012-01-26T16:52:42.989Z| vthread-3|
I120: Building module vmnet.
2012-01-26T16:52:42.989Z| vthread-3| I120: Extracting the sources of the vmnet
module.
2012-01-26T16:52:43.008Z| vthread-3| I120: Building module with command:
/usr/bin/make -j
-C /tmp/vmware-root/modules/vmnet-only auto-build SUPPORT_SMP=1
HEADER_DIR=/lib/modules/3.2.0-1-amd64/build/include CC=/usr/bin/gcc
GREP=/usr/bin/make IS_GCC_3=no
VMCCVER=4.6 2012-01-26T16:52:44.707Z| vthread-3| I120: Failed to compile module
vmnet!
So next I found the source and compiled and got this result ::-
Using 2.6.x kernel build system.
make -C /lib/modules/3.2.0-1-amd64/build/include/.. SUBDIRS=$PWD SRCROOT=$PWD/.
\
MODULEBUILDDIR= modules
make[1]: Entering directory `/usr/src/linux-headers-3.2.0-1-amd64'
CC [M] /usr/local/src/vmnet-only/driver.o
CC [M] /usr/local/src/vmnet-only/hub.o
CC [M] /usr/local/src/vmnet-only/userif.o
/usr/local/src/vmnet-only/userif.c: In function ‘VNetCsumCopyDatagram’:
/usr/local/src/vmnet-only/userif.c:520:3: error: incompatible type for argument
1 of ‘kmap’
/usr/src/linux-headers-3.2.0-1-common/include/linux/highmem.h:48:21: note:
expected ‘struct page *’ but
argument is of type ‘const struct <anonymous>’
/usr/local/src/vmnet-only/userif.c:523:3: error:
incompatible type for argument 1 of
‘kunmap’ /usr/src/linux-headers-3.2.0-1-common/include/linux/highmem.h:54:20:
note: expected ‘struct
page *’ but argument is of type ‘const struct <anonymous>’ make[4]: ***
[/usr/local/src/vmnet-only/userif.o] Error 1 make[3]: ***
[_module_/usr/local/src/vmnet-only] Error 2
make[2]: *** [sub-make] Error 2 make[1]: *** [all] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.2.0-1-amd64'
make: *** [vmnet.ko] Error 2
here's userif.c
/*********************************************************
* Copyright (C) 1998 VMware, Inc. All rights reserved.
*
* 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 version 2 and no later version.
*
* 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.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#include "driver-config.h"
#define EXPORT_SYMTAB
#define __KERNEL_SYSCALLS__
#include <linux/file.h>
#include <linux/highmem.h>
#include <linux/if_ether.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/mm.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/sockios.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/version.h>
#include <linux/wait.h>
#include <net/checksum.h>
#include <net/sock.h>
#include <asm/io.h>
#include "vnetInt.h"
#include "compat_skbuff.h"
#include "vmnetInt.h"
#include "vm_atomic.h"
#include "vm_assert.h"
#include "monitorAction_exported.h"
typedef struct VNetUserIFStats {
unsigned read;
unsigned written;
unsigned queued;
unsigned droppedDown;
unsigned droppedMismatch;
unsigned droppedOverflow;
unsigned droppedLargePacket;
} VNetUserIFStats;
typedef struct VNetUserIF {
VNetPort port;
struct sk_buff_head packetQueue;
uint32* pollPtr;
MonitorActionIntr *actionIntr;
uint32 pollMask;
MonitorIdemAction actionID;
uint32* recvClusterCount;
wait_queue_head_t waitQueue;
struct page* actPage;
struct page* pollPage;
struct page* recvClusterPage;
VNetUserIFStats stats;
VNetEvent_Sender *eventSender;
} VNetUserIF;
static void VNetUserIfUnsetupNotify(VNetUserIF *userIf);
static int VNetUserIfSetupNotify(VNetUserIF *userIf, VNet_Notify *vn);
static int VNetUserIfSetUplinkState(VNetPort *port, uint8 linkUp);
/*
*-----------------------------------------------------------------------------
*
* UserifLockPage --
*
* Lock in core the physical page associated to a valid virtual
* address.
*
* Results:
* The page structure on success
* NULL on failure: memory pressure. Retry later
*
* Side effects:
* Loads page into memory
*
*-----------------------------------------------------------------------------
*/
static INLINE struct page *
UserifLockPage(VA addr) // IN
{
struct page *page = NULL;
int retval;
down_read(¤t->mm->mmap_sem);
retval = get_user_pages(current, current->mm, addr,
1, 1, 0, &page, NULL);
up_read(¤t->mm->mmap_sem);
if (retval != 1) {
return NULL;
}
return page;
}
/*
*-----------------------------------------------------------------------------
*
* VNetUserIfMapUint32Ptr --
*
* Maps a portion of user-space memory into the kernel.
*
* Results:
* 0 on success
* < 0 on failure: the actual value determines the type of failure
*
* Side effects:
* Might sleep.
*
*-----------------------------------------------------------------------------
*/
static INLINE int
VNetUserIfMapPtr(VA uAddr, // IN: pointer to user memory
size_t size, // IN: size of data
struct page **p, // OUT: locked page
void **ptr) // OUT: kernel mapped pointer
{
if (!access_ok(VERIFY_WRITE, (void *)uAddr, size) ||
(((uAddr + size - 1) & ~(PAGE_SIZE - 1)) !=
(uAddr & ~(PAGE_SIZE - 1)))) {
return -EINVAL;
}
*p = UserifLockPage(uAddr);
if (*p == NULL) {
return -EAGAIN;
}
*ptr = (uint8 *)kmap(*p) + (uAddr & (PAGE_SIZE - 1));
return 0;
}
static INLINE int
VNetUserIfMapUint32Ptr(VA uAddr, // IN: pointer to user memory
struct page **p, // OUT: locked page
uint32 **ptr) // OUT: kernel mapped pointer
{
return VNetUserIfMapPtr(uAddr, sizeof **ptr, p, (void **)ptr);
}
/*
*-----------------------------------------------------------------------------
*
* VNetUserIfSetupNotify --
*
* Sets up notification by filling in pollPtr, actPtr, and recvClusterCount
* fields.
*
* Results:
* 0 on success
* < 0 on failure: the actual value determines the type of failure
*
* Side effects:
* Fields pollPtr, actPtr, recvClusterCount, pollPage, actPage, and
* recvClusterPage are filled in VNetUserIf structure.
*
*-----------------------------------------------------------------------------
*/
static INLINE int
VNetUserIfSetupNotify(VNetUserIF *userIf, // IN
VNet_Notify *vn) // IN
{
int retval;
if (userIf->pollPtr || userIf->actionIntr || userIf->recvClusterCount) {
LOG(0, (KERN_DEBUG "vmnet: Notification mechanism already active\n"));
return -EBUSY;
}
if ((retval = VNetUserIfMapUint32Ptr((VA)vn->pollPtr, &userIf->pollPage,
&userIf->pollPtr)) < 0) {
return retval;
}
if ((retval = VNetUserIfMapPtr((VA)vn->actPtr, sizeof *userIf->actionIntr,
&userIf->actPage,
(void **)&userIf->actionIntr)) < 0) {
VNetUserIfUnsetupNotify(userIf);
return retval;
}
if ((retval = VNetUserIfMapUint32Ptr((VA)vn->recvClusterPtr,
&userIf->recvClusterPage,
&userIf->recvClusterCount)) < 0) {
VNetUserIfUnsetupNotify(userIf);
return retval;
}
userIf->pollMask = vn->pollMask;
userIf->actionID = vn->actionID;
return 0;
}
/*
*----------------------------------------------------------------------
*
* VNetUserIfUnsetupNotify --
*
* Destroys permanent mapping for notify structure provided by user.
*
* Results:
* None.
*
* Side effects:
* Fields pollPtr, actPtr, recvClusterCount, etc. in VNetUserIf
* structure are cleared.
*
*----------------------------------------------------------------------
*/
static void
VNetUserIfUnsetupNotify(VNetUserIF *userIf) // IN
{
if (userIf->pollPage) {
kunmap(userIf->pollPage);
put_page(userIf->pollPage);
} else {
LOG(0, (KERN_DEBUG "vmnet: pollPtr was already deactivated\n"));
}
if (userIf->actPage) {
kunmap(userIf->actPage);
put_page(userIf->actPage);
} else {
LOG(0, (KERN_DEBUG "vmnet: actPtr was already deactivated\n"));
}
if (userIf->recvClusterPage) {
kunmap(userIf->recvClusterPage);
put_page(userIf->recvClusterPage);
} else {
LOG(0, (KERN_DEBUG "vmnet: recvClusterPtr was already deactivated\n"));
}
userIf->pollPtr = NULL;
userIf->pollPage = NULL;
userIf->actionIntr = NULL;
userIf->actPage = NULL;
userIf->recvClusterCount = NULL;
userIf->recvClusterPage = NULL;
userIf->pollMask = 0;
userIf->actionID = -1;
}
/*
*----------------------------------------------------------------------
*
* VNetUserIfFree --
*
* Free the user interface port.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static void
VNetUserIfFree(VNetJack *this) // IN
{
VNetUserIF *userIf = (VNetUserIF*)this;
struct sk_buff *skb;
for (;;) {
skb = skb_dequeue(&userIf->packetQueue);
if (skb == NULL) {
break;
}
dev_kfree_skb(skb);
}
if (userIf->pollPtr) {
VNetUserIfUnsetupNotify(userIf);
}
if (userIf->eventSender) {
VNetEvent_DestroySender(userIf->eventSender);
}
if (this->procEntry) {
VNetProc_RemoveEntry(this->procEntry);
}
kfree(userIf);
}
/*
*----------------------------------------------------------------------
*
* VNetUserIfReceive --
*
* This jack is receiving a packet. Take appropriate action.
*
* Results:
* None.
*
* Side effects:
* Frees skb.
*
*----------------------------------------------------------------------
*/
static void
VNetUserIfReceive(VNetJack *this, // IN
struct sk_buff *skb) // IN
{
VNetUserIF *userIf = (VNetUserIF*)this->private;
uint8 *dest = SKB_2_DESTMAC(skb);
if (!UP_AND_RUNNING(userIf->port.flags)) {
userIf->stats.droppedDown++;
goto drop_packet;
}
if (!VNetPacketMatch(dest,
userIf->port.paddr,
(const uint8 *)userIf->port.exactFilter,
userIf->port.exactFilterLen,
userIf->port.ladrf,
userIf->port.flags)) {
userIf->stats.droppedMismatch++;
goto drop_packet;
}
if (skb_queue_len(&userIf->packetQueue) >= VNET_MAX_QLEN) {
userIf->stats.droppedOverflow++;
goto drop_packet;
}
if (skb->len > ETHER_MAX_QUEUED_PACKET) {
userIf->stats.droppedLargePacket++;
goto drop_packet;
}
userIf->stats.queued++;
skb_queue_tail(&userIf->packetQueue, skb);
if (userIf->pollPtr) {
*userIf->pollPtr |= userIf->pollMask;
if (skb_queue_len(&userIf->packetQueue) >= (*userIf->recvClusterCount)) {
MonitorAction_SetBits(userIf->actionIntr, userIf->actionID);
}
}
wake_up(&userIf->waitQueue);
return;
drop_packet:
dev_kfree_skb(skb);
}
/*
*----------------------------------------------------------------------
*
* VNetUserIfProcRead --
*
* Callback for read operation on this userif entry in vnets proc fs.
*
* Results:
* Length of read operation.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static int
VNetUserIfProcRead(char *page, // IN/OUT: buffer to write into
char **start, // OUT: 0 if file < 4k, else offset into
// page
off_t off, // IN: offset of read into the file
int count, // IN: maximum number of bytes to read
int *eof, // OUT: TRUE if there is nothing more to
// read
void *data) // IN: client data - not used
{
VNetUserIF *userIf = (VNetUserIF*)data;
int len = 0;
if (!userIf) {
return len;
}
len += VNetPrintPort(&userIf->port, page+len);
len += sprintf(page+len, "read %u written %u queued %u ",
userIf->stats.read,
userIf->stats.written,
userIf->stats.queued);
len += sprintf(page+len,
"dropped.down %u dropped.mismatch %u "
"dropped.overflow %u dropped.largePacket %u",
userIf->stats.droppedDown,
userIf->stats.droppedMismatch,
userIf->stats.droppedOverflow,
userIf->stats.droppedLargePacket);
len += sprintf(page+len, "\n");
*start = 0;
*eof = 1;
return len;
}
/*
*----------------------------------------------------------------------
*
* VNetCopyDatagram --
*
* Copy part of datagram to userspace.
*
* Results:
* zero on success,
* -EFAULT if buffer is an invalid area
*
* Side effects:
* Data copied to the buffer.
*
*----------------------------------------------------------------------
*/
static int
VNetCopyDatagram(const struct sk_buff *skb, // IN: skb to copy
char *buf, // OUT: where to copy data
int len) // IN: length
{
struct iovec iov = {
.iov_base = buf,
.iov_len = len,
};
return skb_copy_datagram_iovec(skb, 0, &iov, len);
}
/*
*----------------------------------------------------------------------
*
* VNetCsumCopyDatagram --
*
* Copy part of datagram to userspace doing checksum at same time.
*
* Do not mark this function INLINE, it is recursive! With all gcc's
* released up to now (<= gcc-3.3.1) inlining this function just
* consumes 120 more bytes of code and goes completely mad on
* register allocation, storing almost everything in the memory.
*
* Results:
* folded checksum (non-negative value) on success,
* -EINVAL if offset is too big,
* -EFAULT if buffer is an invalid area
*
* Side effects:
* Data copied to the buffer.
*
*----------------------------------------------------------------------
*/
static int
VNetCsumCopyDatagram(const struct sk_buff *skb, // IN: skb to copy
unsigned int offset, // IN: how many bytes skip
char *buf) // OUT: where to copy data
{
unsigned int csum;
int err = 0;
int len = skb_headlen(skb) - offset;
char *curr = buf;
const skb_frag_t *frag;
/*
* Something bad happened. We skip only up to skb->nh.raw, and skb->nh.raw
* must be in the header, otherwise we are in the big troubles.
*/
if (len < 0) {
return -EINVAL;
}
csum = csum_and_copy_to_user(skb->data + offset, curr, len, 0, &err);
if (err) {
return err;
}
curr += len;
for (frag = skb_shinfo(skb)->frags;
frag != skb_shinfo(skb)->frags + skb_shinfo(skb)->nr_frags;
frag++) {
if (frag->size > 0) {
unsigned int tmpCsum;
const void *vaddr;
vaddr = kmap(frag->page);
tmpCsum = csum_and_copy_to_user(vaddr + frag->page_offset,
curr, frag->size, 0, &err);
kunmap(frag->page);
if (err) {
return err;
}
csum = csum_block_add(csum, tmpCsum, curr - buf);
curr += frag->size;
}
}
for (skb = skb_shinfo(skb)->frag_list; skb != NULL; skb = skb->next) {
int tmpCsum;
tmpCsum = VNetCsumCopyDatagram(skb, 0, curr);
if (tmpCsum < 0) {
return tmpCsum;
}
/* Folded checksum must be inverted before we can use it */
csum = csum_block_add(csum, tmpCsum ^ 0xFFFF, curr - buf);
curr += skb->len;
}
return csum_fold(csum);
}
/*
*----------------------------------------------------------------------
*
* VNetCopyDatagramToUser --
*
* Copy complete datagram to the user space. Fill correct checksum
* into the copied datagram if nobody did it yet.
*
* Results:
* On success byte count, on failure -EFAULT.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static INLINE_SINGLE_CALLER int
VNetCopyDatagramToUser(const struct sk_buff *skb, // IN
char *buf, // OUT
size_t count) // IN
{
if (count > skb->len) {
count = skb->len;
}
/*
* If truncation occurs, we do not bother with checksumming - caller cannot
* verify checksum anyway in such case, and copy without checksum is
* faster.
*/
if (skb->pkt_type == PACKET_OUTGOING && /* Packet must be outgoing */
skb->ip_summed == VM_TX_CHECKSUM_PARTIAL && /* Without checksum */
compat_skb_network_header_len(skb) && /* We must know where header is
*/
skb->len == count) { /* No truncation may occur */
size_t skl;
int csum;
u_int16_t csum16;
skl = compat_skb_csum_start(skb);
if (VNetCopyDatagram(skb, buf, skl)) {
return -EFAULT;
}
csum = VNetCsumCopyDatagram(skb, skl, buf + skl);
if (csum < 0) {
return csum;
}
csum16 = csum;
if (copy_to_user(buf + skl + compat_skb_csum_offset(skb),
&csum16, sizeof csum16)) {
return -EFAULT;
}
} else {
if (VNetCopyDatagram(skb, buf, count)) {
return -EFAULT;
}
}
return count;
}
/*
*----------------------------------------------------------------------
*
* VNetUserIfRead --
*
* The virtual network's read file operation. Reads the next pending
* packet for this network connection.
*
* Results:
* On success the len of the packet received,
* else if no packet waiting and nonblocking 0,
* else -errno.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static int
VNetUserIfRead(VNetPort *port, // IN
struct file *filp, // IN
char *buf, // OUT
size_t count) // IN
{
VNetUserIF *userIf = (VNetUserIF*)port->jack.private;
struct sk_buff *skb;
int ret;
DECLARE_WAITQUEUE(wait, current);
add_wait_queue(&userIf->waitQueue, &wait);
for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
skb = skb_peek(&userIf->packetQueue);
if (skb && (skb->len > count)) {
skb = NULL;
ret = -EMSGSIZE;
break;
}
ret = -EAGAIN;
skb = skb_dequeue(&userIf->packetQueue);
if (userIf->pollPtr) {
if (skb_queue_empty(&userIf->packetQueue)) {
*userIf->pollPtr &= ~userIf->pollMask;
}
}
if (skb != NULL || filp->f_flags & O_NONBLOCK) {
break;
}
ret = -EINTR;
if (signal_pending(current)) {
break;
}
schedule();
}
__set_current_state(TASK_RUNNING);
remove_wait_queue(&userIf->waitQueue, &wait);
if (! skb) {
return ret;
}
userIf->stats.read++;
count = VNetCopyDatagramToUser(skb, buf, count);
dev_kfree_skb(skb);
return count;
}
/*
*----------------------------------------------------------------------
*
* VNetUserIfWrite --
*
* The virtual network's write file operation. Send the raw packet
* to the network.
*
* Results:
* On success the count of bytes written else errno.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static int
VNetUserIfWrite(VNetPort *port, // IN
struct file *filp, // IN
const char *buf, // IN
size_t count) // IN
{
VNetUserIF *userIf = (VNetUserIF*)port->jack.private;
struct sk_buff *skb;
/*
* Check size
*/
if (count < sizeof (struct ethhdr) ||
count > ETHER_MAX_QUEUED_PACKET) {
return -EINVAL;
}
/*
* Required to enforce the downWhenAddrMismatch policy in the MAC
* layer. --hpreg
*/
if (!UP_AND_RUNNING(userIf->port.flags)) {
userIf->stats.droppedDown++;
return count;
}
/*
* Allocate an sk_buff.
*/
skb = dev_alloc_skb(count + 7);
if (skb == NULL) {
// XXX obey O_NONBLOCK?
return -ENOBUFS;
}
skb_reserve(skb, 2);
/*
* Copy the data and send it.
*/
userIf->stats.written++;
if (copy_from_user(skb_put(skb, count), buf, count)) {
dev_kfree_skb(skb);
return -EFAULT;
}
VNetSend(&userIf->port.jack, skb);
return count;
}
/*
*-----------------------------------------------------------------------------
*
* VNetUserIfIoctl --
*
* XXX
*
* Results:
* 0 on success
* -errno on failure
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
static int
VNetUserIfIoctl(VNetPort *port, // IN
struct file *filp, // IN
unsigned int iocmd, // IN
unsigned long ioarg) // IN or OUT depending on iocmd
{
VNetUserIF *userIf = (VNetUserIF*)port->jack.private;
switch (iocmd) {
case SIOCSETNOTIFY:
return -EINVAL;
case SIOCSETNOTIFY2:
#ifdef VMX86_SERVER
/*
* This ioctl always return failure on ESX since we cannot map pages into
* the console os that are from the VMKernel address space which was the
* only case we used this.
*/
return -EINVAL;
#else // VMX86_SERVER
/*
* ORs pollMask into the integer pointed to by ptr if pending packet. Is
* cleared when all packets are drained.
*/
{
int retval;
VNet_Notify vn;
if (copy_from_user(&vn, (void *)ioarg, sizeof vn)) {
return -EFAULT;
}
ASSERT_ON_COMPILE(VNET_NOTIFY_VERSION == 5);
ASSERT_ON_COMPILE(ACTION_EXPORTED_VERSION == 2);
if (vn.version != VNET_NOTIFY_VERSION ||
vn.actionVersion != ACTION_EXPORTED_VERSION ||
vn.actionID / ACTION_WORD_SIZE >= ACTION_NUM_WORDS) {
return -ENOTTY;
}
retval = VNetUserIfSetupNotify(userIf, &vn);
if (retval < 0) {
return retval;
}
break;
}
#endif // VMX86_SERVER
case SIOCUNSETNOTIFY:
if (!userIf->pollPtr) {
/* This should always happen on ESX. */
return -EINVAL;
}
VNetUserIfUnsetupNotify(userIf);
break;
case SIOCSIFFLAGS:
/*
* Drain queue when interface is no longer active. We drain the queue to
* avoid having old packets delivered to the guest when reneabled.
*/
if (!UP_AND_RUNNING(userIf->port.flags)) {
struct sk_buff *skb;
while ((skb = skb_dequeue(&userIf->packetQueue)) != NULL) {
dev_kfree_skb(skb);
}
if (userIf->pollPtr) {
/* Clear the pending bit as no packets are pending at this point. */
*userIf->pollPtr &= ~userIf->pollMask;
}
}
break;
case SIOCINJECTLINKSTATE:
{
uint8 linkUpFromUser;
if (copy_from_user(&linkUpFromUser, (void *)ioarg,
sizeof linkUpFromUser)) {
return -EFAULT;
}
if (linkUpFromUser != 0 && linkUpFromUser != 1) {
return -EINVAL;
}
return VNetUserIfSetUplinkState(port, linkUpFromUser);
}
break;
default:
return -ENOIOCTLCMD;
break;
}
return 0;
}
/*
*----------------------------------------------------------------------
*
* VNetUserIfPoll --
*
* The virtual network's file poll operation.
*
* Results:
* Return POLLIN if success, else sleep and return 0.
* FIXME: Should not we always return POLLOUT?
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static int
VNetUserIfPoll(VNetPort *port, // IN
struct file *filp, // IN
poll_table *wait) // IN
{
VNetUserIF *userIf = (VNetUserIF*)port->jack.private;
poll_wait(filp, &userIf->waitQueue, wait);
if (!skb_queue_empty(&userIf->packetQueue)) {
return POLLIN;
}
return 0;
}
/*
*----------------------------------------------------------------------
*
* VNetUserIfSetUplinkState --
*
* Sends link state change event.
*
* Results:
* 0 on success, errno on failure.
*
* Side effects:
* Link state event is sent to all the event listeners
*
*----------------------------------------------------------------------
*/
int
VNetUserIfSetUplinkState(VNetPort *port, uint8 linkUp)
{
VNetUserIF *userIf;
VNetJack *hubJack;
VNet_LinkStateEvent event;
int retval;
userIf = (VNetUserIF *)port->jack.private;
hubJack = port->jack.peer;
if (hubJack == NULL) {
return -EINVAL;
}
if (userIf->eventSender == NULL) {
/* create event sender */
retval = VNetHub_CreateSender(hubJack, &userIf->eventSender);
if (retval != 0) {
return retval;
}
}
event.header.size = sizeof event;
retval = VNetEvent_GetSenderId(userIf->eventSender, &event.header.senderId);
if (retval != 0) {
LOG(1, (KERN_NOTICE "userif-%d: can't send link state event, "
"getSenderId failed (%d)\n", userIf->port.id, retval));
return retval;
}
event.header.eventId = 0;
event.header.classSet = VNET_EVENT_CLASS_UPLINK;
event.header.type = VNET_EVENT_TYPE_LINK_STATE;
/*
* XXX kind of a hack, vmx will coalesce linkup/down if they come from the
* same adapter.
*/
event.adapter = linkUp;
event.up = linkUp;
retval = VNetEvent_Send(userIf->eventSender, &event.header);
if (retval != 0) {
LOG(1, (KERN_NOTICE "userif-%d: can't send link state event, send "
"failed (%d)\n", userIf->port.id, retval));
}
LOG(0, (KERN_NOTICE "userif-%d: sent link %s event.",
userIf->port.id, linkUp?"up":"down"));
return retval;
}
/*
*----------------------------------------------------------------------
*
* VNetUserIf_Create --
*
* Create a user level port to the wonderful world of virtual
* networking.
*
* Results:
* Errno. Also returns an allocated port to connect to,
* NULL on error.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
VNetUserIf_Create(VNetPort **ret) // OUT
{
VNetUserIF *userIf;
static unsigned id = 0;
int retval;
userIf = kmalloc(sizeof *userIf, GFP_USER);
if (!userIf) {
return -ENOMEM;
}
/*
* Initialize fields.
*/
userIf->port.id = id++;
userIf->port.jack.peer = NULL;
userIf->port.jack.numPorts = 1;
VNetSnprintf(userIf->port.jack.name, sizeof userIf->port.jack.name,
"userif%u", userIf->port.id);
userIf->port.jack.private = userIf;
userIf->port.jack.index = 0;
userIf->port.jack.procEntry = NULL;
userIf->port.jack.free = VNetUserIfFree;
userIf->port.jack.rcv = VNetUserIfReceive;
userIf->port.jack.cycleDetect = NULL;
userIf->port.jack.portsChanged = NULL;
userIf->port.jack.isBridged = NULL;
userIf->pollPtr = NULL;
userIf->actionIntr = NULL;
userIf->recvClusterCount = NULL;
userIf->pollPage = NULL;
userIf->actPage = NULL;
userIf->recvClusterPage = NULL;
userIf->pollMask = 0;
userIf->actionID = -1;
userIf->port.exactFilterLen = 0;
userIf->eventSender = NULL;
/*
* Make proc entry for this jack.
*/
retval = VNetProc_MakeEntry(userIf->port.jack.name, S_IFREG,
&userIf->port.jack.procEntry);
if (retval) {
if (retval == -ENXIO) {
userIf->port.jack.procEntry = NULL;
} else {
kfree(userIf);
return retval;
}
} else {
userIf->port.jack.procEntry->read_proc = VNetUserIfProcRead;
userIf->port.jack.procEntry->data = userIf;
}
/*
* Rest of fields.
*/
userIf->port.flags = IFF_RUNNING;
memset(userIf->port.paddr, 0, sizeof userIf->port.paddr);
memset(userIf->port.ladrf, 0, sizeof userIf->port.ladrf);
memset(userIf->port.exactFilter, 0, sizeof userIf->port.exactFilter);
VNet_MakeMACAddress(&userIf->port);
userIf->port.fileOpRead = VNetUserIfRead;
userIf->port.fileOpWrite = VNetUserIfWrite;
userIf->port.fileOpIoctl = VNetUserIfIoctl;
userIf->port.fileOpPoll = VNetUserIfPoll;
skb_queue_head_init(&(userIf->packetQueue));
init_waitqueue_head(&userIf->waitQueue);
memset(&userIf->stats, 0, sizeof userIf->stats);
*ret = (VNetPort*)userIf;
return 0;
}
--
Best wishes / 73
Richard Bown
e-mail: [email protected] or [email protected]
nil carborundum a illegitemis
##################################################################################
Ham Call G8JVM . OS Debian Wheezy/Sid amd64 on a Dual core AMD Athlon 5200, 4
GB RAM
Maidenhead QRA: IO82SP38, LAT. 52 39.720' N LONG. 2 28.171 W ( degs mins )
QRV HF + VHF Microwave 23 cms:140W,13 cms:100W,6 cms:10W & 3 cms:5W
##################################################################################
--
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]
Archive: http://lists.debian.org/[email protected]