> On 19 Mar 2015, at 11:11 pm, Martin Pieuchot <[email protected]> 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);
> }
>
> /*