Add dummynet(4) support to if_bridge, this code is largely based on bridge.c.

This is the final piece to match bridge.c in functionality, we can now be a
drop-in replacement.

Approved by:	mlaier (mentor)
This commit is contained in:
Andrew Thompson 2005-06-10 01:25:22 +00:00
parent 163baa0542
commit c8b0129238
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=147205
7 changed files with 98 additions and 19 deletions

View File

@ -61,6 +61,7 @@ pipes.
.Sh SEE ALSO
.Xr setsockopt 2 ,
.Xr bridge 4 ,
.Xr if_bridge 4 ,
.Xr ip 4 ,
.Xr ipfw 8 ,
.Xr sysctl 8

View File

@ -107,6 +107,9 @@ to enable enable layer2 filtering with
, set to
.Li 0
to disable it.
This needs to be enabled for
.Xr dummynet 4
support.
When ipfw is enabled pfil_bridge and pfil_member will be disabled so that IPFW
is not run twice, these can be re-enabled if desired.
.El

View File

@ -129,7 +129,6 @@ __FBSDID("$FreeBSD$");
#include <net/route.h>
#include <netinet/ip_fw.h>
#include <netinet/ip_dummynet.h>
#include <net/bridge.h>
#define sc_if ifb_ac.ac_if
/*
@ -178,6 +177,7 @@ static struct mtx bridge_list_mtx;
extern struct mbuf *(*bridge_input_p)(struct ifnet *, struct mbuf *);
extern int (*bridge_output_p)(struct ifnet *, struct mbuf *,
struct sockaddr *, struct rtentry *);
extern void (*bridge_dn_p)(struct mbuf *, struct ifnet *);
int bridge_rtable_prune_period = BRIDGE_RTABLE_PRUNE_PERIOD;
@ -351,6 +351,7 @@ bridge_modevent(module_t mod, int type, void *data)
LIST_INIT(&bridge_list);
bridge_input_p = bridge_input;
bridge_output_p = bridge_output;
bridge_dn_p = bridge_dummynet;
bstp_linkstate_p = bstp_linkstate;
break;
case MOD_UNLOAD:
@ -360,6 +361,7 @@ bridge_modevent(module_t mod, int type, void *data)
uma_zdestroy(bridge_rtnode_zone);
bridge_input_p = NULL;
bridge_output_p = NULL;
bridge_dn_p = NULL;
bstp_linkstate_p = NULL;
mtx_destroy(&bridge_list_mtx);
break;
@ -1270,6 +1272,33 @@ bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m,
(*dst_ifp->if_start)(dst_ifp);
}
/*
* bridge_dummynet:
*
* Receive a queued packet from dummynet and pass it on to the output
* interface.
*
* The mbuf has the Ethernet header already attached.
*/
void
bridge_dummynet(struct mbuf *m, struct ifnet *ifp)
{
struct bridge_softc *sc;
sc = ifp->if_bridge;
/*
* The packet didnt originate from a member interface. This should only
* ever happen if a member interface is removed while packets are
* queued for it.
*/
if (sc == NULL)
m_freem(m);
return;
bridge_enqueue(sc, ifp, m, 1);
}
/*
* bridge_output:
*
@ -2195,7 +2224,7 @@ static int bridge_pfil(struct mbuf **mp, struct ifnet *bifp,
# endif /* INET6 */
break;
default:
/*
/*
* ipfw allows layer2 protocol filtering using
* 'mac-type' so we will let the packet past, if
* ipfw is disabled then drop it.
@ -2214,6 +2243,43 @@ static int bridge_pfil(struct mbuf **mp, struct ifnet *bifp,
m_adj(*mp, sizeof(struct llc));
}
if (IPFW_LOADED && pfil_ipfw != 0 && dir == PFIL_OUT) {
args.rule = ip_dn_claim_rule(*mp);
if (args.rule != NULL && fw_one_pass)
goto ipfwpass; /* packet already partially processed */
args.m = *mp;
args.oif = ifp;
args.next_hop = NULL;
args.eh = &eh2;
i = ip_fw_chk_ptr(&args);
*mp = args.m;
if (*mp == NULL)
return error;
if (DUMMYNET_LOADED && (i == IP_FW_DUMMYNET)) {
/* put the Ethernet header back on */
M_PREPEND(*mp, ETHER_HDR_LEN, M_DONTWAIT);
if (*mp == NULL)
return error;
bcopy(&eh2, mtod(*mp, caddr_t), ETHER_HDR_LEN);
/*
* Pass the pkt to dummynet, which consumes it. The
* packet will return to us via bridge_dummynet().
*/
args.oif = ifp;
ip_dn_io_ptr(*mp, DN_TO_IFB_FWD, &args);
return error;
}
if (i != IP_FW_PASS) /* drop */
goto bad;
}
ipfwpass:
/*
* Check basic packet sanity and run pfil through pfil.
*/
@ -2246,10 +2312,16 @@ static int bridge_pfil(struct mbuf **mp, struct ifnet *bifp,
error = pfil_run_hooks(&inet_pfil_hook, mp, bifp,
dir, NULL);
if (*mp == NULL) /* filter may consume */
break;
if (error == 0 && pfil_member)
error = pfil_run_hooks(&inet_pfil_hook, mp, ifp,
dir, NULL);
if (*mp == NULL) /* filter may consume */
break;
if (error == 0 && pfil_bridge && dir == PFIL_IN)
error = pfil_run_hooks(&inet_pfil_hook, mp, bifp,
dir, NULL);
@ -2270,10 +2342,16 @@ static int bridge_pfil(struct mbuf **mp, struct ifnet *bifp,
error = pfil_run_hooks(&inet6_pfil_hook, mp, bifp,
dir, NULL);
if (*mp == NULL) /* filter may consume */
break;
if (error == 0 && pfil_member)
error = pfil_run_hooks(&inet6_pfil_hook, mp, ifp,
dir, NULL);
if (*mp == NULL) /* filter may consume */
break;
if (error == 0 && pfil_bridge && dir == PFIL_IN)
error = pfil_run_hooks(&inet6_pfil_hook, mp, bifp,
dir, NULL);
@ -2291,22 +2369,6 @@ static int bridge_pfil(struct mbuf **mp, struct ifnet *bifp,
error = -1;
if (IPFW_LOADED && pfil_ipfw != 0) {
args.m = *mp;
args.oif = NULL;
args.next_hop = NULL;
args.rule = NULL;
args.eh = &eh2;
i = ip_fw_chk_ptr(&args);
*mp = args.m;
if (*mp == NULL)
return error;
if (i == IP_FW_DENY) /* drop */
goto bad;
}
/*
* Finally, put everything back the way it was and return
*/

View File

@ -342,6 +342,7 @@ void bridge_rtdelete(struct bridge_softc *, struct ifnet *ifp, int);
int bridge_output(struct ifnet *, struct mbuf *, struct sockaddr *,
struct rtentry *);
void bridge_dummynet(struct mbuf *, struct ifnet *);
struct mbuf *bridge_input(struct ifnet *, struct mbuf *);
extern void (*bstp_linkstate_p)(struct ifnet *ifp, int state);

View File

@ -115,8 +115,9 @@ bdgtakeifaces_t *bdgtakeifaces_ptr;
struct bdg_softc *ifp2sc;
struct mbuf *(*bridge_input_p)(struct ifnet *, struct mbuf *);
int (*bridge_output_p)(struct ifnet *, struct mbuf *,
int (*bridge_output_p)(struct ifnet *, struct mbuf *,
struct sockaddr *, struct rtentry *);
void (*bridge_dn_p)(struct mbuf *, struct ifnet *);
static const u_char etherbroadcastaddr[ETHER_ADDR_LEN] =
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

View File

@ -128,6 +128,8 @@ static struct dn_flow_set *all_flow_sets = NULL ;/* list of all flow_sets */
static struct callout dn_timeout;
extern void (*bridge_dn_p)(struct mbuf *, struct ifnet *);
#ifdef SYSCTL_NODE
SYSCTL_NODE(_net_inet_ip, OID_AUTO, dummynet,
CTLFLAG_RW, 0, "Dummynet");
@ -478,6 +480,14 @@ transmit_event(struct dn_pipe *pipe)
break ;
#endif
case DN_TO_IFB_FWD:
if (bridge_dn_p != NULL)
((*bridge_dn_p)(m, pkt->ifp));
else
printf("dummynet: if_bridge not loaded\n");
break;
case DN_TO_BDG_FWD :
/*
* The bridge requires/assumes the Ethernet header is

View File

@ -126,6 +126,7 @@ struct dn_pkt_tag {
#define DN_TO_ETH_OUT 5
#define DN_TO_IP6_IN 6
#define DN_TO_IP6_OUT 7
#define DN_TO_IFB_FWD 8
dn_key output_time; /* when the pkt is due for delivery */
struct ifnet *ifp; /* interface, for ip_output */