Skip to content

Commit

Permalink
Merge branch 'libremesh:master' into refstate
Browse files Browse the repository at this point in the history
  • Loading branch information
javierbrk authored Aug 31, 2023
2 parents b8450d6 + 44043c1 commit 20e9dd3
Show file tree
Hide file tree
Showing 11 changed files with 204 additions and 28 deletions.
45 changes: 37 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,44 @@ We encourage each network community to create its firmware profile on

[In this page][1] we provide a list of requirements that ensure you to have a
working LibreMesh node on your router. This list comes with no warranties: read
carefully the [model-specific instructions on OpenWrt wiki][2] and be
carefully the [model-specific instructions on OpenWrt wiki][OpenWrt-ToH] and be
extra-careful when flashing your routers!

## Building a Firmware Image on Your PC

The LibreMesh firmware can be compiled by following [these instructions][13].
### Building the stable release LibreMesh 2020.1

### Using the ImageBuilder
#### Using the BuildRoot

Start an ImageBuilder of your choice, use containers for an easier setup:
The BuildRoot **will cross-compile the whole OpenWrt and the LibreMesh packages** on your computer, so it will take approx 10 GB of disk space and a few hours of compilation time.

For compiling LibreMesh firmware with this method, you can follow [these instructions][development_page].

#### Using the ImageBuilder

The ImageBuilder method is not available for the stable release.

### Building the experimental firmware

The experimental code still has serious issues that have to be solved, use it only for developing or debugging.

#### Using the BuildRoot

As explained above, in the instuctions on the website you will find where to specify the version of the code to compile.

#### Using the ImageBuilder

The ImageBuiler **will download pre-compiled parts of the OpenWrt releases**, and add the pre-compiled LibreMesh packages, so it is **much faster** than the BuildRoot method (but less practical if you want to develop some new features modifying LibreMesh source code).

Start an ImageBuilder of your choice, for example ath79-generic if your device is supported within it, use containers for an easier setup:

```shell
mkdir ./images/
docker run -it -v $(pwd)/images:/images/ ghcr.io/openwrt/imagebuilder:ath79-generic-v22.03.4
docker run -it -v $(pwd)/images:/images/ ghcr.io/openwrt/imagebuilder:ath79-generic-v22.03.5
```

