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
|
||||
@ -42,6 +42,7 @@
|
||||
#include "opt_iso.h"
|
||||
#include "opt_ns.h"
|
||||
#include "opt_natm.h"
|
||||
#include "arp.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
@ -108,6 +109,9 @@ domaininit()
|
||||
#endif
|
||||
#ifdef IPSEC
|
||||
ADDDOMAIN(key);
|
||||
#endif
|
||||
#if NARP > 0
|
||||
ADDDOMAIN(arp);
|
||||
#endif
|
||||
ADDDOMAIN(route);
|
||||
#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.
|
||||
@ -94,6 +94,8 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/domain.h>
|
||||
|
||||
#include <net/ethertypes.h>
|
||||
#include <net/if.h>
|
||||
@ -102,6 +104,7 @@
|
||||
#include <net/if_types.h>
|
||||
#include <net/route.h>
|
||||
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in_var.h>
|
||||
@ -193,6 +196,123 @@ lla_snprintf(adrp, len)
|
||||
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.
|
||||
*/
|
||||
@ -205,6 +325,13 @@ arptimer(arg)
|
||||
register struct llinfo_arp *la, *nla;
|
||||
|
||||
s = splsoftnet();
|
||||
|
||||
if (arp_lock_try(0) == 0) {
|
||||
/* get it later.. */
|
||||
splx(s);
|
||||
return;
|
||||
}
|
||||
|
||||
timeout(arptimer, NULL, arpt_prune * hz);
|
||||
for (la = llinfo_arp.lh_first; la != 0; la = nla) {
|
||||
register struct rtentry *rt = la->la_rt;
|
||||
@ -213,6 +340,9 @@ arptimer(arg)
|
||||
if (rt->rt_expire && rt->rt_expire <= time.tv_sec)
|
||||
arptfree(la); /* timer has expired; clear */
|
||||
}
|
||||
|
||||
ARP_UNLOCK();
|
||||
|
||||
splx(s);
|
||||
}
|
||||
|
||||
@ -229,6 +359,8 @@ arp_rtrequest(req, rt, sa)
|
||||
register struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo;
|
||||
static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
|
||||
size_t allocsize;
|
||||
struct mbuf *mold;
|
||||
int s;
|
||||
|
||||
if (!arpinit_done) {
|
||||
arpinit_done = 1;
|
||||
@ -243,6 +375,9 @@ arp_rtrequest(req, rt, sa)
|
||||
}
|
||||
if (rt->rt_flags & RTF_GATEWAY)
|
||||
return;
|
||||
|
||||
ARP_LOCK(1); /* we may already be locked here. */
|
||||
|
||||
switch (req) {
|
||||
|
||||
case RTM_ADD:
|
||||
@ -344,10 +479,18 @@ arp_rtrequest(req, rt, sa)
|
||||
LIST_REMOVE(la, la_list);
|
||||
rt->rt_llinfo = 0;
|
||||
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);
|
||||
}
|
||||
ARP_UNLOCK();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -407,7 +550,9 @@ arpresolve(ifp, rt, m, dst, desten)
|
||||
{
|
||||
register struct llinfo_arp *la;
|
||||
struct sockaddr_dl *sdl;
|
||||
|
||||
struct mbuf *mold;
|
||||
int s;
|
||||
|
||||
if (rt)
|
||||
la = (struct llinfo_arp *)rt->rt_llinfo;
|
||||
else {
|
||||
@ -435,9 +580,16 @@ arpresolve(ifp, rt, m, dst, desten)
|
||||
* response yet. Replace the held mbuf with this
|
||||
* latest one.
|
||||
*/
|
||||
if (la->la_hold)
|
||||
m_freem(la->la_hold);
|
||||
|
||||
s = splimp();
|
||||
mold = la->la_hold;
|
||||
la->la_hold = m;
|
||||
splx(s);
|
||||
|
||||
if (mold)
|
||||
m_freem(mold);
|
||||
|
||||
|
||||
/*
|
||||
* Re-send the ARP request when appropriate.
|
||||
*/
|
||||
@ -523,12 +675,15 @@ in_arpinput(m)
|
||||
struct arphdr *ah;
|
||||
register struct ifnet *ifp = m->m_pkthdr.rcvif;
|
||||
register struct llinfo_arp *la = 0;
|
||||
register struct rtentry *rt;
|
||||
register struct rtentry *rt;
|
||||
struct in_ifaddr *ia;
|
||||
struct sockaddr_dl *sdl;
|
||||
struct sockaddr sa;
|
||||
struct in_addr isaddr, itaddr, myaddr;
|
||||
int op;
|
||||
struct mbuf *mold;
|
||||
int s;
|
||||
|
||||
|
||||
ah = mtod(m, struct arphdr *);
|
||||
op = ntohs(ah->ar_op);
|
||||
@ -670,11 +825,14 @@ in_arpinput(m)
|
||||
rt->rt_expire = time.tv_sec + arpt_keep;
|
||||
rt->rt_flags &= ~RTF_REJECT;
|
||||
la->la_asked = 0;
|
||||
if (la->la_hold) {
|
||||
(*ifp->if_output)(ifp, la->la_hold,
|
||||
rt_key(rt), rt);
|
||||
la->la_hold = 0;
|
||||
}
|
||||
|
||||
s = splimp();
|
||||
mold = la->la_hold;
|
||||
la->la_hold = 0;
|
||||
splx(s);
|
||||
|
||||
if (mold)
|
||||
(*ifp->if_output)(ifp, mold, rt_key(rt), rt);
|
||||
}
|
||||
reply:
|
||||
if (op != ARPOP_REQUEST) {
|
||||
@ -719,6 +877,8 @@ arptfree(la)
|
||||
register struct rtentry *rt = la->la_rt;
|
||||
register struct sockaddr_dl *sdl;
|
||||
|
||||
ARP_LOCK_CHECK();
|
||||
|
||||
if (rt == 0)
|
||||
panic("arptfree");
|
||||
if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) &&
|
||||
@ -1066,3 +1226,4 @@ db_show_arptab()
|
||||
}
|
||||
#endif
|
||||
#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
|
||||
@ -70,6 +70,8 @@ void arp_rtrequest __P((int, struct rtentry *, struct sockaddr *));
|
||||
int arpresolve __P((struct ifnet *, struct rtentry *, struct mbuf *,
|
||||
struct sockaddr *, u_char *));
|
||||
void arpintr __P((void));
|
||||
void arp_drain __P((void));
|
||||
|
||||
int arpioctl __P((u_long, caddr_t));
|
||||
void arpwhohas __P((struct ifnet *, struct in_addr *));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user