summaryrefslogtreecommitdiffstats
path: root/sys/netgraph/ng_fec.c
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2004-06-20 21:08:58 +0000
committerwpaul <wpaul@FreeBSD.org>2004-06-20 21:08:58 +0000
commit0d2c5309add400692dc414bfd73e76d49fb9d111 (patch)
tree7eda1f1e629a65ce9b9276e044d97dae22154662 /sys/netgraph/ng_fec.c
parent1450b79b4f3a246082640543e67b20df10d1555d (diff)
downloadFreeBSD-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.c44
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);
OpenPOWER on IntegriCloud