> On 19 Mar 2015, at 11:11 pm, Martin Pieuchot <m...@openbsd.org> wrote: > > When a host want to send packets to a destination whose Ethernet address > that has not been resolved yet, it puts such packet on a mbuf queue. > > Right now this queue, linked to the corresponding ARP data structure, is > hand rolled. I wrote the diff below during s2k15 to make use of the > mq_enqueue(9) API instead. > > I verified that the queue is correctly dropped when an infinite recursion > in in_arpinput() is triggered. > > Comments, Ok?
the global count is annoying to read, but i get it. why mbuf_queues instead of mbuf_lists? just to get the drop on mq_enqueue? > > Index: netinet/if_ether.c > =================================================================== > RCS file: /cvs/src/sys/netinet/if_ether.c,v > retrieving revision 1.148 > diff -u -p -r1.148 if_ether.c > --- netinet/if_ether.c 14 Mar 2015 17:13:44 -0000 1.148 > +++ netinet/if_ether.c 19 Mar 2015 13:04:28 -0000 > @@ -69,7 +69,6 @@ > #endif > > #define SDL(s) ((struct sockaddr_dl *)s) > -#define SRP(s) ((struct sockaddr_inarp *)s) > > /* > * ARP trailer negotiation. Trailer protocol is not IP specific, > @@ -77,6 +76,15 @@ > */ > #define ETHERTYPE_IPTRAILERS ETHERTYPE_TRAIL > > +struct llinfo_arp { > + LIST_ENTRY(llinfo_arp) la_list; > + struct rtentry *la_rt; /* backpointer to rtentry */ > + long la_asked; /* last time we QUERIED */ > + struct mbuf_queue la_mq; /* packet hold queue */ > +}; > +#define LA_HOLD_QUEUE 10 > +#define LA_HOLD_TOTAL 100 > + > /* timer values */ > int arpt_prune = (5*60*1); /* walk list every 5 minutes */ > int arpt_keep = (20*60); /* once resolved, good for 20 more minutes */ > @@ -220,6 +228,7 @@ arp_rtrequest(int req, struct rtentry *r > * add with a LL address. > */ > la = pool_get(&arp_pool, PR_NOWAIT | PR_ZERO); > + mq_init(&la->la_mq, LA_HOLD_QUEUE, IPL_NONE); > rt->rt_llinfo = (caddr_t)la; > if (la == NULL) { > log(LOG_DEBUG, "%s: malloc failed\n", __func__); > @@ -282,8 +291,7 @@ arp_rtrequest(int req, struct rtentry *r > LIST_REMOVE(la, la_list); > rt->rt_llinfo = 0; > rt->rt_flags &= ~RTF_LLINFO; > - while ((m = la->la_hold_head) != NULL) { > - la->la_hold_head = la->la_hold_head->m_nextpkt; > + while ((m = mq_dequeue(&la->la_mq)) != NULL) { > la_hold_total--; > m_freem(m); > } > @@ -425,32 +433,14 @@ arpresolve(struct arpcom *ac, struct rte > * response yet. Insert mbuf in hold queue if below limit > * if above the limit free the queue without queuing the new packet. > */ > - if (la_hold_total < MAX_HOLD_TOTAL && la_hold_total < nmbclust / 64) { > - if (la->la_hold_count >= MAX_HOLD_QUEUE) { > - mh = la->la_hold_head; > - la->la_hold_head = la->la_hold_head->m_nextpkt; > - if (mh == la->la_hold_tail) > - la->la_hold_tail = NULL; > - la->la_hold_count--; > - la_hold_total--; > - m_freem(mh); > - } > - if (la->la_hold_tail == NULL) > - la->la_hold_head = m; > - else > - la->la_hold_tail->m_nextpkt = m; > - la->la_hold_tail = m; > - la->la_hold_count++; > - la_hold_total++; > + if (la_hold_total < LA_HOLD_TOTAL && la_hold_total < nmbclust / 64) { > + if (mq_enqueue(&la->la_mq, m) == 0) > + la_hold_total++; > } else { > - while ((mh = la->la_hold_head) != NULL) { > - la->la_hold_head = > - la->la_hold_head->m_nextpkt; > + while ((mh = mq_dequeue(&la->la_mq)) != NULL) { > la_hold_total--; > m_freem(mh); > } > - la->la_hold_tail = NULL; > - la->la_hold_count = 0; > m_freem(m); > } > > @@ -483,14 +473,10 @@ arpresolve(struct arpcom *ac, struct rte > rt->rt_flags |= RTF_REJECT; > rt->rt_expire += arpt_down; > la->la_asked = 0; > - while ((mh = la->la_hold_head) != NULL) { > - la->la_hold_head = > - la->la_hold_head->m_nextpkt; > + while ((mh = mq_dequeue(&la->la_mq)) != NULL) { > la_hold_total--; > m_freem(mh); > } > - la->la_hold_tail = NULL; > - la->la_hold_count = 0; > } > } > } > @@ -570,13 +556,14 @@ in_arpinput(struct mbuf *m) > struct sockaddr_dl *sdl; > struct sockaddr sa; > struct in_addr isaddr, itaddr, myaddr; > - struct mbuf *mh, *mt; > + struct mbuf *mh; > u_int8_t *enaddr = NULL; > #if NCARP > 0 > u_int8_t *ether_shost = NULL; > #endif > char addr[INET_ADDRSTRLEN]; > int op, changed = 0; > + unsigned int len; > > ea = mtod(m, struct ether_arp *); > op = ntohs(ea->arp_op); > @@ -732,25 +719,19 @@ in_arpinput(struct mbuf *m) > if (la->la_asked || changed) > rt_sendmsg(rt, RTM_RESOLVE, rt->rt_ifp->if_rdomain); > la->la_asked = 0; > - while ((mh = la->la_hold_head) != NULL) { > - if ((la->la_hold_head = mh->m_nextpkt) == NULL) > - la->la_hold_tail = NULL; > - la->la_hold_count--; > + while ((len = mq_len(&la->la_mq)) != 0) { > + mh = mq_dequeue(&la->la_mq); > la_hold_total--; > - mt = la->la_hold_tail; > > (*ac->ac_if.if_output)(&ac->ac_if, mh, rt_key(rt), rt); > > - if (la->la_hold_tail == mh) { > + if (mq_len(&la->la_mq) == len) { > /* mbuf is back in queue. Discard. */ > - la->la_hold_tail = mt; > - if (la->la_hold_tail) > - la->la_hold_tail->m_nextpkt = NULL; > - else > - la->la_hold_head = NULL; > - la->la_hold_count--; > - la_hold_total--; > - m_freem(mh); > + while ((mh = mq_dequeue(&la->la_mq)) != NULL) { > + la_hold_total--; > + m_freem(mh); > + } > + break; > } > } > } > @@ -1114,8 +1095,7 @@ db_print_llinfo(caddr_t li) > if (li == 0) > return; > la = (struct llinfo_arp *)li; > - db_printf(" la_rt=%p la_hold_head=%p, la_asked=0x%lx\n", > - la->la_rt, la->la_hold_head, la->la_asked); > + db_printf(" la_rt=%p la_asked=0x%lx\n", la->la_rt, la->la_asked); > } > > /*