Index: if_ether.c =================================================================== RCS file: /cvs/src/sys/netinet/if_ether.c,v retrieving revision 1.216 diff -u -p -r1.216 if_ether.c --- if_ether.c 28 Jun 2016 17:18:24 -0000 1.216 +++ if_ether.c 11 Jul 2016 11:07:29 -0000 @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -81,11 +82,17 @@ int arpt_down = 20; /* once declared do void arptfree(struct rtentry *); void arptimer(void *); struct rtentry *arplookup(struct in_addr *, int, int, unsigned int); -void in_arpinput(struct ifnet *, struct mbuf *); +void in_arpinput(struct mbuf *); void in_revarpinput(struct ifnet *, struct mbuf *); int arpcache(struct ifnet *, struct ether_arp *, struct rtentry *); void arpreply(struct ifnet *, struct mbuf *, struct in_addr *, uint8_t *); +void arprun(void *); +void in_arp(struct ifnet *, struct mbuf *); + +struct mbuf_queue arp_queue = MBUF_QUEUE_INITIALIZER(32, IPL_SOFTNET); +struct task arp_task = TASK_INITIALIZER(arprun, &arp_queue); + LIST_HEAD(, llinfo_arp) arp_list; struct pool arp_pool; /* pool for llinfo_arp structures */ int arp_maxtries = 5; @@ -209,7 +216,7 @@ arp_rtrequest(struct ifnet *ifp, int req if (la == NULL) break; LIST_REMOVE(la, la_list); - rt->rt_llinfo = 0; + rt->rt_llinfo = NULL; rt->rt_flags &= ~RTF_LLINFO; la_hold_total -= ml_purge(&la->la_ml); pool_put(&arp_pool, la); @@ -438,7 +445,35 @@ arpinput(struct ifnet *ifp, struct mbuf if (m->m_len < len && (m = m_pullup(m, len)) == NULL) return; - in_arpinput(ifp, m); + in_arpinput(m); +} + +void +in_arpinput(struct mbuf *m) +{ + if (mq_enqueue(&arp_queue, m) == 0) + task_add(systq, &arp_task); +} + +void +arprun(void *mq) +{ + struct mbuf_list ml; + struct mbuf *m; + struct ifnet *ifp; + + mq_delist(mq, &ml); + + while ((m = ml_dequeue(&ml)) != NULL) { + ifp = if_get(m->m_pkthdr.ph_ifidx); + + if (ifp != NULL) + in_arp(ifp, m); + else + m_freem(m); + + if_put(ifp); + } } /* @@ -447,7 +482,7 @@ arpinput(struct ifnet *ifp, struct mbuf * protocol address, to catch impersonators. */ void -in_arpinput(struct ifnet *ifp, struct mbuf *m) +in_arp(struct ifnet *ifp, struct mbuf *m) { struct ether_arp *ea; struct rtentry *rt = NULL; @@ -788,7 +823,7 @@ in_revarpinput(struct ifnet *ifp, struct switch (op) { case ARPOP_REQUEST: case ARPOP_REPLY: /* per RFC */ - in_arpinput(ifp, m); + in_arpinput(m); return; case ARPOP_REVREPLY: break;