1. 程式人生 > >嵌入式Linux利用ppp實現4G模組聯網

嵌入式Linux利用ppp實現4G模組聯網

之前做專案時需要用到SIM7100模組,便快速瞭解下ppp撥號,實現了功能,但是功能雖然實現了,卻依然有許多疑問,這段時間有點時間,打算更加詳細的研究下。

編譯ppp2.4.5

  • 下載:官方地址
  • 編譯:
    #1.解壓ppp程式包
    tar -xzvf ppp-2.4.5.tar.gz
    #2.進入並生成Makefile
    cd ./ppp-2.4.5
    ./config
    #3.指定交差編譯工具make
    make CC=arm-linux-gcc
    

配置核心

Device Drivers --->Network device support---> <*>   PPP (point-to-point protocol) support 

menuconfig

ppp安裝

以上編譯過程將會生成pppd、pppdump、pppstats、chat四個執行程式,將他們複製到開發平臺下的/usr/sbin/中。

chat:調變解調器的自動對話指令碼,Chat程式定義了一個計算機和調變解調器之間對話交流,其主要目的是用來在本地PPPD和遠端PPPD程式之間建立連線(簡單說就是與4G模組進行AT命令互動的流程表,最終實現與ISP運營商的連線)。

pppd:點對點協議守護程序,其功能為實現ppp策略性的內容,包括所有鑑權、壓縮/解壓和加密/解密等擴充套件功能的控制協議。

pppdump:將使用pppd記錄選項編寫的檔案轉換為人類可讀的格式。

pppstats:顯示PPP連線狀態。pppstats(point to point protocol status)。

撥號流程簡圖

menuconfig

指令碼配置

在開發平臺上建立兩個資料夾,並拷貝ppp.2.4.5資料夾中的chap-secrets、pap-secrets指令碼至/etc/ppp資料夾。

mkdir /etc/ppp
mkdir /etc/ppp/peers
cp ./chap-secrets ./pap-secrets /etc/ppp
# 順便建立一下ip-up、ip-down指令碼
  • pppd配置檔案介紹

    pppd的引數略多啊,具體可以自己man一下或者點選這裡檢視。
    這裡我介紹下我用的,配置檔名稱暫定為“gprs”

    # /etc/ppp/peers/gprs
    # This is pppd script for China Mobile, used SIMCOM SIM7100C Module
    # Usage: root>pppd call gprs
    # Interface should be used is the interface which connects physics interface of SIM7100C Module
    
    # ttyname 串列埠埠,若非以”/“開頭,則會自動補充”/dev/“
    /dev/ttyUSB3
    
    # speed 串列埠波特率
    115200
    
    #硬體流控
    crtscts
    
    # 調變解調器模式
    modem
    
    # 無需身份驗證
    noauth
    
    # 不要求使用chap授權
    refuse-chap
    
    # 不要求使用mschap授權
    refuse-mschap
    
    # 不要求使用mschap-v2授權
    refuse-mschap-v2
    
    # 除錯模式 pppd將以可讀形式記錄傳送或接收的所有控制資料包的內容
    debug
    
    # 前臺執行
    nodetach
    #hide-password
    
    # 向ISP請求2個dns伺服器地址。這兩個地址將以DNS1與DNS2兩個環境變數傳送到/etc/ppp/ip-up指令碼中,並且將環境變USEPEERDNS量置為1
    usepeerdns
    
    # 禁用本地ip,由ISP提供
    noipdefault
    
    # 新增ISP閘道器至路由表,作為預設路由
    defaultroute
    
    # 使用者名稱
    user "cmnet"
    
    0.0.0.0:0.0.0.0
    
    #ipcp-accept-local
    #ipcp-accept-remote
    
    # 使能一下兩個選項可以實現ppp掉線自動重播
    # lcp連線失敗嘗試次數
    lcp-echo-failure 6
    
    # lcp echo傳送間隔
    lcp-echo-interval 10
    
    # 禁用壓縮控制協議ccp
    #noccp
    
    # 禁用Van  Jacobson格式的tcp/ip報頭
    #novj
    
    
    #novjccomp
    
    # 連線終止後不要退出,而是重新嘗試連線,連線次數收到maxfail限制
    persist
    
    # 連線最大嘗試次數,0無限制
    #maxfail
    
    # 啟動ppp協議前,進行硬體撥號
    connect '/usr/sbin/chat -s -v -f /etc/ppp/gprs-connect-chat'
    
  • chat指令碼

    chat指令碼主要用來通過AT命令完成4G模組的撥號過程,關於其選項含義可以man一下或者點選這裡檢視,下面先介紹下其語法:
    chat最主要語法就是“期望-傳送”,直白點說就是,我期望收到[某某AT響應],若收到,則傳送[某某AT命令]。

    chat還有個常用的關鍵詞為ABORT,這個關鍵詞用於判斷何時終止指令碼,在AT互動過程中,模組發生錯誤,並且輸出一些錯誤資訊時,ABORT可根據設定的詞,停止當前指令碼。

    以下指令碼命名為“gprs-connect-chat”

    #Chat script for China Mobile, used SIMCOM sim7100 TD module.
    
    # 設定響應超時
    TIMEOUT 15
    
    # 若接收到“DELAYED”、“BUSY”、“ERROR”、“NO DIALTONE”、“NO CARRIER”,則退出指令碼
    ABORT "DELAYED"
    ABORT "BUSY"
    ABORT "ERROR"
    ABORT "NO DIALTONE"
    ABORT "NO CARRIER"
    
    # 無期望,直接傳送AT字串
    '' AT
    
    # 以下內容可以根據自己模組提供的AT命令手冊查詢含義
    OK ATS0=0
    OK ATE0V1
    
    # 設定APN,移動、聯通、電信各不相同,見文末表格
    OK AT+CGDCONT=1,"IP","CMNET" 
    # 撥號開啟GPRS服務,號碼移動、聯通、電信各不相同,見文末表格
    OK ATD*99***1#
    
    #期望收到CONNECT
    CONNECT
    
  • ip-up指令碼

    之前的指令碼如果沒有問題,正常的話執行 pppd call gprs 就可以撥號成功,並且ifconfig後可以檢視到ppp0這個網絡卡。但是如果你在撥號之前已經啟用了乙太網eth0,此時指定使用ppp0網絡卡ping指定ip或域名ping -I ppp0 並不能成功,原因有兩個,一個是路由表中的預設閘道器是之前eth0生成的,一個是預設的dns伺服器地址有問題。

  • 解決預設閘道器問題

