[ECOS] ethernet driver problem when line reconnected
Jonathan Larmour
jlarmour@redhat.com
Fri Jan 4 07:37:00 GMT 2002
Damir Salantic wrote:
>
> We are experiencing following problem with ethernet driver using our MIPS
> based board.
>
> Once the board is disconnected from the LAN, the number of buffers increases
> with a rate of 4 for each retry (approx. 2 sec.) up
> to 104/106. It takes approx. 50 sec. to reach this limit. If I reconnect the
> LAN just at this moment the communication restarts. If I try
> again but I wait just a little more nothing happens.
>
> After some debug outputs we found the cause of the problem.
You're probably not going to like this :-), but this was already fixed in
the anonymous CVS repository with this change:
2001-10-29 Hugo Tyson <hmt@redhat.com>
* src/sys/net/if_ethersubr.c (ether_output): [CASE 106613] Even if
the queue is full, and we are dropping the packet, try to start
the interface anyway, to give it a chance to empty the queue if
the device has recovered from whatever made the queue fill up in
the first place - being unplugged from the network for example.
This change is belt & braces with a similar policy in the periodic
tickle function in the logical ether driver in io/eth/... ; this
change will recover the situation immediately if the application
continues trying to send despite ENOBUFS.
You mustn't have this fix as it is the same as your own!
Jifl
> The focal point is in if_ethersubr.c in function ether_output():
> ....................
> /*
> * Queue message on interface, and start output if interface
> * not yet active.
> */
> if (IF_QFULL(&ifp->if_snd)) {
> IF_DROP(&ifp->if_snd);
> splx(s);
> senderr(ENOBUFS);
> }
> ifp->if_obytes += m->m_pkthdr.len;
> IF_ENQUEUE(&ifp->if_snd, m);
> if (m->m_flags & M_MCAST)
> ifp->if_omcasts++;
> if ((ifp->if_flags & IFF_OACTIVE) == 0)
> (*ifp->if_start)(ifp);
> splx(s);
> return (error);
> .....................
>
> System is sending packets and is disconnected from the LAN.
> The low level can_send() returns FALSE, so packets are queued and
> *ifp->if_start (points to: eth_drv_send()) is called but
> low level send() is not. When the queue is full (IF_QFULL), then the
> eth_drv_send() is no more called.
> Once the LAN is reconnected what should happen? Low level driver is not
> waiting for a TX event so no TX interrupt occurs and the engine hangs on.
> It's a little confusing that the interface restarts only if somebody try to
> send something.
> Newer requests are aborted because the queue is full, but nobody retry to
> send packets already in queue.......
>
> This fixing will try to restart transmission of the queue every time there
> is a packet to be sent and queue is full.
> .........
> if (IF_QFULL(&ifp->if_snd)) {
> IF_DROP(&ifp->if_snd);
> //fix start
> if ((ifp->if_flags & IFF_OACTIVE) == 0) //try anyway to restart the
> interface
> (*ifp->if_start)(ifp);
> //fix end
> splx(s);
> senderr(ENOBUFS);
> }
> ............
>
> We tried the fixing and it worked, but we are not really sure that it is the
> proper solution.
> Please advice.
>
> Thanks
> Damir
--
Red Hat, Rustat House, Clifton Road, Cambridge, UK. Tel: +44 (1223) 271062
Maybe this world is another planet's Hell -Aldous Huxley || Opinions==mine
More information about the Ecos-discuss
mailing list