Published © MIT

Distributed Emergency Communication System

A rapidly deployable distributed Wi-Fi IEEE 802.11s mesh communication network with cellular modem Internet access for emergency disasters.

IntermediateFull instructions provided2 days9,123
Distributed Emergency Communication System

Things used in this project

Hardware components

Raspberry Pi Zero Wireless
Raspberry Pi Zero Wireless
×1
Hologram Nova
Hologram Nova
×1
Micro USB Cable Hub
×1
Ralink RT5572 USB Wi-Fi adapter
×1
MG Chemicals Nickel Conducting Paint
×1

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)

Story

Read more

Custom parts and enclosures

Antenna Stand

Antenna 3D model

Raspbian sdcard image zipfile

2GB Raspbian "stretch" image zipfile
- updated Linux 4.14.13 kernel
- hostapd & wpa_supplicant with mesh enabled and KRACK attack patches
- systemd configured to bring up mesh & AP networking
- see /usr/src directory for source code

Code

Network configuration script

SH
This script configures the network devices and initializes the firewall.
#!/bin/bash -x
##
##    Copyright (c) 2018 by Droidifi LLC.

##    2018-01-01 Jim Ewing      <jim@droidifi.com>

##    network_setup.sh
##    prototype mesh network startup code

/bin/echo "running network_setup.sh"

## start user configurable parameters ##

# set channel value here -> frequency & band are set automatically
CHANNEL=1  # channels 1-11 for 2.4 GHz, 34-161 for 5 GHz (N America)
HT=HT20    # HT40+ or HT40- for wide channels in 5 GHz band, otherwise HT20
REGION=US  # Two-letter Wifi region code
POWER=2000 # 100 - 2000 in units of mBm, (1 - 20 dBm)

## end user configurable parameters ##

declare -a freq_g=('2412' '2417' '2422' '2427' '2432' '2437' '2442' '2447' '2452' '2457' '2462' '2467' '2472' '2484')
declare -a channel_g=('1' '2' '3' '4' '5' '6' '7' '8' '9' '10' '11' '12' '13' '14')
declare -a freq_a=('5080' '5170' '5180' '5190' '5200' '5210' '5220' '5230' '5240' '5250' '5260' '5270' '5280' '5290' '5300' '5310' '5320' '5500' '5510' '5520' '5530' '5540' '5550' '5560' '5570' '5580' '5590' '5600' '5610' '5620' '5630' '5640' '5660' '5670' '5680' '5690' '5700' '5710' '5720' '5745' '5755' '5765' '5775' '5785' '5795' '5805' '5825' '4915' '4920' '4925' '4935' '4940' '4945' '4960' '4980')
declare -a channel_a=('16' '34' '36' '38' '40' '42' '44' '46' '48' '50' '52' '54' '56' '58' '60' '62' '64' '100' '102' '104' '106' '108' '110' '112' '114' '116' '118' '120' '122' '124' '126' '128' '132' '134' '136' '138' '140' '142' '144' '149' '151' '153' '155' '157' '159' '161' '165' '183' '184' '185' '187' '188' '189' '192' '196')

FREQ=2422  # set below from CHANNEL value
BAND=g     # set below from CHANNEL value

BRIDGE_DEV=br0
PPP_DEV=ppp0
AP_DEV=wlan0   ## internal Pi wlan device used for AP
PHY_AP=phy0
WLAN_DEV=wlan1 ## USB dongle used for mesh device
MESH_DEV=mesh0
PHY_MESH=phy1 

WPA_SUPPLICANT=/usr/local/sbin/wpa_supplicant
WPA_SUPPLICANT_CONF=/etc/wpa_supplicant/wpa_supplicant.conf

HOSTAPD=/usr/local/bin/hostapd
HOSTAPD_CONF=/etc/hostapd/hostapd.conf

# set LAN IP address to IP derived from Wifi permanent MAC address
/usr/local/sbin/setip `cat /sys/class/ieee80211/$PHY_MESH/addresses | awk 'NR==1{print $1}' | grep -o -E '([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}'` -f /etc/rc.$BRIDGE_DEV.ipaddr

LAN_IP=`/bin/cat /etc/rc.$BRIDGE_DEV.ipaddr`

# save IP octects to stings for later use
oct1=$(echo $LAN_IP | tr "." " " | awk '{ print $1 }')
oct2=$(echo $LAN_IP | tr "." " " | awk '{ print $2 }')
oct3=$(echo $LAN_IP | tr "." " " | awk '{ print $3 }')
oct4=$(echo $LAN_IP | tr "." " " | awk '{ print $4 }')

