diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-02-08 06:00:53 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-02-08 06:00:53 +0000 |
commit | 5abebbaf769b6ddee8d1917eabd364eb0a44a4f0 (patch) | |
tree | fb4f1179540b6c1512cf78bdf4486f5fc051353c | |
parent | 32886a8e2b071ec25ba70187f55b9701d56ff70f (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.c | 23 | ||||
-rw-r--r-- | sys/net/if.h | 3 | ||||
-rw-r--r-- | sys/net/if_ethersubr.c | 49 | ||||
-rw-r--r-- | sys/net/if_var.h | 17 |
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 *); |