From: Philip Homburg Date: Mon, 28 Aug 2006 12:59:36 +0000 (+0000) Subject: Do not abort/panic when an ethernet driver does something unexpected. X-Git-Tag: v3.1.3~192 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zpipe.c?a=commitdiff_plain;h=66f9a5f508fe303486cfa52c8d517f85b68ef5fa;p=minix.git Do not abort/panic when an ethernet driver does something unexpected. --- diff --git a/servers/inet/inet.c b/servers/inet/inet.c index f866dadc0..9ce7db78c 100644 --- a/servers/inet/inet.c +++ b/servers/inet/inet.c @@ -258,12 +258,17 @@ PUBLIC void main() mq_free(mq); } #endif - else + else if (mq->mq_mess.m_type == DL_TASK_REPLY) { -compare(mq->mq_mess.m_type, ==, DL_TASK_REPLY); eth_rec(&mq->mq_mess); mq_free(mq); } + else + { + printf("inet: got bad message type 0x%x from %d\n", + mq->mq_mess.m_type, mq->mq_mess.m_source); + mq_free(mq); + } } ip_panic(("task is not allowed to terminate")); } diff --git a/servers/inet/mnx_eth.c b/servers/inet/mnx_eth.c index dad9d60b7..44bb82e3f 100644 --- a/servers/inet/mnx_eth.c +++ b/servers/inet/mnx_eth.c @@ -108,6 +108,7 @@ PUBLIC void osdep_eth_init() eth_port->etp_osdep.etp_port= ecp->ec_port; eth_port->etp_osdep.etp_task= tasknr; + eth_port->etp_osdep.etp_send_ev= 0; ev_init(ð_port->etp_osdep.etp_recvev); mess.m_type= DL_CONF; @@ -335,6 +336,8 @@ acc_t *pack; assert(loc_port != eth_port); loc_port->etp_osdep.etp_sendrepl= block_msg; ev_arg.ev_ptr= loc_port; + assert(!loc_port->etp_osdep.etp_send_ev); + loc_port->etp_osdep.etp_send_ev= 1; ev_enqueue(&loc_port->etp_sendev, eth_sendev, ev_arg); } if (block_msg.DL_STAT & DL_PACK_RECV) @@ -359,6 +362,17 @@ acc_t *pack; return; } + if (mess1.m_type != DL_TASK_REPLY || + mess1.DL_PORT != eth_port->etp_osdep.etp_port || + mess1.DL_PROC != this_proc) + { + printf( +"eth_write_port: ignoring bad message (type = 0x%x, port = %d, proc = %d) from %d\n", + mess1.m_type, mess1.DL_PORT, mess1.DL_PROC, + mess1.m_source); + return; + } + assert(mess1.m_type == DL_TASK_REPLY && mess1.DL_PORT == eth_port->etp_osdep.etp_port && mess1.DL_PROC == this_proc); @@ -392,6 +406,8 @@ acc_t *pack; { eth_port->etp_osdep.etp_sendrepl= mess1; ev_arg.ev_ptr= eth_port; + assert(!eth_port->etp_osdep.etp_send_ev); + eth_port->etp_osdep.etp_send_ev= 1; ev_enqueue(ð_port->etp_sendev, eth_sendev, ev_arg); /* Pretend that we didn't get a reply. */ @@ -428,7 +444,8 @@ message *m; stat= m->DL_STAT & 0xffff; - assert(stat & (DL_PACK_SEND|DL_PACK_RECV)); + if (!(stat & (DL_PACK_SEND|DL_PACK_RECV))) + printf("eth_rec: neither DL_PACK_SEND nor DL_PACK_RECV\n"); if (stat & DL_PACK_SEND) write_int(loc_port); if (stat & DL_PACK_RECV) @@ -615,6 +632,14 @@ eth_port_t *eth_port; u8_t *eth_dst_ptr; pack= eth_port->etp_wr_pack; + if (pack == NULL) + { + printf("write_int: strange no packet on eth port %d\n", + eth_port-eth_port_table); + eth_restart_write(eth_port); + return; + } + eth_port->etp_wr_pack= NULL; eth_dst_ptr= (u8_t *)ptr2acc_data(pack); @@ -642,14 +667,29 @@ int count; pack= eth_port->etp_rd_pack; eth_port->etp_rd_pack= NULL; - cut_pack= bf_cut(pack, 0, count); - bf_afree(pack); + if (count < ETH_MIN_PACK_SIZE) + { + printf("mnx_eth`read_int: packet size too small (%d)\n", + count); + bf_afree(pack); + } + else if (count > ETH_MAX_PACK_SIZE_TAGGED) + { + printf("mnx_eth`read_int: packet size too big (%d)\n", + count); + bf_afree(pack); + } + else + { + cut_pack= bf_cut(pack, 0, count); + bf_afree(pack); - assert(!no_ethWritePort); - no_ethWritePort= 1; - eth_arrive(eth_port, cut_pack, count); - assert(no_ethWritePort); - no_ethWritePort= 0; + assert(!no_ethWritePort); + no_ethWritePort= 1; + eth_arrive(eth_port, cut_pack, count); + assert(no_ethWritePort); + no_ethWritePort= 0; + } eth_port->etp_flags &= ~(EPF_READ_IP|EPF_READ_SP); setup_read(eth_port); @@ -738,10 +778,13 @@ eth_port_t *eth_port; (DL_PACK_SEND|DL_PACK_RECV)); if (block_msg.DL_STAT & DL_PACK_SEND) { - loc_port->etp_osdep.etp_sendrepl= block_msg; + loc_port->etp_osdep.etp_sendrepl= + block_msg; ev_arg.ev_ptr= loc_port; - ev_enqueue(&loc_port->etp_sendev, eth_sendev, - ev_arg); + assert(!loc_port->etp_osdep.etp_send_ev); + loc_port->etp_osdep.etp_send_ev= 1; + ev_enqueue(&loc_port->etp_sendev, + eth_sendev, ev_arg); } if (block_msg.DL_STAT & DL_PACK_RECV) { @@ -768,10 +811,23 @@ eth_port_t *eth_port; continue; } - assert (mess1.m_type == DL_TASK_REPLY && - mess1.DL_PORT == mess1.DL_PORT && - mess1.DL_PROC == this_proc); - compare((mess1.DL_STAT >> 16), ==, OK); + if (mess1.m_type != DL_TASK_REPLY || + mess1.DL_PORT != eth_port->etp_osdep.etp_port || + mess1.DL_PROC != this_proc) + { + printf("mnx_eth`setup_read: bad type, port or proc\n"); + printf("got type %d, port %d, proc %d\n", + mess1.m_type, mess1.DL_PORT, mess1.DL_PROC); + continue; + } + + if ((mess1.DL_STAT >> 16) != OK) + { + printf( + "mnx_eth`setup_read: bad value in DL_STAT: 0x%x\n", + mess1.DL_STAT); + mess1.DL_STAT= 0; + } if (mess1.DL_STAT & DL_PACK_RECV) { @@ -781,15 +837,26 @@ eth_port_t *eth_port; "setup_read(mess1): eth%d: got DL_PACK_RECV\n", mess1.DL_PORT); } - /* packet received */ - pack_ptr= bf_cut(pack, 0, mess1.DL_COUNT); - bf_afree(pack); - - assert(!no_ethWritePort); - no_ethWritePort= 1; - eth_arrive(eth_port, pack_ptr, mess1.DL_COUNT); - assert(no_ethWritePort); - no_ethWritePort= 0; + + if (mess1.DL_COUNT < ETH_MIN_PACK_SIZE) + { + printf( + "mnx_eth`setup_read: packet size too small (%d)\n", + mess1.DL_COUNT); + bf_afree(pack); + } + else + { + /* packet received */ + pack_ptr= bf_cut(pack, 0, mess1.DL_COUNT); + bf_afree(pack); + + assert(!no_ethWritePort); + no_ethWritePort= 1; + eth_arrive(eth_port, pack_ptr, mess1.DL_COUNT); + assert(no_ethWritePort); + no_ethWritePort= 0; + } } else { @@ -800,9 +867,20 @@ eth_port_t *eth_port; if (mess1.DL_STAT & DL_PACK_SEND) { - eth_port->etp_osdep.etp_sendrepl= mess1; - ev_arg.ev_ptr= eth_port; - ev_enqueue(ð_port->etp_sendev, eth_sendev, ev_arg); + if (eth_port->etp_osdep.etp_send_ev) + { + printf( + "mnx_eth`setup_read: etp_send_ev is set, ignoring DL_PACK_SEND\n"); + } + else + { + eth_port->etp_osdep.etp_sendrepl= mess1; + ev_arg.ev_ptr= eth_port; + assert(!eth_port->etp_osdep.etp_send_ev); + eth_port->etp_osdep.etp_send_ev= 1; + ev_enqueue(ð_port->etp_sendev, eth_sendev, + ev_arg); + } } } while (!(eth_port->etp_flags & EPF_READ_IP)); eth_port->etp_flags |= EPF_READ_SP; @@ -851,6 +929,8 @@ ev_arg_t ev_arg; assert(m_ptr->DL_STAT & DL_PACK_SEND); m_ptr->DL_STAT &= ~DL_PACK_SEND; + assert(eth_port->etp_osdep.etp_send_ev); + eth_port->etp_osdep.etp_send_ev= 0; /* packet is sent */ write_int(eth_port); diff --git a/servers/inet/osdep_eth.h b/servers/inet/osdep_eth.h index a31cc6586..0bfec142f 100644 --- a/servers/inet/osdep_eth.h +++ b/servers/inet/osdep_eth.h @@ -19,6 +19,7 @@ typedef struct osdep_eth_port int etp_task; int etp_port; int etp_recvconf; + int etp_send_ev; iovec_s_t etp_wr_iovec[IOVEC_NR]; cp_grant_id_t etp_wr_vec_grant; iovec_s_t etp_rd_iovec[RD_IOVEC];