# convert channel to freq
i=0
for ch in "${channel_g[@]}"
do
    if [ $ch == $CHANNEL ]
        then
            FREQ=${freq_g[$i]}
            BAND=g
    fi
#     echo "g channel " ${channel_g[$i]} " freq " ${freq_g[$i]}
    i=$[ $i + 1 ]
done

i=0
for ch in "${channel_a[@]}"
do
    if [ $ch == $CHANNEL ]
        then
            FREQ=${freq_a[$i]}
            BAND=a
    fi
#     echo "a channel " ${channel_a[$i]} " freq " ${freq_a[$i]}
    i=$[ $i + 1 ]
done

echo "band "$BAND" channel "$CHANNEL" freq "$FREQ" "$HT" power "$POWER

# kill Wifi network daemons
/usr/bin/killall wpa_supplicant 2>&1 > /dev/null
/usr/bin/killall hostapd 2>&1 > /dev/null
/usr/bin/killall pppd 2>&1 > /dev/null

# down all interfaces, tear down bridge
/sbin/ip link set $BRIDGE_DEV down 2>&1 > /dev/null
/sbin/brctl delif $BRIDGE_DEV $PPP_DEV 2>&1 > /dev/null
/sbin/brctl delif $BRIDGE_DEV $AP_DEV 2>&1 > /dev/null
/sbin/brctl delif $BRIDGE_DEV $MESH_DEV 2>&1 > /dev/null
/sbin/brctl delbr $BRIDGE_DEV 2>&1 > /dev/null
/sbin/ip link set $AP_DEV down 2>&1 > /dev/null
/sbin/ip link set $MESH_DEV down 2>&1 > /dev/null
/sbin/iw $MESH_DEV del 2>&1 > /dev/null

# set power level
/sbin/iw phy $PHY_AP set txpower fixed $POWER
/sbin/iw phy $PHY_MESH set txpower fixed $POWER

hostname mesh-"$oct1-$oct2-$oct3-$oct4"

# set region
/sbin/iw reg set $REGION

# bring up 802.11s mesh interface
/sbin/iw dev $WLAN_DEV interface add $MESH_DEV type mp
/sbin/ip link set $MESH_DEV up
/sbin/ip link set $MESH_DEV down

/sbin/iw dev $AP_DEV set type managed

# create bridge device
/sbin/brctl addbr $BRIDGE_DEV

# set bridge device address to IP derived from Wifi MAC address
/sbin/ip addr add $LAN_IP/16 dev $BRIDGE_DEV
/bin/ip link set $BRIDGE_DEV up

# enable forwarding
/bin/echo 1 > /proc/sys/net/ipv4/ip_forward

# bring up PPP device and see if we are connected to an external DHCP server (means we are a GW)
pppd file /etc/ppp/options
/bin/sleep 5
/sbin/dhclient -nw $PPP_DEV
/bin/sleep 7

STATE=$(/sbin/ip r | /bin/grep "default dev $PPP_DEV" | /usr/bin/cut -d ' ' -f 3)
if [ -z $STATE ]
then
  /bin/echo "setting up bridge to route to other nodes"
  /sbin/ip ro add default dev $BRIDGE_DEV
else
  /bin/echo "setting up $PPP_DEV gateway"
  /sbin/iw $MESH_DEV set mesh_param mesh_hwmp_rootmode=4
  /sbin/iw $MESH_DEV set mesh_param mesh_gate_announcements=1
  /bin/echo 1 > /proc/sys/net/ipv4/conf/$BRIDGE_DEV/proxy_arp
fi

# run firewall script
/usr/local/sbin/firewall.sh

# enable bridge STP protocol to prevent loops
/sbin/brctl stp $BRIDGE_DEV on

# set mesh frequency in config file
/bin/sed -i 's/frequency=.*$/frequency='$FREQ'/' $WPA_SUPPLICANT_CONF

# start mesh daemon and add $MESH_DEV device to bridge
$WPA_SUPPLICANT -Dnl80211 -i$MESH_DEV -c $WPA_SUPPLICANT_CONF -B
/bin/sleep 5

/sbin/ip link set $MESH_DEV up

# make sure bridge device and mesh device have same MAC addresses
/sbin/ip link set dev $BRIDGE_DEV address `/sbin/ifconfig  $MESH_DEV | grep -o -E '([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}'`

