Exemplo n.º 1
0
/*
 * The TOE wants an L2 table entry that it can use to reach the next hop over
 * the specified port.  Produce such an entry - create one if needed.
 *
 * Note that the ifnet could be a pseudo-device like if_vlan, if_lagg, etc. on
 * top of the real cxgbe interface.
 */
struct l2t_entry *
t4_l2t_get(struct port_info *pi, struct ifnet *ifp, struct sockaddr *sa)
{
	struct l2t_entry *e;
	struct adapter *sc = pi->adapter;
	struct l2t_data *d = sc->l2t;
	u_int hash, smt_idx = pi->port_id;

	KASSERT(sa->sa_family == AF_INET || sa->sa_family == AF_INET6,
	    ("%s: sa %p has unexpected sa_family %d", __func__, sa,
	    sa->sa_family));

#ifndef VLAN_TAG
	if (ifp->if_type == IFT_L2VLAN)
		return (NULL);
#endif

	hash = l2_hash(d, sa, ifp->if_index);
	rw_wlock(&d->lock);
	for (e = d->l2tab[hash].first; e; e = e->next) {
		if (l2_cmp(sa, e) == 0 && e->ifp == ifp &&
		    e->smt_idx == smt_idx) {
			l2t_hold(d, e);
			goto done;
		}
	}

	/* Need to allocate a new entry */
	e = t4_alloc_l2e(d);
	if (e) {
		mtx_lock(&e->lock);          /* avoid race with t4_l2t_free */
		e->next = d->l2tab[hash].first;
		d->l2tab[hash].first = e;

		e->state = L2T_STATE_RESOLVING;
		l2_store(sa, e);
		e->ifp = ifp;
		e->smt_idx = smt_idx;
		e->hash = hash;
		e->lport = pi->lport;
		e->wrq = &sc->sge.ctrlq[pi->port_id];
		e->iqid = sc->sge.ofld_rxq[pi->vi[0].first_ofld_rxq].iq.abs_id;
		atomic_store_rel_int(&e->refcnt, 1);
#ifdef VLAN_TAG
		if (ifp->if_type == IFT_L2VLAN)
			VLAN_TAG(ifp, &e->vlan);
		else
			e->vlan = VLAN_NONE;
#endif
		mtx_unlock(&e->lock);
	}
done:
	rw_wunlock(&d->lock);
	return e;
}
Exemplo n.º 2
0
/*
 * Called when the host's ARP layer makes a change to some entry that is loaded
 * into the HW L2 table.
 */
void
t4_l2_update(struct toedev *tod, struct ifnet *ifp, struct sockaddr *sa,
    uint8_t *lladdr, uint16_t vtag)
{
	struct adapter *sc = tod->tod_softc;
	struct l2t_entry *e;
	struct l2t_data *d = sc->l2t;
	u_int hash;

	KASSERT(d != NULL, ("%s: no L2 table", __func__));

	hash = l2_hash(d, sa, ifp->if_index);
	rw_rlock(&d->lock);
	for (e = d->l2tab[hash].first; e; e = e->next) {
		if (l2_cmp(sa, e) == 0 && e->ifp == ifp) {
			mtx_lock(&e->lock);
			if (atomic_load_acq_int(&e->refcnt))
				goto found;
			e->state = L2T_STATE_STALE;
			mtx_unlock(&e->lock);
			break;
		}
	}
	rw_runlock(&d->lock);

	/*
	 * This is of no interest to us.  We've never had an offloaded
	 * connection to this destination, and we aren't attempting one right
	 * now.
	 */
	return;

found:
	rw_runlock(&d->lock);

	KASSERT(e->state != L2T_STATE_UNUSED,
	    ("%s: unused entry in the hash.", __func__));

	update_entry(sc, e, lladdr, vtag);
	mtx_unlock(&e->lock);
}