ports/58514: Zebra based software BGP routers may freeze after a small network disturbance

Vladimir Ivanov wawa at yandex-team.ru
Sat Oct 25 11:40:09 UTC 2003


>Number:         58514
>Category:       ports
>Synopsis:       Zebra based software BGP routers may freeze after a small network disturbance
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Oct 25 04:40:01 PDT 2003
>Closed-Date:
>Last-Modified:
>Originator:     Vladimir Ivanov
>Release:        
>Organization:
Yandex LLC
>Environment:
System: FreeBSD wawa.yandex.ru 4.9-RC FreeBSD 4.9-RC #1: Wed Oct 22 09:28:23 MSD 2003 wawa at wawa.yandex.ru:/usr/obj/usr/src/sys/WAWA i386


	
>Description:
	Sometimes Zebra (BGPD) software router freeze.

	After short investigations we've discovered blocked write operation in the BGP code (see the patch below). 
	It's a little bit funny because a couple lines before we can see authors comments which promissed non-blocking write operation.

	Alternate releases of Zebra (aka gnuzebra or quagga) contain the same bug I seem.

>How-To-Repeat:
	The problem occured when two Zebra routers being used to share network traffic. Both routers sould be bgp neighbours.
	Then we have to force both Zebras to fill network sendbuffers of session to each other. It's not very hard task I guess.
	In freeze situation each Zebra waits when other one will read packet and that's why it doesn read packet as we can see.
>Fix:

--- bgpd/bgp_packet.c   Tue Aug 20 19:31:54 2002
+++ bgpd/bgp_packet.c   Thu Oct 16 19:33:14 2003
@@ -566,17 +566,22 @@
   while (1)
     {
       int writenum;
+      int val;

       s = bgp_write_packet (peer);
       if (! s)
        return 0;

+      val = fcntl (peer->fd, F_GETFL, 0);
+      fcntl (peer->fd, F_SETFL, val|O_NONBLOCK);
+
       /* Number of bytes to be sent.  */
       writenum = stream_get_endp (s) - stream_get_getp (s);

       /* Call write() system call.  */
       num = write (peer->fd, STREAM_PNT (s), writenum);
       write_errno = errno;
+      fcntl (peer->fd, F_SETFL, val);
       if (num <= 0)
        {
          /* Partial write. */


>Release-Note:
>Audit-Trail:
>Unformatted:



More information about the freebsd-ports-bugs mailing list