Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 29 Nov 2018 01:15:53 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r341172 - in head/sys: conf dev/cxgbe dev/cxgbe/tom modules/cxgbe/if_cxgbe
Message-ID:  <201811290115.wAT1FrY9055533@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Thu Nov 29 01:15:53 2018
New Revision: 341172
URL: https://svnweb.freebsd.org/changeset/base/341172

Log:
  Move CLIP table handling out of TOM and into the base driver.
  
  - Store the clip table in 'struct adapter' instead of in the TOM softc.
  - Init the clip table during attach and teardown during detach.
  - While here, add a dev.<nexus>.<unit>.misc.clip sysctl to dump the
    CLIP table.
  
  This does mean that we update the clip table even if TOE is not enabled,
  but non-TOE things need the CLIP table anyway.
  
  Reviewed by:	np, Krishnamraju Eraparaju @ Chelsio
  Sponsored by:	Chelsio Communications
  Differential Revision:	https://reviews.freebsd.org/D18010

Added:
  head/sys/dev/cxgbe/t4_clip.c   (contents, props changed)
  head/sys/dev/cxgbe/t4_clip.h   (contents, props changed)
Modified:
  head/sys/conf/files
  head/sys/dev/cxgbe/adapter.h
  head/sys/dev/cxgbe/t4_main.c
  head/sys/dev/cxgbe/tom/t4_connect.c
  head/sys/dev/cxgbe/tom/t4_listen.c
  head/sys/dev/cxgbe/tom/t4_tom.c
  head/sys/dev/cxgbe/tom/t4_tom.h
  head/sys/modules/cxgbe/if_cxgbe/Makefile

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Thu Nov 29 01:05:21 2018	(r341171)
+++ head/sys/conf/files	Thu Nov 29 01:15:53 2018	(r341172)
@@ -1382,6 +1382,8 @@ dev/cxgb/sys/uipc_mvec.c	optional cxgb pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgb"
 dev/cxgb/cxgb_t3fw.c		optional cxgb cxgb_t3fw \
 	compile-with "${NORMAL_C} -I$S/dev/cxgb"
+dev/cxgbe/t4_clip.c		optional cxgbe pci \
+	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/t4_filter.c		optional cxgbe pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/t4_if.m		optional cxgbe pci

Modified: head/sys/dev/cxgbe/adapter.h
==============================================================================
--- head/sys/dev/cxgbe/adapter.h	Thu Nov 29 01:05:21 2018	(r341171)
+++ head/sys/dev/cxgbe/adapter.h	Thu Nov 29 01:15:53 2018	(r341172)
@@ -771,6 +771,8 @@ struct devnames {
 	const char *vf_ifnet_name;
 };
 
