Implement arp_drain(), which frees packets tied up in the arp cache if
mbufs are in short supply. Create a (trivial) protocol domain for arp so that the drain routine will be called from m_reclaim()
This commit is contained in:
parent
b8e4538f80
commit
2aa9696fee
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: uipc_domain.c,v 1.27 1999/07/09 22:57:16 thorpej Exp $ */
|
/* $NetBSD: uipc_domain.c,v 1.28 1999/08/05 04:04:28 sommerfeld Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1982, 1986, 1993
|
* Copyright (c) 1982, 1986, 1993
|
||||||
@ -42,6 +42,7 @@
|
|||||||
#include "opt_iso.h"
|
#include "opt_iso.h"
|
||||||
#include "opt_ns.h"
|
#include "opt_ns.h"
|
||||||
#include "opt_natm.h"
|
#include "opt_natm.h"
|
||||||
|
#include "arp.h"
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
@ -108,6 +109,9 @@ domaininit()
|
|||||||
#endif
|
#endif
|
||||||
#ifdef IPSEC
|
#ifdef IPSEC
|
||||||
ADDDOMAIN(key);
|
ADDDOMAIN(key);
|
||||||
|
#endif
|
||||||
|
#if NARP > 0
|
||||||
|
ADDDOMAIN(arp);
|
||||||
#endif
|
#endif
|
||||||
ADDDOMAIN(route);
|
ADDDOMAIN(route);
|
||||||
#endif /* ! lint */
|
#endif /* ! lint */
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: if_arp.c,v 1.62 1999/06/18 18:20:50 thorpej Exp $ */
|
/* $NetBSD: if_arp.c,v 1.63 1999/08/05 04:04:29 sommerfeld Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||||
@ -94,6 +94,8 @@
|
|||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/syslog.h>
|
#include <sys/syslog.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
|
#include <sys/protosw.h>
|
||||||
|
#include <sys/domain.h>
|
||||||
|
|
||||||
#include <net/ethertypes.h>
|
#include <net/ethertypes.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
@ -102,6 +104,7 @@
|
|||||||
#include <net/if_types.h>
|
#include <net/if_types.h>
|
||||||
#include <net/route.h>
|
#include <net/route.h>
|
||||||
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/in_systm.h>
|
#include <netinet/in_systm.h>
|
||||||
#include <netinet/in_var.h>
|
#include <netinet/in_var.h>
|
||||||
@ -193,6 +196,123 @@ lla_snprintf(adrp, len)
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct protosw arpsw[] = {
|
||||||
|
{ 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0,
|
||||||
|
0, 0, 0, arp_drain,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct domain arpdomain =
|
||||||
|
{ PF_ARP, "arp", 0, 0, 0,
|
||||||
|
arpsw, &arpsw[sizeof(arpsw)/sizeof(arpsw[0])]
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ARP table locking.
|
||||||
|
*
|
||||||
|
* to prevent lossage vs. the arp_drain routine (which may be called at
|
||||||
|
* any time, including in a device driver context), we do two things:
|
||||||
|
*
|
||||||
|
* 1) manipulation of la->la_hold is done at splimp() (for all of
|
||||||
|
* about two instructions).
|
||||||
|
*
|
||||||
|
* 2) manipulation of the arp table's linked list is done under the
|
||||||
|
* protection of the ARP_LOCK; if arp_drain() or arptimer is called
|
||||||
|
* while the arp table is locked, we punt and try again later.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int arp_locked;
|
||||||
|
|
||||||
|
static __inline int arp_lock_try __P((int));
|
||||||
|
static __inline void arp_unlock __P((void));
|
||||||
|
|
||||||
|
static __inline int
|
||||||
|
arp_lock_try(int recurse)
|
||||||
|
{
|
||||||
|
int s;
|
||||||
|
|
||||||
|
s = splimp();
|
||||||
|
if (!recurse && arp_locked) {
|
||||||
|
splx(s);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
arp_locked++;
|
||||||
|
splx(s);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline void
|
||||||
|
arp_unlock()
|
||||||
|
{
|
||||||
|
int s;
|
||||||
|
|
||||||
|
s = splimp();
|
||||||
|
arp_locked--;
|
||||||
|
splx(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DIAGNOSTIC
|
||||||
|
#define ARP_LOCK(recurse) \
|
||||||
|
do { \
|
||||||
|
if (arp_lock_try(recurse) == 0) { \
|
||||||
|
printf("%s:%d: arp already locked\n", __FILE__, __LINE__); \
|
||||||
|
panic("arp_lock"); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#define ARP_LOCK_CHECK() \
|
||||||
|
do { \
|
||||||
|
if (arp_locked == 0) { \
|
||||||
|
printf("%s:%d: arp lock not held\n", __FILE__, __LINE__); \
|
||||||
|
panic("arp lock check"); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
#define ARP_LOCK(x) (void) arp_lock_try(x)
|
||||||
|
#define ARP_LOCK_CHECK() /* nothing */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ARP_UNLOCK() arp_unlock()
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ARP protocol drain routine. Called when memory is in short supply.
|
||||||
|
* Called at splimp();
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
arp_drain()
|
||||||
|
{
|
||||||
|
register struct llinfo_arp *la, *nla;
|
||||||
|
int count = 0;
|
||||||
|
struct mbuf *mold;
|
||||||
|
|
||||||
|
printf("arp_drain: entered\n");
|
||||||
|
|
||||||
|
if (arp_lock_try(0) == 0) {
|
||||||
|
printf("arp_drain: locked; punting\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (la = llinfo_arp.lh_first; la != 0; la = nla) {
|
||||||
|
nla = la->la_list.le_next;
|
||||||
|
|
||||||
|
mold = la->la_hold;
|
||||||
|
la->la_hold = 0;
|
||||||
|
|
||||||
|
if (mold) {
|
||||||
|
m_freem(mold);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ARP_UNLOCK();
|
||||||
|
|
||||||
|
printf("arp_drain: freed %d\n", count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Timeout routine. Age arp_tab entries periodically.
|
* Timeout routine. Age arp_tab entries periodically.
|
||||||
*/
|
*/
|
||||||
@ -205,6 +325,13 @@ arptimer(arg)
|
|||||||
register struct llinfo_arp *la, *nla;
|
register struct llinfo_arp *la, *nla;
|
||||||
|
|
||||||
s = splsoftnet();
|
s = splsoftnet();
|
||||||
|
|
||||||
|
if (arp_lock_try(0) == 0) {
|
||||||
|
/* get it later.. */
|
||||||
|
splx(s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
timeout(arptimer, NULL, arpt_prune * hz);
|
timeout(arptimer, NULL, arpt_prune * hz);
|
||||||
for (la = llinfo_arp.lh_first; la != 0; la = nla) {
|
for (la = llinfo_arp.lh_first; la != 0; la = nla) {
|
||||||
register struct rtentry *rt = la->la_rt;
|
register struct rtentry *rt = la->la_rt;
|
||||||
@ -213,6 +340,9 @@ arptimer(arg)
|
|||||||
if (rt->rt_expire && rt->rt_expire <= time.tv_sec)
|
if (rt->rt_expire && rt->rt_expire <= time.tv_sec)
|
||||||
arptfree(la); /* timer has expired; clear */
|
arptfree(la); /* timer has expired; clear */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ARP_UNLOCK();
|
||||||
|
|
||||||
splx(s);
|
splx(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,6 +359,8 @@ arp_rtrequest(req, rt, sa)
|
|||||||
register struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo;
|
register struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo;
|
||||||
static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
|
static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
|
||||||
size_t allocsize;
|
size_t allocsize;
|
||||||
|
struct mbuf *mold;
|
||||||
|
int s;
|
||||||
|
|
||||||
if (!arpinit_done) {
|
if (!arpinit_done) {
|
||||||
arpinit_done = 1;
|
arpinit_done = 1;
|
||||||
@ -243,6 +375,9 @@ arp_rtrequest(req, rt, sa)
|
|||||||
}
|
}
|
||||||
if (rt->rt_flags & RTF_GATEWAY)
|
if (rt->rt_flags & RTF_GATEWAY)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
ARP_LOCK(1); /* we may already be locked here. */
|
||||||
|
|
||||||
switch (req) {
|
switch (req) {
|
||||||
|
|
||||||
case RTM_ADD:
|
case RTM_ADD:
|
||||||
@ -344,10 +479,18 @@ arp_rtrequest(req, rt, sa)
|
|||||||
LIST_REMOVE(la, la_list);
|
LIST_REMOVE(la, la_list);
|
||||||
rt->rt_llinfo = 0;
|
rt->rt_llinfo = 0;
|
||||||
rt->rt_flags &= ~RTF_LLINFO;
|
rt->rt_flags &= ~RTF_LLINFO;
|
||||||
if (la->la_hold)
|
|
||||||
m_freem(la->la_hold);
|
s = splimp();
|
||||||
|
mold = la->la_hold;
|
||||||
|
la->la_hold = 0;
|
||||||
|
splx(s);
|
||||||
|
|
||||||
|
if (mold)
|
||||||
|
m_freem(mold);
|
||||||
|
|
||||||
Free((caddr_t)la);
|
Free((caddr_t)la);
|
||||||
}
|
}
|
||||||
|
ARP_UNLOCK();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -407,7 +550,9 @@ arpresolve(ifp, rt, m, dst, desten)
|
|||||||
{
|
{
|
||||||
register struct llinfo_arp *la;
|
register struct llinfo_arp *la;
|
||||||
struct sockaddr_dl *sdl;
|
struct sockaddr_dl *sdl;
|
||||||
|
struct mbuf *mold;
|
||||||
|
int s;
|
||||||
|
|
||||||
if (rt)
|
if (rt)
|
||||||
la = (struct llinfo_arp *)rt->rt_llinfo;
|
la = (struct llinfo_arp *)rt->rt_llinfo;
|
||||||
else {
|
else {
|
||||||
@ -435,9 +580,16 @@ arpresolve(ifp, rt, m, dst, desten)
|
|||||||
* response yet. Replace the held mbuf with this
|
* response yet. Replace the held mbuf with this
|
||||||
* latest one.
|
* latest one.
|
||||||
*/
|
*/
|
||||||
if (la->la_hold)
|
|
||||||
m_freem(la->la_hold);
|
s = splimp();
|
||||||
|
mold = la->la_hold;
|
||||||
la->la_hold = m;
|
la->la_hold = m;
|
||||||
|
splx(s);
|
||||||
|
|
||||||
|
if (mold)
|
||||||
|
m_freem(mold);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Re-send the ARP request when appropriate.
|
* Re-send the ARP request when appropriate.
|
||||||
*/
|
*/
|
||||||
@ -523,12 +675,15 @@ in_arpinput(m)
|
|||||||
struct arphdr *ah;
|
struct arphdr *ah;
|
||||||
register struct ifnet *ifp = m->m_pkthdr.rcvif;
|
register struct ifnet *ifp = m->m_pkthdr.rcvif;
|
||||||
register struct llinfo_arp *la = 0;
|
register struct llinfo_arp *la = 0;
|
||||||
register struct rtentry *rt;
|
register struct rtentry *rt;
|
||||||
struct in_ifaddr *ia;
|
struct in_ifaddr *ia;
|
||||||
struct sockaddr_dl *sdl;
|
struct sockaddr_dl *sdl;
|
||||||
struct sockaddr sa;
|
struct sockaddr sa;
|
||||||
struct in_addr isaddr, itaddr, myaddr;
|
struct in_addr isaddr, itaddr, myaddr;
|
||||||
int op;
|
int op;
|
||||||
|
struct mbuf *mold;
|
||||||
|
int s;
|
||||||
|
|
||||||
|
|
||||||
ah = mtod(m, struct arphdr *);
|
ah = mtod(m, struct arphdr *);
|
||||||
op = ntohs(ah->ar_op);
|
op = ntohs(ah->ar_op);
|
||||||
@ -670,11 +825,14 @@ in_arpinput(m)
|
|||||||
rt->rt_expire = time.tv_sec + arpt_keep;
|
rt->rt_expire = time.tv_sec + arpt_keep;
|
||||||
rt->rt_flags &= ~RTF_REJECT;
|
rt->rt_flags &= ~RTF_REJECT;
|
||||||
la->la_asked = 0;
|
la->la_asked = 0;
|
||||||
if (la->la_hold) {
|
|
||||||
(*ifp->if_output)(ifp, la->la_hold,
|
s = splimp();
|
||||||
rt_key(rt), rt);
|
mold = la->la_hold;
|
||||||
la->la_hold = 0;
|
la->la_hold = 0;
|
||||||
}
|
splx(s);
|
||||||
|
|
||||||
|
if (mold)
|
||||||
|
(*ifp->if_output)(ifp, mold, rt_key(rt), rt);
|
||||||
}
|
}
|
||||||
reply:
|
reply:
|
||||||
if (op != ARPOP_REQUEST) {
|
if (op != ARPOP_REQUEST) {
|
||||||
@ -719,6 +877,8 @@ arptfree(la)
|
|||||||
register struct rtentry *rt = la->la_rt;
|
register struct rtentry *rt = la->la_rt;
|
||||||
register struct sockaddr_dl *sdl;
|
register struct sockaddr_dl *sdl;
|
||||||
|
|
||||||
|
ARP_LOCK_CHECK();
|
||||||
|
|
||||||
if (rt == 0)
|
if (rt == 0)
|
||||||
panic("arptfree");
|
panic("arptfree");
|
||||||
if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) &&
|
if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) &&
|
||||||
@ -1066,3 +1226,4 @@ db_show_arptab()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif /* INET */
|
#endif /* INET */
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: if_inarp.h,v 1.28 1999/02/21 15:17:14 drochner Exp $ */
|
/* $NetBSD: if_inarp.h,v 1.29 1999/08/05 04:04:29 sommerfeld Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1982, 1986, 1993
|
* Copyright (c) 1982, 1986, 1993
|
||||||
@ -70,6 +70,8 @@ void arp_rtrequest __P((int, struct rtentry *, struct sockaddr *));
|
|||||||
int arpresolve __P((struct ifnet *, struct rtentry *, struct mbuf *,
|
int arpresolve __P((struct ifnet *, struct rtentry *, struct mbuf *,
|
||||||
struct sockaddr *, u_char *));
|
struct sockaddr *, u_char *));
|
||||||
void arpintr __P((void));
|
void arpintr __P((void));
|
||||||
|
void arp_drain __P((void));
|
||||||
|
|
||||||
int arpioctl __P((u_long, caddr_t));
|
int arpioctl __P((u_long, caddr_t));
|
||||||
void arpwhohas __P((struct ifnet *, struct in_addr *));
|
void arpwhohas __P((struct ifnet *, struct in_addr *));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user