]>
Commit | Line | Data |
---|---|---|
867ec289 AA |
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__ */ |