diff options
author | wpaul <wpaul@FreeBSD.org> | 2004-06-20 21:08:58 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 2004-06-20 21:08:58 +0000 |
commit | 0d2c5309add400692dc414bfd73e76d49fb9d111 (patch) | |
tree | 7eda1f1e629a65ce9b9276e044d97dae22154662 /sys/netgraph/ng_fec.c | |
parent | 1450b79b4f3a246082640543e67b20df10d1555d (diff) | |
download | FreeBSD-src-0d2c5309add400692dc414bfd73e76d49fb9d111.zip FreeBSD-src-0d2c5309add400692dc414bfd73e76d49fb9d111.tar.gz |
Remove one more unneeded reference to arpcom.ac_netgraph.
Tweak things so that ng_fec has a chance of working with things
other than ethernet. Use ifp->if_output of the underlying interfaces
and use IF_HANDOFF() rather than depending on ether_output() and
ether_output_frame() explicitly. Also, don't insist that underlying
devices be IFM_ETHER when checking their link states in the link
monitor code.
With these changes, I was able to create a two channel bundle
consisting of one ethernet interface and one 802.11 wireless
device (via ndis). Note that this only works because both devices
use the same if_output vector: ng_fec will not let you bundle
devices with different output vectors together (it really doesn't
make sense to do that).
Diffstat (limited to 'sys/netgraph/ng_fec.c')
-rw-r--r-- | sys/netgraph/ng_fec.c | 44 |
1 files changed, 34 insertions, 10 deletions
diff --git a/sys/netgraph/ng_fec.c b/sys/netgraph/ng_fec.c index 31b0d9d..5997162 100644 --- a/sys/netgraph/ng_fec.c +++ b/sys/netgraph/ng_fec.c @@ -130,8 +130,8 @@ * ifnet structure so that receive handling works. As far as I can * tell, although there is an AF_NETGRAPH address family, it's only * used to identify sockaddr_ng structures: there is no netgraph address - * family domain. This means the AF_NETGRAPH entry in ifp->if_afdata[] - * should be unused, so we can (ab)use it to hold our node context. + * family domain. This means the AF_NETGRAPH entry in ifp->if_afdata + * should be unused, so we can use to hold our node context. */ #define IFP2NG(ifp) (struct ng_node *)(ifp->if_afdata[AF_NETGRAPH]) #define FEC_INC(x, y) (x) = (x + 1) % y @@ -144,7 +144,8 @@ struct ng_fec_portlist { struct ifnet *fec_if; - void (*fec_if_input) (struct ifnet *, struct mbuf *); + void (*fec_if_input) (struct ifnet *, + struct mbuf *); int fec_idx; int fec_ifstat; struct ether_addr fec_mac; @@ -155,6 +156,10 @@ struct ng_fec_bundle { TAILQ_HEAD(,ng_fec_portlist) ng_fec_ports; int fec_ifcnt; int fec_btype; + int (*fec_if_output) (struct ifnet *, + struct mbuf *, + struct sockaddr *, + struct rtentry *); }; #define FEC_BTYPE_MAC 0x01 @@ -362,6 +367,20 @@ ng_fec_addport(struct ng_fec_private *priv, char *iface) } } + /* + * All interfaces must use the same output vector. Once the + * user attaches an interface of one type, make all subsequent + * interfaces have the same output vector. + */ + if (b->fec_if_output != NULL) { + if (b->fec_if_output != bifp->if_output) { + printf("fec%d: iface %s is not the same type " + "as the other interface(s) already in " + "the bundle\n", priv->unit, iface); + return(EINVAL); + } + } + /* Allocate new list entry. */ MALLOC(new, struct ng_fec_portlist *, sizeof(struct ng_fec_portlist), M_NETGRAPH, M_NOWAIT); @@ -408,6 +427,10 @@ ng_fec_addport(struct ng_fec_private *priv, char *iface) /* Override it with our own */ bifp->if_input = ng_fec_input; + /* Save output vector too. */ + if (b->fec_if_output == NULL) + b->fec_if_output = bifp->if_output; + /* Add to the queue */ new->fec_if = bifp; TAILQ_INSERT_TAIL(&b->ng_fec_ports, new, fec_list); @@ -474,6 +497,9 @@ ng_fec_delport(struct ng_fec_private *priv, char *iface) FREE(p, M_NETGRAPH); b->fec_ifcnt--; + if (b->fec_ifcnt == 0) + b->fec_if_output = NULL; + return(0); } @@ -581,8 +607,7 @@ ng_fec_tick(void *arg) continue; } - if (ifmr.ifm_status & IFM_AVALID && - IFM_TYPE(ifmr.ifm_active) == IFM_ETHER) { + if (ifmr.ifm_status & IFM_AVALID) { if (ifmr.ifm_status & IFM_ACTIVE) { if (p->fec_ifstat == -1 || p->fec_ifstat == 0) { @@ -788,7 +813,7 @@ ng_fec_input(struct ifnet *ifp, struct mbuf *m0) * Take a quick peek at the packet and see if it's ok for us to use * the inet or inet6 hash methods on it, if they're enabled. We do * this by setting flags in the mbuf header. Once we've made up our - * mind what to do, we pass the frame to ether_output() for further + * mind what to do, we pass the frame to output vector for further * processing. */ @@ -842,12 +867,12 @@ ng_fec_output(struct ifnet *ifp, struct mbuf *m, } /* - * Pass the frame to ether_output() for all the protocol + * Pass the frame to the output vector for all the protocol * handling. This will put the ethernet header on the packet * for us. */ priv->if_error = 0; - error = ether_output(ifp, m, dst, rt0); + error = (*b->fec_if_output)(ifp, m, dst, rt0); if (priv->if_error && !error) error = priv->if_error; @@ -1007,7 +1032,7 @@ ng_fec_start(struct ifnet *ifp) } ifp->if_opackets++; - priv->if_error = ether_output_frame(oifp, m0); + priv->if_error = IF_HANDOFF(&oifp->if_snd, m0, oifp) ? 0 : ENOBUFS; return; } @@ -1085,7 +1110,6 @@ ng_fec_constructor(node_p node) /* Link together node and private info */ NG_NODE_SET_PRIVATE(node, priv); priv->node = node; - priv->arpcom.ac_netgraph = node; /* Initialize interface structure */ if_initname(ifp, NG_FEC_FEC_NAME, priv->unit); |