Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F139445426
D18010.id50498.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
28 KB
Referenced Files
None
Subscribers
None
D18010.id50498.diff
View Options
Index: sys/conf/files
===================================================================
--- sys/conf/files
+++ sys/conf/files
@@ -1382,6 +1382,8 @@
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
Index: sys/dev/cxgbe/adapter.h
===================================================================
--- sys/dev/cxgbe/adapter.h
+++ sys/dev/cxgbe/adapter.h
@@ -769,6 +769,8 @@
const char *vf_ifnet_name;
};
+struct clip_entry;
+
struct adapter {
SLIST_ENTRY(adapter) link;
device_t dev;
@@ -815,6 +817,10 @@
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;
struct t4_offload_policy *policy;
Index: sys/dev/cxgbe/t4_clip.h
===================================================================
--- /dev/null
+++ sys/dev/cxgbe/t4_clip.h
@@ -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 */
Index: sys/dev/cxgbe/t4_clip.c
===================================================================
--- /dev/null
+++ sys/dev/cxgbe/t4_clip.c
@@ -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);
+}
Index: sys/dev/cxgbe/t4_main.c
===================================================================
--- sys/dev/cxgbe/t4_main.c
+++ sys/dev/cxgbe/t4_main.c
@@ -82,6 +82,7 @@
#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"
@@ -1153,6 +1154,7 @@
#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);
@@ -1443,6 +1445,7 @@
#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);
@@ -5900,6 +5903,10 @@
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");
@@ -10456,6 +10463,7 @@
sx_init(&t4_uld_list_lock, "T4/T5 ULDs");
SLIST_INIT(&t4_uld_list);
#endif
+ t4_clip_modload();
t4_tracer_modload();
tweak_tunables();
}
@@ -10495,6 +10503,7 @@
if (t4_sge_extfree_refs() == 0) {
t4_tracer_modunload();
+ t4_clip_modunload();
#ifdef TCP_OFFLOAD
sx_destroy(&t4_uld_list_lock);
#endif
Index: sys/dev/cxgbe/tom/t4_connect.c
===================================================================
--- sys/dev/cxgbe/tom/t4_connect.c
+++ sys/dev/cxgbe/tom/t4_connect.c
@@ -62,6 +62,7 @@
#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 @@
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 @@
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 @@
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);
}
Index: sys/dev/cxgbe/tom/t4_listen.c
===================================================================
--- sys/dev/cxgbe/tom/t4_listen.c
+++ sys/dev/cxgbe/tom/t4_listen.c
@@ -68,6 +68,7 @@
#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 @@
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 @@
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 @@
__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 @@
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
Index: sys/dev/cxgbe/tom/t4_tom.h
===================================================================
--- sys/dev/cxgbe/tom/t4_tom.h
+++ sys/dev/cxgbe/tom/t4_tom.h
@@ -259,13 +259,6 @@
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 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;
@@ -342,9 +331,6 @@
struct offload_settings *);
void set_ulp_mode(struct toepcb *, int);
int negative_advice(int);
-struct clip_entry *hold_lip(struct tom_data *, struct in6_addr *,
- struct clip_entry *);
-void release_lip(struct tom_data *, struct clip_entry *);
/* t4_connect.c */
void t4_init_connect_cpl_handlers(void);
Index: sys/dev/cxgbe/tom/t4_tom.c
===================================================================
--- sys/dev/cxgbe/tom/t4_tom.c
+++ sys/dev/cxgbe/tom/t4_tom.c
@@ -71,6 +71,7 @@
#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 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 @@
}
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,266 +811,6 @@
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 @@
("%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_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 @@
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 @@
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));
}
@@ -1552,11 +1265,6 @@
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();
Index: sys/modules/cxgbe/if_cxgbe/Makefile
===================================================================
--- sys/modules/cxgbe/if_cxgbe/Makefile
+++ sys/modules/cxgbe/if_cxgbe/Makefile
@@ -15,6 +15,7 @@
SRCS+= opt_ratelimit.h
SRCS+= opt_rss.h
SRCS+= pci_if.h pci_iov_if.h
+SRCS+= t4_clip.c
SRCS+= t4_filter.c
SRCS+= t4_hw.c
SRCS+= t4_if.c t4_if.h
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Dec 13, 4:24 AM (16 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26921183
Default Alt Text
D18010.id50498.diff (28 KB)
Attached To
Mode
D18010: Move CLIP table handling out of TOM and into the base driver.
Attached
Detach File
Event Timeline
Log In to Comment