在pppd指令碼中使能了defaultroute後,pppd會在撥號成功後向路由表中新增一條預設閘道器資訊,但是因為之前已經有一條預設網關了,於是新增失敗,預設閘道器依然是之前eth設定的,因此在pppd call gprs之前我們應該先route del default來刪除預設路由(最好寫個指令碼來實現刪除預設路由–撥號等一系列操作)。

  • 解決dns問題

在pppd指令碼中使能了usepeerdns後,pppd會在撥號成功後,在/etc/ppp下生成resolv.conf,這是ISP運營商提供的dns,我們應該將拷貝或者連線到/etc目錄下,當然這件事就可以交給ip-up來做。

ip-up指令碼:

#!/bin/bash
#ip-up
dns_file="/etc/resolv.conf"

rm "$dns_file"
ln /etc/ppp/resolv.conf "$dns_file"
  • ip-down指令碼

    按照ppp撥號過程中列印資訊可以發現,在退出pppd程序時,會呼叫/etc/ppp/ip-down。因此刪除預設閘道器,恢復dns就交由ip-down指令碼做了。

#!/bin/bash
#ip-down
#set -vx
dns_file="/etc/resolv.conf"

rm $dns_file

cat > "$dns_file" <<EOF
# auto create by ip-down
nameserver 114.114.114.114
nameserver 8.8.8.8
EOF

chmod 755 "$dns_file"

/etc/init.d/networking restart

echo "Set dns for eth0" 

除錯資訊

執行pppd call gprs後成功撥號的除錯列印資訊:

timeout set to 15 seconds
abort on (DELAYED)
abort on (BUSY)
abort on (ERROR)
abort on (NO DIALTONE)
abort on (NO CARRIER)
timeout set to 15 seconds
send (^MAT^M)
expect (OK)
^M
OK
 -- got it

send (ATS0=0^M)
expect (OK)
^M
^M
OK
 -- got it

