Exemple #1
0
/*
 * Allocate an L2T entry for use by a switching rule.  Such need to be
 * explicitly freed and while busy they are not on any hash chain, so normal
 * address resolution updates do not see them.
 */
struct l2t_entry *
t4_l2t_alloc_switching(struct adapter *sc, uint16_t vlan, uint8_t port,
    uint8_t *eth_addr)
{
	struct l2t_data *d = sc->l2t;
	struct l2t_entry *e;
	int rc;

	rw_wlock(&d->lock);
	e = find_or_alloc_l2e(d, vlan, port, eth_addr);
	if (e) {
		if (atomic_load_acq_int(&e->refcnt) == 0) {
			mtx_lock(&e->lock);    /* avoid race with t4_l2t_free */
			e->wrq = &sc->sge.ctrlq[0];
			e->iqid = sc->sge.fwq.abs_id;
			e->state = L2T_STATE_SWITCHING;
			e->vlan = vlan;
			e->lport = port;
			memcpy(e->dmac, eth_addr, ETHER_ADDR_LEN);
			atomic_store_rel_int(&e->refcnt, 1);
			atomic_subtract_int(&d->nfree, 1);
			rc = t4_write_l2e(e, 0);
			mtx_unlock(&e->lock);
			if (rc != 0)
				e = NULL;
		} else {
			MPASS(e->vlan == vlan);
			MPASS(e->lport == port);
			atomic_add_int(&e->refcnt, 1);
		}
	}
	rw_wunlock(&d->lock);
	return (e);
}
Exemple #2
0
/*
 * Sets/updates the contents of a switching L2T entry that has been allocated
 * with an earlier call to @t4_l2t_alloc_switching.
 */
int
t4_l2t_set_switching(struct adapter *sc, struct l2t_entry *e, uint16_t vlan,
    uint8_t port, uint8_t *eth_addr)
{
	int rc;

	e->vlan = vlan;
	e->lport = port;
	memcpy(e->dmac, eth_addr, ETHER_ADDR_LEN);
	mtx_lock(&e->lock);
	rc = t4_write_l2e(sc, e, 0);
	mtx_unlock(&e->lock);
	return (rc);
}
Exemple #3
0
static void
update_entry(struct adapter *sc, struct l2t_entry *e, uint8_t *lladdr,
    uint16_t vtag)
{

	mtx_assert(&e->lock, MA_OWNED);

	/*
	 * The entry may be in active use (e->refcount > 0) or not.  We update
	 * it even when it's not as this simplifies the case where we decide to
	 * reuse the entry later.
	 */

	if (lladdr == NULL &&
	    (e->state == L2T_STATE_RESOLVING || e->state == L2T_STATE_FAILED)) {
		/*
		 * Never got a valid L2 address for this one.  Just mark it as
		 * failed instead of removing it from the hash (for which we'd
		 * need to wlock the table).
		 */
		e->state = L2T_STATE_FAILED;
		resolution_failed(e);
		return;

	} else if (lladdr == NULL) {

		/* Valid or already-stale entry was deleted (or expired) */

		KASSERT(e->state == L2T_STATE_VALID ||
		    e->state == L2T_STATE_STALE,
		    ("%s: lladdr NULL, state %d", __func__, e->state));

		e->state = L2T_STATE_STALE;

	} else {

		if (e->state == L2T_STATE_RESOLVING ||
		    e->state == L2T_STATE_FAILED ||
		    memcmp(e->dmac, lladdr, ETHER_ADDR_LEN)) {

			/* unresolved -> resolved; or dmac changed */

			memcpy(e->dmac, lladdr, ETHER_ADDR_LEN);
			e->vlan = vtag;
			t4_write_l2e(sc, e, 1);
		}
		e->state = L2T_STATE_VALID;
	}
}