Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F108052403
D35365.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D35365.diff
View Options
diff --git a/sys/net/if_llatbl.h b/sys/net/if_llatbl.h
--- a/sys/net/if_llatbl.h
+++ b/sys/net/if_llatbl.h
@@ -231,6 +231,8 @@
void lltable_prefix_free(int, struct sockaddr *,
struct sockaddr *, u_int);
int lltable_sysctl_dumparp(int, struct sysctl_req *);
+size_t lltable_append_entry_queue(struct llentry *,
+ struct mbuf *, size_t);
struct lltable *in_lltable_get(struct ifnet *ifp);
struct lltable *in6_lltable_get(struct ifnet *ifp);
diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c
--- a/sys/net/if_llatbl.c
+++ b/sys/net/if_llatbl.c
@@ -127,6 +127,41 @@
return (error);
}
+/*
+ * Adds a mbuf to hold queue. Drops old packets if the queue is full.
+ *
+ * Returns the number of held packets that were dropped.
+ */
+size_t
+lltable_append_entry_queue(struct llentry *lle, struct mbuf *m,
+ size_t maxheld)
+{
+ size_t pkts_dropped = 0;
+
+ LLE_WLOCK_ASSERT(lle);
+
+ while (lle->la_numheld >= maxheld && lle->la_hold != NULL) {
+ struct mbuf *next = lle->la_hold->m_nextpkt;
+ m_freem(lle->la_hold);
+ lle->la_hold = next;
+ lle->la_numheld--;
+ pkts_dropped++;
+ }
+
+ if (lle->la_hold != NULL) {
+ struct mbuf *curr = lle->la_hold;
+ while (curr->m_nextpkt != NULL)
+ curr = curr->m_nextpkt;
+ curr->m_nextpkt = m;
+ } else
+ lle->la_hold = m;
+
+ lle->la_numheld++;
+
+ return pkts_dropped;
+}
+
+
/*
* Common function helpers for chained hash table.
*/
@@ -285,14 +320,12 @@
size_t
lltable_drop_entry_queue(struct llentry *lle)
{
- size_t pkts_dropped;
- struct mbuf *next;
+ size_t pkts_dropped = 0;
LLE_WLOCK_ASSERT(lle);
- pkts_dropped = 0;
- while ((lle->la_numheld > 0) && (lle->la_hold != NULL)) {
- next = lle->la_hold->m_nextpkt;
+ while (lle->la_hold != NULL) {
+ struct mbuf *next = lle->la_hold->m_nextpkt;
m_freem(lle->la_hold);
lle->la_hold = next;
lle->la_numheld--;
diff --git a/sys/netinet/icmp6.h b/sys/netinet/icmp6.h
--- a/sys/netinet/icmp6.h
+++ b/sys/netinet/icmp6.h
@@ -602,6 +602,7 @@
uint64_t icp6s_tooshort; /* packet < sizeof(struct icmp6_hdr) */
uint64_t icp6s_checksum; /* bad checksum */
uint64_t icp6s_badlen; /* calculated bound mismatch */
+ uint64_t icp6s_dropped; /* # of packets dropped waiting for a resolution */
/*
* number of responses: this member is inherited from netinet code, but
* for netinet6 code, it is already available in icp6s_outhist[].
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -464,8 +464,6 @@
struct llentry **plle)
{
struct llentry *la = NULL, *la_tmp;
- struct mbuf *curr = NULL;
- struct mbuf *next = NULL;
int error, renew;
char *lladdr;
int ll_len;
@@ -533,6 +531,7 @@
}
renew = (la->la_asked == 0 || la->la_expire != time_uptime);
+
/*
* There is an arptab entry, but no ethernet address
* response yet. Add the mbuf to the list, dropping
@@ -540,24 +539,10 @@
* setting.
*/
if (m != NULL) {
- if (la->la_numheld >= V_arp_maxhold) {
- if (la->la_hold != NULL) {
- next = la->la_hold->m_nextpkt;
- m_freem(la->la_hold);
- la->la_hold = next;
- la->la_numheld--;
- ARPSTAT_INC(dropped);
- }
- }
- if (la->la_hold != NULL) {
- curr = la->la_hold;
- while (curr->m_nextpkt != NULL)
- curr = curr->m_nextpkt;
- curr->m_nextpkt = m;
- } else
- la->la_hold = m;
- la->la_numheld++;
+ size_t dropped = lltable_append_entry_queue(la, m, V_arp_maxhold);
+ ARPSTAT_ADD(dropped, dropped);
}
+
/*
* Return EWOULDBLOCK if we have tried less than arp_maxtries. It
* will be masked by ether_output(). Return EHOSTDOWN/EHOSTUNREACH
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -138,7 +138,6 @@
static void nd6_free_redirect(const struct llentry *);
static void nd6_llinfo_timer(void *);
static void nd6_llinfo_settimer_locked(struct llentry *, long);
-static void clear_llinfo_pqueue(struct llentry *);
static int nd6_resolve_slow(struct ifnet *, int, int, struct mbuf *,
const struct sockaddr_in6 *, u_char *, uint32_t *, struct llentry **);
static int nd6_need_cache(struct ifnet *);
@@ -804,18 +803,19 @@
/* Send NS to multicast address */
pdst = NULL;
} else {
- struct mbuf *m = ln->la_hold;
- if (m) {
- struct mbuf *m0;
+ struct mbuf *m;
+ ICMP6STAT_ADD(icp6s_dropped, ln->la_numheld);
+
+ m = ln->la_hold;
+ if (m != NULL) {
/*
* assuming every packet in la_hold has the
* same IP header. Send error after unlock.
*/
- m0 = m->m_nextpkt;
+ ln->la_hold = m->m_nextpkt;
m->m_nextpkt = NULL;
- ln->la_hold = m0;
- clear_llinfo_pqueue(ln);
+ ln->la_numheld--;
}
nd6_free(&ln, 0);
if (m != NULL) {
@@ -2199,6 +2199,7 @@
chain = ln->la_hold;
ln->la_hold = NULL;
+ ln->la_numheld = 0;
if (ln->ln_state == ND6_LLINFO_STALE) {
/*
@@ -2418,6 +2419,7 @@
struct in6_addr *psrc, src;
int send_ns, ll_len;
char *lladdr;
+ size_t dropped;
NET_EPOCH_ASSERT();
@@ -2484,28 +2486,8 @@
* packet queue in the mbuf. When it exceeds nd6_maxqueuelen,
* the oldest packet in the queue will be removed.
*/
-
- if (lle->la_hold != NULL) {
- struct mbuf *m_hold;
- int i;
-
- i = 0;
- for (m_hold = lle->la_hold; m_hold; m_hold = m_hold->m_nextpkt){
- i++;
- if (m_hold->m_nextpkt == NULL) {
- m_hold->m_nextpkt = m;
- break;
- }
- }
- while (i >= V_nd6_maxqueuelen) {
- m_hold = lle->la_hold;
- lle->la_hold = lle->la_hold->m_nextpkt;
- m_freem(m_hold);
- i--;
- }
- } else {
- lle->la_hold = m;
- }
+ dropped = lltable_append_entry_queue(lle, m, V_nd6_maxqueuelen);
+ ICMP6STAT_ADD(icp6s_dropped, dropped);
/*
* If there has been no NS for the neighbor after entering the
@@ -2700,19 +2682,6 @@
lltable_delete_addr(LLTABLE6(ifp), LLE_IFADDR, saddr);
}
-static void
-clear_llinfo_pqueue(struct llentry *ln)
-{
- struct mbuf *m_hold, *m_hold_next;
-
- for (m_hold = ln->la_hold; m_hold; m_hold = m_hold_next) {
- m_hold_next = m_hold->m_nextpkt;
- m_freem(m_hold);
- }
-
- ln->la_hold = NULL;
-}
-
static int
nd6_sysctl_prlist(SYSCTL_HANDLER_ARGS)
{
diff --git a/usr.bin/netstat/inet6.c b/usr.bin/netstat/inet6.c
--- a/usr.bin/netstat/inet6.c
+++ b/usr.bin/netstat/inet6.c
@@ -994,6 +994,8 @@
"{N:/bad checksum%s}\n");
p(icp6s_badlen, "\t{:dropped-bad-length/%ju} "
"{N:/message%s with bad length}\n");
+ p(icp6s_dropped, "{:dropped-no-entry/%ju} "
+ "{N:/total packet%s dropped due to failed NDP resolution}\n");
#define NELEM (int)(sizeof(icmp6stat.icp6s_inhist)/sizeof(icmp6stat.icp6s_inhist[0]))
for (first = 1, i = 0; i < NELEM; i++)
if (icmp6stat.icp6s_inhist[i] != 0) {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Jan 21, 10:49 PM (18 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16021435
Default Alt Text
D35365.diff (6 KB)
Attached To
Mode
D35365: Fix mbuf leak in NDP
Attached
Detach File
Event Timeline
Log In to Comment