Monday, October 1, 2018

PPP Over UART

Hi Folks,

After a long time I manged to write this post. We are well aware of inter-process communication for data exchange between processes, here we are now going to discuss the reliable means of data transfer between two CPUs running Linux over UART interface.

PPP (Point-to-Point Protocol) is a specification for transmission of network data over point-to-point links, in simple words it provides TCP/IP across a serial link. Over internet you can find lot of information over PPP and I am not going to discuss here. 
This post mainly focuses on configuration PPP services on a embedded device running Linux. I choose an ARM based CPU with buildroot filesystem. 
In one of the designs I worked on, we had UART interface between two ARM CPUs, cross connected like in null-modem cable. Tx line of UART from one CPU is connected to Rx line of the other CPU UART, similarly Rx is connected to Tx with a common ground as shown in the below Figure-1. Both the CPUs are running Linux (4.4.41+) with buildroot filesystem.

 

Figure-1: UART cross connection between two CPUs

UART interface between the CPUs was intended for command/data exchange in the design, I though I can implement a standalone c-application on either side for data transfer and achieve functionality. Realized application will grow in complexity if at all we had to do implement transfer of files between the CPUs over UART or if multiple application want to use the same interface then synchronization comes into picture, considering all these I decided to choose PPP communication protocol. Using PPP will ease all the development efforts as CPUs see each other as a network device with fixed IP, hence you can use all standard network tools like ssh, scp, ping ..etc. and for custom application to do command/data exchange start developing it as a socket program, and works even if the UART is replaced by another physical interface say Ethernet.
We go through a set of steps enabling support right from Kernel, Buildroot & PPP configuration options to filesystem.

Enable PPP in Kernel

from menuconfig "Device Drivers --> Network device support" enable following
CONFIG_PPP=y
CONFIG_PPP_FILTER=y
CONFIG_PPP_ASYNC=y

I have observed below configs are enabled as well, could have be dependencies.
CONFIG_SLHC=y
CONFIG_CRC_CCITT=y
CONFIG_NF_NAT_PROTO_GRE=m
CONFIG_NF_NAT_PPTP=m
CONFIG_NF_CONNTRACK=y
CONFIG_NF_CONNTRACK_PROCFS=y
CONFIG_NF_CT_PROTO_GRE=y
CONFIG_NF_CT_PROTO_SCTP=m
CONFIG_NF_CONNTRACK_PPTP=y 


Figure2: Menuconfig to enable PPP in kernel

Enable PPP in Buildroot

from menuconfig "Target packages --> Networking applications" enable "pppd"


Figure3: Menuconfig to enable PPP service in buildroot

Enabling PPP Communication

One of the CPU is regarded as server say CPU-1 and the other as client say CPU-2. UART device node on CPU-1 is "/dev/ttyS1" and on that of CPU-2 is "/dev/ttyS0". In Linux PPP is implemented by "pppd" daemon. All its configuration files are available at "/etc/ppp", in this processes we will either create or modifying the following list of files.
  • /etc/ppp/options
    • Contains all general configuration options of PPP service
  • /etc/ppp/options.ttyS1
    • Contains PPP options specific to UART connection over /dev/ttyS1
  • /etc/ppp/pap-secrets
    • Contains authentication information

Server Configurations (on CPU-1)

Note: The lines starting with a "#" are comments.

$ vi /etc/ppp/options

#/etc/ppp/options
lock
auth                                                                        
login

  • lock : Parameter indicates that a lock file will be created to ensure exclusive access to the serial device.
  • auth: Parameter indicates that the client will need to authenticate itself, it will still use pap-secrets for username & password information during authentication.
  • login: Parameter tell pppd to use the system user names and passwords for authentication.

$ vi /etc/ppp/pap-secrets
 
#/etc/ppp/pap-secrets                                                             
# Secrets for authentication using PAP                                            
# client                 server                  secret         IP addresses      
*                        *                       ""             *

The only line, in the file allows any machine with any IP address to connect to the server without using a password. "login" parameter specified in the "/etc/ppp/options" file makes that the username and password supplied by the client for authorization have to match the "/etc/ppp/pap-secrets" file as well as the system user name and password, so the connection will only succeed after a valid username and password are provided.

$ vi /etc/ppp/options.ttyS1

Options specific to the serial line we are connecting with, are placed in "/etc/ppp/options.ttySn", where n is the number of the serial device. In our case Server/CPU-1 is using "/dev/ttyS1", hence the options go into the file with name "/etc/ppp/options.ttyS1"
 