send (ATE0V1^M)
expect (OK)
^M
^M
OK
 -- got it

send (AT+CGDCONT=1,"IP","CMNET"^M)
expect (OK)
^M
^M
OK
 -- got it

send (ATD*99***1#^M)
expect (CONNECT)
^M
^M
CONNECT
 -- got it

Script /usr/sbin/chat -s -v -f /etc/ppp/gprs-connect-chat finished (pid 21001), status = 0x0
Serial connection established.
using channel 19
Using interface ppp0
Connect: ppp0 <--> /dev/ttyUSB3
Warning - secret file /etc/ppp/pap-secrets has world and/or group access
sent [LCP ConfReq id=0x4 <asyncmap 0x0> <magic 0xc2c88df0> <pcomp> <accomp>]
rcvd [LCP ConfReq id=0x60 <asyncmap 0x0> <auth chap MD5> <magic 0x5742a3f6> <pcomp> <accomp>]
No auth is possible
sent [LCP ConfRej id=0x60 <auth chap MD5>]
rcvd [LCP ConfAck id=0x4 <asyncmap 0x0> <magic 0xc2c88df0> <pcomp> <accomp>]
rcvd [LCP ConfReq id=0x61 <asyncmap 0x0> <magic 0x5742a3f6> <pcomp> <accomp>]
sent [LCP ConfAck id=0x61 <asyncmap 0x0> <magic 0x5742a3f6> <pcomp> <accomp>]
sent [LCP EchoReq id=0x0 magic=0xc2c88df0]
sent [CCP ConfReq id=0x2 <deflate 15> <deflate(old#) 15> <bsd v1 15>]
sent [IPCP ConfReq id=0x4 <compress VJ 0f 01> <addr 0.0.0.0> <ms-dns1 0.0.0.0> <ms-dns2 0.0.0.0>]
rcvd [LCP DiscReq id=0x62 magic=0x5742a3f6]
rcvd [LCP EchoRep id=0x0 magic=0x5742a3f6 c2 c8 8d f0]
rcvd [LCP ProtRej id=0x63 80 fd 01 02 00 0f 1a 04 78 00 18 04 78 00 15 03 2f]
Protocol-Reject for 'Compression Control Protocol' (0x80fd) received
rcvd [IPCP ConfReq id=0x2e]
sent [IPCP ConfNak id=0x2e <addr 0.0.0.0>]
rcvd [IPCP ConfRej id=0x4 <compress VJ 0f 01>]
sent [IPCP ConfReq id=0x5 <addr 0.0.0.0> <ms-dns1 0.0.0.0> <ms-dns2 0.0.0.0>]
rcvd [IPCP ConfReq id=0x2f]
sent [IPCP ConfAck id=0x2f]
rcvd [IPCP ConfNak id=0x5 <addr 10.149.99.154> <ms-dns1 211.136.17.107> <ms-dns2 211.136.20.203>]
sent [IPCP ConfReq id=0x6 <addr 10.149.99.154> <ms-dns1 211.136.17.107> <ms-dns2 211.136.20.203>]
rcvd [IPCP ConfAck id=0x6 <addr 10.149.99.154> <ms-dns1 211.136.17.107> <ms-dns2 211.136.20.203>]
Could not determine remote IP address: defaulting to 10.64.64.64
local  IP address 10.149.99.154
remote IP address 10.64.64.64
primary   DNS address 211.136.17.107
secondary DNS address 211.136.20.203
Script /etc/ppp/ip-up started (pid 21008)
Script /etc/ppp/ip-up finished (pid 21008), status = 0x0

以下為設定了斷線重撥(lcp-echo-failure、lcp-echo-interval)後的列印資訊:

No response to 6 echo-requests   # 6次echo未收到ISP迴應,自動重撥。
Serial link appears to be disconnected.
Connect time 719.4 minutes.
Sent 0 bytes, received 0 bytes.
Script /etc/ppp/ip-down started (pid 29547)   # 呼叫了 /etc/ppp/ip-down 但是我指令碼的未執行
sent [LCP TermReq id=0x5 "Peer not responding"]
Script /etc/ppp/ip-down finished (pid 29547), status = 0x0
sent [LCP TermReq id=0x6 "Peer not responding"]
Connection terminated.
Modem hangup
timeout set to 15 seconds
abort on (DELAYED)
abort on (BUSY)
abort on (ERROR)
abort on (NO DIALTONE)
abort on (NO CARRIER)
timeout set to 15 seconds
send (^MAT^M)
expect (OK)
^M
OK
 -- got it

send (ATS0=0^M)
expect (OK)
^M
^M
OK
 -- got it

send (ATE0V1^M)
expect (OK)
^M
^M
OK
 -- got it

send (AT+CGDCONT=1,"IP","CMNET"^M)
expect (OK)
^M
^M
OK
 -- got it

send (ATD*99***1#^M)
expect (CONNECT)
^M
^M
CONNECT
 -- got it

Script /usr/sbin/chat -s -v -f /etc/ppp/gprs-connect-chat finished (pid 29664), status = 0x0
Serial connection established.
using channel 20
Using interface ppp0
Connect: ppp0 <--> /dev/ttyUSB3
Warning - secret file /etc/ppp/pap-secrets has world and/or group access
sent [LCP ConfReq id=0x7 <asyncmap 0x0> <magic 0xf8a6761> <pcomp> <accomp>]
rcvd [LCP ConfReq id=0x64 <asyncmap 0x0> <auth chap MD5> <magic 0x59d5de84> <pcomp> <accomp>]
No auth is possible
sent [LCP ConfRej id=0x64 <auth chap MD5>]
rcvd [LCP ConfAck id=0x7 <asyncmap 0x0> <magic 0xf8a6761> <pcomp> <accomp>]
rcvd [LCP ConfReq id=0x65 <asyncmap 0x0> <magic 0x59d5de84> <pcomp> <accomp>]
sent [LCP ConfAck id=0x65 <asyncmap 0x0> <magic 0x59d5de84> <pcomp> <accomp>]
sent [LCP EchoReq id=0x0 magic=0xf8a6761]
sent [CCP ConfReq id=0x3 <deflate 15> <deflate(old#) 15> <bsd v1 15>]
sent [IPCP ConfReq id=0x7 <compress VJ 0f 01> <addr 0.0.0.0> <ms-dns1 0.0.0.0> <ms-dns2 0.0.0.0>]
rcvd [LCP DiscReq id=0x66 magic=0x59d5de84]
rcvd [LCP EchoRep id=0x0 magic=0x59d5de84 0f 8a 67 61]
rcvd [LCP ProtRej id=0x67 80 fd 01 03 00 0f 1a 04 78 00 18 04 78 00 15 03 2f]
Protocol-Reject for 'Compression Control Protocol' (0x80fd) received
rcvd [IPCP ConfReq id=0x30]
sent [IPCP ConfNak id=0x30 <addr 0.0.0.0>]
rcvd [IPCP ConfRej id=0x7 <compress VJ 0f 01>]
sent [IPCP ConfReq id=0x8 <addr 0.0.0.0> <ms-dns1 0.0.0.0> <ms-dns2 0.0.0.0>]
rcvd [IPCP ConfReq id=0x31]
sent [IPCP ConfAck id=0x31]
rcvd [IPCP ConfNak id=0x8 <addr 10.42.72.220> <ms-dns1 211.136.17.107> <ms-dns2 211.136.20.203>]
sent [IPCP ConfReq id=0x9 <addr 10.42.72.220> <ms-dns1 211.136.17.107> <ms-dns2 211.136.20.203>]
rcvd [IPCP ConfAck id=0x9 <addr 10.42.72.220> <ms-dns1 211.136.17.107> <ms-dns2 211.136.20.203>]
Could not determine remote IP address: defaulting to 10.64.64.64
local  IP address 10.42.72.220
remote IP address 10.64.64.64
primary   DNS address 211.136.17.107
secondary DNS address 211.136.20.203
Script /etc/ppp/ip-up started (pid 29675)
Script /etc/ppp/ip-up finished (pid 29675), status = 0x0

三大運營商撥號設定

運營商(ISP) APN 撥號號碼 賬號 密碼
中國聯通WCDMA 3GNET *99#
中國移動TD-SCDMA CMNET 981#
中國移動GPRS/EGDE CMNET 99**1#