NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: kern/49682: reproducable panic when detaching bge (IPv6 related)
The following reply was made to PR kern/49682; it has been noted by GNATS.
From: Martin Husemann <martin%duskware.de@localhost>
To: Christos Zoulas <christos%zoulas.com@localhost>
Cc: gnats-bugs%NetBSD.org@localhost
Subject: Re: kern/49682: reproducable panic when detaching bge (IPv6 related)
Date: Sun, 22 Feb 2015 22:06:11 +0100
The last time we have a chance to successfully clean this up is before
dom_ifdetach frees the adress family specific data - so we need to make
sure nd6_purge is called from there as well, and gets the info explicitly
passed.
The patch below works for me.
Martin
Index: in6.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/in6.c,v
retrieving revision 1.181
diff -u -p -r1.181 in6.c
--- in6.c 20 Feb 2015 22:13:48 -0000 1.181
+++ in6.c 22 Feb 2015 21:04:15 -0000
@@ -2318,7 +2318,7 @@ in6_domifdetach(struct ifnet *ifp, void
{
struct in6_ifextra *ext = (struct in6_ifextra *)aux;
- nd6_ifdetach(ext->nd_ifinfo);
+ nd6_ifdetach(ifp, ext);
free(ext->in6_ifstat, M_IFADDR);
free(ext->icmp6_ifstat, M_IFADDR);
scope6_ifdetach(ext->scope6_id);
Index: in6_ifattach.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/in6_ifattach.c,v
retrieving revision 1.94
diff -u -p -r1.94 in6_ifattach.c
--- in6_ifattach.c 14 Nov 2014 17:34:23 -0000 1.94
+++ in6_ifattach.c 22 Feb 2015 21:04:15 -0000
@@ -847,8 +847,9 @@ in6_ifdetach(struct ifnet *ifp)
/* remove ip6_mrouter stuff */
ip6_mrouter_detach(ifp);
- /* remove neighbor management table */
- nd6_purge(ifp);
+ /* remove neighbor management table, if ND data is still available */
+ if (ifp->if_afdata[AF_INET6] != NULL)
+ nd6_purge(ifp, ifp->if_afdata[AF_INET6]);
/* XXX this code is duplicated in in6_purgeif() --dyoung */
/* nuke any of IPv6 addresses we have */
@@ -919,7 +920,8 @@ in6_ifdetach(struct ifnet *ifp)
* prefixes after removing all addresses above.
* (Or can we just delay calling nd6_purge until at this point?)
*/
- nd6_purge(ifp);
+ if (ifp->if_afdata[AF_INET6] != NULL)
+ nd6_purge(ifp, ifp->if_afdata[AF_INET6]);
}
int
Index: nd6.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/nd6.c,v
retrieving revision 1.157
diff -u -p -r1.157 nd6.c
--- nd6.c 17 Feb 2015 15:14:28 -0000 1.157
+++ nd6.c 22 Feb 2015 21:04:15 -0000
@@ -205,10 +205,11 @@ nd6_ifattach(struct ifnet *ifp)
}
void
-nd6_ifdetach(struct nd_ifinfo *nd)
+nd6_ifdetach(struct ifnet *ifp, struct in6_ifextra *ext)
{
- free(nd, M_IP6NDP);
+ nd6_purge(ifp, ext);
+ free(ext->nd_ifinfo, M_IP6NDP);
}
void
@@ -556,7 +557,7 @@ nd6_timer(void *ignored_arg)
TAILQ_FOREACH_SAFE(dr, &nd_defrouter, dr_entry, next_dr) {
if (dr->expire && dr->expire < time_second) {
- defrtrlist_del(dr);
+ defrtrlist_del(dr, NULL);
}
}
@@ -746,13 +747,21 @@ nd6_accepts_rtadv(const struct nd_ifinfo
* ifp goes away.
*/
void
-nd6_purge(struct ifnet *ifp)
+nd6_purge(struct ifnet *ifp, struct in6_ifextra *ext)
{
struct llinfo_nd6 *ln, *nln;
struct nd_defrouter *dr, *ndr;
struct nd_prefix *pr, *npr;
/*
+ * During detach, the ND info might be already removed, but
+ * then is explitly passed as argument.
+ * Otherwise get it from ifp->if_afdata.
+ */
+ if (ext == NULL)
+ ext = ifp->if_afdata[AF_INET6];
+
+ /*
* Nuke default router list entries toward ifp.
* We defer removal of default router list entries that is installed
* in the routing table, in order to keep additional side effects as
@@ -762,16 +771,20 @@ nd6_purge(struct ifnet *ifp)
if (dr->installed)
continue;
- if (dr->ifp == ifp)
- defrtrlist_del(dr);
+ if (dr->ifp == ifp) {
+ KASSERT(ext != NULL);
+ defrtrlist_del(dr, ext);
+ }
}
TAILQ_FOREACH_SAFE(dr, &nd_defrouter, dr_entry, ndr) {
if (!dr->installed)
continue;
- if (dr->ifp == ifp)
- defrtrlist_del(dr);
+ if (dr->ifp == ifp) {
+ KASSERT(ext != NULL);
+ defrtrlist_del(dr, ext);
+ }
}
/* Nuke prefix list entries toward ifp */
@@ -1797,7 +1810,7 @@ nd6_ioctl(u_long cmd, void *data, struct
s = splsoftnet();
defrouter_reset();
TAILQ_FOREACH_SAFE(drtr, &nd_defrouter, dr_entry, next) {
- defrtrlist_del(drtr);
+ defrtrlist_del(drtr, NULL);
}
defrouter_select();
splx(s);
Index: nd6.h
===================================================================
RCS file: /cvsroot/src/sys/netinet6/nd6.h,v
retrieving revision 1.61
diff -u -p -r1.61 nd6.h
--- nd6.h 16 Dec 2014 11:42:27 -0000 1.61
+++ nd6.h 22 Feb 2015 21:04:15 -0000
@@ -407,7 +407,7 @@ union nd_opts {
/* nd6.c */
void nd6_init(void);
struct nd_ifinfo *nd6_ifattach(struct ifnet *);
-void nd6_ifdetach(struct nd_ifinfo *);
+void nd6_ifdetach(struct ifnet *, struct in6_ifextra *);
int nd6_is_addr_neighbor(const struct sockaddr_in6 *, struct ifnet *);
void nd6_option_init(void *, int, union nd_opts *);
struct nd_opt_hdr *nd6_option(union nd_opts *);
@@ -417,7 +417,7 @@ void nd6_rtmsg(int, struct rtentry *);
void nd6_setmtu(struct ifnet *);
void nd6_llinfo_settimer(struct llinfo_nd6 *, long);
void nd6_timer(void *);
-void nd6_purge(struct ifnet *);
+void nd6_purge(struct ifnet *, struct in6_ifextra *);
void nd6_nud_hint(struct rtentry *, struct in6_addr *, int);
int nd6_resolve(struct ifnet *, struct rtentry *,
struct mbuf *, struct sockaddr *, u_char *);
@@ -454,7 +454,7 @@ void prelist_del(struct nd_prefix *);
void defrouter_addreq(struct nd_defrouter *);
void defrouter_reset(void);
void defrouter_select(void);
-void defrtrlist_del(struct nd_defrouter *);
+void defrtrlist_del(struct nd_defrouter *, struct in6_ifextra *);
void prelist_remove(struct nd_prefix *);
int nd6_prelist_add(struct nd_prefixctl *, struct nd_defrouter *,
struct nd_prefix **);
Index: nd6_nbr.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/nd6_nbr.c,v
retrieving revision 1.103
diff -u -p -r1.103 nd6_nbr.c
--- nd6_nbr.c 16 Dec 2014 11:42:27 -0000 1.103
+++ nd6_nbr.c 22 Feb 2015 21:04:15 -0000
@@ -804,7 +804,7 @@ nd6_na_input(struct mbuf *m, int off, in
s = splsoftnet();
dr = defrouter_lookup(in6, rt->rt_ifp);
if (dr)
- defrtrlist_del(dr);
+ defrtrlist_del(dr, NULL);
else if (!ip6_forwarding) {
/*
* Even if the neighbor is not in the default
Index: nd6_rtr.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/nd6_rtr.c,v
retrieving revision 1.95
diff -u -p -r1.95 nd6_rtr.c
--- nd6_rtr.c 16 Dec 2014 11:42:27 -0000 1.95
+++ nd6_rtr.c 22 Feb 2015 21:04:15 -0000
@@ -483,12 +483,20 @@ defrouter_lookup(const struct in6_addr *
}
void
-defrtrlist_del(struct nd_defrouter *dr)
+defrtrlist_del(struct nd_defrouter *dr, struct in6_ifextra *ext)
{
- struct nd_ifinfo *ndi = ND_IFINFO(dr->ifp);
struct nd_defrouter *deldr = NULL;
struct nd_prefix *pr;
- struct in6_ifextra *ext = dr->ifp->if_afdata[AF_INET6];
+ struct nd_ifinfo *ndi;
+
+ if (ext == NULL)
+ ext = dr->ifp->if_afdata[AF_INET6];
+
+ /* detach already in progress, can not do anything */
+ if (ext == NULL)
+ return;
+
+ ndi = ext->nd_ifinfo;
/*
* Flush all the routing table entries that use the router
@@ -749,7 +757,7 @@ defrtrlist_update(struct nd_defrouter *n
if ((dr = defrouter_lookup(&newdr->rtaddr, newdr->ifp)) != NULL) {
/* entry exists */
if (newdr->rtlifetime == 0) {
- defrtrlist_del(dr);
+ defrtrlist_del(dr, ext);
dr = NULL;
} else {
int oldpref = rtpref(dr);
Home |
Main Index |
Thread Index |
Old Index