#/etc/options.ttyS1 
asyncmap 0                                                                   
local                                                                        
silent                                                                       
192.168.0.1:192.168.1.1
require-pap                                                                  
115200
xonxoff

  • local: Indicates modem lines are not used
  • silent: Causes pppd to wait until a connection is made from other side
  • xonxoff: The better flow control is CTS/RTS. However, if you can not do the hardware flow control with the signals CTS and RTS, then use XON/XOFF. In the Figure-1 we are just using Tx & Rx lines only.
  • asyncmap: This parameter is used when software control is used in conjunction with xonxoff, please refer man page.
  • 192.168.0.1:192.168.1.1 This entry specifies the local and remote IP address to be assigned after the link is up. Server/CPU-1 is given IP 192.168.0.1 and the Client/CPU-2 is given IP 192.168.1.1.
  • 115200: Specifies the  baud-rate on serial-link.

Client Configurations (on CPU-2)

On client side it is pretty easy, following are the list of files 

$ vi /etc/ppp/options

#/etc/ppp/options
lock

$ vi /etc/ppp/pap-secrets
 
# Secrets for authentication using PAP                                              
# client                 server                  secret                IP addresses 
root    *    root         
#

So user "root" uses password "root"

$ vi /etc/ppp/options.ttyS0

Options specific to the serial line we are connecting with, are placed in "/etc/ppp/options.ttySn", where n is the number of the serial device. In our case Server/CPU-1 is using "/dev/ttyS1", hence the options go into the file with name "/etc/ppp/options.ttyS1"
 
#/etc/options.ttyS0 
115200                                                                   
local                                                                       
xonxoff
user root
noauth

now that all configuration files are in place, its time to run the pppd services on CPU-1 & CPU-2

Running PPPD Services on Server & Client

It is understood that you have serial console access to shell of both CPU using the popular utilities like gtkterm or cutecome .etc. 

 

Server Side

On CPU-1 that is server,  run the pppd service in background as shown below

# pppd /dev/ttyS1 nodetach &

You see the following output, server is now waiting indefinitely for clients request.

# pppd /dev/ttyS1 nodetach & 
# Using interface ppp0
Connect: ppp0 <--> /dev/ttyS1

Client Side

On CPU-2 that is client, run the pppd service in background as shown below.

# pppd /dev/ttyS0 nodetach &

You see the following output, client has established the connection with server and has obtained the IP-address as 192.168.1.1.

# pppd /dev/ttyS0 nodetach &
# Using interface ppp0
Connect: ppp0 <--> /dev/ttyS0
Warning - secret file /etc/ppp/pap-secrets has world and/or group access
Warning - secret file /etc/ppp/pap-secrets has world and/or group access
Remote message: Session started successfully
PAP authentication succeeded
local  IP address 192.168.1.1
remote IP address 192.168.0.1

After the client established connection with server, following is the server log with local IP assigned to 192.168.0.1 and client IP over ppp0 interface assigned to 192.168.1.1

#Warning - secret file /etc/ppp/pap-secrets has world and/or group access
Warning - secret file /etc/ppp/pap-secrets has world and/or group access
user root logged in on tty ttyS4 intf ppp0
PAP peer authentication succeeded for root
local  IP address 192.168.0.1
remote IP address 192.168.1.1

You can now ping client from server and vice versa

On server side

# ifconfig ppp0
ppp0      Link encap:Point-to-Point Protocol  
          inet addr:192.168.0.1  P-t-P:192.168.1.1  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:91 errors:0 dropped:0 overruns:0 frame:0
          TX packets:91 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3 
          RX bytes:4907 (4.7 KiB)  TX bytes:4904 (4.7 KiB)
#  # ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1): 56 data bytes
64 bytes from 192.168.1.1: seq=0 ttl=64 time=16.590 ms
64 bytes from 192.168.1.1: seq=1 ttl=64 time=16.637 ms
^C
--- 192.168.1.1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 16.590/16.613/16.637 ms
#

On client side

# ifconfig ppp0
ppp0      Link encap:Point-to-Point Protocol  
          inet addr:192.168.1.1  P-t-P:192.168.0.1  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:103 errors:0 dropped:0 overruns:0 frame:0
          TX packets:103 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3 
          RX bytes:5546 (5.4 KiB)  TX bytes:5549 (5.4 KiB)
# ping 192.168.0.1
PING 192.168.0.1 (192.168.0.1): 56 data bytes
64 bytes from 192.168.0.1: seq=0 ttl=64 time=16.592 ms
64 bytes from 192.168.0.1: seq=1 ttl=64 time=16.354 ms
64 bytes from 192.168.0.1: seq=2 ttl=64 time=16.527 ms
^C
--- 192.168.0.1 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 16.354/16.491/16.592 ms
# 

With this you can use any network tools for communication and data transfer between two CPUs. Using PPP has eased lot of development efforts. 

Similarly you can have multiple clients to server as shown below.

 

In this case you have to create "options.ttyS4" on server side for ppp1 interface to client-2 & all set of files "options, options.ttyS0 & pap-secrets" on client side. Here client-2 also uses ttyS0,  interfaced with ttyS4 of server CPU. On server you have to run another "pppd" service for client-2 "pppd /dev/ttyS4 nodetach &"

 

Following link helped me during my understanding

Link1

 

Any queries please drop a comment!!

2 comments: