PERFORCE change 130830 for review
Qing Li
qingli at FreeBSD.org
Thu Dec 13 18:07:51 PST 2007
http://perforce.freebsd.org/chv.cgi?CH=130830
Change 130830 by qingli at FreeBSD-newarp on 2007/12/14 02:07:22
These files have been modified to work with the new ARP code.
The immediate To-Do list:
1. cleanup the locking code
2. work in comments from Gleb
Performed buildworld, installworld, buildkernel, installkernel,
and simple testing involved running "arp", "ndp", "ping" and "ping6".
cxgb_l2t.c compiles and links, but I doubt the actual code works due to
internal "struct llinfo_arp{}" definition. I will clean it up soon.
Affected files ...
.. //depot/projects/arp-v2/src/lib/libstand/if_ether.h#2 edit
.. //depot/projects/arp-v2/src/sys/conf/files#2 edit
.. //depot/projects/arp-v2/src/sys/dev/cxgb/cxgb_l2t.c#2 edit
.. //depot/projects/arp-v2/src/sys/net/if.c#2 edit
.. //depot/projects/arp-v2/src/sys/net/if_arcsubr.c#2 edit
.. //depot/projects/arp-v2/src/sys/net/if_ethersubr.c#2 edit
.. //depot/projects/arp-v2/src/sys/net/if_fddisubr.c#2 edit
.. //depot/projects/arp-v2/src/sys/net/if_fwsubr.c#2 edit
.. //depot/projects/arp-v2/src/sys/net/if_iso88025subr.c#2 edit
.. //depot/projects/arp-v2/src/sys/net/if_var.h#2 edit
.. //depot/projects/arp-v2/src/sys/net/route.c#2 edit
.. //depot/projects/arp-v2/src/sys/net/rtsock.c#2 edit
.. //depot/projects/arp-v2/src/sys/netinet/if_ether.c#2 edit
.. //depot/projects/arp-v2/src/sys/netinet/if_ether.h#2 edit
.. //depot/projects/arp-v2/src/sys/netinet/in.c#2 edit
.. //depot/projects/arp-v2/src/sys/netinet/ip_output.c#2 edit
.. //depot/projects/arp-v2/src/sys/netinet6/icmp6.c#2 edit
.. //depot/projects/arp-v2/src/sys/netinet6/in6.c#2 edit
.. //depot/projects/arp-v2/src/sys/netinet6/ip6_forward.c#2 edit
.. //depot/projects/arp-v2/src/sys/netinet6/ip6_input.c#2 edit
.. //depot/projects/arp-v2/src/sys/netinet6/ip6_mroute.c#2 edit
.. //depot/projects/arp-v2/src/sys/netinet6/ip6_output.c#2 edit
.. //depot/projects/arp-v2/src/sys/netinet6/nd6.c#2 edit
.. //depot/projects/arp-v2/src/sys/netinet6/nd6.h#2 edit
.. //depot/projects/arp-v2/src/sys/netinet6/nd6_nbr.c#2 edit
.. //depot/projects/arp-v2/src/sys/netinet6/nd6_rtr.c#2 edit
.. //depot/projects/arp-v2/src/usr.sbin/arp/arp.c#2 edit
.. //depot/projects/arp-v2/src/usr.sbin/ndp/ndp.c#2 edit
Differences ...
==== //depot/projects/arp-v2/src/lib/libstand/if_ether.h#2 (text+ko) ====
@@ -156,7 +156,7 @@
void arpwhohas(struct arpcom *, struct in_addr *);
void arpintr(void);
int arpresolve(struct arpcom *,
- struct rtentry *, struct mbuf *, struct sockaddr *, u_char *);
+ struct rtentry *, struct mbuf *, struct sockaddr *, u_char *, struct llentry **);
void arp_ifinit(struct arpcom *, struct ifaddr *);
void arp_rtrequest(int, struct rtentry *, struct sockaddr *);
@@ -233,7 +233,7 @@
#ifdef _KERNEL
void arp_rtrequest(int, struct rtentry *, struct sockaddr *);
int arpresolve(struct arpcom *, struct rtentry *, struct mbuf *,
- struct sockaddr *, u_char *);
+ struct sockaddr *, u_char *, struct llentry **);
void arpintr(void);
int arpioctl(u_long, caddr_t);
void arp_ifinit(struct arpcom *, struct ifaddr *);
==== //depot/projects/arp-v2/src/sys/conf/files#2 (text+ko) ====
@@ -1624,6 +1624,7 @@
net/if_iso88025subr.c optional token
net/if_lagg.c optional lagg
net/if_loop.c optional loop
+net/if_llatbl.c standard
net/if_media.c standard
net/if_mib.c standard
net/if_ppp.c optional ppp
==== //depot/projects/arp-v2/src/sys/dev/cxgb/cxgb_l2t.c#2 (text+ko) ====
@@ -173,6 +173,7 @@
{
struct rtentry *rt;
struct mbuf *m0;
+ struct llentry *lle=NULL;
if ((m0 = m_gethdr(M_NOWAIT, MT_DATA)) == NULL)
return (ENOMEM);
@@ -182,7 +183,7 @@
again:
switch (e->state) {
case L2T_STATE_STALE: /* entry is stale, kick off revalidation */
- arpresolve(rt->rt_ifp, rt, m0, rt->rt_gateway, RT_ENADDR(rt));
+ arpresolve(rt->rt_ifp, rt, m0, rt->rt_gateway, RT_ENADDR(rt), &lle);
mtx_lock(&e->lock);
if (e->state == L2T_STATE_STALE)
e->state = L2T_STATE_VALID;
@@ -208,7 +209,7 @@
* A better way would be to use a work request to retry L2T
* entries when there's no memory.
*/
- if (arpresolve(rt->rt_ifp, rt, m0, rt->rt_gateway, RT_ENADDR(rt)) == 0) {
+ if (arpresolve(rt->rt_ifp, rt, m0, rt->rt_gateway, RT_ENADDR(rt), &lle) == 0) {
mtx_lock(&e->lock);
if (e->arpq_head)
@@ -226,6 +227,7 @@
{
struct rtentry *rt;
struct mbuf *m0;
+ struct llentry *lle=NULL;
if ((m0 = m_gethdr(M_NOWAIT, MT_DATA)) == NULL)
return;
@@ -234,7 +236,7 @@
again:
switch (e->state) {
case L2T_STATE_STALE: /* entry is stale, kick off revalidation */
- arpresolve(rt->rt_ifp, rt, m0, rt->rt_gateway, RT_ENADDR(rt));
+ arpresolve(rt->rt_ifp, rt, m0, rt->rt_gateway, RT_ENADDR(rt), &lle);
mtx_lock(&e->lock);
if (e->state == L2T_STATE_STALE) {
e->state = L2T_STATE_VALID;
@@ -261,7 +263,7 @@
* A better way would be to use a work request to retry L2T
* entries when there's no memory.
*/
- arpresolve(rt->rt_ifp, rt, m0, rt->rt_gateway, RT_ENADDR(rt));
+ arpresolve(rt->rt_ifp, rt, m0, rt->rt_gateway, RT_ENADDR(rt), &lle);
}
return;
==== //depot/projects/arp-v2/src/sys/net/if.c#2 (text+ko) ====
@@ -57,6 +57,7 @@
#include <sys/domain.h>
#include <sys/jail.h>
#include <machine/stdarg.h>
+#include <vm/uma.h>
#include <net/if.h>
#include <net/if_clone.h>
@@ -65,6 +66,7 @@
#include <net/if_var.h>
#include <net/radix.h>
#include <net/route.h>
+#include <net/if_llatbl.h>
#if defined(INET) || defined(INET6)
/*XXX*/
@@ -134,6 +136,9 @@
extern void nd6_setmtu(struct ifnet *);
#endif
+extern uma_zone_t llezone;
+extern uma_zone_t lltzone;
+
int if_index = 0;
struct ifindex_entry *ifindex_table = NULL;
int ifqmaxlen = IFQ_MAXLEN;
@@ -294,7 +299,6 @@
static void
if_init(void *dummy __unused)
{
-
IFNET_LOCK_INIT();
TAILQ_INIT(&ifnet);
TAILQ_INIT(&ifg_head);
@@ -303,6 +307,13 @@
ifdev_byindex(0) = make_dev(&net_cdevsw, 0,
UID_ROOT, GID_WHEEL, 0600, "network");
if_clone_init();
+ /*
+ * create uma zone for L2/L3 cache
+ */
+ llezone = uma_zcreate("llentry", sizeof(struct llentry), NULL, NULL,
+ NULL, NULL, UMA_ALIGN_PTR, 0);
+ lltzone = uma_zcreate("lltable", sizeof(struct lltable), NULL, NULL,
+ NULL, NULL, UMA_ALIGN_PTR, 0);
}
static void
@@ -463,11 +474,13 @@
TASK_INIT(&ifp->if_starttask, 0, if_start_deferred, ifp);
TASK_INIT(&ifp->if_linktask, 0, do_link_state_change, ifp);
IF_AFDATA_LOCK_INIT(ifp);
+ IF_LLTBLS_LOCK_INIT(ifp);
ifp->if_afdata_initialized = 0;
TAILQ_INIT(&ifp->if_addrhead);
TAILQ_INIT(&ifp->if_prefixhead);
TAILQ_INIT(&ifp->if_multiaddrs);
+ TAILQ_INIT(&ifp->if_lltables);
TAILQ_INIT(&ifp->if_groups);
if_addgroup(ifp, IFG_ALL);
==== //depot/projects/arp-v2/src/sys/net/if_arcsubr.c#2 (text+ko) ====
@@ -64,6 +64,7 @@
#include <net/if_arc.h>
#include <net/if_arp.h>
#include <net/bpf.h>
+#include <net/if_llatbl.h>
#if defined(INET) || defined(INET6)
#include <netinet/in.h>
@@ -108,6 +109,7 @@
u_int8_t atype, adst;
int loop_copy = 0;
int isphds;
+ struct llentry *lle;
if (!((ifp->if_flags & IFF_UP) &&
(ifp->if_drv_flags & IFF_DRV_RUNNING)))
@@ -127,7 +129,7 @@
else if (ifp->if_flags & IFF_NOARP)
adst = ntohl(SIN(dst)->sin_addr.s_addr) & 0xFF;
else {
- error = arpresolve(ifp, rt0, m, dst, &adst);
+ error = arpresolve(ifp, rt0, m, dst, &adst, &lle);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
}
@@ -165,7 +167,7 @@
#endif
#ifdef INET6
case AF_INET6:
- error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)&adst);
+ error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)&adst, &lle);
if (error)
return (error);
atype = ARCTYPE_INET6;
==== //depot/projects/arp-v2/src/sys/net/if_ethersubr.c#2 (text+ko) ====
@@ -60,6 +60,7 @@
#include <net/ethernet.h>
#include <net/if_bridgevar.h>
#include <net/if_vlan_var.h>
+#include <net/if_llatbl.h>
#include <net/pf_mtag.h>
#if defined(INET) || defined(INET6)
@@ -138,6 +139,8 @@
static int ether_ipfw;
#endif
+extern int useloopback;
+
/*
* Ethernet output routine.
* Encapsulate a packet of type family for the local net.
@@ -151,6 +154,7 @@
short type;
int error, hdrcmplt = 0;
u_char esrc[ETHER_ADDR_LEN], edst[ETHER_ADDR_LEN];
+ struct llentry *lle = NULL;
struct ether_header *eh;
struct pf_mtag *t;
int loop_copy = 1;
@@ -172,7 +176,7 @@
switch (dst->sa_family) {
#ifdef INET
case AF_INET:
- error = arpresolve(ifp, rt0, m, dst, edst);
+ error = arpresolve(ifp, rt0, m, dst, edst, &lle);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
type = htons(ETHERTYPE_IP);
@@ -207,7 +211,7 @@
#endif
#ifdef INET6
case AF_INET6:
- error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst);
+ error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst, &lle);
if (error)
return error;
type = htons(ETHERTYPE_IPV6);
@@ -275,6 +279,9 @@
senderr(EAFNOSUPPORT);
}
+ if (lle && (lle->la_flags & LLE_IFADDR) && useloopback)
+ return (if_simloop(ifp, m, dst->sa_family, 0));
+
/*
* Add local net header. If no space in first mbuf,
* allocate another.
==== //depot/projects/arp-v2/src/sys/net/if_fddisubr.c#2 (text+ko) ====
@@ -55,6 +55,7 @@
#include <net/if_dl.h>
#include <net/if_llc.h>
#include <net/if_types.h>
+#include <net/if_llatbl.h>
#include <net/netisr.h>
#include <net/route.h>
@@ -119,6 +120,7 @@
int loop_copy = 0, error = 0, hdrcmplt = 0;
u_char esrc[FDDI_ADDR_LEN], edst[FDDI_ADDR_LEN];
struct fddi_header *fh;
+ struct llentry *lle;
#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
@@ -136,7 +138,7 @@
switch (dst->sa_family) {
#ifdef INET
case AF_INET: {
- error = arpresolve(ifp, rt0, m, dst, edst);
+ error = arpresolve(ifp, rt0, m, dst, edst, &lle);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
type = htons(ETHERTYPE_IP);
@@ -172,7 +174,7 @@
#endif /* INET */
#ifdef INET6
case AF_INET6:
- error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst);
+ error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst, &lle);
if (error)
return (error); /* Something bad happened */
type = htons(ETHERTYPE_IPV6);
==== //depot/projects/arp-v2/src/sys/net/if_fwsubr.c#2 (text+ko) ====
@@ -51,6 +51,7 @@
#include <net/if_types.h>
#include <net/bpf.h>
#include <net/firewire.h>
+#include <net/if_llatbl.h>
#if defined(INET) || defined(INET6)
#include <netinet/in.h>
@@ -89,6 +90,7 @@
struct mbuf *mtail;
int unicast, dgl, foff;
static int next_dgl;
+ struct llentry *lle;
#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
@@ -144,7 +146,7 @@
* doesn't fit into the arp model.
*/
if (unicast) {
- error = arpresolve(ifp, rt, m, dst, (u_char *) destfw);
+ error = arpresolve(ifp, rt, m, dst, (u_char *) destfw, &lle);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
}
@@ -174,7 +176,7 @@
case AF_INET6:
if (unicast) {
error = nd6_storelladdr(fc->fc_ifp, rt, m, dst,
- (u_char *) destfw);
+ (u_char *) destfw, &lle);
if (error)
return (error);
}
==== //depot/projects/arp-v2/src/sys/net/if_iso88025subr.c#2 (text+ko) ====
@@ -58,6 +58,7 @@
#include <net/if_dl.h>
#include <net/if_llc.h>
#include <net/if_types.h>
+#include <net/if_llatbl.h>
#include <net/netisr.h>
#include <net/route.h>
@@ -242,6 +243,7 @@
struct iso88025_header gen_th;
struct sockaddr_dl *sdl = NULL;
struct rtentry *rt = NULL;
+ struct llentry *lle;
#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
@@ -287,7 +289,7 @@
switch (dst->sa_family) {
#ifdef INET
case AF_INET:
- error = arpresolve(ifp, rt0, m, dst, edst);
+ error = arpresolve(ifp, rt0, m, dst, edst, &lle);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
snap_type = ETHERTYPE_IP;
@@ -322,7 +324,7 @@
#endif /* INET */
#ifdef INET6
case AF_INET6:
- error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst);
+ error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst, &lle);
if (error)
return (error);
snap_type = ETHERTYPE_IPV6;
==== //depot/projects/arp-v2/src/sys/net/if_var.h#2 (text+ko) ====
@@ -68,6 +68,7 @@
struct rt_addrinfo;
struct socket;
struct ether_header;
+struct lltable;
struct carp_if;
struct ifvlantrunk;
#endif
@@ -92,6 +93,7 @@
TAILQ_HEAD(ifprefixhead, ifprefix);
TAILQ_HEAD(ifmultihead, ifmultiaddr);
TAILQ_HEAD(ifgrouphead, ifg_group);
+TAILQ_HEAD(lltables, lltable); /* L2/L3 address resolution table */
/*
* Structure defining a queue for a network interface.
@@ -169,7 +171,7 @@
void *if_bridge; /* bridge glue */
- struct lltable *lltables; /* list of L3-L2 resolution tables */
+ struct lltables if_lltables; /* list of L3-L2 resolution tables */
struct label *if_label; /* interface MAC label */
@@ -181,6 +183,8 @@
struct task if_starttask; /* task for IFF_NEEDSGIANT */
struct task if_linktask; /* task for link change events */
struct mtx if_addr_mtx; /* mutex to protect address lists */
+ struct mtx if_lltbls_mtx; /* mutex to protect link-layer
+ address tables */
LIST_ENTRY(ifnet) if_clones; /* interfaces of a cloner */
TAILQ_HEAD(, ifg_list) if_groups; /* linked list of groups per if */
/* protected by if_addr_mtx */
@@ -235,6 +239,22 @@
#define IF_ADDR_LOCK_ASSERT(if) mtx_assert(&(if)->if_addr_mtx, MA_OWNED)
/*
+ * Locks for link-layer address tables on the network interface.
+ */
+#define IF_LLTBLS_LOCK_INIT(if) mtx_init(&(if)->if_lltbls_mtx, \
+ "if_lltbls_mtx", NULL, MTX_DEF | MTX_RECURSE)
+#define IF_LLTBLS_LOCK_DESTROY(if) mtx_destroy(&(if)->if_lltbls_mtx)
+#if 0
+#define IF_LLTBLS_LOCK(if) mtx_lock(&(if)->if_lltbls_mtx)
+#define IF_LLTBLS_UNLOCK(if) mtx_unlock(&(if)->if_lltbls_mtx)
+#else
+#define IF_LLTBLS_LOCK(if)
+#define IF_LLTBLS_UNLOCK(if)
+#endif
+#define IF_LLTBLS_LOCK_ASSERT(if) mtx_assert(&(if)->if_lltbls_mtx, MA_OWNED)
+
+
+/*
* Output queues (ifp->if_snd) and slow device input queues (*ifp->if_slowq)
* are queues of messages stored on ifqueue structures
* (defined above). Entries are added to and deleted from these structures
==== //depot/projects/arp-v2/src/sys/net/route.c#2 (text+ko) ====
@@ -42,6 +42,7 @@
#include <sys/kernel.h>
#include <net/if.h>
+#include <net/if_dl.h>
#include <net/route.h>
#include <netinet/in.h>
@@ -1149,6 +1150,7 @@
struct rtentry *rt = NULL;
struct rt_addrinfo info;
int error;
+ static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
if (flags & RTF_HOST) {
dst = ifa->ifa_dstaddr;
@@ -1209,7 +1211,13 @@
info.rti_ifa = ifa;
info.rti_flags = flags | ifa->ifa_flags;
info.rti_info[RTAX_DST] = dst;
- info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
+ /*
+ * doing this for compatibility reasons
+ */
+ if (cmd == RTM_ADD)
+ info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&null_sdl;
+ else
+ info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
info.rti_info[RTAX_NETMASK] = netmask;
error = rtrequest1(cmd, &info, &rt);
if (error == 0 && rt != NULL) {
@@ -1217,6 +1225,13 @@
* notify any listening routing agents of the change
*/
RT_LOCK(rt);
+ /*
+ * doing this for compatibility reasons
+ */
+ if (cmd == RTM_ADD) {
+ ((struct sockaddr_dl *)rt->rt_gateway)->sdl_type = rt->rt_ifp->if_type;
+ ((struct sockaddr_dl *)rt->rt_gateway)->sdl_index = rt->rt_ifp->if_index;
+ }
rt_newaddrmsg(cmd, ifa, error, rt);
if (cmd == RTM_DELETE) {
/*
==== //depot/projects/arp-v2/src/sys/net/rtsock.c#2 (text+ko) ====
@@ -44,8 +44,10 @@
#include <sys/socketvar.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
+#include <sys/callout.h>
#include <net/if.h>
+#include <net/if_llatbl.h>
#include <net/netisr.h>
#include <net/raw_cb.h>
#include <net/route.h>
@@ -106,6 +108,8 @@
struct rt_metrics *out);
static void rt_dispatch(struct mbuf *, const struct sockaddr *);
+extern int sysctl_dumparp(int af, struct sysctl_req *wr);
+
static void
rts_init(void)
{
@@ -385,6 +389,11 @@
if (info.rti_info[RTAX_GATEWAY] == NULL)
senderr(EINVAL);
saved_nrt = NULL;
+ /* support for new ARP code */
+ if (info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) {
+ error = lla_rt_output(rtm, &info);
+ break;
+ }
error = rtrequest1(RTM_ADD, &info, &saved_nrt);
if (error == 0 && saved_nrt) {
RT_LOCK(saved_nrt);
@@ -399,6 +408,12 @@
case RTM_DELETE:
saved_nrt = NULL;
+ /* support for new ARP code */
+ if (info.rti_info[RTAX_GATEWAY] &&
+ (info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK)) {
+ error = lla_rt_output(rtm, &info);
+ break;
+ }
error = rtrequest1(RTM_DELETE, &info, &saved_nrt);
if (error == 0) {
RT_LOCK(saved_nrt);
@@ -1265,6 +1280,11 @@
RADIX_NODE_HEAD_UNLOCK(rnh);
} else if (af != 0)
error = EAFNOSUPPORT;
+ /*
+ * take care of llinfo entries
+ */
+ if (w.w_op == NET_RT_FLAGS && (RTF_LLINFO & w.w_arg))
+ error = sysctl_dumparp(af, w.w_req);
break;
case NET_RT_IFLIST:
==== //depot/projects/arp-v2/src/sys/netinet/if_ether.c#2 (text+ko) ====
@@ -62,6 +62,7 @@
#include <netinet/in.h>
#include <netinet/in_var.h>
+#include <net/if_llatbl.h>
#include <netinet/if_ether.h>
#include <net/if_arc.h>
@@ -85,21 +86,10 @@
SYSCTL_INT(_net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_RW,
&arpt_keep, 0, "ARP entry lifetime in seconds");
-#define rt_expire rt_rmx.rmx_expire
-
-struct llinfo_arp {
- struct callout la_timer;
- struct rtentry *la_rt;
- struct mbuf *la_hold; /* last packet until resolved/timeout */
- u_short la_preempt; /* countdown for pre-expiry arps */
- u_short la_asked; /* # requests sent */
-};
-
static struct ifqueue arpintrq;
-static int arp_allocated;
static int arp_maxtries = 5;
-static int useloopback = 1; /* use loopback interface for local traffic */
+int useloopback = 1; /* use loopback interface for local traffic */
static int arp_proxyall = 0;
SYSCTL_INT(_net_link_ether_inet, OID_AUTO, maxtries, CTLFLAG_RW,
@@ -110,210 +100,97 @@
&arp_proxyall, 0, "Enable proxy ARP for all suitable requests");
static void arp_init(void);
-static void arp_rtrequest(int, struct rtentry *, struct rt_addrinfo *);
-static void arprequest(struct ifnet *,
+void arprequest(struct ifnet *,
struct in_addr *, struct in_addr *, u_char *);
static void arpintr(struct mbuf *);
static void arptimer(void *);
-static struct rtentry
- *arplookup(u_long, int, int);
#ifdef INET
static void in_arpinput(struct mbuf *);
#endif
+#ifdef AF_INET
+void arp_ifscrub(struct ifnet *ifp, uint32_t addr);
+
/*
- * Timeout routine.
+ * called by in_ifscrub to remove entry from the table when
+ * the interface goes away
*/
-static void
-arptimer(void *arg)
+void
+arp_ifscrub(struct ifnet *ifp, uint32_t addr)
{
- struct rtentry *rt = (struct rtentry *)arg;
+ struct sockaddr_in addr4;
+ struct llentry *lle;
- RT_LOCK_ASSERT(rt);
- /*
- * The lock is needed to close a theoretical race
- * between spontaneous expiry and intentional removal.
- * We still got an extra reference on rtentry, so can
- * safely pass pointers to its contents.
- */
- RT_UNLOCK(rt);
-
- rtrequest(RTM_DELETE, rt_key(rt), NULL, rt_mask(rt), 0, NULL);
+ bzero((void *)&addr4, sizeof(addr4));
+ addr4.sin_len = sizeof(addr4);
+ addr4.sin_family = AF_INET;
+ addr4.sin_addr.s_addr = addr;
+ IF_LLTBLS_LOCK(ifp);
+ lle = lla_lookup(ifp, (LLE_DELETE | LLE_IFADDR), (struct sockaddr *)&addr4);
+ IF_LLTBLS_UNLOCK(ifp);
+#if 0
+ if (lle == NULL)
+ log(LOG_INFO, "arp_ifscrub: interface address is missing from cache\n");
+#endif
}
+#endif
/*
- * Parallel to llc_rtrequest.
+ * Timeout routine. Age arp_tab entries periodically.
*/
static void
-arp_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
+arptimer(void *arg)
{
- struct sockaddr *gate;
- struct llinfo_arp *la;
- static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
- struct in_ifaddr *ia;
- struct ifaddr *ifa;
+ struct ifnet *ifp;
+ struct llentry *lle = (struct llentry *)arg;
- RT_LOCK_ASSERT(rt);
-
- if (rt->rt_flags & RTF_GATEWAY)
- return;
- gate = rt->rt_gateway;
- la = (struct llinfo_arp *)rt->rt_llinfo;
- switch (req) {
-
- case RTM_ADD:
- /*
- * XXX: If this is a manually added route to interface
- * such as older version of routed or gated might provide,
- * restore cloning bit.
- */
- if ((rt->rt_flags & RTF_HOST) == 0 &&
- rt_mask(rt) != NULL &&
- SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff)
- rt->rt_flags |= RTF_CLONING;
- if (rt->rt_flags & RTF_CLONING) {
- /*
- * Case 1: This route should come from a route to iface.
- */
- rt_setgate(rt, rt_key(rt),
- (struct sockaddr *)&null_sdl);
- gate = rt->rt_gateway;
- SDL(gate)->sdl_type = rt->rt_ifp->if_type;
- SDL(gate)->sdl_index = rt->rt_ifp->if_index;
- rt->rt_expire = time_uptime;
- break;
- }
- /* Announce a new entry if requested. */
- if (rt->rt_flags & RTF_ANNOUNCE)
- arprequest(rt->rt_ifp,
- &SIN(rt_key(rt))->sin_addr,
- &SIN(rt_key(rt))->sin_addr,
- (u_char *)LLADDR(SDL(gate)));
- /*FALLTHROUGH*/
- case RTM_RESOLVE:
- if (gate->sa_family != AF_LINK ||
- gate->sa_len < sizeof(null_sdl)) {
- log(LOG_DEBUG, "%s: bad gateway %s%s\n", __func__,
- inet_ntoa(SIN(rt_key(rt))->sin_addr),
- (gate->sa_family != AF_LINK) ?
- " (!AF_LINK)": "");
- break;
- }
- SDL(gate)->sdl_type = rt->rt_ifp->if_type;
- SDL(gate)->sdl_index = rt->rt_ifp->if_index;
- if (la != 0)
- break; /* This happens on a route change */
- /*
- * Case 2: This route may come from cloning, or a manual route
- * add with a LL address.
- */
- R_Zalloc(la, struct llinfo_arp *, sizeof(*la));
- rt->rt_llinfo = (caddr_t)la;
- if (la == 0) {
- log(LOG_DEBUG, "%s: malloc failed\n", __func__);
- break;
- }
- arp_allocated++;
- /*
- * We are storing a route entry outside of radix tree. So,
- * it can be found and accessed by other means than radix
- * lookup. The routing code assumes that any rtentry detached
- * from radix can be destroyed safely. To prevent this, we
- * add an additional reference.
- */
- RT_ADDREF(rt);
- la->la_rt = rt;
- rt->rt_flags |= RTF_LLINFO;
- callout_init_mtx(&la->la_timer, &rt->rt_mtx,
- CALLOUT_RETURNUNLOCKED);
-
-#ifdef INET
- /*
- * This keeps the multicast addresses from showing up
- * in `arp -a' listings as unresolved. It's not actually
- * functional. Then the same for broadcast.
- */
- if (IN_MULTICAST(ntohl(SIN(rt_key(rt))->sin_addr.s_addr)) &&
- rt->rt_ifp->if_type != IFT_ARCNET) {
- ETHER_MAP_IP_MULTICAST(&SIN(rt_key(rt))->sin_addr,
- LLADDR(SDL(gate)));
- SDL(gate)->sdl_alen = 6;
- rt->rt_expire = 0;
- }
- if (in_broadcast(SIN(rt_key(rt))->sin_addr, rt->rt_ifp)) {
- memcpy(LLADDR(SDL(gate)), rt->rt_ifp->if_broadcastaddr,
- rt->rt_ifp->if_addrlen);
- SDL(gate)->sdl_alen = rt->rt_ifp->if_addrlen;
- rt->rt_expire = 0;
- }
-#endif
-
- TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) {
- if (ia->ia_ifp == rt->rt_ifp &&
- SIN(rt_key(rt))->sin_addr.s_addr ==
- (IA_SIN(ia))->sin_addr.s_addr)
- break;
- }
- if (ia) {
- /*
- * This test used to be
- * if (loif.if_flags & IFF_UP)
- * It allowed local traffic to be forced
- * through the hardware by configuring the loopback down.
- * However, it causes problems during network configuration
- * for boards that can't receive packets they send.
- * It is now necessary to clear "useloopback" and remove
- * the route to force traffic out to the hardware.
- */
- rt->rt_expire = 0;
- bcopy(IF_LLADDR(rt->rt_ifp), LLADDR(SDL(gate)),
- SDL(gate)->sdl_alen = rt->rt_ifp->if_addrlen);
- if (useloopback) {
- rt->rt_ifp = loif;
- rt->rt_rmx.rmx_mtu = loif->if_mtu;
- }
-
- /*
- * make sure to set rt->rt_ifa to the interface
- * address we are using, otherwise we will have trouble
- * with source address selection.
- */
- ifa = &ia->ia_ifa;
- if (ifa != rt->rt_ifa) {
- IFAFREE(rt->rt_ifa);
- IFAREF(ifa);
- rt->rt_ifa = ifa;
- }
- }
- break;
-
- case RTM_DELETE:
- if (la == NULL) /* XXX: at least CARP does this. */
- break;
- callout_stop(&la->la_timer);
- rt->rt_llinfo = NULL;
- rt->rt_flags &= ~RTF_LLINFO;
- RT_REMREF(rt);
- if (la->la_hold)
- m_freem(la->la_hold);
- Free((caddr_t)la);
+ ifp = lle->lle_tbl->llt_ifp;
+ IF_LLTBLS_LOCK(ifp);
+ if ((lle->la_flags & LLE_DELETED) &&
+ !(lle->la_flags & LLE_STATIC)) {
+ callout_stop(&lle->la_timer);
+ (void)llentry_free(lle);
}
+ IF_LLTBLS_UNLOCK(ifp);
}
+
/*
* Broadcast an ARP request. Caller specifies:
* - arp header source ip address
* - arp header target ip address
* - arp header source ethernet address
*/
-static void
-arprequest(struct ifnet *ifp, struct in_addr *sip, struct in_addr *tip,
+void
+arprequest(struct ifnet *ifp, struct in_addr *sip, struct in_addr *tip,
u_char *enaddr)
{
struct mbuf *m;
struct arphdr *ah;
struct sockaddr sa;
+ if (sip == NULL) {
+ /*
+ * The caller did not supply a source address, try to find
+ * a compatible one among those assigned to this interface.
+ */
+ struct ifaddr *ifa;
+
+ TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ if (!ifa->ifa_addr ||
+ ifa->ifa_addr->sa_family != AF_INET)
+ continue;
+ sip = &SIN(ifa->ifa_addr)->sin_addr;
+ if (0 == ((sip->s_addr ^ tip->s_addr) &
+ SIN(ifa->ifa_netmask)->sin_addr.s_addr) )
+ break; /* found it. */
+ }
+ }
+ if (sip == NULL) {
+ printf(" cannot find matching address, no arprequest\n");
+ return;
+ }
+
if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
return;
m->m_len = sizeof(*ah) + 2*sizeof(struct in_addr) +
@@ -355,13 +232,14 @@
*/
int
arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
- struct sockaddr *dst, u_char *desten)
+ struct sockaddr *dst, u_char *desten, struct llentry **lle)
{
- struct llinfo_arp *la = NULL;
- struct rtentry *rt = NULL;
- struct sockaddr_dl *sdl;
+ struct llentry *la = 0;
+ u_int flags;
int error;
+ *lle = NULL;
+
if (m->m_flags & M_BCAST) { /* broadcast */
(void)memcpy(desten, ifp->if_broadcastaddr, ifp->if_addrlen);
return (0);
@@ -370,77 +248,49 @@
ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten);
return (0);
}
+ if (!ifp)
+ panic("%s: invalid interface pointer", __func__);
- if (rt0 != NULL) {
- error = rt_check(&rt, &rt0, dst);
- if (error) {
- m_freem(m);
- return error;
- }
- la = (struct llinfo_arp *)rt->rt_llinfo;
- if (la == NULL)
- RT_UNLOCK(rt);
- }
+ flags = (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) ? 0 : LLE_CREATE;
+
+ /* Qing
+ * because this function returns an llentry,
+ * the IF LLTBLS lock is held by the caller
+ */
+ la = lla_lookup(ifp, flags, dst);
if (la == NULL) {
- /*
- * We enter this block in case if rt0 was NULL,
- * or if rt found by rt_check() didn't have llinfo.
- */
- rt = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0);
- if (rt == NULL) {
- log(LOG_DEBUG,
- "arpresolve: can't allocate route for %s\n",
- inet_ntoa(SIN(dst)->sin_addr));
- m_freem(m);
- return (EINVAL); /* XXX */
- }
- la = (struct llinfo_arp *)rt->rt_llinfo;
- if (la == NULL) {
- RT_UNLOCK(rt);
+ if (flags & LLE_CREATE)
log(LOG_DEBUG,
"arpresolve: can't allocate llinfo for %s\n",
inet_ntoa(SIN(dst)->sin_addr));
- m_freem(m);
- return (EINVAL); /* XXX */
- }
- }
- sdl = SDL(rt->rt_gateway);
- /*
- * Check the address family and length is valid, the address
- * is resolved; otherwise, try to resolve.
- */
- if ((rt->rt_expire == 0 || rt->rt_expire > time_uptime) &&
- sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) {
+ m_freem(m);
+ return (EINVAL);
+ }
+ if (flags & LLE_CREATE)
+ callout_init(&la->la_timer, 0);
- bcopy(LLADDR(sdl), desten, sdl->sdl_alen);
-
+ if (la->la_flags & LLE_VALID &&
+ (la->la_flags & LLE_STATIC || la->la_expire > time_uptime)) {
+ bcopy(&la->ll_addr, desten, ifp->if_addrlen);
/*
* If entry has an expiry time and it is approaching,
- * send an ARP request.
+ * see if we need to send an ARP request within this
+ * arpt_down interval.
*/
- if ((rt->rt_expire != 0) &&
- (time_uptime + la->la_preempt > rt->rt_expire)) {
- struct in_addr sin =
- SIN(rt->rt_ifa->ifa_addr)->sin_addr;
+ if (!(la->la_flags & LLE_STATIC) &&
+ time_uptime + la->la_preempt > la->la_expire) {
+ arprequest(ifp, NULL,
+ &SIN(dst)->sin_addr, IF_LLADDR(ifp));
la->la_preempt--;
- RT_UNLOCK(rt);
- arprequest(ifp, &sin, &SIN(dst)->sin_addr,
- IF_LLADDR(ifp));
- return (0);
}
-
- RT_UNLOCK(rt);
+ *lle = la;
return (0);
}
- /*
- * If ARP is disabled or static on this interface, stop.
- * XXX
- * Probably should not allocate empty llinfo struct if we are
- * not going to be sending out an arp request.
- */
- if (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) {
- RT_UNLOCK(rt);
+
+ if (la->la_flags & LLE_STATIC) { /* should not happen! */
+ log(LOG_DEBUG, "arpresolve: ouch, empty static llinfo for %s\n",
+ inet_ntoa(SIN(dst)->sin_addr));
m_freem(m);
return (EINVAL);
}
@@ -453,8 +303,6 @@
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list