I noticed that when starting my test bgpd multihop sessions that the
session engine is busy spinning until the tables are loaded. Now since the
network is rather slow this does not make sense and indicates that the
poll timeout is wrongly set to 0 almost all the time until the session
finished the initial load.

Looking at this I realized that the current indication that there is still
work pending for a peer is wrong. Just checking if there is data in the
read buffer is wrong since in my case this most probably because of a
short read and so no immediate work needs to happen. This diff changes
the check and replaces it with a flag that is only set in the case we
stopped parsing because of hitting the MSG_PROCESS_LIMIT.

With this my session engine no longer busy loops at start which saves a
lot of CPU :)
-- 
:wq Claudio


Index: session.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/session.c,v
retrieving revision 1.377
diff -u -p -r1.377 session.c
--- session.c   31 Mar 2019 16:57:38 -0000      1.377
+++ session.c   2 Apr 2019 10:23:09 -0000
@@ -81,7 +81,7 @@ void  session_rrefresh(struct peer *, u_i
 int    session_graceful_restart(struct peer *);
 int    session_graceful_stop(struct peer *);
 int    session_dispatch_msg(struct pollfd *, struct peer *);
-int    session_process_msg(struct peer *);
+void   session_process_msg(struct peer *);
 int    parse_header(struct peer *, u_char *, u_int16_t *, u_int8_t *);
 int    parse_open(struct peer *);
 int    parse_update(struct peer *);
@@ -426,7 +426,7 @@ session_main(int debug, int verbose)
                        if (p->wbuf.queued > 0 || p->state == STATE_CONNECT)
                                events |= POLLOUT;
                        /* is there still work to do? */
-                       if (p->rbuf && p->rbuf->wpos)
+                       if (p->rpending)
                                timeout = 0;
 
                        /* poll events */
@@ -1779,7 +1779,7 @@ session_dispatch_msg(struct pollfd *pfd,
        return (0);
 }
 
-int
+void
 session_process_msg(struct peer *p)
 {
        struct mrt      *mrt;
@@ -1790,19 +1790,20 @@ session_process_msg(struct peer *p)
 
        rpos = 0;
        av = p->rbuf->wpos;
+       p->rpending = 0;
 
        /*
         * session might drop to IDLE -> buffers deallocated
         * we MUST check rbuf != NULL before use
         */
        for (;;) {
-               if (rpos + MSGSIZE_HEADER > av)
-                       break;
                if (p->rbuf == NULL)
+                       return;
+               if (rpos + MSGSIZE_HEADER > av)
                        break;
                if (parse_header(p, p->rbuf->buf + rpos, &msglen,
                    &msgtype) == -1)
-                       return (0);
+                       return;
                if (rpos + msglen > av)
                        break;
                p->rbuf->rptr = p->rbuf->buf + rpos;
@@ -1847,11 +1848,11 @@ session_process_msg(struct peer *p)
                        bgp_fsm(p, EVNT_CON_FATAL);
                }
                rpos += msglen;
-               if (++processed > MSG_PROCESS_LIMIT)
+               if (++processed > MSG_PROCESS_LIMIT) {
+                       p->rpending = 1;
                        break;
+               }
        }
-       if (p->rbuf == NULL)
-               return (1);
 
        if (rpos < av) {
                left = av - rpos;
@@ -1859,8 +1860,6 @@ session_process_msg(struct peer *p)
                p->rbuf->wpos = left;
        } else
                p->rbuf->wpos = 0;
-
-       return (1);
 }
 
 int
Index: session.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/session.h,v
retrieving revision 1.135
diff -u -p -r1.135 session.h
--- session.h   31 Mar 2019 16:57:38 -0000      1.135
+++ session.h   2 Apr 2019 10:13:28 -0000
@@ -231,6 +231,7 @@ struct peer {
        u_int8_t                 demoted;
        u_int8_t                 passive;
        u_int8_t                 throttled;
+       u_int8_t                 rpending;
 };
 
 extern time_t           pauseaccept;

Reply via email to