summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2015-02-08 06:00:53 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2015-02-08 06:00:53 +0000
commit5abebbaf769b6ddee8d1917eabd364eb0a44a4f0 (patch)
treefb4f1179540b6c1512cf78bdf4486f5fc051353c
parent32886a8e2b071ec25ba70187f55b9701d56ff70f (diff)
Introduce if_input() a function to pass packets dequeued from a
recieving ring to the stack. if_input() is at the moment a drop-in replacement for ether_input_mbuf() but will let us stack pseudo-driver in a nice way in order to no longer call ether_input() recursively. ok pelikan@, reyk@, blambert@, henning@
-rw-r--r--sys/net/if.c23
-rw-r--r--sys/net/if.h3
-rw-r--r--sys/net/if_ethersubr.c49
-rw-r--r--sys/net/if_var.h17
4 files changed, 71 insertions, 21 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index 6b83e3dbdf9..2dcdc636105 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.c,v 1.316 2015/02/05 10:28:50 henning Exp $ */
+/* $OpenBSD: if.c,v 1.317 2015/02/08 06:00:52 mpi Exp $ */
/* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
/*
@@ -431,6 +431,27 @@ if_start(struct ifnet *ifp)
}
void
+if_input(struct ifnet *ifp, struct mbuf *m)
+{
+ struct ifih *ifih;
+
+ splassert(IPL_NET);
+
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.ph_rtableid = ifp->if_rdomain;
+
+#if NBPFILTER > 0
+ if (ifp->if_bpf)
+ bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_IN);
+#endif
+
+ SLIST_FOREACH(ifih, &ifp->if_inputs, ifih_next) {
+ if ((*ifih->ifih_input)(ifp, NULL, m))
+ break;
+ }
+}
+
+void
nettxintr(void)
{
struct ifnet *ifp;
diff --git a/sys/net/if.h b/sys/net/if.h
index 4bf6a686d3d..b80e4c30b04 100644
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.h,v 1.159 2015/01/06 21:26:46 stsp Exp $ */
+/* $OpenBSD: if.h,v 1.160 2015/02/08 06:00:52 mpi Exp $ */
/* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */
/*
@@ -462,7 +462,6 @@ int if_delgroup(struct ifnet *, const char *);
void if_group_routechange(struct sockaddr *, struct sockaddr *);
struct ifnet *ifunit(const char *);
struct ifnet *if_get(unsigned int);
-void if_start(struct ifnet *);
void ifnewlladdr(struct ifnet *);
#endif /* _KERNEL */
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 507bd461080..07be9fb9e5f 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ethersubr.c,v 1.186 2015/02/06 16:00:30 benno Exp $ */
+/* $OpenBSD: if_ethersubr.c,v 1.187 2015/02/08 06:00:52 mpi Exp $ */
/* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $ */
/*
@@ -445,9 +445,10 @@ bad:
* the packet is in the mbuf chain m without
* the ether header, which is provided separately.
*/
-void
-ether_input(struct ifnet *ifp0, struct ether_header *eh, struct mbuf *m)
+int
+ether_input(struct ifnet *ifp0, void *hdr, struct mbuf *m)
{
+ struct ether_header *eh = hdr;
struct ifqueue *inq;
u_int16_t etype;
int s, llcfound = 0;
@@ -474,10 +475,10 @@ ether_input(struct ifnet *ifp0, struct ether_header *eh, struct mbuf *m)
while (ifp->if_type == IFT_IEEE8023ADLAG) {
if (++i > TRUNK_MAX_STACKING) {
m_freem(m);
- return;
+ return (1);
}
if (trunk_input(ifp, eh, m) != 0)
- return;
+ return (1);
/* Has been set to the trunk interface */
ifp = m->m_pkthdr.rcvif;
@@ -486,7 +487,7 @@ ether_input(struct ifnet *ifp0, struct ether_header *eh, struct mbuf *m)
if ((ifp->if_flags & IFF_UP) == 0) {
m_freem(m);
- return;
+ return (1);
}
if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
/*
@@ -497,7 +498,7 @@ ether_input(struct ifnet *ifp0, struct ether_header *eh, struct mbuf *m)
if (memcmp(LLADDR(ifp->if_sadl), eh->ether_shost,
ETHER_ADDR_LEN) == 0) {
m_freem(m);
- return;
+ return (1);
}
}
@@ -529,7 +530,7 @@ ether_input(struct ifnet *ifp0, struct ether_header *eh, struct mbuf *m)
#if NVLAN > 0
if (((m->m_flags & M_VLANTAG) || etype == ETHERTYPE_VLAN ||
etype == ETHERTYPE_QINQ) && (vlan_input(eh, m) == 0))
- return;
+ return (1);
#endif
#if NBRIDGE > 0
@@ -545,7 +546,7 @@ ether_input(struct ifnet *ifp0, struct ether_header *eh, struct mbuf *m)
else {
m = bridge_input(ifp, eh, m);
if (m == NULL)
- return;
+ return (1);
/* The bridge has determined it's for us. */
ifp = m->m_pkthdr.rcvif;
}
@@ -558,14 +559,14 @@ ether_input(struct ifnet *ifp0, struct ether_header *eh, struct mbuf *m)
/* The bridge did not want the vlan frame either, drop it. */
ifp->if_noproto++;
m_freem(m);
- return;
+ return (1);
}
#endif /* NVLAN > 0 */
#if NCARP > 0
if (ifp->if_carp) {
if (ifp->if_type != IFT_CARP && (carp_input(ifp, eh, m) == 0))
- return;
+ return (1);
/* clear mcast if received on a carp IP balanced address */
else if (ifp->if_type == IFT_CARP &&
m->m_flags & (M_BCAST|M_MCAST) &&
@@ -581,7 +582,7 @@ ether_input(struct ifnet *ifp0, struct ether_header *eh, struct mbuf *m)
*/
if (m->m_flags & M_FILDROP) {
m_freem(m);
- return;
+ return (1);
}
/*
@@ -592,7 +593,7 @@ ether_input(struct ifnet *ifp0, struct ether_header *eh, struct mbuf *m)
((ifp->if_flags & IFF_PROMISC) || (ifp0->if_flags & IFF_PROMISC))) {
if (memcmp(ac->ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN)) {
m_freem(m);
- return;
+ return (1);
}
}
@@ -706,6 +707,7 @@ decapsulate:
IF_INPUT_ENQUEUE(inq, m);
done:
splx(s);
+ return (1);
}
/*
@@ -752,6 +754,9 @@ ether_fakeaddr(struct ifnet *ifp)
void
ether_ifattach(struct ifnet *ifp)
{
+ struct arpcom *ac = (struct arpcom *)ifp;
+ struct ifih *ether_ifih;
+
/*
* Any interface which provides a MAC address which is obviously
* invalid gets whacked, so that users will notice.
@@ -764,14 +769,18 @@ ether_ifattach(struct ifnet *ifp)
ifp->if_hdrlen = ETHER_HDR_LEN;
ifp->if_mtu = ETHERMTU;
ifp->if_output = ether_output;
+ SLIST_INIT(&ifp->if_inputs);
+
+ ether_ifih = malloc(sizeof(*ether_ifih), M_DEVBUF, M_WAITOK);
+ ether_ifih->ifih_input = ether_input;
+ SLIST_INSERT_HEAD(&ifp->if_inputs, ether_ifih, ifih_next);
if (ifp->if_hardmtu == 0)
ifp->if_hardmtu = ETHERMTU;
if_alloc_sadl(ifp);
- memcpy(LLADDR(ifp->if_sadl), ((struct arpcom *)ifp)->ac_enaddr,
- ifp->if_addrlen);
- LIST_INIT(&((struct arpcom *)ifp)->ac_multiaddrs);
+ memcpy(LLADDR(ifp->if_sadl), ac->ac_enaddr, ifp->if_addrlen);
+ LIST_INIT(&ac->ac_multiaddrs);
#if NBPFILTER > 0
bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, ETHER_HDR_LEN);
#endif
@@ -781,8 +790,16 @@ void
ether_ifdetach(struct ifnet *ifp)
{
struct arpcom *ac = (struct arpcom *)ifp;
+ struct ifih *ether_ifih;
struct ether_multi *enm;
+ ether_ifih = SLIST_FIRST(&ifp->if_inputs);
+ SLIST_REMOVE_HEAD(&ifp->if_inputs, ifih_next);
+
+ KASSERT(SLIST_EMPTY(&ifp->if_inputs));
+
+ free(ether_ifih, M_DEVBUF, sizeof(*ether_ifih));
+
for (enm = LIST_FIRST(&ac->ac_multiaddrs);
enm != NULL;
enm = LIST_FIRST(&ac->ac_multiaddrs)) {
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index b07fc6ce99d..c488bf58868 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_var.h,v 1.18 2015/02/06 06:42:36 henning Exp $ */
+/* $OpenBSD: if_var.h,v 1.19 2015/02/08 06:00:52 mpi Exp $ */
/* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */
/*
@@ -111,6 +111,14 @@ struct ifqueue {
};
/*
+ * Interface input hooks.
+ */
+struct ifih {
+ SLIST_ENTRY(ifih) ifih_next;
+ int (*ifih_input)(struct ifnet *, void *, struct mbuf *);
+};
+
+/*
* Structure defining a queue for a network interface.
*
* (Would like to call this struct ``if'', but C isn't PL/1.)
@@ -153,6 +161,8 @@ struct ifnet { /* and the entries */
struct task *if_linkstatetask; /* task to do route updates */
/* procedure handles */
+ SLIST_HEAD(, ifih) if_inputs; /* input routines (dequeue) */
+
/* output routine (enqueue) */
int (*if_output)(struct ifnet *, struct mbuf *, struct sockaddr *,
struct rtentry *);
@@ -385,12 +395,15 @@ do { \
extern struct ifnet_head ifnet;
extern struct ifnet *lo0ifp;
+void if_start(struct ifnet *);
+void if_input(struct ifnet *, struct mbuf *);
+
#define ether_input_mbuf(ifp, m) ether_input((ifp), NULL, (m))
void ether_ifattach(struct ifnet *);
void ether_ifdetach(struct ifnet *);
int ether_ioctl(struct ifnet *, struct arpcom *, u_long, caddr_t);
-void ether_input(struct ifnet *, struct ether_header *, struct mbuf *);
+int ether_input(struct ifnet *, void *, struct mbuf *);
int ether_output(struct ifnet *,
struct mbuf *, struct sockaddr *, struct rtentry *);
char *ether_sprintf(u_char *);