37#include <sys/kernel.h>
38#include <sys/module.h>
40#include <sys/fnv_hash.h>
43#include <sys/rwlock.h>
44#include <sys/socket.h>
46#include <sys/taskqueue.h>
48#include <net/if_types.h>
49#include <net/ethernet.h>
50#include <net/if_vlan_var.h>
52#include <netinet/in.h>
53#include <netinet/toecore.h>
60#define VLAN_NONE 0xfff
66 if (atomic_fetchadd_int(&e->
refcnt, 1) == 0)
67 atomic_subtract_int(&d->
nfree, 1);
71l2_hash(
struct l2t_data *d,
const struct sockaddr *sa,
int ifindex)
73 u_int hash, half = d->
l2t_size / 2, start = 0;
77 KASSERT(sa->sa_family == AF_INET || sa->sa_family == AF_INET6,
78 (
"%s: sa %p has unexpected sa_family %d", __func__, sa,
81 if (sa->sa_family == AF_INET) {
82 const struct sockaddr_in *sin = (
const void *)sa;
85 len =
sizeof(sin->sin_addr);
87 const struct sockaddr_in6 *sin6 = (
const void *)sa;
89 key = &sin6->sin6_addr;
90 len =
sizeof(sin6->sin6_addr);
94 hash = fnv_32_buf(key, len, FNV1_32_INIT);
95 hash = fnv_32_buf(&ifindex,
sizeof(ifindex), hash);
98 return (hash + start);
102l2_cmp(
const struct sockaddr *sa,
struct l2t_entry *e)
105 KASSERT(sa->sa_family == AF_INET || sa->sa_family == AF_INET6,
106 (
"%s: sa %p has unexpected sa_family %d", __func__, sa,
109 if (sa->sa_family == AF_INET) {
110 const struct sockaddr_in *sin = (
const void *)sa;
112 return (e->
addr[0] != sin->sin_addr.s_addr);
114 const struct sockaddr_in6 *sin6 = (
const void *)sa;
116 return (memcmp(&e->
addr[0], &sin6->sin6_addr,
sizeof(e->
addr)));
121l2_store(
const struct sockaddr *sa,
struct l2t_entry *e)
124 KASSERT(sa->sa_family == AF_INET || sa->sa_family == AF_INET6,
125 (
"%s: sa %p has unexpected sa_family %d", __func__, sa,
128 if (sa->sa_family == AF_INET) {
129 const struct sockaddr_in *sin = (
const void *)sa;
131 e->
addr[0] = sin->sin_addr.s_addr;
134 const struct sockaddr_in6 *sin6 = (
const void *)sa;
136 memcpy(&e->
addr[0], &sin6->sin6_addr,
sizeof(e->
addr));
148 mtx_assert(&e->
lock, MA_OWNED);
150 STAILQ_INSERT_TAIL(&e->wr_list, wr, link);
158 mtx_assert(&e->
lock, MA_OWNED);
160 while ((wr = STAILQ_FIRST(&e->wr_list)) != NULL) {
161 STAILQ_REMOVE_HEAD(&e->wr_list, link);
171 mtx_assert(&e->
lock, MA_OWNED);
174 STAILQ_CONCAT(&td->unsent_wr_list, &e->wr_list);
185 mtx_assert(&e->
lock, MA_OWNED);
193 if (lladdr == NULL &&
201 resolution_failed(sc, e);
204 }
else if (lladdr == NULL) {
210 (
"%s: lladdr NULL, state %d", __func__, e->
state));
218 memcmp(e->
dmac, lladdr, ETHER_ADDR_LEN)) {
222 memcpy(e->
dmac, lladdr, ETHER_ADDR_LEN);
234 struct toedev *tod = &td->
tod;
235 struct sockaddr_in sin = {0};
236 struct sockaddr_in6 sin6 = {0};
238 uint8_t dmac[ETHER_HDR_LEN];
243 sin.sin_family = AF_INET;
244 sin.sin_len =
sizeof(
struct sockaddr_in);
245 sin.sin_addr.s_addr = e->
addr[0];
248 sin6.sin6_family = AF_INET6;
249 sin6.sin6_len =
sizeof(
struct sockaddr_in6);
250 memcpy(&sin6.sin6_addr, &e->
addr[0],
sizeof(e->
addr));
254 vtag = EVL_MAKETAG(VLAN_NONE, 0, 0);
255 rc = toe_l2_resolve(tod, e->
ifp, sa, dmac, &vtag);
256 if (rc == EWOULDBLOCK)
260 update_entry(sc, e, rc == 0 ? dmac : NULL, vtag);
261 mtx_unlock(&e->
lock);
274 resolve_entry(sc, e);
290 mtx_unlock(&e->
lock);
294 mtx_unlock(&e->
lock);
296 if (resolve_entry(sc, e) == EWOULDBLOCK)
303 resolution_failed(sc, e);
304 mtx_unlock(&e->
lock);
308 return (EHOSTUNREACH);
320 unsigned int tid =
GET_TID(rpl);
325 "Unexpected L2T_WRITE_RPL (%u) for entry at hw_idx %u\n",
338 mtx_unlock(&e->
lock);
357 u_int hash, smt_idx = pi->
port_id;
358 uint16_t vid, pcp, vtag;
360 KASSERT(sa->sa_family == AF_INET || sa->sa_family == AF_INET6,
361 (
"%s: sa %p has unexpected sa_family %d", __func__, sa,
366 if (
ifp->if_type == IFT_L2VLAN) {
369 }
else if (
ifp->if_pcp != IFNET_PCP_NONE) {
373 vtag = EVL_MAKETAG(vid, pcp, 0);
375 hash = l2_hash(d, sa,
ifp->if_index);
378 if (l2_cmp(sa, e) == 0 && e->
ifp ==
ifp && e->
vlan == vtag &&
400 atomic_store_rel_int(&e->
refcnt, 1);
402 mtx_unlock(&e->
lock);
405 rw_wunlock(&d->
lock);
414t4_l2_update(
struct toedev *tod,
struct ifnet *
ifp,
struct sockaddr *sa,
415 uint8_t *lladdr, uint16_t vtag)
417 struct adapter *sc = tod->tod_softc;
422 KASSERT(d != NULL, (
"%s: no L2 table", __func__));
424 hash = l2_hash(d, sa,
ifp->if_index);
427 if (l2_cmp(sa, e) == 0 && e->
ifp ==
ifp) {
429 if (atomic_load_acq_int(&e->
refcnt))
432 mtx_unlock(&e->
lock);
436 rw_runlock(&d->
lock);
446 rw_runlock(&d->
lock);
449 (
"%s: unused entry in the hash.", __func__));
451 update_entry(sc, e, lladdr, vtag);
452 mtx_unlock(&e->
lock);
static void t4_wrq_tx(struct adapter *sc, struct wrqe *wr)
uint8_t dmac[ETHER_ADDR_LEN]
struct sge_ofld_rxq * ofld_rxq
struct mtx unsent_wr_lock
struct task reclaim_wr_resources
struct l2t_entry * t4_alloc_l2e(struct l2t_data *d)
int t4_write_l2e(struct l2t_entry *e, int sync)
int t4_l2t_send_slow(struct adapter *, struct wrqe *, struct l2t_entry *)
struct l2t_entry * t4_l2t_get(struct port_info *, struct ifnet *, struct sockaddr *)
int do_l2t_write_rpl2(struct sge_iq *, const struct rss_header *, struct mbuf *)
void t4_l2_update(struct toedev *, struct ifnet *, struct sockaddr *, uint8_t *, uint16_t)