[PATCH rtems-libbsd] ppp: Fix transmitting data

Christian Mauderer christian.mauderer at embedded-brains.de
Thu Aug 12 11:42:53 UTC 2021


The pppstart expected that a driver write would somehow magically
process all data passed to the write function. Because ppp disables all
buffering that originally has been in termios, that assumption is not
true for all but polled drivers.

With this patch, the pppstart now gets and processes the feedback that
is returned from the driver via rtems_termios_dequeue_characters.

Fixes #4493
---
 rtemsbsd/sys/net/if_ppp.c    | 11 ++++++-----
 rtemsbsd/sys/net/if_pppvar.h |  1 +
 rtemsbsd/sys/net/ppp_tty.c   | 32 ++++++++++++++++++++++++++++----
 3 files changed, 35 insertions(+), 9 deletions(-)

diff --git a/rtemsbsd/sys/net/if_ppp.c b/rtemsbsd/sys/net/if_ppp.c
index 709f13e04..e134dc760 100644
--- a/rtemsbsd/sys/net/if_ppp.c
+++ b/rtemsbsd/sys/net/if_ppp.c
@@ -313,11 +313,12 @@ static rtems_task ppp_txdaemon(rtems_task_argument arg)
       frag=0;
 
       /* initialize output values */
-      sc->sc_outfcs    = PPP_INITFCS;
-      sc->sc_outbuf    = (u_char *)0;
-      sc->sc_outlen    = (short   )0;
-      sc->sc_outoff    = (short   )0;
-      sc->sc_outfcslen = (short   )0;
+      sc->sc_outfcs        = PPP_INITFCS;
+      sc->sc_outbuf        = (u_char *)0;
+      sc->sc_outlen        = (short   )0;
+      sc->sc_outoff        = (short   )0;
+      sc->sc_outoff_update = false;
+      sc->sc_outfcslen     = (short   )0;
 
 /*	  printf("Start Transmit Packet..\n"); */
 
diff --git a/rtemsbsd/sys/net/if_pppvar.h b/rtemsbsd/sys/net/if_pppvar.h
index fdfb56df0..bd11bcbc4 100644
--- a/rtemsbsd/sys/net/if_pppvar.h
+++ b/rtemsbsd/sys/net/if_pppvar.h
@@ -117,6 +117,7 @@ struct ppp_softc {
 
 	struct	ifqueue sc_freeq;       /* free packets */
 	short	sc_outoff;		/* output packet byte offset */
+	bool	sc_outoff_update;	/* outoff needs update in pppstart */
 	short	sc_outflag;		/* output status flag */
 	short	sc_outlen;		/* length of output packet */
 	short	sc_outfcslen;		/* length of output fcs data */
diff --git a/rtemsbsd/sys/net/ppp_tty.c b/rtemsbsd/sys/net/ppp_tty.c
index 80d4fee16..2e850dc77 100644
--- a/rtemsbsd/sys/net/ppp_tty.c
+++ b/rtemsbsd/sys/net/ppp_tty.c
@@ -124,7 +124,7 @@ int     pppread(struct rtems_termios_tty *tty, rtems_libio_rw_args_t *rw_args);
 int     pppwrite(struct rtems_termios_tty *tty, rtems_libio_rw_args_t *rw_args);
 int     ppptioctl(struct rtems_termios_tty *tty, rtems_libio_ioctl_args_t *args);
 int     pppinput(int c, struct rtems_termios_tty *tty);
-int     pppstart(struct rtems_termios_tty *tp);
+int     pppstart(struct rtems_termios_tty *tp, int len);
 u_short pppfcs(u_short fcs, u_char *cp, int len);
 void    pppallocmbuf(struct ppp_softc *sc, struct mbuf **mp);
 
@@ -557,7 +557,7 @@ pppasyncctlp(
  * Called at spltty or higher.
  */
 int
-pppstart(struct rtems_termios_tty *tp)
+pppstart(struct rtems_termios_tty *tp, int len)
 {
   u_char             *sendBegin;
   u_long              ioffset = (u_long       )0;
@@ -567,6 +567,13 @@ pppstart(struct rtems_termios_tty *tp)
 
   /* ensure input is valid and we are busy */
   if (( sc != NULL ) && ( sc->sc_outflag & SC_TX_BUSY )) {
+    /* Adapt offsets if necessary */
+    if ( sc->sc_outoff_update ) {
+      sc->sc_stats.ppp_obytes += len;
+      sc->sc_outoff += len;
+      sc->sc_outoff_update = false;
+    }
+
     /* check to see if we need to get the next buffer */
 
     /* Ready with PPP_FLAG Character ? */
@@ -644,8 +651,25 @@ pppstart(struct rtems_termios_tty *tp)
 
       /* write out the character(s) and update the stats */
       (*tp->handler.write)(ctx, (char *)sendBegin, (ioffset > 0) ? ioffset : 1);
-      sc->sc_stats.ppp_obytes += (ioffset > 0) ? ioffset : 1;
-      sc->sc_outoff += ioffset;
+      /*
+       * In case of polled drivers, everything is sent here. So adapt the
+       * offsets. In case of interrupt or task driven drivers, we don't know
+       * whether all characters have been sent. We only get feedback via
+       * rtems_termios_dequeue_characters() function which is the one that is
+       * calling us.
+       */
+      if (tp->handler.mode == TERMIOS_POLLED) {
+        sc->sc_stats.ppp_obytes += (ioffset > 0) ? ioffset : 1;
+        sc->sc_outoff += ioffset;
+        sc->sc_outoff_update = false;
+      } else {
+        if (ioffset > 0) {
+          sc->sc_outoff_update = true;
+        } else {
+          sc->sc_outoff_update = false;
+          sc->sc_stats.ppp_obytes += 1;
+        }
+      }
 
       return (0);
     }
-- 
2.31.1



More information about the devel mailing list