Re: ARP mbuf queues
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.c14 Mar 2015 17:13:44 - 1.148 +++ netinet/if_ether.c19 Mar 2015 13:04:28 - @@ -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_queuela_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
Re: ARP mbuf queues
On 21/03/15(Sat) 17:48, David Gwynne wrote: 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? Yep... That might be overkill since we do not really use the mutex. Do you prefer the version below using a mbuf_list? As a bonus this diff only call ml_init() if the pool allocation succeed. 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 - 1.148 +++ netinet/if_ether.c 21 Mar 2015 13:59:55 - @@ -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_list la_ml; /* packet hold queue */ +}; +#define LA_HOLD_QUEUE 10 +#define LA_HOLD_TOTAL 100 + /* timer values */ intarpt_prune = (5*60*1); /* walk list every 5 minutes */ intarpt_keep = (20*60);/* once resolved, good for 20 more minutes */ @@ -227,6 +235,7 @@ arp_rtrequest(int req, struct rtentry *r } arp_inuse++; arp_allocated++; + ml_init(la-la_ml); la-la_rt = rt; rt-rt_flags |= RTF_LLINFO; LIST_INSERT_HEAD(llinfo_arp, la, la_list); @@ -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 = ml_dequeue(la-la_ml)) != NULL) { la_hold_total--; m_freem(m); } @@ -425,32 +433,19 @@ 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--; + if (la_hold_total LA_HOLD_TOTAL la_hold_total nmbclust / 64) { + if (ml_len(la-la_ml) = LA_HOLD_QUEUE) { + mh = ml_dequeue(la-la_ml); 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++; + ml_enqueue(la-la_ml, m); la_hold_total++; } else { - while ((mh = la-la_hold_head) != NULL) { - la-la_hold_head = - la-la_hold_head-m_nextpkt; + while ((mh = ml_dequeue(la-la_ml)) != NULL) { la_hold_total--; m_freem(mh); } - la-la_hold_tail = NULL; - la-la_hold_count = 0; m_freem(m); } @@ -483,14 +478,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 = ml_dequeue(la-la_ml)) != NULL) { la_hold_total--;
Re: ARP mbuf queues
On 19/03/15(Thu) 14:11, Martin Pieuchot 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? Oops, kspillner@ pointed that I forgot a chunk, here's the full diff: 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 - 1.148 +++ netinet/if_ether.c 19 Mar 2015 13:04:28 - @@ -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_queuela_mq; /* packet hold queue */ +}; +#define LA_HOLD_QUEUE 10 +#define LA_HOLD_TOTAL 100 + /* timer values */ intarpt_prune = (5*60*1); /* walk list every 5 minutes */ intarpt_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;
ARP mbuf queues
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? 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 - 1.148 +++ netinet/if_ether.c 19 Mar 2015 13:04:28 - @@ -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_queuela_mq; /* packet hold queue */ +}; +#define LA_HOLD_QUEUE 10 +#define LA_HOLD_TOTAL 100 + /* timer values */ intarpt_prune = (5*60*1); /* walk list every 5 minutes */ intarpt_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;