+struct clip_entry;
+
 struct adapter {
 	SLIST_ENTRY(adapter) link;
 	device_t dev;
@@ -816,6 +818,10 @@ struct adapter {
 	struct taskqueue *tq[MAX_NCHAN];	/* General purpose taskqueues */
 	struct port_info *port[MAX_NPORTS];
 	uint8_t chan_map[MAX_NCHAN];		/* channel -> port */
+
+	struct mtx clip_table_lock;
+	TAILQ_HEAD(, clip_entry) clip_table;
+	int clip_gen;
 
 	void *tom_softc;	/* (struct tom_data *) */
 	struct tom_tunables tt;

Added: head/sys/dev/cxgbe/t4_clip.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/cxgbe/t4_clip.c	Thu Nov 29 01:15:53 2018	(r341172)
@@ -0,0 +1,382 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2012 Chelsio Communications, Inc.
+ * All rights reserved.
+ * Written by: Navdeep Parhar <np@FreeBSD.org>
+ *
+ * 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$");
+
+#include <sys/types.h>
+#include <sys/ck.h>
+#include <sys/eventhandler.h>
+#include <sys/malloc.h>
+#include <sys/rmlock.h>
+#include <sys/sbuf.h>
+#include <sys/socket.h>
+#include <sys/taskqueue.h>
+#include <net/if.h>
+#include <net/if_var.h>
+#include <netinet/in.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/scope6_var.h>
+
+#include "common/common.h"
+#include "t4_clip.h"
+
+static int add_lip(struct adapter *, struct in6_addr *);
+static int delete_lip(struct adapter *, struct in6_addr *);
+static struct clip_entry *search_lip(struct adapter *, struct in6_addr *);
+static void update_clip(struct adapter *, void *);
+static void t4_clip_task(void *, int);
+static void update_clip_table(struct adapter *);
+
+static int in6_ifaddr_gen;
+static eventhandler_tag ifaddr_evhandler;
+static struct timeout_task clip_task;
+
+static int
+add_lip(struct adapter *sc, struct in6_addr *lip)
+{
+        struct fw_clip_cmd c;
+
+	ASSERT_SYNCHRONIZED_OP(sc);
+	mtx_assert(&sc->clip_table_lock, MA_OWNED);
+
+        memset(&c, 0, sizeof(c));
+	c.op_to_write = htonl(V_FW_CMD_OP(FW_CLIP_CMD) | F_FW_CMD_REQUEST |
+	    F_FW_CMD_WRITE);
+        c.alloc_to_len16 = htonl(F_FW_CLIP_CMD_ALLOC | FW_LEN16(c));
+        c.ip_hi = *(uint64_t *)&lip->s6_addr[0];
+        c.ip_lo = *(uint64_t *)&lip->s6_addr[8];
+
+	return (-t4_wr_mbox_ns(sc, sc->mbox, &c, sizeof(c), &c));
+}
+
+static int
+delete_lip(struct adapter *sc, struct in6_addr *lip)
+{
+	struct fw_clip_cmd c;
+
+	ASSERT_SYNCHRONIZED_OP(sc);
+	mtx_assert(&sc->clip_table_lock, MA_OWNED);
+
+	memset(&c, 0, sizeof(c));
+	c.op_to_write = htonl(V_FW_CMD_OP(FW_CLIP_CMD) | F_FW_CMD_REQUEST |
+	    F_FW_CMD_READ);
+        c.alloc_to_len16 = htonl(F_FW_CLIP_CMD_FREE | FW_LEN16(c));
+        c.ip_hi = *(uint64_t *)&lip->s6_addr[0];
+        c.ip_lo = *(uint64_t *)&lip->s6_addr[8];
+
+	return (-t4_wr_mbox_ns(sc, sc->mbox, &c, sizeof(c), &c));
+}
+
+static struct clip_entry *
+search_lip(struct adapter *sc, struct in6_addr *lip)
+{
+	struct clip_entry *ce;
+
+	mtx_assert(&sc->clip_table_lock, MA_OWNED);
+
+	TAILQ_FOREACH(ce, &sc->clip_table, link) {
+		if (IN6_ARE_ADDR_EQUAL(&ce->lip, lip))
+			return (ce);
+	}
+
+	return (NULL);
+}
+
+struct clip_entry *
+t4_hold_lip(struct adapter *sc, struct in6_addr *lip, struct clip_entry *ce)
+{
+
+	mtx_lock(&sc->clip_table_lock);
+	if (ce == NULL)
+		ce = search_lip(sc, lip);
+	if (ce != NULL)
+		ce->refcount++;
+	mtx_unlock(&sc->clip_table_lock);
+
+	return (ce);
+}
+
+void
+t4_release_lip(struct adapter *sc, struct clip_entry *ce)
+{
+
+	mtx_lock(&sc->clip_table_lock);
+	KASSERT(search_lip(sc, &ce->lip) == ce,
+	    ("%s: CLIP entry %p p not in CLIP table.", __func__, ce));
+	KASSERT(ce->refcount > 0,
+	    ("%s: CLIP entry %p has refcount 0", __func__, ce));
+	--ce->refcount;
+	mtx_unlock(&sc->clip_table_lock);
+}
+
+void
+t4_init_clip_table(struct adapter *sc)
+{
+
+	mtx_init(&sc->clip_table_lock, "CLIP table lock", NULL, MTX_DEF);
+	TAILQ_INIT(&sc->clip_table);
+	sc->clip_gen = -1;
+
+	/*
+	 * Don't bother forcing an update of the clip table when the
+	 * adapter is initialized.  Before an interface can be used it
+	 * must be assigned an address which will trigger the event
+	 * handler to update the table.
+	 */
+}
+
+static void
+update_clip(struct adapter *sc, void *arg __unused)
+{
+
+	if (begin_synchronized_op(sc, NULL, HOLD_LOCK, "t4clip"))
+		return;
+
+	if (mtx_initialized(&sc->clip_table_lock))
+		update_clip_table(sc);
+
+	end_synchronized_op(sc, LOCK_HELD);
+}
+
+static void
+t4_clip_task(void *arg, int count)
+{
+
+	t4_iterate(update_clip, NULL);
+}
+
+static void
+update_clip_table(struct adapter *sc)
+{
+	struct rm_priotracker in6_ifa_tracker;
+	struct in6_ifaddr *ia;
+	struct in6_addr *lip, tlip;
+	TAILQ_HEAD(, clip_entry) stale;
+	struct clip_entry *ce, *ce_temp;
+	struct vi_info *vi;
+	int rc, gen, i, j;
+	uintptr_t last_vnet;
+
+	ASSERT_SYNCHRONIZED_OP(sc);
+
+	IN6_IFADDR_RLOCK(&in6_ifa_tracker);
+	mtx_lock(&sc->clip_table_lock);
+
+	gen = atomic_load_acq_int(&in6_ifaddr_gen);
+	if (gen == sc->clip_gen)
+		goto done;
+
+	TAILQ_INIT(&stale);
+	TAILQ_CONCAT(&stale, &sc->clip_table, link);
+
+	/*
+	 * last_vnet optimizes the common cases where all if_vnet = NULL (no
+	 * VIMAGE) or all if_vnet = vnet0.
+	 */
+	last_vnet = (uintptr_t)(-1);
+	for_each_port(sc, i)
+	for_each_vi(sc->port[i], j, vi) {
+		if (last_vnet == (uintptr_t)vi->ifp->if_vnet)
+			continue;
+
+		/* XXX: races with if_vmove */
+		CURVNET_SET(vi->ifp->if_vnet);
+		CK_STAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
+			lip = &ia->ia_addr.sin6_addr;
+
+			KASSERT(!IN6_IS_ADDR_MULTICAST(lip),
+			    ("%s: mcast address in in6_ifaddr list", __func__));
+
+			if (IN6_IS_ADDR_LOOPBACK(lip))
+				continue;
+			if (IN6_IS_SCOPE_EMBED(lip)) {
+				/* Remove the embedded scope */
+				tlip = *lip;
+				lip = &tlip;
+				in6_clearscope(lip);
+			}
+			/*
+			 * XXX: how to weed out the link local address for the
+			 * loopback interface?  It's fe80::1 usually (always?).
+			 */
+
+			/*
+			 * If it's in the main list then we already know it's
+			 * not stale.
+			 */
+			TAILQ_FOREACH(ce, &sc->clip_table, link) {
+				if (IN6_ARE_ADDR_EQUAL(&ce->lip, lip))
+					goto next;
+			}
+
+			/*
+			 * If it's in the stale list we should move it to the
+			 * main list.
+			 */
+			TAILQ_FOREACH(ce, &stale, link) {
+				if (IN6_ARE_ADDR_EQUAL(&ce->lip, lip)) {
+					TAILQ_REMOVE(&stale, ce, link);
+					TAILQ_INSERT_TAIL(&sc->clip_table, ce,
+					    link);
+					goto next;
+				}
+			}
+
+			/* A new IP6 address; add it to the CLIP table */
+			ce = malloc(sizeof(*ce), M_CXGBE, M_NOWAIT);
+			memcpy(&ce->lip, lip, sizeof(ce->lip));
+			ce->refcount = 0;
+			rc = add_lip(sc, lip);
+			if (rc == 0)
+				TAILQ_INSERT_TAIL(&sc->clip_table, ce, link);
+			else {
+				char ip[INET6_ADDRSTRLEN];
+
+				inet_ntop(AF_INET6, &ce->lip, &ip[0],
+				    sizeof(ip));
+				log(LOG_ERR, "%s: could not add %s (%d)\n",
+				    __func__, ip, rc);
+				free(ce, M_CXGBE);
+			}
+next:
+			continue;
+		}
+		CURVNET_RESTORE();
+		last_vnet = (uintptr_t)vi->ifp->if_vnet;
+	}
+
+	/*
+	 * Remove stale addresses (those no longer in V_in6_ifaddrhead) that are
+	 * no longer referenced by the driver.
+	 */
+	TAILQ_FOREACH_SAFE(ce, &stale, link, ce_temp) {
+		if (ce->refcount == 0) {
+			rc = delete_lip(sc, &ce->lip);
+			if (rc == 0) {
+				TAILQ_REMOVE(&stale, ce, link);
+				free(ce, M_CXGBE);
+			} else {
+				char ip[INET6_ADDRSTRLEN];
+
+				inet_ntop(AF_INET6, &ce->lip, &ip[0],
+				    sizeof(ip));
+				log(LOG_ERR, "%s: could not delete %s (%d)\n",
+				    __func__, ip, rc);
+			}
+		}
+	}
+	/* The ones that are still referenced need to stay in the CLIP table */
+	TAILQ_CONCAT(&sc->clip_table, &stale, link);
+
+	sc->clip_gen = gen;
+done:
+	mtx_unlock(&sc->clip_table_lock);
+	IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
+}
+
+void
+t4_destroy_clip_table(struct adapter *sc)
+{
+	struct clip_entry *ce, *ce_temp;
+
+	if (mtx_initialized(&sc->clip_table_lock)) {
+		mtx_lock(&sc->clip_table_lock);
+		TAILQ_FOREACH_SAFE(ce, &sc->clip_table, link, ce_temp) {
+			KASSERT(ce->refcount == 0,
+			    ("%s: CLIP entry %p still in use (%d)", __func__,
+			    ce, ce->refcount));
+			TAILQ_REMOVE(&sc->clip_table, ce, link);
+			delete_lip(sc, &ce->lip);
+			free(ce, M_CXGBE);
+		}
+		mtx_unlock(&sc->clip_table_lock);
+		mtx_destroy(&sc->clip_table_lock);
+	}
+}
+
+static void
+t4_tom_ifaddr_event(void *arg __unused, struct ifnet *ifp)
+{
+
+	atomic_add_rel_int(&in6_ifaddr_gen, 1);
+	taskqueue_enqueue_timeout(taskqueue_thread, &clip_task, -hz / 4);
+}
+
+int
+sysctl_clip(SYSCTL_HANDLER_ARGS)
+{
+	struct adapter *sc = arg1;
+	struct clip_entry *ce;
+	struct sbuf *sb;
+	int rc, header = 0;
+	char ip[INET6_ADDRSTRLEN];
+
+	rc = sysctl_wire_old_buffer(req, 0);
+	if (rc != 0)
+		return (rc);
+
+	sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req);
+	if (sb == NULL)
+		return (ENOMEM);
+
+	mtx_lock(&sc->clip_table_lock);
+	TAILQ_FOREACH(ce, &sc->clip_table, link) {
+		if (header == 0) {
+			sbuf_printf(sb, "%-40s %-5s", "IP address", "Users");
+			header = 1;
+		}
+		inet_ntop(AF_INET6, &ce->lip, &ip[0], sizeof(ip));
+
+		sbuf_printf(sb, "\n%-40s %5u", ip, ce->refcount);
+	}
+	mtx_unlock(&sc->clip_table_lock);
+
+	rc = sbuf_finish(sb);
+	sbuf_delete(sb);
+
+	return (rc);
+}
+
+void
+t4_clip_modload(void)
+{
+
+	TIMEOUT_TASK_INIT(taskqueue_thread, &clip_task, 0, t4_clip_task, NULL);
+	ifaddr_evhandler = EVENTHANDLER_REGISTER(ifaddr_event,
+	    t4_tom_ifaddr_event, NULL, EVENTHANDLER_PRI_ANY);
+}
+
+void
+t4_clip_modunload(void)
+{
+
+	EVENTHANDLER_DEREGISTER(ifaddr_event, ifaddr_evhandler);
+	taskqueue_cancel_timeout(taskqueue_thread, &clip_task, NULL);
+}

