summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormikeb <mikeb@openbsd.org>2013-10-19 14:54:18 +0000
committermikeb <mikeb@openbsd.org>2013-10-19 14:54:18 +0000
commit70beccd4c6547f0c0028abb4eeb12294b7ff1bcf (patch)
treefef024218b48bad7d720e27515573d09857bd6db
parentremove confusing comments referencing the vax (diff)
downloadwireguard-openbsd-70beccd4c6547f0c0028abb4eeb12294b7ff1bcf.tar.xz
wireguard-openbsd-70beccd4c6547f0c0028abb4eeb12294b7ff1bcf.zip
in order to make our life a tad easier and prevent rogue accesses
to the routing table from the hardware interrupt context defer the if_link_state_change to the process context. a token (an interface index) is passed to the workq in order to make sure that if the interface would be gone by the time syswq goes around to run the task it would just fall through. ok henning, mpi, deraadt, claudio
-rw-r--r--sys/net/if.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index b65736c5c26..9c246e0df93 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.c,v 1.270 2013/10/19 14:05:14 reyk Exp $ */
+/* $OpenBSD: if.c,v 1.271 2013/10/19 14:54:18 mikeb Exp $ */
/* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
/*
@@ -81,6 +81,7 @@
#include <sys/ioctl.h>
#include <sys/domain.h>
#include <sys/sysctl.h>
+#include <sys/workq.h>
#include <net/if.h>
#include <net/if_dl.h>
@@ -154,6 +155,8 @@ struct if_clone *if_clone_lookup(const char *, int *);
void if_congestion_clear(void *);
int if_group_egress_build(void);
+void if_link_state_change_task(void *, void *);
+
int ifai_cmp(struct ifaddr_item *, struct ifaddr_item *);
void ifa_item_insert(struct sockaddr *, struct ifaddr *, struct ifnet *);
void ifa_item_remove(struct sockaddr *, struct ifaddr *, struct ifnet *);
@@ -1111,17 +1114,35 @@ if_up(struct ifnet *ifp)
}
/*
- * Process a link state change.
- * NOTE: must be called at splsoftnet or equivalent.
+ * Schedule a link state change task.
*/
void
if_link_state_change(struct ifnet *ifp)
{
- rt_ifmsg(ifp);
+ /* try to put the routing table update task on syswq */
+ workq_add_task(NULL, 0, if_link_state_change_task,
+ (void *)((unsigned long)ifp->if_index), NULL);
+}
+
+/*
+ * Process a link state change.
+ */
+void
+if_link_state_change_task(void *arg, void *unused)
+{
+ unsigned int index = (unsigned long)arg;
+ struct ifnet *ifp;
+ int s;
+
+ s = splsoftnet();
+ if ((ifp = if_get(index)) != NULL) {
+ rt_ifmsg(ifp);
#ifndef SMALL_KERNEL
- rt_if_track(ifp);
+ rt_if_track(ifp);
#endif
- dohooks(ifp->if_linkstatehooks, 0);
+ dohooks(ifp->if_linkstatehooks, 0);
+ }
+ splx(s);
}
/*