diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ff9d82db2..56899355b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,9 +22,9 @@ jobs: - uses: actions/checkout@v2 - name: Build packages - uses: openwrt/gh-action-sdk@v5 + uses: openwrt/gh-action-sdk@v7 env: - ARCH: "x86_64" + ARCH: "x86_64-openwrt-23.05" FEEDNAME: "libremesh" IGNORE_ERRORS: "n m y" KEY_BUILD: "${{ secrets.KEY_BUILD }}" diff --git a/.gitignore b/.gitignore index 8af25e1f1..86006527d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,8 @@ build luacov.stats.out tools/ansible/files/generic-rootfs.tar.gz tools/ansible/files/ramfs.bzImage - +deploy-pirania.sh +updatepkg.sh # Vim text editor swap files **/*~ diff --git a/packages/lime-app/Makefile b/packages/lime-app/Makefile index 1c0e4d335..7ac250246 100644 --- a/packages/lime-app/Makefile +++ b/packages/lime-app/Makefile @@ -22,7 +22,7 @@ define Package/$(PKG_NAME) URL:=http://github.com/libremesh/lime-app DEPENDS:=+rpcd +uhttpd +uhttpd-mod-ubus +uhttpd-mod-lua \ +ubus-lime-location +ubus-lime-metrics +ubus-lime-utils \ - +rpcd-mod-iwinfo +ubus-lime-grondrouting + +rpcd-mod-iwinfo +ubus-lime-groundrouting PKGARCH:=all endef diff --git a/packages/lime-system/files/usr/lib/lua/lime/network.lua b/packages/lime-system/files/usr/lib/lua/lime/network.lua index 1d9856051..ba5b89b76 100644 --- a/packages/lime-system/files/usr/lib/lua/lime/network.lua +++ b/packages/lime-system/files/usr/lib/lua/lime/network.lua @@ -259,12 +259,14 @@ function network.scandevices() --! With DSA, the WAN is named wan. Copying the code from the lan case. if dev:match("^wan$") then + devices[dev] = {} local lower_if = network._get_lower(dev) if lower_if then devices[lower_if] = { nobridge = true } - devices[dev] = {} utils.log( "network.scandevices.dev_parser found WAN port %s " .. "and marking %s as nobridge", dev, lower_if ) + else + utils.log( "network.scandevices.dev_parser found WAN port %s", dev) end end diff --git a/packages/pirania/Readme.md b/packages/pirania/Readme.md index a2df5f888..bbf447bea 100644 --- a/packages/pirania/Readme.md +++ b/packages/pirania/Readme.md @@ -21,7 +21,7 @@ This are the currently implemented features: * Can be used without vouchers. ## Prerequisites -This software assumes that will be running on a OpenWRT/LEDE distribution (because uses uci for config). Needs `ip6tables-mod-nat` and `ipset` packages installed. +This software assumes that will be running on a OpenWRT/LEDE distribution (because uses uci for config). Needs `nftables` and `ipset` packages installed. ## Install diff --git a/packages/pirania/files/etc/config/pirania b/packages/pirania/files/etc/config/pirania index 9fdfb24b5..147d1990b 100644 --- a/packages/pirania/files/etc/config/pirania +++ b/packages/pirania/files/etc/config/pirania @@ -8,7 +8,7 @@ config base_config 'base_config' option url_fail '/portal/fail.html' option db_path '/etc/pirania/vouchers/' option hooks_path '/etc/pirania/hooks/' - option append_ipt_rules '0' # if set to 1, iptables rules will be Appended instead of Inserted + option append_nft_rules '0' # if set to 1, iptables rules will be Appended instead of Inserted option with_vouchers '0' list allowlist_ipv4 '10.0.0.0/8' list allowlist_ipv4 '172.16.0.0/12' @@ -16,7 +16,7 @@ config base_config 'base_config' list allowlist_ipv6 'fc00::/7' list allowlist_ipv6 'fe80::/64' list allowlist_ipv6 '2a00:1508:0a00::/40' - # list catch_interfaces 'br-lan' + list catch_interfaces 'br-lan' # list catch_interfaces 'anygw' list catch_bridged_interfaces 'wlan0-ap' diff --git a/packages/pirania/files/usr/bin/captive-portal b/packages/pirania/files/usr/bin/captive-portal index a97210d1a..99d3adae7 100755 --- a/packages/pirania/files/usr/bin/captive-portal +++ b/packages/pirania/files/usr/bin/captive-portal @@ -1,139 +1,91 @@ #!/bin/sh -# requires ip6tables-mod-nat and ipset +# requires nftables, liblucihttp0, liblucihttp-lua, uhttpd, uhttpd-mod-lua, uhttpd-mod-ubus -clean_tables () { - echo "Cleaning captive-portal rules" - for iface in $(uci get pirania.base_config.catch_bridged_interfaces); do - ebtables -t nat -D PREROUTING -i $iface -j mark --mark-set 0x9124714 - done - - for ipvX in ipv4 ipv6 ; do - if [ "$ipvX" = "ipv4" ] ; then - iptables=iptables - family=inet - ipaddr=ipaddr - else - iptables=ip6tables - family=inet6 - ipaddr=ip6addr - fi - - $iptables -t mangle -D PREROUTING -m mark --mark 0x9124714 -j pirania - - for interface in $(uci get pirania.base_config.catch_interfaces); do - $iptables -t mangle -D PREROUTING -i $interface -j pirania - done - - $iptables -t nat -D PREROUTING -j pirania - $iptables -t filter -D FORWARD -j pirania - for table in mangle nat filter; do - $iptables -t $table -F pirania - $iptables -t $table -X pirania - done - done -} -clean_sets () { - ipset flush pirania-auth-macs - for ipvX in ipv4 ipv6 ; do - ipset flush pirania-allowlist-$ipvX - done +clean_tables () { + echo "Cleaning captive-portal rules if there's any" + if nft list tables inet | grep -q "pirania"; then + nft delete table inet pirania + fi + } -set_iptables () { +set_nftables () { echo "Apply captive-portal rules" - - append_ipt_rules=$(uci get pirania.base_config.append_ipt_rules 2> /dev/null) - if [ "$append_ipt_rules" = "1" ] ; then - AorI="A" - else - AorI="I" - fi - - # Mark every packet from catch_bridged_interfaces to be handled later. - # bridged interfaces cant be handled by iptables. - for iface in $(uci get pirania.base_config.catch_bridged_interfaces); do - ebtables -t nat -$AorI PREROUTING -i $iface -j mark --mark-set 0x9124714 - done - - for ipvX in ipv4 ipv6 ; do - if [ "$ipvX" = "ipv4" ] ; then - iptables=iptables - family=inet - anygw=$(uci get network.lm_net_br_lan_anygw_if.ipaddr) - else - iptables=ip6tables - family=inet6 - anygw=[$(uci get network.lan.ip6addr | cut -d/ -f1)] - fi - - ### Buildup: create a pirania chain in each table - for table in mangle nat filter; do - $iptables -t $table -N pirania - done - - # Redirect to pirania chain every packet from catch_bridged_interfaces - if [ -n "$(uci get pirania.base_config.catch_bridged_interfaces)" ] ; then - $iptables -t mangle -$AorI PREROUTING -m mark --mark 0x9124714 -j pirania - fi - - # Redirect to pirania chain every packet from catch_interfaces - for interface in $(uci get pirania.base_config.catch_interfaces); do - $iptables -t mangle -$AorI PREROUTING -i $interface -j pirania - done - - # stop processing the chain for authorized macs and allowed ips (so they are accepted) - $iptables -t mangle -A pirania -m set --match-set pirania-auth-macs src -j RETURN - $iptables -t mangle -A pirania -m set --match-set pirania-allowlist-$ipvX dst -j RETURN - - # mark other packages to be rejected later - $iptables -t mangle -A pirania -j MARK --set-mark 0x66/0xff - # except their dest port is 80, in this case mark to be redirected later - $iptables -t mangle -A pirania -p tcp -m tcp --dport 80 -j MARK --set-mark 0x80/0xff - - # marked packages reach nat-prerouting table, send them to nat-pirania chain. - $iptables -t nat -$AorI PREROUTING --jump pirania + # Detect wheter add or insert rules + #append_nft_rules=$(uci get pirania.base_config.append_nft_rules 2> /dev/null) + #if [ "$append_nft_rules" = "1" ] ; then + # op="add rule" + #else + # op="insert rule" + #fi + + # Create pirania tables + nft create table inet pirania + # Create default tables and chains + nft add table inet pirania + nft add chain inet pirania prerouting { type nat hook prerouting priority 0 \; } + nft add chain inet pirania input { type filter hook input priority 0 \; } + nft add chain inet pirania forward { type filter hook forward priority 0 \; } + + # Add mac-adress set + nft add set inet pirania pirania-auth-macs { type ether_addr\; } + + # Create ipv4 set on pirania table + nft add set inet pirania pirania-allowlist-ipv4 { type ipv4_addr \; flags interval \; comment \"allow ipv4 list\" \; } + # Create ipv6 set on pirania table + nft add set inet pirania pirania-allowlist-ipv6 { type ipv6_addr \; flags interval \; comment \"allow ipv6 list\" \; } + + # Only accept packets from interfaces defined in catch_bridged_interfaces + catch_interfaces=$(uci get pirania.base_config.catch_bridged_interfaces | sed 's/ /,/g') + + # stop processing the chain for authorized macs and allowed ips (so they are accepted) + nft add rule inet pirania prerouting ether saddr @pirania-auth-macs ct state new,established,related counter log prefix "ValidSMAC" accept + nft add rule inet pirania prerouting ip daddr @pirania-allowlist-ipv4 ct state new,established,related counter log prefix "ACCEPT-ipv4" accept + nft add rule inet pirania prerouting ip6 daddr @pirania-allowlist-ipv6 ct state new,established,related counter log prefix "ACCEPT-ipv6" accept + + # send DNS requests, that are not from valid ips or macs, to our own captive portal DNS at 59053 + nft add rule inet pirania prerouting meta l4proto udp udp dport 53 ether saddr != @pirania-auth-macs ct state new,established,related counter log prefix "SMACDNS" redirect to :59053 + # redirect packets with dest port 80 to port 59080 of this host (the captive portal page). + nft add rule inet pirania prerouting meta l4proto tcp tcp dport 80 ether saddr != @pirania-auth-macs ct state new,established,related counter log prefix "SMACHTTP" redirect to :59080 + + #nft add rule inet pirania prerouting meta l4proto tcp tcp dport 80 ip saddr @pirania-allowlist-ipv4 ct state new,established,related counter log prefix "IPv4HTTP" redirect to :59080 + #nft add rule inet pirania prerouting meta l4proto tcp tcp dport 80 ip6 saddr @pirania-allowlist-ipv6 ct state new,established,related counter log prefix "IPV6HTTP" redirect to :59080 + + #nft add rule inet pirania prerouting meta l4proto udp udp dport 53 ip saddr @pirania-allowlist-ipv4 ct state new,established,related counter redirect to :59053 + #nft add rule inet pirania prerouting meta l4proto udp udp dport 53 ip6 saddr @pirania-allowlist-ipv6 ct state new,established,related counter redirect to :59053 + + + # reject - # in nat-pirania chain do: - # send DNS requests, that are not from valid ips or macs, to our own captive portal DNS at 59053 - $iptables -t nat -A pirania -p udp -m set ! --match-set pirania-allowlist-$ipvX src -m set ! --match-set pirania-auth-macs src --dport 53 -j DNAT --to-destination $anygw:59053 - # redirect packets with dest port 80 to port 59080 of this host (the captive portal page). - $iptables -t nat -A pirania -p tcp -m tcp -m mark --mark 0x80/0xff -j REDIRECT --to-ports 59080 - - # Other packets, if intended to be forwarded will reach filter-forward chain, send them to filter-pirania chain. - $iptables -t filter -$AorI FORWARD --jump pirania - # And in there let's reject them with the best suited reject reason. - $iptables -t filter -A pirania -p tcp -m mark --mark 0x66/0xff -j REJECT --reject-with tcp-reset - $iptables -t filter -A pirania -m mark --mark 0x66/0xff -j REJECT - done + #nft add rule inet pirania prerouting drop + #nft add rule inet pirania forward meta mark 0x11/0x11 counter reject with tcp reset + #nft add rule inet pirania forward meta mark 0x11/0x11 counter reject + } update_ipsets () { - # using temporary ipset sets and swaping them so the update - # implies minimal disturb to the network and a previous clean-up - # is not needed - ipset -exist create pirania-auth-macs hash:mac timeout 0 - ipset -exist create pirania-auth-macs-tmp hash:mac timeout 0 - for mac in $(pirania_authorized_macs) ; do - ipset -exist add pirania-auth-macs-tmp $mac - done - ipset swap pirania-auth-macs-tmp pirania-auth-macs - ipset destroy pirania-auth-macs-tmp - - for ipvX in ipv4 ipv6 ; do - if [ "$ipvX" = "ipv4" ] ; then - family=inet - else - family=inet6 - fi - ipset -exist create pirania-allowlist-${ipvX} hash:net family $family - ipset -exist create pirania-allowlist-${ipvX}-tmp hash:net family $family - for item in $(uci get pirania.base_config.allowlist_$ipvX); do - ipset -exist add pirania-allowlist-${ipvX}-tmp $item - done - ipset swap pirania-allowlist-${ipvX}-tmp pirania-allowlist-${ipvX} - ipset destroy pirania-allowlist-${ipvX}-tmp - done + + # Create tables and sets + echo "Updating captive-portal rules" + + # Add authorized MAC addresses + for mac in $(pirania_authorized_macs) ; do + nft add element inet pirania pirania-auth-macs {$mac} + echo "Adicionando enderecos:" $mac + done + + # Update pirania-allowlist sets for ipv4 and ipv6 + nft flush set inet pirania pirania-allowlist-ipv4 + nft flush set inet pirania pirania-allowlist-ipv6 + + # Add allowed ip/prefixes + # Get values from allowlist_ipvX and add to pirania-allowlist-ipvX set + ipv4allowlist=$(uci get pirania.base_config.allowlist_ipv4 | sed 's/ /,/g') + nft add element inet pirania pirania-allowlist-ipv4 {$ipv4allowlist} + + ipv6allowlist=$(uci get pirania.base_config.allowlist_ipv6 | sed 's/ /,/g') + nft add element inet pirania pirania-allowlist-ipv6 {$ipv6allowlist} } # check if captive-portal is enabled in /etc/config/pirania @@ -141,24 +93,31 @@ enabled=$(uci get pirania.base_config.enabled) if [ "$1" = "start" ]; then echo "Running captive-portal" + /etc/init.d/pirania-dnsmasq start + /etc/init.d/pirania-uhttpd start clean_tables + set_nftables update_ipsets - set_iptables exit elif [ "$1" = "update" ] ; then + echo "Captive-portal updating rules" update_ipsets exit elif [ "$1" = "clean" ] || [ "$1" = "stop" ] ; then clean_tables - clean_sets exit elif [ "$enabled" = "1" ]; then + echo "Captive-portal already enabled, reloading rules" clean_tables +# set_nftables update_ipsets - set_iptables exit +elif [ "$1" = "enabled" ]; then + uci set pirania.base_config.enabled='1' + # i/o error in my device - check later + #uci commit + echo "Captive-portal is now enabled" else echo "Pirania captive-portal is disabled. Try running captive-portal start" exit -fi - +fi \ No newline at end of file diff --git a/packages/pirania/files/usr/lib/lua/voucher/utils.lua b/packages/pirania/files/usr/lib/lua/voucher/utils.lua index 3589db578..f1f472314 100644 --- a/packages/pirania/files/usr/lib/lua/voucher/utils.lua +++ b/packages/pirania/files/usr/lib/lua/voucher/utils.lua @@ -39,12 +39,12 @@ function utils.getIpv4AndMac(ip_address) res.mac = ipv4mac return res else - local ipv6macCommand = "ip neighbor | grep "..ip_address.." | awk -F ' ' '{print $5}' | head -n 1" + local ipv6macCommand = "ip neigh | grep "..ip_address.." | awk -F ' ' '{print $5}' | head -n 1" fd6 = io.popen(ipv6macCommand, 'r') ipv6mac = fd6:read('*l') fd6:close() - local ipv4Command = "cat /proc/net/arp | grep "..ipv6mac.." | awk -F ' ' '{print $1}' | head -n 1" - fd4 = io.popen(ipv4Command, 'r') + local ipv4cCommand = "cat /proc/net/arp | grep "..ipv6mac.." | awk -F ' ' '{print $1}' | head -n 1" + fd4 = io.popen(ipv4cCommand, 'r') ipv4 = fd4:read('*l') fd4:close() local res = {} diff --git a/packages/shared-state-async/README.adoc b/packages/shared-state-async/README.adoc index 3359017c7..b693634f7 100644 --- a/packages/shared-state-async/README.adoc +++ b/packages/shared-state-async/README.adoc @@ -1,3 +1,318 @@ += LibreMesh: Shared State Overview +:toc: +:toclevels: 3 + +== Introduction + +LibreMesh is an open-source framework designed to facilitate the creation of community mesh networks. A key component of this framework is the **Shared State**, a Conflict-Free Replicated Data Type (CRDT) daemon. This module enables seamless information exchange between nodes in a decentralized network, ensuring consistency and reliability. + +The official repository is: https://github.com/LibreMesh/shared-state-async. + +Features: + +- **Conflict-Free Synchronization**: Shared State ensures data consistency across nodes without requiring a central authority or lock mechanism. +- **Decentralized Communication**: Nodes exchange data directly, allowing the network to function even in the absence of a central controller. +- **Flexible Data Types**: Supports various data types, including Wi-Fi link information, node details, and more. + +== Available Commands + +Shared State provides several commands to interact with and manage data types. Below is an overview of the most commonly used commands for getting and managing data. + +-------------------------------------------------------------------------------- +shared-state-async +Usage: shared-state-async OPERATION [ARGUMENTS] +Supported operations: discover, dump, get, insert, peer, register, sync +-------------------------------------------------------------------------------- + + + +**Get** + +In LibreMesh, shared-state is already included and running so you can run this command. This command allows you to retrieve the current state of a specific data type. + + shared-state-async get + +Example: + +-------------------------------------------------------------------------------- +shared-state-async get net-stats +-------------------------------------------------------------------------------- + +**Insert** + +This command is used to insert data into Shared State. You can specify the data type and the information you want to insert using std input. + + echo '{}' | shared-state-async insert + +Example: + +-------------------------------------------------------------------------------- +echo '{"cheche":{"src_loc":{"long":"-64.4228178","lat":"-31.8019512"},"links":{"ae40411f73a8c64a00fc3abe":{"freq":2462,"iface":"wlan0-mesh","tx_rate":144400,"dst_mac":"c6:4a:00:fc:3a:be","channel":11,"chains":[-40,-35],"signal":-34,"rx_rate":144400,"src_mac":"ae:40:41:1f:73:a8"}}}}'| shared-state-async insert wifi_links_info_ref +-------------------------------------------------------------------------------- + +**Dump** + +Is like get but with extended shared state debug info of a datatype. It will report "Author" and "Ttl" + + shared-state-async dump + +Example: + +-------------------------------------------------------------------------------- +shared-state-async get bat-hosts +{ +... + "ae:40:41:22:55:78": "estela_y_julio_wlan1_mesh_17", + "ae:40:41:22:55:7b": "estela_y_julio_wlan2_mesh" +} + + +shared-state-async dump bat-hosts + +... + + { + "key": "ae:40:41:22:55:78", + "value": { + "mAuthor": "estela-y-julio", + "mTtl": { + "xint64": 1422, + "xstr64": "1422" + }, + "mData": "estela_y_julio_wlan1_mesh_17" + } + }, + { + "key": "ae:40:41:22:55:7b", + "value": { + "mAuthor": "estela-y-julio", + "mTtl": { + "xint64": 1422, + "xstr64": "1422" + }, + "mData": "estela_y_julio_wlan2_mesh" + } + } +... + +-------------------------------------------------------------------------------- + +**sync** + +This is used to force synchronization between nodes. It will try to sync with neighbors but you can also specify a specific host to try to sync to. +In order to get the most accurate and fresh info from a node you must force the publisher of the data type to be executed and then sync your info with that node. + +Example: + +-------------------------------------------------------------------------------- + + shared-state-async sync bat-hots 8.8.8.8 + +-------------------------------------------------------------------------------- + + +**peer** + +Shared state is basically only one binary that has to be called first with the "peer" argument in order to lunch the daemon. Then the same binary can be used as a tool to interact with the daemon. + + shared-state-async peer + + +**discover** + +Discover the nodes able to parte in the Shared State network. + + + shared-state-async discover + + +**register** + +Register a new data type or node in the Shared State system. + + + shared-state-async register DATA-TYPE TYPE-SCOPE UPDATE-INTERVAL BLEACH-TTL + + + +== Ubus Wrapper + +Shared State also supports using ubus for remote procedure calls (RPC) to interact with the system. Get method returns shared-state "get" json data or reported error in case no json is found. Errors are bubbled up as they come from shared-state inside a json structure with the name "error". + +Available commands are: + +[source,json] +---- +{ + "sync": { "data_type": "str", "peers_ip": "str" }, + "get": { "data_type": "str" }, + "publish": { "data_type": "str" }, + "publish_all": { }, + "insert": { "data_type": "str", "json": "str" } +} +---- + +=== Get + +Get bat-hosts + +-------------------------------------------------------------------------------- + +# ubus -S call shared-state-async get "{'data_type': 'bat-hosts'}" + +{"a8:40:41:1f:73:ab":"lrsegundo_eth1_2","02:95:39:1f:73:aa":"lrsegundo_eth0_250","a8:40:41:1c:85:c3":"lrsegundo_wlan2_mesh","a8:40:41:1c:85:16":"lrsegundo_wlan1_mesh","02:bb:ed:1f:73:aa":"lrsegundo_eth1_250","a8:40:41:1f:73:a8":"lrsegundo_wlan0_ap","aa:40:41:1f:73:a8":"lrsegundo_wlan0_apname","02:db:d6:1f:73:aa":"lrsegundo_eth0_1_250","02:29:0f:1f:73:aa":"lrsegundo_eth1_2_250","c2:10:20:5e:7f:b3":"lrsegundo_bat0","a8:40:41:1f:73:aa":"lrsegundo_eth0"} + +-------------------------------------------------------------------------------- + +Get an invalid data type + +-------------------------------------------------------------------------------- + +# ubus -S call shared-state-async get "{'data_type': 'bat-hosss'}" + +{"error":53248} + +-------------------------------------------------------------------------------- + +=== Sync +Sync valid data type + +-------------------------------------------------------------------------------- + +# ubus -S call shared-state-async sync "{'data_type': 'bat-hosts'}" + +{"error":0} + +-------------------------------------------------------------------------------- + +Sync invalid data type + +-------------------------------------------------------------------------------- + +ubus -S call shared-state-async sync "{'data_type': 'bat-hoss' }" + +{"error":53248} + +-------------------------------------------------------------------------------- + +Sync valid data type with unreachable ipv4 addresses + +-------------------------------------------------------------------------------- + +# ubus -S call shared-state-async sync "{'data_type': 'bat-hosts' ,'peers_ip':['10.0.0.1','10.0.0.2']}'" + +{"error":32768} + +-------------------------------------------------------------------------------- + +Sync valid data type with invalid ipv4 address + +-------------------------------------------------------------------------------- + +# ubus -S call shared-state-async sync "{'data_type': 'bat-hosts' ,'peers_ip':['10.0.0.1','10.0.2']}'" + +{"error":61952} + +-------------------------------------------------------------------------------- + +Sync invalid data type with specified ipv4 address + +-------------------------------------------------------------------------------- + +ubus -S call shared-state-async sync "{'data_type': 'bat-hosts' ,'peers_ip':['127.0.0.1','127.0.0.1']}'" + +{"error":53248} + +-------------------------------------------------------------------------------- + +Sync valid data type with reachable ipv4 addresses + +-------------------------------------------------------------------------------- + +# ubus -S call shared-state-async sync "{'data_type': 'bat-hosts' ,'peers_ip':['127.0.0.1','127.0.0.1']}'" + +{"error":0} + +-------------------------------------------------------------------------------- + +== Data types +Each data type in Shared State consists of at least two key components: + +1. **Definition**: Specifies the structure and properties of the data type. +2. **Publisher**: Responsible for generating and updating the data. +3. **Hook(optional)**: optionally a data type can implement a third component that is a hook. These executes custom actions when the data type is updated or accessed. + +all data types are in a separate package in LibreMesh and are named "shared-state-**dataType**". A good example of a package is https://github.com/LibreMesh/lime-packages/tree/08784318f4e9fd4269675bd9dbc8ebf6962ce5da/packages/shared-state-bat_hosts[bat-hosts] + +=== Available data types + +Shared State uses data types to support various functions. Each data types is responsible for handling a specific information, ensuring seamless integration and management of that data within the mesh network. + +The some of the currently supported data types include: + +- **bat-hosts**: Handles information about hosts in the network and helps resolving node's domain name. + +- **wifi_links_info**: Handles information about Wi-Fi link status and metrics. + +- **node_info**: Manages metadata about individual nodes. + +- **babel_links_info**: babel routing protocol-specific link data. + +- **bat_links_info**: Manages link information for BATMAN-adv networks. + +- **Reference State**: One application of Shared State is maintaining a reference state for troubleshooting, diagnostics, and disaster recovery in mesh networks. Refer to the detailed documentation in https://github.com/LibreMesh/lime-packages/blob/08784318f4e9fd4269675bd9dbc8ebf6962ce5da/packages/shared-state-ref_state_commons/README.md[README.md] for more on Reference State. + +=== Data types registration + +To add support for a new data type, you can develop a custom new data type tailored to your requirements. Data types must be registered into shared-state-async by using a config file. UCI infrastructure is preferred and here is a sample + +[source,bash] +-------------------------------------------------------------------------------- +mSc="plugin_name" + +uci set shared-state.${mSc}=dataType +uci set shared-state.${mSc}.name='data_type_name' +uci set shared-state.${mSc}.scope='community' +uci set shared-state.${mSc}.ttl='1200' +uci set shared-state.${mSc}.update_interval='120' +uci commit shared-state +-------------------------------------------------------------------------------- + +'name' and 'ttl' are the most important attributes.'name' is the name of the data type and 'ttl' parameter stands for "time to live" and will decrease every second until 0. + +=== Datatype publishers + +In Shared State, **publishers** are responsible for producing and updating data. Each publisher acts as a source for specific data types, feeding information into the system that is then distributed and replicated across the network. + +Publishers must be located at +/usr/share/shared-state/publishers+ +All Publishers will be called periodically using shared-state-async-publish-all, this can also be invoked manually. + +Sync is called automatically by shared-state daemon every 15s +"ttl" parameter stands for "time to live" and will decrease every second until 0. +Data contents will be erased if "ttl" reaches 0. So calling publishers has to be done periodically before that happens. + +=== Datatype hooks + +**Datatype hooks** allow custom behavior to be triggered when specific data types are updated or accessed. These hooks enable developers to extend the functionality of Shared State by defining actions that respond to changes in the data. + +Examples of hooks in action can be found in the `shared-state-mesh-upgrade` package. This package demonstrates how hooks can be utilized to enhance mesh network functionalities. + +=== Adding Hooks + +Hooks can be added by defining callback script tied to specific data types. + +hooks scripts must be placed in /usr/share/shared-state/hooks/dataType folder and must read std input as + +[source,lua] +-------------------------------------------------------------------------------- +local indata = io.stdin:read("*all") +utils.printJson(JSON.parse(indata)) +-------------------------------------------------------------------------------- + + +== Debugging +By default shared state async is already installed in LibreMesh, but if you want to debug you can compile the binary with debug flag enabled. +First you must have a clone of openWRT with LibreMesh feeds installed. Please refer to LibreMesh docs to achieve this. .Build with debugging enabled -------------------------------------------------------------------------------- @@ -38,8 +353,6 @@ while Builds/build-lime-shared-state-async-node-Desktop-Debug/shared-state-async while shared-state-async sync bat-hosts fe80::ea94:f6ff:fe68:3364%br-lan; do echo ------------------------------------------------------------------- ;done -------------------------------------------------------------------------------- - - === Interesting Readings https://openwrt.org/docs/guide-developer/gdb @@ -47,24 +360,7 @@ https://openwrt.org/docs/guide-developer/gdb VoCore2: Develop for OpenWrt on Qt Creator https://vonger.cn/?p=14657 -=== Plugin related notes -Plugins must be registered into shared-state-async by using the config file. UCI infrastructure is preferred +== Contributing -[source,console] --------------------------------------------------------------------------------- -mSc="plugin_name" - -uci set shared-state.${mSc}=dataType -uci set shared-state.${mSc}.name='plugin-name' -uci set shared-state.${mSc}.scope='community' -uci set shared-state.${mSc}.ttl='1200' -uci set shared-state.${mSc}.update_interval='120' -uci commit shared-state --------------------------------------------------------------------------------- - -Publishers must be located at +/usr/share/shared-state/publishers+ -All Publishers will be called at least once using shared-state-async-publish-all +We welcome contributions to improve Shared State and its applications. Feel free to open issues or submit pull requests on the [GitHub repository](https://github.com/LibreMesh/lime-packages) -Sync is called automatically by shared-state-async according to "update_interval" parameter -"ttl" stands for "time to live" and will decrease until 0. -Data contents will be erased if "ttl" reaches 0.