Added: head/sys/dev/cxgbe/t4_clip.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/cxgbe/t4_clip.h	Thu Nov 29 01:15:53 2018	(r341172)
@@ -0,0 +1,51 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2012 Chelsio Communications, Inc.
+ * All rights reserved.
+ * Written by: Navdeep Parhar <np@FreeBSD.org>
+ *
+ * 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 __T4_CLIP_H
+#define	__T4_CLIP_H
+
+struct clip_entry {
+	TAILQ_ENTRY(clip_entry) link;
+	struct in6_addr lip;	/* local IPv6 address */
+	u_int refcount;
+};
+
+void t4_clip_modload(void);
+void t4_clip_modunload(void);
+void t4_init_clip_table(struct adapter *);
+void t4_destroy_clip_table(struct adapter *);
+struct clip_entry *t4_hold_lip(struct adapter *, struct in6_addr *,
+    struct clip_entry *);
+void t4_release_lip(struct adapter *, struct clip_entry *);
+
+int sysctl_clip(SYSCTL_HANDLER_ARGS);
+
+#endif	/* __T4_CLIP_H */

Modified: head/sys/dev/cxgbe/t4_main.c
==============================================================================
--- head/sys/dev/cxgbe/t4_main.c	Thu Nov 29 01:05:21 2018	(r341171)
+++ head/sys/dev/cxgbe/t4_main.c	Thu Nov 29 01:15:53 2018	(r341172)
@@ -82,6 +82,7 @@ __FBSDID("$FreeBSD$");
 #include "common/t4_regs.h"
 #include "common/t4_regs_values.h"
 #include "cudbg/cudbg.h"
