Page MenuHomeFreeBSD

D903.id1897.diff
No OneTemporary

D903.id1897.diff

Index: sys/conf/files
===================================================================
--- sys/conf/files
+++ sys/conf/files
@@ -3213,6 +3213,7 @@
net/bpf_zerocopy.c optional bpf
net/bridgestp.c optional bridge | if_bridge
net/flowtable.c optional flowtable inet | flowtable inet6
+net/delayed_dispatch.c standard
net/ieee8023ad_lacp.c optional lagg
net/if.c standard
net/if_arcsubr.c optional arcnet
Index: sys/net/delayed_dispatch.h
===================================================================
--- /dev/null
+++ sys/net/delayed_dispatch.h
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2014 Alexander V. Chernikov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _NET_DELAYED_DISPATCH_H_
+#define _NET_DELAYED_DISPATCH_H_
+
+struct dly_item {
+ int type;
+ int subtype;
+ struct ifnet *ifp;
+ uintptr_t data;
+};
+
+typedef int dly_dispatch_t(struct mbuf *, int, uintptr_t, struct ifnet *);
+typedef int dly_pdispatch_t(struct mbuf *, struct dly_item *);
+typedef int dly_free_t(struct mbuf *, int, uintptr_t, struct ifnet *);
+
+struct dly_dispatcher {
+ const char *name;
+ dly_dispatch_t *dly_dispatch;
+ dly_pdispatch_t *dly_pdispatch;
+ dly_free_t *dly_free;
+};
+
+
+int dly_register(struct dly_dispatcher *);
+void dly_unregister(int);
+int dly_queue(int, struct mbuf *, int, uintptr_t, struct ifnet *);
+int dly_pqueue(int, struct mbuf *, struct dly_item *, size_t);
+
+#endif
+
Index: sys/net/delayed_dispatch.c
===================================================================
--- /dev/null
+++ sys/net/delayed_dispatch.c
@@ -0,0 +1,364 @@
+/*-
+ * Copyright (c) 2014 Alexander V. Chernikov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/sys/net/delayed_dispatch.c$");
+
+/*
+ * delayed dispatch is so-called "slowpath" packet path which permits you
+ * to enqueue mbufs requiring complex dispath (and/or possibly complex locking)
+ * into separate netisr queue instead of trying to deal with it in "fast" code path.
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/mutex.h>
+#include <sys/rmlock.h>
+#include <sys/syslog.h>
+#include <sys/types.h>
+#include <sys/taskqueue.h>
+#include <sys/eventhandler.h>
+
+#include <net/delayed_dispatch.h>
+#include <net/netisr.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+
+struct dly_info {
+ struct dly_dispatcher *index;
+ int alloc;
+ int count;
+ struct rmlock lock;
+};
+#define DLY_ALLOC_ITEMS 16
+
+static struct dly_info dly;
+
+#define DLY_LOCK_INIT() rm_init(&dly.lock, "dly_lock")
+#define DLY_RLOCK() rm_rlock(&dly.lock, &tracker)
+#define DLY_RUNLOCK() rm_runlock(&dly.lock, &tracker)
+#define DLY_WLOCK() rm_wlock(&dly.lock)
+#define DLY_WUNLOCK() rm_wunlock(&dly.lock)
+#define DLY_READER struct rm_priotracker tracker
+
+static eventhandler_tag ifdetach_tag;
+
+/*
+ * Adds mbuf to slowpath queue. Additional information
+ * is stored in PACKET_TAG_DISPATCH_INFO mbuf tag.
+ * Returns 0 if successfull, error code overwise.
+ */
+int
+dly_queue(int dtype, struct mbuf *m, int dsubtype, uintptr_t data,
+ struct ifnet *ifp)
+{
+ struct dly_item *item;
+ struct m_tag *dtag;
+ DLY_READER;
+
+ /* Ensure we're not going to cycle packet */
+ if ((dtag = m_tag_find(m, PACKET_TAG_DISPATCH_INFO, NULL)) != NULL) {
+ printf("tag found: %p\n", dtag);
+ return (EINVAL);
+ }
+
+ DLY_RLOCK();
+ if (dtype < 0 || dtype >= dly.alloc || dly.index[dtype].name == NULL) {
+ DLY_RUNLOCK();
+ printf("invalid dtype: 0..%d..%d\n", dtype, dly.alloc);
+ return (EINVAL);
+ }
+ DLY_RUNLOCK();
+
+ VNET_ASSERT(m->m_pkthdr.rcvif != NULL,
+ ("%s:%d rcvif == NULL: m=%p", __func__, __LINE__, m));
+
+ /*
+ * Do not allocate tag for basic IPv4/IPv6 output
+ */
+ if (dtype != 0) {
+ dtag = m_tag_get(PACKET_TAG_DISPATCH_INFO,
+ sizeof(struct dly_item), M_NOWAIT);
+
+ if (dtag == NULL)
+ return (ENOBUFS);
+
+ item = (struct dly_item *)(dtag + 1);
+
+ item->type = dtype;
+ item->subtype = dsubtype;
+ item->data = data;
+ item->ifp = ifp;
+
+ m_tag_prepend(m, dtag);
+ }
+
+ netisr_queue(NETISR_SLOWPATH, m);
+
+ return (0);
+}
+
+/*
+ * Adds mbuf to slowpath queue. User-provided buffer
+ * of size @size is stored inside PACKET_TAG_DISPATCH_INFO
+ * mbuf tag. Buffer structure needs to embed properly filled
+ * dly_item structure at the beginning of buffer. Such buffers
+ * needs to be dispatched by dly_pdispatch() handler.
+ *
+ * Returns 0 if successfull, error code overwise.
+ */
+int
+dly_pqueue(int dtype, struct mbuf *m, struct dly_item *item, size_t size)
+{
+ struct m_tag *dtag;
+ DLY_READER;
+
+ /* Ensure we're not going to cycle packet */
+ if ((dtag = m_tag_find(m, PACKET_TAG_DISPATCH_INFO, NULL)) != NULL) {
+ return (EINVAL);
+ }
+
+ DLY_RLOCK();
+ if (dtype < 0 || dtype >= dly.alloc || dly.index[dtype].name == NULL) {
+ DLY_RUNLOCK();
+ return (EINVAL);
+ }
+ DLY_RUNLOCK();
+
+ VNET_ASSERT(m->m_pkthdr.rcvif != NULL,
+ ("%s:%d rcvif == NULL: m=%p", __func__, __LINE__, m));
+
+ dtag = m_tag_get(PACKET_TAG_DISPATCH_INFO, size, M_NOWAIT);
+
+ if (dtag == NULL)
+ return (ENOBUFS);
+
+ memcpy(dtag + 1, item, size);
+ m_tag_prepend(m, dtag);
+ netisr_queue(NETISR_SLOWPATH, m);
+
+ return (0);
+}
+
+/*
+ * Base netisr handler for slowpath
+ */
+static void
+dly_dispatch_item(struct mbuf *m)
+{
+ struct m_tag *dtag;
+ struct dly_item *item;
+ int dtype;
+ struct dly_dispatcher *dld;
+ DLY_READER;
+
+ item = NULL;
+ dtype = 0;
+
+ if ((dtag = m_tag_find(m, PACKET_TAG_DISPATCH_INFO, NULL)) != NULL) {
+ item = (struct dly_item *)(dtag + 1);
+ dtype = item->type;
+ }
+
+ DLY_RLOCK();
+ if (dtype < 0 || dtype >= dly.alloc || dly.index[dtype].name == NULL) {
+ DLY_RUNLOCK();
+ return;
+ }
+
+ dld = &dly.index[dtype];
+
+ if (dld->dly_dispatch != NULL)
+ dld->dly_dispatch(m, item->subtype, item->data, item->ifp);
+ else
+ dld->dly_pdispatch(m, item);
+
+ DLY_RUNLOCK();
+
+ return;
+}
+
+
+/*
+ * Check if queue items is received or going to be transmitted
+ * via destroying interface.
+ */
+static int
+dly_scan_ifp(struct mbuf *m, void *_data)
+{
+ struct m_tag *dtag;
+ struct dly_item *item;
+ struct ifnet *difp;
+
+ difp = (struct ifnet *)_data;
+
+ if (m->m_pkthdr.rcvif == difp)
+ return (1);
+
+ if ((dtag = m_tag_find(m, PACKET_TAG_DISPATCH_INFO, NULL)) != NULL) {
+ item = (struct dly_item *)(dtag + 1);
+ if (item->ifp == difp)
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
+ * Registers new slowpath handler.
+ * Returns handler id to use in dly_queue() or
+ * dly_pqueue() functions/
+ */
+int
+dly_register(struct dly_dispatcher *dld)
+{
+ int i, alloc;
+ struct dly_dispatcher *dd, *tmp;
+
+again:
+ DLY_WLOCK();
+
+ if (dly.count < dly.alloc) {
+ i = dly.count++;
+ dly.index[i] = *dld;
+ DLY_WUNLOCK();
+ return (i);
+ }
+
+ alloc = dly.alloc + DLY_ALLOC_ITEMS;
+
+ DLY_WUNLOCK();
+
+ /* No spare room, need to increase */
+ dd = malloc(sizeof(struct dly_dispatcher) * alloc, M_TEMP,
+ M_ZERO|M_WAITOK);
+
+ DLY_WLOCK();
+ if (dly.alloc >= alloc) {
+ /* Lost the race, try again */
+ DLY_WUNLOCK();
+ free(dd, M_TEMP);
+ goto again;
+ }
+
+ memcpy(dly.index, dd, sizeof(struct dly_dispatcher) * dly.alloc);
+ tmp = dly.index;
+ dly.index = dd;
+ dly.alloc = alloc;
+ i = dly.count++;
+ dly.index[i] = *dld;
+ DLY_WUNLOCK();
+
+ free(tmp, M_TEMP);
+
+ return (i);
+}
+
+/*
+ * Checks if given netisr queue item is of type which
+ * needs to be unregistered.
+ */
+static int
+dly_scan_unregistered(struct mbuf *m, void *_data)
+{
+ struct m_tag *dtag;
+ struct dly_item *item;
+ int i;
+
+ i = *((int *)(intptr_t)_data);
+
+ if ((dtag = m_tag_find(m, PACKET_TAG_DISPATCH_INFO, NULL)) != NULL) {
+ item = (struct dly_item *)(dtag + 1);
+ if (item->type == i)
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
+ * Unregisters slow handler registered previously by dly_register().
+ * Caller needs to ensure that no new items of given type can be queued
+ * prior calling this function.
+ */
+void
+dly_unregister(int dtype)
+{
+
+ netisr_scan(NETISR_SLOWPATH, dly_scan_unregistered, &dtype);
+
+ DLY_WLOCK();
+ if (dtype < 0 || dtype >= dly.alloc || dly.index[dtype].name == NULL) {
+ DLY_WUNLOCK();
+ return;
+ }
+
+ KASSERT(dly.index[dtype].name != NULL,
+ ("%s: unresigstering non-existend protocol %d", __func__, dtype));
+
+ memset(&dly.index[dtype], 0, sizeof(struct dly_dispatcher));
+ DLY_WUNLOCK();
+}
+
+
+static void
+dly_ifdetach(void *arg __unused, struct ifnet *ifp)
+{
+
+ netisr_scan(NETISR_SLOWPATH, dly_scan_ifp, ifp);
+}
+
+static struct netisr_handler dly_nh = {
+ .nh_name = "slow",
+ .nh_handler = dly_dispatch_item,
+ .nh_proto = NETISR_SLOWPATH,
+ .nh_policy = NETISR_POLICY_SOURCE,
+};
+
+static void
+dly_init(__unused void *arg)
+{
+
+ memset(&dly, 0, sizeof(dly));
+ dly.index = malloc(sizeof(struct dly_dispatcher) * DLY_ALLOC_ITEMS,
+ M_TEMP, M_ZERO | M_WAITOK);
+ dly.alloc = DLY_ALLOC_ITEMS;
+ dly.count = 1;
+
+ DLY_LOCK_INIT();
+
+ netisr_register(&dly_nh);
+ ifdetach_tag = EVENTHANDLER_REGISTER(ifnet_departure_event,
+ dly_ifdetach, NULL, EVENTHANDLER_PRI_ANY);
+}
+
+/* Exactly after netisr */
+SYSINIT(dly_init, SI_SUB_SOFTINTR, SI_ORDER_SECOND, dly_init, NULL);
+
Index: sys/net/netisr.h
===================================================================
--- sys/net/netisr.h
+++ sys/net/netisr.h
@@ -59,6 +59,7 @@
#define NETISR_EPAIR 8 /* if_epair(4) */
#define NETISR_IP_DIRECT 9 /* direct-dispatch IPv4 */
#define NETISR_IPV6_DIRECT 10 /* direct-dispatch IPv6 */
+#define NETISR_SLOWPATH 11 /* delayed dispatch */
/*
* Protocol ordering and affinity policy constants. See the detailed
@@ -176,6 +177,7 @@
*/
struct mbuf;
typedef void netisr_handler_t(struct mbuf *m);
+typedef int netisr_scan_t(struct mbuf *m, void *);
typedef struct mbuf *netisr_m2cpuid_t(struct mbuf *m, uintptr_t source,
u_int *cpuid);
typedef struct mbuf *netisr_m2flow_t(struct mbuf *m, uintptr_t source);
@@ -210,6 +212,7 @@
void netisr_register(const struct netisr_handler *nhp);
int netisr_setqlimit(const struct netisr_handler *nhp, u_int qlimit);
void netisr_unregister(const struct netisr_handler *nhp);
+int netisr_scan(u_int proto, netisr_scan_t *, void *);
/*
* Process a packet destined for a protocol, and attempt direct dispatch.
Index: sys/net/netisr.c
===================================================================
--- sys/net/netisr.c
+++ sys/net/netisr.c
@@ -551,6 +551,85 @@
}
/*
+ * Scan workqueue and delete mbufs pointed by handler.
+ */
+static int
+netisr_scan_workqueue(struct netisr_work *npwp, netisr_scan_t *scan_f,
+ void *data)
+{
+ struct mbuf *m, *m_prev;
+ int deleted;
+
+ deleted = 0;
+ m_prev = NULL;
+ m = npwp->nw_head;
+ while (m != NULL) {
+ if (scan_f(m, data) == 0) {
+ m_prev = m;
+ m = m->m_nextpkt;
+ continue;
+ }
+
+ /* Handler requested item deletion */
+ if (m_prev == NULL)
+ npwp->nw_head = m->m_nextpkt;
+ else
+ m_prev->m_nextpkt = m->m_nextpkt;
+
+ if (m->m_nextpkt == NULL)
+ npwp->nw_tail = m_prev;
+
+ npwp->nw_len--;
+ m_freem(m);
+ deleted++;
+
+ if (m_prev == NULL)
+ m = npwp->nw_head;
+ else
+ m = m_prev->m_nextpkt;
+ }
+
+ return (deleted);
+}
+
+int
+netisr_scan(unsigned int proto, netisr_scan_t *scan_f, void *data)
+{
+#ifdef NETISR_LOCKING
+ struct rm_priotracker tracker;
+#endif
+ struct netisr_proto *np;
+ struct netisr_workstream *nwsp;
+ struct netisr_work *npwp;
+ unsigned int i;
+ int deleted;
+
+#ifdef NETISR_LOCKING
+ NETISR_RLOCK(&tracker);
+#endif
+
+ deleted = 0;
+
+ KASSERT(scan_f != NULL, ("%s: scan function is NULL", __func__));
+
+ np = &netisr_proto[proto];
+
+ CPU_FOREACH(i) {
+ nwsp = DPCPU_ID_PTR(i, nws);
+ npwp = &nwsp->nws_work[proto];
+ NWS_LOCK(nwsp);
+ deleted += netisr_scan_workqueue(npwp, scan_f, data);
+ NWS_UNLOCK(nwsp);
+ }
+
+#ifdef NETISR_LOCKING
+ NETISR_RUNLOCK(&tracker);
+#endif
+
+ return (deleted);
+}
+
+/*
* Drain all packets currently held in a particular protocol work queue.
*/
static void
Index: sys/netinet6/nd6.h
===================================================================
--- sys/netinet6/nd6.h
+++ sys/netinet6/nd6.h
@@ -421,6 +421,8 @@
const struct sockaddr *, u_char *, struct llentry **);
/* nd6_nbr.c */
+void nd6_nbr_init(void);
+void nd6_nbr_destroy(void);
void nd6_na_input(struct mbuf *, int, int);
void nd6_na_output(struct ifnet *, const struct in6_addr *,
const struct in6_addr *, u_long, int, struct sockaddr *);
Index: sys/netinet6/nd6.c
===================================================================
--- sys/netinet6/nd6.c
+++ sys/netinet6/nd6.c
@@ -153,6 +153,8 @@
callout_init(&V_nd6_slowtimo_ch, 0);
callout_reset(&V_nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz,
nd6_slowtimo, curvnet);
+
+ nd6_nbr_init();
}
#ifdef VIMAGE
@@ -160,6 +162,7 @@
nd6_destroy()
{
+ nd6_nbr_destroy();
callout_drain(&V_nd6_slowtimo_ch);
callout_drain(&V_nd6_timer_ch);
}
@@ -500,9 +503,7 @@
if (ln->la_asked < V_nd6_mmaxtries) {
ln->la_asked++;
nd6_llinfo_settimer_locked(ln, (long)ndi->retrans * hz / 1000);
- LLE_WUNLOCK(ln);
nd6_ns_output(ifp, NULL, dst, ln, 0);
- LLE_WLOCK(ln);
} else {
struct mbuf *m = ln->la_hold;
if (m) {
@@ -547,9 +548,7 @@
ln->la_asked = 1;
ln->ln_state = ND6_LLINFO_PROBE;
nd6_llinfo_settimer_locked(ln, (long)ndi->retrans * hz / 1000);
- LLE_WUNLOCK(ln);
nd6_ns_output(ifp, dst, dst, ln, 0);
- LLE_WLOCK(ln);
} else {
ln->ln_state = ND6_LLINFO_STALE; /* XXX */
nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
@@ -559,9 +558,7 @@
if (ln->la_asked < V_nd6_umaxtries) {
ln->la_asked++;
nd6_llinfo_settimer_locked(ln, (long)ndi->retrans * hz / 1000);
- LLE_WUNLOCK(ln);
nd6_ns_output(ifp, dst, dst, ln, 0);
- LLE_WLOCK(ln);
} else {
EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_EXPIRED);
(void)nd6_free(ln, 0);
Index: sys/netinet6/nd6_nbr.c
===================================================================
--- sys/netinet6/nd6_nbr.c
+++ sys/netinet6/nd6_nbr.c
@@ -74,6 +74,7 @@
#include <netinet/icmp6.h>
#include <netinet/ip_carp.h>
#include <netinet6/send.h>
+#include <net/delayed_dispatch.h>
#define SDL(s) ((struct sockaddr_dl *)s)
@@ -87,6 +88,7 @@
static void nd6_dad_na_input(struct ifaddr *);
static void nd6_na_output_fib(struct ifnet *, const struct in6_addr *,
const struct in6_addr *, u_long, int, struct sockaddr *, u_int);
+static int nd6_ns_output2(struct mbuf *, int, uintptr_t, struct ifnet *);
static VNET_DEFINE(int, dad_ignore_ns) = 0; /* ignore NS in DAD
- specwise incorrect */
@@ -95,6 +97,29 @@
#define V_dad_ignore_ns VNET(dad_ignore_ns)
#define V_dad_maxtry VNET(dad_maxtry)
+static struct dly_dispatcher dly_d = {
+ .name = "nd6_ns",
+ .dly_dispatch = nd6_ns_output2,
+};
+
+static int nd6_dlyid;
+
+void
+nd6_nbr_init()
+{
+
+ if (IS_DEFAULT_VNET(curvnet))
+ nd6_dlyid = dly_register(&dly_d);
+}
+
+void
+nd6_nbr_destroy()
+{
+
+ if (IS_DEFAULT_VNET(curvnet))
+ dly_unregister(nd6_dlyid);
+}
+
/*
* Input a Neighbor Solicitation Message.
*
@@ -368,11 +393,34 @@
m_freem(m);
}
+static int
+nd6_ns_output2(struct mbuf *m, int dad, uintptr_t _data, struct ifnet *ifp)
+{
+ struct ip6_moptions im6o;
+
+ if (m->m_flags & M_MCAST) {
+ im6o.im6o_multicast_ifp = ifp;
+ im6o.im6o_multicast_hlim = 255;
+ im6o.im6o_multicast_loop = 0;
+ }
+
+ /* Zero ingress interface not to fool PFIL consumers */
+ m->m_pkthdr.rcvif = NULL;
+
+ ip6_output(m, NULL, NULL, dad ? IPV6_UNSPECSRC : 0, &im6o, NULL, NULL);
+ icmp6_ifstat_inc(ifp, ifs6_out_msg);
+ icmp6_ifstat_inc(ifp, ifs6_out_neighborsolicit);
+ ICMP6STAT_INC(icp6s_outhist[ND_NEIGHBOR_SOLICIT]);
+
+ return (0);
+}
+
/*
* Output a Neighbor Solicitation Message. Caller specifies:
* - ICMP6 header source IP6 address
* - ND6 header target IP6 address
* - ND6 header source datalink address
+ * Note llentry has to be locked if specified
*
* Based on RFC 2461
* Based on RFC 2462 (duplicate address detection)
@@ -388,11 +436,9 @@
struct m_tag *mtag;
struct ip6_hdr *ip6;
struct nd_neighbor_solicit *nd_ns;
- struct ip6_moptions im6o;
int icmp6len;
int maxlen;
caddr_t mac;
- struct route_in6 ro;
if (IN6_IS_ADDR_MULTICAST(taddr6))
return;
@@ -415,13 +461,8 @@
if (m == NULL)
return;
- bzero(&ro, sizeof(ro));
-
if (daddr6 == NULL || IN6_IS_ADDR_MULTICAST(daddr6)) {
m->m_flags |= M_MCAST;
- im6o.im6o_multicast_ifp = ifp;
- im6o.im6o_multicast_hlim = 255;
- im6o.im6o_multicast_loop = 0;
}
icmp6len = sizeof(*nd_ns);
@@ -470,7 +511,6 @@
hsrc = NULL;
if (ln != NULL) {
- LLE_RLOCK(ln);
if (ln->la_hold != NULL) {
struct ip6_hdr *hip6; /* hold ip6 */
@@ -485,7 +525,6 @@
hsrc = &hip6->ip6_src;
}
}
- LLE_RUNLOCK(ln);
}
if (hsrc && (ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp,
hsrc)) != NULL) {
@@ -504,7 +543,7 @@
oifp = ifp;
error = in6_selectsrc(&dst_sa, NULL,
- NULL, &ro, NULL, &oifp, &src_in);
+ NULL, NULL, NULL, &oifp, &src_in);
if (error) {
char ip6buf[INET6_ADDRSTRLEN];
nd6log((LOG_DEBUG,
@@ -574,20 +613,16 @@
m_tag_prepend(m, mtag);
}
- ip6_output(m, NULL, &ro, dad ? IPV6_UNSPECSRC : 0, &im6o, NULL, NULL);
- icmp6_ifstat_inc(ifp, ifs6_out_msg);
- icmp6_ifstat_inc(ifp, ifs6_out_neighborsolicit);
- ICMP6STAT_INC(icp6s_outhist[ND_NEIGHBOR_SOLICIT]);
-
- /* We don't cache this route. */
- RO_RTFREE(&ro);
+ if (ln == NULL)
+ nd6_ns_output2(m, dad, 0, ifp);
+ else {
+ m->m_pkthdr.rcvif = ifp; /* Save VNET */
+ dly_queue(nd6_dlyid, m, dad, 0, ifp);
+ }
return;
bad:
- if (ro.ro_rt) {
- RTFREE(ro.ro_rt);
- }
m_freem(m);
return;
}
Index: sys/sys/mbuf.h
===================================================================
--- sys/sys/mbuf.h
+++ sys/sys/mbuf.h
@@ -1051,6 +1051,7 @@
#define PACKET_TAG_CARP 28 /* CARP info */
#define PACKET_TAG_IPSEC_NAT_T_PORTS 29 /* two uint16_t */
#define PACKET_TAG_ND_OUTGOING 30 /* ND outgoing */
+#define PACKET_TAG_DISPATCH_INFO 31 /* Netist slow dispatch */
/* Specific cookies and tags. */

File Metadata

Mime Type
text/plain
Expires
Tue, Apr 21, 1:32 PM (10 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31913193
Default Alt Text
D903.id1897.diff (20 KB)

Event Timeline