# set wlan device
/bin/sed -i 's/interface=.*$/interface='$AP_DEV'/' $HOSTAPD_CONF

# set bridge device
/bin/sed -i 's/bridge=.*$/bridge='$BRIDGE_DEV'/' $HOSTAPD_CONF

# set AP SSID to ECM-MESH in config file
/bin/sed -i 's/ssid=.*$/ssid=ECM-MESH/' $HOSTAPD_CONF

# set AP channel in config file
/bin/sed -i 's/channel=.*$/channel='$CHANNEL'/' $HOSTAPD_CONF

# set AP frequency band in config file
/bin/sed -i 's/hw_mode=.*$/hw_mode='$BAND'/' $HOSTAPD_CONF

# start AP daemon
$HOSTAPD $HOSTAPD_CONF -B
/bin/sleep 1

# add mesh interface to bridge
/sbin/brctl addif $BRIDGE_DEV $MESH_DEV

/sbin/ifconfig $BRIDGE_DEV up

# set nameservers to Google's so we always have DNS available
/bin/echo "nameserver 8.8.8.8" > /etc/resolv.conf
/bin/echo "nameserver 8.8.4.4" >> /etc/resolv.conf

# force any URL resolves to DNSMasq to our IP address
/usr/sbin/service dnsmasq restart

exit 0

Firewall script

SH
Shell script to initialize the firewall
#!/bin/sh -x

## Copyright (c) 2018 by Droidifi LLC.

##    2018-12-01 Jim Ewing      <jim@droidifi.com>

# ECM-MESH Firewall

EBTABLES=/sbin/ebtables
IP6TABLES=/sbin/ip6tables
IPTABLES=/sbin/iptables
IFCONFIG=/sbin/ifconfig
BRCTL=/sbin/brctl

LAN_IF=br0
LAN_IP=`/bin/cat /etc/rc.br0.ipaddr`
LAN_NET=169.254.0.0
LAN_MASK=16

WAN_IF=ppp0
WAN_IP_MASK=`ip -o -f inet addr show $WAN_IF | awk '/scope global/ {print $4}'`
WAN_MAC=`$IFCONFIG $WAN_IF | /bin/grep -o -E '([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}'`

MESH_IF=mesh0
AP_IF=wlan0

BR_IF=br0
BR_STP=off

# force bridge interfaces to L3 iptables filters
for T in filter nat broute; do
  $EBTABLES -t $T -F
  $EBTABLES -t $T -X
done

# do not allow ipv6
$IP6TABLES -F
$IP6TABLES -X
$IP6TABLES -F -t nat
$IP6TABLES -F -t mangle
$IP6TABLES -P INPUT DROP
$IP6TABLES -P FORWARD DROP
$IP6TABLES -P OUTPUT DROP

# ipv4 rules
for T in filter nat mangle; do
  $IPTABLES -t $T -F
  $IPTABLES -t $T -X
done
$IPTABLES -P INPUT ACCEPT
$IPTABLES -P FORWARD ACCEPT
$IPTABLES -P OUTPUT ACCEPT

# begin paranoid protection rules

# defend against incoming malformed XMAS Packets:
$IPTABLES -A INPUT -p tcp --tcp-flags ALL ALL -j DROP

# defend against outgoing malformed XMAS Packets:
$IPTABLES -A OUTPUT -p tcp --tcp-flags ALL ALL -j DROP

# defend against outgoing malformed Packets:
$IPTABLES -A OUTPUT -p tcp --tcp-flags ALL NONE -j DROP

# defend against incoming malformed NULL Packets:
$IPTABLES -A INPUT -p tcp --tcp-flags ALL NONE -j DROP

# drop invalid SYN Packets:
$IPTABLES -A OUTPUT -p tcp --tcp-flags ALL ACK,RST,SYN,FIN -j DROP
$IPTABLES -A OUTPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
$IPTABLES -A OUTPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP

# limit UDP flooding
$IPTABLES -A INPUT -p udp -m limit --limit 10/s -j ACCEPT

# defend against incoming fragments:
$IPTABLES -A INPUT -f -j DROP

# new incoming connections must be SYN Packets; otherwise drop them:
$IPTABLES -A INPUT -p tcp ! --syn -m state --state NEW -j DROP

# drop ping from address-mask-request
$IPTABLES -A INPUT -p icmp -m icmp --icmp-type address-mask-request -j DROP

# drop ping from timestamp-request
$IPTABLES -A INPUT -p icmp -m icmp --icmp-type timestamp-request -j DROP

# rate limit ping
$IPTABLES -A INPUT -p icmp -m icmp --icmp-type echo-request -m limit --limit 1/second -j ACCEPT

# drop invalid packets
$IPTABLES -A INPUT -m state --state INVALID -j DROP

# hide from traceroute tools
$IPTABLES -A PREROUTING -t mangle ! -d $LAN_IP -j TTL --ttl-inc 1

# end paranoid protection rules

# begin AP rules #

# accept AP client DHCP requests
$IPTABLES -A INPUT    -p udp -m physdev --physdev-in $AP_IF -m pkttype --pkt-type broadcast --dport 67 -j ACCEPT
$IPTABLES -A FORWARD  -p udp -m physdev --physdev-in $AP_IF -m pkttype --pkt-type broadcast --dport 67 -j ACCEPT
$IPTABLES -A INPUT    -p udp -m physdev --physdev-in $AP_IF --dport 67:68 -j ACCEPT
$IPTABLES -A FORWARD  -p udp -m physdev --physdev-in $AP_IF --dport 67:68 -j ACCEPT
$IPTABLES -A FORWARD  -p udp -m physdev --physdev-in $AP_IF --sport 67:68 -j ACCEPT
$IPTABLES -A OUTPUT   -p udp --sport 67:68 -j ACCEPT

$IPTABLES -A FORWARD  -p udp -m physdev --physdev-in $AP_IF --dport 80 -j ACCEPT
$IPTABLES -A FORWARD  -p udp -m physdev --physdev-in $AP_IF --dport 443 -j ACCEPT

# AP web redirect rule - enable for captive portal
# $IPTABLES -t nat -A PREROUTING -i $LAN_IF -p tcp ! -d $LAN_NET/$LAN_MASK --dport http  -m physdev --physdev-in $AP_IF -j DNAT --to-destination $LAN_IP:80
# AP web redirect rule
# $IPTABLES -t nat -A PREROUTING -i $LAN_IF -p tcp ! -d $LAN_NET/$LAN_MASK --dport https -m physdev --physdev-in $AP_IF -j DNAT --to-destination $LAN_IP:80

# force AP to use local DNS server
$IPTABLES -t nat -A PREROUTING -i $LAN_IF -p udp --dport 53 -m physdev --physdev-in $AP_IF -j DNAT --to-destination $LAN_IP:53
$IPTABLES -t nat -A PREROUTING -i $LAN_IF -p tcp --dport 53 -m physdev --physdev-in $AP_IF -j DNAT --to-destination $LAN_IP:53

# drop AP connections outside of the local LAN - enable for captive portal
# $IPTABLES -A FORWARD -i $LAN_IF -p tcp ! -d $LAN_NET/$LAN_MASK -m physdev --physdev-in $AP_IF -j DROP

# end AP rules #

# INPUT tables #

# stateful packets allowed
$IPTABLES -A INPUT -m state --state INVALID -j DROP
$IPTABLES -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# allow packets from the private NAT LAN
$IPTABLES -A INPUT -i $LAN_IF -s $LAN_IP/$LAN_MASK -j ACCEPT

# allow packets from loopback
$IPTABLES -A INPUT -i lo -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT
 
# Connections allowed to firewall from WAN
# ICMP
$IPTABLES -A INPUT -p icmp -j ACCEPT
 
# allow IP packets from the WAN
if [ ! -z "$WAN_IP_MASK" ] 
then
    $IPTABLES -A INPUT -s $WAN_IP_MASK -j ACCEPT
fi

# SSH
$IPTABLES -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -m recent --set --name SSH
$IPTABLES -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -m recent --update --seconds 60 --hitcount 4 --rttl --name SSH -j DROP

# Deny the rest
$IPTABLES -A INPUT -j DROP

# OUTPUT tables #

# allow ping
$IPTABLES -A OUTPUT -o $WAN_IF -p icmp --icmp-type 0 -j ACCEPT
$IPTABLES -A OUTPUT -o $WAN_IF -p icmp --icmp-type 8 -j ACCEPT
$IPTABLES -A OUTPUT -o $WAN_IF -p icmp -j DROP

# apply NAT to local packets headed to the WAN
# $IPTABLES -t nat -A POSTROUTING -o $WAN_IF -j MASQUERADE
$IPTABLES -t nat -A POSTROUTING -o $WAN_IF -s $LAN_IP/$LAN_MASK -j MASQUERADE

# FORWARD tables #

# statefull packets allowed
$IPTABLES -A FORWARD -m state --state INVALID -j DROP
$IPTABLES -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
$IPTABLES -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
 
# allow IP packets from the LAN to the LAN
if [ ! -z "$WAN_IP_MASK" ] 
then
    $IPTABLES -A FORWARD -s $LAN_NET/$LAN_MASK -d $WAN_IP_MASK -j ACCEPT
fi 

# allow LAN to LAN
$IPTABLES -A FORWARD -i $LAN_IF -o $LAN_IF -j ACCEPT
 
# allow outbound connections
$IPTABLES -A FORWARD -i $LAN_IF -o $WAN_IF -j ACCEPT
 
# Deny the rest
$IPTABLES -A FORWARD -j DROP

Zeroconfig generator

C/C++
This utility generates a Zeroconfig 169.254.x.x/16 address from a hash of a device MAC address.
// Copyright (c) 2018 by Droidifi LLC.  All rights reserved.

// @file        setip.c
// @author      Jim Ewing jim@droidifi.com
// @description set an IP address to a hash of a mac address


#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <openssl/sha.h>

#define USAGE "setip XX:XX:XX:XX:XX:XX [-f filename]\n\nreturn unique ip address from a mac address hash\n\n"

#define MAX_BUF 255
#define MAC_LEN 6

// @brief       create a cryptographic 16-bit hash value that meets the strict avalanche criterion (SAC), hash algorithm modifed from code Copyright (C) 2012 Zilong Tan (eric.zltan@gmail.com)
// @param       input, array of unsigned bytes
// @param       len, length of byte array
// @return      uint16_t hash value
#define mix(h) ({                                       \
                        (h) ^= (h) >> 23;               \
                        (h) *= 0x2127599bf4325c37ULL;   \
                        (h) ^= (h) >> 47; })
                        
uint16_t hash16(uint8_t *input, int32_t len)
{
    uint64_t h=(((uint64_t)rand()) << 32) + rand();
    uint64_t v=0;
    const uint64_t  m = 0x880355f21e6d1965ULL;
    uint8_t  hash[SHA256_DIGEST_LENGTH];
    int32_t i = 0;

    SHA256_CTX sha256;
    SHA256_Init(&sha256);
    SHA256_Update(&sha256, input, len);
    SHA256_Final(hash, &sha256);
    
    for(i = 0; i < SHA256_DIGEST_LENGTH; i++)
    {
        v = hash[i];
        h ^= mix(v);
        h *= m;
    }

    switch (len & 7) {
        case 7: v ^= (uint64_t)hash[6] << 48;
        case 6: v ^= (uint64_t)hash[5] << 40;
        case 5: v ^= (uint64_t)hash[4] << 32;
        case 4: v ^= (uint64_t)hash[3] << 24;
        case 3: v ^= (uint64_t)hash[2] << 16;
        case 2: v ^= (uint64_t)hash[1] << 8;
        case 1: v ^= (uint64_t)hash[0];
                h ^= mix(v);
                h *= m;
    }

    h = mix(h);
    return (uint16_t)(h - (h>>48));
}

// @brief       generate a unique ipv4 address in the 169.254.x.x/16 address space from a MAC address string
// @param       see usage
// @return      0 on success, -1 on failure
int main(int argc, char** argv)
{
    int opt=0;
    FILE *fp=NULL;
    char fname[MAX_BUF]={0};
    uint32_t values[MAC_LEN];
    uint8_t mac[MAC_LEN];
    char tmp[32]={0};
    int i=0;
    int idx=1;
    uint16_t ip=0;
    
    if(argc < 2){
        fprintf(stderr, USAGE);
        exit(EXIT_FAILURE);  
    }
    
    while ((opt = getopt(argc, argv, "f:")) != -1) {
        switch (opt) 
        {
            case 'f':
                memset(fname, 0, MAX_BUF);
                strncpy((char*)fname, optarg, MAX_BUF-1);
                idx=3;
                break;
            default:
                fprintf(stderr, "%c\n", opt);
                fprintf(stderr, USAGE);
                exit(EXIT_FAILURE);
                break;
        }
    }

    if( strchr(argv[idx], ':') && 
        MAC_LEN == sscanf( argv[idx], "%x:%x:%x:%x:%x:%x", &values[0], &values[1], &values[2], &values[3], &values[4], &values[5]) ){
        for( i = 0; i < MAC_LEN; ++i )
        {
            mac[i] = (uint8_t) values[i];
        }
    }
    else if( strchr(argv[idx], '-') && 
        MAC_LEN == sscanf( argv[idx], "%x-%x-%x-%x-%x-%x", &values[0], &values[1], &values[2], &values[3], &values[4], &values[5]) ){
        for( i = 0; i < MAC_LEN; ++i )
        {
            mac[i] = (uint8_t) values[i];
        }
    }
    else{
        fprintf(stderr, "%s", USAGE);
        exit(EXIT_FAILURE);
    }
    
    ip = hash16(mac, MAC_LEN);
        
    snprintf(tmp, sizeof(tmp)-1, "169.254.%d.%d", (int)((ip >> 8) & 0x00FF), (int)(ip & 0x00FF));
    
    if(strlen(fname) > 0){
        fp = fopen(fname, "w+");
        if(fp){
            fprintf(fp, "%s", tmp);
            fclose(fp);
        }
    }
    else{
        printf("%s", tmp);
    }
    
    return EXIT_SUCCESS;
}

wpa_supplicant.conf file

INI
Copy to /etc/wpa_supplicant/wpa_supplicant.conf
ctrl_interface=/var/run/wpa_supplicant
user_mpm=1
# Mesh network with no authentication
network={
        ssid="ecm_mesh"
        mode=5
        frequency=2412
        key_mgmt=NONE
}

hostapd.conf

INI
Copy to /etc/hostapd/hostapd.conf
##    2015-01-01 Jim Ewing      <jim@droidifi.com>
##    /etc/hostapd/hostapd.conf
##    prototype mesh network AP startup code for hostapd daemon

ctrl_interface=wlan0
ctrl_interface_group=0
interface=wlan0
bridge=br0
country_code=US
ssid=ECM-MESH
channel=1
ht_capab=[SHORT-GI-40][SHORT-GI-20][RX-STBC1][TX-STBC]
ieee80211n=1
ieee80211d=0
ieee80211h=0
hw_mode=g
beacon_int=100
pmk_r1_push=1

### WMM
wmm_enabled=1
uapsd_advertisement_enabled=1
wmm_ac_bk_cwmin=4
wmm_ac_bk_cwmax=10
wmm_ac_bk_aifs=7
wmm_ac_bk_txop_limit=0
wmm_ac_bk_acm=0
wmm_ac_be_aifs=3
wmm_ac_be_cwmin=4
wmm_ac_be_cwmax=10
wmm_ac_be_txop_limit=0
wmm_ac_be_acm=0
wmm_ac_vi_aifs=2
wmm_ac_vi_cwmin=3
wmm_ac_vi_cwmax=4
wmm_ac_vi_txop_limit=94
wmm_ac_vi_acm=0
wmm_ac_vo_aifs=2
wmm_ac_vo_cwmin=2
wmm_ac_vo_cwmax=3
wmm_ac_vo_txop_limit=47
wmm_ac_vo_acm=0

### TX queue parameters
tx_queue_data3_aifs=7
tx_queue_data3_cwmin=15
tx_queue_data3_cwmax=1023
tx_queue_data3_burst=0
tx_queue_data2_aifs=3
tx_queue_data2_cwmin=15
tx_queue_data2_cwmax=63
tx_queue_data2_burst=0
tx_queue_data1_aifs=1
tx_queue_data1_cwmin=7
tx_queue_data1_cwmax=15
tx_queue_data1_burst=3.0
tx_queue_data0_aifs=1
tx_queue_data0_cwmin=3
tx_queue_data0_cwmax=7
tx_queue_data0_burst=1.5

pppd options

INI
Copy to /etc/ppp/options
/dev/ttyACM0
9600
crtscts
noauth
noipdefault
usepeerdns
defaultroute
connect "/usr/sbin/chat -v -f /etc/ppp/chatscripts/hologram.chat"

Hologram pppd chatscript

INI
Copy to /etc/ppp/chatscripts/hologram.chat
# Chat script for modems using Hologram SIM card
# See hologram.io for more information

ABORT 'BUSY'
ABORT 'NO CARRIER'
ABORT 'VOICE'
ABORT 'NO DIALTONE'
ABORT 'NO DIAL TONE'
ABORT 'NO ANSWER'
ABORT 'DELAYED'
TIMEOUT 12
REPORT CONNECT

"" AT
OK ATH
OK ATZ
OK ATQ0
OK AT+CGDCONT=1,"IP","hologram"
OK ATDT*99***1#
CONNECT ''

Credits

Thanks to Lucas Ewing and Ryan Ewing.

Comments