]> git.pld-linux.org Git - packages/VMware-player.git/blob - VMware-player-vmnet.patch
- allow build on 2.6.25.14
[packages/VMware-player.git] / VMware-player-vmnet.patch
1 diff -Nur old/vmware-any-any-update117d/vmnet-only/bridge.c new/vmware-any-any-update117d/vmnet-only/bridge.c
2 --- old/vmware-any-any-update117d/vmnet-only/bridge.c   2008-08-30 15:50:06.800648000 +0000
3 +++ new/vmware-any-any-update117d/vmnet-only/bridge.c   2008-08-30 16:10:34.153352750 +0000
4 @@ -275,7 +275,7 @@
5                          struct net_device *net)  // IN: Network device
6  {
7  #ifdef VMW_NETDEV_HAS_NET
8 -   if (dev_net(net) != dev_net(bridge->internalDev)) {
9 +   if (net->nd_net != bridge->internalDev->nd_net) {
10        return 0;
11     }
12  #endif
13 diff -Nur old/vmware-any-any-update117d/vmnet-only/bridge.c~ new/vmware-any-any-update117d/vmnet-only/bridge.c~
14 --- old/vmware-any-any-update117d/vmnet-only/bridge.c~  1970-01-01 00:00:00.000000000 +0000
15 +++ new/vmware-any-any-update117d/vmnet-only/bridge.c~  2008-08-30 15:57:32.192483250 +0000
16 @@ -0,0 +1,1550 @@
17 +/* **********************************************************
18 + * Copyright 1998 VMware, Inc.  All rights reserved. -- VMware Confidential
19 + * **********************************************************/
20 +
21 +#include "driver-config.h"
22 +
23 +#define EXPORT_SYMTAB
24 +
25 +#include <linux/kernel.h>
26 +#include <linux/version.h>
27 +#include <linux/sched.h>
28 +#ifdef KERNEL_2_2
29 +#   include <linux/slab.h>
30 +#else
31 +#   include <linux/malloc.h>
32 +#endif
33 +#include <linux/poll.h>
34 +
35 +#include <linux/netdevice.h>
36 +#include <linux/etherdevice.h>
37 +#include <linux/mm.h>
38 +#include "compat_skbuff.h"
39 +#include <linux/sockios.h>
40 +#include "compat_sock.h"
41 +
42 +#define __KERNEL_SYSCALLS__
43 +#include <asm/io.h>
44 +
45 +#include <linux/proc_fs.h>
46 +#include <linux/file.h>
47 +#include <linux/ip.h>
48 +#include <linux/tcp.h>
49 +#include <net/tcp.h>
50 +
51 +#ifdef CONFIG_NET_RADIO
52 +#   include <linux/wireless.h>
53 +#endif
54 +#include "vmnetInt.h"
55 +#include "compat_spinlock.h"
56 +#include "compat_netdevice.h"
57 +#include "vnetInt.h"
58 +#include "smac.h"
59 +
60 +#define VNET_BRIDGE_HISTORY    48
61 +
62 +/*
63 + * Bytes reserved before start of packet.  As Ethernet header has 14 bytes,
64 + * to get aligned IP header we must skip 2 bytes before packet.  Not that it
65 + * matters a lot for us, but using 2 is compatible with what newer 2.6.x
66 + * kernels do.
67 + */
68 +#ifndef NET_IP_ALIGN
69 +#define NET_IP_ALIGN   2
70 +#endif
71 +
72 +#if LOGLEVEL >= 4
73 +static struct timeval vnetTime;
74 +#endif
75 +
76 +typedef struct VNetBridge VNetBridge;
77 +
78 +struct VNetBridge {
79 +   struct notifier_block    notifier;       // for device state changes
80 +   char                     name[VNET_NAME_LEN]; // name of net device (e.g., "eth0")
81 +   struct net_device       *dev;            // device structure for 'name'
82 +   struct sock             *sk;             // socket associated with skb's
83 +   struct packet_type       pt;             // used to add packet handler
84 +   Bool                     enabledPromisc; // track if promisc enabled
85 +   Bool                     warnPromisc;    // tracks if warning has been logged
86 +   struct sk_buff          *history[VNET_BRIDGE_HISTORY];  // avoid duplicate packets
87 +   spinlock_t              historyLock;    // protects 'history'
88 +   VNetPort                 port;           // connection to virtual hub
89 +   Bool                     wirelessAdapter; // connected to wireless adapter?
90 +   struct SMACState        *smac;           // device structure for wireless
91 +#ifdef VMW_NETDEV_HAS_NET
92 +   struct net_device       *internalDev;
93 +#endif
94 +};
95 +
96 +typedef PacketStatus (* SMACINT SMACFunc)(struct SMACState *, SMACPackets *);
97 +
98 +static int  VNetBridgeUp(VNetBridge *bridge, Bool rtnlLock);
99 +static void VNetBridgeDown(VNetBridge *bridge, Bool rtnlLock);
100 +
101 +static int  VNetBridgeNotify(struct notifier_block *this, u_long msg,
102 +                            void *data);
103 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14) && \
104 +    !defined(VMW_TL10S64_WORKAROUND)
105 +static int VNetBridgeReceiveFromDev(struct sk_buff *skb,
106 +                                    struct net_device *dev,
107 +                                    struct packet_type *pt);
108 +#else
109 +static int VNetBridgeReceiveFromDev(struct sk_buff *skb,
110 +                                    struct net_device *dev,
111 +                                    struct packet_type *pt,
112 +                                    struct net_device *real_dev);
113 +#endif
114 +
115 +static void VNetBridgeFree(VNetJack *this);
116 +static void VNetBridgeReceiveFromVNet(VNetJack *this, struct sk_buff *skb);
117 +static Bool VNetBridgeCycleDetect(VNetJack *this, int generation);
118 +static Bool VNetBridgeIsDeviceWireless(struct net_device *dev);
119 +static void VNetBridgePortsChanged(VNetJack *this);
120 +static int  VNetBridgeIsBridged(VNetJack *this);
121 +static int  VNetBridgeProcRead(char *page, char **start, off_t off,
122 +                               int count, int *eof, void *data);
123 +
124 +
125 +/*
126 + *----------------------------------------------------------------------
127 + *
128 + * VNetBridgeStartPromisc --
129 + *
130 + *      Set IFF_PROMISC on the peer interface.
131 + *
132 + * Results:
133 + *      None.
134 + *
135 + * Side effects:
136 + *      The peer interface IFF_PROMISC flag may be changed.
137 + *
138 + *----------------------------------------------------------------------
139 + */
140 +
141 +static void
142 +VNetBridgeStartPromisc(VNetBridge *bridge,      // IN:
143 +                       Bool rtnlLock)           // IN: Acquire RTNL lock
144 +{
145 +   struct net_device *dev = bridge->dev;
146 +
147 +   /*
148 +    * Disable wireless cards from going into promiscous mode because those
149 +    * cards which do support RF monitoring would not be able to function
150 +    * correctly i.e. they would not be able to send data packets.
151 +    */
152 +   if (rtnlLock) {
153 +      rtnl_lock();
154 +   }
155 +   if (!bridge->enabledPromisc && !bridge->wirelessAdapter) {
156 +      dev_set_promiscuity(dev, 1);
157 +      bridge->enabledPromisc = TRUE;
158 +      bridge->warnPromisc = FALSE;
159 +      LOG(0, (KERN_NOTICE "bridge-%s: enabled promiscuous mode\n",
160 +             bridge->name));
161 +   }
162 +   if (rtnlLock) {
163 +      rtnl_unlock();
164 +   }
165 +}
166 +
167 +
168 +/*
169 + *----------------------------------------------------------------------
170 + *
171 + * VNetBridgeStopPromisc --
172 + *
173 + *      Restore saved IFF_PROMISC on the peer interface.
174 + *
175 + * Results:
176 + *      None.
177 + *
178 + * Side effects:
179 + *      The peer interface IFF_PROMISC flag may be changed.
180 + *
181 + *----------------------------------------------------------------------
182 + */
183 +
184 +static void
185 +VNetBridgeStopPromisc(VNetBridge *bridge,       // IN:
186 +                      Bool rtnlLock)            // IN: Acquire RTNL lock
187 +{
188 +   struct net_device *dev = bridge->dev;
189 +
190 +   if (rtnlLock) {
191 +      rtnl_lock();
192 +   }
193 +   if (bridge->enabledPromisc && !bridge->wirelessAdapter) {
194 +      dev_set_promiscuity(dev, -1);
195 +      bridge->enabledPromisc = FALSE;
196 +      LOG(0, (KERN_NOTICE "bridge-%s: disabled promiscuous mode\n",
197 +             bridge->name));
198 +   }
199 +   if (rtnlLock) {
200 +      rtnl_unlock();
201 +   }
202 +}
203 +
204 +
205 +/*
206 + *----------------------------------------------------------------------
207 + *
208 + * VNetBridgeCheckPromisc --
209 + *
210 + *      Make sure IFF_PROMISC on the peer interface is set.
211 + *
212 + *      This can be called periodically.
213 + *
214 + * Results:
215 + *      None.
216 + *
217 + * Side effects:
218 + *      Hopefully enables promiscuous mode again if it should have been enabled.
219 + *
220 + *----------------------------------------------------------------------
221 + */
222 +
223 +static INLINE_SINGLE_CALLER void
224 +VNetBridgeCheckPromisc(VNetBridge *bridge)
225 +{
226 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
227 +   if (bridge->enabledPromisc && !bridge->wirelessAdapter) {
228 +      struct net_device *dev = bridge->dev;
229 +      Bool devPromisc = (dev->flags & IFF_PROMISC) != 0;
230 +
231 +      if (!devPromisc) {
232 +         if (!bridge->warnPromisc) {
233 +            bridge->warnPromisc = TRUE;
234 +            LOG(0, (KERN_NOTICE "bridge-%s: someone disabled promiscuous mode\n"
235 +                   "Your Ethernet driver is not compatible with VMware's bridged networking.\n",
236 +                    bridge->name));
237 +         }
238 +         rtnl_lock();
239 +         dev_set_promiscuity(dev, 0);
240 +         rtnl_unlock();
241 +      }
242 +   }
243 +#endif
244 +}
245 +
246 +
247 +#ifdef VMW_NETDEV_HAS_NET
248 +/*
249 + *----------------------------------------------------------------------
250 + *
251 + * VNetBridgeInternalSetup --
252 + *
253 + *      Setup callback for our bridge internal device.  Nothing to do,
254 + *      generic code sets up everything we expect from device.
255 + *
256 + * Results:
257 + *      None.
258 + *
259 + * Side effects:
260 + *      None.
261 + *
262 + *----------------------------------------------------------------------
263 + */
264 +
265 +static void
266 +VNetBridgeInternalSetup(struct net_device *net)
267 +{
268 +   /* Do nothing. */
269 +}
270 +#endif
271 +
272 +
273 +/*
274 + *----------------------------------------------------------------------
275 + *
276 + * VNetBridgeDevCompatible --
277 + *
278 + *      Check whether bridge and network device are compatible.
279 + *
280 + * Results:
281 + *      Non-zero if device is good enough for bridge.  Zero otherwise.
282 + *
283 + * Side effects:
284 + *      None.
285 + *
286 + *----------------------------------------------------------------------
287 + */
288 +
289 +static INLINE_SINGLE_CALLER int
290 +VNetBridgeDevCompatible(VNetBridge *bridge,      // IN: Bridge
291 +                        struct net_device *net)  // IN: Network device
292 +{
293 +#ifdef VMW_NETDEV_HAS_NET
294 +   if (net->nd_net != bridge->internalDev->nd_net)) {
295 +      return 0;
296 +   }
297 +#endif
298 +   return strcmp(net->name, bridge->name) == 0;
299 +}
300 +
301 +
302 +/*
303 + *----------------------------------------------------------------------
304 + *
305 + * VNetBridge_Create --
306 + *
307 + *      Create a bridge.  Allocates/initializes struct, registers
308 + *      with kernel for device state changes, connects to virtual
309 + *      hub, initializes port/jack, and creates a proc entry.
310 + *
311 + * Results:
312 + *      Errno. Also returns an allocated jack to connect to,
313 + *      NULL on error.
314 + *
315 + * Side effects:
316 + *      None.
317 + *
318 + *----------------------------------------------------------------------
319 + */
320 +
321 +int
322 +VNetBridge_Create(char      *devName, // IN:  name of device (e.g., "eth0")
323 +                  VNetPort **ret)     // OUT: port to virtual hub
324 +{
325 +   VNetBridge *bridge = NULL;
326 +   static unsigned id = 0;
327 +   int retval = 0;
328 +
329 +   *ret = NULL;
330 +
331 +   /*
332 +    * Its an error if device name is empty.
333 +    */
334 +
335 +   if (devName[0] == '\0') {
336 +      retval = -EINVAL;
337 +      goto out;
338 +   }
339 +
340 +   /*
341 +    * Allocate bridge structure
342 +    */
343 +
344 +   bridge = kmalloc(sizeof *bridge, GFP_USER);
345 +   if (bridge == NULL) {
346 +      retval = -ENOMEM;
347 +      goto out;
348 +   }
349 +   memset(bridge, 0, sizeof *bridge);
350 +   spin_lock_init(&bridge->historyLock);
351 +   memcpy(bridge->name, devName, sizeof bridge->name);
352 +   NULL_TERMINATE_STRING(bridge->name);
353 +
354 +#ifdef VMW_NETDEV_HAS_NET
355 +   bridge->internalDev = compat_alloc_netdev(0, "vmnetX", VNetBridgeInternalSetup);
356 +   if (!bridge->internalDev) {
357 +      retval = -ENOMEM;
358 +      goto out;
359 +   }
360 +#endif
361 +
362 +   /*
363 +    * Set up notifier for network device state change
364 +    */
365 +
366 +   bridge->notifier.notifier_call = VNetBridgeNotify;
367 +   bridge->notifier.priority = 0;
368 +   register_netdevice_notifier(&bridge->notifier);
369 +
370 +   /*
371 +    * Try to bring it up
372 +    */
373 +
374 +   retval = VNetBridgeUp(bridge, TRUE);
375 +   if (retval == -ENODEV) {
376 +      LOG(1, (KERN_DEBUG "bridge-%s: peer interface %s not found, "
377 +             "will wait for it to come up\n",
378 +             bridge->name, devName));
379 +      retval = 0;
380 +   }
381 +   if (retval != 0) {
382 +      goto out;
383 +   }
384 +
385 +   /*
386 +    * Initialize jack
387 +    */
388 +
389 +   bridge->port.id = id++;
390 +   bridge->port.next = NULL;
391 +
392 +   bridge->port.jack.peer = NULL;
393 +   bridge->port.jack.numPorts = 1;
394 +   VNetSnprintf(bridge->port.jack.name, sizeof bridge->port.jack.name,
395 +               "bridge%u", bridge->port.id);
396 +   bridge->port.jack.private = bridge;
397 +   bridge->port.jack.index = 0;
398 +   bridge->port.jack.procEntry = NULL;
399 +   bridge->port.jack.free = VNetBridgeFree;
400 +   bridge->port.jack.rcv = VNetBridgeReceiveFromVNet;
401 +   bridge->port.jack.cycleDetect = VNetBridgeCycleDetect;
402 +   bridge->port.jack.portsChanged = VNetBridgePortsChanged;
403 +   bridge->port.jack.isBridged = VNetBridgeIsBridged;
404 +
405 +   /*
406 +    * Make proc entry for this jack.
407 +    */
408 +
409 +   retval = VNetProc_MakeEntry(NULL, bridge->port.jack.name, S_IFREG,
410 +                               &bridge->port.jack.procEntry);
411 +   if (retval) {
412 +      if (retval == -ENXIO) {
413 +         bridge->port.jack.procEntry = NULL;
414 +      } else {
415 +         goto out;
416 +      }
417 +   } else {
418 +      bridge->port.jack.procEntry->read_proc = VNetBridgeProcRead;
419 +      bridge->port.jack.procEntry->data = bridge;
420 +   }
421 +
422 +   /*
423 +    * Rest of fields.
424 +    */
425 +
426 +   bridge->port.flags = IFF_RUNNING;
427 +
428 +   memset(bridge->port.paddr, 0, sizeof bridge->port.paddr);
429 +   memset(bridge->port.ladrf, 0, sizeof bridge->port.ladrf);
430 +
431 +   bridge->port.paddr[0] = VMX86_STATIC_OUI0;
432 +   bridge->port.paddr[1] = VMX86_STATIC_OUI1;
433 +   bridge->port.paddr[2] = VMX86_STATIC_OUI2;
434 +
435 +   bridge->port.fileOpRead = NULL;
436 +   bridge->port.fileOpWrite = NULL;
437 +   bridge->port.fileOpIoctl = NULL;
438 +   bridge->port.fileOpPoll = NULL;
439 +
440 +   *ret = &bridge->port;
441 +
442 +   LOG(1, (KERN_DEBUG "bridge-%s: attached\n", bridge->name));
443 +   return 0;
444 +
445 +out:
446 +   if (bridge != NULL) {
447 +      if (bridge->notifier.notifier_call != NULL) {
448 +         unregister_netdevice_notifier(&bridge->notifier);
449 +      }
450 +#ifdef VMW_NETDEV_HAS_NET
451 +      if (bridge->internalDev) {
452 +         compat_free_netdev(bridge->internalDev);
453 +      }
454 +#endif
455 +      kfree(bridge);
456 +   }
457 +   return retval;
458 +}
459 +
460 +
461 +/*
462 + *----------------------------------------------------------------------
463 + *
464 + * VNetBridgeFree --
465 + *
466 + *      Disconnect the bridge, unregister from device state
467 + *      notifications, remove proc entry, and deallocate struct.
468 + *
469 + * Results:
470 + *      None.
471 + *
472 + * Side effects:
473 + *      None.
474 + *
475 + *----------------------------------------------------------------------
476 + */
477 +
478 +void
479 +VNetBridgeFree(VNetJack *this) // IN: jack to free
480 +{
481 +   VNetBridge *bridge = (VNetBridge*)this->private;
482 +
483 +   if (bridge->dev != NULL) {
484 +      VNetBridgeDown(bridge, TRUE);
485 +   }
486 +
487 +   unregister_netdevice_notifier(&bridge->notifier);
488 +
489 +#ifdef VMW_NETDEV_HAS_NET
490 +   if (bridge->internalDev) {
491 +      compat_free_netdev(bridge->internalDev);
492 +   }
493 +#endif
494 +
495 +   if (this->procEntry) {
496 +      VNetProc_RemoveEntry(this->procEntry, NULL);
497 +   }
498 +
499 +   if (bridge->smac){
500 +      SMAC_CleanupState(&(bridge->smac));
501 +   }
502 +
503 +   LOG(1, (KERN_DEBUG "bridge-%s: detached\n", bridge->name));
504 +   kfree(bridge);
505 +}
506 +
507 +
508 +/*
509 + *----------------------------------------------------------------------
510 + *
511 + * VNetCallSMACFunc --
512 + *
513 + *      Wrapper for SMAC functions.
514 + *
515 + * Results:
516 + *      Packet Status.
517 + *
518 + * Side effects:
519 + *      The skb buffer is freed if not succesfull otherwise it points to
520 + *      the clone.
521 + *
522 + *----------------------------------------------------------------------
523 + */
524 +
525 +PacketStatus
526 +VNetCallSMACFunc(struct SMACState *state, // IN: pointer to state
527 +                 struct sk_buff **skb,    // IN/OUT: packet to process
528 +                 void *startOfData,       // IN: points to start of data
529 +                 SMACFunc func)           // IN: function to be called
530 +{
531 +   SMACPackets packets = { {0} };
532 +   PacketStatus status;
533 +
534 +   packets.orig.skb = *skb;
535 +   packets.orig.startOfData = startOfData;
536 +
537 +   status = func(state, &packets);
538 +   if (status != PacketStatusForwardPacket) {
539 +      dev_kfree_skb(*skb);
540 +      return status;
541 +   }
542 +
543 +   if (packets.clone.skb) {
544 +      dev_kfree_skb(*skb);
545 +      *skb = packets.clone.skb;
546 +   }
547 +   return status;
548 +}
549 +
550 +
551 +/*
552 + *----------------------------------------------------------------------
553 + *
554 + * VNetBridgeReceiveFromVNet --
555 + *
556 + *      This jack is receiving a packet from a vnet.  This function
557 + *      sends down (i.e., out on the host net device) if the packet
558 + *      isn't destined for the host, and it sends up (i.e.,
559 + *      simulates a receive for the host) if the packet
560 + *      satisfies the host's packet filter.
561 + *
562 + *      When the function sends up it keeps a reference to the
563 + *      packet in a history list so that we can avoid handing
564 + *      a VM a copy of its own packet.
565 + *
566 + * Results:
567 + *      None.
568 + *
569 + * Side effects:
570 + *      Frees skb.  Checks if host device is still using
571 + *      promiscuous mode.
572 + *
573 + *----------------------------------------------------------------------
574 + */
575 +
576 +void
577 +VNetBridgeReceiveFromVNet(VNetJack        *this, // IN: jack
578 +                          struct sk_buff  *skb)  // IN: pkt to receive
579 +{
580 +   VNetBridge *bridge = (VNetBridge*)this->private;
581 +   struct net_device *dev = bridge->dev;
582 +   uint8 dest[ETH_ALEN];
583 +   struct sk_buff *clone;
584 +
585 +   LOG(3, (KERN_DEBUG "bridge-%s: transmit %d\n",
586 +           bridge->name, (int) skb->len));
587 +
588 +   if (!dev) {
589 +      dev_kfree_skb(skb);
590 +      return;
591 +   }
592 +
593 +   /*
594 +    * skb might be freed by wireless code, so need to keep
595 +    * a local copy of the MAC rather than a pointer to it.
596 +    */
597 +
598 +   memcpy(dest, SKB_2_DESTMAC(skb), ETH_ALEN);
599 +
600 +   /*
601 +    * Check promiscuous bit periodically
602 +    */
603 +
604 +   VNetBridgeCheckPromisc(bridge);
605 +
606 +#ifdef notdef
607 +   // xxx;
608 +   /*
609 +    * We need to send the packet both up to the host and down
610 +    * to the interface.
611 +    * However, we ignore packets destined only for this hub.
612 +    */
613 +
614 +   for (i = 0; i < VNET_PORTS_PER_HUB; i++) {
615 +      VNetPort *p = &port->hub->port[i];
616 +      if (UP_AND_RUNNING(p->flags) && MAC_EQ(dest, p->paddr)) {
617 +        return;
618 +      }
619 +   }
620 +#endif
621 +
622 +   /*
623 +    * Wireless processing
624 +    */
625 +
626 +   if (bridge->smac) {
627 +      if (VNetCallSMACFunc(bridge->smac, &skb, skb->data,
628 +                           SMAC_CheckPacketToHost) !=
629 +          PacketStatusForwardPacket) {
630 +         LOG(4, (KERN_NOTICE "bridge-%s: packet dropped .\n",
631 +                 bridge->name));
632 +        return;
633 +      }
634 +   }
635 +
636 +   /*
637 +    * Send down (imitate packet_sendmsg)
638 +    *
639 +    * Do this only if the packet is not addressed to the peer,
640 +    * and the packet size is not too big.
641 +    */
642 +
643 +   dev_lock_list();
644 +   if (MAC_EQ(dest, dev->dev_addr) ||
645 +       skb->len > dev->mtu + dev->hard_header_len) {
646 +      dev_unlock_list();
647 +   } else {
648 +#     if 0 // XXX we should do header translation
649 +      if ((dev->flags & IFF_SOFTHEADERS) != 0) {
650 +        if (skb->len > dev->mtu) {
651 +           clone = NULL;
652 +        } else {
653 +           clone = dev_alloc_skb(skb->len + dev->hard_header_len, GFP_ATOMIC);
654 +        }
655 +        if (clone != NULL) {
656 +           skb_reserve(clone, dev->hard_header_len);
657 +           if (dev->hard_header != NULL) {
658 +              dev->hard_header(clone, dev, ETH_P_IP, NULL, NULL, skb->len);
659 +           }
660 +           memcpy(skb_put(clone, skb->len), skb->data, skb->len);
661 +        }
662 +      }
663 +#     endif
664 +      clone = skb_clone(skb, GFP_ATOMIC);
665 +      if (clone == NULL) {
666 +        dev_unlock_list();
667 +      } else {
668 +        struct sock *sk = bridge->sk;
669 +        atomic_add(skb->truesize, &sk->sk_wmem_alloc);
670 +        clone->sk = sk;
671 +        clone->protocol = ((struct ethhdr *)skb->data)->h_proto; // XXX
672 +        if ((dev->flags & IFF_UP) != 0) {
673 +           dev_unlock_list();
674 +           DEV_QUEUE_XMIT(clone, dev, 0);
675 +        } else {
676 +           dev_unlock_list();
677 +           dev_kfree_skb(clone);
678 +        }
679 +      }
680 +   }
681 +
682 +   /*
683 +    * Send up (imitate Ethernet receive)
684 +    *
685 +    * Do this if the packet is addressed to the peer (or is broadcast, etc.).
686 +    *
687 +    * This packet will get back to us, via VNetBridgeReceive.
688 +    * We save it so we can recognize it (and its clones) again.
689 +    */
690 +
691 +   if (VNetPacketMatch(dest, dev->dev_addr, (uint8 *)&AllMultiFilter, dev->flags)) {
692 +      clone = skb_clone(skb, GFP_ATOMIC);
693 +      if (clone) {
694 +        unsigned long flags;
695 +        int i;
696 +
697 +        atomic_inc(&clone->users);
698 +
699 +        clone->dev = dev;
700 +        clone->protocol = eth_type_trans(clone, dev);
701 +        spin_lock_irqsave(&bridge->historyLock, flags);
702 +        for (i = 0; i < VNET_BRIDGE_HISTORY; i++) {
703 +           if (bridge->history[i] == NULL) {
704 +              bridge->history[i] = clone;
705 +#             if LOGLEVEL >= 3
706 +              {
707 +                 int j;
708 +                 int count = 0;
709 +                 for (j = 0; j < VNET_BRIDGE_HISTORY; j++) {
710 +                    if (bridge->history[j] != NULL) {
711 +                       count++;
712 +                    }
713 +                 }
714 +                 LOG(3, (KERN_DEBUG "bridge-%s: host slot %d history %d\n",
715 +                         bridge->name, i, count));
716 +              }
717 +#             endif
718 +              break;
719 +           }
720 +        }
721 +        if (i >= VNET_BRIDGE_HISTORY) {
722 +           LOG(1, (KERN_NOTICE "bridge-%s: history full\n",
723 +                   bridge->name));
724 +
725 +           for (i = 0; i < VNET_BRIDGE_HISTORY; i++) {
726 +              struct sk_buff *s = bridge->history[i];
727 +
728 +              /*
729 +               * We special case 0 to avoid races with another thread on
730 +               * another cpu wanting to use the 0 entry. This could happen
731 +               * when we release the lock to free the former entry.
732 +               * See bug 11231 for details.
733 +               */
734 +              if (i == 0) {
735 +                 bridge->history[0] = clone;
736 +              } else {
737 +                 bridge->history[i] = NULL;
738 +              }
739 +              if (s) {
740 +                 spin_unlock_irqrestore(&bridge->historyLock, flags);
741 +                 dev_kfree_skb(s);
742 +                 spin_lock_irqsave(&bridge->historyLock, flags);
743 +              }
744 +           }
745 +        }
746 +         spin_unlock_irqrestore(&bridge->historyLock, flags);
747 +
748 +         /*
749 +          * We used to cli() before calling netif_rx() here. It was probably
750 +          * unneeded (as we never did it in netif.c, and the code worked). In
751 +          * any case, now that we are using netif_rx_ni(), we should certainly
752 +          * not do it, or netif_rx_ni() will deadlock on the cli() lock --hpreg
753 +          */
754 +
755 +        netif_rx_ni(clone);
756 +#       if LOGLEVEL >= 4
757 +        do_gettimeofday(&vnetTime);
758 +#       endif
759 +      }
760 +   }
761 +
762 +   // xxx;
763 +   dev_kfree_skb(skb);
764 +}
765 +
766 +
767 +/*
768 + *----------------------------------------------------------------------
769 + *
770 + * VNetBridgeCycleDetect --
771 + *
772 + *      Cycle detection algorithm.
773 + *
774 + * Results:
775 + *      TRUE if a cycle was detected, FALSE otherwise.
776 + *
777 + * Side effects:
778 + *      None.
779 + *
780 + *----------------------------------------------------------------------
781 + */
782 +
783 +Bool
784 +VNetBridgeCycleDetect(VNetJack *this,       // IN: jack
785 +                      int       generation) // IN: generation
786 +{
787 +   VNetBridge *bridge = (VNetBridge*)this->private;
788 +   return VNetCycleDetectIf(bridge->name, generation);
789 +}
790 +
791 +
792 +/*
793 + *----------------------------------------------------------------------
794 + *
795 + * VNetBridgePortsChanged --
796 + *
797 + *      The number of ports connected to this jack has change, react
798 + *      accordingly by starting/stopping promiscuous mode based on
799 + *      whether any peers exist.
800 + *
801 + * Results:
802 + *      None.
803 + *
804 + * Side effects:
805 + *      Promiscuous mode may be started or stopped.
806 + *
807 + *----------------------------------------------------------------------
808 + */
809 +
810 +void
811 +VNetBridgePortsChanged(VNetJack *this) // IN: jack
812 +{
813 +   VNetBridge *bridge = (VNetBridge*)this->private;
814 +   if (bridge->dev) {
815 +      if (VNetGetAttachedPorts(this)) {
816 +         VNetBridgeStartPromisc(bridge, TRUE);
817 +      } else {
818 +         VNetBridgeStopPromisc(bridge, TRUE);
819 +      }
820 +   }
821 +}
822 +
823 +
824 +/*
825 + *----------------------------------------------------------------------
826 + *
827 + * VNetBridgeIsBridged --
828 + *
829 + *      Reports if the bridged interface is up or down.
830 + *
831 + * Results:
832 + *      1 - we are bridged but the interface is not up
833 + *      2 - we are bridged and the interface is up
834 + *
835 + * Side effects:
836 + *      None.
837 + *
838 + *----------------------------------------------------------------------
839 + */
840 +
841 +int
842 +VNetBridgeIsBridged(VNetJack *this) // IN: jack
843 +{
844 +   VNetBridge *bridge = (VNetBridge*)this->private;
845 +   if (bridge->dev) {
846 +      return 2;
847 +   } else {
848 +      return 1;
849 +   }
850 +}
851 +
852 +/*
853 + *----------------------------------------------------------------------
854 + *
855 + * VNetBridgeIsDeviceWireless --
856 + *
857 + *      Check if the device is a wireless adapter, depending on the version
858 + *      of the wireless extension present in the kernel.
859 + *
860 + * Results:
861 + *      TRUE if the device is wireless, FALSE otherwise.
862 + *
863 + * Side effects:
864 + *      None.
865 + *
866 + *----------------------------------------------------------------------
867 + */
868 +
869 +static Bool
870 +VNetBridgeIsDeviceWireless(struct net_device *dev) //IN: sock
871 +{
872 +#if !defined(CONFIG_NET_RADIO)
873 +   return FALSE;
874 +#elif WIRELESS_EXT > 19
875 +   return dev->wireless_handlers != NULL;
876 +#elif WIRELESS_EXT > 12
877 +   return dev->wireless_handlers != NULL || dev->get_wireless_stats != NULL;
878 +#else
879 +   return dev->get_wireless_stats != NULL;
880 +#endif
881 +}
882 +
883 +/*
884 + *----------------------------------------------------------------------
885 + *
886 + * VNetBridgeUp --
887 + *
888 + *      Bring a bridge up.  Gets peer's device structure, verifies
889 + *      that interface is up, checks the header length,
890 + *      allocates a socket, adds a packet handler to the network
891 + *      stack, and then places the peer's device in promiscuous
892 + *      mode.
893 + *
894 + * Results:
895 + *      errno.
896 + *
897 + * Side effects:
898 + *      Bridging may be brought up with a peer interface.
899 + *
900 + *----------------------------------------------------------------------
901 + */
902 +
903 +int
904 +VNetBridgeUp(VNetBridge *bridge, // IN: bridge struct
905 +             Bool rtnlLock)      // IN: acquire RTNL lock
906 +{
907 +   int retval = 0;
908 +
909 +   if (bridge->dev != NULL) {
910 +      LOG(0, (KERN_NOTICE "bridge-%s: already up\n", bridge->name));
911 +      goto out;
912 +   }
913 +
914 +   /*
915 +    * Get peer device structure
916 +    */
917 +
918 +   dev_lock_list();
919 +   bridge->dev = DEV_GET(bridge);
920 +   LOG(2, (KERN_DEBUG "bridge-%s: got dev %p\n",
921 +          bridge->name, bridge->dev));
922 +   if (bridge->dev == NULL) {
923 +      dev_unlock_list();
924 +      retval = -ENODEV;
925 +      goto out;
926 +   }
927 +   if (!(bridge->dev->flags & IFF_UP)) {
928 +      LOG(2, (KERN_DEBUG "bridge-%s: interface %s is not up\n",
929 +              bridge->name, bridge->dev->name));
930 +      dev_unlock_list();
931 +      retval = -ENODEV;
932 +      goto out;
933 +   }
934 +
935 +   /*
936 +    * At a minimum, the header size should be the same as ours.
937 +    *
938 +    * XXX we should either do header translation or ensure this
939 +    * is an Ethernet.
940 +    */
941 +
942 +   if (bridge->dev->hard_header_len != ETH_HLEN) {
943 +      LOG(1, (KERN_DEBUG "bridge-%s: can't bridge with %s, bad header length %d\n",
944 +             bridge->name, bridge->dev->name, bridge->dev->hard_header_len));
945 +      dev_unlock_list();
946 +      retval = -EINVAL;
947 +      goto out;
948 +   }
949 +
950 +   /*
951 +    * Get a socket to play with
952 +    *
953 +    * We set the dead field so we don't get a call back from dev_kfree_skb().
954 +    * (The alternative is to support the callback.)
955 +    */
956 +
957 +   bridge->sk = compat_sk_alloc(bridge, GFP_ATOMIC);
958 +   if (bridge->sk == NULL) {
959 +      dev_unlock_list();
960 +      retval = -ENOMEM;
961 +      goto out;
962 +   }
963 +   SET_SK_DEAD(bridge->sk);
964 +
965 +   bridge->wirelessAdapter = VNetBridgeIsDeviceWireless(bridge->dev);
966 +
967 +   /*
968 +    * If it is a wireless adapter initialize smac struct.
969 +    */
970 +
971 +   if (bridge->wirelessAdapter) {
972 +
973 +      LOG(1, (KERN_NOTICE "bridge-%s: is a Wireless Adapter\n", bridge->name));
974 +      SMAC_InitState(&(bridge->smac));
975 +      if (bridge->smac) {
976 +         /*
977 +          * Store the MAC address of the adapter
978 +          */
979 +
980 +         SMAC_SetMac(bridge->smac, bridge->dev->dev_addr);
981 +      }
982 +   }
983 +
984 +   /*
985 +    * Link up with the peer device by adding a
986 +    * packet handler to the networking stack.
987 +    */
988 +
989 +   bridge->pt.func = VNetBridgeReceiveFromDev;
990 +   bridge->pt.type = htons(ETH_P_ALL);
991 +   bridge->pt.dev = bridge->dev;
992 +
993 +   /*
994 +    * TurboLinux10 uses 2.6.0-test5, which we do not support, so special case it,
995 +    * 2.6.0 with tl_kernel_version_h is 2.6.0-pre5...
996 +    */
997 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) || \
998 +   (LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 0) && defined(__tl_kernel_version_h__))
999 +   bridge->pt.data = bridge->sk;
1000 +#else
1001 +   bridge->pt.af_packet_priv = bridge->sk;
1002 +#endif
1003 +   bridge->enabledPromisc = FALSE;
1004 +   bridge->warnPromisc = FALSE;
1005 +   dev_add_pack(&bridge->pt);
1006 +   dev_unlock_list();
1007 +
1008 +   /*
1009 +    * Put in promiscuous mode if need be.
1010 +    */
1011 +
1012 +   down(&vnetStructureSemaphore);
1013 +   if (VNetGetAttachedPorts(&bridge->port.jack)) {
1014 +      VNetBridgeStartPromisc(bridge, rtnlLock);
1015 +   }
1016 +   up(&vnetStructureSemaphore);
1017 +
1018 +   /*
1019 +    * Finish up
1020 +    */
1021 +
1022 +   LOG(1, (KERN_DEBUG "bridge-%s: up\n", bridge->name));
1023 +
1024 +   /*
1025 +    * Return
1026 +    */
1027 +
1028 +out:
1029 +   if (retval != 0) {
1030 +      if (bridge->sk != NULL) {
1031 +        sk_free(bridge->sk);
1032 +        bridge->sk = NULL;
1033 +      }
1034 +      bridge->dev = NULL;
1035 +   }
1036 +   return retval;
1037 +}
1038 +
1039 +
1040 +/*
1041 + *----------------------------------------------------------------------
1042 + *
1043 + * VNetBridgeDown --
1044 + *
1045 + *      Bring a bridge down.  Stops promiscuous mode, removes the
1046 + *      packet handler from the network stack, and frees the
1047 + *      socket.
1048 + *
1049 + * Results:
1050 + *      None.
1051 + *
1052 + * Side effects:
1053 + *      Bridging is brought down.
1054 + *
1055 + *----------------------------------------------------------------------
1056 + */
1057 +
1058 +void
1059 +VNetBridgeDown(VNetBridge *bridge, // IN: bridge
1060 +               Bool rtnlLock)      // IN: acquire RTNL lock
1061 +{
1062 +   if (bridge->dev == NULL) {
1063 +      LOG(0, (KERN_NOTICE "bridge-%s: already down\n", bridge->name));
1064 +      return;
1065 +   }
1066 +
1067 +   VNetBridgeStopPromisc(bridge, rtnlLock);
1068 +   if (bridge->smac){
1069 +      SMAC_SetMac(bridge->smac, NULL);
1070 +   }
1071 +   bridge->dev = NULL;
1072 +   dev_remove_pack(&bridge->pt);
1073 +   sk_free(bridge->sk);
1074 +   bridge->sk = NULL;
1075 +   LOG(1, (KERN_DEBUG "bridge-%s: down\n", bridge->name));
1076 +}
1077 +
1078 +
1079 +/*
1080 + *-----------------------------------------------------------------------------
1081 + *
1082 + * VNetBridgeNotify --
1083 + *
1084 + *      Callback on peer device state change.  The function brings
1085 + *      the bridge up/down in response to changes in the peer device.
1086 + *
1087 + * Results:
1088 + *      NOTIFY_DONE
1089 + *
1090 + * Side effects:
1091 + *      Promiscuous mode is changed when bridge brought up/down.
1092 + *
1093 + *-----------------------------------------------------------------------------
1094 + */
1095 +
1096 +int
1097 +VNetBridgeNotify(struct notifier_block *this, // IN: callback data (bridge)
1098 +                 u_long msg,                  // IN: type of event
1099 +                 void *data)                  // IN: device pertaining to event
1100 +{
1101 +   VNetBridge *bridge = list_entry(this, VNetBridge, notifier);
1102 +   struct net_device *dev = (struct net_device *) data;
1103 +
1104 +   switch (msg) {
1105 +   case NETDEV_UNREGISTER:
1106 +      LOG(2, (KERN_DEBUG "bridge-%s: interface %s is unregistering\n",
1107 +              bridge->name, dev->name));
1108 +      if (dev == bridge->dev) {
1109 +         /* This should never happen --hpreg */
1110 +         LOG(0, (KERN_WARNING "bridge-%s: interface %s unregistered without "
1111 +                 "going down! Disabling the bridge\n", bridge->name,
1112 +                 dev->name));
1113 +         VNetBridgeDown(bridge, FALSE);
1114 +      }
1115 +      break;
1116 +
1117 +   case NETDEV_DOWN:
1118 +      LOG(2, (KERN_DEBUG "bridge-%s: interface %s is going down\n",
1119 +              bridge->name, dev->name));
1120 +      if (dev == bridge->dev) {
1121 +         LOG(1, (KERN_DEBUG "bridge-%s: disabling the bridge\n",
1122 +                 bridge->name));
1123 +         VNetBridgeDown(bridge, FALSE);
1124 +      }
1125 +      break;
1126 +
1127 +   case NETDEV_UP:
1128 +      LOG(2, (KERN_DEBUG "bridge-%s: interface %s is going up\n",
1129 +              bridge->name, dev->name));
1130 +      if (bridge->dev == NULL && VNetBridgeDevCompatible(bridge, dev)) {
1131 +         int errno;
1132 +
1133 +         LOG(1, (KERN_DEBUG "bridge-%s: enabling the bridge\n", bridge->name));
1134 +        errno = VNetBridgeUp(bridge, FALSE);
1135 +        switch (-errno) {
1136 +        case 0:
1137 +           break;
1138 +
1139 +        case ENODEV:
1140 +            LOG(0, (KERN_WARNING "bridge-%s: interface %s not found or not "
1141 +                    "up\n", bridge->name, dev->name));
1142 +           break;
1143 +
1144 +        case EINVAL:
1145 +            LOG(0, (KERN_WARNING "bridge-%s: interface %s is not a valid "
1146 +                    "Ethernet interface\n", bridge->name, dev->name));
1147 +           break;
1148 +
1149 +        case ENOMEM:
1150 +            LOG(0, (KERN_WARNING "bridge-%s: failed to allocate memory\n",
1151 +                    bridge->name));
1152 +           break;
1153 +
1154 +        default:
1155 +            /* This should never happen --hpreg */
1156 +            LOG(0, (KERN_WARNING "bridge-%s: failed to enable the bridge to "
1157 +                    "interface %s (error %d)\n", bridge->name, dev->name,
1158 +                    -errno));
1159 +            break;
1160 +        }
1161 +      }
1162 +      break;
1163 +
1164 +   default:
1165 +      LOG(2, (KERN_DEBUG "bridge-%s: interface %s is sending notification "
1166 +              "0x%lx\n", bridge->name, dev->name, msg));
1167 +      break;
1168 +   }
1169 +
1170 +   return NOTIFY_DONE;
1171 +}
1172 +
1173 +
1174 +/*
1175 + *----------------------------------------------------------------------
1176 + *
1177 + * VNetBridgeComputeHeaderPos --
1178 + *
1179 + *      Compute correct position for UDP/TCP header.
1180 + *
1181 + * Results:
1182 + *      None.
1183 + *
1184 + * Side effects:
1185 + *      transport header pointer updated to point to the tcp/udp header.
1186 + *
1187 + *----------------------------------------------------------------------
1188 + */
1189 +
1190 +static INLINE_SINGLE_CALLER void
1191 +VNetBridgeComputeHeaderPos(struct sk_buff *skb) // IN: buffer to examine
1192 +{
1193 +   /* Maybe some kernel gets it right... */
1194 +   if (compat_skb_network_header_len(skb)) {
1195 +      return;
1196 +   }
1197 +   switch (be16_to_cpu(skb->protocol)) {
1198 +      case ETH_P_IP: {
1199 +            struct iphdr *ipHdr = compat_skb_ip_header(skb);
1200 +
1201 +            compat_skb_set_transport_header(skb, compat_skb_network_offset(skb) +
1202 +                                                 ipHdr->ihl * 4);
1203 +         }
1204 +        return;
1205 +      default:
1206 +         LOG(3, (KERN_DEBUG "Unknown EII protocol %04X: csum at %d\n",
1207 +                be16_to_cpu(skb->protocol), compat_skb_csum_offset(skb)));
1208 +        break;
1209 +   }
1210 +   return;
1211 +}
1212 +
1213 +
1214 +/*
1215 + * We deal with three types of kernels:
1216 + * New kernels: skb_shinfo() has gso_size member, and there is
1217 + *              skb_gso_segment() helper to split GSO skb into flat ones.
1218 + * Older kernels: skb_shinfo() has tso_size member, and there is
1219 + *                no helper.
1220 + * Oldest kernels: without any segmentation offload support.
1221 + */
1222 +#if defined(NETIF_F_GSO) || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
1223 +#define VNetBridgeIsGSO(skb) skb_shinfo(skb)->gso_size
1224 +#define VNetBridgeGSOSegment(skb) skb_gso_segment(skb, 0)
1225 +#elif defined(NETIF_F_TSO)
1226 +#define VNetBridgeIsGSO(skb) skb_shinfo(skb)->tso_size
1227 +
1228 +
1229 +/*
1230 + *----------------------------------------------------------------------
1231 + *
1232 + * VNetBridgeGSOSegment --
1233 + *
1234 + *     Split a large TCP/IPv4 sk_buff into multiple sk_buffs of
1235 + *     size skb_shinfo(skb)->tso_size
1236 + *     Called from VNetBridgeSendLargePacket().
1237 + *
1238 + * Results:
1239 + *     List of skbs created.
1240 + *
1241 + * Side effects:
1242 + *     The incoming packet is split into multiple packets.
1243 + *
1244 + *----------------------------------------------------------------------
1245 + */
1246 +
1247 +static struct sk_buff *
1248 +VNetBridgeGSOSegment(struct sk_buff *skb)        // IN: packet to split
1249 +{
1250 +   struct sk_buff *segs = NULL;
1251 +   struct sk_buff **next = &segs;
1252 +   int bytesPerPacket, bytesLeft;
1253 +   int macHdrLen, ipHdrLen, tcpHdrLen, allHdrLen;
1254 +   int curByteOffset;
1255 +   uint16 ipID;
1256 +   uint32 seqNo;
1257 +
1258 +   if (((struct ethhdr *)compat_skb_mac_header(skb))->h_proto != htons(ETH_P_IP)) {
1259 +      return ERR_PTR(-EPFNOSUPPORT);
1260 +   }
1261 +
1262 +   if (compat_skb_ip_header(skb)->protocol != IPPROTO_TCP) {
1263 +      return ERR_PTR(-EPROTONOSUPPORT);
1264 +   }
1265 +
1266 +   macHdrLen = compat_skb_network_header(skb) - compat_skb_mac_header(skb);
1267 +   ipHdrLen = compat_skb_ip_header(skb)->ihl << 2;
1268 +   tcpHdrLen = compat_skb_tcp_header(skb)->doff << 2;
1269 +   allHdrLen = macHdrLen + ipHdrLen + tcpHdrLen;
1270 +
1271 +   ipID = ntohs(compat_skb_ip_header(skb)->id);
1272 +   seqNo = ntohl(compat_skb_tcp_header(skb)->seq);
1273 +
1274 +   /* Host TCP stack populated this (MSS) for the host NIC driver */
1275 +   bytesPerPacket = skb_shinfo(skb)->tso_size;
1276 +
1277 +   bytesLeft = skb->len - allHdrLen;
1278 +   curByteOffset = allHdrLen;
1279 +
1280 +   while (bytesLeft) {
1281 +      struct sk_buff *newSkb;
1282 +      int payloadSize = (bytesLeft < bytesPerPacket) ? bytesLeft : bytesPerPacket;
1283 +
1284 +      newSkb = dev_alloc_skb(payloadSize + allHdrLen + NET_IP_ALIGN);
1285 +      if (!newSkb) {
1286 +         while (segs) {
1287 +            newSkb = segs;
1288 +            segs = segs->next;
1289 +            newSkb->next = NULL;
1290 +            dev_kfree_skb(newSkb);
1291 +         }
1292 +         return ERR_PTR(-ENOMEM);
1293 +      }
1294 +      skb_reserve(newSkb, NET_IP_ALIGN);
1295 +      newSkb->dev = skb->dev;
1296 +      newSkb->protocol = skb->protocol;
1297 +      newSkb->pkt_type = skb->pkt_type;
1298 +      newSkb->ip_summed = VM_CHECKSUM_PARTIAL;
1299 +
1300 +      /*
1301 +       * MAC+IP+TCP copy
1302 +       * This implies that ALL fields in the IP and TCP headers are copied from
1303 +       * the original skb. This is convenient: we'll only fix up fields that
1304 +       * need to be changed below
1305 +       */
1306 +      memcpy(skb_put(newSkb, allHdrLen), skb->data, allHdrLen);
1307 +
1308 +      /* Fix up pointers to different layers */
1309 +      compat_skb_reset_mac_header(newSkb);
1310 +      compat_skb_set_network_header(newSkb, macHdrLen);
1311 +      compat_skb_set_transport_header(newSkb, macHdrLen + ipHdrLen);
1312 +
1313 +      /* Payload copy */
1314 +      skb_copy_bits(skb, curByteOffset, compat_skb_tail_pointer(newSkb), payloadSize);
1315 +      skb_put(newSkb, payloadSize);
1316 +
1317 +      curByteOffset+=payloadSize;
1318 +      bytesLeft -= payloadSize;
1319 +
1320 +      /* Fix up IP hdr */
1321 +      compat_skb_ip_header(newSkb)->tot_len = htons(payloadSize + tcpHdrLen + ipHdrLen);
1322 +      compat_skb_ip_header(newSkb)->id = htons(ipID);
1323 +      compat_skb_ip_header(newSkb)->check = 0;
1324 +      /* Recompute new IP checksum */
1325 +      compat_skb_ip_header(newSkb)->check =
1326 +              ip_fast_csum(compat_skb_network_header(newSkb),
1327 +                           compat_skb_ip_header(newSkb)->ihl);
1328 +
1329 +      /* Fix up TCP hdr */
1330 +      compat_skb_tcp_header(newSkb)->seq = htonl(seqNo);
1331 +      /* Clear FIN/PSH if not last packet */
1332 +      if (bytesLeft > 0) {
1333 +         compat_skb_tcp_header(newSkb)->fin = 0;
1334 +         compat_skb_tcp_header(newSkb)->psh = 0;
1335 +      }
1336 +      /* Recompute partial TCP checksum */
1337 +      compat_skb_tcp_header(newSkb)->check =
1338 +         ~csum_tcpudp_magic(compat_skb_ip_header(newSkb)->saddr,
1339 +                            compat_skb_ip_header(newSkb)->daddr,
1340 +                            payloadSize+tcpHdrLen, IPPROTO_TCP, 0);
1341 +
1342 +      /* Offset of field */
1343 +      newSkb->csum = offsetof(struct tcphdr, check);
1344 +
1345 +      /* Join packet to the list of segments */
1346 +      *next = newSkb;
1347 +      next = &newSkb->next;
1348 +
1349 +      /* Bump up our counters */
1350 +      ipID++;
1351 +      seqNo += payloadSize;
1352 +
1353 +   }
1354 +   return segs;
1355 +}
1356 +#else
1357 +#define VNetBridgeIsGSO(skb) (0)
1358 +#define VNetBridgeGSOSegment(skb) ERR_PTR(-ENOSYS)
1359 +#endif
1360 +
1361 +
1362 +/*
1363 + *----------------------------------------------------------------------
1364 + *
1365 + * VNetBridgeSendLargePacket --
1366 + *
1367 + *      Split and send a large TCP/IPv4 sk_buff into multiple sk_buffs which
1368 + *      fits on wire.  Called from VNetBridgeReceiveFromDev(), which is a
1369 + *     protocol handler called from the bottom half, so steady as she
1370 + *     goes...
1371 + *
1372 + *     skb passed in is deallocated by function.
1373 + *
1374 + * Results:
1375 + *      None.
1376 + *
1377 + * Side effects:
1378 + *      The incoming packet is split into multiple packets and sent to the
1379 + *      vnet.
1380 + *
1381 + *----------------------------------------------------------------------
1382 + */
1383 +
1384 +void
1385 +VNetBridgeSendLargePacket(struct sk_buff *skb,        // IN: packet to split
1386 +                          VNetBridge *bridge)         // IN: bridge
1387 +{
1388 +   struct sk_buff *segs;
1389 +
1390 +   segs = VNetBridgeGSOSegment(skb);
1391 +   dev_kfree_skb(skb);
1392 +   if (IS_ERR(segs)) {
1393 +      LOG(1, (KERN_DEBUG "bridge-%s: cannot segment packet: error %ld\n",
1394 +              bridge->name, PTR_ERR(segs)));
1395 +      return;
1396 +   }
1397 +
1398 +   while (segs) {
1399 +      struct sk_buff *newSkb;
1400 +
1401 +      newSkb = segs;
1402 +      segs = newSkb->next;
1403 +      newSkb->next = NULL;
1404 +      /* Send it along */
1405 +      skb = newSkb;
1406 +      VNetSend(&bridge->port.jack, newSkb);
1407 +   }
1408 +}
1409 +
1410 +
1411 +/*
1412 + *----------------------------------------------------------------------
1413 + *
1414 + * VNetBridgeReceiveFromDev --
1415 + *
1416 + *      Receive a packet from a bridged peer device
1417 + *
1418 + *      This is called from the bottom half.  Must be careful.
1419 + *
1420 + * Results:
1421 + *      errno.
1422 + *
1423 + * Side effects:
1424 + *      A packet may be sent to the vnet.
1425 + *
1426 + *----------------------------------------------------------------------
1427 + */
1428 +
1429 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14) && \
1430 +    !defined(VMW_TL10S64_WORKAROUND)
1431 +int
1432 +VNetBridgeReceiveFromDev(struct sk_buff *skb,         // IN: packet to receive
1433 +                         struct net_device *dev,      // IN: unused
1434 +                         struct packet_type *pt)      // IN: pt (pointer to bridge)
1435 +#else
1436 +int
1437 +VNetBridgeReceiveFromDev(struct sk_buff *skb,         // IN: packet to receive
1438 +                         struct net_device *dev,      // IN: unused
1439 +                         struct packet_type *pt,      // IN: pt (pointer to bridge)
1440 +                         struct net_device *real_dev) // IN: real device, unused
1441 +#endif
1442 +{
1443 +   VNetBridge *bridge = list_entry(pt, VNetBridge, pt);
1444 +   int i;
1445 +   unsigned long flags;
1446 +
1447 +   if (bridge->dev == NULL) {
1448 +      LOG(3, (KERN_DEBUG "bridge-%s: received %d closed\n",
1449 +             bridge->name, (int) skb->len));
1450 +      dev_kfree_skb(skb);
1451 +      return -EIO;     // value is ignored anyway
1452 +   }
1453 +
1454 +   /*
1455 +    * Check is this is a packet that we sent up to the host, and if
1456 +    * so then don't bother to receive the packet.
1457 +    */
1458 +
1459 +   spin_lock_irqsave(&bridge->historyLock, flags);
1460 +   for (i = 0; i < VNET_BRIDGE_HISTORY; i++) {
1461 +      struct sk_buff *s = bridge->history[i];
1462 +      if (s != NULL &&
1463 +         (s == skb || SKB_IS_CLONE_OF(skb, s))) {
1464 +        bridge->history[i] = NULL;
1465 +        spin_unlock_irqrestore(&bridge->historyLock, flags);
1466 +        dev_kfree_skb(s);
1467 +        LOG(3, (KERN_DEBUG "bridge-%s: receive %d self %d\n",
1468 +                bridge->name, (int) skb->len, i));
1469 +        dev_kfree_skb(skb);
1470 +        return 0;
1471 +      }
1472 +   }
1473 +   spin_unlock_irqrestore(&bridge->historyLock, flags);
1474 +
1475 +#  if LOGLEVEL >= 4
1476 +   {
1477 +      struct timeval now;
1478 +      do_gettimeofday(&now);
1479 +      LOG(3, (KERN_DEBUG "bridge-%s: time %d\n",
1480 +             bridge->name,
1481 +             (int)((now.tv_sec * 1000000 + now.tv_usec)
1482 +                    - (vnetTime.tv_sec * 1000000 + vnetTime.tv_usec))));
1483 +   }
1484 +#  endif
1485 +
1486 +   if (bridge->smac) {
1487 +      if (VNetCallSMACFunc(bridge->smac, &skb, compat_skb_mac_header(skb),
1488 +                           SMAC_CheckPacketFromHost) !=
1489 +          PacketStatusForwardPacket) {
1490 +         LOG(4, (KERN_NOTICE "bridge-%s: packet dropped .\n",
1491 +                 bridge->name));
1492 +        return 0;
1493 +      }
1494 +   }
1495 +
1496 +#ifdef KERNEL_2_3_15
1497 +   skb = skb_share_check(skb, GFP_ATOMIC);
1498 +   if (!skb) {
1499 +      return 0;
1500 +   }
1501 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 4)
1502 +   /*
1503 +    * Unbelievable... Caller sets h.raw = nh.raw before invoking us...
1504 +    */
1505 +   VNetBridgeComputeHeaderPos(skb);
1506 +#endif
1507 +#endif
1508 +
1509 +   skb_push(skb, skb->data - compat_skb_mac_header(skb));
1510 +   LOG(3, (KERN_DEBUG "bridge-%s: receive %d\n",
1511 +          bridge->name, (int) skb->len));
1512 +
1513 +   /*
1514 +    * If this is a large packet, chop chop chop (if supported)...
1515 +    */
1516 +   if (VNetBridgeIsGSO(skb)) {
1517 +      VNetBridgeSendLargePacket(skb, bridge);
1518 +   } else {
1519 +      VNetSend(&bridge->port.jack, skb);
1520 +   }
1521 +
1522 +   return 0;
1523 +}
1524 +
1525 +
1526 +/*
1527 + *----------------------------------------------------------------------
1528 + *
1529 + * VNetBridgeProcRead --
1530 + *
1531 + *      Callback for read operation on this bridge entry in vnets proc fs.
1532 + *
1533 + * Results:
1534 + *      Length of read operation.
1535 + *
1536 + * Side effects:
1537 + *      None.
1538 + *
1539 + *----------------------------------------------------------------------
1540 + */
1541 +
1542 +int
1543 +VNetBridgeProcRead(char    *page,   // IN/OUT: buffer to write into
1544 +                   char   **start,  // OUT: 0 if file < 4k, else offset into page
1545 +                   off_t    off,    // IN: (unused) offset of read into the file
1546 +                   int      count,  // IN: (unused) maximum number of bytes to read
1547 +                   int     *eof,    // OUT: TRUE if there is nothing more to read
1548 +                   void    *data)   // IN: client data - pointer to bridge
1549 +{
1550 +   VNetBridge *bridge = (VNetBridge*)data;
1551 +   int len = 0;
1552 +
1553 +   if (!bridge) {
1554 +      return len;
1555 +   }
1556 +
1557 +   len += VNetPrintPort(&bridge->port, page+len);
1558 +
1559 +   len += sprintf(page+len, "dev %s ", bridge->name);
1560 +
1561 +   len += sprintf(page+len, "\n");
1562 +
1563 +   *start = 0;
1564 +   *eof   = 1;
1565 +   return len;
1566 +}
1567 diff -Nur old/vmware-any-any-update117d/vmnet-only/vmnetInt.h new/vmware-any-any-update117d/vmnet-only/vmnetInt.h
1568 --- old/vmware-any-any-update117d/vmnet-only/vmnetInt.h 2008-08-30 15:50:06.800648000 +0000
1569 +++ new/vmware-any-any-update117d/vmnet-only/vmnetInt.h 2008-08-30 15:59:47.768956250 +0000
1570 @@ -63,7 +63,7 @@
1571  #   define dev_lock_list()    read_lock(&dev_base_lock)
1572  #   define dev_unlock_list()  read_unlock(&dev_base_lock)
1573  #   ifdef VMW_NETDEV_HAS_NET
1574 -#      define DEV_GET(x)      __dev_get_by_name(dev_net((x)->internalDev), (x)->name)
1575 +#      define DEV_GET(x)      __dev_get_by_name((x)->internalDev->nd_net, (x)->name)
1576  #   else
1577  #      define DEV_GET(x)      __dev_get_by_name((x)->name)
1578  #   endif
1579 @@ -89,7 +89,7 @@
1580  
1581  #ifdef VMW_NETDEV_HAS_NET
1582  extern struct proto vmnet_proto;
1583 -#   define compat_sk_alloc(_bri, _pri) sk_alloc(dev_net((_bri)->internalDev), \
1584 +#   define compat_sk_alloc(_bri, _pri) sk_alloc((_bri)->internalDev->nd_net, \
1585                                                  PF_NETLINK, _pri, &vmnet_proto)
1586  #elif defined(VMW_HAVE_SK_ALLOC_WITH_PROTO)
1587  extern struct proto vmnet_proto;
1588 diff -Nur old/vmware-any-any-update117d/vmnet-only/vmnetInt.h~ new/vmware-any-any-update117d/vmnet-only/vmnetInt.h~
1589 --- old/vmware-any-any-update117d/vmnet-only/vmnetInt.h~        1970-01-01 00:00:00.000000000 +0000
1590 +++ new/vmware-any-any-update117d/vmnet-only/vmnetInt.h~        2008-08-30 15:49:59.016161500 +0000
1591 @@ -0,0 +1,157 @@
1592 +/* **********************************************************
1593 + * Copyright 1998 VMware, Inc.  All rights reserved. -- VMware Confidential
1594 + * **********************************************************/
1595 +
1596 +#ifndef __VMNETINT_H__
1597 +#define __VMNETINT_H__
1598 +
1599 +
1600 +#define INCLUDE_ALLOW_MODULE
1601 +#include "includeCheck.h"
1602 +#include "driver-config.h"
1603 +
1604 +
1605 +/*
1606 + * Hide all kernel compatibility stuff in those macros
1607 + */
1608 +
1609 +/* All kernels above 2.6.23 have net namespaces. */
1610 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && !defined(VMW_NETDEV_HAS_NET)
1611 +#   define VMW_NETDEV_HAS_NET
1612 +#endif
1613 +
1614 +/* All kernels above 2.6.23 have skb argument in nf_hookfn. */
1615 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && !defined(VMW_NFHOOK_USES_SKB)
1616 +#   define VMW_NFHOOK_USES_SKB
1617 +#endif
1618 +
1619 +
1620 +#ifdef KERNEL_2_4_0
1621 +#   define compat_fop_set_owner(_pFop) do { \
1622 +   (_pFop)->owner = THIS_MODULE;            \
1623 +} while (0)
1624 +#   define compat_mod_inc_refcount
1625 +#   define compat_mod_dec_refcount
1626 +#else
1627 +#   define compat_fop_set_owner(_pFop)
1628 +#   define compat_mod_inc_refcount do { \
1629 +   MOD_INC_USE_COUNT;                   \
1630 +} while (0)
1631 +#   define compat_mod_dec_refcount do { \
1632 +   MOD_DEC_USE_COUNT;                   \
1633 +} while (0)
1634 +#endif
1635 +
1636 +
1637 +#ifdef skb_shinfo
1638 +#  define SKB_IS_CLONE_OF(clone, skb)   (  \
1639 +      skb_shinfo(clone) == skb_shinfo(skb) \
1640 +   )
1641 +#else
1642 +#  define SKB_IS_CLONE_OF(clone, skb)   (      \
1643 +      skb_datarefp(clone) == skb_datarefp(skb) \
1644 +   )
1645 +#endif
1646 +#define DEV_QUEUE_XMIT(skb, dev, pri)   (                 \
1647 +    (skb)->dev = (dev),                                   \
1648 +    (skb)->priority = (pri),                              \
1649 +    compat_skb_reset_mac_header(skb),                     \
1650 +    compat_skb_set_network_header(skb, sizeof (struct ethhdr)),  \
1651 +    dev_queue_xmit(skb)                                   \
1652 +  )
1653 +#ifdef KERNEL_2_3_15
1654 +#   define dev_lock_list()    read_lock(&dev_base_lock)
1655 +#   define dev_unlock_list()  read_unlock(&dev_base_lock)
1656 +#   ifdef VMW_NETDEV_HAS_NET
1657 +#      define DEV_GET(x)      __dev_get_by_name(dev_net((x)->internalDev), (x)->name)
1658 +#   else
1659 +#      define DEV_GET(x)      __dev_get_by_name((x)->name)
1660 +#   endif
1661 +#else
1662 +#   define DEV_GET(x)         dev_get((x)->name)
1663 +#endif
1664 +
1665 +
1666 +/*
1667 + * Various fields (including 'dead') of struct sock are replaced with the
1668 + * 'flags' bitfield in 2.5.65, with sock_valbool_flag() to set flag's
1669 + * value.  Since 2.5.71 there is sock_set_flag() to set bit to 1, and
1670 + * since 2.6.25-rc1 sock_valbool_flag() is gone.
1671 + */
1672 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 65)
1673 +#   define SET_SK_DEAD(_sk) (_sk)->dead = 1
1674 +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 71)
1675 +#   define SET_SK_DEAD(_sk) sock_valbool_flag(_sk, SOCK_DEAD, 1)
1676 +#else
1677 +#   define SET_SK_DEAD(_sk) sock_set_flag(_sk, SOCK_DEAD)
1678 +#endif
1679 +
1680 +
1681 +#ifdef VMW_NETDEV_HAS_NET
1682 +extern struct proto vmnet_proto;
1683 +#   define compat_sk_alloc(_bri, _pri) sk_alloc(dev_net((_bri)->internalDev), \
1684 +                                                PF_NETLINK, _pri, &vmnet_proto)
1685 +#elif defined(VMW_HAVE_SK_ALLOC_WITH_PROTO)
1686 +extern struct proto vmnet_proto;
1687 +#   define compat_sk_alloc(_bri, _pri) sk_alloc(PF_NETLINK, _pri, &vmnet_proto, 1)
1688 +#elif defined(KERNEL_2_5_5)
1689 +#   define compat_sk_alloc(_bri, _pri) sk_alloc(PF_NETLINK, _pri, 1, NULL)
1690 +#else
1691 +#   define compat_sk_alloc(_bri, _pri) sk_alloc(0, _pri, 1)
1692 +#endif
1693 +
1694 +
1695 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
1696 +#   define fileTraversalLock(lock) spin_lock(lock)
1697 +#   define fileTraversalUnLock(lock) spin_unlock(lock)
1698 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1699 +#   define fileTraversalLock(lock) read_lock(lock)
1700 +#   define fileTraversalUnLock(lock) read_unlock(lock)
1701 +#else //2.2 kernels
1702 +#   define fileTraversalLock(lock) lock_kernel()
1703 +#   define fileTraversalUnLock(lock) unlock_kernel()
1704 +#endif
1705 +
1706 +
1707 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1708 +#   define taskLock(lock) task_lock(lock)
1709 +#   define taskUnLock(lock) task_unlock(lock)
1710 +#else //2.2 kernels
1711 +#   define taskLock(lock) lock_kernel()
1712 +#   define taskUnLock(lock) unlock_kernel()
1713 +#endif
1714 +
1715 +
1716 +/* 
1717 + * Use CHECKSUM_HW for old kernels, if they have CHECKSUM_HW.  Use CHECKSUM_PARTIAL for 
1718 + * new ones even if CHECKSUM_HW is defined.  We do not do decision based on kernel version
1719 + * only as CHECKSUM_PARTIAL was in mm tree for some time already, and we do not test
1720 + * for CHECKSUM_PARTIAL existence as it may get converted to enum in future.
1721 + */
1722 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) && defined(CHECKSUM_HW)
1723 +#   define VM_CHECKSUM_PARTIAL  CHECKSUM_HW
1724 +#else
1725 +#   define VM_CHECKSUM_PARTIAL  CHECKSUM_PARTIAL
1726 +#endif
1727 +
1728 +
1729 +/*
1730 + * The "owner" field in nf_hook_ops got added in 2.5.69
1731 + */
1732 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 69)
1733 +#   define compat_nf_hook_owner  .owner = THIS_MODULE,
1734 +#else
1735 +#   define compat_nf_hook_owner
1736 +#endif
1737 +
1738 +
1739 +#ifdef NF_IP_LOCAL_IN
1740 +#define VMW_NF_INET_LOCAL_IN     NF_IP_LOCAL_IN
1741 +#define VMW_NF_INET_POST_ROUTING NF_IP_POST_ROUTING
1742 +#else
1743 +#define VMW_NF_INET_LOCAL_IN     NF_INET_LOCAL_IN
1744 +#define VMW_NF_INET_POST_ROUTING NF_INET_POST_ROUTING
1745 +#endif
1746 +
1747 +
1748 +#endif /* __VMNETINT_H__ */
This page took 0.398173 seconds and 3 git commands to generate.