If your device is not part of ath79-generic profiles, you can replace it with another <target>-<subtarget> combination. For knowing which target and subtarget is best suited for your router, check out the page about it in the [OpenWrt's Table of Hardware][OpenWrt-ToH].

Within the container, add the `lime-packages` feed:

```shell
Expand All @@ -55,11 +77,18 @@ Now create an image of your choice, to see the names of supported profiles run
`make info` first.

```shell
make image PROFILE=ubnt_unifi PACKAGES="lime-system lime-proto-babeld" BIN_DIR=/images FILES=files
make image PROFILE=ubnt_unifi PACKAGES="lime-system lime-proto-babeld lime-proto-batadv lime-proto-anygw lime-hwd-openwrt-wan -dnsmasq" BIN_DIR=/images FILES=files
```

Your images should be available outside of the container in the `./images/` folder

##### Possible errors from the ImageBuilder

If you get a `docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?.` error, means that you don't have Docker's daemon running. Make sure you have `docker` installed and start its daemon with `systemctl start docker.service`.

If you get a `opkg_download: Check your network settings and connectivity.` error, both check the connectivity and make sure that the firewall rules of your computer allow the container to reach the internet.


## Testing

LibreMesh has unit tests that help us add new features while keeping maintenance
Expand Down Expand Up @@ -115,13 +144,13 @@ sponsor](https://opencollective.com/libremesh#sponsor)]
<a href="https://opencollective.com/libremesh/sponsor/9/website" target="_blank"><img src="https://opencollective.com/libremesh/sponsor/9/avatar.svg"></a>

[1]: https://libremesh.org/docs/hardware/
[2]: https://openwrt.org/toh/start
[OpenWrt-ToH]: https://openwrt.org/toh/start
[4]: https://libremesh.org/howitworks.html
[5]: https://libremesh.org/
[8]: https://www.autistici.org/mailman/listinfo/libremesh
[9]: https://libremesh.org/communication.html
[10]: https://github.com/libremesh/network-profiles/
[12]: https://opencollective.com/libremesh
[13]: https://libremesh.org/development.html
[development_page]: https://libremesh.org/development.html

[lime-example]: https://github.com/libremesh/lime-packages/blob/master/packages/lime-docs/files/www/docs/lime-example.txt
23 changes: 23 additions & 0 deletions packages/shared-state-node_info/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#
# Copyright (C) 2023 Javier Jorge <[email protected]>
# Copyright (C) 2023 Asociación Civil Altermundi <[email protected]>
# This is free software, licensed under the GNU Affero General Public License v3.
#

include ../../libremesh.mk

define Package/$(PKG_NAME)
SECTION:=lime
CATEGORY:=LibreMesh
TITLE:=Node information module for shared-state
MAINTAINER:= Javier <[email protected]>
DEPENDS:=+lua +luci-lib-jsonc +ubus-lime-utils \
+lime-system +ubus-lime-location shared-state
PKGARCH:=all
endef

define Package/$(PKG_NAME)/description
Syncronize node information beween nodes.
endef

$(eval $(call BuildPackage,$(PKG_NAME)))
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/sh
unique_append()
{
grep -qF "$1" "$2" || echo "$1" >> "$2"
}

unique_append \
'*/5 * * * * ((sleep $(($RANDOM % 120)); shared-state sync node_info &> /dev/null)&)'\
/etc/crontabs/root
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/lua

--! LibreMesh
--! Copyright (C) 2023 Javier Jorge <[email protected]>
--! Copyright (C) 2023 Asociación Civil Altermundi <[email protected]>
--!
--! This program is free software: you can redistribute it and/or modify
--! it under the terms of the GNU Affero General Public License as
--! published by the Free Software Foundation, either version 3 of the
--! License, or (at your option) any later version.
--!
--! This program is distributed in the hope that it will be useful,
--! but WITHOUT ANY WARRANTY; without even the implied warranty of
--! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
--! GNU Affero General Public License for more details.
--!
--! You should have received a copy of the GNU Affero General Public License
--! along with this program. If not, see <http://www.gnu.org/licenses/>.

local JSON = require("luci.jsonc")
local network = require ("lime.network")
local location = require("lime.location")
local utils = require('lime.utils')
local config = require("lime.config")

local hostname = utils.hostname()
function get_node_info()
local uci = config.get_uci_cursor()
local coords = location.get_node() or location.get_community() or
{lat="FIXME", long="FIXME"}
local fw_version = "no version"
pcall(function () fw_version = utils.release_info()['DISTRIB_RELEASE'] end)
local board = "no board"
pcall(function () board = utils.current_board() end)
local ipv4 = uci:get("network", "lan", "ipaddr")
local ipv6 = uci:get("network", "lan", "ip6addr")
if ipv6 then ipv6 = ipv6:gsub("/.*$", "") end
local uptime = utils.uptime_s()
local macs = network.get_own_macs("*")
return {hostname=hostname, firmware_version=fw_version, board=board,
ipv4=ipv4, ipv6=ipv6,coordinates=coords,macs= macs,uptime = uptime,
device = "Router" }
end

local result = { [hostname] = get_node_info() }
io.popen("shared-state insert node_info", "w"):write(JSON.stringify(result))
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
local JSON = require("luci.jsonc")
local test_utils = require('tests.utils')
local utils = require('lime.utils')

local uci = nil

package.path = package.path .. ";packages/shared-state-node_info/files/usr/bin/?;;"
require ("shared-state-publish_node_info")

describe('Tests network_nodes #network_nodes', function ()
before_each('', function()
uci = test_utils.setup_test_uci()
stub(utils, "release_info", function () return {DISTRIB_RELEASE='2021.1'} end)
stub(utils, "current_board", function () return 'devboard' end)
end)

after_each('', function()
test_utils.teardown_test_uci(uci)
end)

it('a simple test to get node info and assert requiered fields are present', function()
uci = config.get_uci_cursor()
uci:set('network', 'lan', 'interface')
uci:set('network', 'lan', 'ipaddr', '10.5.0.5')
uci:set('network', 'lan', 'ip6addr', 'fd0d:fe46:8ce8::ab:cd00/64')
uci:commit('network')
nodeinfo = get_node_info()
assert.are.equal('devboard', nodeinfo.board)
assert.are.equal('2021.1', nodeinfo.firmware_version)
assert.are.equal('10.5.0.5', nodeinfo.ipv4)
assert.are.equal('fd0d:fe46:8ce8::ab:cd00', nodeinfo.ipv6)
end)
end)
2 changes: 1 addition & 1 deletion packages/shared-state-wifi_links_info/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ define Package/$(PKG_NAME)
MAINTAINER:=
URL:=http://libremesh.org
DEPENDS:=+lua +luci-lib-jsonc +ubus-lime-utils \
+lime-system shared-state
+lime-system +libiwinfo-lua shared-state
PKGARCH:=all
endef

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
local JSON = require("luci.jsonc")
local node_status = require ("lime.node_status")
local network = require ("lime.network")
local iwinfo = require "iwinfo"


function get_wifi_links_info()
local stations = node_status.get_stations()
Expand All @@ -28,9 +30,10 @@ function get_wifi_links_info()
macparts = network.get_mac(station.iface)
src_macaddr = table.concat(macparts,":")
local station_stats = node_status.get_station_stats(station)
local freq = iwinfo.nl80211.frequency(station.iface)
table.insert(links, {src_mac=src_macaddr ,dst_mac=station.station_mac,
signal=station_stats.signal,chains=station_stats.chains,
rx_rate=station_stats.rx_rate,tx_rate=station_stats.tx_rate } )
rx_rate=station_stats.rx_rate,tx_rate=station_stats.tx_rate,freq=freq } )
end
return links
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ it('a simple test to get links info and assert requiered fields are present', fu
return iwinfo.mocks.iw_station_get_result_wlan1
end)
stub(node_status, "get_stations", function () return iwinfo.mocks.get_stations end)

stub(node_status, "get_stations", function () return iwinfo.mocks.get_stations end)
stub(iwinfo.nl80211,"frequency",function (iface) return 2400 end)
stub(network, "get_mac", function (iface)
if string.match(iface, "wlan0") then
return iwinfo.mocks.wlan0_mesh_mac
Expand All @@ -28,6 +29,7 @@ it('a simple test to get links info and assert requiered fields are present', fu
assert.is.same({-17,-18}, links_info[1].chains)
assert.is.equal(-14, links_info[1].signal)
assert.is.equal(13000, links_info[1].rx_rate)
assert.is.equal(2400, links_info[1].freq)
assert.is.equal("C0:00:00:00:00:00", links_info[1].src_mac)
end)

12 changes: 10 additions & 2 deletions packages/shared-state/files/usr/libexec/rpcd/shared-state
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,22 @@ local function getFromSharedState(msg)
local sharedState = shared_state.SharedState:new(msg.data_type,
nixio.syslog)
local resultTable = sharedState:get()
utils.printJson(resultTable)
local response ={}
for k,v in pairs(resultTable) do
response[k]=v.data
end
utils.printJson(response)
end

local function getFromSharedStateMultiWriter(msg)
local sharedState = shared_state.SharedStateMultiWriter:new(msg.data_type,
nixio.syslog)
local resultTable = sharedState:get()
utils.printJson(resultTable)
local response ={}
for k,v in pairs(resultTable) do
response[k]=v.data
end
utils.printJson(response)
end

local function insertIntoSharedStateMultiWriter(msg)
Expand Down
52 changes: 37 additions & 15 deletions packages/shared-state/tests/test_rpcd_shared-state.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
local testUtils = require "tests.utils"
local sharedState = require("shared-state")
local json = require("luci.jsonc")

local testFileName = "packages/shared-state/files/usr/libexec/rpcd/shared-state"
local sharedStateRpc = testUtils.load_lua_file_as_function(testFileName)
Expand Down Expand Up @@ -37,9 +38,9 @@ describe('ubus-shared-state tests #ubus-shared-state', function()
assert.is.equal(dbA.zig.data, 'zag')
local response = rpcdCall(sharedStateRpc, {'call', 'getFromSharedState'},
'{"data_type": "wifi_links_info"}')
assert.is.equal(response.bar.data, 'foo')
assert.is.equal(response.baz.data, 'qux')
assert.is.equal(response.zig.data, 'zag')
assert.is.equal(response.bar, 'foo')
assert.is.equal(response.baz, 'qux')
assert.is.equal(response.zig, 'zag')
end)

it('test get multiwriter data ', function()
Expand All @@ -54,12 +55,12 @@ describe('ubus-shared-state tests #ubus-shared-state', function()
assert.is.equal('zag', dbA.zig.data)
local response = rpcdCall(sharedStateRpc, {'call',
'getFromSharedStateMultiWriter'}, '{"data_type": "A"}')
assert.is.equal(response.bar.data, 'foo')
assert.is.equal(response.baz.data, 'qux')
assert.is.equal(response.zig.data, 'zag')
assert.is.equal(response.bar, 'foo')
assert.is.equal(response.baz, 'qux')
assert.is.equal(response.zig, 'zag')
end)

it('test set multiwriter data ', function()
it('test insert multiwriter data ', function()
local sharedStateA = sharedState.SharedStateMultiWriter:new('A')
sharedStateA:insert({
bar = 'foo',
Expand All @@ -72,7 +73,28 @@ describe('ubus-shared-state tests #ubus-shared-state', function()
local response = rpcdCall(sharedStateRpc, {'call',
'insertIntoSharedStateMultiWriter'},
'{"data_type": "A", "json": {"zig": "newzag"}}')
local dbA = sharedStateA:get()
dbA = sharedStateA:get()
assert.is.equal('foo', dbA.bar.data)
assert.is.equal('newzag', dbA.zig.data)
end)

it('test insert multiwriter data ', function()
local sharedStateA = sharedState.SharedStateMultiWriter:new('A')
sharedStateA:insert({
bar = 'foo',
baz = 'qux',
zig = 'zag'
})
local response = rpcdCall(sharedStateRpc, {'call',
'getFromSharedStateMultiWriter'}, '{"data_type": "A"}')
assert.is.equal('foo', response.bar)
assert.is.equal('zag', response.zig)
response.zig="newzag"
callargs = '{"data_type": "A", "json": '..json.stringify(response)..'}'
local response = rpcdCall(sharedStateRpc, {'call',
'insertIntoSharedStateMultiWriter'},
callargs)
dbA = sharedStateA:get()
assert.is.equal('foo', dbA.bar.data)
assert.is.equal('newzag', dbA.zig.data)
end)
Expand Down Expand Up @@ -121,16 +143,16 @@ describe('ubus-shared-state tests #ubus-shared-state', function()
'{"data_type": "A", "json": {"zig": "zag"}}')
response = rpcdCall(sharedStateRpc, {'call',
'getFromSharedStateMultiWriter'}, '{"data_type": "A"}')
assert.is.equal(response.zig.data, 'zag')
assert.is.equal(response.zig, 'zag')

response = rpcdCall(sharedStateRpc, {'call',
'insertIntoSharedStateMultiWriter'},
wifiStatusJsonsample23)
response = rpcdCall(sharedStateRpc, {'call',
'getFromSharedStateMultiWriter'},
'{"data_type": "ref_state_wifilinks"}')
assert.is.equal(response.primero.data.bleachTTL, 23)
assert.is.equal(response.primero.data.author, "primero")
assert.is.equal(response.primero.bleachTTL, 23)
assert.is.equal(response.primero.author, "primero")

response = rpcdCall(sharedStateRpc, {'call',
'insertIntoSharedStateMultiWriter'},wifiStatusJsonsample27)
Expand All @@ -139,16 +161,16 @@ describe('ubus-shared-state tests #ubus-shared-state', function()
'getFromSharedStateMultiWriter'},
'{"data_type": "ref_state_wifilinks"}')

assert.is.equal(response.primero.data.bleachTTL, 27)
assert.is.equal(response.primero.data.author, "primero")
assert.is.equal(response.primero.bleachTTL, 27)
assert.is.equal(response.primero.author, "primero")

response = rpcdCall(sharedStateRpc, {'call',
'insertIntoSharedStateMultiWriter'},
wifiStatusJsonsample23)
response = rpcdCall(sharedStateRpc, {'call',
'getFromSharedStateMultiWriter'},
'{"data_type": "ref_state_wifilinks"}')
assert.is.equal(response.primero.data.bleachTTL, 23)
assert.is.equal(response.primero.data.author, "primero")
assert.is.equal(response.primero.bleachTTL, 23)
assert.is.equal(response.primero.author, "primero")
end)
end)

0 comments on commit 20e9dd3

Please sign in to comment.