示例#1
0
文件: dls.c 项目: andreiw/polaris
void
dls_close(dls_channel_t dc)
{
	dls_impl_t		*dip = (dls_impl_t *)dc;
	dls_vlan_t		*dvp;
	dls_link_t		*dlp;
	dls_multicst_addr_t	*p;
	dls_multicst_addr_t	*nextp;

	dls_active_clear(dc);

	rw_enter(&(dip->di_lock), RW_WRITER);

	/*
	 * Remove the notify function.
	 */
	mac_notify_remove(dip->di_mh, dip->di_mnh);
	dip->di_mnh = NULL;

	/*
	 * If the dls_impl_t is bound then unbind it.
	 */
	dvp = dip->di_dvp;
	dlp = dvp->dv_dlp;

	if (dip->di_bound) {
		rw_exit(&(dip->di_lock));
		dls_link_remove(dlp, dip);
		rw_enter(&(dip->di_lock), RW_WRITER);
		dip->di_bound = B_FALSE;
	}

	dip->di_rx = NULL;
	dip->di_rx_arg = NULL;

	/*
	 * Walk the list of multicast addresses, disabling each at the MAC.
	 */
	for (p = dip->di_dmap; p != NULL; p = nextp) {
		(void) mac_multicst_remove(dip->di_mh, p->dma_addr);
		nextp = p->dma_nextp;
		kmem_free(p, sizeof (dls_multicst_addr_t));
	}
	dip->di_dmap = NULL;

	rw_exit(&(dip->di_lock));

	/*
	 * If the MAC has been set in promiscuous mode then disable it.
	 */
	(void) dls_promisc(dc, 0);

	/*
	 * Free the dls_impl_t back to the cache.
	 */
	dip->di_dvp = NULL;
	dip->di_txinfo = NULL;

	if (dip->di_soft_ring_list != NULL) {
		soft_ring_set_destroy(dip->di_soft_ring_list,
		    dip->di_soft_ring_size);
		dip->di_soft_ring_list = NULL;
	}
	dip->di_soft_ring_size = 0;

	kmem_cache_free(i_dls_impl_cachep, dip);

	/*
	 * Decrement the reference count to allow the cache to be destroyed
	 * if there are no more dls_impl_t.
	 */
	atomic_add_32(&i_dls_impl_count, -1);

	/*
	 * Release our reference to the dls_vlan_t allowing that to be
	 * destroyed if there are no more dls_impl_t. An unreferenced tagged
	 * vlan gets destroyed automatically.
	 */
	dls_vlan_rele(dvp);
}
示例#2
0
/*
 * DL_PROMISCOFF_REQ
 */
static void
proto_promiscoff_req(dld_str_t *dsp, mblk_t *mp)
{
	dl_promiscoff_req_t *dlp = (dl_promiscoff_req_t *)mp->b_rptr;
	int		err = 0;
	t_uscalar_t	dl_err;
	uint32_t	promisc_saved;
	queue_t		*q = dsp->ds_wq;
	mac_perim_handle_t	mph;

	if (MBLKL(mp) < sizeof (dl_promiscoff_req_t)) {
		dl_err = DL_BADPRIM;
		goto failed;
	}

	if (dsp->ds_dlstate == DL_UNATTACHED ||
	    DL_ACK_PENDING(dsp->ds_dlstate)) {
		dl_err = DL_OUTSTATE;
		goto failed;
	}

	promisc_saved = dsp->ds_promisc;
	switch (dlp->dl_level) {
	case DL_PROMISC_SAP:
		if (!(dsp->ds_promisc & DLS_PROMISC_SAP)) {
			dl_err = DL_NOTENAB;
			goto failed;
		}
		dsp->ds_promisc &= ~DLS_PROMISC_SAP;
		break;

	case DL_PROMISC_MULTI:
		if (!(dsp->ds_promisc & DLS_PROMISC_MULTI)) {
			dl_err = DL_NOTENAB;
			goto failed;
		}
		dsp->ds_promisc &= ~DLS_PROMISC_MULTI;
		break;

	case DL_PROMISC_PHYS:
		if (!(dsp->ds_promisc & DLS_PROMISC_PHYS)) {
			dl_err = DL_NOTENAB;
			goto failed;
		}
		dsp->ds_promisc &= ~DLS_PROMISC_PHYS;
		break;

	default:
		dl_err = DL_NOTSUPPORTED;
		goto failed;
	}

	mac_perim_enter_by_mh(dsp->ds_mh, &mph);
	/*
	 * Adjust channel promiscuity.
	 */
	err = dls_promisc(dsp, promisc_saved);

	if (err != 0) {
		mac_perim_exit(mph);
		dl_err = DL_SYSERR;
		goto failed;
	}

	if (dsp->ds_promisc == 0)
		dls_active_clear(dsp, B_FALSE);

	mac_perim_exit(mph);

	dlokack(q, mp, DL_PROMISCOFF_REQ);
	return;
failed:
	dlerrorack(q, mp, DL_PROMISCOFF_REQ, dl_err, (t_uscalar_t)err);
}