diff options
author | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2001-07-18 12:50:45 +0000 |
---|---|---|
committer | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2001-07-18 12:50:45 +0000 |
commit | 1b9e8efd6e3c626840081750789297daf99ccb76 (patch) | |
tree | c156e1459f4011e1bf645beb039ce7a748b5d898 /sys/netinet6 | |
parent | d4faff719766b6a4ad20c1a3b81b5166dd8c3cb7 (diff) |
avoid using malloc() during interupt context for multicast kludge entry.
allocate it on interface initialization.
Diffstat (limited to 'sys/netinet6')
-rw-r--r-- | sys/netinet6/in6.c | 56 | ||||
-rw-r--r-- | sys/netinet6/in6_ifattach.c | 7 | ||||
-rw-r--r-- | sys/netinet6/in6_var.h | 3 |
3 files changed, 48 insertions, 18 deletions
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 6af82df76f3..656f98caf7a 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -1,5 +1,5 @@ -/* $OpenBSD: in6.c,v 1.28 2001/06/09 06:43:37 angelos Exp $ */ -/* $KAME: in6.c,v 1.176 2001/02/16 12:49:45 itojun Exp $ */ +/* $OpenBSD: in6.c,v 1.29 2001/07/18 12:50:44 itojun Exp $ */ +/* $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -87,9 +87,9 @@ #include <netinet/in_var.h> #include <netinet/if_ether.h> -#include <netinet6/nd6.h> #include <netinet/ip6.h> #include <netinet6/ip6_var.h> +#include <netinet6/nd6.h> #include <netinet6/mld6_var.h> #include <netinet6/ip6_mroute.h> #include <netinet6/in6_ifattach.h> @@ -1253,10 +1253,12 @@ in6_savemkludge(oia) } else { /* last address on this if deleted, save */ struct multi6_kludge *mk; - mk = malloc(sizeof(*mk), M_IPMADDR, M_WAITOK); - - LIST_INIT(&mk->mk_head); - mk->mk_ifp = oia->ia_ifp; + for (mk = in6_mk.lh_first; mk; mk = mk->mk_entry.le_next) { + if (mk->mk_ifp == oia->ia_ifp) + break; + } + if (mk == NULL) /* this should not happen! */ + panic("in6_savemkludge: no kludge space"); for (in6m = oia->ia6_multiaddrs.lh_first; in6m; in6m = next){ next = in6m->in6m_entry.le_next; @@ -1264,12 +1266,6 @@ in6_savemkludge(oia) in6m->in6m_ia = NULL; LIST_INSERT_HEAD(&mk->mk_head, in6m, in6m_entry); } - - if (mk->mk_head.lh_first != NULL) { - LIST_INSERT_HEAD(&in6_mk, mk, mk_entry); - } else { - FREE(mk, M_IPMADDR); - } } } @@ -1296,13 +1292,43 @@ in6_restoremkludge(ia, ifp) LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry); } - LIST_REMOVE(mk, mk_entry); - free(mk, M_IPMADDR); + LIST_INIT(&mk->mk_head); break; } } } +/* + * Allocate space for the kludge at interface initialization time. + * Formerly, we dynamically allocated the space in in6_savemkludge() with + * malloc(M_WAITOK). However, it was wrong since the function could be called + * under an interrupt context (software timer on address lifetime expiration). + * Also, we cannot just give up allocating the strucutre, since the group + * membership structure is very complex and we need to keep it anyway. + * Of course, this function MUST NOT be called under an interrupt context. + * Specifically, it is expected to be called only from in6_ifattach(), though + * it is a global function. + */ +void +in6_createmkludge(ifp) + struct ifnet *ifp; +{ + struct multi6_kludge *mk; + + for (mk = in6_mk.lh_first; mk; mk = mk->mk_entry.le_next) { + /* If we've already had one, do not allocate. */ + if (mk->mk_ifp == ifp) + return; + } + + mk = malloc(sizeof(*mk), M_IPMADDR, M_WAITOK); + + bzero(mk, sizeof(*mk)); + LIST_INIT(&mk->mk_head); + mk->mk_ifp = ifp; + LIST_INSERT_HEAD(&in6_mk, mk, mk_entry); +} + void in6_purgemkludge(ifp) struct ifnet *ifp; diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c index df723fccad1..5e49c126921 100644 --- a/sys/netinet6/in6_ifattach.c +++ b/sys/netinet6/in6_ifattach.c @@ -1,5 +1,5 @@ -/* $OpenBSD: in6_ifattach.c,v 1.17 2001/06/09 06:43:37 angelos Exp $ */ -/* $KAME: in6_ifattach.c,v 1.112 2001/02/10 15:44:59 jinmei Exp $ */ +/* $OpenBSD: in6_ifattach.c,v 1.18 2001/07/18 12:50:44 itojun Exp $ */ +/* $KAME: in6_ifattach.c,v 1.124 2001/07/18 08:32:51 jinmei Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -630,6 +630,9 @@ in6_ifattach(ifp, altifp) icmp6_ifstatmax = if_indexlim; } + /* create a multicast kludge storage (if we have not had one) */ + in6_createmkludge(ifp); + /* * quirks based on interface type */ diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h index bf038cf403d..adad5456777 100644 --- a/sys/netinet6/in6_var.h +++ b/sys/netinet6/in6_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: in6_var.h,v 1.12 2001/02/16 14:45:12 itojun Exp $ */ +/* $OpenBSD: in6_var.h,v 1.13 2001/07/18 12:50:44 itojun Exp $ */ /* $KAME: in6_var.h,v 1.55 2001/02/16 12:49:45 itojun Exp $ */ /* @@ -567,6 +567,7 @@ void in6_purgeaddr __P((struct ifaddr *, struct ifnet *)); void in6_savemkludge __P((struct in6_ifaddr *)); void in6_setmaxmtu __P((void)); void in6_restoremkludge __P((struct in6_ifaddr *, struct ifnet *)); +void in6_createmkludge __P((struct ifnet *)); void in6_purgemkludge __P((struct ifnet *)); struct in6_ifaddr *in6ifa_ifpforlinklocal __P((struct ifnet *, int)); struct in6_ifaddr *in6ifa_ifpwithaddr __P((struct ifnet *, |