VBoxNetFlt.c revision 40295ab70cb24d4b45580b9e03766935cca282ab
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * VBoxNetFlt - Network Filter Driver (Host), Common Code.
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * Copyright (C) 2008-2012 Oracle Corporation
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * available from http://www.virtualbox.org. This file is free software;
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * you can redistribute it and/or modify it under the terms of the GNU
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * General Public License (GPL) as published by the Free Software
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
9b6c3413bf8a8eda0e1b71fda8ce7f7289470f0evboxsync/** @page pg_netflt VBoxNetFlt - Network Interface Filter
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * This is a kernel module that attaches to a real interface on the host and
41a5daa2596de76f4977055944c7ff54a0afdc3avboxsync * filters and injects packets.
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * In the big picture we're one of the three trunk interface on the internal
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * network, the one named "NIC Filter Driver": @image html Networking_Overview.gif
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * @section sec_netflt_locking Locking and Potential Races
dcd68204fbfce8a2703fde4a6decb9ccb2054b39vboxsync * The main challenge here is to make sure the netfilter and internal network
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * instances won't be destroyed while someone is calling into them.
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * The main calls into or out of of the filter driver are:
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * - Async send completion (not implemented yet)
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * - Release by the internal network.
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * - Receive.
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * - Disappearance of the host networking interface.
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * - Reappearance of the host networking interface.
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * The latter two calls are can be caused by driver unloading/loading or the
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * device being physical unplugged (e.g. a USB network device). Actually, the
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * unload scenario must fervently be prevent as it will cause panics because the
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * internal network will assume the trunk is around until it releases it.
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * @todo Need to figure which host allow unloading and block/fix it.
25798ffda5d17be278d15c265ade35ac15b2146bvboxsync * Currently the netfilter instance lives until the internal network releases
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * it. So, it is the internal networks responsibility to make sure there are no
5b802b5e11fed6e163afca32e9118d2599d312fbvboxsync * active calls when it releases the trunk and destroys the network. The
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * netfilter assists in this by providing INTNETTRUNKIFPORT::pfnSetState and
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * INTNETTRUNKIFPORT::pfnWaitForIdle. The trunk state is used to enable/disable
25798ffda5d17be278d15c265ade35ac15b2146bvboxsync * promiscuous mode on the hardware NIC (or similar activation) as well
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * indicating that disconnect is imminent and no further calls shall be made
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * into the internal network. After changing the state to disconnecting and
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * prior to invoking INTNETTRUNKIFPORT::pfnDisconnectAndRelease, the internal
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * network will use INTNETTRUNKIFPORT::pfnWaitForIdle to wait for any still
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * active calls to complete.
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * The netfilter employs a busy counter and an internal state in addition to the
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * public trunk state. All these variables are protected using a spinlock.
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * @section sec_netflt_msc Locking / Sequence Diagrams - OBSOLETE
5b802b5e11fed6e163afca32e9118d2599d312fbvboxsync * !OBSOLETE! - THIS WAS THE OLD APPROACH!
a996fbbf1ca46be54ed995ceddf1e6b035b6ef6cvboxsync * This secion contains a few sequence diagrams describing the problematic
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * transitions of a host interface filter instance.
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * The thing that makes it all a bit problematic is that multiple events may
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * happen at the same time, and that we have to be very careful to avoid
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * deadlocks caused by mixing our locks with the ones in the host kernel. The
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * main events are receive, send, async send completion, disappearance of the
526dfa543052a069767fbb88f438459378bef5fcvboxsync * host networking interface and its reappearance. The latter two events are
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * can be caused by driver unloading/loading or the device being physical
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * unplugged (e.g. a USB network device).
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * The strategy for dealing with these issues are:
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * - Use a simple state machine.
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * - Require the user (IntNet) to serialize all its calls to us,
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * while at the same time not owning any lock used by any of the
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * the callbacks we might call on receive and async send completion.
6df37320db2ea21e05e1f89e5824022b449b387dvboxsync * - Make sure we're 100% idle before disconnecting, and have a
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * disconnected status on both sides to fend off async calls.
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * - Protect the host specific interface handle and the state variables
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * using a spinlock.
6df37320db2ea21e05e1f89e5824022b449b387dvboxsync * @subsection subsec_netflt_msc_dis_rel Disconnect from the network and release - OBSOLETE
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * VM, IntNet, NetFlt, Kernel, Wire;
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * VM->IntNet [label="pkt0", linecolor="green", textcolor="green"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet=>IntNet [label="Lock Network", linecolor="green", textcolor="green" ];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet=>IntNet [label="Route packet -> wire", linecolor="green", textcolor="green" ];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet=>IntNet [label="Unlock Network", linecolor="green", textcolor="green" ];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet=>NetFlt [label="pkt0 to wire", linecolor="green", textcolor="green" ];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt=>Kernel [label="pkt0 to wire", linecolor="green", textcolor="green"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * Kernel->Wire [label="pkt0 to wire", linecolor="green", textcolor="green"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * --- [label="Suspending the trunk interface"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet=>IntNet [label="Lock Network"];
b26266e64cc81dd32722cade8418604d66f2ac3avboxsync * Wire->Kernel [label="pkt1 - racing us", linecolor="red", textcolor="red"];
b26266e64cc81dd32722cade8418604d66f2ac3avboxsync * Kernel=>>NetFlt [label="pkt1 - racing us", linecolor="red", textcolor="red"];
b26266e64cc81dd32722cade8418604d66f2ac3avboxsync * NetFlt=>>IntNet [label="pkt1 recv - blocks", linecolor="red", textcolor="red"];
b26266e64cc81dd32722cade8418604d66f2ac3avboxsync * IntNet=>IntNet [label="Mark Trunk Suspended"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet=>IntNet [label="Unlock Network"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet=>NetFlt [label="pfnSetActive(false)"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt=>NetFlt [label="Mark inactive (atomic)"];
a996fbbf1ca46be54ed995ceddf1e6b035b6ef6cvboxsync * IntNet<<NetFlt;
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet=>NetFlt [label="pfnWaitForIdle(forever)"];
a996fbbf1ca46be54ed995ceddf1e6b035b6ef6cvboxsync * IntNet=>>NetFlt [label="pkt1 to host", linecolor="red", textcolor="red"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt=>>Kernel [label="pkt1 to host", linecolor="red", textcolor="red"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * Kernel<-Wire [label="pkt0 on wire", linecolor="green", textcolor="green"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt<<Kernel [label="pkt0 on wire", linecolor="green", textcolor="green"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet<<=NetFlt [label="pfnSGRelease", linecolor="green", textcolor="green"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet<<=IntNet [label="Lock Net, free SG, Unlock Net", linecolor="green", textcolor="green"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet>>NetFlt [label="pfnSGRelease", linecolor="green", textcolor="green"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt<-NetFlt [label="idle", linecolor="green", textcolor="green"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet<<NetFlt [label="idle (pfnWaitForIdle)"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * Wire->Kernel [label="pkt2", linecolor="red", textcolor="red"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * Kernel=>>NetFlt [label="pkt2", linecolor="red", textcolor="red"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt=>>Kernel [label="pkt2 to host", linecolor="red", textcolor="red"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * VM->IntNet [label="pkt3", linecolor="green", textcolor="green"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet=>IntNet [label="Lock Network", linecolor="green", textcolor="green" ];
a996fbbf1ca46be54ed995ceddf1e6b035b6ef6cvboxsync * IntNet=>IntNet [label="Route packet -> drop", linecolor="green", textcolor="green" ];
a996fbbf1ca46be54ed995ceddf1e6b035b6ef6cvboxsync * IntNet=>IntNet [label="Unlock Network", linecolor="green", textcolor="green" ];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * --- [label="The trunk interface is idle now, disconnect it"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet=>IntNet [label="Lock Network"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet=>IntNet [label="Unlink Trunk"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet=>IntNet [label="Unlock Network"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet=>NetFlt [label="pfnDisconnectAndRelease"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt=>Kernel [label="iflt_detach"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt<<=Kernel [label="iff_detached"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt>>Kernel [label="iff_detached"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt<<Kernel [label="iflt_detach"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt=>NetFlt [label="Release"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet<<NetFlt [label="pfnDisconnectAndRelease"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * @subsection subsec_netflt_msc_hif_rm Host Interface Removal - OBSOLETE
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * The ifnet_t (pIf) is a tricky customer as any reference to it can potentially
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * race the filter detaching. The simple way of solving it on Darwin is to guard
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * all access to the pIf member with a spinlock. The other host systems will
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * probably have similar race conditions, so the spinlock is a generic thing.
46fea8848077384c07f8ab6da815c6a83a2fc1f1vboxsync * VM, IntNet, NetFlt, Kernel;
46fea8848077384c07f8ab6da815c6a83a2fc1f1vboxsync * VM->IntNet [label="pkt0", linecolor="green", textcolor="green"];
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * IntNet=>IntNet [label="Lock Network", linecolor="green", textcolor="green" ];
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * IntNet=>IntNet [label="Route packet -> wire", linecolor="green", textcolor="green" ];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet=>IntNet [label="Unlock Network", linecolor="green", textcolor="green" ];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet=>NetFlt [label="pkt0 to wire", linecolor="green", textcolor="green" ];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt=>Kernel [label="ifnet_reference w/ spinlock", linecolor="green", textcolor="green" ];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt<<Kernel [label="ifnet_reference", linecolor="green", textcolor="green" ];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt=>Kernel [label="pkt0 to wire (blocks)", linecolor="green", textcolor="green" ];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * --- [label="The host interface is being disconnected"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * Kernel->NetFlt [label="iff_detached"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt=>Kernel [label="ifnet_release w/ spinlock"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt<<Kernel [label="ifnet_release"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt=>NetFlt [label="fDisconnectedFromHost=true"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt>>Kernel [label="iff_detached"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt<<Kernel [label="dropped", linecolor="green", textcolor="green"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt=>NetFlt [label="Acquire spinlock", linecolor="green", textcolor="green"];
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * NetFlt=>Kernel [label="ifnet_release", linecolor="green", textcolor="green"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt<<Kernel [label="ifnet_release", linecolor="green", textcolor="green"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt=>NetFlt [label="pIf=NULL", linecolor="green", textcolor="green"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt=>NetFlt [label="Release spinlock", linecolor="green", textcolor="green"];
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * IntNet<=NetFlt [label="pfnSGRelease", linecolor="green", textcolor="green"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet>>NetFlt [label="pfnSGRelease", linecolor="green", textcolor="green"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet<<NetFlt [label="pkt0 to wire", linecolor="green", textcolor="green"];
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * @subsection subsec_netflt_msc_hif_rm Host Interface Rediscovery - OBSOLETE
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * The rediscovery is performed when we receive a send request and a certain
a0a9f39e8864357c2e1e61106958411240f5bf6bvboxsync * period have elapsed since the last attempt, i.e. we're polling it. We
a0a9f39e8864357c2e1e61106958411240f5bf6bvboxsync * synchronize the rediscovery with disconnection from the internal network
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * by means of the pfnWaitForIdle call, so no special handling is required.
25798ffda5d17be278d15c265ade35ac15b2146bvboxsync * VM2, VM1, IntNet, NetFlt, Kernel, Wire;
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * --- [label="Rediscovery conditions are not met"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * VM1->IntNet [label="pkt0"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet=>IntNet [label="Lock Network"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet=>IntNet [label="Route packet -> wire"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet=>IntNet [label="Unlock Network"];
25798ffda5d17be278d15c265ade35ac15b2146bvboxsync * IntNet=>NetFlt [label="pkt0 to wire"];
25798ffda5d17be278d15c265ade35ac15b2146bvboxsync * NetFlt=>NetFlt [label="Read pIf(==NULL) w/ spinlock"];
25798ffda5d17be278d15c265ade35ac15b2146bvboxsync * IntNet<<NetFlt [label="pkt0 to wire (dropped)"];
25798ffda5d17be278d15c265ade35ac15b2146bvboxsync * --- [label="Rediscovery conditions"];
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * VM1->IntNet [label="pkt1"];
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * IntNet=>IntNet [label="Lock Network"];
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * IntNet=>IntNet [label="Route packet -> wire"];
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * IntNet=>IntNet [label="Unlock Network"];
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * IntNet=>NetFlt [label="pkt1 to wire"];
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * NetFlt=>NetFlt [label="Read pIf(==NULL) w/ spinlock"];
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * NetFlt=>NetFlt [label="fRediscoveryPending=true w/ spinlock"];
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * NetFlt=>Kernel [label="ifnet_find_by_name"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt<<Kernel [label="ifnet_find_by_name (success)"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * VM2->IntNet [label="pkt2", linecolor="red", textcolor="red"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet=>IntNet [label="Lock Network", linecolor="red", textcolor="red"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet=>IntNet [label="Route packet -> wire", linecolor="red", textcolor="red"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet=>IntNet [label="Unlock Network", linecolor="red", textcolor="red"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet=>NetFlt [label="pkt2 to wire", linecolor="red", textcolor="red"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt=>NetFlt [label="!pIf || fRediscoveryPending (w/ spinlock)", linecolor="red", textcolor="red"];
5b802b5e11fed6e163afca32e9118d2599d312fbvboxsync * IntNet<<NetFlt [label="pkt2 to wire (dropped)", linecolor="red", textcolor="red"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt=>Kernel [label="iflt_attach"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt<<Kernel [label="iflt_attach (success)"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt=>NetFlt [label="Acquire spinlock"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt=>NetFlt [label="Set pIf and update flags"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt=>NetFlt [label="Release spinlock"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt=>Kernel [label="pkt1 to wire"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * Kernel->Wire [label="pkt1 to wire"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * NetFlt<<Kernel [label="pkt1 to wire"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * IntNet<<NetFlt [label="pkt1 to wire"];
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync/*******************************************************************************
cf8fa49133dc7d885c6e8da467c7335d6f45327fvboxsync* Header Files *
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync*******************************************************************************/
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync/*******************************************************************************
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync* Defined Constants And Macros *
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync*******************************************************************************/
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync ( (PVBOXNETFLTINS)((uint8_t *)pIfPort - RT_OFFSETOF(VBOXNETFLTINS, MyPort)) )
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsyncAssertCompileMemberSize(VBOXNETFLTINS, enmState, sizeof(uint32_t));
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * Sets the enmState member atomically.
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * Used for all updates.
25798ffda5d17be278d15c265ade35ac15b2146bvboxsync * @param pThis The instance.
25798ffda5d17be278d15c265ade35ac15b2146bvboxsync * @param enmNewState The new value.
25798ffda5d17be278d15c265ade35ac15b2146bvboxsyncDECLINLINE(void) vboxNetFltSetState(PVBOXNETFLTINS pThis, VBOXNETFTLINSSTATE enmNewState)
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmState, enmNewState);
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * Gets the enmState member atomically.
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * Used for all reads.
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * @returns The enmState value.
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * @param pThis The instance.
d766e56621531afa7cc104d93a53697d293f4bfbvboxsyncDECLINLINE(VBOXNETFTLINSSTATE) vboxNetFltGetState(PVBOXNETFLTINS pThis)
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync return (VBOXNETFTLINSSTATE)ASMAtomicUoReadU32((uint32_t volatile *)&pThis->enmState);
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * Finds a instance by its name, the caller does the locking.
25798ffda5d17be278d15c265ade35ac15b2146bvboxsync * @returns Pointer to the instance by the given name. NULL if not found.
25798ffda5d17be278d15c265ade35ac15b2146bvboxsync * @param pGlobals The globals.
25798ffda5d17be278d15c265ade35ac15b2146bvboxsync * @param pszName The name of the instance.
ceac9502f79429220abff899f1cd07e7aba68cb9vboxsyncstatic PVBOXNETFLTINS vboxNetFltFindInstanceLocked(PVBOXNETFLTGLOBALS pGlobals, const char *pszName)
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync for (pCur = pGlobals->pInstanceHead; pCur; pCur = pCur->pNext)
25798ffda5d17be278d15c265ade35ac15b2146bvboxsync * Finds a instance by its name, will request the mutex.
25798ffda5d17be278d15c265ade35ac15b2146bvboxsync * No reference to the instance is retained, we're assuming the caller to
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * already have one but just for some reason doesn't have the pointer to it.
d766e56621531afa7cc104d93a53697d293f4bfbvboxsync * @returns Pointer to the instance by the given name. NULL if not found.
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * @param pGlobals The globals.
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * @param pszName The name of the instance.
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsyncDECLHIDDEN(PVBOXNETFLTINS) vboxNetFltFindInstance(PVBOXNETFLTGLOBALS pGlobals, const char *pszName)
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync int rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync pRet = vboxNetFltFindInstanceLocked(pGlobals, pszName);
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * Unlinks an instance from the chain.
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * @param pGlobals The globals.
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * @param pToUnlink The instance to unlink.
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsyncstatic void vboxNetFltUnlinkLocked(PVBOXNETFLTGLOBALS pGlobals, PVBOXNETFLTINS pToUnlink)
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync for (pCur = pGlobals->pInstanceHead; pCur; pCur = pCur->pNext)
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * Performs interface rediscovery if it was disconnected from the host.
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * @returns true if successfully rediscovered and connected, false if not.
dd770e74b6654ce0e5584dbd4ec72e90fd4cc58fvboxsync * @param pThis The instance.
bool fRediscovered;
bool fDoIt;
if (fDoIt)
if (fDoIt)
if (fRediscovered)
return fRediscovered;
static DECLCALLBACK(int) vboxNetFltPortXmit(PINTNETTRUNKIFPORT pIfPort, void *pvIfData, PINTNETSG pSG, uint32_t fDst)
return rc;
int rc;
return rc;
static DECLCALLBACK(INTNETTRUNKIFSTATE) vboxNetFltPortSetState(PINTNETTRUNKIFPORT pIfPort, INTNETTRUNKIFSTATE enmState)
AssertReturn(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected, INTNETTRUNKIFSTATE_INVALID);
return enmOldTrunkState;
static DECLCALLBACK(void) vboxNetFltPortNotifyMacAddress(PINTNETTRUNKIFPORT pIfPort, void *pvIfData, PCRTMAC pMac)
static DECLCALLBACK(int) vboxNetFltPortConnectInterface(PINTNETTRUNKIFPORT pIfPort, void *pvIf, void **ppvIfData)
int rc;
return rc;
static DECLCALLBACK(void) vboxNetFltPortDisconnectInterface(PINTNETTRUNKIFPORT pIfPort, void *pvIfData)
int rc;
#ifdef VBOXNETFLT_STATIC_CONFIG
int rc;
#ifdef VBOXNETFLT_STATIC_CONFIG
if (fBusy)
if (!cRefs)
if (!cRefs)
#ifdef VBOX_WITH_INTNET_DISCONNECT
if (fBusy)
bool fRc;
if (fRc)
return fRc;
bool fRc;
if (fRc)
return fRc;
static int vboxNetFltConnectIt(PVBOXNETFLTINS pThis, PINTNETTRUNKSWPORT pSwitchPort, PINTNETTRUNKIFPORT *ppIfPort)
int rc;
#ifdef VBOXNETFLT_STATIC_CONFIG
return rc;
static int vboxNetFltNewInstance(PVBOXNETFLTGLOBALS pGlobals, const char *pszName, PINTNETTRUNKSWPORT pSwitchPort,
int rc;
if (!pNew)
return VERR_INTNET_FLT_IF_FAILED;
#ifdef VBOXNETFLT_STATIC_CONFIG
#ifdef VBOXNETFLT_STATIC_CONFIG
return rc;
return rc;
return rc;
#ifdef VBOXNETFLT_STATIC_CONFIG
DECLHIDDEN(int) vboxNetFltSearchCreateInstance(PVBOXNETFLTGLOBALS pGlobals, const char *pszName, PVBOXNETFLTINS *ppInstance, void *pvContext)
int rc;
while (pCur)
switch (enmState)
return VINF_ALREADY_INITIALIZED;
LogRel(("VBoxNetFlt: Huh? An instance of '%s' already exists! [pCur=%p cRefs=%d fDfH=%RTbool enmState=%d]\n",
return VERR_INTNET_FLT_IF_BUSY;
# ifdef RT_STRICT
return rc;
static DECLCALLBACK(int) vboxNetFltFactoryCreateAndConnect(PINTNETTRUNKFACTORY pIfFactory, const char *pszName,
PVBOXNETFLTGLOBALS pGlobals = (PVBOXNETFLTGLOBALS)((uint8_t *)pIfFactory - RT_OFFSETOF(VBOXNETFLTGLOBALS, TrunkFactory));
int rc;
LogFlow(("vboxNetFltFactoryCreateAndConnect: pszName=%p:{%s} fFlags=%#x\n", pszName, pszName, fFlags));
if (pCur)
#ifdef VBOXNETFLT_STATIC_CONFIG
if (pCur)
return rc;
#ifdef VBOXNETFLT_STATIC_CONFIG
NULL,
ppIfPort);
return rc;
PVBOXNETFLTGLOBALS pGlobals = (PVBOXNETFLTGLOBALS)((uint8_t *)pIfFactory - RT_OFFSETOF(VBOXNETFLTGLOBALS, TrunkFactory));
static DECLCALLBACK(void *) vboxNetFltQueryFactoryInterface(PCSUPDRVFACTORY pSupDrvFactory, PSUPDRVSESSION pSession, const char *pszInterfaceUuid)
PVBOXNETFLTGLOBALS pGlobals = (PVBOXNETFLTGLOBALS)((uint8_t *)pSupDrvFactory - RT_OFFSETOF(VBOXNETFLTGLOBALS, SupDrvFactory));
#ifdef LOG_ENABLED
return NULL;
return fRc;
int rc;
return VERR_WRONG_ORDER;
return VERR_WRONG_ORDER;
return rc;
int rc;
rc = SUPR0IdcOpen(&pGlobals->SupDrvIDC, 0 /* iReqVersion = default */, 0 /* iMinVersion = default */, NULL, NULL, NULL);
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;