+#include "t4_clip.h"
 #include "t4_ioctl.h"
 #include "t4_l2t.h"
 #include "t4_mp_ring.h"
@@ -1221,6 +1222,7 @@ t4_attach(device_t dev)
 #ifdef RATELIMIT
 	t4_init_etid_table(sc);
 #endif
+	t4_init_clip_table(sc);
 	if (sc->vres.key.size != 0)
 		sc->key_map = vmem_create("T4TLS key map", sc->vres.key.start,
 		    sc->vres.key.size, 32, 0, M_FIRSTFIT | M_WAITOK);
@@ -1511,6 +1513,7 @@ t4_detach_common(device_t dev)
 #endif
 	if (sc->key_map)
 		vmem_destroy(sc->key_map);
+	t4_destroy_clip_table(sc);
 
 #if defined(TCP_OFFLOAD) || defined(RATELIMIT)
 	free(sc->sge.ofld_txq, M_CXGBE);
@@ -5964,6 +5967,10 @@ t4_sysctls(struct adapter *sc)
 	    CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
 	    sysctl_smt, "A", "hardware source MAC table");
 
+	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "clip",
+	    CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
+	    sysctl_clip, "A", "active CLIP table entries");
+
 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "lb_stats",
 	    CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
 	    sysctl_lb_stats, "A", "loopback statistics");
@@ -10520,6 +10527,7 @@ mod_event(module_t mod, int cmd, void *arg)
 			sx_init(&t4_uld_list_lock, "T4/T5 ULDs");
 			SLIST_INIT(&t4_uld_list);
 #endif
+			t4_clip_modload();
 			t4_tracer_modload();
 			tweak_tunables();
 		}
