📄 eth.c
字号:
}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= ð_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 == ð_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= ð_port->etp_type_any; } else { hash= eth_fd->ef_ethopt.nweo_type; hash ^= (hash >> 8); hash &= (ETH_TYPE_HASH_NR-1); eth_fd_p= ð_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= ð_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 + -