├── Makefile ├── README.md ├── luasrc ├── controller │ └── easymesh.lua └── model │ └── cbi │ └── easymesh.lua ├── po ├── zh-cn │ └── easymesh.po └── zh_Hans └── root ├── etc ├── config │ └── easymesh ├── init.d │ └── easymesh └── uci-defaults │ └── luci-easymesh └── usr └── share └── rpcd └── acl.d └── luci-app-easymesh.json /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | #-- Copyright (C) 2021 dz 3 | # 4 | 5 | include $(TOPDIR)/rules.mk 6 | 7 | LUCI_TITLE:=LuCI Support for easymesh 8 | LUCI_DEPENDS:= +kmod-cfg80211 +batctl-default +kmod-batman-adv +wpad-mesh-openssl +dawn 9 | PKG_VERSION:=2.0 10 | 11 | include $(TOPDIR)/feeds/luci/luci.mk 12 | 13 | # call BuildPackage - OpenWrt buildroot signature 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # luci-app-easymesh 2 | 水平有限写了基于kmod-batman-adv+802.11s 有线+无线回程的mesh luci设置插件。 3 | 4 | 新增ap设置让设置更加方便。 5 | 6 | 新增KVR设置并添加dawn依赖在ap之间切换延迟明显降低。 7 | 8 | 插件只对https://github.com/coolsnowwolf/lede lean版openwrt做了测试 其他源码出现问题请自行解决。 9 | 10 | 写的很烂暂时能用 11 | -------------------------------------------------------------------------------- /luasrc/controller/easymesh.lua: -------------------------------------------------------------------------------- 1 | -- Copyright (C) 2021 dz 2 | 3 | module("luci.controller.easymesh", package.seeall) 4 | 5 | function index() 6 | if not nixio.fs.access("/etc/config/easymesh") then 7 | return 8 | end 9 | 10 | local page 11 | 12 | page = entry({"admin", "network", "easymesh"}, cbi("easymesh"), _("EASY MESH"), 60) 13 | page.dependent = true 14 | page.acl_depends = { "luci-app-easymesh" } 15 | end 16 | -------------------------------------------------------------------------------- /luasrc/model/cbi/easymesh.lua: -------------------------------------------------------------------------------- 1 | -- Copyright (C) 2021 dz 2 | 3 | local m,s,o 4 | local sys = require "luci.sys" 5 | local uci = require "luci.model.uci".cursor() 6 | 7 | m = Map("easymesh") 8 | 9 | function detect_Node() 10 | local data = {} 11 | local lps = luci.util.execi(" batctl n 2>/dev/null | tail +2 | sed 's/^[ ][ ]*//g' | sed 's/[ ][ ]*/ /g' | sed 's/$/ /g' ") 12 | for value in lps do 13 | local row = {} 14 | local pos = string.find(value, " ") 15 | local IFA = string.sub(value, 1, pos - 1) 16 | local value = string.sub(value, pos + 1, string.len(value)) 17 | pos = string.find(value, " ") 18 | local pos = string.find(value, " ") 19 | local Neighbora = string.sub(value, 1, pos - 1) 20 | local value = string.sub(value, pos + 1, string.len(value)) 21 | pos = string.find(value, " ") 22 | local pos = string.find(value, " ") 23 | local lastseena = string.sub(value, 1, pos - 1) 24 | local value = string.sub(value, pos + 1, string.len(value)) 25 | pos = string.find(value, " ") 26 | row["IF"] = IFA 27 | row["Neighbor"] = Neighbora 28 | row["lastseen"] = lastseena 29 | table.insert(data, row) 30 | end 31 | return data 32 | end 33 | local Nodes = luci.sys.exec("batctl n 2>/dev/null| tail +3 | wc -l") 34 | local Node = detect_Node() 35 | v = m:section(Table, Node, "" ,"" .. translate("Active node") .. ":" .. Nodes .. "") 36 | v:option(DummyValue, "IF", translate("IF")) 37 | v:option(DummyValue, "Neighbor", translate("Neighbor")) 38 | v:option(DummyValue, "lastseen", translate("lastseen")) 39 | 40 | -- Basic 41 | s = m:section(TypedSection, "easymesh", translate("Settings"), translate("General Settings")) 42 | s.anonymous = true 43 | 44 | ---- Eanble 45 | o = s:option(Flag, "enabled", translate("Enable"), translate("Enable or disable EASY MESH")) 46 | o.default = 0 47 | o.rmempty = false 48 | 49 | o = s:option(ListValue, "role", translate("role")) 50 | o:value("off", translate("off")) 51 | o:value("server", translate("host MESH")) 52 | o:value("client", translate("son MESH")) 53 | o.rmempty = false 54 | 55 | apRadio = s:option(ListValue, "apRadio", translate("MESH Radio device"), translate("The radio device which MESH use")) 56 | uci:foreach("wireless", "wifi-device", 57 | function(s) 58 | apRadio:value(s['.name']) 59 | end) 60 | apRadio:value("all", translate("ALL")) 61 | o.default = "radio0" 62 | o.rmempty = false 63 | 64 | ---- mesh 65 | o = s:option(Value, "mesh_id", translate("MESH ID")) 66 | o.default = "easymesh" 67 | o.description = translate("MESH ID") 68 | 69 | enable = s:option(Flag, "encryption", translate("Encryption"), translate("")) 70 | enable.default = 0 71 | enable.rmempty = false 72 | 73 | o = s:option(Value, "key", translate("Key")) 74 | o.default = "easymesh" 75 | o:depends("encryption", 1) 76 | 77 | ---- kvr 78 | enable = s:option(Flag, "kvr", translate("K/V/R"), translate("")) 79 | enable.default = 1 80 | enable.rmempty = false 81 | 82 | o = s:option(Value, "mobility_domain", translate("Mobility Domain"), translate("4-character hexadecimal ID")) 83 | o.default = "4f57" 84 | o.datatype = "and(hexstring,rangelength(4,4))" 85 | o:depends("kvr", 1) 86 | 87 | o = s:option(Value, "rssi_val", translate("Threshold for an good RSSI")) 88 | o.default = "-60" 89 | o.atatype = "range(-1,-120)" 90 | o:depends("kvr", 1) 91 | 92 | o = s:option(Value, "low_rssi_val", translate("Threshold for an bad RSSI")) 93 | o.default = "-88" 94 | o.atatype = "range(-1,-120)" 95 | o:depends("kvr", 1) 96 | 97 | ---- 802.11F 98 | --enable = s:option(Flag, "iapp", translate("inter-access point protocol"), translate("Wireless Access Points (APs) running on different vendors can communicate with each other")) 99 | --enable.default = 0 100 | --enable.rmempty = false 101 | 102 | ---- ap_mode 103 | enable = s:option(Flag, "ap_mode", translate("AP MODE Enable"), translate("Enable or disable AP MODE")) 104 | enable.default = 0 105 | enable.rmempty = false 106 | 107 | o = s:option(Value, "ipaddr", translate("IPv4-Address")) 108 | o.default = "192.168.1.10" 109 | o.datatype = "ip4addr" 110 | o:depends("ap_mode", 1) 111 | 112 | o = s:option(Value, "netmask", translate("IPv4 netmask")) 113 | o.default = "255.255.255.0" 114 | o.datatype = "ip4addr" 115 | o:depends("ap_mode", 1) 116 | 117 | o = s:option(Value, "gateway", translate("IPv4 gateway")) 118 | o.default = "192.168.1.1" 119 | o.datatype = "ip4addr" 120 | o:depends("ap_mode", 1) 121 | 122 | o = s:option(Value, "dns", translate("Use custom DNS servers")) 123 | o.default = "192.168.1.1" 124 | o.datatype = "ip4addr" 125 | o:depends("ap_mode", 1) 126 | 127 | return m 128 | -------------------------------------------------------------------------------- /po/zh-cn/easymesh.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "Content-Type: text/plain; charset=UTF-8\n" 3 | 4 | msgid "easymesh" 5 | msgstr "easymesh" 6 | 7 | msgid "Active node" 8 | msgstr "活动节点" 9 | 10 | msgid "IF" 11 | msgstr "IF" 12 | 13 | msgid "Neighbor" 14 | msgstr "节点邻居设备" 15 | 16 | msgid "lastseen" 17 | msgstr "上次连接延时" 18 | 19 | msgid "EASY MESH" 20 | msgstr "简单MESH" 21 | 22 | msgid "Settings" 23 | msgstr "设置" 24 | 25 | msgid "General Settings" 26 | msgstr "基本设置" 27 | 28 | msgid "Enable" 29 | msgstr "启用" 30 | 31 | msgid "role" 32 | msgstr "角色" 33 | 34 | msgid "off" 35 | msgstr "关闭" 36 | 37 | msgid "host MESH" 38 | msgstr "主MESH" 39 | 40 | msgid "son MESH" 41 | msgstr "子MESH" 42 | 43 | msgid "MESH Radio device" 44 | msgstr "MESH无线设备" 45 | 46 | msgid "The radio device which MESH use" 47 | msgstr "使用MESH组网的无线设备" 48 | 49 | msgid "AUTO" 50 | msgstr "自动" 51 | 52 | msgid "Enable or disable EASY MESH" 53 | msgstr "启用或禁用简单MESH" 54 | 55 | msgid "Encryption" 56 | msgstr "加密" 57 | 58 | msgid "Key" 59 | msgstr "密码" 60 | 61 | msgid "inter-access point protocol" 62 | msgstr "接入点内部协议" 63 | 64 | msgid "Wireless Access Points (APs) running on different vendors can communicate with each other" 65 | msgstr "运行在不同供应商的无线访问点(AP)可以相互交流" 66 | 67 | msgid "Threshold for an good RSSI" 68 | msgstr "快速漫游接入值" 69 | 70 | msgid "Threshold for an bad RSSI" 71 | msgstr "快速漫游踢出值" 72 | 73 | msgid "AP MODE Enable" 74 | msgstr "启用AP模式" 75 | 76 | msgid "Enable or disable AP MODE" 77 | msgstr "启用或禁用AP模式" 78 | 79 | msgid "IPv4-Address" 80 | msgstr "IPv4 地址" 81 | 82 | msgid "IPv4 netmask" 83 | msgstr "IPv4 子网掩码" 84 | 85 | msgid "IPv4 gateway" 86 | msgstr "IPv4 网关" 87 | 88 | msgid "Use custom DNS servers" 89 | msgstr "使用自定义的 DNS 服务器" 90 | -------------------------------------------------------------------------------- /po/zh_Hans: -------------------------------------------------------------------------------- 1 | zh-cn -------------------------------------------------------------------------------- /root/etc/config/easymesh: -------------------------------------------------------------------------------- 1 | 2 | config easymesh 'config' 3 | option enabled '0' 4 | -------------------------------------------------------------------------------- /root/etc/init.d/easymesh: -------------------------------------------------------------------------------- 1 | #!/bin/sh /etc/rc.common 2 | START=99 3 | STOP=70 4 | 5 | load_easymesh_config() { 6 | enable=$(uci -q get easymesh.config.enabled) 7 | mesh_bat0=$(uci -q get network.bat0) 8 | ap_mode=$(uci -q get easymesh.config.ap_mode) 9 | lan=$(uci -q get network.lan.ifname) 10 | ipaddr=$(uci -q get easymesh.config.ipaddr) 11 | netmask=$(uci -q get easymesh.config.netmask) 12 | gateway=$(uci -q get easymesh.config.gateway) 13 | dns=$(uci -q get easymesh.config.dns) 14 | ap_ipaddr=$(uci -q get network.lan.ipaddr) 15 | ap_ipaddr1=$(sed -n '1p' /etc/easymesh 2>/dev/null) 16 | apRadio=$(uci -q get easymesh.config.apRadio) 17 | kvr=$(uci -q get easymesh.config.kvr) 18 | iapp=$(uci -q get easymesh.config.iapp) 19 | brlan=$(uci -q get network.@device[0].name) 20 | role=$(uci -q get easymesh.config.role) 21 | } 22 | 23 | ap_mode_stop() { 24 | ap_ipaddr=$(uci -q get network.lan.ipaddr) 25 | ap_ipaddr1=$(sed -n '1p' /etc/easymesh 2>/dev/null) 26 | dns1=$(sed -n '2p' /etc/easymesh 2>/dev/null) 27 | if [ "$ap_ipaddr" = "$ap_ipaddr1" ]; then 28 | uci -q delete network.lan.gateway 29 | uci -q del_list network.lan.dns=$dns1 30 | uci commit network 31 | 32 | echo "" >/etc/easymesh 33 | 34 | uci -q delete dhcp.lan.dynamicdhcp 35 | uci -q delete dhcp.lan.ignore 36 | uci commit dhcp 37 | 38 | /etc/init.d/odhcpd enable && /etc/init.d/odhcpd start 39 | /etc/init.d/firewall enable && /etc/init.d/firewall start >/dev/null 2>&1 40 | fi 41 | } 42 | 43 | add_wifi_mesh() { 44 | mesh_nwi_mesh=$(uci -q get network.nwi_mesh_${apall}) 45 | mesh_apRadio=$(uci -q get wireless.mesh_${apall}.device) 46 | mesh_mesh=$(uci -q get wireless.mesh_${apall}) 47 | mesh_id=$(uci -q get easymesh.config.mesh_id) 48 | mobility_domain=$(uci -q get easymesh.config.mobility_domain) 49 | key=$(uci -q get easymesh.config.key) 50 | encryption=$(uci -q get easymesh.config.encryption) 51 | 52 | if [ "$mesh_nwi_mesh" != "interface" ]; then 53 | uci set network.nwi_mesh_$apall=interface 54 | uci set network.nwi_mesh_$apall.proto='batadv_hardif' 55 | uci set network.nwi_mesh_$apall.master='bat0' 56 | uci set network.nwi_mesh_$apall.mtu='1536' 57 | uci commit network 58 | fi 59 | 60 | if [ "$mesh_mesh" != "wifi-iface" ]; then 61 | uci set wireless.mesh_$apall=wifi-iface 62 | uci set wireless.mesh_$apall.device=$apall 63 | uci set wireless.mesh_$apall.ifname=mesh_${apall} 64 | uci set wireless.mesh_$apall.network=nwi_mesh_${apall} 65 | uci set wireless.mesh_$apall.mode='mesh' 66 | uci set wireless.mesh_$apall.mesh_id=$mesh_id 67 | uci set wireless.mesh_$apall.mesh_fwding='0' 68 | uci set wireless.mesh_$apall.mesh_ttl='1' 69 | uci set wireless.mesh_$apall.mcast_rate='24000' 70 | uci set wireless.mesh_$apall.disabled='0' 71 | uci commit wireless 72 | fi 73 | 74 | if [ "$mesh_mesh" = "wifi-iface" ]; then 75 | if [ "$mesh_apRadio" != "$apall" ]; then 76 | uci set wireless.mesh_$apall.device=$apall 77 | uci commit wireless 78 | fi 79 | fi 80 | 81 | if [ "$encryption" != 1 ]; then 82 | uci set wireless.mesh_$apall.encryption='none' 83 | uci commit wireless 84 | else 85 | uci set wireless.mesh_$apall.encryption='sae' 86 | uci set wireless.mesh_$apall.key=$key 87 | uci commit wireless 88 | fi 89 | } 90 | 91 | add_kvr() { 92 | kvr=$(uci -q get easymesh.config.kvr) 93 | mobility_domain=$(uci -q get easymesh.config.mobility_domain) 94 | iapp=$(uci -q get easymesh.config.iapp) 95 | for apall in $(uci -X show wireless | grep wifi-device | awk -F'[.=]' '{print $2}'); do 96 | if [ "$kvr" = 1 ]; then 97 | uci set wireless.default_$apall.ieee80211k='1' 98 | uci set wireless.default_$apall.rrm_neighbor_report='1' 99 | uci set wireless.default_$apall.rrm_beacon_report='1' 100 | uci set wireless.default_$apall.ieee80211v='1' 101 | uci set wireless.default_$apall.bss_transition='1' 102 | uci set wireless.default_$apall.ieee80211r='1' 103 | uci set wireless.default_$apall.encryption='psk2+ccmp' 104 | uci set wireless.default_$apall.mobility_domain=$mobility_domain 105 | uci set wireless.default_$apall.ft_over_ds='1' 106 | uci set wireless.default_$apall.ft_psk_generate_local='1' 107 | uci commit wireless 108 | else 109 | uci -q delete wireless.default_$apall.ieee80211k 110 | uci -q delete wireless.default_$apall.ieee80211v 111 | uci -q delete wireless.default_$apall.ieee80211r 112 | uci commit wireless 113 | fi 114 | if [ "$iapp" = 1 ]; then 115 | uci set wireless.default_$apall.iapp_interface='br-lan' 116 | uci commit wireless 117 | else 118 | uci -q delete wireless.default_$apall.iapp_interface 119 | uci commit wireless 120 | fi 121 | done 122 | } 123 | 124 | add_dawn() { 125 | kvr=$(uci -q get easymesh.config.kvr) 126 | rssi_val=$(uci -q get easymesh.config.rssi_val) 127 | low_rssi_val=$(uci -q get easymesh.config.low_rssi_val) 128 | 129 | if [ "$kvr" = 1 ]; then 130 | uci set dawn.@metric[0].rssi_val=$rssi_val 131 | uci set dawn.@metric[0].low_rssi_val=$low_rssi_val 132 | uci commit dawn 133 | /etc/init.d/dawn enable && /etc/init.d/dawn start 134 | else 135 | /etc/init.d/dawn stop && /etc/init.d/dawn disable 136 | fi 137 | } 138 | 139 | set_easymesh() { 140 | load_easymesh_config 141 | if [ "$enable" = 1 ]; then 142 | if [ "$mesh_bat0" != "interface" ]; then 143 | uci set network.bat0=interface 144 | uci set network.bat0.proto='batadv' 145 | uci set network.bat0.routing_algo='BATMAN_IV' 146 | uci set network.bat0.aggregated_ogms='1' 147 | uci set network.bat0.ap_isolation='0' 148 | uci set network.bat0.bonding='0' 149 | uci set network.bat0.bridge_loop_avoidance='1' 150 | uci set network.bat0.distributed_arp_table='1' 151 | uci set network.bat0.fragmentation='1' 152 | # uci set network.bat0.gw_bandwidth='10000/2000' 153 | # uci set network.bat0.gw_sel_class='20' 154 | uci set network.bat0.hop_penalty='30' 155 | uci set network.bat0.isolation_mark='0x00000000/0x00000000' 156 | uci set network.bat0.log_level='0' 157 | uci set network.bat0.multicast_fanout='16' 158 | uci set network.bat0.multicast_mode='1' 159 | uci set network.bat0.network_coding='0' 160 | uci set network.bat0.orig_interval='1000' 161 | 162 | if [ "$role" = "server" ]; then 163 | uci set network.bat0.gw_mode='server' 164 | elif [ "$role" = "client" ]; then 165 | uci set network.bat0.gw_mode='client' 166 | else 167 | uci set network.bat0.gw_mode='off' 168 | fi 169 | 170 | if [ "$brlan" = "br-lan" ]; then 171 | uci add_list network.@device[0].ports='bat0' 172 | else 173 | uci set network.lan.ifname="${lan} bat0" 174 | fi 175 | uci commit network 176 | fi 177 | 178 | if [ "$apRadio" = "all" ]; then 179 | for apall in $(uci -X show wireless | grep wifi-device | awk -F'[.=]' '{print $2}'); do 180 | add_wifi_mesh 181 | done 182 | else 183 | apall=$apRadio 184 | add_wifi_mesh 185 | fi 186 | 187 | add_kvr 188 | add_dawn 189 | 190 | if [ "$ap_mode" = 1 ]; then 191 | if [ "$ap_ipaddr" != "$ipaddr" ]; then 192 | uci set network.lan.ipaddr=$ipaddr 193 | uci set network.lan.netmask=$netmask 194 | uci set network.lan.gateway=$gateway 195 | uci add_list network.lan.dns=$dns 196 | uci commit network 197 | 198 | echo "" >/etc/easymesh 199 | echo "$ipaddr" >/etc/easymesh 200 | echo "$dns" >>/etc/easymesh 201 | 202 | uci set dhcp.lan.dynamicdhcp='0' 203 | uci set dhcp.lan.ignore='1' 204 | uci -q delete dhcp.lan.ra 205 | uci -q delete dhcp.lan.dhcpv6 206 | uci -q delete dhcp.lan.ra_management 207 | uci commit dhcp 208 | 209 | /etc/init.d/odhcpd stop && /etc/init.d/odhcpd disable 210 | /etc/init.d/firewall stop && /etc/init.d/firewall disable >/dev/null 2>&1 211 | fi 212 | else 213 | ap_mode_stop 214 | fi 215 | else 216 | if [ "$mesh_bat0" = "interface" ]; then 217 | uci -q delete network.bat0 218 | if [ "$brlan" = "br-lan" ]; then 219 | uci -q del_list network.@device[0].ports='bat0' 220 | else 221 | sed -i 's/ bat0//' /etc/config/network 222 | fi 223 | uci commit network 224 | fi 225 | 226 | for apall in $(uci -X show wireless | grep wifi-device | awk -F'[.=]' '{print $2}'); do 227 | mesh_nwi_mesh=$(uci -q get network.nwi_mesh_${apall}) 228 | mesh_mesh=$(uci -q get wireless.mesh_${apall}) 229 | 230 | if [ "$mesh_nwi_mesh" = "interface" ]; then 231 | uci -q delete network.nwi_mesh_$apall 232 | uci commit network 233 | fi 234 | 235 | if [ "$mesh_mesh" = "wifi-iface" ]; then 236 | uci -q delete wireless.mesh_$apall 237 | uci commit wireless 238 | fi 239 | done 240 | 241 | add_kvr 242 | add_dawn 243 | 244 | if [ "$ap_mode" = 1 ]; then 245 | ap_mode_stop 246 | fi 247 | fi 248 | /etc/init.d/network restart 249 | } 250 | 251 | start() { 252 | return 0 253 | } 254 | 255 | stop() { 256 | return 0 257 | } 258 | 259 | restart() { 260 | set_easymesh 261 | } 262 | -------------------------------------------------------------------------------- /root/etc/uci-defaults/luci-easymesh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | uci -q batch <<-EOF >/dev/null 4 | delete ucitrack.@easymesh[-1] 5 | add ucitrack easymesh 6 | set ucitrack.@easymesh[-1].init=easymesh 7 | commit ucitrack 8 | EOF 9 | 10 | rm -f /tmp/luci-indexcache 11 | exit 0 12 | -------------------------------------------------------------------------------- /root/usr/share/rpcd/acl.d/luci-app-easymesh.json: -------------------------------------------------------------------------------- 1 | { 2 | "luci-app-easymesh": { 3 | "description": "Grant UCI access for luci-app-easymesh", 4 | "read": { 5 | "uci": [ "easymesh" ] 6 | }, 7 | "write": { 8 | "uci": [ "easymesh" ] 9 | } 10 | } 11 | } --------------------------------------------------------------------------------