I have two Linux machines connected with a serial interface. I use ppp to communicate between them (I have to since it is a project requirement). Communication speed is at 9600 bits/s. I need to measure bandwidth used, bits/s, live, i.e. while the system is running. Initially I thought I would use ifstat -btwTWS -i ppp0, since this is what the tools was designed for. However the value that was displayed was way more than 9600 bits/s. It hovered around 12.09 Kbits/s. I did ask why this happening, and the response was that it could be because of a compression. This does make sense. What I need, however, is actual bits/s after compression and before decompression happens.

My initial approach to solve this problem:

Initially I thought to use some sort of a serial traffic sniffer with a capability to display a data rate. I've tried several, but whenever I try to connect to /dev/ttyUSB0 I'm getting a resource busy error. This is happening because PPP is taking over the device.

My second approach to solve this problem:

I want to create a pseudo serial port, connect it to a real serial port. Then PPP will take over pseudo serial port and I will sniff the traffic on a real serial port. Here is the diagram:

--------------------         -------------------------  
|                  |         |                       |
|      PPP         |         |        sniffer        |
|  -------------   |         |   ------------------  |              
|  | /dev/pty0 |---|---------|---|  /dev/ttyUSB0  |  |
|  -------------   |         |   ------------------  |
|                  |         |                       |
--------------------         -------------------------

My understanding is that socat can do that. I've been reading up on this, but I coulnd't find any options that allow me to do that.

So here is my question:

How do I create a pseudoterminal with socat and connect to a real serial port? Is that even possible?

  • 1
    I wonder why you don't just disable the compression in pppd? (novj, nobsdcomp, noccp, nodeflate, etc).
    – user313992
    Jan 12, 2019 at 18:34

1 Answer 1


You should be able to use socat in a simple command like

socat pty,link=$HOME/myserial,rawer /dev/ttyUSB0,rawer 2>&1

This creates a symbolic link ~/myserial to the pty, and any i/o to the pty is copied to/from the serial port. Going one step further, you can add options -v to get the i/o copied to stderr, and -x to have it printed in hex with header lines of the form:

< 2019/01/12 18:16:36.528942  length=12 from=310 to=321

where the first character is the direction < or >, and the length is the number of bytes copied. The use of hex ensures the header line is not confused with the raw data. Here's a possible awk script to parse this. Approximately every 10 seconds it writes out the current number of bytes/second in a direction.

socat -v -x pty,link=$HOME/myserial,rawer /dev/ttyUSB0,rawer 2>&1  |
awk '
 /^[><]/{ split($3,x,":"); tod = (x[1]*60+x[2])*60+x[3]; 
          split($4,x,"="); len = x[2]+0; 
          dir = $1=="<" ? "rx" : "tx";
            printf "%s %f\n",dir,(len+tot[dir])/(tod-lasttod[dir])
            lasttod[dir] = tod
            tot[dir] = 0
          }else tot[dir] += len

To keep it simple, each direction is handled separately, and you will need to fix time going through midnight. Typical output might be

tx 2.398754
rx 0.000425
tx 2.398772
rx 61.768501

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .