From: Sepherosa Ziehau Date: Tue, 1 Aug 2017 08:22:00 +0000 (+0800) Subject: inet6: Drain IPv6 fragments in netisr0 X-Git-Tag: v5.1.0~303 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/e8fdde2758a3389a04bc44215cbfd0d8dcddaf80 inet6: Drain IPv6 fragments in netisr0 --- diff --git a/sys/netinet6/frag6.c b/sys/netinet6/frag6.c index 24ea4dbbc9..bb1af7f83f 100644 --- a/sys/netinet6/frag6.c +++ b/sys/netinet6/frag6.c @@ -72,6 +72,7 @@ static void frag6_remque (struct ip6q *); static void frag6_freef (struct ip6q *); static void frag6_slowtimo_dispatch (netmsg_t); static void frag6_slowtimo (void *); +static void frag6_drain_dispatch (netmsg_t); /* XXX we eventually need splreass6, or some real semaphore */ int frag6_doing_reass; @@ -84,6 +85,7 @@ MALLOC_DEFINE(M_FTABLE, "fragment", "fragment reassembly header"); static struct callout frag6_slowtimo_ch; static struct netmsg_base frag6_slowtimo_nmsg; +static struct netmsg_base frag6_drain_nmsg; /* * Initialise reassembly queue and fragment identifier. @@ -104,6 +106,9 @@ frag6_init(void) ip6_id = krandom() ^ tv.tv_usec; ip6q.ip6q_next = ip6q.ip6q_prev = &ip6q; + netmsg_init(&frag6_drain_nmsg, NULL, &netisr_adone_rport, + MSGF_PRIORITY, frag6_drain_dispatch); + callout_init_mp(&frag6_slowtimo_ch); netmsg_init(&frag6_slowtimo_nmsg, NULL, &netisr_adone_rport, MSGF_PRIORITY, frag6_slowtimo_dispatch); @@ -680,9 +685,12 @@ frag6_slowtimo(void *dummy __unused) /* * Drain off all datagram fragments. */ -void -frag6_drain(void) +static void +frag6_drain_oncpu(void) { + + ASSERT_NETISR_NCPUS(curthread, 0); + if (frag6_doing_reass) return; while (ip6q.ip6q_next != &ip6q) { @@ -691,3 +699,42 @@ frag6_drain(void) frag6_freef(ip6q.ip6q_next); } } + +static void +frag6_drain_dispatch(netmsg_t nmsg) +{ + + ASSERT_NETISR_NCPUS(curthread, 0); + + crit_enter(); + netisr_replymsg(&nmsg->base, 0); + crit_exit(); + + frag6_drain_oncpu(); +} + +static void +frag6_drain_ipi(void *dummy __unused) +{ + struct netmsg_base *nmsg = &frag6_drain_nmsg; + + KKASSERT(mycpuid == 0); + + crit_enter(); + if (nmsg->lmsg.ms_flags & MSGF_DONE) + netisr_sendmsg_oncpu(nmsg); + crit_exit(); +} + +void +frag6_drain(void) +{ + + if (IS_NETISR(curthread, 0)) { + frag6_drain_oncpu(); + return; + } + + /* Target cpu0. */ + lwkt_send_ipiq_bycpu(0, frag6_drain_ipi, NULL); +}