On Sun, Dec 08, 2019 at 11:34:15PM +0100, Remi Locherer wrote:
> On Thu, Dec 05, 2019 at 12:07:25PM +1100, Jason Tubnor wrote:
> > I have been trying to track down a memory leak that has been observed for
> > quite a number of years over multiple releases without success.  I feel
> > that I have exhausted all potential configuration items that may have
> > caused this issue so now filing a bug.
> > 
> > >Synopsis:      ripd engine develops memory leak over time
> > >Category:      system
> > >Environment:
> >         System      : OpenBSD 6.6
> >         Details     : OpenBSD 6.6-current (GENERIC.MP) #492: Wed Nov 27
> > 00:21:04 MST 2019
> >                          dera...@amd64.openbsd.org:
> > /usr/src/sys/arch/amd64/compile/GENERIC.MP
> > 
> >         Architecture: OpenBSD.amd64
> >         Machine     : amd64
> > >Description:
> >          When ripd isn't configured to redistribute anything, memory usage
> > remains static, once something is set for redistribution, that is when
> > memory begins to be consumed.  The config below (minus security - but
> > without security yields the same result) is loaded and the engine process
> > [below] is the memory behavior over a 3 hour period.  I have been able to
> > expedite memory consumption by increasing the interfaces and endpoints that
> > participate.  I have witnessed the engine grow to over 10GB in size with no
> > change in the routing table (393 routes).  Once memory is exhausted and
> > pressure put on swap, the host falls over.
> > 
> > >How-To-Repeat:
> >         Various version 5.8 - 6.6 exhibit this problem.  Below is a simple
> > configuration and the resulting engine process being monitored over 3 hours:
> > 
> > # cat /etc/ripd.conf
> > no redistribute <external subnet>/22
> > redistribute connected
> > split-horizon simple
> > 
> > interface vxlan32 {
> > }
> > interface vio0 {
> >         passive
> > }
> > interface vio1 {
> >         passive
> > }
> > interface vio2 {
> >         passive
> > }
> > interface vio3 {
> >         passive
> > }
> > interface vio4 {
> >         passive
> > }
> > interface vio5 {
> >         passive
> > }
> > 
> 
> I can reproduce this issue. But only when I combine the use of
> "interface XY { passive }" and "redistribute connected". When I remove
> the passive interfaces from ripd.conf memory consumption is stable.
> 
> Why do you combine these configs?

Below diff fixes the memory leak for me.

In addition to clear r_list I also moved the check for passive interface
a bit up so that the function can return as soon as possible.

OK?

Remi



Index: message.c
===================================================================
RCS file: /cvs/src/usr.sbin/ripd/message.c,v
retrieving revision 1.12
diff -u -p -r1.12 message.c
--- message.c   25 Oct 2014 03:23:49 -0000      1.12
+++ message.c   8 Dec 2019 23:35:42 -0000
@@ -105,15 +105,15 @@ send_triggered_update(struct iface *ifac
        u_int16_t                afi, route_tag;
        u_int32_t                address, netmask, nexthop, metric;
 
+       if (iface->passive)
+               return (0);
+
        inet_aton(ALL_RIP_ROUTERS, &dst.sin_addr);
 
        dst.sin_port = htons(RIP_PORT);
        dst.sin_family = AF_INET;
        dst.sin_len = sizeof(struct sockaddr_in);
 
-       if (iface->passive)
-               return (0);
-
        if ((buf = ibuf_open(iface->mtu - sizeof(struct ip) -
            sizeof(struct udphdr))) == NULL)
                fatal("send_triggered_update");
@@ -166,13 +166,15 @@ send_request(struct packet_head *r_list,
                port = htons(RIP_PORT);
        }
 
+       if (iface->passive) {
+               clear_list(r_list);
+               return (0);
+       }
+
        dst.sin_port = port;
        dst.sin_family = AF_INET;
        dst.sin_len = sizeof(struct sockaddr_in);
 
-       if (iface->passive)
-               return (0);
-
        while (!TAILQ_EMPTY(r_list)) {
                if ((buf = ibuf_open(iface->mtu - sizeof(struct ip) -
                    sizeof(struct udphdr))) == NULL)
@@ -240,13 +242,15 @@ send_response(struct packet_head *r_list
                port = htons(RIP_PORT);
        }
 
+       if (iface->passive) {
+               clear_list(r_list);
+               return (0);
+       }
+
        dst.sin_port = port;
        dst.sin_family = AF_INET;
        dst.sin_len = sizeof(struct sockaddr_in);
 
-       if (iface->passive)
-               return (0);
-
        while (!TAILQ_EMPTY(r_list)) {
                if ((buf = ibuf_open(iface->mtu - sizeof(struct ip) -
                    sizeof(struct udphdr))) == NULL)

Reply via email to