gif interface now uses generic software interrupt

(on archs that support it).  also, make gif ALTQ-capable on outgoing.
sync with kame, comments from thorpej.
This commit is contained in:
itojun 2001-08-16 17:45:25 +00:00
parent e6de26d11c
commit 74ad87bc53
6 changed files with 168 additions and 71 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_gif.c,v 1.32 2001/07/30 11:12:58 itojun Exp $ */
/* $NetBSD: if_gif.c,v 1.33 2001/08/16 17:45:25 itojun Exp $ */
/* $KAME: if_gif.c,v 1.67 2001/07/30 08:42:06 itojun Exp $ */
/*
@ -46,6 +46,9 @@
#include <sys/proc.h>
#include <sys/protosw.h>
#include <machine/cpu.h>
#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
#include <machine/intr.h>
#endif
#include <net/if.h>
#include <net/if_types.h>
@ -88,9 +91,13 @@
#if NGIF > 0
void gifattach __P((int));
#ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
void gifnetisr __P((void));
#endif
void gifintr __P((void *));
#ifdef ISO
static struct mbuf *gif_eon_encap(struct mbuf *);
static struct mbuf *gif_eon_decap(struct ifnet *, struct mbuf *);
static struct mbuf *gif_eon_encap __P((struct mbuf *));
static struct mbuf *gif_eon_decap __P((struct ifnet *, struct mbuf *));
#endif
/*
@ -260,6 +267,10 @@ gif_output(ifp, m, dst, rt)
struct gif_softc *sc = (struct gif_softc*)ifp;
int error = 0;
static int called = 0; /* XXX: MUTEX */
ALTQ_DECL(struct altq_pktattr pktattr;)
int s;
IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
/*
* gif may cause infinite recursion calls when misconfigured.
@ -285,32 +296,6 @@ gif_output(ifp, m, dst, rt)
goto end;
}
#if NBPFILTER > 0
if (ifp->if_bpf) {
/*
* We need to prepend the address family as
* a four byte field. Cons up a dummy header
* to pacify bpf. This is safe because bpf
* will only read from the mbuf (i.e., it won't
* try to free it or keep a pointer a to it).
*/
struct mbuf m0;
u_int32_t af = dst->sa_family;
m0.m_next = m;
m0.m_len = 4;
m0.m_data = (char *)&af;
#ifdef HAVE_OLD_BPF
bpf_mtap(ifp, &m0);
#else
bpf_mtap(ifp->if_bpf, &m0);
#endif
}
#endif
ifp->if_opackets++;
ifp->if_obytes += m->m_pkthdr.len;
/* inner AF-specific encapsulation */
switch (dst->sa_family) {
#ifdef ISO
@ -328,23 +313,29 @@ gif_output(ifp, m, dst, rt)
/* XXX should we check if our outer source is legal? */
/* dispatch to output logic based on outer AF */
switch (sc->gif_psrc->sa_family) {
#ifdef INET
case AF_INET:
error = in_gif_output(ifp, dst->sa_family, m, rt);
break;
#endif
#ifdef INET6
case AF_INET6:
error = in6_gif_output(ifp, dst->sa_family, m, rt);
break;
#endif
default:
m_freem(m);
error = ENETDOWN;
/* use DLT_NULL encapsulation here to pass inner af type */
M_PREPEND(m, sizeof(int), M_DONTWAIT);
if (!m) {
error = ENOBUFS;
goto end;
}
*mtod(m, int *) = dst->sa_family;
s = splnet();
IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
if (error) {
splx(s);
goto end;
}
splx(s);
#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
softintr_schedule(sc->gif_si);
#else
/* XXX bad spl level? */
gifnetisr();
#endif
error = 0;
end:
called = 0; /* reset recursion counter */
@ -353,25 +344,110 @@ gif_output(ifp, m, dst, rt)
return error;
}
#ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
void
gif_input(m, af, gifp)
gifnetisr()
{
struct gif_softc *sc;
for (sc = LIST_FIRST(&gif_softc_list); sc != NULL;
sc = LIST_NEXT(sc, gif_list)) {
gifintr(sc);
}
}
#endif
void
gifintr(arg)
void *arg;
{
struct gif_softc *sc;
struct ifnet *ifp;
struct mbuf *m;
int family;
int len;
int s;
int error;
sc = (struct gif_softc *)arg;
ifp = &sc->gif_if;
/* output processing */
while (1) {
s = splnet();
IF_DEQUEUE(&sc->gif_if.if_snd, m);
splx(s);
if (m == NULL)
break;
/* grab and chop off inner af type */
if (sizeof(int) > m->m_len) {
m = m_pullup(m, sizeof(int));
if (!m) {
ifp->if_oerrors++;
continue;
}
}
family = *mtod(m, int *);
#if NBPFILTER > 0
if (ifp->if_bpf) {
#ifdef HAVE_OLD_BPF
bpf_mtap(ifp, m);
#else
bpf_mtap(ifp->if_bpf, m);
#endif
}
#endif
m_adj(m, sizeof(int));
len = m->m_pkthdr.len;
/* dispatch to output logic based on outer AF */
switch (sc->gif_psrc->sa_family) {
#ifdef INET
case AF_INET:
error = in_gif_output(ifp, family, m);
break;
#endif
#ifdef INET6
case AF_INET6:
error = in6_gif_output(ifp, family, m);
break;
#endif
default:
m_freem(m);
error = ENETDOWN;
break;
}
if (error)
ifp->if_oerrors++;
else {
ifp->if_opackets++;
ifp->if_obytes += len;
}
}
}
void
gif_input(m, af, ifp)
struct mbuf *m;
int af;
struct ifnet *gifp;
struct ifnet *ifp;
{
int s, isr;
struct ifqueue *ifq = 0;
struct ifqueue *ifq = NULL;
if (gifp == NULL) {
if (ifp == NULL) {
/* just in case */
m_freem(m);
return;
}
m->m_pkthdr.rcvif = gifp;
m->m_pkthdr.rcvif = ifp;
#if NBPFILTER > 0
if (gifp->if_bpf) {
if (ifp->if_bpf) {
/*
* We need to prepend the address family as
* a four byte field. Cons up a dummy header
@ -387,9 +463,9 @@ gif_input(m, af, gifp)
m0.m_data = (char *)&af1;
#ifdef HAVE_OLD_BPF
bpf_mtap(gifp, &m0);
bpf_mtap(ifp, &m0);
#else
bpf_mtap(gifp->if_bpf, &m0);
bpf_mtap(ifp->if_bpf, &m0);
#endif
}
#endif /*NBPFILTER > 0*/
@ -420,7 +496,7 @@ gif_input(m, af, gifp)
#endif
#ifdef ISO
case AF_ISO:
m = gif_eon_decap(gifp, m);
m = gif_eon_decap(ifp, m);
if (!m)
return;
ifq = &clnlintrq;
@ -439,14 +515,12 @@ gif_input(m, af, gifp)
splx(s);
return;
}
gifp->if_ipackets++;
gifp->if_ibytes += m->m_pkthdr.len;
ifp->if_ipackets++;
ifp->if_ibytes += m->m_pkthdr.len;
IF_ENQUEUE(ifq, m);
/* we need schednetisr since the address family may change */
schednetisr(isr);
splx(s);
return;
}
/* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */
@ -760,6 +834,14 @@ gif_set_tunnel(ifp, src, dst)
#endif
}
#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
sc->gif_si = softintr_establish(IPL_SOFTNET, gifintr, sc);
if (sc->gif_si == NULL) {
error = ENOMEM;
goto bad;
}
#endif
osrc = sc->gif_psrc;
sa = (struct sockaddr *)malloc(src->sa_len, M_IFADDR, M_WAITOK);
bcopy((caddr_t)src, (caddr_t)sa, src->sa_len);
@ -796,9 +878,19 @@ gif_set_tunnel(ifp, src, dst)
if (odst)
free((caddr_t)odst, M_IFADDR);
error = 0;
if (sc->gif_psrc && sc->gif_pdst)
ifp->if_flags |= IFF_RUNNING;
else
ifp->if_flags &= ~IFF_RUNNING;
splx(s);
return 0;
bad:
#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
if (sc->gif_si)
softintr_disestablish(sc->gif_si);
#endif
if (sc->gif_psrc && sc->gif_pdst)
ifp->if_flags |= IFF_RUNNING;
else
@ -817,6 +909,10 @@ gif_delete_tunnel(ifp)
s = splsoftnet();
#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
if (sc->gif_si)
softintr_disestablish(sc->gif_si);
#endif
if (sc->gif_psrc) {
free((caddr_t)sc->gif_psrc, M_IFADDR);
sc->gif_psrc = NULL;
@ -886,13 +982,13 @@ gif_eon_encap(struct mbuf *m)
* remove EON header and check checksum
*/
static struct mbuf *
gif_eon_decap(struct ifnet *gifp, struct mbuf *m)
gif_eon_decap(struct ifnet *ifp, struct mbuf *m)
{
struct eonhdr *ehdr;
if (m->m_len < sizeof(*ehdr) &&
(m = m_pullup(m, sizeof(*ehdr))) == NULL) {
gifp->if_ierrors++;
ifp->if_ierrors++;
return NULL;
}
if (iso_check_csum(m, sizeof(struct eonhdr))) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_gif.h,v 1.7 2001/07/29 05:08:32 itojun Exp $ */
/* $NetBSD: if_gif.h,v 1.8 2001/08/16 17:45:26 itojun Exp $ */
/* $KAME: if_gif.h,v 1.23 2001/07/27 09:21:42 itojun Exp $ */
/*
@ -62,6 +62,9 @@ struct gif_softc {
const struct encaptab *encap_cookie4;
const struct encaptab *encap_cookie6;
LIST_ENTRY(gif_softc) gif_list; /* list of all gifs */
#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
void *gif_si; /* softintr handle */
#endif
};
#define gif_ro gifsc_gifscr.gifscr_ro

View File

@ -1,4 +1,4 @@
/* $NetBSD: in_gif.c,v 1.22 2001/07/29 05:08:33 itojun Exp $ */
/* $NetBSD: in_gif.c,v 1.23 2001/08/16 17:45:26 itojun Exp $ */
/* $KAME: in_gif.c,v 1.66 2001/07/29 04:46:09 itojun Exp $ */
/*
@ -81,11 +81,10 @@ int ip_gif_ttl = 0;
extern struct protosw in_gif_protosw;
int
in_gif_output(ifp, family, m, rt)
in_gif_output(ifp, family, m)
struct ifnet *ifp;
int family;
struct mbuf *m;
struct rtentry *rt;
{
struct gif_softc *sc = (struct gif_softc*)ifp;
struct sockaddr_in *dst = (struct sockaddr_in *)&sc->gif_ro.ro_dst;

View File

@ -1,4 +1,4 @@
/* $NetBSD: in_gif.h,v 1.6 2001/07/29 05:08:33 itojun Exp $ */
/* $NetBSD: in_gif.h,v 1.7 2001/08/16 17:45:26 itojun Exp $ */
/* $KAME: in_gif.h,v 1.6 2001/07/25 00:55:48 itojun Exp $ */
/*
@ -39,7 +39,7 @@ extern int ip_gif_ttl;
struct gif_softc;
void in_gif_input __P((struct mbuf *, ...));
int in_gif_output __P((struct ifnet *, int, struct mbuf *, struct rtentry *));
int in_gif_output __P((struct ifnet *, int, struct mbuf *));
int gif_encapcheck4 __P((const struct mbuf *, int, int, void *));
int in_gif_attach __P((struct gif_softc *));
int in_gif_detach __P((struct gif_softc *));

View File

@ -1,4 +1,4 @@
/* $NetBSD: in6_gif.c,v 1.21 2001/07/29 05:08:33 itojun Exp $ */
/* $NetBSD: in6_gif.c,v 1.22 2001/08/16 17:45:26 itojun Exp $ */
/* $KAME: in6_gif.c,v 1.62 2001/07/29 04:27:25 itojun Exp $ */
/*
@ -73,11 +73,10 @@ static int gif_validate6 __P((const struct ip6_hdr *, struct gif_softc *,
extern struct ip6protosw in6_gif_protosw;
int
in6_gif_output(ifp, family, m, rt)
in6_gif_output(ifp, family, m)
struct ifnet *ifp;
int family; /* family of the packet to be encapsulate. */
struct mbuf *m;
struct rtentry *rt;
{
struct gif_softc *sc = (struct gif_softc*)ifp;
struct sockaddr_in6 *dst = (struct sockaddr_in6 *)&sc->gif_ro6.ro_dst;

View File

@ -1,4 +1,4 @@
/* $NetBSD: in6_gif.h,v 1.5 2001/07/29 05:08:33 itojun Exp $ */
/* $NetBSD: in6_gif.h,v 1.6 2001/08/16 17:45:26 itojun Exp $ */
/* $KAME: in6_gif.h,v 1.7 2001/07/26 06:53:16 jinmei Exp $ */
/*
@ -37,7 +37,7 @@
struct gif_softc;
int in6_gif_input __P((struct mbuf **, int *, int));
int in6_gif_output __P((struct ifnet *, int, struct mbuf *, struct rtentry *));
int in6_gif_output __P((struct ifnet *, int, struct mbuf *));
int gif_encapcheck6 __P((const struct mbuf *, int, int, void *));
int in6_gif_attach __P((struct gif_softc *));
int in6_gif_detach __P((struct gif_softc *));