@@ -10559,6 +10567,7 @@ mod_event(module_t mod, int cmd, void *arg)
 
 			if (t4_sge_extfree_refs() == 0) {
 				t4_tracer_modunload();
+				t4_clip_modunload();
 #ifdef TCP_OFFLOAD
 				sx_destroy(&t4_uld_list_lock);
 #endif

Modified: head/sys/dev/cxgbe/tom/t4_connect.c
==============================================================================
--- head/sys/dev/cxgbe/tom/t4_connect.c	Thu Nov 29 01:05:21 2018	(r341171)
+++ head/sys/dev/cxgbe/tom/t4_connect.c	Thu Nov 29 01:15:53 2018	(r341172)
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
 #include "common/t4_msg.h"
 #include "common/t4_regs.h"
 #include "common/t4_regs_values.h"
+#include "t4_clip.h"
 #include "tom/t4_tom_l2t.h"
 #include "tom/t4_tom.h"
 
@@ -316,7 +317,6 @@ t4_connect(struct toedev *tod, struct socket *so, stru
     struct sockaddr *nam)
 {
 	struct adapter *sc = tod->tod_softc;
-	struct tom_data *td = tod_td(tod);
 	struct toepcb *toep = NULL;
 	struct wrqe *wr = NULL;
 	struct ifnet *rt_ifp = rt->rt_ifp;
@@ -409,7 +409,7 @@ t4_connect(struct toedev *tod, struct socket *so, stru
 		if ((inp->inp_vflag & INP_IPV6) == 0)
 			DONT_OFFLOAD_ACTIVE_OPEN(ENOTSUP);
 
-		toep->ce = hold_lip(td, &inp->in6p_laddr, NULL);
+		toep->ce = t4_hold_lip(sc, &inp->in6p_laddr, NULL);
 		if (toep->ce == NULL)
 			DONT_OFFLOAD_ACTIVE_OPEN(ENOENT);
 
@@ -496,7 +496,7 @@ failed:
 		if (toep->l2te)
 			t4_l2t_release(toep->l2te);
 		if (toep->ce)
-			release_lip(td, toep->ce);
+			t4_release_lip(sc, toep->ce);
 		free_toepcb(toep);
 	}
 

Modified: head/sys/dev/cxgbe/tom/t4_listen.c
==============================================================================
--- head/sys/dev/cxgbe/tom/t4_listen.c	Thu Nov 29 01:05:21 2018	(r341171)
+++ head/sys/dev/cxgbe/tom/t4_listen.c	Thu Nov 29 01:15:53 2018	(r341172)
@@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$");
 #include "common/common.h"
 #include "common/t4_msg.h"
 #include "common/t4_regs.h"
+#include "t4_clip.h"
 #include "tom/t4_tom_l2t.h"
 #include "tom/t4_tom.h"
 
@@ -212,9 +213,7 @@ alloc_lctx(struct adapter *sc, struct inpcb *inp, stru
 
 	if (inp->inp_vflag & INP_IPV6 &&
 	    !IN6_ARE_ADDR_EQUAL(&in6addr_any, &inp->in6p_laddr)) {
-		struct tom_data *td = sc->tom_softc;
-
-		lctx->ce = hold_lip(td, &inp->in6p_laddr, NULL);
+		lctx->ce = t4_hold_lip(sc, &inp->in6p_laddr, NULL);
 		if (lctx->ce == NULL) {
 			free(lctx, M_CXGBE);
 			return (NULL);
@@ -238,7 +237,6 @@ static int
 free_lctx(struct adapter *sc, struct listen_ctx *lctx)
 {
 	struct inpcb *inp = lctx->inp;
-	struct tom_data *td = sc->tom_softc;
 
 	INP_WLOCK_ASSERT(inp);
 	KASSERT(lctx->refcount == 0,
@@ -251,7 +249,7 @@ free_lctx(struct adapter *sc, struct listen_ctx *lctx)
 	    __func__, lctx->stid, lctx, lctx->inp);
 
 	if (lctx->ce)
-		release_lip(td, lctx->ce);
+		t4_release_lip(sc, lctx->ce);
 	free_stid(sc, lctx);
 	free(lctx, M_CXGBE);
 
@@ -1675,7 +1673,7 @@ reset:
 	MPASS(so->so_vnet == lctx->vnet);
 	toep->vnet = lctx->vnet;
 	if (inc.inc_flags & INC_ISIPV6)
-		toep->ce = hold_lip(sc->tom_softc, &inc.inc6_laddr, lctx->ce);
+		toep->ce = t4_hold_lip(sc, &inc.inc6_laddr, lctx->ce);
 
 	/*
 	 * This is for the unlikely case where the syncache entry that we added

Modified: head/sys/dev/cxgbe/tom/t4_tom.c
==============================================================================
--- head/sys/dev/cxgbe/tom/t4_tom.c	Thu Nov 29 01:05:21 2018	(r341171)
+++ head/sys/dev/cxgbe/tom/t4_tom.c	Thu Nov 29 01:15:53 2018	(r341172)
@@ -71,6 +71,7 @@ __FBSDID("$FreeBSD$");
 #include "common/t4_regs.h"
 #include "common/t4_regs_values.h"
 #include "common/t4_tcb.h"
+#include "t4_clip.h"
 #include "tom/t4_tom_l2t.h"
 #include "tom/t4_tom.h"
 #include "tom/t4_tls.h"
@@ -99,21 +100,9 @@ static struct uld_info tom_uld_info = {
 static void release_offload_resources(struct toepcb *);
 static int alloc_tid_tabs(struct tid_info *);
 static void free_tid_tabs(struct tid_info *);
-static int add_lip(struct adapter *, struct in6_addr *);
-static int delete_lip(struct adapter *, struct in6_addr *);
-static struct clip_entry *search_lip(struct tom_data *, struct in6_addr *);
-static void init_clip_table(struct adapter *, struct tom_data *);
-static void update_clip(struct adapter *, void *);
-static void t4_clip_task(void *, int);
-static void update_clip_table(struct adapter *, struct tom_data *);
-static void destroy_clip_table(struct adapter *, struct tom_data *);
 static void free_tom_data(struct adapter *, struct tom_data *);
 static void reclaim_wr_resources(void *, int);
 
-static int in6_ifaddr_gen;
-static eventhandler_tag ifaddr_evhandler;
-static struct timeout_task clip_task;
-
 struct toepcb *
 alloc_toepcb(struct vi_info *vi, int txqid, int rxqid, int flags)
 {
@@ -315,7 +304,7 @@ release_offload_resources(struct toepcb *toep)
 	}
 
 	if (toep->ce)
-		release_lip(td, toep->ce);
+		t4_release_lip(sc, toep->ce);
 
 	if (toep->tc_idx != -1)
 		t4_release_cl_rl(sc, toep->vi->pi->port_id, toep->tc_idx);
@@ -822,267 +811,7 @@ failed:
 	return (rc);
 }
 
-static int
-add_lip(struct adapter *sc, struct in6_addr *lip)
-{
-        struct fw_clip_cmd c;
-
-	ASSERT_SYNCHRONIZED_OP(sc);
-	/* mtx_assert(&td->clip_table_lock, MA_OWNED); */
-
-        memset(&c, 0, sizeof(c));
-	c.op_to_write = htonl(V_FW_CMD_OP(FW_CLIP_CMD) | F_FW_CMD_REQUEST |
-	    F_FW_CMD_WRITE);
-        c.alloc_to_len16 = htonl(F_FW_CLIP_CMD_ALLOC | FW_LEN16(c));
-        c.ip_hi = *(uint64_t *)&lip->s6_addr[0];
-        c.ip_lo = *(uint64_t *)&lip->s6_addr[8];
-
-	return (-t4_wr_mbox_ns(sc, sc->mbox, &c, sizeof(c), &c));
-}
-
-static int
-delete_lip(struct adapter *sc, struct in6_addr *lip)
-{
-	struct fw_clip_cmd c;
-
-	ASSERT_SYNCHRONIZED_OP(sc);
-	/* mtx_assert(&td->clip_table_lock, MA_OWNED); */
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_write = htonl(V_FW_CMD_OP(FW_CLIP_CMD) | F_FW_CMD_REQUEST |
-	    F_FW_CMD_READ);
-        c.alloc_to_len16 = htonl(F_FW_CLIP_CMD_FREE | FW_LEN16(c));
-        c.ip_hi = *(uint64_t *)&lip->s6_addr[0];
-        c.ip_lo = *(uint64_t *)&lip->s6_addr[8];
-
-	return (-t4_wr_mbox_ns(sc, sc->mbox, &c, sizeof(c), &c));
-}
-
-static struct clip_entry *
-search_lip(struct tom_data *td, struct in6_addr *lip)
-{
-	struct clip_entry *ce;
-
-	mtx_assert(&td->clip_table_lock, MA_OWNED);
-
-	TAILQ_FOREACH(ce, &td->clip_table, link) {
-		if (IN6_ARE_ADDR_EQUAL(&ce->lip, lip))
-			return (ce);
-	}
-
-	return (NULL);
-}
-
-struct clip_entry *
-hold_lip(struct tom_data *td, struct in6_addr *lip, struct clip_entry *ce)
-{
-
-	mtx_lock(&td->clip_table_lock);
-	if (ce == NULL)
-		ce = search_lip(td, lip);
-	if (ce != NULL)
-		ce->refcount++;
-	mtx_unlock(&td->clip_table_lock);
-
-	return (ce);
-}
-
-void
-release_lip(struct tom_data *td, struct clip_entry *ce)
-{
-
-	mtx_lock(&td->clip_table_lock);
-	KASSERT(search_lip(td, &ce->lip) == ce,
-	    ("%s: CLIP entry %p p not in CLIP table.", __func__, ce));
-	KASSERT(ce->refcount > 0,
-	    ("%s: CLIP entry %p has refcount 0", __func__, ce));
-	--ce->refcount;
-	mtx_unlock(&td->clip_table_lock);
-}
-
 static void
-init_clip_table(struct adapter *sc, struct tom_data *td)
-{
-
-	ASSERT_SYNCHRONIZED_OP(sc);
-
-	mtx_init(&td->clip_table_lock, "CLIP table lock", NULL, MTX_DEF);
-	TAILQ_INIT(&td->clip_table);
-	td->clip_gen = -1;
-
-	update_clip_table(sc, td);
-}
-
-static void
-update_clip(struct adapter *sc, void *arg __unused)
-{
-
-	if (begin_synchronized_op(sc, NULL, HOLD_LOCK, "t4tomuc"))
-		return;
-
-	if (uld_active(sc, ULD_TOM))
-		update_clip_table(sc, sc->tom_softc);
-
-	end_synchronized_op(sc, LOCK_HELD);
-}
-
-static void
-t4_clip_task(void *arg, int count)
-{
-
-	t4_iterate(update_clip, NULL);
-}
-
-static void
-update_clip_table(struct adapter *sc, struct tom_data *td)
-{
-	struct rm_priotracker in6_ifa_tracker;
-	struct in6_ifaddr *ia;
-	struct in6_addr *lip, tlip;
-	struct clip_head stale;
-	struct clip_entry *ce, *ce_temp;
-	struct vi_info *vi;
-	int rc, gen, i, j;
-	uintptr_t last_vnet;
-
-	ASSERT_SYNCHRONIZED_OP(sc);
-
-	IN6_IFADDR_RLOCK(&in6_ifa_tracker);
-	mtx_lock(&td->clip_table_lock);
-
-	gen = atomic_load_acq_int(&in6_ifaddr_gen);
-	if (gen == td->clip_gen)
-		goto done;
-
-	TAILQ_INIT(&stale);
-	TAILQ_CONCAT(&stale, &td->clip_table, link);
-
-	/*
-	 * last_vnet optimizes the common cases where all if_vnet = NULL (no
-	 * VIMAGE) or all if_vnet = vnet0.
-	 */
-	last_vnet = (uintptr_t)(-1);
-	for_each_port(sc, i)
-	for_each_vi(sc->port[i], j, vi) {
-		if (last_vnet == (uintptr_t)vi->ifp->if_vnet)
-			continue;
-
-		/* XXX: races with if_vmove */
-		CURVNET_SET(vi->ifp->if_vnet);
-		CK_STAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
-			lip = &ia->ia_addr.sin6_addr;
-
-			KASSERT(!IN6_IS_ADDR_MULTICAST(lip),
-			    ("%s: mcast address in in6_ifaddr list", __func__));
-
-			if (IN6_IS_ADDR_LOOPBACK(lip))
-				continue;
-			if (IN6_IS_SCOPE_EMBED(lip)) {
-				/* Remove the embedded scope */
-				tlip = *lip;
-				lip = &tlip;
-				in6_clearscope(lip);
-			}
-			/*
-			 * XXX: how to weed out the link local address for the
-			 * loopback interface?  It's fe80::1 usually (always?).
-			 */
-
-			/*
-			 * If it's in the main list then we already know it's
-			 * not stale.
-			 */
-			TAILQ_FOREACH(ce, &td->clip_table, link) {
-				if (IN6_ARE_ADDR_EQUAL(&ce->lip, lip))
-					goto next;
-			}
-
-			/*
-			 * If it's in the stale list we should move it to the
-			 * main list.
-			 */
-			TAILQ_FOREACH(ce, &stale, link) {
-				if (IN6_ARE_ADDR_EQUAL(&ce->lip, lip)) {
-					TAILQ_REMOVE(&stale, ce, link);
-					TAILQ_INSERT_TAIL(&td->clip_table, ce,
-					    link);
-					goto next;
-				}
-			}
-
-			/* A new IP6 address; add it to the CLIP table */
-			ce = malloc(sizeof(*ce), M_CXGBE, M_NOWAIT);
-			memcpy(&ce->lip, lip, sizeof(ce->lip));
-			ce->refcount = 0;
-			rc = add_lip(sc, lip);
-			if (rc == 0)
-				TAILQ_INSERT_TAIL(&td->clip_table, ce, link);
-			else {
-				char ip[INET6_ADDRSTRLEN];
-
-				inet_ntop(AF_INET6, &ce->lip, &ip[0],
-				    sizeof(ip));
-				log(LOG_ERR, "%s: could not add %s (%d)\n",
-				    __func__, ip, rc);
-				free(ce, M_CXGBE);
-			}
-next:
-			continue;
-		}
-		CURVNET_RESTORE();
-		last_vnet = (uintptr_t)vi->ifp->if_vnet;
-	}
-
-	/*
-	 * Remove stale addresses (those no longer in V_in6_ifaddrhead) that are
-	 * no longer referenced by the driver.
-	 */
-	TAILQ_FOREACH_SAFE(ce, &stale, link, ce_temp) {
-		if (ce->refcount == 0) {
-			rc = delete_lip(sc, &ce->lip);
-			if (rc == 0) {
-				TAILQ_REMOVE(&stale, ce, link);
-				free(ce, M_CXGBE);
-			} else {
-				char ip[INET6_ADDRSTRLEN];
-
-				inet_ntop(AF_INET6, &ce->lip, &ip[0],
-				    sizeof(ip));
-				log(LOG_ERR, "%s: could not delete %s (%d)\n",
-				    __func__, ip, rc);
-			}
-		}
-	}
-	/* The ones that are still referenced need to stay in the CLIP table */
-	TAILQ_CONCAT(&td->clip_table, &stale, link);
-
-	td->clip_gen = gen;
-done:
-	mtx_unlock(&td->clip_table_lock);
-	IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
-}
-
-static void
-destroy_clip_table(struct adapter *sc, struct tom_data *td)
-{
-	struct clip_entry *ce, *ce_temp;
-
-	if (mtx_initialized(&td->clip_table_lock)) {
-		mtx_lock(&td->clip_table_lock);
-		TAILQ_FOREACH_SAFE(ce, &td->clip_table, link, ce_temp) {
-			KASSERT(ce->refcount == 0,
-			    ("%s: CLIP entry %p still in use (%d)", __func__,
-			    ce, ce->refcount));
-			TAILQ_REMOVE(&td->clip_table, ce, link);
-			delete_lip(sc, &ce->lip);
-			free(ce, M_CXGBE);
-		}
-		mtx_unlock(&td->clip_table_lock);
-		mtx_destroy(&td->clip_table_lock);
-	}
-}
-
-static void
 free_tom_data(struct adapter *sc, struct tom_data *td)
 {
 
@@ -1094,7 +823,6 @@ free_tom_data(struct adapter *sc, struct tom_data *td)
 	    ("%s: lctx hash table is not empty.", __func__));
 
 	t4_free_ppod_region(&td->pr);
-	destroy_clip_table(sc, td);
 
 	if (td->listen_mask != 0)
 		hashdestroy(td->listen_hash, M_CXGBE, td->listen_mask);
@@ -1369,9 +1097,6 @@ t4_tom_activate(struct adapter *sc)
 	t4_set_reg_field(sc, A_ULP_RX_TDDP_TAGMASK,
 	    V_TDDPTAGMASK(M_TDDPTAGMASK), td->pr.pr_tag_mask);
 
-	/* CLIP table for IPv6 offload */
-	init_clip_table(sc, td);
-
 	/* toedev ops */
 	tod = &td->tod;
 	init_toedev(tod);
@@ -1449,14 +1174,6 @@ t4_tom_deactivate(struct adapter *sc)
 	return (rc);
 }
 
-static void
-t4_tom_ifaddr_event(void *arg __unused, struct ifnet *ifp)
-{
-
-	atomic_add_rel_int(&in6_ifaddr_gen, 1);
-	taskqueue_enqueue_timeout(taskqueue_thread, &clip_task, -hz / 4);
-}
-
 static int
 t4_aio_queue_tom(struct socket *so, struct kaiocb *job)
 {
@@ -1524,10 +1241,6 @@ t4_tom_mod_load(void)
 	toe6_protosw.pr_ctloutput = t4_ctloutput_tom;
 	toe6_protosw.pr_usrreqs = &toe6_usrreqs;
 
-	TIMEOUT_TASK_INIT(taskqueue_thread, &clip_task, 0, t4_clip_task, NULL);
-	ifaddr_evhandler = EVENTHANDLER_REGISTER(ifaddr_event,
-	    t4_tom_ifaddr_event, NULL, EVENTHANDLER_PRI_ANY);
-
 	return (t4_register_uld(&tom_uld_info));
 }
 
@@ -1551,11 +1264,6 @@ t4_tom_mod_unload(void)
 
 	if (t4_unregister_uld(&tom_uld_info) == EBUSY)
 		return (EBUSY);
-
-	if (ifaddr_evhandler) {
-		EVENTHANDLER_DEREGISTER(ifaddr_event, ifaddr_evhandler);
-		taskqueue_cancel_timeout(taskqueue_thread, &clip_task, NULL);
-	}
 
 	t4_tls_mod_unload();
 	t4_ddp_mod_unload();

Modified: head/sys/dev/cxgbe/tom/t4_tom.h
==============================================================================
--- head/sys/dev/cxgbe/tom/t4_tom.h	Thu Nov 29 01:05:21 2018	(r341171)
+++ head/sys/dev/cxgbe/tom/t4_tom.h	Thu Nov 29 01:15:53 2018	(r341172)
@@ -259,13 +259,6 @@ struct listen_ctx {
 	TAILQ_HEAD(, synq_entry) synq;
 };
 
-struct clip_entry {
-	TAILQ_ENTRY(clip_entry) link;
-	struct in6_addr lip;	/* local IPv6 address */
-	u_int refcount;
-};
-
-TAILQ_HEAD(clip_head, clip_entry);
 struct tom_data {
 	struct toedev tod;
 
@@ -280,10 +273,6 @@ struct tom_data {
 
 	struct ppod_region pr;
 
-	struct mtx clip_table_lock;
-	struct clip_head clip_table;
-	int clip_gen;
-
 	/* WRs that will not be sent to the chip because L2 resolution failed */
 	struct mtx unsent_wr_lock;
 	STAILQ_HEAD(, wrqe) unsent_wr_list;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201811290115.wAT1FrY9055533>