⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eth.c

📁 Minix比较全的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
}PUBLIC int eth_select(fd, operations)int fd;unsigned operations;{	printf("eth_select: not implemented\n");	return 0;}PUBLIC void eth_close(fd)int fd;{	eth_fd_t *eth_fd;	eth_port_t *eth_port;	acc_t *pack;	eth_fd= &eth_fd_table[fd];	assert ((eth_fd->ef_flags & EFF_INUSE) &&		!(eth_fd->ef_flags & EFF_BUSY));	if (eth_fd->ef_flags & EFF_OPTSET)		unhash_fd(eth_fd);	while (eth_fd->ef_rdbuf_head != NULL)	{		pack= eth_fd->ef_rdbuf_head;		eth_fd->ef_rdbuf_head= pack->acc_ext_link;		bf_afree(pack);	}	eth_fd->ef_flags= EFF_EMPTY;	eth_port= eth_fd->ef_port;	do_rec_conf(eth_port);}PUBLIC void eth_loop_ev(ev, ev_arg)event_t *ev;ev_arg_t ev_arg;{	acc_t *pack;	eth_port_t *eth_port;	eth_port= ev_arg.ev_ptr;	assert(ev == &eth_port->etp_sendev);	pack= eth_port->etp_wr_pack;	assert(!no_ethWritePort);	no_ethWritePort= 1;	eth_arrive(eth_port, pack, bf_bufsize(pack));	assert(no_ethWritePort);	no_ethWritePort= 0;	eth_port->etp_wr_pack= NULL;	eth_restart_write(eth_port);}PRIVATE int eth_checkopt (eth_fd)eth_fd_t *eth_fd;{/* bug: we don't check access modes yet */	unsigned long flags;	unsigned int en_di_flags;	eth_port_t *eth_port;	acc_t *pack;	eth_port= eth_fd->ef_port;	flags= eth_fd->ef_ethopt.nweo_flags;	en_di_flags= (flags >>16) | (flags & 0xffff);	if ((en_di_flags & NWEO_ACC_MASK) &&		(en_di_flags & NWEO_LOC_MASK) &&		(en_di_flags & NWEO_BROAD_MASK) &&		(en_di_flags & NWEO_MULTI_MASK) &&		(en_di_flags & NWEO_PROMISC_MASK) &&		(en_di_flags & NWEO_REM_MASK) &&		(en_di_flags & NWEO_TYPE_MASK) &&		(en_di_flags & NWEO_RW_MASK))	{		eth_fd->ef_flags |= EFF_OPTSET;	}	else		eth_fd->ef_flags &= ~EFF_OPTSET;	while (eth_fd->ef_rdbuf_head != NULL)	{		pack= eth_fd->ef_rdbuf_head;		eth_fd->ef_rdbuf_head= pack->acc_ext_link;		bf_afree(pack);	}	return NW_OK;}PRIVATE void hash_fd(eth_fd)eth_fd_t *eth_fd;{	eth_port_t *eth_port;	int hash;	eth_port= eth_fd->ef_port;	if (eth_fd->ef_ethopt.nweo_flags & NWEO_TYPEANY)	{		eth_fd->ef_type_next= eth_port->etp_type_any;		eth_port->etp_type_any= eth_fd;	}	else	{		hash= eth_fd->ef_ethopt.nweo_type;		hash ^= (hash >> 8);		hash &= (ETH_TYPE_HASH_NR-1);		eth_fd->ef_type_next= eth_port->etp_type[hash];		eth_port->etp_type[hash]= eth_fd;	}}PRIVATE void unhash_fd(eth_fd)eth_fd_t *eth_fd;{	eth_port_t *eth_port;	eth_fd_t *prev, *curr, **eth_fd_p;	int hash;	eth_port= eth_fd->ef_port;	if (eth_fd->ef_ethopt.nweo_flags & NWEO_TYPEANY)	{		eth_fd_p= &eth_port->etp_type_any;	}	else	{		hash= eth_fd->ef_ethopt.nweo_type;		hash ^= (hash >> 8);		hash &= (ETH_TYPE_HASH_NR-1);		eth_fd_p= &eth_port->etp_type[hash];	}	for (prev= NULL, curr= *eth_fd_p; curr;		prev= curr, curr= curr->ef_type_next)	{		if (curr == eth_fd)			break;	}	assert(curr);	if (prev)		prev->ef_type_next= curr->ef_type_next;	else		*eth_fd_p= curr->ef_type_next;}PUBLIC void eth_restart_write(eth_port)eth_port_t *eth_port;{	eth_fd_t *eth_fd;	int r;	assert(eth_port->etp_wr_pack == NULL);	while (eth_fd= eth_port->etp_sendq_head, eth_fd != NULL)	{		if (eth_port->etp_wr_pack)			return;		eth_port->etp_sendq_head= eth_fd->ef_send_next;		assert(eth_fd->ef_flags & EFF_WRITE_IP);		eth_fd->ef_flags &= ~EFF_WRITE_IP;		r= eth_write(eth_fd-eth_fd_table, eth_fd->ef_write_count);		assert(r == NW_OK);	}}PUBLIC void eth_arrive (eth_port, pack, pack_size)eth_port_t *eth_port;acc_t *pack;size_t pack_size;{	eth_hdr_t *eth_hdr;	ether_addr_t *dst_addr;	int pack_stat;	ether_type_t type;	eth_fd_t *eth_fd, *first_fd, *share_fd;	int hash, i;	u16_t vlan, temp;	time_t exp_time;	acc_t *vlan_pack, *hdr_acc, *tmp_acc;	eth_port_t *vp;	vlan_hdr_t vh;	u32_t *p;	exp_time= get_time() + EXPIRE_TIME;	pack= bf_packIffLess(pack, ETH_HDR_SIZE);	eth_hdr= (eth_hdr_t*)ptr2acc_data(pack);	dst_addr= &eth_hdr->eh_dst;	DIFBLOCK(0x20, dst_addr->ea_addr[0] != 0xFF &&		(dst_addr->ea_addr[0] & 0x1),		printf("got multicast packet\n"));	if (dst_addr->ea_addr[0] & 0x1)	{		/* multi cast or broadcast */		if (eth_addrcmp(*dst_addr, broadcast) == 0)			pack_stat= NWEO_EN_BROAD;		else			pack_stat= NWEO_EN_MULTI;	}	else	{		assert(eth_port->etp_flags & EPF_GOT_ADDR);		if (eth_addrcmp (*dst_addr, eth_port->etp_ethaddr) == 0)			pack_stat= NWEO_EN_LOC;		else			pack_stat= NWEO_EN_PROMISC;	}	type= eth_hdr->eh_proto;	hash= type;	hash ^= (hash >> 8);	hash &= (ETH_TYPE_HASH_NR-1);	if (type == HTONS(ETH_VLAN_PROTO))	{		/* VLAN packet. Extract original ethernet packet */		vlan_pack= pack;		vlan_pack->acc_linkC++;		hdr_acc= bf_cut(vlan_pack, 0, 2*sizeof(ether_addr_t));		vlan_pack= bf_delhead(vlan_pack, 2*sizeof(ether_addr_t));		vlan_pack= bf_packIffLess(vlan_pack, sizeof(vh));		vh= *(vlan_hdr_t *)ptr2acc_data(vlan_pack);		vlan_pack= bf_delhead(vlan_pack, sizeof(vh));		hdr_acc= bf_append(hdr_acc, vlan_pack);		vlan_pack= hdr_acc; hdr_acc= NULL;		if (bf_bufsize(vlan_pack) < ETH_MIN_PACK_SIZE)		{			tmp_acc= bf_memreq(sizeof(vh));			/* Clear padding */			assert(sizeof(vh) <= sizeof(*p));			p= (u32_t *)ptr2acc_data(tmp_acc);			*p= 0xdeadbeef;			vlan_pack= bf_append(vlan_pack, tmp_acc);			tmp_acc= NULL;		}		vlan= ntohs(vh.vh_vlan);		if (vlan & ETH_TCI_CFI)		{			/* No support for extended address formats */			bf_afree(vlan_pack); vlan_pack= NULL;		}		vlan &= ETH_TCI_VLAN_MASK;	}	else	{		/* No VLAN processing */		vlan_pack= NULL;		vlan= 0;	/* lint */	}	first_fd= NULL;	for (i= 0; i<2; i++)	{		share_fd= NULL;		eth_fd= (i == 0) ? eth_port->etp_type_any :			eth_port->etp_type[hash];		for (; eth_fd; eth_fd= eth_fd->ef_type_next)		{			if (i && eth_fd->ef_ethopt.nweo_type != type)				continue;			if (!(eth_fd->ef_ethopt.nweo_flags & pack_stat))				continue;			if (eth_fd->ef_ethopt.nweo_flags & NWEO_REMSPEC &&				eth_addrcmp(eth_hdr->eh_src,				eth_fd->ef_ethopt.nweo_rem) != 0)			{					continue;			}			if ((eth_fd->ef_ethopt.nweo_flags & NWEO_ACC_MASK) ==				NWEO_SHARED)			{				if (!share_fd)				{					share_fd= eth_fd;					continue;				}				if (!eth_fd->ef_rdbuf_head)					share_fd= eth_fd;				continue;			}			if (!first_fd)			{				first_fd= eth_fd;				continue;			}			pack->acc_linkC++;			packet2user(eth_fd, pack, exp_time);		}		if (share_fd)		{			pack->acc_linkC++;			packet2user(share_fd, pack, exp_time);		}	}	if (first_fd)	{		if (first_fd->ef_put_pkt &&			(first_fd->ef_flags & EFF_READ_IP) &&			!(first_fd->ef_ethopt.nweo_flags & NWEO_RWDATONLY))		{			(*first_fd->ef_put_pkt)(first_fd->ef_srfd, pack,				pack_size);		}		else			packet2user(first_fd, pack, exp_time);	}	else	{		if (pack_stat == NWEO_EN_LOC)		{			DBLOCK(0x01,			printf("eth_arrive: dropping packet for proto 0x%x\n",				ntohs(type)));		}		else		{			DBLOCK(0x20, printf("dropping packet for proto 0x%x\n",				ntohs(type)));		}					bf_afree(pack);	}	if (vlan_pack)	{		hash= ETH_HASH_VLAN(vlan, temp);		for (vp= eth_port->etp_vlan_tab[hash]; vp;			vp= vp->etp_vlan_next)		{			if (vp->etp_vlan == vlan)				break;		}		if (vp)		{			eth_arrive(vp, vlan_pack, pack_size-sizeof(vh));			vlan_pack= NULL;		}		else		{			/* No device for VLAN */			bf_afree(vlan_pack);			vlan_pack= NULL;		}	}}PUBLIC void eth_reg_vlan(eth_port, vlan_port)eth_port_t *eth_port;eth_port_t *vlan_port;{	u16_t t, vlan;	int h;	vlan= vlan_port->etp_vlan;	h= ETH_HASH_VLAN(vlan, t);	vlan_port->etp_vlan_next= eth_port->etp_vlan_tab[h];	eth_port->etp_vlan_tab[h]= vlan_port;}PUBLIC void eth_restart_ioctl(eth_port)eth_port_t *eth_port;{	int i, r;	eth_fd_t *eth_fd;	acc_t *acc;	printf("in eth_restart_ioctl\n");	/* eth_restart_ioctl is called on too occasions: when a device	 * driver registers with inet and when a eth_get_stat call has	 * completed. We assume the second option when etp_getstat is	 * not equal to zero at the start of the call.	 */	acc= eth_port->etp_getstat;	for (i= 0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)	{		if (!(eth_fd->ef_flags & EFF_INUSE))			continue;		if (eth_fd->ef_port != eth_port)			continue;		if (!(eth_fd->ef_flags & EFF_IOCTL_IP))			continue;		if (eth_fd->ef_ioctl_req != NWIOGETHSTAT)			continue;printf("eth_restart_ioctl: etp_getstat in port %d is %p\n",	eth_port-eth_port_table, acc);		if (acc != NULL)		{			printf("eth_restart_ioctl: completed getstat\n");			acc->acc_linkC++;			r= (*eth_fd->ef_put_userdata)(eth_fd->ef_srfd, 0,				acc, TRUE);			if (r >= 0)				reply_thr_put(eth_fd, NW_OK, TRUE);			eth_fd->ef_flags &= ~EFF_IOCTL_IP;			continue;		} { static int count; if (++count > 5) ip_panic(("too many restarts")); }		eth_fd->ef_flags &= ~EFF_IOCTL_IP;		eth_ioctl(i, eth_fd->ef_ioctl_req);	}	if (acc != NULL)	{printf("eth_restart_ioctl: clearing etp_getstat in port %d\n",	eth_port-eth_port_table);		assert(acc == eth_port->etp_getstat);		bf_afree(acc);		eth_port->etp_getstat= NULL;	}}PRIVATE void packet2user (eth_fd, pack, exp_time)eth_fd_t *eth_fd;acc_t *pack;time_t exp_time;{	int result;	acc_t *tmp_pack;	size_t size;	assert (eth_fd->ef_flags & EFF_INUSE);	if (!(eth_fd->ef_flags & EFF_READ_IP))	{		if (pack->acc_linkC != 1)		{			tmp_pack= bf_dupacc(pack);			bf_afree(pack);			pack= tmp_pack;			tmp_pack= NULL;		}		pack->acc_ext_link= NULL;		if (eth_fd->ef_rdbuf_head == NULL)		{			eth_fd->ef_rdbuf_head= pack;			eth_fd->ef_exp_time= exp_time;		}		else			eth_fd->ef_rdbuf_tail->acc_ext_link= pack;		eth_fd->ef_rdbuf_tail= pack;		return;	}	if (eth_fd->ef_ethopt.nweo_flags & NWEO_RWDATONLY)		pack= bf_delhead(pack, ETH_HDR_SIZE);	size= bf_bufsize(pack);	if (eth_fd->ef_put_pkt)	{		(*eth_fd->ef_put_pkt)(eth_fd->ef_srfd, pack, size);		return;	}	eth_fd->ef_flags &= ~EFF_READ_IP;	result= (*eth_fd->ef_put_userdata)(eth_fd->ef_srfd, (size_t)0, pack,		FALSE);	if (result >=0)		reply_thr_put(eth_fd, size, FALSE);	else		reply_thr_put(eth_fd, result, FALSE);}PRIVATE void eth_buffree (priority)int priority;{	int i;	eth_fd_t *eth_fd;	acc_t *pack;	if (priority == ETH_PRI_FDBUFS_EXTRA)	{		for (i= 0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)		{			while (eth_fd->ef_rdbuf_head &&				eth_fd->ef_rdbuf_head->acc_ext_link)			{				pack= eth_fd->ef_rdbuf_head;				eth_fd->ef_rdbuf_head= pack->acc_ext_link;				bf_afree(pack);			}		}	}	if (priority == ETH_PRI_FDBUFS)	{		for (i= 0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)		{			while (eth_fd->ef_rdbuf_head)			{				pack= eth_fd->ef_rdbuf_head;				eth_fd->ef_rdbuf_head= pack->acc_ext_link;				bf_afree(pack);			}		}	}}#ifdef BUF_CONSISTENCY_CHECKPRIVATE void eth_bufcheck(){	int i;	eth_fd_t *eth_fd;	acc_t *pack;	for (i= 0; i<eth_conf_nr; i++)	{		bf_check_acc(eth_port_table[i].etp_rd_pack);		bf_check_acc(eth_port_table[i].etp_wr_pack);	}	for (i= 0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)	{		for (pack= eth_fd->ef_rdbuf_head; pack;			pack= pack->acc_ext_link)		{			bf_check_acc(pack);		}	}}#endifPRIVATE void do_rec_conf(eth_port)eth_port_t *eth_port;{	int i;	u32_t flags;	eth_port_t *vp;	assert(eth_port);	if (eth_port->etp_vlan)	{		/* Configure underlying device */		eth_port= eth_port->etp_vlan_port;	}	flags= compute_rec_conf(eth_port);	for (i= 0; i<ETH_VLAN_HASH_NR; i++)	{		for (vp= eth_port->etp_vlan_tab[i]; vp; vp= vp->etp_vlan_next)			flags |= compute_rec_conf(vp);	}	eth_set_rec_conf(eth_port, flags);}PRIVATE u32_t compute_rec_conf(eth_port)eth_port_t *eth_port;{	eth_fd_t *eth_fd;	u32_t flags;	int i;	flags= NWEO_NOFLAGS;	for (i=0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)	{		if ((eth_fd->ef_flags & (EFF_INUSE|EFF_OPTSET)) !=			(EFF_INUSE|EFF_OPTSET))		{			continue;		}		if (eth_fd->ef_port != eth_port)			continue;		flags |= eth_fd->ef_ethopt.nweo_flags;	}	return flags;}PRIVATE void reply_thr_get (eth_fd, result, for_ioctl)eth_fd_t *eth_fd;size_t result;int for_ioctl;{	acc_t *data;	data= (*eth_fd->ef_get_userdata)(eth_fd->ef_srfd, result, 0, for_ioctl);	assert (!data);	}PRIVATE void reply_thr_put (eth_fd, result, for_ioctl)eth_fd_t *eth_fd;size_t result;int for_ioctl;{	int error;	error= (*eth_fd->ef_put_userdata)(eth_fd->ef_srfd, result, (acc_t *)0,		for_ioctl);	assert(error == NW_OK);}PRIVATE acc_t *insert_vlan_hdr(eth_port, pack)eth_port_t *eth_port;acc_t *pack;{	acc_t *head_acc, *vh_acc;	u16_t type, vlan;	vlan_hdr_t *vp;	head_acc= bf_cut(pack, 0, 2*sizeof(ether_addr_t));	pack= bf_delhead(pack, 2*sizeof(ether_addr_t));	pack= bf_packIffLess(pack, sizeof(type));	type= *(u16_t *)ptr2acc_data(pack);	if (type == HTONS(ETH_VLAN_PROTO))	{		/* Packeted is already tagged. Should update vlan number.		 * For now, just discard packet.		 */		printf("insert_vlan_hdr: discarding vlan packet\n");		bf_afree(head_acc); head_acc= NULL;		bf_afree(pack); pack= NULL;		return NULL;	}	vlan= eth_port->etp_vlan;	/* priority and CFI are zero */	vh_acc= bf_memreq(sizeof(vlan_hdr_t));	vp= (vlan_hdr_t *)ptr2acc_data(vh_acc);	vp->vh_type= HTONS(ETH_VLAN_PROTO);	vp->vh_vlan= htons(vlan);	head_acc= bf_append(head_acc, vh_acc); vh_acc= NULL;	head_acc= bf_append(head_acc, pack); pack= NULL;	pack= head_acc; head_acc= NULL;	return pack;}/* * $PchId: eth.c,v 1.23 2005/06/28 14:15:58 philip Exp $ */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -