Lorafwd is a service running on the gateway that implements the GWMP Protocol, also known as Legacy UDP Packet forwarder.
This service works with LoRaD.
lorafwd is running by default with its configuration file /etc/lorafwd.toml
.
The file allows to configure:
The configuration file is in TOML format. Here is an example:
# The LoRa forwarder configuration file.
#
# This configuration file is formatted using the TOML v0.5.0 language:
# https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md
[ gateway ]
# The gateway identifier. Used to identify the gateway inside the network. This
# identifier is 64 bits long. It could be expressed in hexadecimal for better
# readability.
#
# Type: integer
# Example: 1194684 or 0x123abc or 0o4435274 or 0b100100011101010111100
# Default: value of 'EUI64' environment variable (or 0 if not found)
#
#id = 0xFFFFFFFFFFFFFFFF
[ filter ]
# Whether or not an uplink message with a valid CRC will be forwarded.
#
# Type: boolean
# Example: false
# Default: true
#
#crc.valid = true
# Whether or not an uplink message with an invalid CRC will be forwarded.
#
# Type: boolean
# Example: true
# Default: false
#
#crc.invalid = false
# Whether or not an uplink message without CRC will be forwarded.
#
# Type: boolean
# Example: true
# Default: false
#
#crc.none = false
# Whether or not a LoRaWAN downlink will be forwarded as an uplink message.
#
# Type: boolean
# Example: true
# Default: false
#
#lorawan.downlink = false
# Whether or not a LoRaWAN uplink message with a matching device address will
# be forwarded.
#
# Type: string or array of strings using CIDR notation
# Example: [ "0x12000000/8", "!0x12340000/16", "0x34000000/8" ]
# Default: "" (everything allowed)
#
#lorawan.netid = [ "0x24000000/7" ]
# Whether or not a LoRaWAN uplink message with a matching join EUI will
# be forwarded.
#
# Type: string or array of strings using CIDR notation
# Example: [ "0x1200000000000000/8", "!0x1234000000000000/16" ]
# Default: "" (everything allowed)
#
#lorawan.joineui = [ "0x7076FF0001000000/40" ]
# Whether or not a LoRaWAN uplink message with a matching device EUI will
# be forwarded.
#
# Type: string or array of strings using CIDR notation
# Example: [ "0x1200000000000000/8", "!0x1234000000000000/16" ]
# Default: "" (everything allowed)
#
#lorawan.deveui = [ "0x7076FF0000000000/40" ]
# Whether or not a LoRaWAN proprietary message with be forwarded.
#
# Type: boolean
# Example: false
# Default: true
#
#lorawan.proprietary = true
[ database ]
# Whether or not a persistent database will store the incoming messages until
# they will be sent and acknowledged.
#
# Type: boolean
# Example: true
# Default: false
#
#enable = true
# The maximum number of messages allowed to be stored in the database. When
# full the newest message will replace the oldest one.
#
# Type: integer
# Example: 20000
# Default: 200
#
#limit.messages = 200
# The minimum delay between two database fetch. To allow incoming messages
# to be aggregated before to be sent.
#
# Type: integer (in milliseconds)
# Example: 1000
# Default: 100
#
#delay.cooldown = 1000
[ gwmp ]
# The internet host where the gateway should connect. The node can be either a
# fully qualified domain name or an IP address (IPv4 or IPv6).
#
# Type: string
# Example: "myhost.example.com" or "123.45.67.89" or "2001:db8::1234"
# Default: "127.0.0.1"
#
#node = "localhost"
# The timeout in seconds before GWMP services consider that host/node is not connected
#
# Type: integer
# Example: 5
# Default: 3
#
#timeout = 3
# The GWMP services can be a service name (see services(5)) or an integer and,
# in this case, refers to a network port.
# The service where the gateway should push uplink messages.
#
# Type: string or integer
# Example: "https" or 1700
# Default: 1700
#
#service.uplink = 1700
# The service where the gateway should pull downlink messages.
#
# Type: string or integer
# Example: "https" or 1700
# Default: 1700
#
#service.downlink = 1700
# The heartbeat period. Used to keep the firewall open.
#
# Type: integer (in seconds)
# Example: 30
# Default: 10
#
#period.heartbeat = 10
# The statistics period. Used to send statistics.
#
# Type: integer (in seconds)
# Example: 10
# Default: 30
#
#period.statistics = 30
# The number of timed out messages which will automatically trigger a network
# socket restart. Used to monitor the connection.
#
# Type: boolean or integer (false = 0 = disabled) (true = 10)
# Example: 3
# Default: true
#
#autorestart = false
# The maximum datagram size for uplink messages. The datagram includes the GWMP
# header and payload.
#
# Type: integer
# Example: 50000
# Default: 20000
#
#limit.datagram = 65507
# The endpoint to control the LoRa daemon. Used to request statistics.
#
# Type: string
# Example: "tcp://localhost:3333"
# Default: "ipc:///var/run/lora/lorad"
#
#lorad.control = "ipc:///var/run/lora/lorad"
# Tx power used is reported in TX_ACK payload when warn "TX_POWER" field available: txpk_ack.warn and txpk_ack.power
# instead of txpk_ack.error when a tx packet is sent with a power different from the expected one.
#
# Type: boolean
# Example: false
# Default: false
#
#report_tx_power = false
[ api ]
# The API use ZeroMQ as transport layer. More informations about ZeroMQ
# endpoints format can be found here:
#
# http://api.zeromq.org/4-2:zmq-connect
# The endpoints for the uplink channel. Used to receive uplink messages.
#
# Type: string or array of strings
# Example: "tcp://localhost:1111"
# Default: "ipc:///var/run/lora/uplink"
#
#uplink = [ "ipc:///var/run/lora/uplink", "tcp://localhost:1111" ]
# The endpoints for the downlink channel. Used to send downlink messages.
#
# Type: string or array of strings
# Example: "tcp://localhost:2222"
# Default: "ipc:///var/run/lora/downlink"
#
#downlink = [ "ipc:///var/run/lora/downlink", "tcp://localhost:2222" ]
# The endpoints for the control channel. Used to receive control request.
#
# Type: string or array of strings
# Example: "tcp://eth0:4444"
# Default: "ipc:///var/run/lora/lorafwd"
#
#control = [ "ipc:///var/run/lora/lorafwd", "tcp://eth0:4444" ]
# The filters for the uplink channel. Used to subscribe to uplink messages.
#
# The filters can handle raw binary (by using unicode) or keywords. The special
# empty filter ("") subscribe to all incoming messages.
#
# Keywords are case-insensitive and are one of these:
# - "lora"
# - "gfsk" or "fsk"
# - "event" (for ease of use, lorafwd always subscribe to event messages)
#
# Type: string or array of strings
# Example: [ "\u000A", "keyword" ]
# Default: ""
#
#filters = [ "lora", "gfsk" ]
A tool to edit the lorafwd configuration is installed by default. It can be used instead of editing manually the configuration file.
Examples:
sudo lorafwdctl -s gwmp.node mylns.example.com
sudo lorafwdctl gwmp.service.uplink 1234
sudo lorafwdctl gwmp.service.downlink 1234
sudo lorafwdctl filter.crc.invalid true
In the section [gwmp]
of the configuration file, you must configure this 3 parameters:
node
: The internet host where the gateway should connect.service.uplink
: The service where the gateway should push uplink messagesservice.downlink
: The service where the gateway should push downlink messagesThis feature allows to save data consumption by forwarding only LoRaWAN packets from a given DevAddr range.
A DevAddr is the ID used by a LoRaWAN device to communicate on a LoRaWAN network, NetID is a part of this DevAddr.
See Lora Alliance NetID FAQ for further details.
In order to activate this filtering, configuration is done by a CIDR notation of wanted mask in lorafwd configuration.
Examples:
sudo lorafwdctl -s filter.lorawan.netid "0x24000000/7"
Once activated, the gateway will only forward packets from devices with DevAddr from 0x24000001 to 0x25FFFFFF.
sudo lorafwdctl -s filter.lorawan.netid "0xE0280000/14"
Once activated, the gateway will only forward packets from devices with DevAddr from 0xE0280000 to 0xE029FFFF.
sudo lorafwdctl -s filter.lorawan.netid "0xE0501234/32"
Once activated, the gateway will only forward packets from the device E0501234.
Associated logs can then be observed in log (sudo journalctl -fu lorafwd
) with a trace like this:
Drop message from 0x24f52627 (not in NetID range 0xE0501234/32)
This feature allows to save data consumption by forwarding only LoRaWAN packets from a given JoinEUI range.
A JoinEUI is an ID used by a LoRaWAN device to join on a LoRaWAN network.
In order to activate this filtering, configuration is done by a CIDR notation of wanted mask in lorafwd configuration.
Examples:
sudo lorafwdctl -s filter.lorawan.joineui "0x7076FF0001000000/40"
Once activated, the gateway will only forward join requests from devices with JoinEui from 0x7076FF0001000000 to 0x7076FF0001FFFFFF.
sudo lorafwdctl -s filter.lorawan.joineui "0x7076FF0001005554/64"
Once activated, the gateway will only forward join requests from devices with JoinEUI 7076FF0001005554.
This feature allows to save data consumption by forwarding only LoRaWAN packets from a given DevEUI range.
A DevEUI is an ID used by a LoRaWAN device to communicate on a LoRaWAN network.
In order to activate this filtering, configuration is done by a CIDR notation of wanted mask in lorafwd configuration.
Examples:
sudo lorafwdctl -s filter.lorawan.deveui "0x7777777700000000/32"
Once activated, the gateway will only forward packets from devices with DevEui from 0x7777777700000000 to 0x77777777FFFFFFFF.
sudo lorafwdctl -s filter.lorawan.deveui "0x7076FF0001005554/64"
Once activated, the gateway will only forward packets from devices with DevEUI 7076FF0001005554.
Multiple range filter can be applied on NetID/DevAddr, JoinEUI, DevEUI filters.
It is useful when several range of IDs need to be filtered in.
Examples:
sudo lorafwdctl -s filter.lorawan.netid "0x24000000/8" "0x26000000/8"
Once activated, the gateway will only forward packets from devices with DevAddr from 24000000 to 24FFFFFF and from 26000000 to 26FFFFFF.
Reverse filter can be applied on NetID/DevAddr, JoinEUI, DevEUI filters.
It is useful when several range of IDs need to be filtered out.
In this case, filter has to start with “!”.
Examples:
sudo lorafwdctl -s filter.lorawan.netid "!0x24000000/7"
Once activated, the gateway will reject packets from devices with DevAddr from 0x24000001 to 0x25FFFFFF and will forward any other packets.
It is possible to combine multiple and reverse filter
For example :
sudo lorafwdctl -s filter.lorawan.netid “!0x11111100/24” “0x11111110/28”
Be careful at the order of filter when you use simple and reverse filter
Filter [ “!0x24000000/7”, “0x24000000/7” ] is different from filter [ “0x24000000/7”, “!0x24000000/7” ]
See the Filter cheat sheet for a better understanding.
It is possible to filter proprietary LoRaWAN frame.
To do so:
sudo lorafwdctl -s filter.lorawan.proprietary true
This feature allows to push LoRaWAN frame, received by the gateway, to 2 different LNS. A second instance of lorafwd may be created for this occasion.
sudo cp /etc/lorafwd.toml /etc/lorafwd-second_instance.toml
You may configure this file as wanted
sudo sytemctl start lorafwd@second_instance
sudo journalctl -fu lorafwd@second_instance
In this example, the instance is named
second_instance
but you can name it as you like
You can do as much as instance as you want
Only UDP/GWMP packet forwarder (lorafwd) instances can be created this way but they can be used at the same time as a Kerlink Basic Station Packet forwarder.