Initial commit
Some checks failed
Build Kernel / Build all affected Kernels (push) Has been cancelled
Build all core packages / Build all core packages for selected target (push) Has been cancelled
Build and Push prebuilt tools container / Build and Push all prebuilt containers (push) Has been cancelled
Build Toolchains / Build Toolchains for each target (push) Has been cancelled
Build host tools / Build host tools for linux and macos based systems (push) Has been cancelled
Coverity scan build / Coverity x86/64 build (push) Has been cancelled
Some checks failed
Build Kernel / Build all affected Kernels (push) Has been cancelled
Build all core packages / Build all core packages for selected target (push) Has been cancelled
Build and Push prebuilt tools container / Build and Push all prebuilt containers (push) Has been cancelled
Build Toolchains / Build Toolchains for each target (push) Has been cancelled
Build host tools / Build host tools for linux and macos based systems (push) Has been cancelled
Coverity scan build / Coverity x86/64 build (push) Has been cancelled
This commit is contained in:
64
package/network/config/firewall/Makefile
Normal file
64
package/network/config/firewall/Makefile
Normal file
@@ -0,0 +1,64 @@
|
||||
#
|
||||
# Copyright (C) 2013-2016 OpenWrt.org
|
||||
# Copyright (C) 2016 LEDE project
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=firewall
|
||||
PKG_RELEASE:=3
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/firewall3.git
|
||||
PKG_SOURCE_DATE:=2022-02-17
|
||||
PKG_SOURCE_VERSION:=4cd7d4f36bea731bf901cb067456f1d460294926
|
||||
PKG_MIRROR_HASH:=d48a1937328b4a46b4771839d7f281a0e95e024169caa02253fc216a0907d0b9
|
||||
PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
|
||||
PKG_LICENSE:=ISC
|
||||
|
||||
PKG_CONFIG_DEPENDS := CONFIG_IPV6
|
||||
|
||||
PKG_BUILD_FLAGS:=gc-sections lto
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
|
||||
define Package/firewall
|
||||
SECTION:=net
|
||||
CATEGORY:=Base system
|
||||
TITLE:=OpenWrt C Firewall
|
||||
DEPENDS:=+libubox +libubus +libuci +libip4tc +IPV6:libip6tc +libiptext +IPV6:libiptext6 +libxtables +kmod-ipt-core +kmod-ipt-conntrack +IPV6:kmod-nf-conntrack6 +kmod-ipt-nat
|
||||
PROVIDES:=uci-firewall
|
||||
CONFLICTS:=firewall4
|
||||
endef
|
||||
|
||||
define Package/firewall/description
|
||||
This package provides a config-compatible C implementation of the UCI firewall.
|
||||
endef
|
||||
|
||||
define Package/firewall/conffiles
|
||||
/etc/config/firewall
|
||||
/etc/firewall.user
|
||||
endef
|
||||
|
||||
CMAKE_OPTIONS += $(if $(CONFIG_IPV6),,-DDISABLE_IPV6=1)
|
||||
|
||||
define Package/firewall/install
|
||||
$(INSTALL_DIR) $(1)/sbin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/firewall3 $(1)/sbin/fw3
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) ./files/firewall.init $(1)/etc/init.d/firewall
|
||||
$(INSTALL_DIR) $(1)/etc/hotplug.d/iface
|
||||
$(INSTALL_CONF) ./files/firewall.hotplug $(1)/etc/hotplug.d/iface/20-firewall
|
||||
$(INSTALL_DIR) $(1)/etc/config/
|
||||
$(INSTALL_CONF) ./files/firewall.config $(1)/etc/config/firewall
|
||||
$(INSTALL_DIR) $(1)/etc/
|
||||
$(INSTALL_CONF) ./files/firewall.user $(1)/etc/firewall.user
|
||||
$(INSTALL_DIR) $(1)/usr/share/fw3
|
||||
$(INSTALL_CONF) $(PKG_BUILD_DIR)/helpers.conf $(1)/usr/share/fw3
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,firewall))
|
||||
206
package/network/config/firewall/files/firewall.config
Normal file
206
package/network/config/firewall/files/firewall.config
Normal file
@@ -0,0 +1,206 @@
|
||||
config defaults
|
||||
option syn_flood 1
|
||||
option input REJECT
|
||||
option output ACCEPT
|
||||
option forward REJECT
|
||||
# Uncomment this line to disable ipv6 rules
|
||||
# option disable_ipv6 1
|
||||
|
||||
config zone
|
||||
option name lan
|
||||
list network 'lan'
|
||||
option input ACCEPT
|
||||
option output ACCEPT
|
||||
option forward ACCEPT
|
||||
|
||||
config zone
|
||||
option name wan
|
||||
list network 'wan'
|
||||
list network 'wan6'
|
||||
option input REJECT
|
||||
option output ACCEPT
|
||||
option forward REJECT
|
||||
option masq 1
|
||||
option mtu_fix 1
|
||||
|
||||
config forwarding
|
||||
option src lan
|
||||
option dest wan
|
||||
|
||||
# We need to accept udp packets on port 68,
|
||||
# see https://dev.openwrt.org/ticket/4108
|
||||
config rule
|
||||
option name Allow-DHCP-Renew
|
||||
option src wan
|
||||
option proto udp
|
||||
option dest_port 68
|
||||
option target ACCEPT
|
||||
option family ipv4
|
||||
|
||||
# Allow IPv4 ping
|
||||
config rule
|
||||
option name Allow-Ping
|
||||
option src wan
|
||||
option proto icmp
|
||||
option icmp_type echo-request
|
||||
option family ipv4
|
||||
option target ACCEPT
|
||||
|
||||
config rule
|
||||
option name Allow-IGMP
|
||||
option src wan
|
||||
option proto igmp
|
||||
option family ipv4
|
||||
option target ACCEPT
|
||||
|
||||
# Allow DHCPv6 replies
|
||||
# see https://github.com/openwrt/openwrt/issues/5066
|
||||
config rule
|
||||
option name Allow-DHCPv6
|
||||
option src wan
|
||||
option proto udp
|
||||
option dest_port 546
|
||||
option family ipv6
|
||||
option target ACCEPT
|
||||
|
||||
config rule
|
||||
option name Allow-MLD
|
||||
option src wan
|
||||
option proto icmp
|
||||
option src_ip fe80::/10
|
||||
list icmp_type '130/0'
|
||||
list icmp_type '131/0'
|
||||
list icmp_type '132/0'
|
||||
list icmp_type '143/0'
|
||||
option family ipv6
|
||||
option target ACCEPT
|
||||
|
||||
# Allow essential incoming IPv6 ICMP traffic
|
||||
config rule
|
||||
option name Allow-ICMPv6-Input
|
||||
option src wan
|
||||
option proto icmp
|
||||
list icmp_type echo-request
|
||||
list icmp_type echo-reply
|
||||
list icmp_type destination-unreachable
|
||||
list icmp_type packet-too-big
|
||||
list icmp_type time-exceeded
|
||||
list icmp_type bad-header
|
||||
list icmp_type unknown-header-type
|
||||
list icmp_type router-solicitation
|
||||
list icmp_type neighbour-solicitation
|
||||
list icmp_type router-advertisement
|
||||
list icmp_type neighbour-advertisement
|
||||
option limit 1000/sec
|
||||
option family ipv6
|
||||
option target ACCEPT
|
||||
|
||||
# Allow essential forwarded IPv6 ICMP traffic
|
||||
config rule
|
||||
option name Allow-ICMPv6-Forward
|
||||
option src wan
|
||||
option dest *
|
||||
option proto icmp
|
||||
list icmp_type echo-request
|
||||
list icmp_type echo-reply
|
||||
list icmp_type destination-unreachable
|
||||
list icmp_type packet-too-big
|
||||
list icmp_type time-exceeded
|
||||
list icmp_type bad-header
|
||||
list icmp_type unknown-header-type
|
||||
option limit 1000/sec
|
||||
option family ipv6
|
||||
option target ACCEPT
|
||||
|
||||
config rule
|
||||
option name Allow-IPSec-ESP
|
||||
option src wan
|
||||
option dest lan
|
||||
option proto esp
|
||||
option target ACCEPT
|
||||
|
||||
config rule
|
||||
option name Allow-ISAKMP
|
||||
option src wan
|
||||
option dest lan
|
||||
option dest_port 500
|
||||
option proto udp
|
||||
option target ACCEPT
|
||||
|
||||
# allow interoperability with traceroute classic
|
||||
# note that traceroute uses a fixed port range, and depends on getting
|
||||
# back ICMP Unreachables. if we're operating in DROP mode, it won't
|
||||
# work so we explicitly REJECT packets on these ports.
|
||||
config rule
|
||||
option name Support-UDP-Traceroute
|
||||
option src wan
|
||||
option dest_port 33434:33689
|
||||
option proto udp
|
||||
option family ipv4
|
||||
option target REJECT
|
||||
option enabled false
|
||||
|
||||
# include a file with users custom iptables rules
|
||||
config include
|
||||
option path /etc/firewall.user
|
||||
|
||||
|
||||
### EXAMPLE CONFIG SECTIONS
|
||||
# do not allow a specific ip to access wan
|
||||
#config rule
|
||||
# option src lan
|
||||
# option src_ip 192.168.45.2
|
||||
# option dest wan
|
||||
# option proto tcp
|
||||
# option target REJECT
|
||||
|
||||
# block a specific mac on wan
|
||||
#config rule
|
||||
# option dest wan
|
||||
# option src_mac 00:11:22:33:44:66
|
||||
# option target REJECT
|
||||
|
||||
# block incoming ICMP traffic on a zone
|
||||
#config rule
|
||||
# option src lan
|
||||
# option proto ICMP
|
||||
# option target DROP
|
||||
|
||||
# port redirect port coming in on wan to lan
|
||||
#config redirect
|
||||
# option src wan
|
||||
# option src_dport 80
|
||||
# option dest lan
|
||||
# option dest_ip 192.168.16.235
|
||||
# option dest_port 80
|
||||
# option proto tcp
|
||||
|
||||
# port redirect of remapped ssh port (22001) on wan
|
||||
#config redirect
|
||||
# option src wan
|
||||
# option src_dport 22001
|
||||
# option dest lan
|
||||
# option dest_port 22
|
||||
# option proto tcp
|
||||
|
||||
### FULL CONFIG SECTIONS
|
||||
#config rule
|
||||
# option src lan
|
||||
# option src_ip 192.168.45.2
|
||||
# option src_mac 00:11:22:33:44:55
|
||||
# option src_port 80
|
||||
# option dest wan
|
||||
# option dest_ip 194.25.2.129
|
||||
# option dest_port 120
|
||||
# option proto tcp
|
||||
# option target REJECT
|
||||
|
||||
#config redirect
|
||||
# option src lan
|
||||
# option src_ip 192.168.45.2
|
||||
# option src_mac 00:11:22:33:44:55
|
||||
# option src_port 1024
|
||||
# option src_dport 80
|
||||
# option dest_ip 194.25.2.129
|
||||
# option dest_port 120
|
||||
# option proto tcp
|
||||
11
package/network/config/firewall/files/firewall.hotplug
Normal file
11
package/network/config/firewall/files/firewall.hotplug
Normal file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ "$ACTION" = ifup -o "$ACTION" = ifupdate ] || exit 0
|
||||
[ "$ACTION" = ifupdate -a -z "$IFUPDATE_ADDRESSES" -a -z "$IFUPDATE_DATA" ] && exit 0
|
||||
|
||||
/etc/init.d/firewall enabled || exit 0
|
||||
|
||||
fw3 -q network "$INTERFACE" >/dev/null || exit 0
|
||||
|
||||
logger -t firewall "Reloading firewall due to $ACTION of $INTERFACE ($DEVICE)"
|
||||
fw3 -q reload
|
||||
61
package/network/config/firewall/files/firewall.init
Executable file
61
package/network/config/firewall/files/firewall.init
Executable file
@@ -0,0 +1,61 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=19
|
||||
USE_PROCD=1
|
||||
QUIET=""
|
||||
|
||||
validate_firewall_redirect()
|
||||
{
|
||||
uci_validate_section firewall redirect "${1}" \
|
||||
'proto:or(uinteger, string)' \
|
||||
'src:string' \
|
||||
'src_ip:cidr' \
|
||||
'src_dport:or(port, portrange)' \
|
||||
'dest:string' \
|
||||
'dest_ip:cidr' \
|
||||
'dest_port:or(port, portrange)' \
|
||||
'target:or("SNAT", "DNAT")'
|
||||
}
|
||||
|
||||
validate_firewall_rule()
|
||||
{
|
||||
uci_validate_section firewall rule "${1}" \
|
||||
'proto:or(uinteger, string)' \
|
||||
'src:string' \
|
||||
'dest:string' \
|
||||
'src_port:or(port, portrange)' \
|
||||
'dest_port:or(port, portrange)' \
|
||||
'target:string'
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger firewall
|
||||
|
||||
procd_open_validate
|
||||
validate_firewall_redirect
|
||||
validate_firewall_rule
|
||||
procd_close_validate
|
||||
}
|
||||
|
||||
restart() {
|
||||
fw3 restart
|
||||
}
|
||||
|
||||
start_service() {
|
||||
fw3 ${QUIET} start
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
fw3 flush
|
||||
}
|
||||
|
||||
reload_service() {
|
||||
fw3 reload
|
||||
}
|
||||
|
||||
boot() {
|
||||
# Be silent on boot, firewall might be started by hotplug already,
|
||||
# so don't complain in syslog.
|
||||
QUIET=-q
|
||||
start
|
||||
}
|
||||
7
package/network/config/firewall/files/firewall.user
Normal file
7
package/network/config/firewall/files/firewall.user
Normal file
@@ -0,0 +1,7 @@
|
||||
# This file is interpreted as shell script.
|
||||
# Put your custom iptables rules here, they will
|
||||
# be executed with each firewall (re-)start.
|
||||
|
||||
# Internal uci firewall chains are flushed and recreated on reload, so
|
||||
# put custom rules into the root chains e.g. INPUT or FORWARD or into the
|
||||
# special user chains, e.g. input_wan_rule or postrouting_lan_rule.
|
||||
50
package/network/config/firewall4/Makefile
Normal file
50
package/network/config/firewall4/Makefile
Normal file
@@ -0,0 +1,50 @@
|
||||
#
|
||||
# Copyright (C) 2021 Jo-Philipp Wich <jo@mein.io>
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=firewall4
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/firewall4.git
|
||||
PKG_SOURCE_DATE:=2024-05-21
|
||||
PKG_SOURCE_VERSION:=4c01d1ebf99e8ecfa69758a9b4f450ecef7b93cd
|
||||
PKG_MIRROR_HASH:=bbc5622bc03e3b43116fcc86e3fa2d2372bfc07b3a00d2b3a6efac4f7454a403
|
||||
PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
|
||||
PKG_LICENSE:=ISC
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/firewall4
|
||||
SECTION:=net
|
||||
CATEGORY:=Base system
|
||||
TITLE:=OpenWrt 4th gen firewall
|
||||
DEPENDS:= \
|
||||
+kmod-nft-core +kmod-nft-fib +kmod-nft-offload \
|
||||
+kmod-nft-nat \
|
||||
+nftables-json \
|
||||
+ucode +ucode-mod-fs +ucode-mod-ubus +ucode-mod-uci
|
||||
EXTRA_DEPENDS:=ucode (>=2022.03.22)
|
||||
PROVIDES:=uci-firewall
|
||||
endef
|
||||
|
||||
define Package/firewall4/description
|
||||
This package provides an nftables-based implementation of the UCI firewall
|
||||
sharing the same configuration format.
|
||||
endef
|
||||
|
||||
define Package/firewall4/conffiles
|
||||
/etc/config/firewall
|
||||
/etc/nftables.d/
|
||||
endef
|
||||
|
||||
define Package/firewall4/install
|
||||
$(CP) -a $(PKG_BUILD_DIR)/root/* $(1)/
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,firewall4))
|
||||
44
package/network/config/gre/Makefile
Normal file
44
package/network/config/gre/Makefile
Normal file
@@ -0,0 +1,44 @@
|
||||
#
|
||||
# Copyright (C) 2014 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=gre
|
||||
PKG_RELEASE:=13
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/gre/Default
|
||||
endef
|
||||
|
||||
define Package/gre
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
MAINTAINER:=Hans Dedecker <dedeckeh@gmail.com>
|
||||
TITLE:=Generic Routing Encapsulation config support
|
||||
DEPENDS:=+kmod-gre +IPV6:kmod-gre6 +resolveip
|
||||
PROVIDES:=grev4 grev6
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/gre/description
|
||||
Generic Routing Encapsulation config support (IPv4 and IPv6) in /etc/config/network.
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Package/gre/install
|
||||
$(INSTALL_DIR) $(1)/lib/netifd/proto
|
||||
$(INSTALL_BIN) ./files/gre.sh $(1)/lib/netifd/proto/gre.sh
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,gre))
|
||||
296
package/network/config/gre/files/gre.sh
Executable file
296
package/network/config/gre/files/gre.sh
Executable file
@@ -0,0 +1,296 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ -n "$INCLUDE_ONLY" ] || {
|
||||
. /lib/functions.sh
|
||||
. /lib/functions/network.sh
|
||||
. ../netifd-proto.sh
|
||||
init_proto "$@"
|
||||
}
|
||||
|
||||
gre_generic_setup() {
|
||||
local cfg="$1"
|
||||
local mode="$2"
|
||||
local local="$3"
|
||||
local remote="$4"
|
||||
local link="$5"
|
||||
local mtu ipv6 ttl tos zone ikey okey icsum ocsum iseqno oseqno multicast
|
||||
json_get_vars mtu ipv6 ttl tos zone ikey okey icsum ocsum iseqno oseqno multicast
|
||||
|
||||
[ -z "$multicast" ] && multicast=1
|
||||
|
||||
proto_init_update "$link" 1
|
||||
|
||||
proto_add_tunnel
|
||||
json_add_string mode "$mode"
|
||||
json_add_int mtu "${mtu:-1280}"
|
||||
json_add_boolean ipv6 "${ipv6:-1}"
|
||||
[ -n "$df" ] && json_add_boolean df "$df"
|
||||
[ -n "$ttl" ] && json_add_int ttl "$ttl"
|
||||
[ -n "$tos" ] && json_add_string tos "$tos"
|
||||
json_add_boolean multicast "$multicast"
|
||||
json_add_string local "$local"
|
||||
json_add_string remote "$remote"
|
||||
[ -n "$tunlink" ] && json_add_string link "$tunlink"
|
||||
|
||||
json_add_object 'data'
|
||||
[ -n "$ikey" ] && json_add_int ikey "$ikey"
|
||||
[ -n "$okey" ] && json_add_int okey "$okey"
|
||||
[ -n "$icsum" ] && json_add_boolean icsum "$icsum"
|
||||
[ -n "$ocsum" ] && json_add_boolean ocsum "$ocsum"
|
||||
[ -n "$iseqno" ] && json_add_boolean iseqno "$iseqno"
|
||||
[ -n "$oseqno" ] && json_add_boolean oseqno "$oseqno"
|
||||
[ -n "$encaplimit" ] && json_add_string encaplimit "$encaplimit"
|
||||
json_close_object
|
||||
|
||||
proto_close_tunnel
|
||||
|
||||
proto_add_data
|
||||
[ -n "$zone" ] && json_add_string zone "$zone"
|
||||
proto_close_data
|
||||
|
||||
proto_send_update "$cfg"
|
||||
}
|
||||
|
||||
gre_setup() {
|
||||
local cfg="$1"
|
||||
local mode="$2"
|
||||
local remoteip
|
||||
|
||||
local ipaddr peeraddr
|
||||
json_get_vars df ipaddr peeraddr tunlink nohostroute
|
||||
|
||||
[ -z "$peeraddr" ] && {
|
||||
proto_notify_error "$cfg" "MISSING_PEER_ADDRESS"
|
||||
proto_block_restart "$cfg"
|
||||
exit
|
||||
}
|
||||
|
||||
remoteip=$(resolveip -t 10 -4 "$peeraddr")
|
||||
|
||||
if [ -z "$remoteip" ]; then
|
||||
proto_notify_error "$cfg" "PEER_RESOLVE_FAIL"
|
||||
exit
|
||||
fi
|
||||
|
||||
for ip in $remoteip; do
|
||||
peeraddr=$ip
|
||||
break
|
||||
done
|
||||
|
||||
if [ "${nohostroute}" != "1" ]; then
|
||||
( proto_add_host_dependency "$cfg" "$peeraddr" "$tunlink" )
|
||||
fi
|
||||
|
||||
[ -z "$ipaddr" ] && {
|
||||
local wanif="$tunlink"
|
||||
if [ -z $wanif ] && ! network_find_wan wanif; then
|
||||
proto_notify_error "$cfg" "NO_WAN_LINK"
|
||||
exit
|
||||
fi
|
||||
|
||||
if ! network_get_ipaddr ipaddr "$wanif"; then
|
||||
proto_notify_error "$cfg" "NO_WAN_LINK"
|
||||
exit
|
||||
fi
|
||||
}
|
||||
|
||||
[ -z "$df" ] && df="1"
|
||||
|
||||
case "$mode" in
|
||||
gretapip)
|
||||
gre_generic_setup $cfg $mode $ipaddr $peeraddr "gre4t-$cfg"
|
||||
;;
|
||||
*)
|
||||
gre_generic_setup $cfg $mode $ipaddr $peeraddr "gre4-$cfg"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
proto_gre_setup() {
|
||||
local cfg="$1"
|
||||
|
||||
gre_setup $cfg "greip"
|
||||
}
|
||||
|
||||
proto_gretap_setup() {
|
||||
local cfg="$1"
|
||||
|
||||
local network
|
||||
json_get_vars network
|
||||
|
||||
gre_setup $cfg "gretapip"
|
||||
|
||||
json_init
|
||||
json_add_string name "gre4t-$cfg"
|
||||
json_add_boolean link-ext 0
|
||||
json_close_object
|
||||
|
||||
for i in $network; do
|
||||
ubus call network.interface."$i" add_device "$(json_dump)"
|
||||
done
|
||||
}
|
||||
|
||||
grev6_setup() {
|
||||
local cfg="$1"
|
||||
local mode="$2"
|
||||
local remoteip6
|
||||
|
||||
local ip6addr peer6addr weakif
|
||||
json_get_vars ip6addr peer6addr tunlink weakif encaplimit nohostroute
|
||||
|
||||
[ -z "$peer6addr" ] && {
|
||||
proto_notify_error "$cfg" "MISSING_PEER_ADDRESS"
|
||||
proto_block_restart "$cfg"
|
||||
exit
|
||||
}
|
||||
|
||||
remoteip6=$(resolveip -t 10 -6 "$peer6addr")
|
||||
|
||||
if [ -z "$remoteip6" ]; then
|
||||
proto_notify_error "$cfg" "PEER_RESOLVE_FAIL"
|
||||
exit
|
||||
fi
|
||||
|
||||
for ip6 in $remoteip6; do
|
||||
peer6addr=$ip6
|
||||
break
|
||||
done
|
||||
|
||||
if [ "${nohostroute}" != "1" ]; then
|
||||
( proto_add_host_dependency "$cfg" "$peer6addr" "$tunlink" )
|
||||
fi
|
||||
|
||||
[ -z "$ip6addr" ] && {
|
||||
local wanif="$tunlink"
|
||||
if [ -z $wanif ] && ! network_find_wan6 wanif; then
|
||||
proto_notify_error "$cfg" "NO_WAN_LINK"
|
||||
exit
|
||||
fi
|
||||
|
||||
if ! network_get_ipaddr6 ip6addr "$wanif"; then
|
||||
[ -z "$weakif" ] && weakif="lan"
|
||||
if ! network_get_ipaddr6 ip6addr "$weakif"; then
|
||||
proto_notify_error "$cfg" "NO_WAN_LINK"
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
case "$mode" in
|
||||
gretapip6)
|
||||
gre_generic_setup $cfg $mode $ip6addr $peer6addr "gre6t-$cfg"
|
||||
;;
|
||||
*)
|
||||
gre_generic_setup $cfg $mode $ip6addr $peer6addr "gre6-$cfg"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
proto_grev6_setup() {
|
||||
local cfg="$1"
|
||||
|
||||
grev6_setup $cfg "greip6"
|
||||
}
|
||||
|
||||
proto_grev6tap_setup() {
|
||||
local cfg="$1"
|
||||
|
||||
local network
|
||||
json_get_vars network
|
||||
|
||||
grev6_setup $cfg "gretapip6"
|
||||
|
||||
json_init
|
||||
json_add_string name "gre6t-$cfg"
|
||||
json_add_boolean link-ext 0
|
||||
json_close_object
|
||||
|
||||
for i in $network; do
|
||||
ubus call network.interface."$i" add_device "$(json_dump)"
|
||||
done
|
||||
}
|
||||
|
||||
gretap_generic_teardown() {
|
||||
local network
|
||||
json_get_vars network
|
||||
|
||||
json_init
|
||||
json_add_string name "$1"
|
||||
json_add_boolean link-ext 0
|
||||
json_close_object
|
||||
|
||||
for i in $network; do
|
||||
ubus call network.interface."$i" remove_device "$(json_dump)"
|
||||
done
|
||||
}
|
||||
|
||||
proto_gre_teardown() {
|
||||
local cfg="$1"
|
||||
}
|
||||
|
||||
proto_gretap_teardown() {
|
||||
local cfg="$1"
|
||||
|
||||
gretap_generic_teardown "gre4t-$cfg"
|
||||
}
|
||||
|
||||
proto_grev6_teardown() {
|
||||
local cfg="$1"
|
||||
}
|
||||
|
||||
proto_grev6tap_teardown() {
|
||||
local cfg="$1"
|
||||
|
||||
gretap_generic_teardown "gre6t-$cfg"
|
||||
}
|
||||
|
||||
gre_generic_init_config() {
|
||||
no_device=1
|
||||
available=1
|
||||
|
||||
proto_config_add_int "mtu"
|
||||
proto_config_add_boolean "ipv6"
|
||||
proto_config_add_int "ttl"
|
||||
proto_config_add_string "tos"
|
||||
proto_config_add_string "tunlink"
|
||||
proto_config_add_string "zone"
|
||||
proto_config_add_int "ikey"
|
||||
proto_config_add_int "okey"
|
||||
proto_config_add_boolean "icsum"
|
||||
proto_config_add_boolean "ocsum"
|
||||
proto_config_add_boolean "iseqno"
|
||||
proto_config_add_boolean "oseqno"
|
||||
proto_config_add_boolean "multicast"
|
||||
}
|
||||
|
||||
proto_gre_init_config() {
|
||||
gre_generic_init_config
|
||||
proto_config_add_string "ipaddr"
|
||||
proto_config_add_string "peeraddr"
|
||||
proto_config_add_boolean "df"
|
||||
proto_config_add_boolean "nohostroute"
|
||||
}
|
||||
|
||||
proto_gretap_init_config() {
|
||||
proto_gre_init_config
|
||||
proto_config_add_string "network"
|
||||
}
|
||||
|
||||
proto_grev6_init_config() {
|
||||
gre_generic_init_config
|
||||
proto_config_add_string "ip6addr"
|
||||
proto_config_add_string "peer6addr"
|
||||
proto_config_add_string "weakif"
|
||||
proto_config_add_string "encaplimit"
|
||||
proto_config_add_boolean "nohostroute"
|
||||
}
|
||||
|
||||
proto_grev6tap_init_config() {
|
||||
proto_grev6_init_config
|
||||
proto_config_add_string "network"
|
||||
}
|
||||
|
||||
[ -n "$INCLUDE_ONLY" ] || {
|
||||
[ -d /sys/module/ip_gre ] && { add_protocol gre; add_protocol gretap; }
|
||||
[ -d /sys/module/ip6_gre ] && { add_protocol grev6; add_protocol grev6tap; }
|
||||
}
|
||||
40
package/network/config/ipip/Makefile
Normal file
40
package/network/config/ipip/Makefile
Normal file
@@ -0,0 +1,40 @@
|
||||
#
|
||||
# Copyright (C) 2014 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ipip
|
||||
PKG_RELEASE:=4
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/ipip
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
MAINTAINER:=Hans Dedecker <dedeckeh@gmail.com>
|
||||
TITLE:=IP in IP Tunnel config support
|
||||
DEPENDS:= +kmod-ipip +resolveip
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/ipip/description
|
||||
IP in IP Tunnel config support in /etc/config/network.
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Package/ipip/install
|
||||
$(INSTALL_DIR) $(1)/lib/netifd/proto
|
||||
$(INSTALL_BIN) ./files/ipip.sh $(1)/lib/netifd/proto/ipip.sh
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ipip))
|
||||
94
package/network/config/ipip/files/ipip.sh
Executable file
94
package/network/config/ipip/files/ipip.sh
Executable file
@@ -0,0 +1,94 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ -n "$INCLUDE_ONLY" ] || {
|
||||
. /lib/functions.sh
|
||||
. /lib/functions/network.sh
|
||||
. ../netifd-proto.sh
|
||||
init_proto "$@"
|
||||
}
|
||||
|
||||
proto_ipip_setup() {
|
||||
local cfg="$1"
|
||||
local remoteip
|
||||
|
||||
local df ipaddr peeraddr tunlink ttl tos zone mtu
|
||||
json_get_vars df ipaddr peeraddr tunlink ttl tos zone mtu nohostroute
|
||||
|
||||
[ -z "$peeraddr" ] && {
|
||||
proto_notify_error "$cfg" "MISSING_PEER_ADDRESS"
|
||||
proto_block_restart "$cfg"
|
||||
return
|
||||
}
|
||||
|
||||
remoteip=$(resolveip -t 10 -4 "$peeraddr")
|
||||
|
||||
if [ -z "$remoteip" ]; then
|
||||
proto_notify_error "$cfg" "PEER_RESOLVE_FAIL"
|
||||
return
|
||||
fi
|
||||
|
||||
for ip in $remoteip; do
|
||||
peeraddr=$ip
|
||||
break
|
||||
done
|
||||
|
||||
if [ "${nohostroute}" != "1" ]; then
|
||||
( proto_add_host_dependency "$cfg" "$peeraddr" "$tunlink" )
|
||||
fi
|
||||
|
||||
[ -z "$ipaddr" ] && {
|
||||
local wanif="$tunlink"
|
||||
if [ -z $wanif ] && ! network_find_wan wanif; then
|
||||
proto_notify_error "$cfg" "NO_WAN_LINK"
|
||||
return
|
||||
fi
|
||||
|
||||
if ! network_get_ipaddr ipaddr "$wanif"; then
|
||||
proto_notify_error "$cfg" "NO_WAN_LINK"
|
||||
return
|
||||
fi
|
||||
}
|
||||
|
||||
proto_init_update "ipip-$cfg" 1
|
||||
|
||||
proto_add_tunnel
|
||||
json_add_string mode "ipip"
|
||||
json_add_int mtu "${mtu:-1280}"
|
||||
json_add_int ttl "${ttl:-64}"
|
||||
[ -n "$tos" ] && json_add_string tos "$tos"
|
||||
json_add_string local "$ipaddr"
|
||||
json_add_string remote "$peeraddr"
|
||||
[ -n "$tunlink" ] && json_add_string link "$tunlink"
|
||||
json_add_boolean df "${df:-1}"
|
||||
|
||||
proto_close_tunnel
|
||||
|
||||
proto_add_data
|
||||
[ -n "$zone" ] && json_add_string zone "$zone"
|
||||
proto_close_data
|
||||
|
||||
proto_send_update "$cfg"
|
||||
}
|
||||
|
||||
proto_ipip_teardown() {
|
||||
local cfg="$1"
|
||||
}
|
||||
|
||||
proto_ipip_init_config() {
|
||||
no_device=1
|
||||
available=1
|
||||
|
||||
proto_config_add_int "mtu"
|
||||
proto_config_add_int "ttl"
|
||||
proto_config_add_string "tos"
|
||||
proto_config_add_string "tunlink"
|
||||
proto_config_add_string "zone"
|
||||
proto_config_add_string "ipaddr"
|
||||
proto_config_add_string "peeraddr"
|
||||
proto_config_add_boolean "df"
|
||||
proto_config_add_boolean "nohostroute"
|
||||
}
|
||||
|
||||
[ -n "$INCLUDE_ONLY" ] || {
|
||||
add_protocol ipip
|
||||
}
|
||||
92
package/network/config/ltq-adsl-app/Makefile
Normal file
92
package/network/config/ltq-adsl-app/Makefile
Normal file
@@ -0,0 +1,92 @@
|
||||
#
|
||||
# Copyright (C) 2011-2012 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=dsl_cpe_control_danube
|
||||
PKG_VERSION:=3.24.4.4
|
||||
PKG_RELEASE:=11
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/dsl_cpe_control-$(PKG_VERSION)
|
||||
PKG_SOURCE_URL:=@OPENWRT
|
||||
PKG_HASH:=af0bdf45cc7a62e2b38d39aad4924dd83c24fae170ae5bbd8190c2a3d9106257
|
||||
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
|
||||
PKG_LICENSE:=BSD-3-Clause
|
||||
|
||||
PKG_FIXUP:=autoreconf
|
||||
|
||||
PKG_CONFIG_DEPENDS:=\
|
||||
CONFIG_LTQ_DSL_ENABLE_SOAP \
|
||||
CONFIG_LTQ_DSL_ENABLE_DSL_EVENT_POLLING
|
||||
|
||||
PKG_BUILD_DEPENDS:=ltq-adsl
|
||||
|
||||
PKG_FLAGS:=nonshared
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/ltq-adsl-app
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=Lantiq DSL userland tool
|
||||
URL:=http://www.lantiq.com/
|
||||
DEPENDS:=@(TARGET_lantiq_xway||TARGET_lantiq_xway_legacy||TARGET_lantiq_ase) +libpthread +ltq-dsl-base +libubox +libubus
|
||||
PROVIDES:=ltq-dsl-app
|
||||
MENU:=1
|
||||
endef
|
||||
|
||||
define Package/ltq-adsl-app/description
|
||||
Infineon DSL CPE API for Amazon SE, Danube and Vinax.
|
||||
endef
|
||||
|
||||
LTQ_DSL_MAX_DEVICE=1
|
||||
LTQ_DSL_LINES_PER_DEVICE=1
|
||||
LTQ_DSL_CHANNELS_PER_LINE=1
|
||||
|
||||
CONFIGURE_ARGS += \
|
||||
--with-max-device="$(LTQ_DSL_MAX_DEVICE)" \
|
||||
--with-lines-per-device="$(LTQ_DSL_LINES_PER_DEVICE)" \
|
||||
--with-channels-per-line="$(LTQ_DSL_CHANNELS_PER_LINE)" \
|
||||
--enable-danube \
|
||||
--enable-driver-include="-I$(STAGING_DIR)/usr/include/adsl/" \
|
||||
--enable-debug-prints \
|
||||
--enable-add-appl-cflags="-DMAX_CLI_PIPES=2" \
|
||||
--enable-cli-support \
|
||||
--enable-cmv-scripts \
|
||||
--enable-debug-tool-interface \
|
||||
--enable-adsl-led \
|
||||
--enable-dsl-ceoc \
|
||||
--enable-script-notification \
|
||||
--enable-dsl-pm \
|
||||
--enable-dsl-pm-total \
|
||||
--enable-dsl-pm-history \
|
||||
--enable-dsl-pm-showtime \
|
||||
--enable-dsl-pm-channel-counters \
|
||||
--enable-dsl-pm-datapath-counters \
|
||||
--enable-dsl-pm-line-counters \
|
||||
--enable-dsl-pm-channel-thresholds \
|
||||
--enable-dsl-pm-datapath-thresholds \
|
||||
--enable-dsl-pm-line-thresholds \
|
||||
--enable-dsl-pm-optional-parameters
|
||||
|
||||
TARGET_CFLAGS += -I$(LINUX_DIR)/include
|
||||
|
||||
define Build/Prepare
|
||||
$(call Build/Prepare/Default)
|
||||
$(CP) ../ltq-vdsl-vr9-app/src/src/dsl_cpe_ubus.c $(PKG_BUILD_DIR)/src/
|
||||
endef
|
||||
|
||||
define Package/ltq-adsl-app/install
|
||||
$(INSTALL_DIR) $(1)/etc/init.d $(1)/sbin $(1)/etc/hotplug.d/dsl
|
||||
$(INSTALL_BIN) ./files/dsl_control $(1)/etc/init.d/
|
||||
$(INSTALL_BIN) ./files/10_atm.sh $(1)/etc/hotplug.d/dsl
|
||||
$(INSTALL_BIN) ./files/10_ptm.sh $(1)/etc/hotplug.d/dsl
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/dsl_cpe_control $(1)/sbin
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ltq-adsl-app))
|
||||
29
package/network/config/ltq-adsl-app/files/10_atm.sh
Executable file
29
package/network/config/ltq-adsl-app/files/10_atm.sh
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ "$DSL_NOTIFICATION_TYPE" = "DSL_STATUS" ] && \
|
||||
[ "$DSL_TC_LAYER_STATUS" = "ATM" ] && \
|
||||
! grep -q "ltq_atm_ar9\|ltq_atm_ase\|ltq_atm_danube" /proc/modules || exit 0
|
||||
|
||||
logger -p daemon.notice -t "dsl-notify" "Switching to TC-Layer ATM"
|
||||
|
||||
if grep -q "ltq_ptm_ar9\|ltq_ptm_ase\|ltq_ptm_danube" /proc/modules ; then
|
||||
logger -p daemon.notice -t "dsl-notify" "Loading ATM driver while EFM/PTM driver is loaded is not possible. Reboot is needed."
|
||||
exit
|
||||
fi
|
||||
|
||||
case "$(strings /proc/device-tree/compatible)" in
|
||||
*lantiq,ar9*)
|
||||
soc="ar9"
|
||||
;;
|
||||
*lantiq,ase*)
|
||||
soc="ase"
|
||||
;;
|
||||
*lantiq,danube*)
|
||||
soc="danube"
|
||||
;;
|
||||
*)
|
||||
logger -p daemon.notice -t "dsl-notify" "Unsupported SoC"
|
||||
exit
|
||||
esac
|
||||
|
||||
modprobe ltq_atm_${soc}
|
||||
29
package/network/config/ltq-adsl-app/files/10_ptm.sh
Executable file
29
package/network/config/ltq-adsl-app/files/10_ptm.sh
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ "$DSL_NOTIFICATION_TYPE" = "DSL_STATUS" ] && \
|
||||
[ "$DSL_TC_LAYER_STATUS" = "EFM" ] && \
|
||||
! grep -q "ltq_ptm_ar9\|ltq_ptm_ase\|ltq_ptm_danube" /proc/modules || exit 0
|
||||
|
||||
logger -p daemon.notice -t "dsl-notify" "Switching to TC-Layer EFM/PTM"
|
||||
|
||||
if grep -q "ltq_atm_ar9\|ltq_atm_ase\|ltq_atm_danube" /proc/modules ; then
|
||||
logger -p daemon.notice -t "dsl-notify" "Loading EFM/PTM driver while ATM driver is loaded is not possible. Reboot is needed."
|
||||
exit
|
||||
fi
|
||||
|
||||
case "$(strings /proc/device-tree/compatible)" in
|
||||
*lantiq,ar9*)
|
||||
soc="ar9"
|
||||
;;
|
||||
*lantiq,ase*)
|
||||
soc="ase"
|
||||
;;
|
||||
*lantiq,danube*)
|
||||
soc="danube"
|
||||
;;
|
||||
*)
|
||||
logger -p daemon.notice -t "dsl-notify" "Unsupported SoC"
|
||||
exit
|
||||
esac
|
||||
|
||||
modprobe ltq_ptm_${soc}
|
||||
65
package/network/config/ltq-adsl-app/files/dsl_control
Normal file
65
package/network/config/ltq-adsl-app/files/dsl_control
Normal file
@@ -0,0 +1,65 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2012 OpenWrt.org
|
||||
|
||||
START=97
|
||||
USE_PROCD=1
|
||||
|
||||
dslstat() {
|
||||
ubus call dsl metrics
|
||||
}
|
||||
|
||||
extra_command "dslstat" "Get DSL status information"
|
||||
|
||||
annex_b=10_00_10_00_00_04_00_00
|
||||
annex_bdmt=10_00_00_00_00_00_00_00
|
||||
annex_b2=00_00_10_00_00_00_00_00
|
||||
annex_b2p=00_00_00_00_00_04_00_00
|
||||
annex_a=05_01_04_00_4C_01_04_00
|
||||
annex_at1=01_00_00_00_00_00_00_00
|
||||
annex_alite=00_01_00_00_00_00_00_00
|
||||
annex_admt=04_00_00_00_00_00_00_00
|
||||
annex_a2=00_00_04_00_00_00_00_00
|
||||
annex_a2p=00_00_00_00_00_01_00_00
|
||||
annex_l=00_00_00_00_0C_00_00_00
|
||||
annex_m=00_00_00_00_40_00_04_00
|
||||
annex_m2=00_00_00_00_40_00_00_00
|
||||
annex_m2p=00_00_00_00_00_00_04_00
|
||||
annex_j=10_00_10_40_00_04_01_00
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger network
|
||||
}
|
||||
|
||||
start_service() {
|
||||
local annex
|
||||
local firmware
|
||||
local xtu
|
||||
config_load network
|
||||
config_get annex dsl annex
|
||||
config_get firmware dsl firmware
|
||||
|
||||
eval "xtu=\"\${annex_$annex}\""
|
||||
|
||||
[ -z "${firmware}" ] &&
|
||||
firmware=/lib/firmware/adsl.bin
|
||||
[ -f "${firmware}" ] || {
|
||||
echo failed to find $firmware
|
||||
return 1
|
||||
}
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command /sbin/dsl_cpe_control \
|
||||
-i${xtu} \
|
||||
-n /sbin/dsl_notify.sh \
|
||||
-f ${firmware}
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
DSL_NOTIFICATION_TYPE="DSL_INTERFACE_STATUS" \
|
||||
DSL_INTERFACE_STATUS="DOWN" \
|
||||
/sbin/dsl_notify.sh
|
||||
|
||||
service_stop /sbin/dsl_cpe_control
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
--- a/src/dsl_cpe_cli_access.c
|
||||
+++ b/src/dsl_cpe_cli_access.c
|
||||
@@ -1142,7 +1142,7 @@ DSL_CLI_LOCAL DSL_int_t DSL_CPE_CLI_Auto
|
||||
|
||||
if ((ret < 0) && (autobootCtrl.accessCtl.nReturn < DSL_SUCCESS))
|
||||
{
|
||||
- DSL_CPE_FPrintf (out, sFailureReturn, autobootCtrl.accessCtl.nReturn);
|
||||
+ DSL_CPE_FPrintf (out, sFailureReturn, autobootCtrl.accessCtl.nReturn, DSL_CPE_Fd2DevStr(fd));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1213,7 +1213,7 @@ DSL_CLI_LOCAL DSL_int_t DSL_CPE_CLI_Auto
|
||||
|
||||
if ((ret < 0) && (pData.accessCtl.nReturn < DSL_SUCCESS))
|
||||
{
|
||||
- DSL_CPE_FPrintf (out, sFailureReturn, pData.accessCtl.nReturn);
|
||||
+ DSL_CPE_FPrintf (out, sFailureReturn, pData.accessCtl.nReturn, DSL_CPE_Fd2DevStr(fd));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1290,7 +1290,7 @@ DSL_CLI_LOCAL DSL_int_t DSL_CPE_CLI_Line
|
||||
|
||||
if ((ret < 0) && (pData.accessCtl.nReturn < DSL_SUCCESS))
|
||||
{
|
||||
- DSL_CPE_FPrintf (out, sFailureReturn, pData.accessCtl.nReturn);
|
||||
+ DSL_CPE_FPrintf (out, sFailureReturn, pData.accessCtl.nReturn, DSL_CPE_Fd2DevStr(fd));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1355,7 +1355,7 @@ DSL_CLI_LOCAL DSL_int_t DSL_CPE_CLI_Reso
|
||||
pCtx, &resourceUsageStatisticsData);
|
||||
if (ret < 0)
|
||||
{
|
||||
- DSL_CPE_FPrintf (out, sFailureReturn, ret);
|
||||
+ DSL_CPE_FPrintf (out, sFailureReturn, ret, DSL_CPE_Fd2DevStr(fd));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3084,7 +3084,7 @@ DSL_CLI_LOCAL DSL_int_t DSL_CPE_CLI_G997
|
||||
|
||||
if ((ret < 0) && (pData->accessCtl.nReturn < DSL_SUCCESS))
|
||||
{
|
||||
- DSL_CPE_FPrintf (out, sFailureReturn, pData->accessCtl.nReturn);
|
||||
+ DSL_CPE_FPrintf (out, sFailureReturn, pData->accessCtl.nReturn, DSL_CPE_Fd2DevStr(fd));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4654,7 +4654,7 @@ DSL_CLI_LOCAL DSL_int_t DSL_CPE_CLI_G997
|
||||
|
||||
if ((ret < 0) && (pData.accessCtl.nReturn < DSL_SUCCESS))
|
||||
{
|
||||
- DSL_CPE_FPrintf (out, sFailureReturn, pData.accessCtl.nReturn);
|
||||
+ DSL_CPE_FPrintf (out, sFailureReturn, pData.accessCtl.nReturn, DSL_CPE_Fd2DevStr(fd));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -5714,7 +5714,7 @@ DSL_CLI_LOCAL DSL_int_t DSL_CPE_CLI_G997
|
||||
|
||||
if ((ret < 0) && (pData.accessCtl.nReturn < DSL_SUCCESS))
|
||||
{
|
||||
- DSL_CPE_FPrintf (out, sFailureReturn, pData.accessCtl.nReturn);
|
||||
+ DSL_CPE_FPrintf (out, sFailureReturn, pData.accessCtl.nReturn, DSL_CPE_Fd2DevStr(fd));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -0,0 +1,23 @@
|
||||
--- a/configure.in
|
||||
+++ b/configure.in
|
||||
@@ -29,6 +29,8 @@ AC_C_VOLATILE
|
||||
#AC_FUNC_STRTOD
|
||||
#AC_CHECK_FUNCS([ftime gethostbyname gettimeofday localtime_r memset select socket strchr strerror strstr strtoull])
|
||||
|
||||
+AC_SEARCH_LIBS([clock_gettime],[rt])
|
||||
+
|
||||
#
|
||||
# save the configure arguments
|
||||
#
|
||||
--- a/src/dsl_cpe_linux.h
|
||||
+++ b/src/dsl_cpe_linux.h
|
||||
@@ -45,7 +45,8 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h> /* socket */
|
||||
#include <sys/sem.h> /* semget */
|
||||
-#include <semaphore.h> /* sem_t */
|
||||
+#include <semaphore.h> /* sem_t */
|
||||
+#include <limits.h>
|
||||
|
||||
#ifdef DSL_DEBUG_TOOL_INTERFACE
|
||||
#include <sys/socket.h>
|
||||
@@ -0,0 +1,42 @@
|
||||
From 9d4f86ba2cf10304303011f4f5628fa68dc77624 Mon Sep 17 00:00:00 2001
|
||||
From: Mathias Kresin <dev@kresin.me>
|
||||
Date: Mon, 16 Oct 2017 21:08:26 +0200
|
||||
Subject: ltq-adsl-app: add more script notifications
|
||||
|
||||
Backport HANDSHAKE and TRAINING notification from ltq-vdsl-vr9-app. It
|
||||
unifies the dsl led blinking pattern accross all subtargets and allows
|
||||
to get the current line status from the dsl led.
|
||||
|
||||
Signed-off-by: Mathias Kresin <dev@kresin.me>
|
||||
---
|
||||
.../100-add-more-script-notifications.patch | 27 ++++++++++++++++++++++
|
||||
1 file changed, 27 insertions(+)
|
||||
create mode 100644 package/network/config/ltq-adsl-app/patches/100-add-more-script-notifications.patch
|
||||
|
||||
--- a/src/dsl_cpe_control.c
|
||||
+++ b/src/dsl_cpe_control.c
|
||||
@@ -3273,7 +3273,23 @@ DSL_CPE_STATIC DSL_int_t DSL_CPE_Event_S
|
||||
#ifdef INCLUDE_SCRIPT_NOTIFICATION
|
||||
if (g_sRcScript != DSL_NULL)
|
||||
{
|
||||
- if ( (nLineState == DSL_LINESTATE_SHOWTIME_TC_SYNC) &&
|
||||
+ if ( (nLineState == DSL_LINESTATE_HANDSHAKE) &&
|
||||
+ (g_nPrevLineState[nDevice] != DSL_LINESTATE_HANDSHAKE) )
|
||||
+ {
|
||||
+ if (DSL_CPE_SetEnv("DSL_INTERFACE_STATUS", "HANDSHAKE") == DSL_SUCCESS)
|
||||
+ {
|
||||
+ bExec = DSL_TRUE;
|
||||
+ }
|
||||
+ }
|
||||
+ else if ( (nLineState == DSL_LINESTATE_FULL_INIT) &&
|
||||
+ (g_nPrevLineState[nDevice] != DSL_LINESTATE_FULL_INIT) )
|
||||
+ {
|
||||
+ if (DSL_CPE_SetEnv("DSL_INTERFACE_STATUS", "TRAINING") == DSL_SUCCESS)
|
||||
+ {
|
||||
+ bExec = DSL_TRUE;
|
||||
+ }
|
||||
+ }
|
||||
+ else if ( (nLineState == DSL_LINESTATE_SHOWTIME_TC_SYNC) &&
|
||||
(g_nPrevLineState[nDevice] != DSL_LINESTATE_SHOWTIME_TC_SYNC) )
|
||||
{
|
||||
if (DSL_CPE_SetEnv("DSL_INTERFACE_STATUS", "UP") == DSL_SUCCESS)
|
||||
50
package/network/config/ltq-adsl-app/patches/300-ubus.patch
Normal file
50
package/network/config/ltq-adsl-app/patches/300-ubus.patch
Normal file
@@ -0,0 +1,50 @@
|
||||
--- a/src/dsl_cpe_control.c
|
||||
+++ b/src/dsl_cpe_control.c
|
||||
@@ -139,6 +139,9 @@ extern DSL_Error_t DSL_CPE_Pipe_StaticRe
|
||||
#endif /* INCLUDE_DSL_RESOURCE_STATISTICS*/
|
||||
#endif
|
||||
|
||||
+extern void ubus_init();
|
||||
+extern void ubus_deinit();
|
||||
+
|
||||
DSL_char_t *g_sFirmwareName1 = DSL_NULL;
|
||||
DSL_char_t *g_sFirmwareName2 = DSL_NULL;
|
||||
#ifdef INCLUDE_SCRIPT_NOTIFICATION
|
||||
@@ -5343,6 +5346,8 @@ DSL_int_t dsl_cpe_daemon (
|
||||
signal (SIGINT, DSL_CPE_TerminationHandler);
|
||||
#endif /* RTEMS*/
|
||||
|
||||
+ ubus_init();
|
||||
+
|
||||
/* Open DSL_CPE_MAX_DEVICE_NUMBER devices*/
|
||||
for (nDevice = 0; nDevice < DSL_CPE_MAX_DEVICE_NUMBER; nDevice++)
|
||||
{
|
||||
@@ -5738,6 +5743,7 @@ DSL_int_t dsl_cpe_daemon (
|
||||
#endif /* INCLUDE_DSL_CPE_CLI_SUPPORT */
|
||||
|
||||
DSL_CPE_CONTROL_EXIT:
|
||||
+ ubus_deinit();
|
||||
|
||||
#ifdef INCLUDE_DSL_BONDING
|
||||
DSL_CPE_BND_Stop((DSL_CPE_BND_Context_t*)pCtrlCtx->pBnd);
|
||||
--- a/src/Makefile.am
|
||||
+++ b/src/Makefile.am
|
||||
@@ -11,7 +11,7 @@ else
|
||||
dsl_cpe_control_common_ldflags =
|
||||
endif
|
||||
|
||||
-dsl_cpe_control_LDADD = -lpthread
|
||||
+dsl_cpe_control_LDADD = -lpthread -lubox -lubus
|
||||
|
||||
if INCLUDE_DSL_CPE_SOAP_SUPPORT
|
||||
dsl_cpe_control_LDADD += -lm
|
||||
@@ -70,7 +70,8 @@ dsl_cpe_control_SOURCES = \
|
||||
dsl_cpe_control.c \
|
||||
dsl_cpe_init_cfg.c \
|
||||
dsl_cpe_linux.c \
|
||||
- dsl_cpe_debug.c
|
||||
+ dsl_cpe_debug.c \
|
||||
+ dsl_cpe_ubus.c
|
||||
|
||||
dsl_cpe_control_SOURCES += \
|
||||
$(dsl_cpe_control_dti_sources)
|
||||
92
package/network/config/ltq-vdsl-vr11-app/Makefile
Normal file
92
package/network/config/ltq-vdsl-vr11-app/Makefile
Normal file
@@ -0,0 +1,92 @@
|
||||
# Copyright (C) 2010 OpenWrt.org
|
||||
# Copyright (C) 2015-2016 Lantiq Beteiligungs GmbH & Co KG.
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=ltq-vdsl-vr11-app
|
||||
PKG_VERSION:=4.23.1
|
||||
PKG_RELEASE:=2
|
||||
PKG_BASE_NAME:=dsl_cpe_control
|
||||
|
||||
UGW_VERSION=8.5.2.10
|
||||
UGW_BASENAME=$(PKG_BASE_NAME)-ugw_$(UGW_VERSION)
|
||||
|
||||
PKG_SOURCE:=$(UGW_BASENAME).tar.bz2
|
||||
PKG_SOURCE_URL:=https://gitlab.com/prpl-foundation/intel/$(PKG_BASE_NAME)/-/archive/ugw_$(UGW_VERSION)/
|
||||
PKG_HASH:=d21ec74ca30f7f3893a8aa26d2b74ec319652f6b112832efab6f1274c7e5d1fc
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(UGW_BASENAME)
|
||||
PKG_LICENSE:=BSD-2-Clause
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
|
||||
PKG_BUILD_DEPENDS:=ltq-vdsl-vr11
|
||||
|
||||
PKG_FLAGS:=nonshared
|
||||
PKG_FIXUP:=autoreconf
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/ltq-vdsl-vr11-app
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=Lantiq VDSL userland tool
|
||||
URL:=http://www.lantiq.com/
|
||||
DEPENDS:=@TARGET_ipq40xx +libpthread +librt +libubox +libubus +ltq-dsl-base +kmod-ltq-vdsl-vr11
|
||||
PROVIDES:=ltq-dsl-app
|
||||
endef
|
||||
|
||||
define Package/ltq-vdsl-vr11-app/description
|
||||
Userland tool needed to control Lantiq VDSL CPE
|
||||
endef
|
||||
|
||||
# ltq-vdsl-vr11-app uses a header provided by the MEI driver which has some
|
||||
# conditionals.
|
||||
#
|
||||
# Define them here with the default values they would get in the MEI driver,
|
||||
# have the same view on both sides.
|
||||
#
|
||||
# If you change them, you need to change them for the ltq-vdsl-vr11-app as well
|
||||
VDSL_APP_CFLAGS = \
|
||||
-DMAX_CLI_PIPES=1 \
|
||||
-DMEI_SUPPORT_DEBUG_STREAMS=1 \
|
||||
-DMEI_SUPPORT_OPTIMIZED_FW_DL=1
|
||||
|
||||
CONFIGURE_ARGS += \
|
||||
--enable-debug-logger-support=no
|
||||
|
||||
CONFIGURE_ARGS += \
|
||||
--enable-vrx \
|
||||
--enable-vrx-device=vr11 \
|
||||
--enable-driver-include="-I$(STAGING_DIR)/usr/include/drv_vdsl_cpe_api" \
|
||||
--enable-device-driver-include="-I$(STAGING_DIR)/usr/include/vdsl/" \
|
||||
--enable-ifxos \
|
||||
--enable-ifxos-include="-I$(STAGING_DIR)/usr/include/ifxos" \
|
||||
--enable-ifxos-library="-I$(STAGING_DIR)/usr/lib" \
|
||||
--enable-add-appl-cflags="$(VDSL_APP_CFLAGS)" \
|
||||
--enable-debug \
|
||||
--disable-dti
|
||||
|
||||
CONFIGURE_ARGS += \
|
||||
--enable-model=full \
|
||||
--enable-dsl-ceoc=no
|
||||
#CONFIGURE_ARGS += --enable-model=lite
|
||||
#CONFIGURE_ARGS += --enable-model=footprint
|
||||
#CONFIGURE_ARGS += --enable-model=typical
|
||||
#CONFIGURE_ARGS += --enable-model=debug
|
||||
|
||||
define Build/Prepare
|
||||
$(call Build/Prepare/Default)
|
||||
$(CP) ../ltq-vdsl-vr9-app/src/src/dsl_cpe_ubus.c $(PKG_BUILD_DIR)/src/
|
||||
endef
|
||||
|
||||
define Package/ltq-vdsl-vr11-app/install
|
||||
$(INSTALL_DIR) $(1)/etc/init.d $(1)/sbin $(1)/etc/hotplug.d/dsl
|
||||
$(INSTALL_BIN) ./files/dsl_control $(1)/etc/init.d/
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/dsl_cpe_control $(1)/sbin/vdsl_cpe_control
|
||||
$(INSTALL_BIN) ./files/dsl_cpe_pipe.sh $(1)/sbin/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ltq-vdsl-vr11-app))
|
||||
264
package/network/config/ltq-vdsl-vr11-app/files/dsl_control
Normal file
264
package/network/config/ltq-vdsl-vr11-app/files/dsl_control
Normal file
@@ -0,0 +1,264 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2012 OpenWrt.org
|
||||
|
||||
START=97
|
||||
USE_PROCD=1
|
||||
|
||||
dslstat() {
|
||||
ubus call dsl metrics
|
||||
}
|
||||
|
||||
extra_command "dslstat" "Get DSL status information"
|
||||
|
||||
#
|
||||
# ITU-T G.997.1 (06/2012) - Section 7.3.1.1.1 (xTU transmission system enabling (XTSE))
|
||||
# ITU-T G.997.1 Amendment 2 (04/2013) - Section 2.1 - (Vectoring mode enable (VECTORMODE_ENABLE))
|
||||
#
|
||||
# G.992.1 Annex A
|
||||
# G.992.2 Annex A
|
||||
# G.992.3 Annex A / L-US1 / L_US-2 / M
|
||||
# G.992.5 Annex A / M
|
||||
# G.993.2 Annex A/B/C
|
||||
# G.993.5 Annex A/B/C
|
||||
xtse_xdsl_a="05_01_04_00_4C_01_04_07"
|
||||
|
||||
# G.992.1 Annex B
|
||||
# G.992.3 Annex B
|
||||
# G.992.5 Annex B
|
||||
# G.993.2 Annex A/B/C
|
||||
# G.993.5 Annex A/B/C
|
||||
xtse_xdsl_b="10_00_10_00_00_04_00_07"
|
||||
|
||||
# G.992.1 Annex B
|
||||
# G.992.3 Annex B
|
||||
# G.992.3 Annex J
|
||||
# G.992.5 Annex B
|
||||
# G.992.5 Annex J
|
||||
# G.993.2 Annex A/B/C
|
||||
# G.993.5 Annex A/B/C
|
||||
xtse_xdsl_j="10_00_10_40_00_04_01_07"
|
||||
|
||||
# G.992.1 Annex B
|
||||
xtse_xdsl_bdmt="10_00_00_00_00_00_00_00"
|
||||
|
||||
# G.992.3 Annex B
|
||||
xtse_xdsl_b2="00_00_10_00_00_00_00_00"
|
||||
|
||||
# G.992.5 Annex B
|
||||
xtse_xdsl_b2p="00_00_00_00_00_04_00_00"
|
||||
|
||||
# ANSI T1.413
|
||||
xtse_xdsl_at1="01_00_00_00_00_00_00_00"
|
||||
|
||||
# G.992.2 Annex A
|
||||
xtse_xdsl_alite="00_01_00_00_00_00_00_00"
|
||||
|
||||
# G.992.1 Annex A
|
||||
xtse_xdsl_admt="04_00_00_00_00_00_00_00"
|
||||
|
||||
# G.992.3 Annex A
|
||||
xtse_xdsl_a2="00_00_04_00_00_00_00_00"
|
||||
|
||||
# G.992.5 Annex A
|
||||
xtse_xdsl_a2p="00_00_00_00_00_01_00_00"
|
||||
|
||||
# G.992.3 Annex L
|
||||
xtse_xdsl_l="00_00_00_00_0C_00_00_00"
|
||||
|
||||
# G.992.3 Annex M
|
||||
# G.992.5 Annex M
|
||||
xtse_xdsl_m="00_00_00_00_40_00_04_00"
|
||||
|
||||
# G.992.3 Annex M
|
||||
xtse_xdsl_m2="00_00_00_00_40_00_00_00"
|
||||
|
||||
# G.992.5 Annex M
|
||||
xtse_xdsl_m2p="00_00_00_00_00_00_04_00"
|
||||
|
||||
#
|
||||
# ITU-T G.994.1 (06/2012) - Table 2 (Mandatory carrier sets)
|
||||
#
|
||||
|
||||
# A43
|
||||
tone_adsl_a="0x142" # A43C + J43 + A43
|
||||
tone_vdsl_a="0x142" # A43C + J43 + A43
|
||||
|
||||
# A43 + V43
|
||||
tone_adsl_av="0x142" # A43C + J43 + A43
|
||||
tone_vdsl_av="0x146" # A43C + J43 + A43 + V43
|
||||
|
||||
# B43
|
||||
tone_adsl_b="0x81" # B43 + B43c
|
||||
tone_vdsl_b="0x1" # B43
|
||||
|
||||
# B43 + V43
|
||||
tone_adsl_bv="0x81" # B43 + B43c
|
||||
tone_vdsl_bv="0x5" # B43 + V43
|
||||
|
||||
# create DSL autoboot script. Used for SNR margin tweak and to set MAC address for vectoring error reports
|
||||
autoboot_script() {
|
||||
echo "[WaitForConfiguration]={
|
||||
locs nLine=0 0 $1
|
||||
dsmmcs nLine=0 $2
|
||||
}
|
||||
|
||||
[WaitForLinkActivate]={
|
||||
}
|
||||
|
||||
[WaitForRestart]={
|
||||
}
|
||||
|
||||
[Common]={
|
||||
}" > /tmp/dsl.scr
|
||||
}
|
||||
|
||||
lowlevel_cfg() {
|
||||
echo "# VRX Low Level Configuration File
|
||||
#
|
||||
# Parameters must be separated by tabs or spaces.
|
||||
# Empty lines and comments will be ignored.
|
||||
#
|
||||
|
||||
# nFilter
|
||||
#
|
||||
# NA = -1
|
||||
# OFF = 0
|
||||
# ISDN = 1
|
||||
# POTS = 2
|
||||
# POTS_2 = 3
|
||||
# POTS_3 = 4
|
||||
#
|
||||
# (dec)
|
||||
-1
|
||||
|
||||
# nHsToneGroupMode nHsToneGroup_A nHsToneGroup_V nHsToneGroup_AV
|
||||
#
|
||||
# NA = -1 NA = -1 see see
|
||||
# AUTO = 0 VDSL2_B43 = 0x0001 nHsToneGroup_A nHsToneGroup_A
|
||||
# MANUAL = 1 VDSL2_A43 = 0x0002
|
||||
# VDSL2_V43 = 0x0004
|
||||
# VDSL1_V43P = 0x0008
|
||||
# VDSL1_V43I = 0x0010
|
||||
# ADSL1_C43 = 0x0020
|
||||
# ADSL2_J43 = 0x0040
|
||||
# ADSL2_B43C = 0x0080
|
||||
# ADSL2_A43C = 0x0100
|
||||
#
|
||||
# (dec) (hex) (hex) (hex)
|
||||
1 $1 $2 0x0
|
||||
|
||||
# nBaseAddr nIrqNum
|
||||
#
|
||||
# (hex) (dec)
|
||||
0x1e116000 63
|
||||
|
||||
# nUtopiaPhyAdr nUtopiaBusWidth nPosPhyParity
|
||||
# default(16b) = 0 NA = -1
|
||||
# 8-bit = 1 ODD = 0
|
||||
# 16-bit = 2
|
||||
#
|
||||
#
|
||||
# (hex) (dec) (dec)
|
||||
0xFF 0 0
|
||||
|
||||
# bNtrEnable
|
||||
#
|
||||
# (dec)
|
||||
0" > /tmp/lowlevel.cfg
|
||||
}
|
||||
|
||||
get_macaddr() {
|
||||
local name
|
||||
config_get name $1 name
|
||||
[ "$name" = "dsl0" ] && config_get $2 $1 macaddr
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger network
|
||||
}
|
||||
|
||||
start_service() {
|
||||
local annex
|
||||
local firmware
|
||||
local tone
|
||||
local tone_adsl
|
||||
local tone_vdsl
|
||||
local xtse
|
||||
local xfer_mode
|
||||
local line_mode
|
||||
local tc_layer
|
||||
local mode
|
||||
local lowlevel
|
||||
local snr
|
||||
local macaddr
|
||||
|
||||
config_load network
|
||||
config_get tone dsl tone
|
||||
config_get annex dsl annex
|
||||
config_get firmware dsl firmware
|
||||
config_get xfer_mode dsl xfer_mode
|
||||
config_get line_mode dsl line_mode
|
||||
config_get snr dsl ds_snr_offset
|
||||
config_foreach get_macaddr device macaddr
|
||||
|
||||
eval "xtse=\"\${xtse_xdsl_$annex}\""
|
||||
|
||||
case "${xfer_mode}" in
|
||||
atm)
|
||||
tc_layer="-T1:0x1:0x1_1:0x1:0x1"
|
||||
;;
|
||||
ptm)
|
||||
tc_layer="-T2:0x1:0x1_2:0x1:0x1"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "${line_mode}" in
|
||||
adsl)
|
||||
mode="-M1"
|
||||
|
||||
# mask out VDSL bits when ADSL is requested
|
||||
xtse="${xtse%_*}_00"
|
||||
;;
|
||||
vdsl)
|
||||
mode="-M2"
|
||||
|
||||
# mask out ADSL bits when VDSL is requested
|
||||
xtse="00_00_00_00_00_00_00_${xtse##*_}"
|
||||
;;
|
||||
esac
|
||||
|
||||
[ -z "${firmware}" ] && firmware=/lib/firmware/vdsl.bin
|
||||
[ -f "${firmware}" ] || {
|
||||
echo failed to find $firmware
|
||||
return 1
|
||||
}
|
||||
|
||||
eval "tone_adsl=\"\${tone_adsl_$tone}\""
|
||||
eval "tone_vdsl=\"\${tone_vdsl_$tone}\""
|
||||
[ -n "${tone_adsl}" ] && [ -n "${tone_vdsl}" ] && {
|
||||
lowlevel_cfg "${tone_adsl}" "${tone_vdsl}"
|
||||
lowlevel="-l /tmp/lowlevel.cfg"
|
||||
}
|
||||
|
||||
[ -z "${snr}" ] && snr=0
|
||||
[ -z "${macaddr}" ] && macaddr="00:00:00:00:00:00"
|
||||
autoboot_script "$snr" "$macaddr"
|
||||
autoboot="-a /tmp/dsl.scr -A /tmp/dsl.scr"
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command /sbin/vdsl_cpe_control \
|
||||
-i$xtse \
|
||||
-n /sbin/dsl_notify.sh \
|
||||
-f ${firmware} \
|
||||
$lowlevel \
|
||||
${mode} \
|
||||
${tc_layer} \
|
||||
$autoboot
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
DSL_NOTIFICATION_TYPE="DSL_INTERFACE_STATUS" \
|
||||
DSL_INTERFACE_STATUS="DOWN" \
|
||||
/sbin/dsl_notify.sh
|
||||
}
|
||||
18
package/network/config/ltq-vdsl-vr11-app/files/dsl_cpe_pipe.sh
Executable file
18
package/network/config/ltq-vdsl-vr11-app/files/dsl_cpe_pipe.sh
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
|
||||
pipe_no=0
|
||||
|
||||
# use specified pipe no
|
||||
case "$1" in
|
||||
0|1|2)
|
||||
pipe_no=$1; shift; ;;
|
||||
esac
|
||||
|
||||
|
||||
#echo "Call dsl_pipe with $*"
|
||||
lock /var/lock/dsl_pipe
|
||||
echo $* > /tmp/pipe/dsl_cpe${pipe_no}_cmd
|
||||
result=$(cat /tmp/pipe/dsl_cpe${pipe_no}_ack)
|
||||
lock -u /var/lock/dsl_pipe
|
||||
|
||||
echo "$result"
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/src/dsl_cpe_init_cfg.c
|
||||
+++ b/src/dsl_cpe_init_cfg.c
|
||||
@@ -38,7 +38,7 @@ DSL_InitData_t gInitCfgData =
|
||||
DSL_DEV_HS_TONE_GROUP_CLEANED, \
|
||||
DSL_DEV_HS_TONE_GROUP_CLEANED, \
|
||||
DSL_DEV_HS_TONE_GROUP_CLEANED, \
|
||||
- 0x1E116000, 0x37, -1),
|
||||
+ 0x1E116000, 0x3f, -1),
|
||||
DSL_CPE_SIC_SET(DSL_TC_ATM, DSL_EMF_TC_CLEANED, DSL_EMF_TC_CLEANED, DSL_SYSTEMIF_MII, \
|
||||
DSL_TC_EFM, DSL_EMF_TC_CLEANED, DSL_EMF_TC_CLEANED, DSL_SYSTEMIF_MII),
|
||||
DSL_CPE_MAC_CFG_SET(DSL_EFM_SPEED_100, DSL_EFM_DUPLEX_FULL, DSL_EFM_FLOWCTRL_ON, DSL_EFM_AUTONEG_OFF, \
|
||||
@@ -0,0 +1,87 @@
|
||||
--- a/src/dsl_cpe_control.h
|
||||
+++ b/src/dsl_cpe_control.h
|
||||
@@ -13,6 +13,8 @@
|
||||
#ifndef _DSL_CPE_CONTROL_H
|
||||
#define _DSL_CPE_CONTROL_H
|
||||
|
||||
+#include <string.h>
|
||||
+
|
||||
/** \defgroup DSL_CPE_CONTROL Lantiq DSL CPE API Control Application
|
||||
Lists the entire modules to the DSL CPE_API Control Application.
|
||||
@{ */
|
||||
--- a/src/dsl_cpe_safec_wrapper.h
|
||||
+++ b/src/dsl_cpe_safec_wrapper.h
|
||||
@@ -23,7 +23,7 @@
|
||||
#define cpe_control_vsnprintf_s vsnprintf_s
|
||||
|
||||
/* snprintf_s symbol is not exported in SafeC lib */
|
||||
-static int cpe_control_snprintf_s(char *dest,
|
||||
+static inline int cpe_control_snprintf_s(char *dest,
|
||||
size_t dmax,
|
||||
const char *fmt,
|
||||
...)
|
||||
@@ -40,7 +40,7 @@ static int cpe_control_snprintf_s(char *
|
||||
|
||||
#else
|
||||
|
||||
-#warning "Safe C library is not available!"
|
||||
+//#warning "Safe C library is not available!"
|
||||
|
||||
#include <stddef.h> /* size_t */
|
||||
#include <stdarg.h> /* va_list */
|
||||
@@ -55,7 +55,7 @@ static __inline__ size_t safec_wrapper_m
|
||||
#define cpe_control_memset_s(dest, destsz, src, srcsz) memset(dest, src, safec_wrapper_min(destsz,srcsz))
|
||||
#define cpe_control_strncpy_s(dest, destsz, src, srcsz) strncpy(dest, src, safec_wrapper_min(destsz,srcsz))
|
||||
|
||||
-static size_t cpe_control_strnlen_s(const char *str,
|
||||
+static inline size_t cpe_control_strnlen_s(const char *str,
|
||||
size_t smax)
|
||||
{
|
||||
/* preconditions */
|
||||
@@ -74,7 +74,7 @@ static size_t cpe_control_strnlen_s(cons
|
||||
return size;
|
||||
}
|
||||
|
||||
-static char *cpe_control_strtok_s(char *dest,
|
||||
+static inline char *cpe_control_strtok_s(char *dest,
|
||||
size_t *dmax,
|
||||
const char *delim,
|
||||
char **ptr)
|
||||
@@ -123,7 +123,7 @@ static char *cpe_control_strtok_s(char *
|
||||
return pTmp;
|
||||
}
|
||||
|
||||
-static int cpe_control_pipe_strcat_s(char *dest,
|
||||
+static inline int cpe_control_pipe_strcat_s(char *dest,
|
||||
size_t destsz,
|
||||
char *src)
|
||||
{
|
||||
@@ -157,7 +157,7 @@ static int cpe_control_pipe_strcat_s(cha
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int cpe_control_snprintf_s(char *dest,
|
||||
+static inline int cpe_control_snprintf_s(char *dest,
|
||||
size_t dmax,
|
||||
const char *fmt,
|
||||
...)
|
||||
@@ -181,7 +181,7 @@ static int cpe_control_snprintf_s(char *
|
||||
return retVal;
|
||||
}
|
||||
|
||||
-static int cpe_control_vsnprintf_s(char *dest,
|
||||
+static inline int cpe_control_vsnprintf_s(char *dest,
|
||||
size_t dmax,
|
||||
const char *fmt,
|
||||
va_list vlist)
|
||||
--- a/tools/pipe/dsl_cpe_safec_wrapper.h
|
||||
+++ b/tools/pipe/dsl_cpe_safec_wrapper.h
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#else
|
||||
|
||||
-#warning "Safe C library is not available!"
|
||||
+//#warning "Safe C library is not available!"
|
||||
|
||||
#include <stddef.h> /* size_t */
|
||||
static __inline__ size_t safec_wrapper_min(size_t a, size_t b)
|
||||
@@ -0,0 +1,85 @@
|
||||
This enables automatic connection after the control daemon is started,
|
||||
and also changes the way the connection is stopped on termination.
|
||||
|
||||
Using the autoboot restart command is necessary because the stop command
|
||||
would stop the autoboot thread, and the driver offers no working way to
|
||||
start it again later, short of unloading and reloading the module.
|
||||
|
||||
--- a/src/dsl_cpe_init_cfg.c
|
||||
+++ b/src/dsl_cpe_init_cfg.c
|
||||
@@ -27,7 +27,7 @@ DSL_InitData_t gInitCfgData =
|
||||
DSL_CPE_FW2_SET(DSL_NULL, 0x0),
|
||||
DSL_CPE_XTU_SET(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7),
|
||||
DSL_CPE_LINE_INV_NE_SET(DSL_NULL),
|
||||
- DSL_CPE_AUTOBOOT_CTRL_SET(DSL_AUTOBOOT_CTRL_STOP),
|
||||
+ DSL_CPE_AUTOBOOT_CTRL_SET(DSL_AUTOBOOT_CTRL_START),
|
||||
DSL_CPE_AUTOBOOT_CFG_SET(DSL_FALSE, DSL_FALSE, DSL_FALSE),
|
||||
DSL_CPE_TEST_MODE_CTRL_SET(DSL_TESTMODE_DISABLE),
|
||||
DSL_CPE_LINE_ACTIVATE_CTRL_SET(DSL_G997_INHIBIT_LDSF, DSL_G997_INHIBIT_ACSF, DSL_G997_NORMAL_STARTUP),
|
||||
--- a/src/dsl_cpe_control.c
|
||||
+++ b/src/dsl_cpe_control.c
|
||||
@@ -7338,6 +7338,7 @@ DSL_CPE_STATIC DSL_void_t DSL_CPE_Termi
|
||||
{
|
||||
DSL_Error_t nRet = DSL_SUCCESS;
|
||||
DSL_int_t nDevice = 0;
|
||||
+ DSL_AutobootConfig_t sAutobootCfg;
|
||||
DSL_AutobootControl_t sAutobootCtl;
|
||||
DSL_CPE_Control_Context_t *pCtrlCtx = DSL_NULL;
|
||||
|
||||
@@ -7349,8 +7350,32 @@ DSL_CPE_STATIC DSL_void_t DSL_CPE_Termi
|
||||
|
||||
for (nDevice = 0; nDevice < DSL_CPE_DSL_ENTITIES; ++nDevice)
|
||||
{
|
||||
+ g_bWaitBeforeConfigWrite[nDevice] = DSL_TRUE;
|
||||
+ g_bWaitBeforeLinkActivation[nDevice] = DSL_TRUE;
|
||||
+ g_bWaitBeforeRestart[nDevice] = DSL_TRUE;
|
||||
+
|
||||
+ g_bAutoContinueWaitBeforeConfigWrite[nDevice] = DSL_FALSE;
|
||||
+ g_bAutoContinueWaitBeforeLinkActivation[nDevice] = DSL_FALSE;
|
||||
+ g_bAutoContinueWaitBeforeRestart[nDevice] = DSL_FALSE;
|
||||
+
|
||||
+ memset(&sAutobootCfg, 0x0, sizeof(DSL_AutobootConfig_t));
|
||||
+ sAutobootCfg.data.nStateMachineOptions.bWaitBeforeConfigWrite = DSL_TRUE;
|
||||
+ sAutobootCfg.data.nStateMachineOptions.bWaitBeforeLinkActivation = DSL_TRUE;
|
||||
+ sAutobootCfg.data.nStateMachineOptions.bWaitBeforeRestart = DSL_TRUE;
|
||||
+
|
||||
+ nRet = (DSL_Error_t)DSL_CPE_Ioctl(
|
||||
+ DSL_CPE_GetGlobalContext()->fd[nDevice],
|
||||
+ DSL_FIO_AUTOBOOT_CONFIG_SET, (DSL_int_t)&sAutobootCfg);
|
||||
+
|
||||
+ if (nRet < DSL_SUCCESS)
|
||||
+ {
|
||||
+ DSL_CCA_DEBUG(DSL_CCA_DBG_ERR, (DSL_CPE_PREFIX
|
||||
+ "Autoboot configuration for device (%d) failed!, nRet = %d!"
|
||||
+ DSL_CPE_CRLF, nDevice, sAutobootCtl.accessCtl.nReturn));
|
||||
+ }
|
||||
+
|
||||
memset(&sAutobootCtl, 0, sizeof(DSL_AutobootControl_t));
|
||||
- sAutobootCtl.data.nCommand = DSL_AUTOBOOT_CTRL_STOP;
|
||||
+ sAutobootCtl.data.nCommand = DSL_AUTOBOOT_CTRL_RESTART;
|
||||
|
||||
nRet = (DSL_Error_t)DSL_CPE_Ioctl(
|
||||
DSL_CPE_GetGlobalContext()->fd[nDevice],
|
||||
@@ -7359,13 +7384,13 @@ DSL_CPE_STATIC DSL_void_t DSL_CPE_Termi
|
||||
if (nRet < DSL_SUCCESS)
|
||||
{
|
||||
DSL_CCA_DEBUG(DSL_CCA_DBG_ERR, (DSL_CPE_PREFIX
|
||||
- "Autoboot stop for device (%d) failed!, nRet = %d!"
|
||||
+ "Autoboot restart for device (%d) failed!, nRet = %d!"
|
||||
DSL_CPE_CRLF, nDevice, sAutobootCtl.accessCtl.nReturn));
|
||||
}
|
||||
}
|
||||
|
||||
DSL_CCA_DEBUG(DSL_CCA_DBG_MSG, (DSL_CPE_PREFIX
|
||||
- "Autoboot stop executed" DSL_CPE_CRLF));
|
||||
+ "Autoboot restart executed" DSL_CPE_CRLF));
|
||||
|
||||
DSL_CPE_DaemonExit();
|
||||
|
||||
@@ -8798,4 +8823,4 @@ DSL_CPE_STATIC DSL_Error_t DSL_CPE_Firmw
|
||||
pDecimal));
|
||||
|
||||
return nErrCode;
|
||||
-}
|
||||
\ No newline at end of file
|
||||
+}
|
||||
@@ -0,0 +1,50 @@
|
||||
--- a/src/dsl_cpe_control.c
|
||||
+++ b/src/dsl_cpe_control.c
|
||||
@@ -221,6 +221,9 @@ extern DSL_Error_t DSL_CPE_Pipe_StaticRe
|
||||
#endif /* INCLUDE_DSL_RESOURCE_STATISTICS*/
|
||||
#endif
|
||||
|
||||
+extern void ubus_init();
|
||||
+extern void ubus_deinit();
|
||||
+
|
||||
DSL_char_t *g_sFirmwareName1 = DSL_NULL;
|
||||
DSL_FirmwareFeatures_t g_nFwFeatures1 = {DSL_FW_XDSLMODE_CLEANED, DSL_FW_XDSLFEATURE_CLEANED,
|
||||
DSL_FW_XDSLFEATURE_CLEANED};
|
||||
@@ -7831,6 +7834,8 @@ DSL_int_t dsl_cpe_daemon (
|
||||
#endif /* defined(INCLUDE_DSL_JSON_PARSING) && (INCLUDE_DSL_JSON_PARSING == 1) */
|
||||
#endif /* RTEMS*/
|
||||
|
||||
+ ubus_init();
|
||||
+
|
||||
/* Open DSL_CPE_MAX_DSL_ENTITIES devices*/
|
||||
for (nDevice = 0; nDevice < DSL_CPE_DSL_ENTITIES; nDevice++)
|
||||
{
|
||||
@@ -8367,6 +8372,7 @@ DSL_int_t dsl_cpe_daemon (
|
||||
#endif /* INCLUDE_DSL_CPE_CLI_SUPPORT */
|
||||
|
||||
DSL_CPE_CONTROL_EXIT:
|
||||
+ ubus_deinit();
|
||||
|
||||
if (INCLUDE_DSL_BONDING)
|
||||
{
|
||||
--- a/src/Makefile.am
|
||||
+++ b/src/Makefile.am
|
||||
@@ -17,7 +17,7 @@ else
|
||||
dsl_cpe_control_common_ldflags =
|
||||
endif
|
||||
|
||||
-dsl_cpe_control_LDADD = -lpthread -lrt
|
||||
+dsl_cpe_control_LDADD = -lpthread -lrt -lubox -lubus
|
||||
|
||||
if INCLUDE_DSL_CPE_DTI_SUPPORT
|
||||
dsl_cpe_control_LDADD += -ldti_agent
|
||||
@@ -118,7 +118,8 @@ dsl_cpe_control_SOURCES = \
|
||||
dsl_cpe_control.c \
|
||||
dsl_cpe_init_cfg.c \
|
||||
dsl_cpe_linux.c \
|
||||
- dsl_cpe_debug.c
|
||||
+ dsl_cpe_debug.c \
|
||||
+ dsl_cpe_ubus.c
|
||||
|
||||
dsl_cpe_control_SOURCES += \
|
||||
$(dsl_cpe_control_dti_sources)
|
||||
83
package/network/config/ltq-vdsl-vr9-app/Makefile
Normal file
83
package/network/config/ltq-vdsl-vr9-app/Makefile
Normal file
@@ -0,0 +1,83 @@
|
||||
# Copyright (C) 2010 OpenWrt.org
|
||||
# Copyright (C) 2015-2016 Lantiq Beteiligungs GmbH & Co KG.
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=ltq-vdsl-vr9-app
|
||||
PKG_VERSION:=4.17.18.6
|
||||
PKG_RELEASE:=5
|
||||
PKG_BASE_NAME:=dsl_cpe_control
|
||||
PKG_SOURCE:=$(PKG_BASE_NAME)_vrx-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=@OPENWRT
|
||||
PKG_HASH:=da8bb929526a61aea0e153ef524331fcd472a1ebbc6d88ca017735a4f82ece02
|
||||
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_BASE_NAME)-$(PKG_VERSION)
|
||||
PKG_LICENSE:=BSD-2-Clause
|
||||
|
||||
PKG_BUILD_DEPENDS:=ltq-vdsl-vr9
|
||||
|
||||
PKG_FLAGS:=nonshared
|
||||
PKG_FIXUP:=autoreconf
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/ltq-vdsl-vr9-app
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=Lantiq VDSL userland tool
|
||||
URL:=http://www.lantiq.com/
|
||||
DEPENDS:=@TARGET_lantiq_xrx200 +libpthread +librt +ltq-dsl-base +libubox +libubus
|
||||
PROVIDES:=ltq-dsl-app
|
||||
endef
|
||||
|
||||
define Package/ltq-vdsl-vr9-app/description
|
||||
Userland tool needed to control Lantiq VDSL CPE
|
||||
endef
|
||||
|
||||
# ltq-vdsl-vr9-app uses a header provided by the MEI driver which has some
|
||||
# conditionals.
|
||||
#
|
||||
# Define them here with the default values they would get in the MEI driver,
|
||||
# have the same view on both sides.
|
||||
#
|
||||
# If you change them, you need to change them for the ltq-vdsl-vr9-app as well
|
||||
VDSL_APP_CFLAGS = \
|
||||
-DMAX_CLI_PIPES=1 \
|
||||
-DMEI_SUPPORT_DEBUG_STREAMS=1 \
|
||||
-DMEI_SUPPORT_OPTIMIZED_FW_DL=1
|
||||
|
||||
CONFIGURE_ARGS += \
|
||||
--enable-vrx \
|
||||
--enable-vrx-device=vr9 \
|
||||
--enable-driver-include="-I$(STAGING_DIR)/usr/include/drv_vdsl_cpe_api" \
|
||||
--enable-device-driver-include="-I$(STAGING_DIR)/usr/include/vdsl/" \
|
||||
--enable-ifxos \
|
||||
--enable-ifxos-include="-I$(STAGING_DIR)/usr/include/ifxos" \
|
||||
--enable-ifxos-library="-I$(STAGING_DIR)/usr/lib" \
|
||||
--enable-add-appl-cflags="$(VDSL_APP_CFLAGS)" \
|
||||
--enable-debug \
|
||||
--disable-dti \
|
||||
--with-channels-per-line="1"
|
||||
|
||||
CONFIGURE_ARGS += \
|
||||
--enable-model=full \
|
||||
--enable-dsl-ceoc=no
|
||||
#CONFIGURE_ARGS += --enable-model=lite
|
||||
#CONFIGURE_ARGS += --enable-model=footprint
|
||||
#CONFIGURE_ARGS += --enable-model=typical
|
||||
#CONFIGURE_ARGS += --enable-model=debug
|
||||
|
||||
define Package/ltq-vdsl-vr9-app/install
|
||||
$(INSTALL_DIR) $(1)/etc/init.d $(1)/sbin $(1)/etc/hotplug.d/dsl
|
||||
$(INSTALL_BIN) ./files/dsl_control $(1)/etc/init.d/
|
||||
$(INSTALL_BIN) ./files/10_atm.sh $(1)/etc/hotplug.d/dsl
|
||||
$(INSTALL_BIN) ./files/10_ptm.sh $(1)/etc/hotplug.d/dsl
|
||||
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/dsl_cpe_control $(1)/sbin/vdsl_cpe_control
|
||||
$(INSTALL_BIN) ./files/dsl_cpe_pipe.sh $(1)/sbin/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ltq-vdsl-vr9-app))
|
||||
14
package/network/config/ltq-vdsl-vr9-app/files/10_atm.sh
Executable file
14
package/network/config/ltq-vdsl-vr9-app/files/10_atm.sh
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ "$DSL_NOTIFICATION_TYPE" = "DSL_STATUS" ] && \
|
||||
[ "$DSL_TC_LAYER_STATUS" = "ATM" ] && \
|
||||
! grep -q "ltq_atm_vr9" /proc/modules || exit 0
|
||||
|
||||
logger -p daemon.notice -t "dsl-notify" "Switching to TC-Layer ATM"
|
||||
|
||||
if grep -q "ltq_ptm_vr9" /proc/modules ; then
|
||||
logger -p daemon.notice -t "dsl-notify" "Loading ATM driver while EFM/PTM driver is loaded is not possible. Reboot is needed."
|
||||
exit
|
||||
fi
|
||||
|
||||
modprobe ltq_atm_vr9
|
||||
14
package/network/config/ltq-vdsl-vr9-app/files/10_ptm.sh
Executable file
14
package/network/config/ltq-vdsl-vr9-app/files/10_ptm.sh
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ "$DSL_NOTIFICATION_TYPE" = "DSL_STATUS" ] && \
|
||||
[ "$DSL_TC_LAYER_STATUS" = "EFM" ] && \
|
||||
! grep -q "ltq_ptm_vr9" /proc/modules || exit 0
|
||||
|
||||
logger -p daemon.notice -t "dsl-notify" "Switching to TC-Layer EFM/PTM"
|
||||
|
||||
if grep -q "ltq_atm_vr9" /proc/modules ; then
|
||||
logger -p daemon.notice -t "dsl-notify" "Loading EFM/PTM driver while ATM driver is loaded is not possible. Reboot is needed."
|
||||
exit
|
||||
fi
|
||||
|
||||
modprobe ltq_ptm_vr9
|
||||
322
package/network/config/ltq-vdsl-vr9-app/files/dsl_control
Normal file
322
package/network/config/ltq-vdsl-vr9-app/files/dsl_control
Normal file
@@ -0,0 +1,322 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2012 OpenWrt.org
|
||||
|
||||
START=97
|
||||
USE_PROCD=1
|
||||
|
||||
dslstat() {
|
||||
ubus call dsl metrics
|
||||
}
|
||||
|
||||
extra_command "dslstat" "Get DSL status information"
|
||||
|
||||
#
|
||||
# ITU-T G.997.1 (06/2012) - Section 7.3.1.1.1 (xTU transmission system enabling (XTSE))
|
||||
# ITU-T G.997.1 Amendment 2 (04/2013) - Section 2.1 - (Vectoring mode enable (VECTORMODE_ENABLE))
|
||||
#
|
||||
# G.992.1 Annex A
|
||||
# G.992.2 Annex A
|
||||
# G.992.3 Annex A / L-US1 / L_US-2 / M
|
||||
# G.992.5 Annex A / M
|
||||
# G.993.2 Annex A/B/C
|
||||
# G.993.5 Annex A/B/C
|
||||
xtse_xdsl_a="05_01_04_00_4C_01_04_07"
|
||||
|
||||
# G.992.1 Annex B
|
||||
# G.992.3 Annex B
|
||||
# G.992.5 Annex B
|
||||
# G.993.2 Annex A/B/C
|
||||
# G.993.5 Annex A/B/C
|
||||
xtse_xdsl_b="10_00_10_00_00_04_00_07"
|
||||
|
||||
# G.992.1 Annex B
|
||||
# G.992.3 Annex B
|
||||
# G.992.3 Annex J
|
||||
# G.992.5 Annex B
|
||||
# G.992.5 Annex J
|
||||
# G.993.2 Annex A/B/C
|
||||
# G.993.5 Annex A/B/C
|
||||
xtse_xdsl_j="10_00_10_40_00_04_01_07"
|
||||
|
||||
# G.992.1 Annex B
|
||||
xtse_xdsl_bdmt="10_00_00_00_00_00_00_00"
|
||||
|
||||
# G.992.3 Annex B
|
||||
xtse_xdsl_b2="00_00_10_00_00_00_00_00"
|
||||
|
||||
# G.992.5 Annex B
|
||||
xtse_xdsl_b2p="00_00_00_00_00_04_00_00"
|
||||
|
||||
# ANSI T1.413
|
||||
xtse_xdsl_at1="01_00_00_00_00_00_00_00"
|
||||
|
||||
# G.992.2 Annex A
|
||||
xtse_xdsl_alite="00_01_00_00_00_00_00_00"
|
||||
|
||||
# G.992.1 Annex A
|
||||
xtse_xdsl_admt="04_00_00_00_00_00_00_00"
|
||||
|
||||
# G.992.3 Annex A
|
||||
xtse_xdsl_a2="00_00_04_00_00_00_00_00"
|
||||
|
||||
# G.992.5 Annex A
|
||||
xtse_xdsl_a2p="00_00_00_00_00_01_00_00"
|
||||
|
||||
# G.992.3 Annex L
|
||||
xtse_xdsl_l="00_00_00_00_0C_00_00_00"
|
||||
|
||||
# G.992.3 Annex M
|
||||
# G.992.5 Annex M
|
||||
xtse_xdsl_m="00_00_00_00_40_00_04_00"
|
||||
|
||||
# G.992.3 Annex M
|
||||
xtse_xdsl_m2="00_00_00_00_40_00_00_00"
|
||||
|
||||
# G.992.5 Annex M
|
||||
xtse_xdsl_m2p="00_00_00_00_00_00_04_00"
|
||||
|
||||
#
|
||||
# ITU-T G.994.1 (06/2012) - Table 2 (Mandatory carrier sets)
|
||||
#
|
||||
|
||||
# A43
|
||||
tone_adsl_a="0x142" # A43C + J43 + A43
|
||||
tone_vdsl_a="0x142" # A43C + J43 + A43
|
||||
|
||||
# A43 + V43
|
||||
tone_adsl_av="0x142" # A43C + J43 + A43
|
||||
tone_vdsl_av="0x146" # A43C + J43 + A43 + V43
|
||||
|
||||
# B43
|
||||
tone_adsl_b="0x81" # B43 + B43c
|
||||
tone_vdsl_b="0x1" # B43
|
||||
|
||||
# B43 + V43
|
||||
tone_adsl_bv="0x81" # B43 + B43c
|
||||
tone_vdsl_bv="0x5" # B43 + V43
|
||||
|
||||
# create DSL autoboot script. Used for SNR margin tweak and to set MAC address for vectoring error reports
|
||||
autoboot_script() {
|
||||
echo "[WaitForConfiguration]={
|
||||
locs 0 $1
|
||||
dsmmcs $2
|
||||
}
|
||||
|
||||
[WaitForLinkActivate]={
|
||||
}
|
||||
|
||||
[WaitForRestart]={
|
||||
}
|
||||
|
||||
[Common]={
|
||||
}" > /tmp/dsl.scr
|
||||
}
|
||||
|
||||
lowlevel_cfg() {
|
||||
echo "# VRX Low Level Configuration File
|
||||
#
|
||||
# Parameters must be separated by tabs or spaces.
|
||||
# Empty lines and comments will be ignored.
|
||||
#
|
||||
|
||||
# nFilter
|
||||
#
|
||||
# NA = -1
|
||||
# OFF = 0
|
||||
# ISDN = 1
|
||||
# POTS = 2
|
||||
# POTS_2 = 3
|
||||
# POTS_3 = 4
|
||||
#
|
||||
# (dec)
|
||||
-1
|
||||
|
||||
# nHsToneGroupMode nHsToneGroup_A nHsToneGroup_V nHsToneGroup_AV
|
||||
#
|
||||
# NA = -1 NA = -1 see see
|
||||
# AUTO = 0 VDSL2_B43 = 0x0001 nHsToneGroup_A nHsToneGroup_A
|
||||
# MANUAL = 1 VDSL2_A43 = 0x0002
|
||||
# VDSL2_V43 = 0x0004
|
||||
# VDSL1_V43P = 0x0008
|
||||
# VDSL1_V43I = 0x0010
|
||||
# ADSL1_C43 = 0x0020
|
||||
# ADSL2_J43 = 0x0040
|
||||
# ADSL2_B43C = 0x0080
|
||||
# ADSL2_A43C = 0x0100
|
||||
#
|
||||
# (dec) (hex) (hex) (hex)
|
||||
1 $1 $2 0x0
|
||||
|
||||
# nBaseAddr nIrqNum
|
||||
#
|
||||
# (hex) (dec)
|
||||
0x1e116000 63
|
||||
|
||||
# nUtopiaPhyAdr nUtopiaBusWidth nPosPhyParity
|
||||
# default(16b) = 0 NA = -1
|
||||
# 8-bit = 1 ODD = 0
|
||||
# 16-bit = 2
|
||||
#
|
||||
#
|
||||
# (hex) (dec) (dec)
|
||||
0xFF 0 0
|
||||
|
||||
# bNtrEnable
|
||||
#
|
||||
# (dec)
|
||||
0" > /tmp/lowlevel.cfg
|
||||
}
|
||||
|
||||
get_macaddr() {
|
||||
local name
|
||||
config_get name $1 name
|
||||
[ "$name" = "dsl0" ] && config_get $2 $1 macaddr
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger network
|
||||
}
|
||||
|
||||
start_service() {
|
||||
local annex
|
||||
local firmware
|
||||
local tone
|
||||
local tone_adsl
|
||||
local tone_vdsl
|
||||
local xtse
|
||||
local xfer_mode
|
||||
local line_mode
|
||||
local tc_layer
|
||||
local mode
|
||||
local lowlevel
|
||||
local snr
|
||||
local macaddr
|
||||
|
||||
config_load network
|
||||
config_get tone dsl tone
|
||||
config_get annex dsl annex
|
||||
config_get firmware dsl firmware
|
||||
config_get xfer_mode dsl xfer_mode
|
||||
config_get line_mode dsl line_mode
|
||||
config_get snr dsl ds_snr_offset
|
||||
config_foreach get_macaddr device macaddr
|
||||
|
||||
eval "xtse=\"\${xtse_xdsl_$annex}\""
|
||||
|
||||
case "${xfer_mode}" in
|
||||
atm)
|
||||
tc_layer="-T1:0x1:0x1_1:0x1:0x1"
|
||||
;;
|
||||
ptm)
|
||||
tc_layer="-T2:0x1:0x1_2:0x1:0x1"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "${line_mode}" in
|
||||
adsl)
|
||||
mode="-M1"
|
||||
|
||||
# mask out VDSL bits when ADSL is requested
|
||||
xtse="${xtse%_*}_00"
|
||||
;;
|
||||
vdsl)
|
||||
mode="-M2"
|
||||
|
||||
# mask out ADSL bits when VDSL is requested
|
||||
xtse="00_00_00_00_00_00_00_${xtse##*_}"
|
||||
;;
|
||||
esac
|
||||
|
||||
local annexgpio="/sys/class/gpio/annex"
|
||||
if [ -d "${annexgpio}a" ] && [ -d "${annexgpio}b" ]; then
|
||||
case "${annex}" in
|
||||
a*|l*|m*)
|
||||
echo 1 > "${annexgpio}a/value"
|
||||
echo 0 > "${annexgpio}b/value"
|
||||
;;
|
||||
b*|j*)
|
||||
echo 0 > "${annexgpio}a/value"
|
||||
echo 1 > "${annexgpio}b/value"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ -z "${firmware}" ]; then
|
||||
# search for the firmware provided by dsl-vrx200-firmware-xdsl-*
|
||||
if grep -qE "system type.*: (VR9|xRX200)" /proc/cpuinfo; then
|
||||
case "${annex}" in
|
||||
a*|l*|m*)
|
||||
if [ -f "/lib/firmware/lantiq-vrx200-a.bin" ]; then
|
||||
firmware="/lib/firmware/lantiq-vrx200-a.bin"
|
||||
elif [ -f "/tmp/lantiq-vrx200-a.bin" ]; then
|
||||
firmware="/tmp/lantiq-vrx200-a.bin"
|
||||
elif [ -f "/lib/firmware/lantiq-vrx200-b.bin" ] && [ -f "/lib/firmware/lantiq-vrx200-b-to-a.bspatch" ]; then
|
||||
bspatch /lib/firmware/lantiq-vrx200-b.bin \
|
||||
/tmp/lantiq-vrx200-a.bin \
|
||||
/lib/firmware/lantiq-vrx200-b-to-a.bspatch
|
||||
firmware="/tmp/lantiq-vrx200-a.bin"
|
||||
else
|
||||
echo "firmware for annex a not found"
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
b*|j*)
|
||||
if [ -f "/lib/firmware/vr9_dsl_fw_annex_b.bin" ]; then
|
||||
firmware="/lib/firmware/vr9_dsl_fw_annex_b.bin"
|
||||
elif [ -f "/lib/firmware/lantiq-vrx200-b.bin" ]; then
|
||||
firmware="/lib/firmware/lantiq-vrx200-b.bin"
|
||||
elif [ -f "/tmp/lantiq-vrx200-b.bin" ]; then
|
||||
firmware="/tmp/lantiq-vrx200-b.bin"
|
||||
elif [ -f "/lib/firmware/lantiq-vrx200-a.bin" ] && [ -f "/lib/firmware/lantiq-vrx200-a-to-b.bspatch" ]; then
|
||||
bspatch /lib/firmware/lantiq-vrx200-a.bin \
|
||||
/tmp/lantiq-vrx200-b.bin \
|
||||
/lib/firmware/lantiq-vrx200-a-to-b.bspatch
|
||||
firmware="/tmp/lantiq-vrx200-b.bin"
|
||||
else
|
||||
echo "firmware for annex b not found"
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "annex type not supported use a or b"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
[ -z "${firmware}" ] && firmware=/lib/firmware/vdsl.bin
|
||||
[ -f "${firmware}" ] || {
|
||||
echo failed to find $firmware
|
||||
return 1
|
||||
}
|
||||
|
||||
eval "tone_adsl=\"\${tone_adsl_$tone}\""
|
||||
eval "tone_vdsl=\"\${tone_vdsl_$tone}\""
|
||||
[ -n "${tone_adsl}" ] && [ -n "${tone_vdsl}" ] && {
|
||||
lowlevel_cfg "${tone_adsl}" "${tone_vdsl}"
|
||||
lowlevel="-l /tmp/lowlevel.cfg"
|
||||
}
|
||||
|
||||
[ -z "${snr}" ] && snr=0
|
||||
[ -z "${macaddr}" ] && macaddr="00:00:00:00:00:00"
|
||||
autoboot_script "$snr" "$macaddr"
|
||||
autoboot="-a /tmp/dsl.scr -A /tmp/dsl.scr"
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command /sbin/vdsl_cpe_control \
|
||||
-i$xtse \
|
||||
-n /sbin/dsl_notify.sh \
|
||||
-f ${firmware} \
|
||||
$lowlevel \
|
||||
${mode} \
|
||||
${tc_layer} \
|
||||
$autoboot
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
DSL_NOTIFICATION_TYPE="DSL_INTERFACE_STATUS" \
|
||||
DSL_INTERFACE_STATUS="DOWN" \
|
||||
/sbin/dsl_notify.sh
|
||||
}
|
||||
18
package/network/config/ltq-vdsl-vr9-app/files/dsl_cpe_pipe.sh
Executable file
18
package/network/config/ltq-vdsl-vr9-app/files/dsl_cpe_pipe.sh
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
|
||||
pipe_no=0
|
||||
|
||||
# use specified pipe no
|
||||
case "$1" in
|
||||
0|1|2)
|
||||
pipe_no=$1; shift; ;;
|
||||
esac
|
||||
|
||||
|
||||
#echo "Call dsl_pipe with $*"
|
||||
lock /var/lock/dsl_pipe
|
||||
echo $* > /tmp/pipe/dsl_cpe${pipe_no}_cmd
|
||||
result=$(cat /tmp/pipe/dsl_cpe${pipe_no}_ack)
|
||||
lock -u /var/lock/dsl_pipe
|
||||
|
||||
echo "$result"
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/src/dsl_cpe_init_cfg.c
|
||||
+++ b/src/dsl_cpe_init_cfg.c
|
||||
@@ -38,7 +38,7 @@ DSL_InitData_t gInitCfgData =
|
||||
DSL_DEV_HS_TONE_GROUP_CLEANED, \
|
||||
DSL_DEV_HS_TONE_GROUP_CLEANED, \
|
||||
DSL_DEV_HS_TONE_GROUP_CLEANED, \
|
||||
- 0x1E116000, 0x37, -1),
|
||||
+ 0x1E116000, 0x3f, -1),
|
||||
DSL_CPE_SIC_SET(DSL_TC_ATM, DSL_EMF_TC_CLEANED, DSL_EMF_TC_CLEANED, DSL_SYSTEMIF_MII, \
|
||||
DSL_TC_EFM, DSL_EMF_TC_CLEANED, DSL_EMF_TC_CLEANED, DSL_SYSTEMIF_MII),
|
||||
DSL_CPE_MAC_CFG_SET(DSL_EFM_SPEED_100, DSL_EFM_DUPLEX_FULL, DSL_EFM_FLOWCTRL_ON, DSL_EFM_AUTONEG_OFF, \
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/src/dsl_cpe_control.c
|
||||
+++ b/src/dsl_cpe_control.c
|
||||
@@ -11,6 +11,7 @@
|
||||
/*
|
||||
Includes
|
||||
*/
|
||||
+#include <limits.h>
|
||||
#include "dsl_cpe_control.h"
|
||||
#include "dsl_cpe_cli.h"
|
||||
#include "dsl_cpe_cli_console.h"
|
||||
@@ -0,0 +1,86 @@
|
||||
This enables automatic connection after the control daemon is started,
|
||||
and also stops the connection on termination.
|
||||
|
||||
Using the autoboot restart command is necessary because the stop command
|
||||
doesn't actually stop the connection, and would also leave the driver in
|
||||
a state where an explicit start command is necessary to connect again.
|
||||
|
||||
--- a/src/dsl_cpe_init_cfg.c
|
||||
+++ b/src/dsl_cpe_init_cfg.c
|
||||
@@ -27,7 +27,7 @@ DSL_InitData_t gInitCfgData =
|
||||
DSL_CPE_FW2_SET(DSL_NULL, 0x0),
|
||||
DSL_CPE_XTU_SET(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7),
|
||||
DSL_CPE_LINE_INV_NE_SET(DSL_NULL),
|
||||
- DSL_CPE_AUTOBOOT_CTRL_SET(DSL_AUTOBOOT_CTRL_STOP),
|
||||
+ DSL_CPE_AUTOBOOT_CTRL_SET(DSL_AUTOBOOT_CTRL_START),
|
||||
DSL_CPE_AUTOBOOT_CFG_SET(DSL_FALSE, DSL_FALSE, DSL_FALSE),
|
||||
DSL_CPE_TEST_MODE_CTRL_SET(DSL_TESTMODE_DISABLE),
|
||||
DSL_CPE_LINE_ACTIVATE_CTRL_SET(DSL_G997_INHIBIT_LDSF, DSL_G997_INHIBIT_ACSF, DSL_G997_NORMAL_STARTUP),
|
||||
--- a/src/dsl_cpe_control.c
|
||||
+++ b/src/dsl_cpe_control.c
|
||||
@@ -6515,10 +6515,13 @@ DSL_CPE_STATIC void DSL_CPE_Termination
|
||||
DSL_CPE_STATIC DSL_void_t DSL_CPE_Termination (void)
|
||||
{
|
||||
#ifdef INCLUDE_DSL_CPE_CLI_SUPPORT
|
||||
- DSL_int_t nDevice = 0;
|
||||
DSL_char_t buf[32] = "quit";
|
||||
#endif
|
||||
|
||||
+ DSL_Error_t nRet = DSL_SUCCESS;
|
||||
+ DSL_int_t nDevice = 0;
|
||||
+ DSL_AutobootConfig_t sAutobootCfg;
|
||||
+ DSL_AutobootControl_t sAutobootCtl;
|
||||
DSL_CPE_Control_Context_t *pCtrlCtx;
|
||||
|
||||
pCtrlCtx = DSL_CPE_GetGlobalContext();
|
||||
@@ -6527,6 +6530,50 @@ DSL_CPE_STATIC DSL_void_t DSL_CPE_Termi
|
||||
pCtrlCtx->bRun = DSL_FALSE;
|
||||
}
|
||||
|
||||
+ for (nDevice = 0; nDevice < DSL_CPE_MAX_DSL_ENTITIES; ++nDevice)
|
||||
+ {
|
||||
+ g_bWaitBeforeConfigWrite[nDevice] = DSL_TRUE;
|
||||
+ g_bWaitBeforeLinkActivation[nDevice] = DSL_TRUE;
|
||||
+ g_bWaitBeforeRestart[nDevice] = DSL_TRUE;
|
||||
+
|
||||
+ g_bAutoContinueWaitBeforeConfigWrite[nDevice] = DSL_FALSE;
|
||||
+ g_bAutoContinueWaitBeforeLinkActivation[nDevice] = DSL_FALSE;
|
||||
+ g_bAutoContinueWaitBeforeRestart[nDevice] = DSL_FALSE;
|
||||
+
|
||||
+ memset(&sAutobootCfg, 0x0, sizeof(DSL_AutobootConfig_t));
|
||||
+ sAutobootCfg.data.nStateMachineOptions.bWaitBeforeConfigWrite = DSL_TRUE;
|
||||
+ sAutobootCfg.data.nStateMachineOptions.bWaitBeforeLinkActivation = DSL_TRUE;
|
||||
+ sAutobootCfg.data.nStateMachineOptions.bWaitBeforeRestart = DSL_TRUE;
|
||||
+
|
||||
+ nRet = (DSL_Error_t)DSL_CPE_Ioctl(
|
||||
+ DSL_CPE_GetGlobalContext()->fd[nDevice],
|
||||
+ DSL_FIO_AUTOBOOT_CONFIG_SET, (DSL_int_t)&sAutobootCfg);
|
||||
+
|
||||
+ if (nRet < DSL_SUCCESS)
|
||||
+ {
|
||||
+ DSL_CCA_DEBUG(DSL_CCA_DBG_ERR, (DSL_CPE_PREFIX
|
||||
+ "Autoboot configuration for device (%d) failed!, nRet = %d!"
|
||||
+ DSL_CPE_CRLF, nDevice, sAutobootCtl.accessCtl.nReturn));
|
||||
+ }
|
||||
+
|
||||
+ memset(&sAutobootCtl, 0, sizeof(DSL_AutobootControl_t));
|
||||
+ sAutobootCtl.data.nCommand = DSL_AUTOBOOT_CTRL_RESTART;
|
||||
+
|
||||
+ nRet = (DSL_Error_t)DSL_CPE_Ioctl(
|
||||
+ DSL_CPE_GetGlobalContext()->fd[nDevice],
|
||||
+ DSL_FIO_AUTOBOOT_CONTROL_SET, (DSL_int_t)&sAutobootCtl);
|
||||
+
|
||||
+ if (nRet < DSL_SUCCESS)
|
||||
+ {
|
||||
+ DSL_CCA_DEBUG(DSL_CCA_DBG_ERR, (DSL_CPE_PREFIX
|
||||
+ "Autoboot restart for device (%d) failed!, nRet = %d!"
|
||||
+ DSL_CPE_CRLF, nDevice, sAutobootCtl.accessCtl.nReturn));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ DSL_CCA_DEBUG(DSL_CCA_DBG_MSG, (DSL_CPE_PREFIX
|
||||
+ "Autoboot restart executed" DSL_CPE_CRLF));
|
||||
+
|
||||
#ifdef INCLUDE_DSL_CPE_CLI_SUPPORT
|
||||
for (nDevice = 0; nDevice < DSL_CPE_MAX_DSL_ENTITIES; nDevice++)
|
||||
{
|
||||
@@ -0,0 +1,19 @@
|
||||
--- a/src/dsl_cpe_control.c
|
||||
+++ b/src/dsl_cpe_control.c
|
||||
@@ -6504,7 +6504,7 @@ DSL_CPE_STATIC void DSL_CPE_Termination
|
||||
/* ignore the signal, we'll handle by ourself */
|
||||
signal (sig, SIG_IGN);
|
||||
|
||||
- if (sig == SIGINT)
|
||||
+ if (sig == SIGINT || sig == SIGTERM)
|
||||
{
|
||||
DSL_CCA_DEBUG(DSL_CCA_DBG_MSG, (DSL_CPE_PREFIX "terminated" DSL_CPE_CRLF));
|
||||
DSL_CPE_Termination ();
|
||||
@@ -6803,6 +6803,7 @@ DSL_int_t dsl_cpe_daemon (
|
||||
|
||||
#ifndef RTEMS
|
||||
signal (SIGINT, DSL_CPE_TerminationHandler);
|
||||
+ signal (SIGTERM, DSL_CPE_TerminationHandler);
|
||||
#endif /* RTEMS*/
|
||||
|
||||
/* Open DSL_CPE_MAX_DSL_ENTITIES devices*/
|
||||
@@ -0,0 +1,50 @@
|
||||
--- a/src/dsl_cpe_control.c
|
||||
+++ b/src/dsl_cpe_control.c
|
||||
@@ -177,6 +177,9 @@ extern DSL_Error_t DSL_CPE_Pipe_StaticRe
|
||||
#endif /* INCLUDE_DSL_RESOURCE_STATISTICS*/
|
||||
#endif
|
||||
|
||||
+extern void ubus_init();
|
||||
+extern void ubus_deinit();
|
||||
+
|
||||
DSL_char_t *g_sFirmwareName1 = DSL_NULL;
|
||||
DSL_FirmwareFeatures_t g_nFwFeatures1 = {DSL_FW_XDSLMODE_CLEANED, DSL_FW_XDSLFEATURE_CLEANED,
|
||||
DSL_FW_XDSLFEATURE_CLEANED};
|
||||
@@ -6806,6 +6809,8 @@ DSL_int_t dsl_cpe_daemon (
|
||||
signal (SIGTERM, DSL_CPE_TerminationHandler);
|
||||
#endif /* RTEMS*/
|
||||
|
||||
+ ubus_init();
|
||||
+
|
||||
/* Open DSL_CPE_MAX_DSL_ENTITIES devices*/
|
||||
for (nDevice = 0; nDevice < DSL_CPE_MAX_DSL_ENTITIES; nDevice++)
|
||||
{
|
||||
@@ -7260,6 +7265,7 @@ DSL_int_t dsl_cpe_daemon (
|
||||
#endif /* INCLUDE_DSL_CPE_CLI_SUPPORT */
|
||||
|
||||
DSL_CPE_CONTROL_EXIT:
|
||||
+ ubus_deinit();
|
||||
|
||||
#ifdef INCLUDE_DSL_BONDING
|
||||
DSL_CPE_BND_Stop((DSL_CPE_BND_Context_t*)pCtrlCtx->pBnd);
|
||||
--- a/src/Makefile.am
|
||||
+++ b/src/Makefile.am
|
||||
@@ -11,7 +11,7 @@ else
|
||||
dsl_cpe_control_common_ldflags =
|
||||
endif
|
||||
|
||||
-dsl_cpe_control_LDADD = -lpthread -lrt
|
||||
+dsl_cpe_control_LDADD = -lpthread -lrt -lubox -lubus
|
||||
|
||||
if INCLUDE_DSL_CPE_DTI_SUPPORT
|
||||
dsl_cpe_control_LDADD += -ldti_agent
|
||||
@@ -66,7 +66,8 @@ dsl_cpe_control_SOURCES = \
|
||||
dsl_cpe_control.c \
|
||||
dsl_cpe_init_cfg.c \
|
||||
dsl_cpe_linux.c \
|
||||
- dsl_cpe_debug.c
|
||||
+ dsl_cpe_debug.c \
|
||||
+ dsl_cpe_ubus.c
|
||||
|
||||
dsl_cpe_control_SOURCES += \
|
||||
$(dsl_cpe_control_dti_sources)
|
||||
1170
package/network/config/ltq-vdsl-vr9-app/src/src/dsl_cpe_ubus.c
Normal file
1170
package/network/config/ltq-vdsl-vr9-app/src/src/dsl_cpe_ubus.c
Normal file
File diff suppressed because it is too large
Load Diff
52
package/network/config/netifd/Makefile
Normal file
52
package/network/config/netifd/Makefile
Normal file
@@ -0,0 +1,52 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=netifd
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/netifd.git
|
||||
PKG_SOURCE_DATE:=2024-01-04
|
||||
PKG_SOURCE_VERSION:=f01345ec13b9b27ffd314d8689fb2d3f9c81a47d
|
||||
PKG_MIRROR_HASH:=b051aa94e6413f520b711372f8cae4574cad26cba880ff6ab2d415713d06e592
|
||||
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
PKG_LICENSE_FILES:=
|
||||
|
||||
PKG_BUILD_FLAGS:=lto
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
|
||||
define Package/netifd
|
||||
SECTION:=base
|
||||
CATEGORY:=Base system
|
||||
DEPENDS:=+libuci +libnl-tiny +libubus +ubus +ubusd +jshn +libubox +libudebug +ucode +ucode-mod-fs
|
||||
TITLE:=OpenWrt Network Interface Configuration Daemon
|
||||
endef
|
||||
|
||||
define Package/netifd/conffiles
|
||||
/etc/udhcpc.user
|
||||
/etc/udhcpc.user.d/
|
||||
endef
|
||||
|
||||
TARGET_CFLAGS += \
|
||||
-I$(STAGING_DIR)/usr/include/libnl-tiny \
|
||||
-I$(STAGING_DIR)/usr/include
|
||||
|
||||
CMAKE_OPTIONS += \
|
||||
-DLIBNL_LIBS=-lnl-tiny \
|
||||
-DDEBUG=1
|
||||
|
||||
define Package/netifd/install
|
||||
$(INSTALL_DIR) $(1)/sbin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/netifd $(1)/sbin/
|
||||
$(CP) ./files/* $(1)/
|
||||
$(INSTALL_DIR) $(1)/etc/udhcpc.user.d/
|
||||
$(CP) \
|
||||
$(PKG_BUILD_DIR)/scripts/utils.sh \
|
||||
$(PKG_BUILD_DIR)/scripts/netifd-proto.sh \
|
||||
$(1)/lib/netifd/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,netifd))
|
||||
@@ -0,0 +1,6 @@
|
||||
[ ifup = "$ACTION" ] && {
|
||||
uci_toggle_state network "$INTERFACE" up 1
|
||||
[ -n "$DEVICE" ] && {
|
||||
uci_toggle_state network "$INTERFACE" ifname "$DEVICE"
|
||||
}
|
||||
}
|
||||
144
package/network/config/netifd/files/etc/init.d/network
Executable file
144
package/network/config/netifd/files/etc/init.d/network
Executable file
@@ -0,0 +1,144 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=20
|
||||
STOP=90
|
||||
|
||||
USE_PROCD=1
|
||||
|
||||
init_switch() {
|
||||
setup_switch() { return 0; }
|
||||
|
||||
include /lib/network
|
||||
setup_switch
|
||||
}
|
||||
|
||||
start_service() {
|
||||
init_switch
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command /sbin/netifd
|
||||
procd_set_param respawn
|
||||
procd_set_param watch network.interface
|
||||
[ -e /proc/sys/kernel/core_pattern ] && {
|
||||
procd_set_param limits core="unlimited"
|
||||
}
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
reload_service() {
|
||||
local rv=0
|
||||
|
||||
init_switch
|
||||
ubus call network reload || rv=1
|
||||
/sbin/wifi reload_legacy
|
||||
return $rv
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
/sbin/wifi down
|
||||
ifdown -a
|
||||
sleep 1
|
||||
}
|
||||
|
||||
validate_atm_bridge_section()
|
||||
{
|
||||
uci_validate_section network "atm-bridge" "${1}" \
|
||||
'unit:uinteger:0' \
|
||||
'vci:range(32, 65535):35' \
|
||||
'vpi:range(0, 255):8' \
|
||||
'atmdev:uinteger:0' \
|
||||
'encaps:or("llc", "vc"):llc' \
|
||||
'payload:or("bridged", "routed"):bridged'
|
||||
}
|
||||
|
||||
validate_route_section()
|
||||
{
|
||||
uci_validate_section network route "${1}" \
|
||||
'interface:string' \
|
||||
'target:cidr4' \
|
||||
'netmask:netmask4' \
|
||||
'gateway:ip4addr' \
|
||||
'metric:uinteger' \
|
||||
'mtu:uinteger' \
|
||||
'table:or(range(0,65535),string)'
|
||||
}
|
||||
|
||||
validate_route6_section()
|
||||
{
|
||||
uci_validate_section network route6 "${1}" \
|
||||
'interface:string' \
|
||||
'target:cidr6' \
|
||||
'gateway:ip6addr' \
|
||||
'metric:uinteger' \
|
||||
'mtu:uinteger' \
|
||||
'table:or(range(0,65535),string)'
|
||||
}
|
||||
|
||||
validate_rule_section()
|
||||
{
|
||||
uci_validate_section network rule "${1}" \
|
||||
'in:string' \
|
||||
'out:string' \
|
||||
'src:cidr4' \
|
||||
'dest:cidr4' \
|
||||
'tos:range(0,31)' \
|
||||
'mark:string' \
|
||||
'invert:bool' \
|
||||
'lookup:or(range(0,65535),string)' \
|
||||
'goto:range(0,65535)' \
|
||||
'action:or("prohibit", "unreachable", "blackhole", "throw")'
|
||||
}
|
||||
|
||||
validate_rule6_section()
|
||||
{
|
||||
uci_validate_section network rule6 "${1}" \
|
||||
'in:string' \
|
||||
'out:string' \
|
||||
'src:cidr6' \
|
||||
'dest:cidr6' \
|
||||
'tos:range(0,31)' \
|
||||
'mark:string' \
|
||||
'invert:bool' \
|
||||
'lookup:or(range(0,65535),string)' \
|
||||
'goto:range(0,65535)' \
|
||||
'action:or("prohibit", "unreachable", "blackhole", "throw")'
|
||||
}
|
||||
|
||||
validate_switch_section()
|
||||
{
|
||||
uci_validate_section network switch "${1}" \
|
||||
'name:string' \
|
||||
'enable:bool' \
|
||||
'enable_vlan:bool' \
|
||||
'reset:bool' \
|
||||
'ar8xxx_mib_poll_interval:uinteger' \
|
||||
'ar8xxx_mib_type:range(0,1)'
|
||||
}
|
||||
|
||||
validate_switch_vlan()
|
||||
{
|
||||
uci_validate_section network switch_vlan "${1}" \
|
||||
'device:string' \
|
||||
'vlan:uinteger' \
|
||||
'ports:list(ports)'
|
||||
}
|
||||
|
||||
service_triggers()
|
||||
{
|
||||
procd_add_reload_trigger network wireless
|
||||
|
||||
procd_open_validate
|
||||
validate_atm_bridge_section
|
||||
validate_route_section
|
||||
[ -e /proc/sys/net/ipv6 ] && validate_route6_section
|
||||
validate_rule_section
|
||||
[ -e /proc/sys/net/ipv6 ] && validate_rule6_section
|
||||
validate_switch_section
|
||||
validate_switch_vlan
|
||||
procd_close_validate
|
||||
}
|
||||
|
||||
shutdown() {
|
||||
ifdown -a
|
||||
sleep 1
|
||||
}
|
||||
25
package/network/config/netifd/files/etc/init.d/packet_steering
Executable file
25
package/network/config/netifd/files/etc/init.d/packet_steering
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=25
|
||||
USE_PROCD=1
|
||||
|
||||
start_service() {
|
||||
reload_service
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger "network"
|
||||
procd_add_reload_trigger "firewall"
|
||||
procd_add_raw_trigger "interface.*" 1000 /etc/init.d/packet_steering reload
|
||||
}
|
||||
|
||||
reload_service() {
|
||||
packet_steering="$(uci -q get "network.@globals[0].packet_steering")"
|
||||
steering_flows="$(uci -q get "network.@globals[0].steering_flows")"
|
||||
[ "${steering_flows:-0}" -gt 0 ] && opts="-l $steering_flows"
|
||||
if [ -e "/usr/libexec/platform/packet-steering.sh" ]; then
|
||||
/usr/libexec/platform/packet-steering.sh "$packet_steering"
|
||||
else
|
||||
/usr/libexec/network/packet-steering.uc $opts "$packet_steering"
|
||||
fi
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
. /lib/functions.sh
|
||||
|
||||
migrate_release() {
|
||||
local config="$1"
|
||||
local proto
|
||||
local release
|
||||
|
||||
config_get proto "$config" proto
|
||||
config_get release "$config" release
|
||||
|
||||
[ "$proto" = "dhcp" ] && [ -n "$release" ] && {
|
||||
norelease="$((!$release))"
|
||||
uci_set network "$config" norelease "$norelease"
|
||||
uci_remove network "$config" release
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
config_load network
|
||||
config_foreach migrate_release interface
|
||||
uci commit network
|
||||
|
||||
exit 0
|
||||
1
package/network/config/netifd/files/etc/udhcpc.user
Normal file
1
package/network/config/netifd/files/etc/udhcpc.user
Normal file
@@ -0,0 +1 @@
|
||||
# This script is sourced by udhcpc's dhcp.script at every DHCP event.
|
||||
120
package/network/config/netifd/files/lib/netifd/dhcp.script
Executable file
120
package/network/config/netifd/files/lib/netifd/dhcp.script
Executable file
@@ -0,0 +1,120 @@
|
||||
#!/bin/sh
|
||||
[ -z "$1" ] && echo "Error: should be run by udhcpc" && exit 1
|
||||
|
||||
. /lib/functions.sh
|
||||
. /lib/netifd/netifd-proto.sh
|
||||
|
||||
set_classless_routes() {
|
||||
local max=128
|
||||
while [ -n "$1" -a -n "$2" -a $max -gt 0 ]; do
|
||||
proto_add_ipv4_route "${1%%/*}" "${1##*/}" "$2" "$ip"
|
||||
max=$(($max-1))
|
||||
shift 2
|
||||
done
|
||||
}
|
||||
|
||||
setup_interface () {
|
||||
proto_init_update "*" 1
|
||||
proto_add_ipv4_address "$ip" "${subnet:-255.255.255.0}"
|
||||
# TODO: apply $broadcast
|
||||
|
||||
local ip_net IP PREFIX NETWORK NETMASK BROADCAST
|
||||
ipcalc "$ip/$mask" && ip_net="$NETWORK"
|
||||
|
||||
local i
|
||||
for i in $router; do
|
||||
local gw_net
|
||||
ipcalc "$i/$mask" && gw_net="$NETWORK"
|
||||
|
||||
[ "$ip_net" != "$gw_net" ] && proto_add_ipv4_route "$i" 32 "" "$ip"
|
||||
proto_add_ipv4_route 0.0.0.0 0 "$i" "$ip"
|
||||
|
||||
local r
|
||||
for r in $CUSTOMROUTES; do
|
||||
proto_add_ipv4_route "${r%%/*}" "${r##*/}" "$i" "$ip"
|
||||
done
|
||||
done
|
||||
|
||||
# CIDR STATIC ROUTES (rfc3442)
|
||||
[ -n "$staticroutes" ] && set_classless_routes $staticroutes
|
||||
[ -n "$msstaticroutes" ] && set_classless_routes $msstaticroutes
|
||||
|
||||
for i in $dns; do
|
||||
proto_add_dns_server "$i"
|
||||
done
|
||||
for i in $domain; do
|
||||
proto_add_dns_search "$i"
|
||||
done
|
||||
|
||||
# TODO: Deprecate timesvr in favor of timesrv
|
||||
if [ -n "$timesvr" -a -z "$timesrv" ]; then
|
||||
timesrv="$timesvr"
|
||||
echo "Environment variable 'timesvr' will be deprecated; use 'timesrv' instead."
|
||||
fi
|
||||
|
||||
proto_add_data
|
||||
[ -n "$ZONE" ] && json_add_string zone "$ZONE"
|
||||
[ -n "$ntpsrv" ] && json_add_string ntpserver "$ntpsrv"
|
||||
[ -n "$timesrv" ] && json_add_string timeserver "$timesrv"
|
||||
[ -n "$hostname" ] && json_add_string hostname "$hostname"
|
||||
[ -n "$message" ] && json_add_string message "$message"
|
||||
[ -n "$timezone" ] && json_add_int timezone "$timezone"
|
||||
[ -n "$lease" ] && json_add_int leasetime "$lease"
|
||||
[ -n "$serverid" ] && json_add_string dhcpserver "$serverid"
|
||||
proto_close_data
|
||||
|
||||
proto_send_update "$INTERFACE"
|
||||
|
||||
|
||||
if [ "$IFACE6RD" != 0 -a -n "$ip6rd" ]; then
|
||||
local v4mask="${ip6rd%% *}"
|
||||
ip6rd="${ip6rd#* }"
|
||||
local ip6rdprefixlen="${ip6rd%% *}"
|
||||
ip6rd="${ip6rd#* }"
|
||||
local ip6rdprefix="${ip6rd%% *}"
|
||||
ip6rd="${ip6rd#* }"
|
||||
local ip6rdbr="${ip6rd%% *}"
|
||||
|
||||
[ -n "$ZONE" ] || ZONE=$(fw3 -q network $INTERFACE 2>/dev/null)
|
||||
[ -z "$IFACE6RD" -o "$IFACE6RD" = 1 ] && IFACE6RD=${INTERFACE}_6
|
||||
|
||||
json_init
|
||||
json_add_string name "$IFACE6RD"
|
||||
json_add_string ifname "@$INTERFACE"
|
||||
json_add_string proto "6rd"
|
||||
json_add_string peeraddr "$ip6rdbr"
|
||||
json_add_int ip4prefixlen "$v4mask"
|
||||
json_add_string ip6prefix "$ip6rdprefix"
|
||||
json_add_int ip6prefixlen "$ip6rdprefixlen"
|
||||
json_add_string tunlink "$INTERFACE"
|
||||
[ -n "$IFACE6RD_DELEGATE" ] && json_add_boolean delegate "$IFACE6RD_DELEGATE"
|
||||
[ -n "$ZONE6RD" ] || ZONE6RD=$ZONE
|
||||
[ -n "$ZONE6RD" ] && json_add_string zone "$ZONE6RD"
|
||||
[ -n "$MTU6RD" ] && json_add_string mtu "$MTU6RD"
|
||||
json_close_object
|
||||
|
||||
ubus call network add_dynamic "$(json_dump)"
|
||||
fi
|
||||
}
|
||||
|
||||
deconfig_interface() {
|
||||
proto_init_update "*" 0
|
||||
proto_send_update "$INTERFACE"
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
deconfig)
|
||||
deconfig_interface
|
||||
;;
|
||||
renew|bound)
|
||||
setup_interface
|
||||
;;
|
||||
esac
|
||||
|
||||
# user rules
|
||||
[ -f /etc/udhcpc.user ] && . /etc/udhcpc.user "$@"
|
||||
for f in /etc/udhcpc.user.d/*; do
|
||||
[ -f "$f" ] && (. "$f" "$@")
|
||||
done
|
||||
|
||||
exit 0
|
||||
88
package/network/config/netifd/files/lib/netifd/proto/dhcp.sh
Executable file
88
package/network/config/netifd/files/lib/netifd/proto/dhcp.sh
Executable file
@@ -0,0 +1,88 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ -x /sbin/udhcpc ] || exit 0
|
||||
|
||||
. /lib/functions.sh
|
||||
. ../netifd-proto.sh
|
||||
init_proto "$@"
|
||||
|
||||
proto_dhcp_init_config() {
|
||||
renew_handler=1
|
||||
|
||||
proto_config_add_string 'ipaddr:ipaddr'
|
||||
proto_config_add_string 'hostname:hostname'
|
||||
proto_config_add_string clientid
|
||||
proto_config_add_string vendorid
|
||||
proto_config_add_boolean 'broadcast:bool'
|
||||
proto_config_add_boolean 'norelease:bool'
|
||||
proto_config_add_string 'reqopts:list(string)'
|
||||
proto_config_add_boolean 'defaultreqopts:bool'
|
||||
proto_config_add_string iface6rd
|
||||
proto_config_add_array 'sendopts:list(string)'
|
||||
proto_config_add_boolean delegate
|
||||
proto_config_add_string zone6rd
|
||||
proto_config_add_string zone
|
||||
proto_config_add_string mtu6rd
|
||||
proto_config_add_string customroutes
|
||||
proto_config_add_boolean classlessroute
|
||||
}
|
||||
|
||||
proto_dhcp_add_sendopts() {
|
||||
[ -n "$1" ] && append "$3" "-x $1"
|
||||
}
|
||||
|
||||
proto_dhcp_setup() {
|
||||
local config="$1"
|
||||
local iface="$2"
|
||||
|
||||
local ipaddr hostname clientid vendorid broadcast norelease reqopts defaultreqopts iface6rd sendopts delegate zone6rd zone mtu6rd customroutes classlessroute
|
||||
json_get_vars ipaddr hostname clientid vendorid broadcast norelease reqopts defaultreqopts iface6rd delegate zone6rd zone mtu6rd customroutes classlessroute
|
||||
|
||||
local opt dhcpopts
|
||||
for opt in $reqopts; do
|
||||
append dhcpopts "-O $opt"
|
||||
done
|
||||
|
||||
json_for_each_item proto_dhcp_add_sendopts sendopts dhcpopts
|
||||
|
||||
[ -z "$hostname" ] && hostname="$(cat /proc/sys/kernel/hostname)"
|
||||
[ "$hostname" = "*" ] && hostname=
|
||||
|
||||
[ "$defaultreqopts" = 0 ] && defaultreqopts="-o" || defaultreqopts=
|
||||
[ "$broadcast" = 1 ] && broadcast="-B" || broadcast=
|
||||
[ "$norelease" = 1 ] && norelease="" || norelease="-R"
|
||||
[ -n "$clientid" ] && clientid="-x 0x3d:${clientid//:/}" || clientid="-C"
|
||||
[ -n "$iface6rd" ] && proto_export "IFACE6RD=$iface6rd"
|
||||
[ "$iface6rd" != 0 -a -f /lib/netifd/proto/6rd.sh ] && append dhcpopts "-O 212"
|
||||
[ -n "$zone6rd" ] && proto_export "ZONE6RD=$zone6rd"
|
||||
[ -n "$zone" ] && proto_export "ZONE=$zone"
|
||||
[ -n "$mtu6rd" ] && proto_export "MTU6RD=$mtu6rd"
|
||||
[ -n "$customroutes" ] && proto_export "CUSTOMROUTES=$customroutes"
|
||||
[ "$delegate" = "0" ] && proto_export "IFACE6RD_DELEGATE=0"
|
||||
# Request classless route option (see RFC 3442) by default
|
||||
[ "$classlessroute" = "0" ] || append dhcpopts "-O 121"
|
||||
|
||||
proto_export "INTERFACE=$config"
|
||||
proto_run_command "$config" udhcpc \
|
||||
-p /var/run/udhcpc-$iface.pid \
|
||||
-s /lib/netifd/dhcp.script \
|
||||
-f -t 0 -i "$iface" \
|
||||
${ipaddr:+-r ${ipaddr/\/*/}} \
|
||||
${hostname:+-x "hostname:$hostname"} \
|
||||
${vendorid:+-V "$vendorid"} \
|
||||
$clientid $defaultreqopts $broadcast $norelease $dhcpopts
|
||||
}
|
||||
|
||||
proto_dhcp_renew() {
|
||||
local interface="$1"
|
||||
# SIGUSR1 forces udhcpc to renew its lease
|
||||
local sigusr1="$(kill -l SIGUSR1)"
|
||||
[ -n "$sigusr1" ] && proto_kill_command "$interface" $sigusr1
|
||||
}
|
||||
|
||||
proto_dhcp_teardown() {
|
||||
local interface="$1"
|
||||
proto_kill_command "$interface"
|
||||
}
|
||||
|
||||
add_protocol dhcp
|
||||
76
package/network/config/netifd/files/lib/network/config.sh
Executable file
76
package/network/config/netifd/files/lib/network/config.sh
Executable file
@@ -0,0 +1,76 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2011 OpenWrt.org
|
||||
|
||||
. /usr/share/libubox/jshn.sh
|
||||
|
||||
find_config() {
|
||||
local device="$1"
|
||||
local ifdev ifl3dev ifobj
|
||||
for ifobj in $(ubus list network.interface.\*); do
|
||||
interface="${ifobj##network.interface.}"
|
||||
(
|
||||
json_load "$(ifstatus $interface)"
|
||||
json_get_var ifdev device
|
||||
json_get_var ifl3dev l3_device
|
||||
if [ "$device" = "$ifdev" ] || [ "$device" = "$ifl3dev" ]; then
|
||||
echo "$interface"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
) && return
|
||||
done
|
||||
}
|
||||
|
||||
unbridge() {
|
||||
return
|
||||
}
|
||||
|
||||
ubus_call() {
|
||||
json_init
|
||||
local _data="$(ubus -S call "$1" "$2")"
|
||||
[ -z "$_data" ] && return 1
|
||||
json_load "$_data"
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
fixup_interface() {
|
||||
local config="$1"
|
||||
local ifname type device l3dev
|
||||
|
||||
config_get type "$config" type
|
||||
config_get ifname "$config" ifname
|
||||
[ "bridge" = "$type" ] && ifname="br-$config"
|
||||
ubus_call "network.interface.$config" status || return 0
|
||||
json_get_var l3dev l3_device
|
||||
[ -n "$l3dev" ] && ifname="$l3dev"
|
||||
json_init
|
||||
config_set "$config" ifname "$ifname"
|
||||
}
|
||||
|
||||
scan_interfaces() {
|
||||
config_load network
|
||||
config_foreach fixup_interface interface
|
||||
}
|
||||
|
||||
prepare_interface_bridge() {
|
||||
local config="$1"
|
||||
|
||||
[ -n "$config" ] || return 0
|
||||
ubus call network.interface."$config" prepare
|
||||
}
|
||||
|
||||
setup_interface() {
|
||||
local iface="$1"
|
||||
local config="$2"
|
||||
|
||||
[ -n "$config" ] || return 0
|
||||
ubus call network.interface."$config" add_device "{ \"name\": \"$iface\" }"
|
||||
}
|
||||
|
||||
do_sysctl() {
|
||||
[ -n "$2" ] && \
|
||||
sysctl -n -e -w "$1=$2" >/dev/null || \
|
||||
sysctl -n -e "$1"
|
||||
}
|
||||
12
package/network/config/netifd/files/sbin/devstatus
Executable file
12
package/network/config/netifd/files/sbin/devstatus
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
. /usr/share/libubox/jshn.sh
|
||||
DEVICE="$1"
|
||||
|
||||
[ -n "$DEVICE" ] || {
|
||||
echo "Usage: $0 <device>"
|
||||
exit 1
|
||||
}
|
||||
|
||||
json_init
|
||||
json_add_string name "$DEVICE"
|
||||
ubus call network.device status "$(json_dump)"
|
||||
1
package/network/config/netifd/files/sbin/ifdown
Symbolic link
1
package/network/config/netifd/files/sbin/ifdown
Symbolic link
@@ -0,0 +1 @@
|
||||
ifup
|
||||
13
package/network/config/netifd/files/sbin/ifstatus
Executable file
13
package/network/config/netifd/files/sbin/ifstatus
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
INTERFACE="$1"
|
||||
|
||||
[ -n "$INTERFACE" ] || {
|
||||
echo "Usage: $0 <interface>"
|
||||
exit 1
|
||||
}
|
||||
|
||||
ubus -S list "network.interface.$INTERFACE" >/dev/null || {
|
||||
echo "Interface $INTERFACE not found"
|
||||
exit 1
|
||||
}
|
||||
ubus call network.interface status "{ \"interface\" : \"$INTERFACE\" }"
|
||||
44
package/network/config/netifd/files/sbin/ifup
Executable file
44
package/network/config/netifd/files/sbin/ifup
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/bin/sh
|
||||
|
||||
ifup_all=
|
||||
|
||||
if_call() {
|
||||
local interface="$1"
|
||||
for mode in $modes; do
|
||||
ubus call network.interface $mode "{ \"interface\" : \"$interface\" }"
|
||||
done
|
||||
}
|
||||
|
||||
case "$0" in
|
||||
*ifdown) modes=down;;
|
||||
*ifup)
|
||||
modes="down up"
|
||||
;;
|
||||
*) echo "Invalid command: $0";;
|
||||
esac
|
||||
|
||||
while :; do
|
||||
case "$1" in
|
||||
-a)
|
||||
ifup_all=1
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
[ "$modes" = "down up" ] && ubus call network reload
|
||||
if [ -n "$ifup_all" ]; then
|
||||
for interface in $(ubus -S list 'network.interface.*'); do
|
||||
if_call "${interface##network.interface.}"
|
||||
done
|
||||
exit
|
||||
else
|
||||
ubus -S list "network.interface.$1" > /dev/null || {
|
||||
echo "Interface $1 not found"
|
||||
exit
|
||||
}
|
||||
if_call "$1"
|
||||
fi
|
||||
236
package/network/config/netifd/files/usr/libexec/network/packet-steering.uc
Executable file
236
package/network/config/netifd/files/usr/libexec/network/packet-steering.uc
Executable file
@@ -0,0 +1,236 @@
|
||||
#!/usr/bin/env ucode
|
||||
'use strict';
|
||||
import { glob, basename, dirname, readlink, readfile, realpath, writefile, error, open } from "fs";
|
||||
|
||||
let napi_weight = 1.0;
|
||||
let cpu_thread_weight = 0.75;
|
||||
let rx_weight = 0.75;
|
||||
let eth_bias = 2.0;
|
||||
let debug = 0, do_nothing = 0;
|
||||
let disable;
|
||||
let cpus;
|
||||
let all_cpus;
|
||||
let local_flows = 0;
|
||||
|
||||
while (length(ARGV) > 0) {
|
||||
let arg = shift(ARGV);
|
||||
switch (arg) {
|
||||
case "-d":
|
||||
debug++;
|
||||
break;
|
||||
case "-n":
|
||||
do_nothing++;
|
||||
break;
|
||||
case '0':
|
||||
disable = true;
|
||||
break;
|
||||
case '2':
|
||||
all_cpus = true;
|
||||
break;
|
||||
case '-l':
|
||||
local_flows = +shift(ARGV);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function task_name(pid)
|
||||
{
|
||||
let stat = open(`/proc/${pid}/status`, "r");
|
||||
if (!stat)
|
||||
return;
|
||||
let line = stat.read("line");
|
||||
stat.close();
|
||||
return trim(split(line, "\t", 2)[1]);
|
||||
}
|
||||
|
||||
function set_task_cpu(pid, cpu) {
|
||||
if (disable)
|
||||
cpu = join(",", map(cpus, (cpu) => cpu.id));
|
||||
let name = task_name(pid);
|
||||
if (!name)
|
||||
return;
|
||||
if (debug || do_nothing)
|
||||
warn(`taskset -p -c ${cpu} ${name}\n`);
|
||||
if (!do_nothing)
|
||||
system(`taskset -p -c ${cpu} ${pid}`);
|
||||
}
|
||||
|
||||
function cpu_mask(cpu)
|
||||
{
|
||||
let mask;
|
||||
if (cpu < 0)
|
||||
mask = (1 << length(cpus)) - 1;
|
||||
else
|
||||
mask = (1 << int(cpu));
|
||||
return sprintf("%x", mask);
|
||||
}
|
||||
|
||||
function set_netdev_cpu(dev, cpu) {
|
||||
let queues = glob(`/sys/class/net/${dev}/queues/rx-*/rps_cpus`);
|
||||
let val = cpu_mask(cpu);
|
||||
if (disable)
|
||||
val = 0;
|
||||
for (let queue in queues) {
|
||||
if (debug || do_nothing)
|
||||
warn(`echo ${val} > ${queue}\n`);
|
||||
if (!do_nothing)
|
||||
writefile(queue, `${val}`);
|
||||
}
|
||||
queues = glob(`/sys/class/net/${dev}/queues/rx-*/rps_flow_cnt`);
|
||||
for (let queue in queues) {
|
||||
if (debug || do_nothing)
|
||||
warn(`echo ${local_flows} > ${queue}\n`);
|
||||
if (!do_nothing)
|
||||
writefile(queue, `${local_flows}`);
|
||||
}
|
||||
}
|
||||
|
||||
function task_device_match(name, device)
|
||||
{
|
||||
let napi_match = match(name, /napi\/([^-+])-\d+/);
|
||||
if (!napi_match)
|
||||
napi_match = match(name, /mt76-tx (phy\d+)/);
|
||||
if (napi_match &&
|
||||
(index(device.phy, napi_match[1]) >= 0 ||
|
||||
index(device.netdev, napi_match[1]) >= 0))
|
||||
return true;
|
||||
|
||||
if (device.driver == "mtk_soc_eth" && match(name, /napi\/mtk_eth-/))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
cpus = map(glob("/sys/bus/cpu/devices/*"), (path) => {
|
||||
return {
|
||||
id: int(match(path, /.*cpu(\d+)/)[1]),
|
||||
core: int(trim(readfile(`${path}/topology/core_id`))),
|
||||
load: 0.0,
|
||||
};
|
||||
});
|
||||
|
||||
cpus = slice(cpus, 0, 64);
|
||||
if (length(cpus) < 2)
|
||||
exit(0);
|
||||
|
||||
function cpu_add_weight(cpu_id, weight)
|
||||
{
|
||||
let cpu = cpus[cpu_id];
|
||||
cpu.load += weight;
|
||||
for (let sibling in cpus) {
|
||||
if (sibling == cpu || sibling.core != cpu.core)
|
||||
continue;
|
||||
sibling.load += weight * cpu_thread_weight;
|
||||
}
|
||||
}
|
||||
|
||||
function get_next_cpu(weight, prev_cpu)
|
||||
{
|
||||
if (disable)
|
||||
return 0;
|
||||
|
||||
let sort_cpus = sort(slice(cpus), (a, b) => a.load - b.load);
|
||||
let idx = 0;
|
||||
|
||||
if (prev_cpu != null && sort_cpus[idx].id == prev_cpu)
|
||||
idx++;
|
||||
|
||||
let cpu = sort_cpus[idx].id;
|
||||
cpu_add_weight(cpu, weight);
|
||||
return cpu;
|
||||
}
|
||||
|
||||
let phys_devs = {};
|
||||
let netdev_phys = {};
|
||||
let netdevs = map(glob("/sys/class/net/*"), (dev) => basename(dev));
|
||||
|
||||
for (let dev in netdevs) {
|
||||
let pdev_path = realpath(`/sys/class/net/${dev}/device`);
|
||||
if (!pdev_path)
|
||||
continue;
|
||||
|
||||
if (length(glob(`/sys/class/net/${dev}/lower_*`)) > 0)
|
||||
continue;
|
||||
|
||||
let pdev = phys_devs[pdev_path];
|
||||
if (!pdev) {
|
||||
pdev = phys_devs[pdev_path] = {
|
||||
path: pdev_path,
|
||||
driver: basename(readlink(`${pdev_path}/driver`)),
|
||||
netdev: [],
|
||||
phy: [],
|
||||
tasks: [],
|
||||
};
|
||||
}
|
||||
|
||||
let phyidx = trim(readfile(`/sys/class/net/${dev}/phy80211/index`));
|
||||
if (phyidx != null) {
|
||||
let phy = `phy${phyidx}`;
|
||||
if (index(pdev.phy, phy) < 0)
|
||||
push(pdev.phy, phy);
|
||||
}
|
||||
|
||||
push(pdev.netdev, dev);
|
||||
netdev_phys[dev] = pdev;
|
||||
}
|
||||
|
||||
for (let path in glob("/proc/*/exe")) {
|
||||
readlink(path);
|
||||
if (error() != "No such file or directory")
|
||||
continue;
|
||||
|
||||
let pid = basename(dirname(path));
|
||||
let name = task_name(pid);
|
||||
for (let devname in phys_devs) {
|
||||
let dev = phys_devs[devname];
|
||||
if (!task_device_match(name, dev))
|
||||
continue;
|
||||
|
||||
push(dev.tasks, pid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function assign_dev_cpu(dev) {
|
||||
if (length(dev.tasks) > 0) {
|
||||
let cpu = dev.napi_cpu = get_next_cpu(napi_weight);
|
||||
for (let task in dev.tasks)
|
||||
set_task_cpu(task, cpu);
|
||||
}
|
||||
|
||||
if (length(dev.netdev) > 0) {
|
||||
let cpu;
|
||||
if (all_cpus)
|
||||
cpu = -1;
|
||||
else
|
||||
cpu = get_next_cpu(rx_weight, dev.napi_cpu);
|
||||
dev.rx_cpu = cpu;
|
||||
for (let netdev in dev.netdev)
|
||||
set_netdev_cpu(netdev, cpu);
|
||||
}
|
||||
}
|
||||
|
||||
// Assign ethernet devices first
|
||||
for (let devname in phys_devs) {
|
||||
let dev = phys_devs[devname];
|
||||
if (!length(dev.phy))
|
||||
assign_dev_cpu(dev);
|
||||
}
|
||||
|
||||
// Add bias to avoid assigning other tasks to CPUs with ethernet NAPI
|
||||
for (let devname in phys_devs) {
|
||||
let dev = phys_devs[devname];
|
||||
if (!length(dev.tasks) || dev.napi_cpu == null)
|
||||
continue;
|
||||
cpu_add_weight(dev.napi_cpu, eth_bias);
|
||||
}
|
||||
|
||||
// Assign WLAN devices
|
||||
for (let devname in phys_devs) {
|
||||
let dev = phys_devs[devname];
|
||||
if (length(dev.phy) > 0)
|
||||
assign_dev_cpu(dev);
|
||||
}
|
||||
|
||||
if (debug > 1)
|
||||
warn(sprintf("devices: %.J\ncpus: %.J\n", phys_devs, cpus));
|
||||
57
package/network/config/netifd/files/usr/share/udhcpc/default.script
Executable file
57
package/network/config/netifd/files/usr/share/udhcpc/default.script
Executable file
@@ -0,0 +1,57 @@
|
||||
#!/bin/sh
|
||||
[ -z "$1" ] && echo "Error: should be run by udhcpc" && exit 1
|
||||
|
||||
set_classless_routes() {
|
||||
local max=128
|
||||
local type
|
||||
while [ -n "$1" -a -n "$2" -a $max -gt 0 ]; do
|
||||
[ ${1##*/} -eq 32 ] && type=host || type=net
|
||||
echo "udhcpc: adding route for $type $1 via $2"
|
||||
route add -$type "$1" gw "$2" dev "$interface"
|
||||
max=$(($max-1))
|
||||
shift 2
|
||||
done
|
||||
}
|
||||
|
||||
setup_interface() {
|
||||
echo "udhcpc: ip addr add $ip/${subnet:-255.255.255.0} broadcast ${broadcast:-+} dev $interface"
|
||||
ip addr add $ip/${subnet:-255.255.255.0} broadcast ${broadcast:-+} dev $interface
|
||||
|
||||
[ -n "$router" ] && [ "$router" != "0.0.0.0" ] && [ "$router" != "255.255.255.255" ] && {
|
||||
echo "udhcpc: setting default routers: $router"
|
||||
|
||||
local valid_gw=""
|
||||
for i in $router ; do
|
||||
route add default gw $i dev $interface
|
||||
valid_gw="${valid_gw:+$valid_gw|}$i"
|
||||
done
|
||||
|
||||
eval $(route -n | awk '
|
||||
/^0.0.0.0\W{9}('$valid_gw')\W/ {next}
|
||||
/^0.0.0.0/ {print "route del -net "$1" gw "$2";"}
|
||||
')
|
||||
}
|
||||
|
||||
# CIDR STATIC ROUTES (rfc3442)
|
||||
[ -n "$staticroutes" ] && set_classless_routes $staticroutes
|
||||
[ -n "$msstaticroutes" ] && set_classless_routes $msstaticroutes
|
||||
}
|
||||
|
||||
|
||||
applied=
|
||||
case "$1" in
|
||||
deconfig)
|
||||
ip -4 addr flush dev "$interface"
|
||||
;;
|
||||
renew)
|
||||
setup_interface update
|
||||
;;
|
||||
bound)
|
||||
setup_interface ifup
|
||||
;;
|
||||
esac
|
||||
|
||||
# user rules
|
||||
[ -f /etc/udhcpc.user ] && . /etc/udhcpc.user
|
||||
|
||||
exit 0
|
||||
53
package/network/config/qos-scripts/Makefile
Normal file
53
package/network/config/qos-scripts/Makefile
Normal file
@@ -0,0 +1,53 @@
|
||||
#
|
||||
# Copyright (C) 2006-2015 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=qos-scripts
|
||||
PKG_VERSION:=1.3.1
|
||||
PKG_RELEASE:=33
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
|
||||
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/qos-scripts
|
||||
SECTION:=utils
|
||||
CATEGORY:=Base system
|
||||
DEPENDS:=+tc +kmod-sched-core +kmod-sched-connmark +kmod-ifb +iptables +iptables-mod-ipopt +iptables-mod-conntrack-extra
|
||||
TITLE:=QoS scripts
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/qos-scripts/description
|
||||
A set of scripts that abstract QoS configuration into a simple
|
||||
configuration file supporting stanzas that specify any number of QoS
|
||||
entries.
|
||||
endef
|
||||
|
||||
define Package/qos-scripts/conffiles
|
||||
/etc/config/qos
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/qos-scripts/install
|
||||
$(INSTALL_DIR) $(1)
|
||||
$(CP) ./files/* $(1)/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,qos-scripts))
|
||||
68
package/network/config/qos-scripts/files/etc/config/qos
Normal file
68
package/network/config/qos-scripts/files/etc/config/qos
Normal file
@@ -0,0 +1,68 @@
|
||||
# QoS configuration for OpenWrt
|
||||
|
||||
# INTERFACES:
|
||||
config interface wan
|
||||
option classgroup "Default"
|
||||
option enabled 0
|
||||
option upload 128
|
||||
option download 1024
|
||||
|
||||
# RULES:
|
||||
config classify
|
||||
option target "Priority"
|
||||
option ports "22,53"
|
||||
option comment "ssh, dns"
|
||||
config classify
|
||||
option target "Normal"
|
||||
option proto "tcp"
|
||||
option ports "20,21,25,80,110,443,993,995"
|
||||
option comment "ftp, smtp, http(s), imap"
|
||||
config classify
|
||||
option target "Express"
|
||||
option ports "5190"
|
||||
option comment "AOL, iChat, ICQ"
|
||||
config default
|
||||
option target "Express"
|
||||
option proto "udp"
|
||||
option pktsize "-500"
|
||||
config reclassify
|
||||
option target "Priority"
|
||||
option proto "icmp"
|
||||
config default
|
||||
option target "Bulk"
|
||||
option portrange "1024-65535"
|
||||
|
||||
|
||||
# Don't change the stuff below unless you
|
||||
# really know what it means :)
|
||||
|
||||
config classgroup "Default"
|
||||
option classes "Priority Express Normal Bulk"
|
||||
option default "Normal"
|
||||
|
||||
|
||||
config class "Priority"
|
||||
option packetsize 400
|
||||
option avgrate 10
|
||||
option priority 20
|
||||
config class "Priority_down"
|
||||
option packetsize 1000
|
||||
option avgrate 10
|
||||
|
||||
|
||||
config class "Express"
|
||||
option packetsize 1000
|
||||
option avgrate 50
|
||||
option priority 10
|
||||
|
||||
config class "Normal"
|
||||
option packetsize 1500
|
||||
option packetdelay 100
|
||||
option avgrate 10
|
||||
option priority 5
|
||||
config class "Normal_down"
|
||||
option avgrate 20
|
||||
|
||||
config class "Bulk"
|
||||
option avgrate 1
|
||||
option packetdelay 200
|
||||
2
package/network/config/qos-scripts/files/etc/hotplug.d/iface/10-qos
Executable file
2
package/network/config/qos-scripts/files/etc/hotplug.d/iface/10-qos
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
[ "$ACTION" = ifup ] && /etc/init.d/qos enabled && /usr/lib/qos/generate.sh interface "$INTERFACE" | sh
|
||||
28
package/network/config/qos-scripts/files/etc/init.d/qos
Executable file
28
package/network/config/qos-scripts/files/etc/init.d/qos
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2006 OpenWrt.org
|
||||
|
||||
START=50
|
||||
USE_PROCD=1
|
||||
|
||||
validate_qos_section()
|
||||
{
|
||||
uci_validate_section qos interface "${1}" \
|
||||
'enabled:bool' \
|
||||
'upload:uinteger' \
|
||||
'download:uinteger'
|
||||
}
|
||||
|
||||
service_triggers()
|
||||
{
|
||||
procd_add_reload_trigger "qos"
|
||||
procd_add_validation validate_qos_section
|
||||
qos-start
|
||||
}
|
||||
|
||||
start_service() {
|
||||
qos-start
|
||||
}
|
||||
|
||||
reload_service() {
|
||||
qos-start
|
||||
}
|
||||
4
package/network/config/qos-scripts/files/usr/bin/qos-start
Executable file
4
package/network/config/qos-scripts/files/usr/bin/qos-start
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
qos-stop
|
||||
/usr/lib/qos/generate.sh all | sh
|
||||
68
package/network/config/qos-scripts/files/usr/bin/qos-stat
Executable file
68
package/network/config/qos-scripts/files/usr/bin/qos-stat
Executable file
@@ -0,0 +1,68 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2011 OpenWrt.org
|
||||
|
||||
. /lib/functions.sh
|
||||
|
||||
include /lib/network
|
||||
|
||||
get_ifname() {
|
||||
local interface="$1"
|
||||
local cfgt
|
||||
|
||||
scan_interfaces
|
||||
config_get cfgt "$interface" TYPE
|
||||
[ "$cfgt" = "interface" ] && config_get "$interface" ifname
|
||||
}
|
||||
|
||||
qos_set_device() {
|
||||
config_get TYPE "$1" TYPE
|
||||
[ "interface" = "$TYPE" ] && {
|
||||
config_get device "$1" ifname
|
||||
[ -z "$device" ] && device="$(get_ifname $1)"
|
||||
config_set "$1" device "$device"
|
||||
}
|
||||
}
|
||||
|
||||
config_load qos
|
||||
config_foreach qos_set_device
|
||||
|
||||
print_comments() {
|
||||
echo ''
|
||||
echo '# Interface: '"$1"
|
||||
echo '# Direction: '"$2"
|
||||
echo '# Stats: '"$3"
|
||||
echo ''
|
||||
}
|
||||
|
||||
get_device() {
|
||||
( config_load network; scan_interfaces; config_get "$1" ifname )
|
||||
}
|
||||
|
||||
interface_stats() {
|
||||
local interface="$1"
|
||||
local device
|
||||
|
||||
device="$(get_device "$interface")"
|
||||
[ -z "$device" ] && config_get device "$interface" device
|
||||
config_get_bool enabled "$interface" enabled 1
|
||||
[ -z "$device" -o 1 -ne "$enabled" ] && {
|
||||
return 1
|
||||
}
|
||||
config_get_bool halfduplex "$interface" halfduplex 0
|
||||
|
||||
if [ 1 -ne "$halfduplex" ]; then
|
||||
unset halfduplex
|
||||
print_comments "$interface" "Egress" "Start"
|
||||
tc -s class show dev "$device"
|
||||
print_comments "$interface" "Egress" "End"
|
||||
id="root"
|
||||
else
|
||||
id=""
|
||||
fi
|
||||
|
||||
print_comments "$interface" "Ingress${halfduplex:+/Egress}" "Start"
|
||||
tc -s class show dev "$(tc filter show dev $device $id | grep mirred | sed -e 's,.*\(ifb.*\)).*,\1,')"
|
||||
print_comments "$interface" "Ingress${halfduplex:+/Egress}" "End"
|
||||
}
|
||||
|
||||
[ -z "$1" ] && config_foreach interface_stats interface || interface_stats "$1"
|
||||
7
package/network/config/qos-scripts/files/usr/bin/qos-stop
Executable file
7
package/network/config/qos-scripts/files/usr/bin/qos-stop
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
for iface in $(tc qdisc show | grep -E '(hfsc|ingress)' | awk '{print $5}'); do
|
||||
tc qdisc del dev "$iface" ingress 2>&- >&-
|
||||
tc qdisc del dev "$iface" root 2>&- >&-
|
||||
done
|
||||
/usr/lib/qos/generate.sh firewall stop | sh
|
||||
542
package/network/config/qos-scripts/files/usr/lib/qos/generate.sh
Executable file
542
package/network/config/qos-scripts/files/usr/lib/qos/generate.sh
Executable file
@@ -0,0 +1,542 @@
|
||||
#!/bin/sh
|
||||
[ -e /lib/functions.sh ] && . /lib/functions.sh || . ./functions.sh
|
||||
[ -x /sbin/modprobe ] && {
|
||||
insmod="modprobe"
|
||||
} || {
|
||||
insmod="insmod"
|
||||
}
|
||||
rmmod="rmmod"
|
||||
|
||||
add_insmod() {
|
||||
eval "export isset=\${insmod_$1}"
|
||||
case "$isset" in
|
||||
1) ;;
|
||||
*) {
|
||||
[ "$2" ] && append INSMOD "$rmmod $1 >&- 2>&-" "$N"
|
||||
append INSMOD "$insmod $* >&- 2>&-" "$N"; export insmod_$1=1
|
||||
};;
|
||||
esac
|
||||
}
|
||||
|
||||
[ -e /etc/config/network ] && {
|
||||
# only try to parse network config on openwrt
|
||||
|
||||
. /lib/functions/network.sh
|
||||
|
||||
find_ifname() {
|
||||
local ifname
|
||||
if network_get_device ifname "$1"; then
|
||||
echo "$ifname"
|
||||
else
|
||||
echo "Device for interface $1 not found." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
} || {
|
||||
find_ifname() {
|
||||
echo "Interface not found." >&2
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
parse_matching_rule() {
|
||||
local var="$1"
|
||||
local section="$2"
|
||||
local options="$3"
|
||||
local prefix="$4"
|
||||
local suffix="$5"
|
||||
local proto="$6"
|
||||
local mport=""
|
||||
local ports=""
|
||||
|
||||
append "$var" "$prefix" "$N"
|
||||
for option in $options; do
|
||||
case "$option" in
|
||||
proto) config_get value "$section" proto; proto="${proto:-$value}";;
|
||||
esac
|
||||
done
|
||||
config_get type "$section" TYPE
|
||||
case "$type" in
|
||||
classify) unset pkt; append "$var" "-m mark --mark 0/0x0f";;
|
||||
default) pkt=1; append "$var" "-m mark --mark 0/0xf0";;
|
||||
reclassify) pkt=1;;
|
||||
esac
|
||||
append "$var" "${proto:+-p $proto}"
|
||||
for option in $options; do
|
||||
config_get value "$section" "$option"
|
||||
|
||||
case "$pkt:$option" in
|
||||
*:srchost)
|
||||
append "$var" "-s $value"
|
||||
;;
|
||||
*:dsthost)
|
||||
append "$var" "-d $value"
|
||||
;;
|
||||
*:ports|*:srcports|*:dstports)
|
||||
value="$(echo "$value" | sed -e 's,-,:,g')"
|
||||
lproto=${lproto:-tcp}
|
||||
case "$proto" in
|
||||
""|tcp|udp) append "$var" "-m ${proto:-tcp -p tcp} -m multiport";;
|
||||
*) unset "$var"; return 0;;
|
||||
esac
|
||||
case "$option" in
|
||||
ports)
|
||||
config_set "$section" srcports ""
|
||||
config_set "$section" dstports ""
|
||||
config_set "$section" portrange ""
|
||||
append "$var" "--ports $value"
|
||||
;;
|
||||
srcports)
|
||||
config_set "$section" ports ""
|
||||
config_set "$section" dstports ""
|
||||
config_set "$section" portrange ""
|
||||
append "$var" "--sports $value"
|
||||
;;
|
||||
dstports)
|
||||
config_set "$section" ports ""
|
||||
config_set "$section" srcports ""
|
||||
config_set "$section" portrange ""
|
||||
append "$var" "--dports $value"
|
||||
;;
|
||||
esac
|
||||
ports=1
|
||||
;;
|
||||
*:portrange)
|
||||
config_set "$section" ports ""
|
||||
config_set "$section" srcports ""
|
||||
config_set "$section" dstports ""
|
||||
value="$(echo "$value" | sed -e 's,-,:,g')"
|
||||
case "$proto" in
|
||||
""|tcp|udp) append "$var" "-m ${proto:-tcp -p tcp} --sport $value --dport $value";;
|
||||
*) unset "$var"; return 0;;
|
||||
esac
|
||||
ports=1
|
||||
;;
|
||||
*:connbytes)
|
||||
value="$(echo "$value" | sed -e 's,-,:,g')"
|
||||
add_insmod xt_connbytes
|
||||
append "$var" "-m connbytes --connbytes $value --connbytes-dir both --connbytes-mode bytes"
|
||||
;;
|
||||
*:comment)
|
||||
add_insmod xt_comment
|
||||
append "$var" "-m comment --comment '$value'"
|
||||
;;
|
||||
*:tos)
|
||||
add_insmod xt_dscp
|
||||
case "$value" in
|
||||
!*) append "$var" "-m tos ! --tos $value";;
|
||||
*) append "$var" "-m tos --tos $value"
|
||||
esac
|
||||
;;
|
||||
*:dscp)
|
||||
add_insmod xt_dscp
|
||||
dscp_option="--dscp"
|
||||
[ -z "${value%%[EBCA]*}" ] && dscp_option="--dscp-class"
|
||||
case "$value" in
|
||||
!*) append "$var" "-m dscp ! $dscp_option $value";;
|
||||
*) append "$var" "-m dscp $dscp_option $value"
|
||||
esac
|
||||
;;
|
||||
*:direction)
|
||||
value="$(echo "$value" | sed -e 's,-,:,g')"
|
||||
if [ "$value" = "out" ]; then
|
||||
append "$var" "-o $device"
|
||||
elif [ "$value" = "in" ]; then
|
||||
append "$var" "-i $device"
|
||||
fi
|
||||
;;
|
||||
*:srciface)
|
||||
append "$var" "-i $value"
|
||||
;;
|
||||
1:pktsize)
|
||||
value="$(echo "$value" | sed -e 's,-,:,g')"
|
||||
add_insmod xt_length
|
||||
append "$var" "-m length --length $value"
|
||||
;;
|
||||
1:limit)
|
||||
add_insmod xt_limit
|
||||
append "$var" "-m limit --limit $value"
|
||||
;;
|
||||
1:tcpflags)
|
||||
case "$proto" in
|
||||
tcp) append "$var" "-m tcp --tcp-flags ALL $value";;
|
||||
*) unset $var; return 0;;
|
||||
esac
|
||||
;;
|
||||
1:mark)
|
||||
config_get class "${value##!}" classnr
|
||||
[ -z "$class" ] && continue;
|
||||
case "$value" in
|
||||
!*) append "$var" "-m mark ! --mark $class/0x0f";;
|
||||
*) append "$var" "-m mark --mark $class/0x0f";;
|
||||
esac
|
||||
;;
|
||||
1:TOS)
|
||||
add_insmod xt_DSCP
|
||||
config_get TOS "$rule" 'TOS'
|
||||
suffix="-j TOS --set-tos "${TOS:-"Normal-Service"}
|
||||
;;
|
||||
1:DSCP)
|
||||
add_insmod xt_DSCP
|
||||
config_get DSCP "$rule" 'DSCP'
|
||||
[ -z "${DSCP%%[EBCA]*}" ] && set_value="--set-dscp-class $DSCP" \
|
||||
|| set_value="--set-dscp $DSCP"
|
||||
suffix="-j DSCP $set_value"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
append "$var" "$suffix"
|
||||
case "$ports:$proto" in
|
||||
1:) parse_matching_rule "$var" "$section" "$options" "$prefix" "$suffix" "udp";;
|
||||
esac
|
||||
}
|
||||
|
||||
config_cb() {
|
||||
option_cb() {
|
||||
return 0
|
||||
}
|
||||
case "$1" in
|
||||
interface)
|
||||
config_set "$2" "classgroup" "Default"
|
||||
config_set "$2" "upload" "128"
|
||||
;;
|
||||
classify|default|reclassify)
|
||||
option_cb() {
|
||||
append "CONFIG_${CONFIG_SECTION}_options" "$1"
|
||||
}
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
qos_parse_config() {
|
||||
config_get TYPE "$1" TYPE
|
||||
case "$TYPE" in
|
||||
interface)
|
||||
config_get_bool enabled "$1" enabled 1
|
||||
[ 1 -eq "$enabled" ] && {
|
||||
config_get classgroup "$1" classgroup
|
||||
config_set "$1" ifbdev "$C"
|
||||
C=$(($C+1))
|
||||
append INTERFACES "$1"
|
||||
config_set "$classgroup" enabled 1
|
||||
config_get device "$1" device
|
||||
[ -z "$device" ] && {
|
||||
device="$(find_ifname $1)"
|
||||
[ -z "$device" ] && exit 1
|
||||
config_set "$1" device "$device"
|
||||
}
|
||||
}
|
||||
;;
|
||||
classgroup) append CG "$1";;
|
||||
classify|default|reclassify)
|
||||
case "$TYPE" in
|
||||
classify) var="ctrules";;
|
||||
*) var="rules";;
|
||||
esac
|
||||
append "$var" "$1"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
enum_classes() {
|
||||
local c="0"
|
||||
config_get classes "$1" classes
|
||||
config_get default "$1" default
|
||||
for class in $classes; do
|
||||
c="$(($c + 1))"
|
||||
config_set "${class}" classnr $c
|
||||
case "$class" in
|
||||
$default) class_default=$c;;
|
||||
esac
|
||||
done
|
||||
class_default="${class_default:-$c}"
|
||||
}
|
||||
|
||||
cls_var() {
|
||||
local varname="$1"
|
||||
local class="$2"
|
||||
local name="$3"
|
||||
local type="$4"
|
||||
local default="$5"
|
||||
local tmp tmp1 tmp2
|
||||
config_get tmp1 "$class" "$name"
|
||||
config_get tmp2 "${class}_${type}" "$name"
|
||||
tmp="${tmp2:-$tmp1}"
|
||||
tmp="${tmp:-$tmp2}"
|
||||
export ${varname}="${tmp:-$default}"
|
||||
}
|
||||
|
||||
tcrules() {
|
||||
_dir=/usr/lib/qos
|
||||
[ -e $_dir/tcrules.awk ] || _dir=.
|
||||
echo "$cstr" | awk \
|
||||
-v device="$dev" \
|
||||
-v linespeed="$rate" \
|
||||
-v direction="$dir" \
|
||||
-f $_dir/tcrules.awk
|
||||
}
|
||||
|
||||
start_interface() {
|
||||
local iface="$1"
|
||||
local num_ifb="$2"
|
||||
config_get device "$iface" device
|
||||
config_get_bool enabled "$iface" enabled 1
|
||||
[ -z "$device" -o 1 -ne "$enabled" ] && {
|
||||
return 1
|
||||
}
|
||||
config_get upload "$iface" upload
|
||||
config_get_bool halfduplex "$iface" halfduplex
|
||||
config_get download "$iface" download
|
||||
config_get classgroup "$iface" classgroup
|
||||
config_get_bool overhead "$iface" overhead 0
|
||||
|
||||
download="${download:-${halfduplex:+$upload}}"
|
||||
enum_classes "$classgroup"
|
||||
for dir in ${halfduplex:-up} ${download:+down}; do
|
||||
case "$dir" in
|
||||
up)
|
||||
[ "$overhead" = 1 ] && upload=$(($upload * 98 / 100 - (15 * 128 / $upload)))
|
||||
dev="$device"
|
||||
rate="$upload"
|
||||
dl_mode=""
|
||||
prefix="cls"
|
||||
;;
|
||||
down)
|
||||
[ "$(ls -d /proc/sys/net/ipv4/conf/ifb* 2>&- | wc -l)" -ne "$num_ifb" ] && add_insmod ifb numifbs="$num_ifb"
|
||||
config_get ifbdev "$iface" ifbdev
|
||||
[ "$overhead" = 1 ] && download=$(($download * 98 / 100 - (80 * 1024 / $download)))
|
||||
dev="ifb$ifbdev"
|
||||
rate="$download"
|
||||
dl_mode=1
|
||||
prefix="d_cls"
|
||||
;;
|
||||
*) continue;;
|
||||
esac
|
||||
cstr=
|
||||
for class in $classes; do
|
||||
cls_var pktsize "$class" packetsize $dir 1500
|
||||
cls_var pktdelay "$class" packetdelay $dir 0
|
||||
cls_var maxrate "$class" limitrate $dir 100
|
||||
cls_var prio "$class" priority $dir 1
|
||||
cls_var avgrate "$class" avgrate $dir 0
|
||||
cls_var qdisc "$class" qdisc $dir ""
|
||||
cls_var filter "$class" filter $dir ""
|
||||
config_get classnr "$class" classnr
|
||||
append cstr "$classnr:$prio:$avgrate:$pktsize:$pktdelay:$maxrate:$qdisc:$filter" "$N"
|
||||
done
|
||||
append ${prefix}q "$(tcrules)" "$N"
|
||||
export dev_${dir}="ip link add ${dev} type ifb >&- 2>&-
|
||||
ip link set $dev up >&- 2>&-
|
||||
tc qdisc del dev $dev root >&- 2>&-
|
||||
tc qdisc add dev $dev root handle 1: hfsc default ${class_default}0
|
||||
tc class add dev $dev parent 1: classid 1:1 hfsc sc rate ${rate}kbit ul rate ${rate}kbit"
|
||||
done
|
||||
[ -n "$download" ] && {
|
||||
add_insmod cls_u32
|
||||
add_insmod em_u32
|
||||
add_insmod act_connmark
|
||||
add_insmod act_mirred
|
||||
add_insmod sch_ingress
|
||||
}
|
||||
if [ -n "$halfduplex" ]; then
|
||||
export dev_up="tc qdisc del dev $device root >&- 2>&-
|
||||
tc qdisc add dev $device root handle 1: hfsc
|
||||
tc filter add dev $device parent 1: prio 10 u32 match u32 0 0 flowid 1:1 action mirred egress redirect dev ifb$ifbdev"
|
||||
elif [ -n "$download" ]; then
|
||||
append dev_${dir} "tc qdisc del dev $device ingress >&- 2>&-
|
||||
tc qdisc add dev $device ingress
|
||||
tc filter add dev $device parent ffff: prio 1 u32 match u32 0 0 flowid 1:1 action connmark action mirred egress redirect dev ifb$ifbdev" "$N"
|
||||
fi
|
||||
add_insmod cls_fw
|
||||
add_insmod sch_hfsc
|
||||
|
||||
cat <<EOF
|
||||
${INSMOD:+$INSMOD$N}${dev_up:+$dev_up
|
||||
$clsq
|
||||
}${ifbdev:+$dev_down
|
||||
$d_clsq
|
||||
$d_clsl
|
||||
$d_clsf
|
||||
}
|
||||
EOF
|
||||
unset INSMOD clsq clsf clsl d_clsq d_clsl d_clsf dev_up dev_down
|
||||
}
|
||||
|
||||
start_interfaces() {
|
||||
local C="$1"
|
||||
for iface in $INTERFACES; do
|
||||
start_interface "$iface" "$C"
|
||||
done
|
||||
}
|
||||
|
||||
add_rules() {
|
||||
local var="$1"
|
||||
local rules="$2"
|
||||
local prefix="$3"
|
||||
|
||||
for rule in $rules; do
|
||||
unset iptrule
|
||||
config_get target "$rule" target
|
||||
config_get target "$target" classnr
|
||||
config_get options "$rule" options
|
||||
|
||||
## If we want to override the TOS field, let's clear the DSCP field first.
|
||||
[ ! -z "$(echo $options | grep 'TOS')" ] && {
|
||||
s_options=${options%%TOS}
|
||||
add_insmod xt_DSCP
|
||||
parse_matching_rule iptrule "$rule" "$s_options" "$prefix" "-j DSCP --set-dscp 0"
|
||||
append "$var" "$iptrule" "$N"
|
||||
unset iptrule
|
||||
}
|
||||
|
||||
target=$(($target | ($target << 4)))
|
||||
parse_matching_rule iptrule "$rule" "$options" "$prefix" "-j MARK --set-mark $target/0xff"
|
||||
append "$var" "$iptrule" "$N"
|
||||
done
|
||||
}
|
||||
|
||||
start_cg() {
|
||||
local cg="$1"
|
||||
local iptrules
|
||||
local pktrules
|
||||
local sizerules
|
||||
enum_classes "$cg"
|
||||
for command in $iptables; do
|
||||
add_rules iptrules "$ctrules" "$command -w -t mangle -A qos_${cg}_ct"
|
||||
done
|
||||
config_get classes "$cg" classes
|
||||
for class in $classes; do
|
||||
config_get mark "$class" classnr
|
||||
config_get maxsize "$class" maxsize
|
||||
[ -z "$maxsize" -o -z "$mark" ] || {
|
||||
add_insmod xt_length
|
||||
for command in $iptables; do
|
||||
append pktrules "$command -w -t mangle -A qos_${cg} -m mark --mark $mark/0x0f -m length --length $maxsize: -j MARK --set-mark 0/0xff" "$N"
|
||||
done
|
||||
}
|
||||
done
|
||||
for command in $iptables; do
|
||||
add_rules pktrules "$rules" "$command -w -t mangle -A qos_${cg}"
|
||||
done
|
||||
for iface in $INTERFACES; do
|
||||
config_get classgroup "$iface" classgroup
|
||||
config_get device "$iface" device
|
||||
config_get ifbdev "$iface" ifbdev
|
||||
config_get upload "$iface" upload
|
||||
config_get download "$iface" download
|
||||
config_get halfduplex "$iface" halfduplex
|
||||
download="${download:-${halfduplex:+$upload}}"
|
||||
for command in $iptables; do
|
||||
append up "$command -w -t mangle -A OUTPUT -o $device -j qos_${cg}" "$N"
|
||||
append up "$command -w -t mangle -A FORWARD -o $device -j qos_${cg}" "$N"
|
||||
done
|
||||
done
|
||||
cat <<EOF
|
||||
$INSMOD
|
||||
EOF
|
||||
|
||||
for command in $iptables; do
|
||||
cat <<EOF
|
||||
$command -w -t mangle -N qos_${cg}
|
||||
$command -w -t mangle -N qos_${cg}_ct
|
||||
EOF
|
||||
done
|
||||
cat <<EOF
|
||||
${iptrules:+${iptrules}${N}}
|
||||
EOF
|
||||
for command in $iptables; do
|
||||
cat <<EOF
|
||||
$command -w -t mangle -A qos_${cg}_ct -j CONNMARK --save-mark --mask 0xff
|
||||
$command -w -t mangle -A qos_${cg} -j CONNMARK --restore-mark --mask 0x0f
|
||||
$command -w -t mangle -A qos_${cg} -m mark --mark 0/0x0f -j qos_${cg}_ct
|
||||
EOF
|
||||
done
|
||||
cat <<EOF
|
||||
$pktrules
|
||||
EOF
|
||||
for command in $iptables; do
|
||||
cat <<EOF
|
||||
$command -w -t mangle -A qos_${cg} -j CONNMARK --save-mark --mask 0xff
|
||||
EOF
|
||||
done
|
||||
cat <<EOF
|
||||
$up$N${down:+${down}$N}
|
||||
EOF
|
||||
unset INSMOD
|
||||
}
|
||||
|
||||
start_firewall() {
|
||||
add_insmod xt_multiport
|
||||
add_insmod xt_connmark
|
||||
stop_firewall
|
||||
for group in $CG; do
|
||||
start_cg $group
|
||||
done
|
||||
}
|
||||
|
||||
stop_firewall() {
|
||||
# Builds up a list of iptables commands to flush the qos_* chains,
|
||||
# remove rules referring to them, then delete them
|
||||
|
||||
# Print rules in the mangle table, like iptables-save
|
||||
for command in $iptables; do
|
||||
$command -w -t mangle -S |
|
||||
# Find rules for the qos_* chains
|
||||
grep -E '(^-N qos_|-j qos_)' |
|
||||
# Exclude rules in qos_* chains (inter-qos_* refs)
|
||||
grep -v '^-A qos_' |
|
||||
# Replace -N with -X and hold, with -F and print
|
||||
# Replace -A with -D
|
||||
# Print held lines at the end (note leading newline)
|
||||
sed -e '/^-N/{s/^-N/-X/;H;s/^-X/-F/}' \
|
||||
-e 's/^-A/-D/' \
|
||||
-e '${p;g}' |
|
||||
# Make into proper iptables calls
|
||||
# Note: awkward in previous call due to hold space usage
|
||||
sed -n -e "s/^./${command} -w -t mangle &/p"
|
||||
done
|
||||
}
|
||||
|
||||
C="0"
|
||||
INTERFACES=""
|
||||
[ -e ./qos.conf ] && {
|
||||
. ./qos.conf
|
||||
config_cb
|
||||
} || {
|
||||
config_load qos
|
||||
config_foreach qos_parse_config
|
||||
}
|
||||
|
||||
C="0"
|
||||
for iface in $INTERFACES; do
|
||||
export C="$(($C + 1))"
|
||||
done
|
||||
|
||||
[ -x /usr/sbin/ip6tables ] && {
|
||||
iptables="ip6tables iptables"
|
||||
} || {
|
||||
iptables="iptables"
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
all)
|
||||
start_interfaces "$C"
|
||||
start_firewall
|
||||
;;
|
||||
interface)
|
||||
start_interface "$2" "$C"
|
||||
;;
|
||||
interfaces)
|
||||
start_interfaces
|
||||
;;
|
||||
firewall)
|
||||
case "$2" in
|
||||
stop)
|
||||
stop_firewall
|
||||
;;
|
||||
start|"")
|
||||
start_firewall
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
105
package/network/config/qos-scripts/files/usr/lib/qos/tcrules.awk
Normal file
105
package/network/config/qos-scripts/files/usr/lib/qos/tcrules.awk
Normal file
@@ -0,0 +1,105 @@
|
||||
BEGIN {
|
||||
dmax=100
|
||||
if (!(linespeed > 0)) linespeed = 128
|
||||
FS=":"
|
||||
n = 0
|
||||
}
|
||||
|
||||
($1 != "") {
|
||||
n++
|
||||
class[n] = $1
|
||||
prio[n] = $2
|
||||
avgrate[n] = ($3 * linespeed / 100)
|
||||
pktsize[n] = $4
|
||||
delay[n] = $5
|
||||
maxrate[n] = ($6 * linespeed / 100)
|
||||
qdisc[n] = $7
|
||||
filter[n] = $8
|
||||
}
|
||||
|
||||
END {
|
||||
allocated = 0
|
||||
maxdelay = 0
|
||||
|
||||
for (i = 1; i <= n; i++) {
|
||||
# set defaults
|
||||
if (!(pktsize[i] > 0)) pktsize[i] = 1500
|
||||
if (!(prio[i] > 0)) prio[i] = 1
|
||||
|
||||
allocated += avgrate[i]
|
||||
sum_prio += prio[i]
|
||||
if ((avgrate[i] > 0) && !(delay[i] > 0)) {
|
||||
sum_rtprio += prio[i]
|
||||
}
|
||||
}
|
||||
|
||||
# allocation of m1 in rt classes:
|
||||
# sum(d * m1) must not exceed dmax * (linespeed - allocated)
|
||||
dmax = 0
|
||||
for (i = 1; i <= n; i++) {
|
||||
if (avgrate[i] > 0) {
|
||||
rtm2[i] = avgrate[i]
|
||||
if (delay[i] > 0) {
|
||||
d[i] = delay[i]
|
||||
} else {
|
||||
d[i] = 2 * pktsize[i] * 1000 / (linespeed * 1024)
|
||||
if (d[i] > dmax) dmax = d[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ds_avail = dmax * (linespeed - allocated)
|
||||
for (i = 1; i <= n; i++) {
|
||||
lsm1[i] = 0
|
||||
rtm1[i] = 0
|
||||
lsm2[i] = linespeed * prio[i] / sum_prio
|
||||
if ((avgrate[i] > 0) && (d[i] > 0)) {
|
||||
if (!(delay[i] > 0)) {
|
||||
ds = ds_avail * prio[i] / sum_rtprio
|
||||
ds_avail -= ds
|
||||
rtm1[i] = rtm2[i] + ds/d[i]
|
||||
}
|
||||
lsm1[i] = rtm1[i]
|
||||
}
|
||||
else {
|
||||
d[i] = 0
|
||||
}
|
||||
}
|
||||
|
||||
# main qdisc
|
||||
for (i = 1; i <= n; i++) {
|
||||
printf "tc class add dev "device" parent 1:1 classid 1:"class[i]"0 hfsc"
|
||||
if (rtm1[i] > 0) {
|
||||
printf " rt m1 " int(rtm1[i]) "kbit d " int(d[i] * 1000) "us m2 " int(rtm2[i])"kbit"
|
||||
}
|
||||
printf " ls m1 " int(lsm1[i]) "kbit d " int(d[i] * 1000) "us m2 " int(lsm2[i]) "kbit"
|
||||
print " ul rate " int(maxrate[i]) "kbit"
|
||||
}
|
||||
|
||||
# leaf qdisc
|
||||
avpkt = 1200
|
||||
for (i = 1; i <= n; i++) {
|
||||
print "tc qdisc add dev "device" parent 1:"class[i]"0 handle "class[i]"00: fq_codel limit 800 quantum 300 noecn"
|
||||
}
|
||||
|
||||
# filter rule
|
||||
for (i = 1; i <= n; i++) {
|
||||
filter_cmd = "tc filter add dev "device" parent 1: prio %d handle %s fw flowid 1:%d0\n";
|
||||
if (direction == "up") {
|
||||
filter_1 = sprintf("0x%x0/0xf0", class[i])
|
||||
filter_2 = sprintf("0x0%x/0x0f", class[i])
|
||||
} else {
|
||||
filter_1 = sprintf("0x0%x/0x0f", class[i])
|
||||
filter_2 = sprintf("0x%x0/0xf0", class[i])
|
||||
}
|
||||
|
||||
printf filter_cmd, class[i] * 2, filter_1, class[i]
|
||||
printf filter_cmd, class[i] * 2 + 1, filter_2, class[i]
|
||||
|
||||
filterc=1
|
||||
if (filter[i] != "") {
|
||||
print " tc filter add dev "device" parent "class[i]"00: handle "filterc"0 "filter[i]
|
||||
filterc=filterc+1
|
||||
}
|
||||
}
|
||||
}
|
||||
76
package/network/config/qosify/Makefile
Normal file
76
package/network/config/qosify/Makefile
Normal file
@@ -0,0 +1,76 @@
|
||||
#
|
||||
# Copyright (C) 2021 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=qosify
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/qosify.git
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_DATE:=2023-03-07
|
||||
PKG_SOURCE_VERSION:=9a47ea4b683dd845ec94534fcd82d3117c9ab313
|
||||
PKG_MIRROR_HASH:=3d97456dcd13f481beff9a87d939e4bd671577865ed7cfc11b00d6e40f3e5621
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
PKG_BUILD_DEPENDS:=bpf-headers
|
||||
PKG_FLAGS:=nonshared
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
include $(INCLUDE_DIR)/bpf.mk
|
||||
include $(INCLUDE_DIR)/nls.mk
|
||||
|
||||
define Package/qosify
|
||||
SECTION:=utils
|
||||
CATEGORY:=Base system
|
||||
TITLE:=A simple QoS solution based eBPF + CAKE
|
||||
DEPENDS:=+libbpf +libubox +libubus +libnl-tiny +kmod-sched-cake +kmod-sched-bpf +kmod-ifb +tc $(BPF_DEPENDS)
|
||||
endef
|
||||
|
||||
TARGET_CFLAGS += \
|
||||
-Wno-error=deprecated-declarations \
|
||||
-I$(STAGING_DIR)/usr/include/libnl-tiny \
|
||||
-I$(STAGING_DIR)/usr/include
|
||||
|
||||
CMAKE_OPTIONS += \
|
||||
-DLIBNL_LIBS=-lnl-tiny
|
||||
|
||||
define Build/Compile
|
||||
$(call CompileBPF,$(PKG_BUILD_DIR)/qosify-bpf.c)
|
||||
$(Build/Compile/Default)
|
||||
endef
|
||||
|
||||
define Package/qosify/conffiles
|
||||
/etc/config/qosify
|
||||
/etc/qosify/00-defaults.conf
|
||||
endef
|
||||
|
||||
define Package/qosify/install
|
||||
$(INSTALL_DIR) \
|
||||
$(1)/lib/bpf \
|
||||
$(1)/usr/sbin \
|
||||
$(1)/etc/init.d \
|
||||
$(1)/etc/config \
|
||||
$(1)/etc/qosify \
|
||||
$(1)/etc/hotplug.d/net \
|
||||
$(1)/etc/hotplug.d/iface
|
||||
$(INSTALL_DATA) $(PKG_BUILD_DIR)/qosify-bpf.o $(1)/lib/bpf
|
||||
$(INSTALL_BIN) \
|
||||
$(PKG_INSTALL_DIR)/usr/bin/qosify \
|
||||
./files/qosify-status \
|
||||
$(1)/usr/sbin/
|
||||
$(INSTALL_BIN) ./files/qosify.init $(1)/etc/init.d/qosify
|
||||
$(INSTALL_DATA) ./files/qosify-defaults.conf $(1)/etc/qosify/00-defaults.conf
|
||||
$(INSTALL_DATA) ./files/qosify.conf $(1)/etc/config/qosify
|
||||
$(INSTALL_DATA) ./files/qosify.hotplug $(1)/etc/hotplug.d/net/10-qosify
|
||||
$(INSTALL_DATA) ./files/qosify.hotplug $(1)/etc/hotplug.d/iface/10-qosify
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,qosify))
|
||||
17
package/network/config/qosify/files/qosify-defaults.conf
Normal file
17
package/network/config/qosify/files/qosify-defaults.conf
Normal file
@@ -0,0 +1,17 @@
|
||||
# DNS
|
||||
tcp:53 voice
|
||||
tcp:5353 voice
|
||||
udp:53 voice
|
||||
udp:5353 voice
|
||||
|
||||
# NTP
|
||||
udp:123 voice
|
||||
|
||||
# SSH
|
||||
tcp:22 +video
|
||||
|
||||
# HTTP/QUIC
|
||||
tcp:80 +besteffort
|
||||
tcp:443 +besteffort
|
||||
udp:80 +besteffort
|
||||
udp:443 +besteffort
|
||||
70
package/network/config/qosify/files/qosify-status
Normal file
70
package/network/config/qosify/files/qosify-status
Normal file
@@ -0,0 +1,70 @@
|
||||
#!/bin/sh
|
||||
. /usr/share/libubox/jshn.sh
|
||||
|
||||
dev_status() {
|
||||
tc -s qdisc sh dev "$1" root
|
||||
echo
|
||||
}
|
||||
|
||||
common_status() {
|
||||
json_get_vars ifname ingress egress
|
||||
|
||||
[ -n "$ifname" ] || return
|
||||
|
||||
[ "$egress" -gt 0 ] && {
|
||||
echo "egress status:"
|
||||
dev_status "$ifname"
|
||||
}
|
||||
[ "$ingress" -gt 0 ] && {
|
||||
echo "ingress status:"
|
||||
dev_status "$(printf %.16s "ifb-$ifname")"
|
||||
}
|
||||
}
|
||||
|
||||
is_active() {
|
||||
json_get_vars active
|
||||
|
||||
[ "${active:-0}" -gt 0 ]
|
||||
}
|
||||
|
||||
device_status() {
|
||||
local name="$2"
|
||||
|
||||
json_select "$name"
|
||||
|
||||
if is_active; then
|
||||
status="active"
|
||||
else
|
||||
status="not found"
|
||||
fi
|
||||
|
||||
echo "===== device $name: $status ====="
|
||||
|
||||
is_active && common_status
|
||||
|
||||
json_select ..
|
||||
}
|
||||
|
||||
interface_status() {
|
||||
local name="$2"
|
||||
|
||||
json_select "$name"
|
||||
|
||||
if is_active; then
|
||||
status="active"
|
||||
elif ubus -S -t 0 wait_for "network.interface.$name"; then
|
||||
status="down"
|
||||
else
|
||||
status="not found"
|
||||
fi
|
||||
|
||||
echo "===== interface $name: $status ====="
|
||||
|
||||
is_active && common_status
|
||||
|
||||
json_select ..
|
||||
}
|
||||
|
||||
json_load "$(ubus call qosify status)"
|
||||
json_for_each_item device_status devices
|
||||
json_for_each_item interface_status interfaces
|
||||
48
package/network/config/qosify/files/qosify.conf
Normal file
48
package/network/config/qosify/files/qosify.conf
Normal file
@@ -0,0 +1,48 @@
|
||||
config defaults
|
||||
list defaults /etc/qosify/*.conf
|
||||
option dscp_prio video
|
||||
option dscp_icmp +besteffort
|
||||
option dscp_default_udp besteffort
|
||||
option prio_max_avg_pkt_len 500
|
||||
|
||||
config class besteffort
|
||||
option ingress CS0
|
||||
option egress CS0
|
||||
|
||||
config class bulk
|
||||
option ingress LE
|
||||
option egress LE
|
||||
|
||||
config class video
|
||||
option ingress AF41
|
||||
option egress AF41
|
||||
|
||||
config class voice
|
||||
option ingress CS6
|
||||
option egress CS6
|
||||
option bulk_trigger_pps 100
|
||||
option bulk_trigger_timeout 5
|
||||
option dscp_bulk CS0
|
||||
|
||||
config interface wan
|
||||
option name wan
|
||||
option disabled 1
|
||||
option bandwidth_up 100mbit
|
||||
option bandwidth_down 100mbit
|
||||
option overhead_type none
|
||||
# defaults:
|
||||
option ingress 1
|
||||
option egress 1
|
||||
option mode diffserv4
|
||||
option nat 1
|
||||
option host_isolate 1
|
||||
option autorate_ingress 0
|
||||
option ingress_options ""
|
||||
option egress_options ""
|
||||
option options ""
|
||||
|
||||
config device wandev
|
||||
option disabled 1
|
||||
option name wan
|
||||
option bandwidth 100mbit
|
||||
|
||||
2
package/network/config/qosify/files/qosify.hotplug
Normal file
2
package/network/config/qosify/files/qosify.hotplug
Normal file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
ubus call qosify check_devices
|
||||
171
package/network/config/qosify/files/qosify.init
Normal file
171
package/network/config/qosify/files/qosify.init
Normal file
@@ -0,0 +1,171 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (c) 2021 OpenWrt.org
|
||||
|
||||
START=19
|
||||
|
||||
USE_PROCD=1
|
||||
PROG=/usr/sbin/qosify
|
||||
|
||||
add_option() {
|
||||
local type="$1"
|
||||
local name="$2"
|
||||
|
||||
config_get val "$cfg" "$name"
|
||||
|
||||
[ -n "$val" ] && json_add_$type "$name" "$val"
|
||||
}
|
||||
|
||||
add_flow_config() {
|
||||
local cfg="$1"
|
||||
|
||||
add_option string dscp_prio
|
||||
add_option string dscp_bulk
|
||||
add_option int bulk_trigger_timeout
|
||||
add_option int bulk_trigger_pps
|
||||
add_option int prio_max_avg_pkt_len
|
||||
}
|
||||
|
||||
add_defaults() {
|
||||
cfg="$1"
|
||||
|
||||
json_add_boolean reset 1
|
||||
|
||||
config_get files "$cfg" defaults
|
||||
json_add_array files
|
||||
for i in $files; do
|
||||
json_add_string "" "$i"
|
||||
done
|
||||
json_close_array
|
||||
|
||||
add_flow_config "$cfg"
|
||||
add_option int timeout
|
||||
add_option string dscp_icmp
|
||||
add_option string dscp_default_udp
|
||||
add_option string dscp_default_tcp
|
||||
}
|
||||
|
||||
add_interface() {
|
||||
local cfg="$1"
|
||||
|
||||
config_get_bool disabled "$cfg" disabled 0
|
||||
[ "$disabled" -gt 0 ] && return
|
||||
|
||||
config_get name "$cfg" name
|
||||
json_add_object "$name"
|
||||
|
||||
config_get bw "$cfg" bandwidth
|
||||
|
||||
config_get bw_up "$cfg" bandwidth_up
|
||||
bw_up="${bw_up:-$bw}"
|
||||
[ -n "$bw_up" ] && json_add_string bandwidth_up "$bw_up"
|
||||
|
||||
config_get bw_down "$cfg" bandwidth_down
|
||||
bw_down="${bw_down:-$bw}"
|
||||
[ -n "$bw_down" ] && json_add_string bandwidth_down "$bw_down"
|
||||
|
||||
add_option string bandwidth
|
||||
add_option boolean ingress
|
||||
add_option boolean egress
|
||||
add_option string mode
|
||||
add_option boolean nat
|
||||
add_option boolean host_isolate
|
||||
add_option boolean autorate_ingress
|
||||
add_option string ingress_options
|
||||
add_option string egress_options
|
||||
|
||||
config_get user_options "$cfg" options
|
||||
|
||||
config_get otype "$cfg" overhead_type
|
||||
options=
|
||||
case "$otype" in
|
||||
none);;
|
||||
manual)
|
||||
config_get overhead "$cfg" overhead
|
||||
[ -n "$overhead" ] && append options "overhead $overhead"
|
||||
|
||||
config_get encap "$cfg" overhead_encap
|
||||
[ -n "$encap" ] && append options "$encap"
|
||||
;;
|
||||
conservative|\
|
||||
pppoa-vcmux|\
|
||||
pppoa-llc|\
|
||||
pppoe-vcmux|\
|
||||
pppoe-llcsnap|\
|
||||
bridged-vcmux|\
|
||||
bridged-llcsnap|\
|
||||
ipoa-vcmux|\
|
||||
ipoa-llcsnap|\
|
||||
pppoe-ptm|\
|
||||
bridged-ptm|\
|
||||
docsis|\
|
||||
ethernet)
|
||||
append options "$otype"
|
||||
;;
|
||||
esac
|
||||
|
||||
config_get mpu "$cfg" overhead_mpu
|
||||
[ -n "$mpu" ] && append options "mpu $mpu"
|
||||
|
||||
config_get ovlan "$cfg" overhead_vlan
|
||||
[ "${ovlan:-0}" -ge 2 ] && append options "ether-vlan"
|
||||
[ "${ovlan:-0}" -ge 1 ] && append options "ether-vlan"
|
||||
|
||||
[ -n "$user_options" ] && append options "$user_options"
|
||||
[ -n "$options" ] && json_add_string options "$options"
|
||||
|
||||
json_close_object
|
||||
}
|
||||
|
||||
add_class() {
|
||||
local cfg="$1"
|
||||
|
||||
config_get value "$cfg" value
|
||||
config_get ingress "$cfg" ingress
|
||||
config_get egress "$cfg" egress
|
||||
|
||||
json_add_object "$cfg"
|
||||
json_add_string ingress "${ingress:-$value}"
|
||||
json_add_string egress "${egress:-$value}"
|
||||
add_flow_config "$cfg"
|
||||
json_close_object
|
||||
}
|
||||
|
||||
|
||||
reload_service() {
|
||||
json_init
|
||||
|
||||
config_load qosify
|
||||
|
||||
config_foreach add_defaults defaults
|
||||
|
||||
json_add_object interfaces
|
||||
config_foreach add_interface interface
|
||||
json_close_object
|
||||
|
||||
json_add_object classes
|
||||
config_foreach add_class class
|
||||
config_foreach add_class alias
|
||||
json_close_object
|
||||
|
||||
json_add_object devices
|
||||
config_foreach add_interface device
|
||||
json_close_object
|
||||
|
||||
ubus call qosify config "$(json_dump)"
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger qosify
|
||||
}
|
||||
|
||||
start_service() {
|
||||
procd_open_instance
|
||||
procd_set_param command "$PROG"
|
||||
procd_set_param respawn
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
service_started() {
|
||||
ubus -t 10 wait_for qosify
|
||||
[ $? = 0 ] && reload_service
|
||||
}
|
||||
45
package/network/config/soloscli/Makefile
Normal file
45
package/network/config/soloscli/Makefile
Normal file
@@ -0,0 +1,45 @@
|
||||
#
|
||||
# Copyright (C) 2006-2014 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=soloscli
|
||||
PKG_VERSION:=1.04
|
||||
PKG_RELEASE:=3
|
||||
|
||||
PKG_SOURCE:=solos-pci-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=@SF/openadsl
|
||||
PKG_HASH:=6379e6970a5c97fd5a223d024138ebb71b15d70e2ad1fe9da09edc5b2d760e1d
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/solos-pci-$(PKG_VERSION)
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/soloscli
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=Configuration utility for Solos ADSL2+ modems
|
||||
DEPENDS:=+kmod-solos-pci
|
||||
URL:=http://sourceforge.net/projects/openadsl
|
||||
endef
|
||||
|
||||
define Package/soloscli/description
|
||||
This package contains the soloscli utility
|
||||
for interrogating Traverse Technologies' Solos ADSL2+ modems.
|
||||
endef
|
||||
|
||||
define Package/soloscli/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/soloscli/soloscli $(1)/usr/bin/
|
||||
$(INSTALL_BIN) ./files/solos-log-stats $(1)/usr/bin/
|
||||
$(INSTALL_DIR) $(1)/etc/hotplug.d/atm
|
||||
$(INSTALL_CONF) ./files/etc/hotplug.d/atm/15-solos-init $(1)/etc/hotplug.d/atm/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,soloscli))
|
||||
@@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
|
||||
dialog() {
|
||||
local tag="$(echo "$1" | cut -d= -f1)"
|
||||
local value="$(echo "$1" | cut -d= -f2-)"
|
||||
local response
|
||||
|
||||
response="$(soloscli -s "$port" "$tag" "$value")"
|
||||
[ $? -ne 0 ] && {
|
||||
logger "soloscli($port): $tag '$value' returns $response"
|
||||
}
|
||||
}
|
||||
|
||||
if [ "$ACTION" = "add" ]; then
|
||||
include /lib/network
|
||||
scan_interfaces
|
||||
|
||||
case $DEVICENAME in
|
||||
solos-pci[0-3])
|
||||
port="${DEVICENAME#solos-pci}"
|
||||
device="solos${port}"
|
||||
|
||||
config_list_foreach wan "$device" dialog
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
13
package/network/config/soloscli/files/etc/uci-defaults/solos
Normal file
13
package/network/config/soloscli/files/etc/uci-defaults/solos
Normal file
@@ -0,0 +1,13 @@
|
||||
uci batch <<__EOF__
|
||||
|
||||
delete network.wan.solos0
|
||||
|
||||
add_list network.wan.solos0="ActivateLine=Abort"
|
||||
add_list network.wan.solos0="Retrain=EnableAll"
|
||||
add_list network.wan.solos0="DetectNoise=Enable"
|
||||
add_list network.wan.solos0="BisMCapability=Disable"
|
||||
add_list network.wan.solos0="BisACapability=Disable"
|
||||
add_list network.wan.solos0="ActivateLine=Start"
|
||||
|
||||
commit network
|
||||
__EOF__
|
||||
19
package/network/config/soloscli/files/solos-log-stats
Normal file
19
package/network/config/soloscli/files/solos-log-stats
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
|
||||
cd /sys/class/atm/ || exit 1
|
||||
|
||||
for PORT in solos-pci* ; do
|
||||
|
||||
RXRATE=`cat $PORT/parameters/RxBitRate`
|
||||
TXRATE=`cat $PORT/parameters/TxBitRate`
|
||||
RXSNR=`cat $PORT/parameters/LocalSNRMargin | sed "s/ dB//"`
|
||||
TXSNR=`cat $PORT/parameters/RemoteSNRMargin | sed "s/ dB//"`
|
||||
RXERR=`cat $PORT/parameters/RSUnCorrectedErrorsDn`
|
||||
TXERR=`cat $PORT/parameters/RSUnCorrectedErrorsUp`
|
||||
RXFEC=`cat $PORT/parameters/RSCorrectedErrorsDn`
|
||||
TXFEC=`cat $PORT/parameters/RSCorrectedErrorsUp`
|
||||
|
||||
echo "$RXRATE $RXSNR $RXERR $RXFEC / $TXRATE $TXSNR $TXERR $TXFEC" |
|
||||
logger -t $PORT
|
||||
done
|
||||
|
||||
11
package/network/config/soloscli/patches/001-no-driver.patch
Normal file
11
package/network/config/soloscli/patches/001-no-driver.patch
Normal file
@@ -0,0 +1,11 @@
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -11,7 +11,7 @@ else
|
||||
KDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
PWD := $(shell pwd)
|
||||
|
||||
-all: soloscli driver
|
||||
+all: soloscli
|
||||
|
||||
soloscli: soloscli/soloscli
|
||||
|
||||
12
package/network/config/soloscli/patches/002-cflags.patch
Normal file
12
package/network/config/soloscli/patches/002-cflags.patch
Normal file
@@ -0,0 +1,12 @@
|
||||
--- a/soloscli/Makefile
|
||||
+++ b/soloscli/Makefile
|
||||
@@ -4,9 +4,6 @@
|
||||
# Last Mod: 2009-06-16
|
||||
#
|
||||
|
||||
-CC=gcc
|
||||
-CFLAGS=-Wall
|
||||
-
|
||||
soloscli: soloscli.c soloscli.h
|
||||
|
||||
clean:
|
||||
56
package/network/config/swconfig/Makefile
Normal file
56
package/network/config/swconfig/Makefile
Normal file
@@ -0,0 +1,56 @@
|
||||
#
|
||||
# Copyright (C) 2008-2010 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=swconfig
|
||||
PKG_RELEASE:=12
|
||||
|
||||
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
|
||||
PKG_BUILD_FLAGS:=lto
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
define Package/swconfig
|
||||
SECTION:=base
|
||||
CATEGORY:=Base system
|
||||
DEPENDS:=+libuci +libnl-tiny
|
||||
TITLE:=Switch configuration utility
|
||||
endef
|
||||
|
||||
TARGET_CPPFLAGS := \
|
||||
-D_GNU_SOURCE \
|
||||
-I$(STAGING_DIR)/usr/include/libnl-tiny \
|
||||
-I$(PKG_BUILD_DIR) \
|
||||
$(TARGET_CPPFLAGS) \
|
||||
-I$(LINUX_DIR)/user_headers/include
|
||||
|
||||
define Build/Compile
|
||||
CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" \
|
||||
$(MAKE) -C $(PKG_BUILD_DIR) \
|
||||
$(TARGET_CONFIGURE_OPTS) \
|
||||
LIBS="$(TARGET_LDFLAGS) -lnl-tiny -lm -luci -lubox"
|
||||
endef
|
||||
|
||||
define Build/InstallDev
|
||||
$(INSTALL_DIR) $(1)/usr/include
|
||||
$(CP) $(PKG_BUILD_DIR)/swlib.h $(1)/usr/include/
|
||||
|
||||
$(INSTALL_DIR) $(1)/usr/lib
|
||||
$(CP) $(PKG_BUILD_DIR)/libsw.a $(1)/usr/lib/
|
||||
endef
|
||||
|
||||
define Package/swconfig/install
|
||||
$(INSTALL_DIR) $(1)/sbin $(1)/lib/network
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/swconfig $(1)/sbin/swconfig
|
||||
$(INSTALL_DATA) ./files/switch.sh $(1)/lib/network/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,swconfig))
|
||||
15
package/network/config/swconfig/files/switch.sh
Normal file
15
package/network/config/swconfig/files/switch.sh
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2009 OpenWrt.org
|
||||
|
||||
setup_switch_dev() {
|
||||
local name
|
||||
config_get name "$1" name
|
||||
name="${name:-$1}"
|
||||
[ -d "/sys/class/net/$name" ] && ip link set dev "$name" up
|
||||
swconfig dev "$name" load network
|
||||
}
|
||||
|
||||
setup_switch() {
|
||||
config_load network
|
||||
config_foreach setup_switch_dev switch
|
||||
}
|
||||
16
package/network/config/swconfig/src/Makefile
Normal file
16
package/network/config/swconfig/src/Makefile
Normal file
@@ -0,0 +1,16 @@
|
||||
ifndef CFLAGS
|
||||
CFLAGS = -O2 -g -I ../src
|
||||
endif
|
||||
LIBS=-lnl -lnl-genl
|
||||
|
||||
all: swconfig
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -fPIC -c -o $@ $^
|
||||
|
||||
libsw.a: swlib.o
|
||||
$(AR) rcu $@ swlib.o
|
||||
$(RANLIB) $@
|
||||
|
||||
swconfig: libsw.a cli.o uci.o
|
||||
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS) -L./ -lsw
|
||||
408
package/network/config/swconfig/src/cli.c
Normal file
408
package/network/config/swconfig/src/cli.c
Normal file
@@ -0,0 +1,408 @@
|
||||
/*
|
||||
* swconfig.c: Switch configuration utility
|
||||
*
|
||||
* Copyright (C) 2008 Felix Fietkau <nbd@nbd.name>
|
||||
* Copyright (C) 2010 Martin Mares <mj@ucw.cz>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundatio.
|
||||
*
|
||||
* 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 General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <uci.h>
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/genetlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/genl/genl.h>
|
||||
#include <netlink/genl/ctrl.h>
|
||||
#include <linux/switch.h>
|
||||
#include "swlib.h"
|
||||
|
||||
enum {
|
||||
CMD_NONE,
|
||||
CMD_GET,
|
||||
CMD_SET,
|
||||
CMD_LOAD,
|
||||
CMD_HELP,
|
||||
CMD_SHOW,
|
||||
CMD_PORTMAP,
|
||||
};
|
||||
|
||||
static void
|
||||
print_attrs(const struct switch_attr *attr)
|
||||
{
|
||||
int i = 0;
|
||||
while (attr) {
|
||||
const char *type;
|
||||
switch(attr->type) {
|
||||
case SWITCH_TYPE_INT:
|
||||
type = "int";
|
||||
break;
|
||||
case SWITCH_TYPE_STRING:
|
||||
type = "string";
|
||||
break;
|
||||
case SWITCH_TYPE_PORTS:
|
||||
type = "ports";
|
||||
break;
|
||||
case SWITCH_TYPE_NOVAL:
|
||||
type = "none";
|
||||
break;
|
||||
default:
|
||||
type = "unknown";
|
||||
break;
|
||||
}
|
||||
printf("\tAttribute %d (%s): %s (%s)\n", ++i, type, attr->name, attr->description);
|
||||
attr = attr->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
list_attributes(struct switch_dev *dev)
|
||||
{
|
||||
printf("%s: %s(%s), ports: %d (cpu @ %d), vlans: %d\n", dev->dev_name, dev->alias, dev->name, dev->ports, dev->cpu_port, dev->vlans);
|
||||
printf(" --switch\n");
|
||||
print_attrs(dev->ops);
|
||||
printf(" --vlan\n");
|
||||
print_attrs(dev->vlan_ops);
|
||||
printf(" --port\n");
|
||||
print_attrs(dev->port_ops);
|
||||
}
|
||||
|
||||
static const char *
|
||||
speed_str(int speed)
|
||||
{
|
||||
switch (speed) {
|
||||
case 10:
|
||||
return "10baseT";
|
||||
case 100:
|
||||
return "100baseT";
|
||||
case 1000:
|
||||
return "1000baseT";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
static void
|
||||
free_attr_val(const struct switch_attr *attr, const struct switch_val *val)
|
||||
{
|
||||
switch (attr->type) {
|
||||
case SWITCH_TYPE_STRING:
|
||||
free(val->value.s);
|
||||
break;
|
||||
case SWITCH_TYPE_PORTS:
|
||||
free(val->value.ports);
|
||||
break;
|
||||
case SWITCH_TYPE_LINK:
|
||||
free(val->value.link);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_attr_val(const struct switch_attr *attr, const struct switch_val *val)
|
||||
{
|
||||
struct switch_port_link *link;
|
||||
int i;
|
||||
|
||||
switch (attr->type) {
|
||||
case SWITCH_TYPE_INT:
|
||||
printf("%d", val->value.i);
|
||||
break;
|
||||
case SWITCH_TYPE_STRING:
|
||||
printf("%s", val->value.s);
|
||||
break;
|
||||
case SWITCH_TYPE_PORTS:
|
||||
for(i = 0; i < val->len; i++) {
|
||||
printf("%d%s ",
|
||||
val->value.ports[i].id,
|
||||
(val->value.ports[i].flags &
|
||||
SWLIB_PORT_FLAG_TAGGED) ? "t" : "");
|
||||
}
|
||||
break;
|
||||
case SWITCH_TYPE_LINK:
|
||||
link = val->value.link;
|
||||
if (link->link)
|
||||
printf("port:%d link:up speed:%s %s-duplex %s%s%s%s%s",
|
||||
val->port_vlan,
|
||||
speed_str(link->speed),
|
||||
link->duplex ? "full" : "half",
|
||||
link->tx_flow ? "txflow " : "",
|
||||
link->rx_flow ? "rxflow " : "",
|
||||
link->eee & SWLIB_LINK_FLAG_EEE_100BASET ? "eee100 " : "",
|
||||
link->eee & SWLIB_LINK_FLAG_EEE_1000BASET ? "eee1000 " : "",
|
||||
link->aneg ? "auto" : "");
|
||||
else
|
||||
printf("port:%d link:down", val->port_vlan);
|
||||
break;
|
||||
default:
|
||||
printf("?unknown-type?");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
show_attrs(struct switch_dev *dev, struct switch_attr *attr, struct switch_val *val)
|
||||
{
|
||||
while (attr) {
|
||||
if (attr->type != SWITCH_TYPE_NOVAL) {
|
||||
printf("\t%s: ", attr->name);
|
||||
if (swlib_get_attr(dev, attr, val) < 0)
|
||||
printf("???");
|
||||
else {
|
||||
print_attr_val(attr, val);
|
||||
free_attr_val(attr, val);
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
attr = attr->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
show_global(struct switch_dev *dev)
|
||||
{
|
||||
struct switch_val val;
|
||||
|
||||
printf("Global attributes:\n");
|
||||
show_attrs(dev, dev->ops, &val);
|
||||
}
|
||||
|
||||
static void
|
||||
show_port(struct switch_dev *dev, int port)
|
||||
{
|
||||
struct switch_val val;
|
||||
|
||||
printf("Port %d:\n", port);
|
||||
val.port_vlan = port;
|
||||
show_attrs(dev, dev->port_ops, &val);
|
||||
}
|
||||
|
||||
static void
|
||||
show_vlan(struct switch_dev *dev, int vlan, bool all)
|
||||
{
|
||||
struct switch_val val;
|
||||
struct switch_attr *attr;
|
||||
|
||||
val.port_vlan = vlan;
|
||||
|
||||
if (all) {
|
||||
attr = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_VLAN, "ports");
|
||||
if (swlib_get_attr(dev, attr, &val) < 0)
|
||||
return;
|
||||
|
||||
if (!val.len)
|
||||
return;
|
||||
}
|
||||
|
||||
printf("VLAN %d:\n", vlan);
|
||||
show_attrs(dev, dev->vlan_ops, &val);
|
||||
}
|
||||
|
||||
static void
|
||||
print_usage(void)
|
||||
{
|
||||
printf("swconfig list\n");
|
||||
printf("swconfig dev <dev> [port <port>|vlan <vlan>] (help|set <key> <value>|get <key>|load <config>|show)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
swconfig_load_uci(struct switch_dev *dev, const char *name)
|
||||
{
|
||||
struct uci_context *ctx;
|
||||
struct uci_package *p = NULL;
|
||||
int ret = -1;
|
||||
|
||||
ctx = uci_alloc_context();
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
uci_load(ctx, name, &p);
|
||||
if (!p) {
|
||||
uci_perror(ctx, "Failed to load config file: ");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = swlib_apply_from_uci(dev, p);
|
||||
if (ret < 0)
|
||||
fprintf(stderr, "Failed to apply configuration for switch '%s'\n", dev->dev_name);
|
||||
|
||||
out:
|
||||
uci_free_context(ctx);
|
||||
exit(ret);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int retval = 0;
|
||||
struct switch_dev *dev;
|
||||
struct switch_attr *a;
|
||||
struct switch_val val;
|
||||
int i;
|
||||
|
||||
int cmd = CMD_NONE;
|
||||
char *cdev = NULL;
|
||||
int cport = -1;
|
||||
int cvlan = -1;
|
||||
char *ckey = NULL;
|
||||
char *cvalue = NULL;
|
||||
char *csegment = NULL;
|
||||
|
||||
if((argc == 2) && !strcmp(argv[1], "list")) {
|
||||
swlib_list();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(argc < 4)
|
||||
print_usage();
|
||||
|
||||
if(strcmp(argv[1], "dev"))
|
||||
print_usage();
|
||||
|
||||
cdev = argv[2];
|
||||
|
||||
for(i = 3; i < argc; i++)
|
||||
{
|
||||
char *arg = argv[i];
|
||||
if (cmd != CMD_NONE) {
|
||||
print_usage();
|
||||
} else if (!strcmp(arg, "port") && i+1 < argc) {
|
||||
cport = atoi(argv[++i]);
|
||||
} else if (!strcmp(arg, "vlan") && i+1 < argc) {
|
||||
cvlan = atoi(argv[++i]);
|
||||
} else if (!strcmp(arg, "help")) {
|
||||
cmd = CMD_HELP;
|
||||
} else if (!strcmp(arg, "set") && i+1 < argc) {
|
||||
cmd = CMD_SET;
|
||||
ckey = argv[++i];
|
||||
if (i+1 < argc)
|
||||
cvalue = argv[++i];
|
||||
} else if (!strcmp(arg, "get") && i+1 < argc) {
|
||||
cmd = CMD_GET;
|
||||
ckey = argv[++i];
|
||||
} else if (!strcmp(arg, "load") && i+1 < argc) {
|
||||
if ((cport >= 0) || (cvlan >= 0))
|
||||
print_usage();
|
||||
cmd = CMD_LOAD;
|
||||
ckey = argv[++i];
|
||||
} else if (!strcmp(arg, "portmap")) {
|
||||
if (i + 1 < argc)
|
||||
csegment = argv[++i];
|
||||
cmd = CMD_PORTMAP;
|
||||
} else if (!strcmp(arg, "show")) {
|
||||
cmd = CMD_SHOW;
|
||||
} else {
|
||||
print_usage();
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd == CMD_NONE)
|
||||
print_usage();
|
||||
if (cport > -1 && cvlan > -1)
|
||||
print_usage();
|
||||
|
||||
dev = swlib_connect(cdev);
|
||||
if (!dev) {
|
||||
fprintf(stderr, "Failed to connect to the switch. Use the \"list\" command to see which switches are available.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
swlib_scan(dev);
|
||||
|
||||
if (cmd == CMD_GET || cmd == CMD_SET) {
|
||||
if(cport > -1)
|
||||
a = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_PORT, ckey);
|
||||
else if(cvlan > -1)
|
||||
a = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_VLAN, ckey);
|
||||
else
|
||||
a = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_GLOBAL, ckey);
|
||||
|
||||
if(!a)
|
||||
{
|
||||
fprintf(stderr, "Unknown attribute \"%s\"\n", ckey);
|
||||
retval = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
switch(cmd)
|
||||
{
|
||||
case CMD_SET:
|
||||
if ((a->type != SWITCH_TYPE_NOVAL) &&
|
||||
(cvalue == NULL))
|
||||
print_usage();
|
||||
|
||||
if(cvlan > -1)
|
||||
cport = cvlan;
|
||||
|
||||
retval = swlib_set_attr_string(dev, a, cport, cvalue);
|
||||
if (retval < 0)
|
||||
{
|
||||
nl_perror(-retval, "Failed to set attribute");
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case CMD_GET:
|
||||
if(cvlan > -1)
|
||||
val.port_vlan = cvlan;
|
||||
if(cport > -1)
|
||||
val.port_vlan = cport;
|
||||
retval = swlib_get_attr(dev, a, &val);
|
||||
if (retval < 0)
|
||||
{
|
||||
nl_perror(-retval, "Failed to get attribute");
|
||||
goto out;
|
||||
}
|
||||
print_attr_val(a, &val);
|
||||
free_attr_val(a, &val);
|
||||
putchar('\n');
|
||||
break;
|
||||
case CMD_LOAD:
|
||||
swconfig_load_uci(dev, ckey);
|
||||
break;
|
||||
case CMD_HELP:
|
||||
list_attributes(dev);
|
||||
break;
|
||||
case CMD_PORTMAP:
|
||||
swlib_print_portmap(dev, csegment);
|
||||
break;
|
||||
case CMD_SHOW:
|
||||
if (cport >= 0 || cvlan >= 0) {
|
||||
if (cport >= 0)
|
||||
show_port(dev, cport);
|
||||
else
|
||||
show_vlan(dev, cvlan, false);
|
||||
} else {
|
||||
show_global(dev);
|
||||
for (i=0; i < dev->ports; i++)
|
||||
show_port(dev, i);
|
||||
for (i=0; i < dev->vlans; i++)
|
||||
show_vlan(dev, i, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
swlib_free_all(dev);
|
||||
return retval;
|
||||
}
|
||||
924
package/network/config/swconfig/src/swlib.c
Normal file
924
package/network/config/swconfig/src/swlib.c
Normal file
@@ -0,0 +1,924 @@
|
||||
/*
|
||||
* swlib.c: Switch configuration API (user space part)
|
||||
*
|
||||
* Copyright (C) 2008 Felix Fietkau <nbd@nbd.name>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* 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 General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/switch.h>
|
||||
#include "swlib.h"
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/genl/genl.h>
|
||||
#include <netlink/genl/family.h>
|
||||
|
||||
//#define DEBUG 1
|
||||
#ifdef DEBUG
|
||||
#define DPRINTF(fmt, ...) fprintf(stderr, "%s(%d): " fmt, __func__, __LINE__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define DPRINTF(fmt, ...) do {} while (0)
|
||||
#endif
|
||||
|
||||
static struct nl_sock *handle;
|
||||
static struct nl_cache *cache;
|
||||
static struct genl_family *family;
|
||||
static struct nlattr *tb[SWITCH_ATTR_MAX + 1];
|
||||
static int refcount = 0;
|
||||
|
||||
static struct nla_policy port_policy[SWITCH_ATTR_MAX] = {
|
||||
[SWITCH_PORT_ID] = { .type = NLA_U32 },
|
||||
[SWITCH_PORT_FLAG_TAGGED] = { .type = NLA_FLAG },
|
||||
};
|
||||
|
||||
static struct nla_policy portmap_policy[SWITCH_PORTMAP_MAX] = {
|
||||
[SWITCH_PORTMAP_SEGMENT] = { .type = NLA_STRING },
|
||||
[SWITCH_PORTMAP_VIRT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static struct nla_policy link_policy[SWITCH_LINK_ATTR_MAX] = {
|
||||
[SWITCH_LINK_FLAG_LINK] = { .type = NLA_FLAG },
|
||||
[SWITCH_LINK_FLAG_DUPLEX] = { .type = NLA_FLAG },
|
||||
[SWITCH_LINK_FLAG_ANEG] = { .type = NLA_FLAG },
|
||||
[SWITCH_LINK_SPEED] = { .type = NLA_U32 },
|
||||
[SWITCH_LINK_FLAG_EEE_100BASET] = { .type = NLA_FLAG },
|
||||
[SWITCH_LINK_FLAG_EEE_1000BASET] = { .type = NLA_FLAG },
|
||||
};
|
||||
|
||||
static inline void *
|
||||
swlib_alloc(size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
ptr = malloc(size);
|
||||
if (!ptr)
|
||||
goto done;
|
||||
memset(ptr, 0, size);
|
||||
|
||||
done:
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static int
|
||||
wait_handler(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
int *finished = arg;
|
||||
|
||||
*finished = 1;
|
||||
return NL_STOP;
|
||||
}
|
||||
|
||||
/* helper function for performing netlink requests */
|
||||
static int
|
||||
swlib_call(int cmd, int (*call)(struct nl_msg *, void *),
|
||||
int (*data)(struct nl_msg *, void *), void *arg)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
struct nl_cb *cb = NULL;
|
||||
int finished;
|
||||
int flags = 0;
|
||||
int err = 0;
|
||||
|
||||
msg = nlmsg_alloc();
|
||||
if (!msg) {
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!data)
|
||||
flags |= NLM_F_DUMP;
|
||||
|
||||
genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, genl_family_get_id(family), 0, flags, cmd, 0);
|
||||
if (data) {
|
||||
err = data(msg, arg);
|
||||
if (err < 0)
|
||||
goto nla_put_failure;
|
||||
}
|
||||
|
||||
cb = nl_cb_alloc(NL_CB_CUSTOM);
|
||||
if (!cb) {
|
||||
fprintf(stderr, "nl_cb_alloc failed.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
err = nl_send_auto_complete(handle, msg);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "nl_send_auto_complete failed: %d\n", err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
finished = 0;
|
||||
|
||||
if (call)
|
||||
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, call, arg);
|
||||
|
||||
if (data)
|
||||
nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, wait_handler, &finished);
|
||||
else
|
||||
nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, wait_handler, &finished);
|
||||
|
||||
err = nl_recvmsgs(handle, cb);
|
||||
if (err < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!finished)
|
||||
err = nl_wait_for_ack(handle);
|
||||
|
||||
out:
|
||||
if (cb)
|
||||
nl_cb_put(cb);
|
||||
nla_put_failure:
|
||||
nlmsg_free(msg);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
send_attr(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
struct switch_val *val = arg;
|
||||
struct switch_attr *attr = val->attr;
|
||||
|
||||
NLA_PUT_U32(msg, SWITCH_ATTR_ID, attr->dev->id);
|
||||
NLA_PUT_U32(msg, SWITCH_ATTR_OP_ID, attr->id);
|
||||
switch(attr->atype) {
|
||||
case SWLIB_ATTR_GROUP_PORT:
|
||||
NLA_PUT_U32(msg, SWITCH_ATTR_OP_PORT, val->port_vlan);
|
||||
break;
|
||||
case SWLIB_ATTR_GROUP_VLAN:
|
||||
NLA_PUT_U32(msg, SWITCH_ATTR_OP_VLAN, val->port_vlan);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
store_port_val(struct nl_msg *msg, struct nlattr *nla, struct switch_val *val)
|
||||
{
|
||||
struct nlattr *p;
|
||||
int ports = val->attr->dev->ports;
|
||||
int err = 0;
|
||||
int remaining;
|
||||
|
||||
if (!val->value.ports)
|
||||
val->value.ports = malloc(sizeof(struct switch_port) * ports);
|
||||
|
||||
nla_for_each_nested(p, nla, remaining) {
|
||||
struct nlattr *tb[SWITCH_PORT_ATTR_MAX+1];
|
||||
struct switch_port *port;
|
||||
|
||||
if (val->len >= ports)
|
||||
break;
|
||||
|
||||
err = nla_parse_nested(tb, SWITCH_PORT_ATTR_MAX, p, port_policy);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
if (!tb[SWITCH_PORT_ID])
|
||||
continue;
|
||||
|
||||
port = &val->value.ports[val->len];
|
||||
port->id = nla_get_u32(tb[SWITCH_PORT_ID]);
|
||||
port->flags = 0;
|
||||
if (tb[SWITCH_PORT_FLAG_TAGGED])
|
||||
port->flags |= SWLIB_PORT_FLAG_TAGGED;
|
||||
|
||||
val->len++;
|
||||
}
|
||||
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
store_link_val(struct nl_msg *msg, struct nlattr *nla, struct switch_val *val)
|
||||
{
|
||||
struct nlattr *tb[SWITCH_LINK_ATTR_MAX + 1];
|
||||
struct switch_port_link *link;
|
||||
int err = 0;
|
||||
|
||||
if (!val->value.link)
|
||||
val->value.link = malloc(sizeof(struct switch_port_link));
|
||||
|
||||
err = nla_parse_nested(tb, SWITCH_LINK_ATTR_MAX, nla, link_policy);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
link = val->value.link;
|
||||
link->link = !!tb[SWITCH_LINK_FLAG_LINK];
|
||||
link->duplex = !!tb[SWITCH_LINK_FLAG_DUPLEX];
|
||||
link->aneg = !!tb[SWITCH_LINK_FLAG_ANEG];
|
||||
link->tx_flow = !!tb[SWITCH_LINK_FLAG_TX_FLOW];
|
||||
link->rx_flow = !!tb[SWITCH_LINK_FLAG_RX_FLOW];
|
||||
link->speed = nla_get_u32(tb[SWITCH_LINK_SPEED]);
|
||||
link->eee = 0;
|
||||
if (tb[SWITCH_LINK_FLAG_EEE_100BASET])
|
||||
link->eee |= SWLIB_LINK_FLAG_EEE_100BASET;
|
||||
if (tb[SWITCH_LINK_FLAG_EEE_1000BASET])
|
||||
link->eee |= SWLIB_LINK_FLAG_EEE_1000BASET;
|
||||
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
store_val(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
|
||||
struct switch_val *val = arg;
|
||||
|
||||
if (!val)
|
||||
goto error;
|
||||
|
||||
if (nla_parse(tb, SWITCH_ATTR_MAX - 1, genlmsg_attrdata(gnlh, 0),
|
||||
genlmsg_attrlen(gnlh, 0), NULL) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (tb[SWITCH_ATTR_OP_VALUE_INT])
|
||||
val->value.i = nla_get_u32(tb[SWITCH_ATTR_OP_VALUE_INT]);
|
||||
else if (tb[SWITCH_ATTR_OP_VALUE_STR])
|
||||
val->value.s = strdup(nla_get_string(tb[SWITCH_ATTR_OP_VALUE_STR]));
|
||||
else if (tb[SWITCH_ATTR_OP_VALUE_PORTS])
|
||||
val->err = store_port_val(msg, tb[SWITCH_ATTR_OP_VALUE_PORTS], val);
|
||||
else if (tb[SWITCH_ATTR_OP_VALUE_LINK])
|
||||
val->err = store_link_val(msg, tb[SWITCH_ATTR_OP_VALUE_LINK], val);
|
||||
|
||||
val->err = 0;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
int
|
||||
swlib_get_attr(struct switch_dev *dev, struct switch_attr *attr, struct switch_val *val)
|
||||
{
|
||||
int cmd;
|
||||
int err;
|
||||
|
||||
switch(attr->atype) {
|
||||
case SWLIB_ATTR_GROUP_GLOBAL:
|
||||
cmd = SWITCH_CMD_GET_GLOBAL;
|
||||
break;
|
||||
case SWLIB_ATTR_GROUP_PORT:
|
||||
cmd = SWITCH_CMD_GET_PORT;
|
||||
break;
|
||||
case SWLIB_ATTR_GROUP_VLAN:
|
||||
cmd = SWITCH_CMD_GET_VLAN;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(&val->value, 0, sizeof(val->value));
|
||||
val->len = 0;
|
||||
val->attr = attr;
|
||||
val->err = -EINVAL;
|
||||
err = swlib_call(cmd, store_val, send_attr, val);
|
||||
if (!err)
|
||||
err = val->err;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
send_attr_ports(struct nl_msg *msg, struct switch_val *val)
|
||||
{
|
||||
struct nlattr *n;
|
||||
int i;
|
||||
|
||||
/* TODO implement multipart? */
|
||||
if (val->len == 0)
|
||||
goto done;
|
||||
n = nla_nest_start(msg, SWITCH_ATTR_OP_VALUE_PORTS);
|
||||
if (!n)
|
||||
goto nla_put_failure;
|
||||
for (i = 0; i < val->len; i++) {
|
||||
struct switch_port *port = &val->value.ports[i];
|
||||
struct nlattr *np;
|
||||
|
||||
np = nla_nest_start(msg, SWITCH_ATTR_PORT);
|
||||
if (!np)
|
||||
goto nla_put_failure;
|
||||
|
||||
NLA_PUT_U32(msg, SWITCH_PORT_ID, port->id);
|
||||
if (port->flags & SWLIB_PORT_FLAG_TAGGED)
|
||||
NLA_PUT_FLAG(msg, SWITCH_PORT_FLAG_TAGGED);
|
||||
|
||||
nla_nest_end(msg, np);
|
||||
}
|
||||
nla_nest_end(msg, n);
|
||||
done:
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
send_attr_link(struct nl_msg *msg, struct switch_val *val)
|
||||
{
|
||||
struct switch_port_link *link = val->value.link;
|
||||
struct nlattr *n;
|
||||
|
||||
n = nla_nest_start(msg, SWITCH_ATTR_OP_VALUE_LINK);
|
||||
if (!n)
|
||||
goto nla_put_failure;
|
||||
|
||||
if (link->duplex)
|
||||
NLA_PUT_FLAG(msg, SWITCH_LINK_FLAG_DUPLEX);
|
||||
if (link->aneg)
|
||||
NLA_PUT_FLAG(msg, SWITCH_LINK_FLAG_ANEG);
|
||||
NLA_PUT_U32(msg, SWITCH_LINK_SPEED, link->speed);
|
||||
|
||||
nla_nest_end(msg, n);
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
send_attr_val(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
struct switch_val *val = arg;
|
||||
struct switch_attr *attr = val->attr;
|
||||
|
||||
if (send_attr(msg, arg))
|
||||
goto nla_put_failure;
|
||||
|
||||
switch(attr->type) {
|
||||
case SWITCH_TYPE_NOVAL:
|
||||
break;
|
||||
case SWITCH_TYPE_INT:
|
||||
NLA_PUT_U32(msg, SWITCH_ATTR_OP_VALUE_INT, val->value.i);
|
||||
break;
|
||||
case SWITCH_TYPE_STRING:
|
||||
if (!val->value.s)
|
||||
goto nla_put_failure;
|
||||
NLA_PUT_STRING(msg, SWITCH_ATTR_OP_VALUE_STR, val->value.s);
|
||||
break;
|
||||
case SWITCH_TYPE_PORTS:
|
||||
if (send_attr_ports(msg, val) < 0)
|
||||
goto nla_put_failure;
|
||||
break;
|
||||
case SWITCH_TYPE_LINK:
|
||||
if (send_attr_link(msg, val))
|
||||
goto nla_put_failure;
|
||||
break;
|
||||
default:
|
||||
goto nla_put_failure;
|
||||
}
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
swlib_set_attr(struct switch_dev *dev, struct switch_attr *attr, struct switch_val *val)
|
||||
{
|
||||
int cmd;
|
||||
|
||||
switch(attr->atype) {
|
||||
case SWLIB_ATTR_GROUP_GLOBAL:
|
||||
cmd = SWITCH_CMD_SET_GLOBAL;
|
||||
break;
|
||||
case SWLIB_ATTR_GROUP_PORT:
|
||||
cmd = SWITCH_CMD_SET_PORT;
|
||||
break;
|
||||
case SWLIB_ATTR_GROUP_VLAN:
|
||||
cmd = SWITCH_CMD_SET_VLAN;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
val->attr = attr;
|
||||
return swlib_call(cmd, NULL, send_attr_val, val);
|
||||
}
|
||||
|
||||
enum {
|
||||
CMD_NONE,
|
||||
CMD_DUPLEX,
|
||||
CMD_ANEG,
|
||||
CMD_SPEED,
|
||||
};
|
||||
|
||||
int swlib_set_attr_string(struct switch_dev *dev, struct switch_attr *a, int port_vlan, const char *str)
|
||||
{
|
||||
struct switch_port *ports;
|
||||
struct switch_port_link *link;
|
||||
struct switch_val val;
|
||||
char *ptr;
|
||||
int cmd = CMD_NONE;
|
||||
|
||||
memset(&val, 0, sizeof(val));
|
||||
val.port_vlan = port_vlan;
|
||||
switch(a->type) {
|
||||
case SWITCH_TYPE_INT:
|
||||
val.value.i = atoi(str);
|
||||
break;
|
||||
case SWITCH_TYPE_STRING:
|
||||
val.value.s = (char *)str;
|
||||
break;
|
||||
case SWITCH_TYPE_PORTS:
|
||||
ports = alloca(sizeof(struct switch_port) * dev->ports);
|
||||
memset(ports, 0, sizeof(struct switch_port) * dev->ports);
|
||||
val.len = 0;
|
||||
ptr = (char *)str;
|
||||
while(ptr && *ptr)
|
||||
{
|
||||
while(*ptr && isspace(*ptr))
|
||||
ptr++;
|
||||
|
||||
if (!*ptr)
|
||||
break;
|
||||
|
||||
if (!isdigit(*ptr))
|
||||
return -1;
|
||||
|
||||
if (val.len >= dev->ports)
|
||||
return -1;
|
||||
|
||||
ports[val.len].flags = 0;
|
||||
ports[val.len].id = strtoul(ptr, &ptr, 10);
|
||||
while(*ptr && !isspace(*ptr)) {
|
||||
if (*ptr == 't')
|
||||
ports[val.len].flags |= SWLIB_PORT_FLAG_TAGGED;
|
||||
else
|
||||
return -1;
|
||||
|
||||
ptr++;
|
||||
}
|
||||
if (*ptr)
|
||||
ptr++;
|
||||
val.len++;
|
||||
}
|
||||
val.value.ports = ports;
|
||||
break;
|
||||
case SWITCH_TYPE_LINK:
|
||||
link = malloc(sizeof(struct switch_port_link));
|
||||
memset(link, 0, sizeof(struct switch_port_link));
|
||||
ptr = (char *)str;
|
||||
for (ptr = strtok(ptr," "); ptr; ptr = strtok(NULL, " ")) {
|
||||
switch (cmd) {
|
||||
case CMD_NONE:
|
||||
if (!strcmp(ptr, "duplex"))
|
||||
cmd = CMD_DUPLEX;
|
||||
else if (!strcmp(ptr, "autoneg"))
|
||||
cmd = CMD_ANEG;
|
||||
else if (!strcmp(ptr, "speed"))
|
||||
cmd = CMD_SPEED;
|
||||
else
|
||||
fprintf(stderr, "Unsupported option %s\n", ptr);
|
||||
break;
|
||||
case CMD_DUPLEX:
|
||||
if (!strcmp(ptr, "half"))
|
||||
link->duplex = 0;
|
||||
else if (!strcmp(ptr, "full"))
|
||||
link->duplex = 1;
|
||||
else
|
||||
fprintf(stderr, "Unsupported value %s\n", ptr);
|
||||
cmd = CMD_NONE;
|
||||
break;
|
||||
case CMD_ANEG:
|
||||
if (!strcmp(ptr, "on"))
|
||||
link->aneg = 1;
|
||||
else if (!strcmp(ptr, "off"))
|
||||
link->aneg = 0;
|
||||
else
|
||||
fprintf(stderr, "Unsupported value %s\n", ptr);
|
||||
cmd = CMD_NONE;
|
||||
break;
|
||||
case CMD_SPEED:
|
||||
link->speed = atoi(ptr);
|
||||
cmd = CMD_NONE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
val.value.link = link;
|
||||
break;
|
||||
case SWITCH_TYPE_NOVAL:
|
||||
if (str && !strcmp(str, "0"))
|
||||
return 0;
|
||||
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return swlib_set_attr(dev, a, &val);
|
||||
}
|
||||
|
||||
|
||||
struct attrlist_arg {
|
||||
int id;
|
||||
int atype;
|
||||
struct switch_dev *dev;
|
||||
struct switch_attr *prev;
|
||||
struct switch_attr **head;
|
||||
};
|
||||
|
||||
static int
|
||||
add_id(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
struct attrlist_arg *l = arg;
|
||||
|
||||
NLA_PUT_U32(msg, SWITCH_ATTR_ID, l->id);
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
add_attr(struct nl_msg *msg, void *ptr)
|
||||
{
|
||||
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
|
||||
struct attrlist_arg *arg = ptr;
|
||||
struct switch_attr *new;
|
||||
|
||||
if (nla_parse(tb, SWITCH_ATTR_MAX - 1, genlmsg_attrdata(gnlh, 0),
|
||||
genlmsg_attrlen(gnlh, 0), NULL) < 0)
|
||||
goto done;
|
||||
|
||||
new = swlib_alloc(sizeof(struct switch_attr));
|
||||
if (!new)
|
||||
goto done;
|
||||
|
||||
new->dev = arg->dev;
|
||||
new->atype = arg->atype;
|
||||
if (arg->prev) {
|
||||
arg->prev->next = new;
|
||||
} else {
|
||||
arg->prev = *arg->head;
|
||||
}
|
||||
*arg->head = new;
|
||||
arg->head = &new->next;
|
||||
|
||||
if (tb[SWITCH_ATTR_OP_ID])
|
||||
new->id = nla_get_u32(tb[SWITCH_ATTR_OP_ID]);
|
||||
if (tb[SWITCH_ATTR_OP_TYPE])
|
||||
new->type = nla_get_u32(tb[SWITCH_ATTR_OP_TYPE]);
|
||||
if (tb[SWITCH_ATTR_OP_NAME])
|
||||
new->name = strdup(nla_get_string(tb[SWITCH_ATTR_OP_NAME]));
|
||||
if (tb[SWITCH_ATTR_OP_DESCRIPTION])
|
||||
new->description = strdup(nla_get_string(tb[SWITCH_ATTR_OP_DESCRIPTION]));
|
||||
|
||||
done:
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
int
|
||||
swlib_scan(struct switch_dev *dev)
|
||||
{
|
||||
struct attrlist_arg arg;
|
||||
|
||||
if (dev->ops || dev->port_ops || dev->vlan_ops)
|
||||
return 0;
|
||||
|
||||
arg.atype = SWLIB_ATTR_GROUP_GLOBAL;
|
||||
arg.dev = dev;
|
||||
arg.id = dev->id;
|
||||
arg.prev = NULL;
|
||||
arg.head = &dev->ops;
|
||||
swlib_call(SWITCH_CMD_LIST_GLOBAL, add_attr, add_id, &arg);
|
||||
|
||||
arg.atype = SWLIB_ATTR_GROUP_PORT;
|
||||
arg.prev = NULL;
|
||||
arg.head = &dev->port_ops;
|
||||
swlib_call(SWITCH_CMD_LIST_PORT, add_attr, add_id, &arg);
|
||||
|
||||
arg.atype = SWLIB_ATTR_GROUP_VLAN;
|
||||
arg.prev = NULL;
|
||||
arg.head = &dev->vlan_ops;
|
||||
swlib_call(SWITCH_CMD_LIST_VLAN, add_attr, add_id, &arg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct switch_attr *swlib_lookup_attr(struct switch_dev *dev,
|
||||
enum swlib_attr_group atype, const char *name)
|
||||
{
|
||||
struct switch_attr *head;
|
||||
|
||||
if (!name || !dev)
|
||||
return NULL;
|
||||
|
||||
switch(atype) {
|
||||
case SWLIB_ATTR_GROUP_GLOBAL:
|
||||
head = dev->ops;
|
||||
break;
|
||||
case SWLIB_ATTR_GROUP_PORT:
|
||||
head = dev->port_ops;
|
||||
break;
|
||||
case SWLIB_ATTR_GROUP_VLAN:
|
||||
head = dev->vlan_ops;
|
||||
break;
|
||||
}
|
||||
while(head) {
|
||||
if (!strcmp(name, head->name))
|
||||
return head;
|
||||
head = head->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
swlib_priv_free(void)
|
||||
{
|
||||
if (family)
|
||||
nl_object_put((struct nl_object*)family);
|
||||
if (cache)
|
||||
nl_cache_free(cache);
|
||||
if (handle)
|
||||
nl_socket_free(handle);
|
||||
family = NULL;
|
||||
handle = NULL;
|
||||
cache = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
swlib_priv_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
handle = nl_socket_alloc();
|
||||
if (!handle) {
|
||||
DPRINTF("Failed to create handle\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (genl_connect(handle)) {
|
||||
DPRINTF("Failed to connect to generic netlink\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = genl_ctrl_alloc_cache(handle, &cache);
|
||||
if (ret < 0) {
|
||||
DPRINTF("Failed to allocate netlink cache\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
family = genl_ctrl_search_by_name(cache, "switch");
|
||||
if (!family) {
|
||||
DPRINTF("Switch API not present\n");
|
||||
goto err;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err:
|
||||
swlib_priv_free();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
struct swlib_scan_arg {
|
||||
const char *name;
|
||||
struct switch_dev *head;
|
||||
struct switch_dev *ptr;
|
||||
};
|
||||
|
||||
static int
|
||||
add_port_map(struct switch_dev *dev, struct nlattr *nla)
|
||||
{
|
||||
struct nlattr *p;
|
||||
int err = 0, idx = 0;
|
||||
int remaining;
|
||||
|
||||
dev->maps = malloc(sizeof(struct switch_portmap) * dev->ports);
|
||||
if (!dev->maps)
|
||||
return -1;
|
||||
memset(dev->maps, 0, sizeof(struct switch_portmap) * dev->ports);
|
||||
|
||||
nla_for_each_nested(p, nla, remaining) {
|
||||
struct nlattr *tb[SWITCH_PORTMAP_MAX+1];
|
||||
|
||||
if (idx >= dev->ports)
|
||||
continue;
|
||||
|
||||
err = nla_parse_nested(tb, SWITCH_PORTMAP_MAX, p, portmap_policy);
|
||||
if (err < 0)
|
||||
continue;
|
||||
|
||||
|
||||
if (tb[SWITCH_PORTMAP_SEGMENT] && tb[SWITCH_PORTMAP_VIRT]) {
|
||||
dev->maps[idx].segment = strdup(nla_get_string(tb[SWITCH_PORTMAP_SEGMENT]));
|
||||
dev->maps[idx].virt = nla_get_u32(tb[SWITCH_PORTMAP_VIRT]);
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
add_switch(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
struct swlib_scan_arg *sa = arg;
|
||||
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
|
||||
struct switch_dev *dev;
|
||||
const char *name;
|
||||
const char *alias;
|
||||
|
||||
if (nla_parse(tb, SWITCH_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL) < 0)
|
||||
goto done;
|
||||
|
||||
if (!tb[SWITCH_ATTR_DEV_NAME])
|
||||
goto done;
|
||||
|
||||
name = nla_get_string(tb[SWITCH_ATTR_DEV_NAME]);
|
||||
alias = nla_get_string(tb[SWITCH_ATTR_ALIAS]);
|
||||
|
||||
if (sa->name && (strcmp(name, sa->name) != 0) && (strcmp(alias, sa->name) != 0))
|
||||
goto done;
|
||||
|
||||
dev = swlib_alloc(sizeof(struct switch_dev));
|
||||
if (!dev)
|
||||
goto done;
|
||||
|
||||
strncpy(dev->dev_name, name, IFNAMSIZ - 1);
|
||||
dev->alias = strdup(alias);
|
||||
if (tb[SWITCH_ATTR_ID])
|
||||
dev->id = nla_get_u32(tb[SWITCH_ATTR_ID]);
|
||||
if (tb[SWITCH_ATTR_NAME])
|
||||
dev->name = strdup(nla_get_string(tb[SWITCH_ATTR_NAME]));
|
||||
if (tb[SWITCH_ATTR_PORTS])
|
||||
dev->ports = nla_get_u32(tb[SWITCH_ATTR_PORTS]);
|
||||
if (tb[SWITCH_ATTR_VLANS])
|
||||
dev->vlans = nla_get_u32(tb[SWITCH_ATTR_VLANS]);
|
||||
if (tb[SWITCH_ATTR_CPU_PORT])
|
||||
dev->cpu_port = nla_get_u32(tb[SWITCH_ATTR_CPU_PORT]);
|
||||
if (tb[SWITCH_ATTR_PORTMAP])
|
||||
add_port_map(dev, tb[SWITCH_ATTR_PORTMAP]);
|
||||
|
||||
if (!sa->head) {
|
||||
sa->head = dev;
|
||||
sa->ptr = dev;
|
||||
} else {
|
||||
sa->ptr->next = dev;
|
||||
sa->ptr = dev;
|
||||
}
|
||||
|
||||
refcount++;
|
||||
done:
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
static int
|
||||
list_switch(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
|
||||
|
||||
if (nla_parse(tb, SWITCH_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL) < 0)
|
||||
goto done;
|
||||
|
||||
if (!tb[SWITCH_ATTR_DEV_NAME] || !tb[SWITCH_ATTR_NAME])
|
||||
goto done;
|
||||
|
||||
printf("Found: %s - %s\n", nla_get_string(tb[SWITCH_ATTR_DEV_NAME]),
|
||||
nla_get_string(tb[SWITCH_ATTR_ALIAS]));
|
||||
|
||||
done:
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
void
|
||||
swlib_list(void)
|
||||
{
|
||||
if (swlib_priv_init() < 0)
|
||||
return;
|
||||
swlib_call(SWITCH_CMD_GET_SWITCH, list_switch, NULL, NULL);
|
||||
swlib_priv_free();
|
||||
}
|
||||
|
||||
void
|
||||
swlib_print_portmap(struct switch_dev *dev, char *segment)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (segment) {
|
||||
if (!strcmp(segment, "cpu")) {
|
||||
printf("%d ", dev->cpu_port);
|
||||
} else if (!strcmp(segment, "disabled")) {
|
||||
for (i = 0; i < dev->ports; i++)
|
||||
if (!dev->maps[i].segment)
|
||||
printf("%d ", i);
|
||||
} else for (i = 0; i < dev->ports; i++) {
|
||||
if (dev->maps[i].segment && !strcmp(dev->maps[i].segment, segment))
|
||||
printf("%d ", i);
|
||||
}
|
||||
} else {
|
||||
printf("%s - %s\n", dev->dev_name, dev->name);
|
||||
for (i = 0; i < dev->ports; i++)
|
||||
if (i == dev->cpu_port)
|
||||
printf("port%d:\tcpu\n", i);
|
||||
else if (dev->maps[i].segment)
|
||||
printf("port%d:\t%s.%d\n", i, dev->maps[i].segment, dev->maps[i].virt);
|
||||
else
|
||||
printf("port%d:\tdisabled\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
struct switch_dev *
|
||||
swlib_connect(const char *name)
|
||||
{
|
||||
struct swlib_scan_arg arg;
|
||||
|
||||
if (!refcount) {
|
||||
if (swlib_priv_init() < 0)
|
||||
return NULL;
|
||||
};
|
||||
|
||||
arg.head = NULL;
|
||||
arg.ptr = NULL;
|
||||
arg.name = name;
|
||||
swlib_call(SWITCH_CMD_GET_SWITCH, add_switch, NULL, &arg);
|
||||
|
||||
if (!refcount)
|
||||
swlib_priv_free();
|
||||
|
||||
return arg.head;
|
||||
}
|
||||
|
||||
static void
|
||||
swlib_free_attributes(struct switch_attr **head)
|
||||
{
|
||||
struct switch_attr *a = *head;
|
||||
struct switch_attr *next;
|
||||
|
||||
while (a) {
|
||||
next = a->next;
|
||||
free(a->name);
|
||||
free(a->description);
|
||||
free(a);
|
||||
a = next;
|
||||
}
|
||||
*head = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
swlib_free_port_map(struct switch_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!dev || !dev->maps)
|
||||
return;
|
||||
|
||||
for (i = 0; i < dev->ports; i++)
|
||||
free(dev->maps[i].segment);
|
||||
free(dev->maps);
|
||||
}
|
||||
|
||||
void
|
||||
swlib_free(struct switch_dev *dev)
|
||||
{
|
||||
swlib_free_attributes(&dev->ops);
|
||||
swlib_free_attributes(&dev->port_ops);
|
||||
swlib_free_attributes(&dev->vlan_ops);
|
||||
swlib_free_port_map(dev);
|
||||
free(dev->name);
|
||||
free(dev->alias);
|
||||
free(dev);
|
||||
|
||||
if (--refcount == 0)
|
||||
swlib_priv_free();
|
||||
}
|
||||
|
||||
void
|
||||
swlib_free_all(struct switch_dev *dev)
|
||||
{
|
||||
struct switch_dev *p;
|
||||
|
||||
while (dev) {
|
||||
p = dev->next;
|
||||
swlib_free(dev);
|
||||
dev = p;
|
||||
}
|
||||
}
|
||||
269
package/network/config/swconfig/src/swlib.h
Normal file
269
package/network/config/swconfig/src/swlib.h
Normal file
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* swlib.h: Switch configuration API (user space part)
|
||||
*
|
||||
* Copyright (C) 2008-2009 Felix Fietkau <nbd@nbd.name>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* 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 General Public License for more details.
|
||||
*
|
||||
|
||||
Usage of the library functions:
|
||||
|
||||
The main datastructure for a switch is the struct switch_device
|
||||
To get started, you first need to use switch_connect() to probe
|
||||
for switches and allocate an instance of this struct.
|
||||
|
||||
There are two possible usage modes:
|
||||
dev = switch_connect("eth0");
|
||||
- this call will look for a switch registered for the linux device
|
||||
"eth0" and only allocate a switch_device for this particular switch.
|
||||
|
||||
dev = switch_connect(NULL)
|
||||
- this will return one switch_device struct for each available
|
||||
switch. The switch_device structs are chained with by ->next pointer
|
||||
|
||||
Then to query a switch for all available attributes, use:
|
||||
swlib_scan(dev);
|
||||
|
||||
All allocated datastructures for the switch_device struct can be freed with
|
||||
swlib_free(dev);
|
||||
or
|
||||
swlib_free_all(dev);
|
||||
|
||||
The latter traverses a whole chain of switch_device structs and frees them all
|
||||
|
||||
Switch attributes (struct switch_attr) are divided into three groups:
|
||||
dev->ops:
|
||||
- global settings
|
||||
dev->port_ops:
|
||||
- per-port settings
|
||||
dev->vlan_ops:
|
||||
- per-vlan settings
|
||||
|
||||
switch_lookup_attr() is a small helper function to locate attributes
|
||||
by name.
|
||||
|
||||
switch_set_attr() and switch_get_attr() can alter or request the values
|
||||
of attributes.
|
||||
|
||||
Usage of the switch_attr struct:
|
||||
|
||||
->atype: attribute group, one of:
|
||||
- SWLIB_ATTR_GROUP_GLOBAL
|
||||
- SWLIB_ATTR_GROUP_VLAN
|
||||
- SWLIB_ATTR_GROUP_PORT
|
||||
|
||||
->id: identifier for the attribute
|
||||
|
||||
->type: data type, one of:
|
||||
- SWITCH_TYPE_INT
|
||||
- SWITCH_TYPE_STRING
|
||||
- SWITCH_TYPE_PORT
|
||||
|
||||
->name: short name of the attribute
|
||||
->description: longer description
|
||||
->next: pointer to the next attribute of the current group
|
||||
|
||||
|
||||
Usage of the switch_val struct:
|
||||
|
||||
When setting attributes, following members of the struct switch_val need
|
||||
to be set up:
|
||||
|
||||
->len (for attr->type == SWITCH_TYPE_PORT)
|
||||
->port_vlan:
|
||||
- port number (for attr->atype == SWLIB_ATTR_GROUP_PORT), or:
|
||||
- vlan number (for attr->atype == SWLIB_ATTR_GROUP_VLAN)
|
||||
->value.i (for attr->type == SWITCH_TYPE_INT)
|
||||
->value.s (for attr->type == SWITCH_TYPE_STRING)
|
||||
- owned by the caller, not stored in the library internally
|
||||
->value.ports (for attr->type == SWITCH_TYPE_PORT)
|
||||
- must point to an array of at lest val->len * sizeof(struct switch_port)
|
||||
|
||||
When getting string attributes, val->value.s must be freed by the caller
|
||||
When getting port list attributes, an internal static buffer is used,
|
||||
which changes from call to call.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __SWLIB_H
|
||||
#define __SWLIB_H
|
||||
|
||||
enum swlib_attr_group {
|
||||
SWLIB_ATTR_GROUP_GLOBAL,
|
||||
SWLIB_ATTR_GROUP_VLAN,
|
||||
SWLIB_ATTR_GROUP_PORT,
|
||||
};
|
||||
|
||||
enum swlib_port_flags {
|
||||
SWLIB_PORT_FLAG_TAGGED = (1 << 0),
|
||||
};
|
||||
|
||||
enum swlib_link_flags {
|
||||
SWLIB_LINK_FLAG_EEE_100BASET = (1 << 0),
|
||||
SWLIB_LINK_FLAG_EEE_1000BASET = (1 << 1),
|
||||
};
|
||||
|
||||
struct switch_dev;
|
||||
struct switch_attr;
|
||||
struct switch_port;
|
||||
struct switch_port_map;
|
||||
struct switch_port_link;
|
||||
struct switch_val;
|
||||
struct uci_package;
|
||||
|
||||
struct switch_dev {
|
||||
int id;
|
||||
char dev_name[IFNAMSIZ];
|
||||
char *name;
|
||||
char *alias;
|
||||
int ports;
|
||||
int vlans;
|
||||
int cpu_port;
|
||||
struct switch_attr *ops;
|
||||
struct switch_attr *port_ops;
|
||||
struct switch_attr *vlan_ops;
|
||||
struct switch_portmap *maps;
|
||||
struct switch_dev *next;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
struct switch_val {
|
||||
struct switch_attr *attr;
|
||||
int len;
|
||||
int err;
|
||||
int port_vlan;
|
||||
union {
|
||||
char *s;
|
||||
int i;
|
||||
struct switch_port *ports;
|
||||
struct switch_port_link *link;
|
||||
} value;
|
||||
};
|
||||
|
||||
struct switch_attr {
|
||||
struct switch_dev *dev;
|
||||
int atype;
|
||||
int id;
|
||||
int type;
|
||||
char *name;
|
||||
char *description;
|
||||
struct switch_attr *next;
|
||||
};
|
||||
|
||||
struct switch_port {
|
||||
unsigned int id;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
struct switch_portmap {
|
||||
unsigned int virt;
|
||||
char *segment;
|
||||
};
|
||||
|
||||
struct switch_port_link {
|
||||
int link:1;
|
||||
int duplex:1;
|
||||
int aneg:1;
|
||||
int tx_flow:1;
|
||||
int rx_flow:1;
|
||||
int speed;
|
||||
/* in ethtool adv_t format */
|
||||
uint32_t eee;
|
||||
};
|
||||
|
||||
/**
|
||||
* swlib_list: list all switches
|
||||
*/
|
||||
void swlib_list(void);
|
||||
|
||||
/**
|
||||
* swlib_print_portmap: get portmap
|
||||
* @dev: switch device struct
|
||||
*/
|
||||
void swlib_print_portmap(struct switch_dev *dev, char *segment);
|
||||
|
||||
/**
|
||||
* swlib_connect: connect to the switch through netlink
|
||||
* @name: name of the ethernet interface,
|
||||
*
|
||||
* if name is NULL, it connect and builds a chain of all switches
|
||||
*/
|
||||
struct switch_dev *swlib_connect(const char *name);
|
||||
|
||||
/**
|
||||
* swlib_free: free all dynamically allocated data for the switch connection
|
||||
* @dev: switch device struct
|
||||
*
|
||||
* all members of a switch device chain (generated by swlib_connect(NULL))
|
||||
* must be freed individually
|
||||
*/
|
||||
void swlib_free(struct switch_dev *dev);
|
||||
|
||||
/**
|
||||
* swlib_free_all: run swlib_free on all devices in the chain
|
||||
* @dev: switch device struct
|
||||
*/
|
||||
void swlib_free_all(struct switch_dev *dev);
|
||||
|
||||
/**
|
||||
* swlib_scan: probe the switch driver for available commands/attributes
|
||||
* @dev: switch device struct
|
||||
*/
|
||||
int swlib_scan(struct switch_dev *dev);
|
||||
|
||||
/**
|
||||
* swlib_lookup_attr: look up a switch attribute
|
||||
* @dev: switch device struct
|
||||
* @type: global, port or vlan
|
||||
* @name: name of the attribute
|
||||
*/
|
||||
struct switch_attr *swlib_lookup_attr(struct switch_dev *dev,
|
||||
enum swlib_attr_group atype, const char *name);
|
||||
|
||||
/**
|
||||
* swlib_set_attr: set the value for an attribute
|
||||
* @dev: switch device struct
|
||||
* @attr: switch attribute struct
|
||||
* @val: attribute value pointer
|
||||
* returns 0 on success
|
||||
*/
|
||||
int swlib_set_attr(struct switch_dev *dev, struct switch_attr *attr,
|
||||
struct switch_val *val);
|
||||
|
||||
/**
|
||||
* swlib_set_attr_string: set the value for an attribute with type conversion
|
||||
* @dev: switch device struct
|
||||
* @attr: switch attribute struct
|
||||
* @port_vlan: port or vlan (if applicable)
|
||||
* @str: string value
|
||||
* returns 0 on success
|
||||
*/
|
||||
int swlib_set_attr_string(struct switch_dev *dev, struct switch_attr *attr,
|
||||
int port_vlan, const char *str);
|
||||
|
||||
/**
|
||||
* swlib_get_attr: get the value for an attribute
|
||||
* @dev: switch device struct
|
||||
* @attr: switch attribute struct
|
||||
* @val: attribute value pointer
|
||||
* returns 0 on success
|
||||
* for string attributes, the result string must be freed by the caller
|
||||
*/
|
||||
int swlib_get_attr(struct switch_dev *dev, struct switch_attr *attr,
|
||||
struct switch_val *val);
|
||||
|
||||
/**
|
||||
* swlib_apply_from_uci: set up the switch from a uci configuration
|
||||
* @dev: switch device struct
|
||||
* @p: uci package which contains the desired global config
|
||||
*/
|
||||
int swlib_apply_from_uci(struct switch_dev *dev, struct uci_package *p);
|
||||
|
||||
#endif
|
||||
253
package/network/config/swconfig/src/uci.c
Normal file
253
package/network/config/swconfig/src/uci.c
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* uci.c: UCI binding for the switch configuration utility
|
||||
*
|
||||
* Copyright (C) 2009 Felix Fietkau <nbd@nbd.name>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundatio.
|
||||
*
|
||||
* 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 General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <uci.h>
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/genetlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/genl/genl.h>
|
||||
#include <netlink/genl/ctrl.h>
|
||||
#include <linux/switch.h>
|
||||
#include "swlib.h"
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
|
||||
#endif
|
||||
|
||||
struct swlib_setting {
|
||||
struct switch_attr *attr;
|
||||
const char *name;
|
||||
int port_vlan;
|
||||
const char *val;
|
||||
struct swlib_setting *next;
|
||||
};
|
||||
|
||||
struct swlib_setting early_settings[] = {
|
||||
{ .name = "reset", .val = "1" },
|
||||
{ .name = "enable_vlan", .val = "1" },
|
||||
};
|
||||
|
||||
static struct swlib_setting *settings;
|
||||
static struct swlib_setting **head;
|
||||
|
||||
static bool swlib_match_name(struct switch_dev *dev, const char *name)
|
||||
{
|
||||
return (strcmp(name, dev->dev_name) == 0 ||
|
||||
strcmp(name, dev->alias) == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
swlib_map_settings(struct switch_dev *dev, int type, int port_vlan, struct uci_section *s)
|
||||
{
|
||||
struct swlib_setting *setting;
|
||||
struct switch_attr *attr;
|
||||
struct uci_element *e;
|
||||
struct uci_option *o;
|
||||
|
||||
uci_foreach_element(&s->options, e) {
|
||||
o = uci_to_option(e);
|
||||
|
||||
if (o->type != UCI_TYPE_STRING)
|
||||
continue;
|
||||
|
||||
if (!strcmp(e->name, "device"))
|
||||
continue;
|
||||
|
||||
/* map early settings */
|
||||
if (type == SWLIB_ATTR_GROUP_GLOBAL) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(early_settings); i++) {
|
||||
if (strcmp(e->name, early_settings[i].name) != 0)
|
||||
continue;
|
||||
|
||||
early_settings[i].val = o->v.string;
|
||||
goto skip;
|
||||
}
|
||||
}
|
||||
|
||||
attr = swlib_lookup_attr(dev, type, e->name);
|
||||
if (!attr)
|
||||
continue;
|
||||
|
||||
setting = malloc(sizeof(struct swlib_setting));
|
||||
memset(setting, 0, sizeof(struct swlib_setting));
|
||||
setting->attr = attr;
|
||||
setting->port_vlan = port_vlan;
|
||||
setting->val = o->v.string;
|
||||
*head = setting;
|
||||
head = &setting->next;
|
||||
skip:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
int swlib_apply_from_uci(struct switch_dev *dev, struct uci_package *p)
|
||||
{
|
||||
struct switch_attr *attr;
|
||||
struct uci_element *e;
|
||||
struct uci_section *s;
|
||||
struct uci_option *o;
|
||||
struct uci_ptr ptr;
|
||||
struct switch_val val;
|
||||
int i;
|
||||
|
||||
settings = NULL;
|
||||
head = &settings;
|
||||
|
||||
uci_foreach_element(&p->sections, e) {
|
||||
struct uci_element *n;
|
||||
|
||||
s = uci_to_section(e);
|
||||
|
||||
if (strcmp(s->type, "switch") != 0)
|
||||
continue;
|
||||
|
||||
uci_foreach_element(&s->options, n) {
|
||||
struct uci_option *o = uci_to_option(n);
|
||||
|
||||
if (strcmp(n->name, "name") != 0)
|
||||
continue;
|
||||
|
||||
if (o->type != UCI_TYPE_STRING)
|
||||
continue;
|
||||
|
||||
if (swlib_match_name(dev, o->v.string))
|
||||
goto found;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!swlib_match_name(dev, e->name))
|
||||
continue;
|
||||
|
||||
goto found;
|
||||
}
|
||||
|
||||
/* not found */
|
||||
return -1;
|
||||
|
||||
found:
|
||||
/* look up available early options, which need to be taken care
|
||||
* of in the correct order */
|
||||
for (i = 0; i < ARRAY_SIZE(early_settings); i++) {
|
||||
early_settings[i].attr = swlib_lookup_attr(dev,
|
||||
SWLIB_ATTR_GROUP_GLOBAL, early_settings[i].name);
|
||||
}
|
||||
swlib_map_settings(dev, SWLIB_ATTR_GROUP_GLOBAL, 0, s);
|
||||
|
||||
/* look for port or vlan sections */
|
||||
uci_foreach_element(&p->sections, e) {
|
||||
struct uci_element *os;
|
||||
s = uci_to_section(e);
|
||||
|
||||
if (!strcmp(s->type, "switch_vlan")) {
|
||||
char *devn = NULL, *vlan = NULL, *vlan_err = NULL;
|
||||
int vlan_n;
|
||||
|
||||
uci_foreach_element(&s->options, os) {
|
||||
o = uci_to_option(os);
|
||||
if (o->type != UCI_TYPE_STRING)
|
||||
continue;
|
||||
|
||||
if (!strcmp(os->name, "device")) {
|
||||
devn = o->v.string;
|
||||
if (!swlib_match_name(dev, devn))
|
||||
devn = NULL;
|
||||
} else if (!strcmp(os->name, "vlan")) {
|
||||
vlan = o->v.string;
|
||||
}
|
||||
}
|
||||
if (!devn || !vlan || !vlan[0])
|
||||
continue;
|
||||
|
||||
vlan_n = strtoul(vlan, &vlan_err, 0);
|
||||
if (vlan_err && vlan_err[0])
|
||||
continue;
|
||||
|
||||
swlib_map_settings(dev, SWLIB_ATTR_GROUP_VLAN, vlan_n, s);
|
||||
}
|
||||
}
|
||||
uci_foreach_element(&p->sections, e) {
|
||||
struct uci_element *os;
|
||||
char *devn = NULL, *port = NULL, *port_err = NULL;
|
||||
int port_n;
|
||||
|
||||
s = uci_to_section(e);
|
||||
|
||||
if (strcmp(s->type, "switch_port"))
|
||||
continue;
|
||||
|
||||
uci_foreach_element(&s->options, os) {
|
||||
o = uci_to_option(os);
|
||||
if (o->type != UCI_TYPE_STRING)
|
||||
continue;
|
||||
|
||||
if (!strcmp(os->name, "device")) {
|
||||
devn = o->v.string;
|
||||
if (!swlib_match_name(dev, devn))
|
||||
devn = NULL;
|
||||
} else if (!strcmp(os->name, "port")) {
|
||||
port = o->v.string;
|
||||
}
|
||||
}
|
||||
if (!devn || !port || !port[0])
|
||||
continue;
|
||||
|
||||
port_n = strtoul(port, &port_err, 0);
|
||||
if (port_err && port_err[0])
|
||||
continue;
|
||||
|
||||
swlib_map_settings(dev, SWLIB_ATTR_GROUP_PORT, port_n, s);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(early_settings); i++) {
|
||||
struct swlib_setting *st = &early_settings[i];
|
||||
if (!st->attr || !st->val)
|
||||
continue;
|
||||
swlib_set_attr_string(dev, st->attr, st->port_vlan, st->val);
|
||||
|
||||
}
|
||||
|
||||
while (settings) {
|
||||
struct swlib_setting *st = settings;
|
||||
|
||||
swlib_set_attr_string(dev, st->attr, st->port_vlan, st->val);
|
||||
st = st->next;
|
||||
free(settings);
|
||||
settings = st;
|
||||
}
|
||||
|
||||
/* Apply the config */
|
||||
attr = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_GLOBAL, "apply");
|
||||
if (!attr)
|
||||
return 0;
|
||||
|
||||
memset(&val, 0, sizeof(val));
|
||||
swlib_set_attr(dev, attr, &val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
44
package/network/config/vti/Makefile
Normal file
44
package/network/config/vti/Makefile
Normal file
@@ -0,0 +1,44 @@
|
||||
#
|
||||
# Copyright (C) 2014 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=vti
|
||||
PKG_RELEASE:=5
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/vti/Default
|
||||
endef
|
||||
|
||||
define Package/vti
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
MAINTAINER:=Andre Valentin <avalentin@marcant.net>
|
||||
TITLE:=Virtual IPsec Tunnel Interface config support
|
||||
DEPENDS:=+kmod-ip-vti +IPV6:kmod-ip6-vti
|
||||
PROVIDES:=vtiv4 vtiv6
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/vti/description
|
||||
Virtual IPsec Tunnel Interface config support (IPv4 and IPv6) in /etc/config/network.
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Package/vti/install
|
||||
$(INSTALL_DIR) $(1)/lib/netifd/proto
|
||||
$(INSTALL_BIN) ./files/vti.sh $(1)/lib/netifd/proto/vti.sh
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,vti))
|
||||
154
package/network/config/vti/files/vti.sh
Executable file
154
package/network/config/vti/files/vti.sh
Executable file
@@ -0,0 +1,154 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ -n "$INCLUDE_ONLY" ] || {
|
||||
. /lib/functions.sh
|
||||
. /lib/functions/network.sh
|
||||
. ../netifd-proto.sh
|
||||
init_proto "$@"
|
||||
}
|
||||
|
||||
vti_generic_setup() {
|
||||
local cfg="$1"
|
||||
local mode="$2"
|
||||
local local="$3"
|
||||
local remote="$4"
|
||||
local link="$5"
|
||||
local mtu zone ikey
|
||||
json_get_vars mtu zone ikey okey
|
||||
|
||||
proto_init_update "$link" 1
|
||||
|
||||
proto_add_tunnel
|
||||
json_add_string mode "$mode"
|
||||
json_add_int mtu "${mtu:-1280}"
|
||||
json_add_string local "$local"
|
||||
json_add_string remote "$remote"
|
||||
[ -n "$tunlink" ] && json_add_string link "$tunlink"
|
||||
|
||||
json_add_object 'data'
|
||||
[ -n "$ikey" ] && json_add_int ikey "$ikey"
|
||||
[ -n "$okey" ] && json_add_int okey "$okey"
|
||||
json_close_object
|
||||
|
||||
proto_close_tunnel
|
||||
|
||||
proto_add_data
|
||||
[ -n "$zone" ] && json_add_string zone "$zone"
|
||||
proto_close_data
|
||||
|
||||
proto_send_update "$cfg"
|
||||
}
|
||||
|
||||
vti_setup() {
|
||||
local cfg="$1"
|
||||
local mode="$2"
|
||||
|
||||
local ipaddr peeraddr
|
||||
json_get_vars df ipaddr peeraddr tunlink
|
||||
|
||||
[ -z "$peeraddr" ] && {
|
||||
proto_notify_error "$cfg" "MISSING_ADDRESS"
|
||||
proto_block_restart "$cfg"
|
||||
exit
|
||||
}
|
||||
|
||||
( proto_add_host_dependency "$cfg" "$peeraddr" "$tunlink" )
|
||||
|
||||
[ -z "$ipaddr" ] && {
|
||||
local wanif="$tunlink"
|
||||
if [ -z $wanif ] && ! network_find_wan wanif; then
|
||||
proto_notify_error "$cfg" "NO_WAN_LINK"
|
||||
exit
|
||||
fi
|
||||
|
||||
if ! network_get_ipaddr ipaddr "$wanif"; then
|
||||
proto_notify_error "$cfg" "NO_WAN_LINK"
|
||||
exit
|
||||
fi
|
||||
}
|
||||
|
||||
vti_generic_setup $cfg $mode $ipaddr $peeraddr "vti-$cfg"
|
||||
}
|
||||
|
||||
proto_vti_setup() {
|
||||
local cfg="$1"
|
||||
|
||||
vti_setup $cfg "vtiip"
|
||||
}
|
||||
|
||||
vti6_setup() {
|
||||
local cfg="$1"
|
||||
local mode="$2"
|
||||
|
||||
local ip6addr peer6addr weakif
|
||||
json_get_vars ip6addr peer6addr tunlink weakif
|
||||
|
||||
[ -z "$peer6addr" ] && {
|
||||
proto_notify_error "$cfg" "MISSING_ADDRESS"
|
||||
proto_block_restart "$cfg"
|
||||
exit
|
||||
}
|
||||
|
||||
( proto_add_host_dependency "$cfg" "$peer6addr" "$tunlink" )
|
||||
|
||||
[ -z "$ip6addr" ] && {
|
||||
local wanif="$tunlink"
|
||||
if [ -z $wanif ] && ! network_find_wan6 wanif; then
|
||||
proto_notify_error "$cfg" "NO_WAN_LINK"
|
||||
exit
|
||||
fi
|
||||
|
||||
if ! network_get_ipaddr6 ip6addr "$wanif"; then
|
||||
[ -z "$weakif" ] && weakif="lan"
|
||||
if ! network_get_ipaddr6 ip6addr "$weakif"; then
|
||||
proto_notify_error "$cfg" "NO_WAN_LINK"
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
vti_generic_setup $cfg $mode $ip6addr $peer6addr "vti6-$cfg"
|
||||
}
|
||||
|
||||
proto_vti6_setup() {
|
||||
local cfg="$1"
|
||||
|
||||
vti6_setup $cfg "vtiip6"
|
||||
}
|
||||
|
||||
proto_vti_teardown() {
|
||||
local cfg="$1"
|
||||
}
|
||||
|
||||
proto_vti6_teardown() {
|
||||
local cfg="$1"
|
||||
}
|
||||
|
||||
vti_generic_init_config() {
|
||||
no_device=1
|
||||
available=1
|
||||
|
||||
proto_config_add_int "mtu"
|
||||
proto_config_add_string "tunlink"
|
||||
proto_config_add_string "zone"
|
||||
proto_config_add_int "ikey"
|
||||
proto_config_add_int "okey"
|
||||
}
|
||||
|
||||
proto_vti_init_config() {
|
||||
vti_generic_init_config
|
||||
proto_config_add_string "ipaddr"
|
||||
proto_config_add_string "peeraddr"
|
||||
}
|
||||
|
||||
proto_vti6_init_config() {
|
||||
vti_generic_init_config
|
||||
proto_config_add_string "ip6addr"
|
||||
proto_config_add_string "peer6addr"
|
||||
proto_config_add_string "weakif"
|
||||
}
|
||||
|
||||
[ -n "$INCLUDE_ONLY" ] || {
|
||||
[ -d /sys/module/ip_vti ] && add_protocol vti
|
||||
[ -d /sys/module/ip6_vti ] && add_protocol vti6
|
||||
}
|
||||
33
package/network/config/vxlan/Makefile
Normal file
33
package/network/config/vxlan/Makefile
Normal file
@@ -0,0 +1,33 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=vxlan
|
||||
PKG_RELEASE:=7
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/vxlan
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
MAINTAINER:=Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
TITLE:=Virtual eXtensible LAN config support
|
||||
DEPENDS:=+kmod-vxlan
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/vxlan/description
|
||||
Virtual eXtensible LAN config support in /etc/config/network.
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Package/vxlan/install
|
||||
$(INSTALL_DIR) $(1)/lib/netifd/proto
|
||||
$(INSTALL_BIN) ./files/vxlan.sh $(1)/lib/netifd/proto/vxlan.sh
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,vxlan))
|
||||
195
package/network/config/vxlan/files/vxlan.sh
Executable file
195
package/network/config/vxlan/files/vxlan.sh
Executable file
@@ -0,0 +1,195 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ -n "$INCLUDE_ONLY" ] || {
|
||||
. /lib/functions.sh
|
||||
. /lib/functions/network.sh
|
||||
. ../netifd-proto.sh
|
||||
init_proto "$@"
|
||||
}
|
||||
|
||||
proto_vxlan_setup_peer() {
|
||||
type bridge &> /dev/null || {
|
||||
proto_notify_error "$cfg" "MISSING_BRIDGE_COMMAND"
|
||||
exit
|
||||
}
|
||||
|
||||
local peer_config="$1"
|
||||
|
||||
local vxlan
|
||||
local lladdr
|
||||
local dst
|
||||
local src_vni
|
||||
local vni
|
||||
local port
|
||||
local via
|
||||
|
||||
config_get vxlan "${peer_config}" "vxlan"
|
||||
config_get lladdr "${peer_config}" "lladdr"
|
||||
config_get dst "${peer_config}" "dst"
|
||||
config_get src_vni "${peer_config}" "src_vni"
|
||||
config_get vni "${peer_config}" "vni"
|
||||
config_get port "${peer_config}" "port"
|
||||
config_get via "${peer_config}" "via"
|
||||
|
||||
[ "$cfg" = "$vxlan" ] || {
|
||||
# This peer section belongs to another device
|
||||
return
|
||||
}
|
||||
|
||||
[ -n "${dst}" ] || {
|
||||
proto_notify_error "$cfg" "MISSING_PEER_ADDRESS"
|
||||
exit
|
||||
}
|
||||
|
||||
bridge fdb append \
|
||||
${lladdr:-00:00:00:00:00:00} \
|
||||
dev ${cfg} \
|
||||
dst ${dst} \
|
||||
${src_vni:+src_vni $src_vni} \
|
||||
${vni:+vni $vni} \
|
||||
${port:+port $port} \
|
||||
${via:+via $via}
|
||||
}
|
||||
|
||||
vxlan_generic_setup() {
|
||||
local cfg="$1"
|
||||
local mode="$2"
|
||||
local local="$3"
|
||||
local remote="$4"
|
||||
|
||||
local link="$cfg"
|
||||
|
||||
local port vid ttl tos mtu macaddr zone rxcsum txcsum srcportmin srcportmax ageing maxaddress learning rsc proxy l2miss l3miss gbp
|
||||
json_get_vars port vid ttl tos mtu macaddr zone rxcsum txcsum srcportmin srcportmax ageing maxaddress learning rsc proxy l2miss l3miss gbp
|
||||
|
||||
proto_init_update "$link" 1
|
||||
|
||||
proto_add_tunnel
|
||||
json_add_string mode "$mode"
|
||||
|
||||
[ -n "$tunlink" ] && json_add_string link "$tunlink"
|
||||
[ -n "$local" ] && json_add_string local "$local"
|
||||
[ -n "$remote" ] && json_add_string remote "$remote"
|
||||
|
||||
[ -n "$ttl" ] && json_add_int ttl "$ttl"
|
||||
[ -n "$tos" ] && json_add_string tos "$tos"
|
||||
[ -n "$mtu" ] && json_add_int mtu "$mtu"
|
||||
|
||||
json_add_object 'data'
|
||||
[ -n "$port" ] && json_add_int port "$port"
|
||||
[ -n "$vid" ] && json_add_int id "$vid"
|
||||
[ -n "$srcportmin" ] && json_add_int srcportmin "$srcportmin"
|
||||
[ -n "$srcportmax" ] && json_add_int srcportmax "$srcportmax"
|
||||
[ -n "$ageing" ] && json_add_int ageing "$ageing"
|
||||
[ -n "$maxaddress" ] && json_add_int maxaddress "$maxaddress"
|
||||
[ -n "$macaddr" ] && json_add_string macaddr "$macaddr"
|
||||
[ -n "$rxcsum" ] && json_add_boolean rxcsum "$rxcsum"
|
||||
[ -n "$txcsum" ] && json_add_boolean txcsum "$txcsum"
|
||||
[ -n "$learning" ] && json_add_boolean learning "$learning"
|
||||
[ -n "$rsc" ] && json_add_boolean rsc "$rsc"
|
||||
[ -n "$proxy" ] && json_add_boolean proxy "$proxy"
|
||||
[ -n "$l2miss" ] && json_add_boolean l2miss "$l2miss"
|
||||
[ -n "$l3miss" ] && json_add_boolean l3miss "$l3miss"
|
||||
[ -n "$gbp" ] && json_add_boolean gbp "$gbp"
|
||||
|
||||
json_close_object
|
||||
|
||||
proto_close_tunnel
|
||||
|
||||
proto_add_data
|
||||
[ -n "$zone" ] && json_add_string zone "$zone"
|
||||
proto_close_data
|
||||
|
||||
proto_send_update "$cfg"
|
||||
|
||||
config_load network
|
||||
config_foreach proto_vxlan_setup_peer "vxlan_peer"
|
||||
}
|
||||
|
||||
proto_vxlan_setup() {
|
||||
local cfg="$1"
|
||||
|
||||
local ipaddr peeraddr
|
||||
json_get_vars ipaddr peeraddr tunlink
|
||||
|
||||
( proto_add_host_dependency "$cfg" '' "$tunlink" )
|
||||
|
||||
case "$ipaddr" in
|
||||
"auto"|"")
|
||||
ipaddr="0.0.0.0"
|
||||
;;
|
||||
esac
|
||||
|
||||
vxlan_generic_setup "$cfg" 'vxlan' "$ipaddr" "$peeraddr"
|
||||
}
|
||||
|
||||
proto_vxlan6_setup() {
|
||||
local cfg="$1"
|
||||
|
||||
local ip6addr peer6addr
|
||||
json_get_vars ip6addr peer6addr tunlink
|
||||
|
||||
( proto_add_host_dependency "$cfg" '' "$tunlink" )
|
||||
|
||||
case "$ip6addr" in
|
||||
"auto"|"")
|
||||
# ensure tunnel via ipv6
|
||||
ip6addr="::"
|
||||
;;
|
||||
esac
|
||||
|
||||
vxlan_generic_setup "$cfg" 'vxlan6' "$ip6addr" "$peer6addr"
|
||||
}
|
||||
|
||||
proto_vxlan_teardown() {
|
||||
local cfg="$1"
|
||||
}
|
||||
|
||||
proto_vxlan6_teardown() {
|
||||
local cfg="$1"
|
||||
}
|
||||
|
||||
vxlan_generic_init_config() {
|
||||
no_device=1
|
||||
available=1
|
||||
|
||||
proto_config_add_string "tunlink"
|
||||
proto_config_add_string "zone"
|
||||
|
||||
proto_config_add_int "vid"
|
||||
proto_config_add_int "port"
|
||||
proto_config_add_int "ttl"
|
||||
proto_config_add_int "tos"
|
||||
proto_config_add_int "mtu"
|
||||
proto_config_add_int "srcportmin"
|
||||
proto_config_add_int "srcportmax"
|
||||
proto_config_add_int "ageing"
|
||||
proto_config_add_int "maxaddress"
|
||||
proto_config_add_boolean "rxcsum"
|
||||
proto_config_add_boolean "txcsum"
|
||||
proto_config_add_boolean "learning"
|
||||
proto_config_add_boolean "rsc"
|
||||
proto_config_add_boolean "proxy"
|
||||
proto_config_add_boolean "l2miss"
|
||||
proto_config_add_boolean "l3miss"
|
||||
proto_config_add_boolean "gbp"
|
||||
proto_config_add_string "macaddr"
|
||||
|
||||
}
|
||||
|
||||
proto_vxlan_init_config() {
|
||||
vxlan_generic_init_config
|
||||
proto_config_add_string "ipaddr"
|
||||
proto_config_add_string "peeraddr"
|
||||
}
|
||||
|
||||
proto_vxlan6_init_config() {
|
||||
vxlan_generic_init_config
|
||||
proto_config_add_string "ip6addr"
|
||||
proto_config_add_string "peer6addr"
|
||||
}
|
||||
|
||||
[ -n "$INCLUDE_ONLY" ] || {
|
||||
add_protocol vxlan
|
||||
add_protocol vxlan6
|
||||
}
|
||||
45
package/network/config/wifi-scripts/Makefile
Normal file
45
package/network/config/wifi-scripts/Makefile
Normal file
@@ -0,0 +1,45 @@
|
||||
#
|
||||
# Copyright (C) 2024 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=wifi-scripts
|
||||
PKG_VERSION:=1.0
|
||||
PKG_RELEASE:=1
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
|
||||
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/wifi-scripts
|
||||
SECTION:=utils
|
||||
CATEGORY:=Base system
|
||||
DEPENDS:=+netifd +ucode +ucode-mod-nl80211 +ucode-mod-rtnl +ucode-mod-ubus +ucode-mod-uci
|
||||
TITLE:=Wi-Fi configuration scripts
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/wifi-scripts/description
|
||||
A set of scripts that handle setup and configuration of Wi-Fi devices.
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/wifi-scripts/install
|
||||
$(INSTALL_DIR) $(1)
|
||||
$(CP) ./files/* $(1)/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,wifi-scripts))
|
||||
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ "${ACTION}" = "add" ] && {
|
||||
/sbin/wifi config
|
||||
}
|
||||
1598
package/network/config/wifi-scripts/files/lib/netifd/hostapd.sh
Normal file
1598
package/network/config/wifi-scripts/files/lib/netifd/hostapd.sh
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,439 @@
|
||||
NETIFD_MAIN_DIR="${NETIFD_MAIN_DIR:-/lib/netifd}"
|
||||
|
||||
. /usr/share/libubox/jshn.sh
|
||||
. $NETIFD_MAIN_DIR/utils.sh
|
||||
|
||||
CMD_UP=0
|
||||
CMD_SET_DATA=1
|
||||
CMD_PROCESS_ADD=2
|
||||
CMD_PROCESS_KILL_ALL=3
|
||||
CMD_SET_RETRY=4
|
||||
|
||||
add_driver() {
|
||||
return
|
||||
}
|
||||
|
||||
wireless_setup_vif_failed() {
|
||||
local error="$1"
|
||||
echo "Interface $_w_iface setup failed: $error"
|
||||
}
|
||||
|
||||
wireless_setup_failed() {
|
||||
local error="$1"
|
||||
|
||||
echo "Device setup failed: $error"
|
||||
wireless_set_retry 0
|
||||
}
|
||||
|
||||
prepare_key_wep() {
|
||||
local key="$1"
|
||||
local hex=1
|
||||
|
||||
echo -n "$key" | grep -qE "[^a-fA-F0-9]" && hex=0
|
||||
[ "${#key}" -eq 10 -a $hex -eq 1 ] || \
|
||||
[ "${#key}" -eq 26 -a $hex -eq 1 ] || {
|
||||
[ "${key:0:2}" = "s:" ] && key="${key#s:}"
|
||||
key="$(echo -n "$key" | hexdump -ve '1/1 "%02x" ""')"
|
||||
}
|
||||
echo "$key"
|
||||
}
|
||||
|
||||
_wdev_prepare_channel() {
|
||||
json_get_vars channel band hwmode
|
||||
|
||||
auto_channel=0
|
||||
enable_ht=0
|
||||
htmode=
|
||||
hwmode="${hwmode##11}"
|
||||
|
||||
case "$channel" in
|
||||
""|0|auto)
|
||||
channel=0
|
||||
auto_channel=1
|
||||
;;
|
||||
[0-9]*) ;;
|
||||
*)
|
||||
wireless_setup_failed "INVALID_CHANNEL"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$hwmode" in
|
||||
a|b|g|ad) ;;
|
||||
*)
|
||||
if [ "$channel" -gt 14 ]; then
|
||||
hwmode=a
|
||||
else
|
||||
hwmode=g
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$band" in
|
||||
2g) hwmode=g;;
|
||||
5g|6g) hwmode=a;;
|
||||
60g) hwmode=ad;;
|
||||
*)
|
||||
case "$hwmode" in
|
||||
*a) band=5g;;
|
||||
*ad) band=60g;;
|
||||
*b|*g) band=2g;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
_wdev_handler() {
|
||||
json_load "$data"
|
||||
|
||||
json_select config
|
||||
_wdev_prepare_channel
|
||||
json_select ..
|
||||
|
||||
eval "drv_$1_$2 \"$interface\""
|
||||
}
|
||||
|
||||
_wdev_msg_call() {
|
||||
local old_cb
|
||||
|
||||
json_set_namespace wdev old_cb
|
||||
"$@"
|
||||
json_set_namespace $old_cb
|
||||
}
|
||||
|
||||
_wdev_wrapper() {
|
||||
while [ -n "$1" ]; do
|
||||
eval "$1() { _wdev_msg_call _$1 \"\$@\"; }"
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
_wdev_notify_init() {
|
||||
local command="$1"; shift;
|
||||
|
||||
json_init
|
||||
json_add_int "command" "$command"
|
||||
json_add_string "device" "$__netifd_device"
|
||||
while [ -n "$1" ]; do
|
||||
local name="$1"; shift
|
||||
local value="$1"; shift
|
||||
json_add_string "$name" "$value"
|
||||
done
|
||||
json_add_object "data"
|
||||
}
|
||||
|
||||
_wdev_notify() {
|
||||
local options="$1"
|
||||
|
||||
json_close_object
|
||||
ubus $options call network.wireless notify "$(json_dump)"
|
||||
}
|
||||
|
||||
_wdev_add_variables() {
|
||||
while [ -n "$1" ]; do
|
||||
local var="${1%%=*}"
|
||||
local val="$1"
|
||||
shift
|
||||
[[ "$var" = "$val" ]] && continue
|
||||
val="${val#*=}"
|
||||
json_add_string "$var" "$val"
|
||||
done
|
||||
}
|
||||
|
||||
_wireless_add_vif() {
|
||||
local name="$1"; shift
|
||||
local ifname="$1"; shift
|
||||
|
||||
_wdev_notify_init $CMD_SET_DATA "interface" "$name"
|
||||
json_add_string "ifname" "$ifname"
|
||||
_wdev_add_variables "$@"
|
||||
_wdev_notify
|
||||
}
|
||||
|
||||
_wireless_add_vlan() {
|
||||
local name="$1"; shift
|
||||
local ifname="$1"; shift
|
||||
|
||||
_wdev_notify_init $CMD_SET_DATA interface "$__cur_interface" "vlan" "$name"
|
||||
json_add_string "ifname" "$ifname"
|
||||
_wdev_add_variables "$@"
|
||||
_wdev_notify
|
||||
}
|
||||
|
||||
_wireless_set_up() {
|
||||
_wdev_notify_init $CMD_UP
|
||||
_wdev_notify
|
||||
}
|
||||
|
||||
_wireless_set_data() {
|
||||
_wdev_notify_init $CMD_SET_DATA
|
||||
_wdev_add_variables "$@"
|
||||
_wdev_notify
|
||||
}
|
||||
|
||||
_wireless_add_process() {
|
||||
_wdev_notify_init $CMD_PROCESS_ADD
|
||||
local exe="$2"
|
||||
[ -L "$exe" ] && exe="$(readlink -f "$exe")"
|
||||
json_add_int pid "$1"
|
||||
json_add_string exe "$exe"
|
||||
[ -n "$3" ] && json_add_boolean required 1
|
||||
[ -n "$4" ] && json_add_boolean keep 1
|
||||
exe2="$(readlink -f /proc/$1/exe)"
|
||||
[ "$exe" != "$exe2" ] && echo "WARNING (wireless_add_process): executable path $exe does not match process $1 path ($exe2)"
|
||||
_wdev_notify
|
||||
}
|
||||
|
||||
_wireless_process_kill_all() {
|
||||
_wdev_notify_init $CMD_PROCESS_KILL_ALL
|
||||
[ -n "$1" ] && json_add_int signal "$1"
|
||||
_wdev_notify
|
||||
}
|
||||
|
||||
_wireless_set_retry() {
|
||||
_wdev_notify_init $CMD_SET_RETRY
|
||||
json_add_int retry "$1"
|
||||
_wdev_notify
|
||||
}
|
||||
|
||||
_wdev_wrapper \
|
||||
wireless_add_vif \
|
||||
wireless_add_vlan \
|
||||
wireless_set_up \
|
||||
wireless_set_data \
|
||||
wireless_add_process \
|
||||
wireless_process_kill_all \
|
||||
wireless_set_retry \
|
||||
|
||||
wireless_vif_parse_encryption() {
|
||||
json_get_vars encryption
|
||||
set_default encryption none
|
||||
|
||||
auth_mode_open=1
|
||||
auth_mode_shared=0
|
||||
auth_type=none
|
||||
|
||||
if [ "$hwmode" = "ad" ]; then
|
||||
wpa_cipher="GCMP"
|
||||
else
|
||||
wpa_cipher="CCMP"
|
||||
fi
|
||||
|
||||
case "$encryption" in
|
||||
*tkip+aes|*tkip+ccmp|*aes+tkip|*ccmp+tkip) wpa_cipher="CCMP TKIP";;
|
||||
*ccmp256) wpa_cipher="CCMP-256";;
|
||||
*aes|*ccmp) wpa_cipher="CCMP";;
|
||||
*tkip) wpa_cipher="TKIP";;
|
||||
*gcmp256) wpa_cipher="GCMP-256";;
|
||||
*gcmp) wpa_cipher="GCMP";;
|
||||
wpa3-192*) wpa_cipher="GCMP-256";;
|
||||
esac
|
||||
|
||||
# 802.11n requires CCMP for WPA
|
||||
[ "$enable_ht:$wpa_cipher" = "1:TKIP" ] && wpa_cipher="CCMP TKIP"
|
||||
|
||||
# Examples:
|
||||
# psk-mixed/tkip => WPA1+2 PSK, TKIP
|
||||
# wpa-psk2/tkip+aes => WPA2 PSK, CCMP+TKIP
|
||||
# wpa2/tkip+aes => WPA2 RADIUS, CCMP+TKIP
|
||||
|
||||
case "$encryption" in
|
||||
wpa2*|wpa3*|*psk2*|psk3*|sae*|owe*)
|
||||
wpa=2
|
||||
;;
|
||||
wpa*mixed*|*psk*mixed*)
|
||||
wpa=3
|
||||
;;
|
||||
wpa*|*psk*)
|
||||
wpa=1
|
||||
;;
|
||||
*)
|
||||
wpa=0
|
||||
wpa_cipher=
|
||||
;;
|
||||
esac
|
||||
wpa_pairwise="$wpa_cipher"
|
||||
|
||||
case "$encryption" in
|
||||
owe*)
|
||||
auth_type=owe
|
||||
;;
|
||||
wpa3-192*)
|
||||
auth_type=eap192
|
||||
;;
|
||||
wpa3-mixed*)
|
||||
auth_type=eap-eap2
|
||||
;;
|
||||
wpa3*)
|
||||
auth_type=eap2
|
||||
;;
|
||||
psk3-mixed*|sae-mixed*)
|
||||
auth_type=psk-sae
|
||||
;;
|
||||
psk3*|sae*)
|
||||
auth_type=sae
|
||||
;;
|
||||
*psk*)
|
||||
auth_type=psk
|
||||
;;
|
||||
*wpa*|*8021x*)
|
||||
auth_type=eap
|
||||
;;
|
||||
*wep*)
|
||||
auth_type=wep
|
||||
case "$encryption" in
|
||||
*shared*)
|
||||
auth_mode_open=0
|
||||
auth_mode_shared=1
|
||||
;;
|
||||
*mixed*)
|
||||
auth_mode_shared=1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$encryption" in
|
||||
*osen*)
|
||||
auth_osen=1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
_wireless_set_brsnoop_isolation() {
|
||||
local multicast_to_unicast="$1"
|
||||
local isolate
|
||||
|
||||
json_get_vars isolate proxy_arp
|
||||
|
||||
[ ${isolate:-0} -gt 0 -o -z "$network_bridge" ] && return
|
||||
[ ${multicast_to_unicast:-1} -gt 0 -o ${proxy_arp:-0} -gt 0 ] && json_add_boolean isolate 1
|
||||
}
|
||||
|
||||
for_each_interface() {
|
||||
local _w_types="$1"; shift
|
||||
local _w_ifaces _w_iface
|
||||
local _w_type
|
||||
local _w_found
|
||||
|
||||
local multicast_to_unicast
|
||||
|
||||
json_get_keys _w_ifaces interfaces
|
||||
json_select interfaces
|
||||
for _w_iface in $_w_ifaces; do
|
||||
json_select "$_w_iface"
|
||||
if [ -n "$_w_types" ]; then
|
||||
json_get_var network_bridge bridge
|
||||
json_get_var network_ifname bridge-ifname
|
||||
json_get_var multicast_to_unicast multicast_to_unicast
|
||||
json_select config
|
||||
_wireless_set_brsnoop_isolation "$multicast_to_unicast"
|
||||
json_get_var _w_type mode
|
||||
json_select ..
|
||||
_w_types=" $_w_types "
|
||||
[[ "${_w_types%$_w_type*}" = "$_w_types" ]] && {
|
||||
json_select ..
|
||||
continue
|
||||
}
|
||||
fi
|
||||
__cur_interface="$_w_iface"
|
||||
"$@" "$_w_iface"
|
||||
json_select ..
|
||||
done
|
||||
json_select ..
|
||||
}
|
||||
|
||||
for_each_vlan() {
|
||||
local _w_vlans _w_vlan
|
||||
|
||||
json_get_keys _w_vlans vlans
|
||||
json_select vlans
|
||||
for _w_vlan in $_w_vlans; do
|
||||
json_select "$_w_vlan"
|
||||
json_select config
|
||||
"$@" "$_w_vlan"
|
||||
json_select ..
|
||||
json_select ..
|
||||
done
|
||||
json_select ..
|
||||
}
|
||||
|
||||
for_each_station() {
|
||||
local _w_stas _w_sta
|
||||
|
||||
json_get_keys _w_stas stas
|
||||
json_select stas
|
||||
for _w_sta in $_w_stas; do
|
||||
json_select "$_w_sta"
|
||||
json_select config
|
||||
"$@" "$_w_sta"
|
||||
json_select ..
|
||||
json_select ..
|
||||
done
|
||||
json_select ..
|
||||
}
|
||||
|
||||
_wdev_common_device_config() {
|
||||
config_add_string channel hwmode band htmode noscan
|
||||
}
|
||||
|
||||
_wdev_common_iface_config() {
|
||||
config_add_string mode ssid encryption 'key:wpakey'
|
||||
config_add_boolean bridge_isolate
|
||||
}
|
||||
|
||||
_wdev_common_vlan_config() {
|
||||
config_add_string name vid iface
|
||||
config_add_boolean bridge_isolate
|
||||
}
|
||||
|
||||
_wdev_common_station_config() {
|
||||
config_add_string mac key vid iface
|
||||
}
|
||||
|
||||
init_wireless_driver() {
|
||||
name="$1"; shift
|
||||
cmd="$1"; shift
|
||||
|
||||
case "$cmd" in
|
||||
dump)
|
||||
add_driver() {
|
||||
eval "drv_$1_cleanup"
|
||||
|
||||
json_init
|
||||
json_add_string name "$1"
|
||||
|
||||
json_add_array device
|
||||
_wdev_common_device_config
|
||||
eval "drv_$1_init_device_config"
|
||||
json_close_array
|
||||
|
||||
json_add_array iface
|
||||
_wdev_common_iface_config
|
||||
eval "drv_$1_init_iface_config"
|
||||
json_close_array
|
||||
|
||||
json_add_array vlan
|
||||
_wdev_common_vlan_config
|
||||
eval "drv_$1_init_vlan_config"
|
||||
json_close_array
|
||||
|
||||
json_add_array station
|
||||
_wdev_common_station_config
|
||||
eval "drv_$1_init_station_config"
|
||||
json_close_array
|
||||
|
||||
json_dump
|
||||
}
|
||||
;;
|
||||
setup|teardown)
|
||||
interface="$1"; shift
|
||||
data="$1"; shift
|
||||
export __netifd_device="$interface"
|
||||
|
||||
add_driver() {
|
||||
[[ "$name" == "$1" ]] || return 0
|
||||
_wdev_handler "$1" "$cmd"
|
||||
}
|
||||
;;
|
||||
esac
|
||||
}
|
||||
1198
package/network/config/wifi-scripts/files/lib/netifd/wireless/mac80211.sh
Executable file
1198
package/network/config/wifi-scripts/files/lib/netifd/wireless/mac80211.sh
Executable file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env ucode
|
||||
import { readfile } from "fs";
|
||||
import * as uci from 'uci';
|
||||
|
||||
const bands_order = [ "6G", "5G", "2G" ];
|
||||
const htmode_order = [ "HE", "VHT", "HT" ];
|
||||
|
||||
let board = json(readfile("/etc/board.json"));
|
||||
if (!board.wlan)
|
||||
exit(0);
|
||||
|
||||
let idx = 0;
|
||||
let commit;
|
||||
|
||||
let config = uci.cursor().get_all("wireless") ?? {};
|
||||
|
||||
function radio_exists(path, macaddr, phy) {
|
||||
for (let name, s in config) {
|
||||
if (s[".type"] != "wifi-device")
|
||||
continue;
|
||||
if (s.macaddr & lc(s.macaddr) == lc(macaddr))
|
||||
return true;
|
||||
if (s.phy == phy)
|
||||
return true;
|
||||
if (!s.path || !path)
|
||||
continue;
|
||||
if (substr(s.path, -length(path)) == path)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (let phy_name, phy in board.wlan) {
|
||||
let info = phy.info;
|
||||
if (!info || !length(info.bands))
|
||||
continue;
|
||||
|
||||
while (config[`radio${idx}`])
|
||||
idx++;
|
||||
let name = "radio" + idx++;
|
||||
|
||||
let s = "wireless." + name;
|
||||
let si = "wireless.default_" + name;
|
||||
|
||||
let band_name = filter(bands_order, (b) => info.bands[b])[0];
|
||||
if (!band_name)
|
||||
continue;
|
||||
|
||||
let band = info.bands[band_name];
|
||||
let channel = band.default_channel ?? "auto";
|
||||
|
||||
let width = band.max_width;
|
||||
if (band_name == "2G")
|
||||
width = 20;
|
||||
else if (width > 80)
|
||||
width = 80;
|
||||
|
||||
let htmode = filter(htmode_order, (m) => band[lc(m)])[0];
|
||||
if (htmode)
|
||||
htmode += width;
|
||||
else
|
||||
htmode = "NOHT";
|
||||
|
||||
if (!phy.path)
|
||||
continue;
|
||||
|
||||
let macaddr = trim(readfile(`/sys/class/ieee80211/${phy_name}/macaddress`));
|
||||
if (radio_exists(phy.path, macaddr, phy_name))
|
||||
continue;
|
||||
|
||||
let id = `phy='${phy_name}'`;
|
||||
if (match(phy_name, /^phy[0-9]/))
|
||||
id = `path='${phy.path}'`;
|
||||
|
||||
print(`set ${s}=wifi-device
|
||||
set ${s}.type='mac80211'
|
||||
set ${s}.${id}
|
||||
set ${s}.band='${lc(band_name)}'
|
||||
set ${s}.channel='${channel}'
|
||||
set ${s}.htmode='${htmode}'
|
||||
set ${s}.disabled='1'
|
||||
|
||||
set ${si}=wifi-iface
|
||||
set ${si}.device='${name}'
|
||||
set ${si}.network='lan'
|
||||
set ${si}.mode='ap'
|
||||
set ${si}.ssid='OpenWrt'
|
||||
set ${si}.encryption='none'
|
||||
|
||||
`);
|
||||
commit = true;
|
||||
}
|
||||
|
||||
if (commit)
|
||||
print("commit wireless\n");
|
||||
274
package/network/config/wifi-scripts/files/sbin/wifi
Executable file
274
package/network/config/wifi-scripts/files/sbin/wifi
Executable file
@@ -0,0 +1,274 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2006 OpenWrt.org
|
||||
|
||||
. /lib/functions.sh
|
||||
. /usr/share/libubox/jshn.sh
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $0 [config|up|down|reconf|reload|status|isup]
|
||||
enables (default), disables or configures devices not yet configured.
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
ubus_wifi_cmd() {
|
||||
local cmd="$1"
|
||||
local dev="$2"
|
||||
|
||||
json_init
|
||||
[ -n "$dev" ] && json_add_string device "$dev"
|
||||
ubus call network.wireless "$cmd" "$(json_dump)"
|
||||
}
|
||||
|
||||
wifi_isup() {
|
||||
local dev="$1"
|
||||
|
||||
json_load "$(ubus_wifi_cmd "status" "$dev")"
|
||||
json_get_keys devices
|
||||
|
||||
for device in $devices; do
|
||||
json_select "$device"
|
||||
json_get_var up up
|
||||
[ $up -eq 0 ] && return 1
|
||||
json_select ..
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
find_net_config() {(
|
||||
local vif="$1"
|
||||
local cfg
|
||||
local ifname
|
||||
|
||||
config_get cfg "$vif" network
|
||||
|
||||
[ -z "$cfg" ] && {
|
||||
include /lib/network
|
||||
scan_interfaces
|
||||
|
||||
config_get ifname "$vif" ifname
|
||||
|
||||
cfg="$(find_config "$ifname")"
|
||||
}
|
||||
[ -z "$cfg" ] && return 0
|
||||
echo "$cfg"
|
||||
)}
|
||||
|
||||
|
||||
bridge_interface() {(
|
||||
local cfg="$1"
|
||||
[ -z "$cfg" ] && return 0
|
||||
|
||||
include /lib/network
|
||||
scan_interfaces
|
||||
|
||||
for cfg in $cfg; do
|
||||
config_get iftype "$cfg" type
|
||||
[ "$iftype" = bridge ] && config_get "$cfg" ifname
|
||||
prepare_interface_bridge "$cfg"
|
||||
return $?
|
||||
done
|
||||
)}
|
||||
|
||||
prepare_key_wep() {
|
||||
local key="$1"
|
||||
local hex=1
|
||||
|
||||
echo -n "$key" | grep -qE "[^a-fA-F0-9]" && hex=0
|
||||
[ "${#key}" -eq 10 -a $hex -eq 1 ] || \
|
||||
[ "${#key}" -eq 26 -a $hex -eq 1 ] || {
|
||||
[ "${key:0:2}" = "s:" ] && key="${key#s:}"
|
||||
key="$(echo -n "$key" | hexdump -ve '1/1 "%02x" ""')"
|
||||
}
|
||||
echo "$key"
|
||||
}
|
||||
|
||||
wifi_fixup_hwmode() {
|
||||
local device="$1"
|
||||
local default="$2"
|
||||
local hwmode hwmode_11n
|
||||
|
||||
config_get channel "$device" channel
|
||||
config_get hwmode "$device" hwmode
|
||||
case "$hwmode" in
|
||||
11bg) hwmode=bg;;
|
||||
11a) hwmode=a;;
|
||||
11ad) hwmode=ad;;
|
||||
11b) hwmode=b;;
|
||||
11g) hwmode=g;;
|
||||
11n*)
|
||||
hwmode_11n="${hwmode##11n}"
|
||||
case "$hwmode_11n" in
|
||||
a|g) ;;
|
||||
default) hwmode_11n="$default"
|
||||
esac
|
||||
config_set "$device" hwmode_11n "$hwmode_11n"
|
||||
;;
|
||||
*)
|
||||
hwmode=
|
||||
if [ "${channel:-0}" -gt 0 ]; then
|
||||
if [ "${channel:-0}" -gt 14 ]; then
|
||||
hwmode=a
|
||||
else
|
||||
hwmode=g
|
||||
fi
|
||||
else
|
||||
hwmode="$default"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
config_set "$device" hwmode "$hwmode"
|
||||
}
|
||||
|
||||
_wifi_updown() {
|
||||
for device in ${2:-$DEVICES}; do (
|
||||
config_get disabled "$device" disabled
|
||||
[ "$disabled" = "1" ] && {
|
||||
echo "'$device' is disabled"
|
||||
set disable
|
||||
}
|
||||
config_get iftype "$device" type
|
||||
if eval "type ${1}_$iftype" 2>/dev/null >/dev/null; then
|
||||
eval "scan_$iftype '$device'"
|
||||
eval "${1}_$iftype '$device'" || echo "$device($iftype): ${1} failed"
|
||||
elif [ ! -f /lib/netifd/wireless/$iftype.sh ]; then
|
||||
echo "$device($iftype): Interface type not supported"
|
||||
fi
|
||||
); done
|
||||
}
|
||||
|
||||
wifi_updown() {
|
||||
cmd=down
|
||||
[ enable = "$1" ] && {
|
||||
_wifi_updown disable "$2"
|
||||
ubus_wifi_cmd "$cmd" "$2"
|
||||
ubus call network reload
|
||||
scan_wifi
|
||||
cmd=up
|
||||
}
|
||||
[ reconf = "$1" ] && {
|
||||
ubus call network reload
|
||||
scan_wifi
|
||||
cmd=reconf
|
||||
}
|
||||
ubus_wifi_cmd "$cmd" "$2"
|
||||
_wifi_updown "$@"
|
||||
}
|
||||
|
||||
wifi_reload_legacy() {
|
||||
_wifi_updown "disable" "$1"
|
||||
scan_wifi
|
||||
_wifi_updown "enable" "$1"
|
||||
}
|
||||
|
||||
wifi_reload() {
|
||||
ubus call network reload
|
||||
wifi_reload_legacy
|
||||
}
|
||||
|
||||
wifi_detect_notice() {
|
||||
>&2 echo "WARNING: Wifi detect is deprecated. Use wifi config instead"
|
||||
>&2 echo "For more information, see commit 5f8f8a366136a07df661e31decce2458357c167a"
|
||||
exit 1
|
||||
}
|
||||
|
||||
wifi_config() {
|
||||
[ -e /tmp/.config_pending ] && return
|
||||
ucode /usr/share/hostap/wifi-detect.uc
|
||||
[ ! -f /etc/config/wireless ] && touch /etc/config/wireless
|
||||
ucode /lib/wifi/mac80211.uc | uci -q batch
|
||||
|
||||
for driver in $DRIVERS; do (
|
||||
if eval "type detect_$driver" 2>/dev/null >/dev/null; then
|
||||
eval "detect_$driver" || echo "$driver: Detect failed" >&2
|
||||
else
|
||||
echo "$driver: Hardware detection not supported" >&2
|
||||
fi
|
||||
); done
|
||||
}
|
||||
|
||||
start_net() {(
|
||||
local iface="$1"
|
||||
local config="$2"
|
||||
local vifmac="$3"
|
||||
|
||||
[ -f "/var/run/$iface.pid" ] && kill "$(cat /var/run/${iface}.pid)" 2>/dev/null
|
||||
[ -z "$config" ] || {
|
||||
include /lib/network
|
||||
scan_interfaces
|
||||
for config in $config; do
|
||||
setup_interface "$iface" "$config" "" "$vifmac"
|
||||
done
|
||||
}
|
||||
)}
|
||||
|
||||
set_wifi_up() {
|
||||
local cfg="$1"
|
||||
local ifname="$2"
|
||||
uci_set_state wireless "$cfg" up 1
|
||||
uci_set_state wireless "$cfg" ifname "$ifname"
|
||||
}
|
||||
|
||||
set_wifi_down() {
|
||||
local cfg="$1"
|
||||
local vifs vif vifstr
|
||||
|
||||
[ -f "/var/run/wifi-${cfg}.pid" ] &&
|
||||
kill "$(cat "/var/run/wifi-${cfg}.pid")" 2>/dev/null
|
||||
uci_revert_state wireless "$cfg"
|
||||
config_get vifs "$cfg" vifs
|
||||
for vif in $vifs; do
|
||||
uci_revert_state wireless "$vif"
|
||||
done
|
||||
}
|
||||
|
||||
scan_wifi() {
|
||||
local cfgfile="$1"
|
||||
DEVICES=
|
||||
config_cb() {
|
||||
local type="$1"
|
||||
local section="$2"
|
||||
|
||||
# section start
|
||||
case "$type" in
|
||||
wifi-device)
|
||||
append DEVICES "$section"
|
||||
config_set "$section" vifs ""
|
||||
config_set "$section" ht_capab ""
|
||||
;;
|
||||
esac
|
||||
|
||||
# section end
|
||||
config_get TYPE "$CONFIG_SECTION" TYPE
|
||||
case "$TYPE" in
|
||||
wifi-iface)
|
||||
config_get device "$CONFIG_SECTION" device
|
||||
config_get vifs "$device" vifs
|
||||
append vifs "$CONFIG_SECTION"
|
||||
config_set "$device" vifs "$vifs"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
config_load "${cfgfile:-wireless}"
|
||||
}
|
||||
|
||||
DEVICES=
|
||||
DRIVERS=
|
||||
include /lib/wifi
|
||||
scan_wifi
|
||||
|
||||
case "$1" in
|
||||
down) wifi_updown "disable" "$2";;
|
||||
detect) wifi_detect_notice ;;
|
||||
config) wifi_config ;;
|
||||
status) ubus_wifi_cmd "status" "$2";;
|
||||
isup) wifi_isup "$2"; exit $?;;
|
||||
reload) wifi_reload "$2";;
|
||||
reload_legacy) wifi_reload_legacy "$2";;
|
||||
--help|help) usage;;
|
||||
reconf) wifi_updown "reconf" "$2";;
|
||||
''|up) wifi_updown "enable" "$2";;
|
||||
*) usage; exit 1;;
|
||||
esac
|
||||
@@ -0,0 +1,373 @@
|
||||
import * as nl80211 from "nl80211";
|
||||
import * as rtnl from "rtnl";
|
||||
import { readfile, glob, basename, readlink } from "fs";
|
||||
|
||||
const iftypes = {
|
||||
ap: nl80211.const.NL80211_IFTYPE_AP,
|
||||
mesh: nl80211.const.NL80211_IFTYPE_MESH_POINT,
|
||||
sta: nl80211.const.NL80211_IFTYPE_STATION,
|
||||
adhoc: nl80211.const.NL80211_IFTYPE_ADHOC,
|
||||
monitor: nl80211.const.NL80211_IFTYPE_MONITOR,
|
||||
};
|
||||
|
||||
const mesh_params = {
|
||||
mesh_retry_timeout: "retry_timeout",
|
||||
mesh_confirm_timeout: "confirm_timeout",
|
||||
mesh_holding_timeout: "holding_timeout",
|
||||
mesh_max_peer_links: "max_peer_links",
|
||||
mesh_max_retries: "max_retries",
|
||||
mesh_ttl: "ttl",
|
||||
mesh_element_ttl: "element_ttl",
|
||||
mesh_auto_open_plinks: "auto_open_plinks",
|
||||
mesh_hwmp_max_preq_retries: "hwmp_max_preq_retries",
|
||||
mesh_path_refresh_time: "path_refresh_time",
|
||||
mesh_min_discovery_timeout: "min_discovery_timeout",
|
||||
mesh_hwmp_active_path_timeout: "hwmp_active_path_timeout",
|
||||
mesh_hwmp_preq_min_interval: "hwmp_preq_min_interval",
|
||||
mesh_hwmp_net_diameter_traversal_time: "hwmp_net_diam_trvs_time",
|
||||
mesh_hwmp_rootmode: "hwmp_rootmode",
|
||||
mesh_hwmp_rann_interval: "hwmp_rann_interval",
|
||||
mesh_gate_announcements: "gate_announcements",
|
||||
mesh_sync_offset_max_neighor: "sync_offset_max_neighbor",
|
||||
mesh_rssi_threshold: "rssi_threshold",
|
||||
mesh_hwmp_active_path_to_root_timeout: "hwmp_path_to_root_timeout",
|
||||
mesh_hwmp_root_interval: "hwmp_root_interval",
|
||||
mesh_hwmp_confirmation_interval: "hwmp_confirmation_interval",
|
||||
mesh_awake_window: "awake_window",
|
||||
mesh_plink_timeout: "plink_timeout",
|
||||
mesh_fwding: "forwarding",
|
||||
mesh_power_mode: "power_mode",
|
||||
mesh_nolearn: "nolearn"
|
||||
};
|
||||
|
||||
function wdev_remove(name)
|
||||
{
|
||||
nl80211.request(nl80211.const.NL80211_CMD_DEL_INTERFACE, 0, { dev: name });
|
||||
}
|
||||
|
||||
function __phy_is_fullmac(phyidx)
|
||||
{
|
||||
let data = nl80211.request(nl80211.const.NL80211_CMD_GET_WIPHY, 0, { wiphy: phyidx });
|
||||
|
||||
return !data.software_iftypes.monitor;
|
||||
}
|
||||
|
||||
function phy_is_fullmac(phy)
|
||||
{
|
||||
let phyidx = int(trim(readfile(`/sys/class/ieee80211/${phy}/index`)));
|
||||
|
||||
return __phy_is_fullmac(phyidx);
|
||||
}
|
||||
|
||||
function find_reusable_wdev(phyidx)
|
||||
{
|
||||
if (!__phy_is_fullmac(phyidx))
|
||||
return null;
|
||||
|
||||
let data = nl80211.request(
|
||||
nl80211.const.NL80211_CMD_GET_INTERFACE,
|
||||
nl80211.const.NLM_F_DUMP,
|
||||
{ wiphy: phyidx });
|
||||
for (let res in data)
|
||||
if (trim(readfile(`/sys/class/net/${res.ifname}/operstate`)) == "down")
|
||||
return res.ifname;
|
||||
return null;
|
||||
}
|
||||
|
||||
function wdev_create(phy, name, data)
|
||||
{
|
||||
let phyidx = int(readfile(`/sys/class/ieee80211/${phy}/index`));
|
||||
|
||||
wdev_remove(name);
|
||||
|
||||
if (!iftypes[data.mode])
|
||||
return `Invalid mode: ${data.mode}`;
|
||||
|
||||
let req = {
|
||||
wiphy: phyidx,
|
||||
ifname: name,
|
||||
iftype: iftypes[data.mode],
|
||||
};
|
||||
|
||||
if (data["4addr"])
|
||||
req["4addr"] = data["4addr"];
|
||||
if (data.macaddr)
|
||||
req.mac = data.macaddr;
|
||||
|
||||
nl80211.error();
|
||||
|
||||
let reuse_ifname = find_reusable_wdev(phyidx);
|
||||
if (reuse_ifname &&
|
||||
(reuse_ifname == name ||
|
||||
rtnl.request(rtnl.const.RTM_SETLINK, 0, { dev: reuse_ifname, ifname: name}) != false))
|
||||
nl80211.request(
|
||||
nl80211.const.NL80211_CMD_SET_INTERFACE, 0, {
|
||||
wiphy: phyidx,
|
||||
dev: name,
|
||||
iftype: iftypes[data.mode],
|
||||
});
|
||||
else
|
||||
nl80211.request(
|
||||
nl80211.const.NL80211_CMD_NEW_INTERFACE,
|
||||
nl80211.const.NLM_F_CREATE,
|
||||
req);
|
||||
|
||||
let error = nl80211.error();
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (data.powersave != null) {
|
||||
nl80211.request(nl80211.const.NL80211_CMD_SET_POWER_SAVE, 0,
|
||||
{ dev: name, ps_state: data.powersave ? 1 : 0});
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function wdev_set_mesh_params(name, data)
|
||||
{
|
||||
let mesh_cfg = {};
|
||||
|
||||
for (let key in mesh_params) {
|
||||
let val = data[key];
|
||||
if (val == null)
|
||||
continue;
|
||||
mesh_cfg[mesh_params[key]] = int(val);
|
||||
}
|
||||
|
||||
if (!length(mesh_cfg))
|
||||
return null;
|
||||
|
||||
nl80211.request(nl80211.const.NL80211_CMD_SET_MESH_CONFIG, 0,
|
||||
{ dev: name, mesh_params: mesh_cfg });
|
||||
|
||||
return nl80211.error();
|
||||
}
|
||||
|
||||
function wdev_set_up(name, up)
|
||||
{
|
||||
rtnl.request(rtnl.const.RTM_SETLINK, 0, { dev: name, change: 1, flags: up ? 1 : 0 });
|
||||
}
|
||||
|
||||
function phy_sysfs_file(phy, name)
|
||||
{
|
||||
return trim(readfile(`/sys/class/ieee80211/${phy}/${name}`));
|
||||
}
|
||||
|
||||
function macaddr_split(str)
|
||||
{
|
||||
return map(split(str, ":"), (val) => hex(val));
|
||||
}
|
||||
|
||||
function macaddr_join(addr)
|
||||
{
|
||||
return join(":", map(addr, (val) => sprintf("%02x", val)));
|
||||
}
|
||||
|
||||
function wdev_macaddr(wdev)
|
||||
{
|
||||
return trim(readfile(`/sys/class/net/${wdev}/address`));
|
||||
}
|
||||
|
||||
const phy_proto = {
|
||||
macaddr_init: function(used, options) {
|
||||
this.macaddr_options = options ?? {};
|
||||
this.macaddr_list = {};
|
||||
|
||||
if (type(used) == "object")
|
||||
for (let addr in used)
|
||||
this.macaddr_list[addr] = used[addr];
|
||||
else
|
||||
for (let addr in used)
|
||||
this.macaddr_list[addr] = -1;
|
||||
|
||||
this.for_each_wdev((wdev) => {
|
||||
let macaddr = wdev_macaddr(wdev);
|
||||
this.macaddr_list[macaddr] ??= -1;
|
||||
});
|
||||
|
||||
return this.macaddr_list;
|
||||
},
|
||||
|
||||
macaddr_generate: function(data) {
|
||||
let phy = this.name;
|
||||
let idx = int(data.id ?? 0);
|
||||
let mbssid = int(data.mbssid ?? 0) > 0;
|
||||
let num_global = int(data.num_global ?? 1);
|
||||
let use_global = !mbssid && idx < num_global;
|
||||
|
||||
let base_addr = phy_sysfs_file(phy, "macaddress");
|
||||
if (!base_addr)
|
||||
return null;
|
||||
|
||||
if (!idx && !mbssid)
|
||||
return base_addr;
|
||||
|
||||
let base_mask = phy_sysfs_file(phy, "address_mask");
|
||||
if (!base_mask)
|
||||
return null;
|
||||
|
||||
if (base_mask == "00:00:00:00:00:00" && idx >= num_global) {
|
||||
let addrs = split(phy_sysfs_file(phy, "addresses"), "\n");
|
||||
|
||||
if (idx < length(addrs))
|
||||
return addrs[idx];
|
||||
|
||||
base_mask = "ff:ff:ff:ff:ff:ff";
|
||||
}
|
||||
|
||||
let addr = macaddr_split(base_addr);
|
||||
let mask = macaddr_split(base_mask);
|
||||
let type;
|
||||
|
||||
if (mbssid)
|
||||
type = "b5";
|
||||
else if (use_global)
|
||||
type = "add";
|
||||
else if (mask[0] > 0)
|
||||
type = "b1";
|
||||
else if (mask[5] < 0xff)
|
||||
type = "b5";
|
||||
else
|
||||
type = "add";
|
||||
|
||||
switch (type) {
|
||||
case "b1":
|
||||
if (!(addr[0] & 2))
|
||||
idx--;
|
||||
addr[0] |= 2;
|
||||
addr[0] ^= idx << 2;
|
||||
break;
|
||||
case "b5":
|
||||
if (mbssid)
|
||||
addr[0] |= 2;
|
||||
addr[5] ^= idx;
|
||||
break;
|
||||
default:
|
||||
for (let i = 5; i > 0; i--) {
|
||||
addr[i] += idx;
|
||||
if (addr[i] < 256)
|
||||
break;
|
||||
addr[i] %= 256;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return macaddr_join(addr);
|
||||
},
|
||||
|
||||
macaddr_next: function(val) {
|
||||
let data = this.macaddr_options ?? {};
|
||||
let list = this.macaddr_list;
|
||||
|
||||
for (let i = 0; i < 32; i++) {
|
||||
data.id = i;
|
||||
|
||||
let mac = this.macaddr_generate(data);
|
||||
if (!mac)
|
||||
return null;
|
||||
|
||||
if (list[mac] != null)
|
||||
continue;
|
||||
|
||||
list[mac] = val != null ? val : -1;
|
||||
return mac;
|
||||
}
|
||||
},
|
||||
|
||||
for_each_wdev: function(cb) {
|
||||
let wdevs = glob(`/sys/class/ieee80211/${this.name}/device/net/*`);
|
||||
wdevs = map(wdevs, (arg) => basename(arg));
|
||||
for (let wdev in wdevs) {
|
||||
if (basename(readlink(`/sys/class/net/${wdev}/phy80211`)) != this.name)
|
||||
continue;
|
||||
|
||||
cb(wdev);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function phy_open(phy)
|
||||
{
|
||||
let phyidx = readfile(`/sys/class/ieee80211/${phy}/index`);
|
||||
if (!phyidx)
|
||||
return null;
|
||||
|
||||
return proto({
|
||||
name: phy,
|
||||
idx: int(phyidx)
|
||||
}, phy_proto);
|
||||
}
|
||||
|
||||
const vlist_proto = {
|
||||
update: function(values, arg) {
|
||||
let data = this.data;
|
||||
let cb = this.cb;
|
||||
let seq = { };
|
||||
let new_data = {};
|
||||
let old_data = {};
|
||||
|
||||
this.data = new_data;
|
||||
|
||||
if (type(values) == "object") {
|
||||
for (let key in values) {
|
||||
old_data[key] = data[key];
|
||||
new_data[key] = values[key];
|
||||
delete data[key];
|
||||
}
|
||||
} else {
|
||||
for (let val in values) {
|
||||
let cur_key = val[0];
|
||||
let cur_obj = val[1];
|
||||
|
||||
old_data[cur_key] = data[cur_key];
|
||||
new_data[cur_key] = val[1];
|
||||
delete data[cur_key];
|
||||
}
|
||||
}
|
||||
|
||||
for (let key in data) {
|
||||
cb(null, data[key], arg);
|
||||
delete data[key];
|
||||
}
|
||||
for (let key in new_data)
|
||||
cb(new_data[key], old_data[key], arg);
|
||||
}
|
||||
};
|
||||
|
||||
function is_equal(val1, val2) {
|
||||
let t1 = type(val1);
|
||||
|
||||
if (t1 != type(val2))
|
||||
return false;
|
||||
|
||||
if (t1 == "array") {
|
||||
if (length(val1) != length(val2))
|
||||
return false;
|
||||
|
||||
for (let i = 0; i < length(val1); i++)
|
||||
if (!is_equal(val1[i], val2[i]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
} else if (t1 == "object") {
|
||||
for (let key in val1)
|
||||
if (!is_equal(val1[key], val2[key]))
|
||||
return false;
|
||||
for (let key in val2)
|
||||
if (val1[key] == null)
|
||||
return false;
|
||||
return true;
|
||||
} else {
|
||||
return val1 == val2;
|
||||
}
|
||||
}
|
||||
|
||||
function vlist_new(cb) {
|
||||
return proto({
|
||||
cb: cb,
|
||||
data: {}
|
||||
}, vlist_proto);
|
||||
}
|
||||
|
||||
export { wdev_remove, wdev_create, wdev_set_mesh_params, wdev_set_up, is_equal, vlist_new, phy_is_fullmac, phy_open };
|
||||
@@ -0,0 +1,186 @@
|
||||
#!/usr/bin/env ucode
|
||||
'use strict';
|
||||
import { vlist_new, is_equal, wdev_create, wdev_set_mesh_params, wdev_remove, wdev_set_up, phy_open } from "/usr/share/hostap/common.uc";
|
||||
import { readfile, writefile, basename, readlink, glob } from "fs";
|
||||
let libubus = require("ubus");
|
||||
|
||||
let keep_devices = {};
|
||||
let phy = shift(ARGV);
|
||||
let command = shift(ARGV);
|
||||
let phydev;
|
||||
|
||||
function iface_stop(wdev)
|
||||
{
|
||||
if (keep_devices[wdev.ifname])
|
||||
return;
|
||||
|
||||
wdev_remove(wdev.ifname);
|
||||
}
|
||||
|
||||
function iface_start(wdev)
|
||||
{
|
||||
let ifname = wdev.ifname;
|
||||
|
||||
if (readfile(`/sys/class/net/${ifname}/ifindex`)) {
|
||||
wdev_set_up(ifname, false);
|
||||
wdev_remove(ifname);
|
||||
}
|
||||
let wdev_config = {};
|
||||
for (let key in wdev)
|
||||
wdev_config[key] = wdev[key];
|
||||
if (!wdev_config.macaddr && wdev.mode != "monitor")
|
||||
wdev_config.macaddr = phydev.macaddr_next();
|
||||
wdev_create(phy, ifname, wdev_config);
|
||||
wdev_set_up(ifname, true);
|
||||
let htmode = wdev.htmode || "NOHT";
|
||||
if (wdev.freq)
|
||||
system(`iw dev ${ifname} set freq ${wdev.freq} ${htmode}`);
|
||||
if (wdev.mode == "adhoc") {
|
||||
let cmd = ["iw", "dev", ifname, "ibss", "join", wdev.ssid, wdev.freq, htmode, "fixed-freq" ];
|
||||
if (wdev.bssid)
|
||||
push(cmd, wdev.bssid);
|
||||
for (let key in [ "beacon-interval", "basic-rates", "mcast-rate", "keys" ])
|
||||
if (wdev[key])
|
||||
push(cmd, key, wdev[key]);
|
||||
system(cmd);
|
||||
} else if (wdev.mode == "mesh") {
|
||||
let cmd = [ "iw", "dev", ifname, "mesh", "join", wdev.ssid, "freq", wdev.freq, htmode ];
|
||||
for (let key in [ "mcast-rate", "beacon-interval" ])
|
||||
if (wdev[key])
|
||||
push(cmd, key, wdev[key]);
|
||||
system(cmd);
|
||||
|
||||
wdev_set_mesh_params(ifname, wdev);
|
||||
}
|
||||
}
|
||||
|
||||
function iface_cb(new_if, old_if)
|
||||
{
|
||||
if (old_if && new_if && is_equal(old_if, new_if))
|
||||
return;
|
||||
|
||||
if (old_if)
|
||||
iface_stop(old_if);
|
||||
if (new_if)
|
||||
iface_start(new_if);
|
||||
}
|
||||
|
||||
function drop_inactive(config)
|
||||
{
|
||||
for (let key in config) {
|
||||
if (!readfile(`/sys/class/net/${key}/ifindex`))
|
||||
delete config[key];
|
||||
}
|
||||
}
|
||||
|
||||
function add_ifname(config)
|
||||
{
|
||||
for (let key in config)
|
||||
config[key].ifname = key;
|
||||
}
|
||||
|
||||
function delete_ifname(config)
|
||||
{
|
||||
for (let key in config)
|
||||
delete config[key].ifname;
|
||||
}
|
||||
|
||||
function add_existing(phy, config)
|
||||
{
|
||||
let wdevs = glob(`/sys/class/ieee80211/${phy}/device/net/*`);
|
||||
wdevs = map(wdevs, (arg) => basename(arg));
|
||||
for (let wdev in wdevs) {
|
||||
if (config[wdev])
|
||||
continue;
|
||||
|
||||
if (basename(readlink(`/sys/class/net/${wdev}/phy80211`)) != phy)
|
||||
continue;
|
||||
|
||||
if (trim(readfile(`/sys/class/net/${wdev}/operstate`)) == "down")
|
||||
config[wdev] = {};
|
||||
}
|
||||
}
|
||||
|
||||
function usage()
|
||||
{
|
||||
warn(`Usage: ${basename(sourcepath())} <phy> <command> [<arguments>]
|
||||
|
||||
Commands:
|
||||
set_config <config> [<device]...] - set phy configuration
|
||||
get_macaddr <id> - get phy MAC address for vif index <id>
|
||||
`);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const commands = {
|
||||
set_config: function(args) {
|
||||
let statefile = `/var/run/wdev-${phy}.json`;
|
||||
|
||||
let new_config = shift(args);
|
||||
for (let dev in ARGV)
|
||||
keep_devices[dev] = true;
|
||||
|
||||
if (!new_config)
|
||||
usage();
|
||||
|
||||
new_config = json(new_config);
|
||||
if (!new_config) {
|
||||
warn("Invalid configuration\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
let old_config = readfile(statefile);
|
||||
if (old_config)
|
||||
old_config = json(old_config);
|
||||
|
||||
let config = vlist_new(iface_cb);
|
||||
if (type(old_config) == "object")
|
||||
config.data = old_config;
|
||||
|
||||
add_existing(phy, config.data);
|
||||
add_ifname(config.data);
|
||||
drop_inactive(config.data);
|
||||
|
||||
let ubus = libubus.connect();
|
||||
let data = ubus.call("hostapd", "config_get_macaddr_list", { phy: phy });
|
||||
let macaddr_list = [];
|
||||
if (type(data) == "object" && data.macaddr)
|
||||
macaddr_list = data.macaddr;
|
||||
ubus.disconnect();
|
||||
phydev.macaddr_init(macaddr_list);
|
||||
|
||||
add_ifname(new_config);
|
||||
config.update(new_config);
|
||||
|
||||
drop_inactive(config.data);
|
||||
delete_ifname(config.data);
|
||||
writefile(statefile, sprintf("%J", config.data));
|
||||
},
|
||||
get_macaddr: function(args) {
|
||||
let data = {};
|
||||
|
||||
for (let arg in args) {
|
||||
arg = split(arg, "=", 2);
|
||||
data[arg[0]] = arg[1];
|
||||
}
|
||||
|
||||
let macaddr = phydev.macaddr_generate(data);
|
||||
if (!macaddr) {
|
||||
warn(`Could not get MAC address for phy ${phy}\n`);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
print(macaddr + "\n");
|
||||
},
|
||||
};
|
||||
|
||||
if (!phy || !command | !commands[command])
|
||||
usage();
|
||||
|
||||
phydev = phy_open(phy);
|
||||
if (!phydev) {
|
||||
warn(`PHY ${phy} does not exist\n`);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
commands[command](ARGV);
|
||||
@@ -0,0 +1,187 @@
|
||||
#!/usr/bin/env ucode
|
||||
'use strict';
|
||||
import { readfile, writefile, realpath, glob, basename, unlink, open, rename } from "fs";
|
||||
import { is_equal } from "/usr/share/hostap/common.uc";
|
||||
let nl = require("nl80211");
|
||||
|
||||
let board_file = "/etc/board.json";
|
||||
let prev_board_data = json(readfile(board_file));
|
||||
let board_data = json(readfile(board_file));
|
||||
|
||||
function phy_idx(name) {
|
||||
return +rtrim(readfile(`/sys/class/ieee80211/${name}/index`));
|
||||
}
|
||||
|
||||
function phy_path(name) {
|
||||
let devpath = realpath(`/sys/class/ieee80211/${name}/device`);
|
||||
|
||||
devpath = replace(devpath, /^\/sys\/devices\//, "");
|
||||
if (match(devpath, /^platform\/.*\/pci/))
|
||||
devpath = replace(devpath, /^platform\//, "");
|
||||
let dev_phys = map(glob(`/sys/class/ieee80211/${name}/device/ieee80211/*`), basename);
|
||||
sort(dev_phys, (a, b) => phy_idx(a) - phy_idx(b));
|
||||
|
||||
let ofs = index(dev_phys, name);
|
||||
if (ofs > 0)
|
||||
devpath += `+${ofs}`;
|
||||
|
||||
return devpath;
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
let wlan = board_data.wlan;
|
||||
|
||||
for (let name in wlan)
|
||||
if (substr(name, 0, 3) == "phy")
|
||||
delete wlan[name];
|
||||
else
|
||||
delete wlan[name].info;
|
||||
}
|
||||
|
||||
function wiphy_get_entry(phy, path) {
|
||||
board_data.wlan ??= {};
|
||||
|
||||
let wlan = board_data.wlan;
|
||||
for (let name in wlan)
|
||||
if (wlan[name].path == path)
|
||||
return wlan[name];
|
||||
|
||||
wlan[phy] = {
|
||||
path: path
|
||||
};
|
||||
|
||||
return wlan[phy];
|
||||
}
|
||||
|
||||
function freq_to_channel(freq) {
|
||||
if (freq < 1000)
|
||||
return 0;
|
||||
if (freq == 2484)
|
||||
return 14;
|
||||
if (freq == 5935)
|
||||
return 2;
|
||||
if (freq < 2484)
|
||||
return (freq - 2407) / 5;
|
||||
if (freq >= 4910 && freq <= 4980)
|
||||
return (freq - 4000) / 5;
|
||||
if (freq < 5950)
|
||||
return (freq - 5000) / 5;
|
||||
if (freq <= 45000)
|
||||
return (freq - 5950) / 5;
|
||||
if (freq >= 58320 && freq <= 70200)
|
||||
return (freq - 56160) / 2160;
|
||||
return 0;
|
||||
}
|
||||
|
||||
function wiphy_detect() {
|
||||
let phys = nl.request(nl.const.NL80211_CMD_GET_WIPHY, nl.const.NLM_F_DUMP, { split_wiphy_dump: true });
|
||||
if (!phys)
|
||||
return;
|
||||
|
||||
for (let phy in phys) {
|
||||
let name = phy.wiphy_name;
|
||||
let path = phy_path(name);
|
||||
let info = {
|
||||
antenna_rx: phy.wiphy_antenna_avail_rx,
|
||||
antenna_tx: phy.wiphy_antenna_avail_tx,
|
||||
bands: {},
|
||||
};
|
||||
|
||||
let bands = info.bands;
|
||||
for (let band in phy.wiphy_bands) {
|
||||
if (!band || !band.freqs)
|
||||
continue;
|
||||
let freq = band.freqs[0].freq;
|
||||
let band_info = {};
|
||||
let band_name;
|
||||
if (freq > 50000)
|
||||
band_name = "60G";
|
||||
else if (freq > 5900)
|
||||
band_name = "6G";
|
||||
else if (freq > 4000)
|
||||
band_name = "5G";
|
||||
else if (freq > 2000)
|
||||
band_name = "2G";
|
||||
else
|
||||
continue;
|
||||
bands[band_name] = band_info;
|
||||
if (band.ht_capa > 0)
|
||||
band_info.ht = true;
|
||||
if (band.vht_capa > 0)
|
||||
band_info.vht = true;
|
||||
let he_phy_cap = 0;
|
||||
|
||||
for (let ift in band.iftype_data) {
|
||||
if (!ift.he_cap_phy)
|
||||
continue;
|
||||
|
||||
band_info.he = true;
|
||||
he_phy_cap |= ift.he_cap_phy[0];
|
||||
/* TODO: EHT */
|
||||
}
|
||||
|
||||
if (band_name != "2G" &&
|
||||
(he_phy_cap & 0x18) || ((band.vht_capa >> 2) & 0x3))
|
||||
band_info.max_width = 160;
|
||||
else if (band_name != "2G" &&
|
||||
(he_phy_cap & 4) || band.vht_capa > 0)
|
||||
band_info.max_width = 80;
|
||||
else if ((band.ht_capa & 0x2) || (he_phy_cap & 0x2))
|
||||
band_info.max_width = 40;
|
||||
else
|
||||
band_info.max_width = 20;
|
||||
|
||||
let modes = band_info.modes = [ "NOHT" ];
|
||||
if (band_info.ht)
|
||||
push(modes, "HT20");
|
||||
if (band_info.vht)
|
||||
push(modes, "VHT20");
|
||||
if (band_info.he)
|
||||
push(modes, "HE20");
|
||||
if (band.ht_capa & 0x2) {
|
||||
push(modes, "HT40");
|
||||
if (band_info.vht)
|
||||
push(modes, "VHT40")
|
||||
}
|
||||
if (he_phy_cap & 0x2)
|
||||
push(modes, "HE40");
|
||||
|
||||
for (let freq in band.freqs) {
|
||||
if (freq.disabled)
|
||||
continue;
|
||||
let chan = freq_to_channel(freq.freq);
|
||||
if (!chan)
|
||||
continue;
|
||||
band_info.default_channel = chan;
|
||||
break;
|
||||
}
|
||||
|
||||
if (band_name == "2G")
|
||||
continue;
|
||||
if (band_info.vht)
|
||||
push(modes, "VHT80");
|
||||
if (he_phy_cap & 4)
|
||||
push(modes, "HE80");
|
||||
if ((band.vht_capa >> 2) & 0x3)
|
||||
push(modes, "VHT160");
|
||||
if (he_phy_cap & 0x18)
|
||||
push(modes, "HE160");
|
||||
}
|
||||
|
||||
let entry = wiphy_get_entry(name, path);
|
||||
entry.info = info;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup();
|
||||
wiphy_detect();
|
||||
if (!is_equal(prev_board_data, board_data)) {
|
||||
let new_file = board_file + ".new";
|
||||
unlink(new_file);
|
||||
let f = open(new_file, "wx");
|
||||
if (!f)
|
||||
exit(1);
|
||||
f.write(sprintf("%.J\n", board_data));
|
||||
f.close();
|
||||
rename(new_file, board_file);
|
||||
}
|
||||
38
package/network/config/xfrm/Makefile
Normal file
38
package/network/config/xfrm/Makefile
Normal file
@@ -0,0 +1,38 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=xfrm
|
||||
PKG_RELEASE:=4
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/xfrm/Default
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
MAINTAINER:=Andre Valentin <avalentin@marcant.net>
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/xfrm
|
||||
$(call Package/xfrm/Default)
|
||||
TITLE:=XFRM IPsec Tunnel Interface config support
|
||||
DEPENDS:=+kmod-xfrm-interface
|
||||
endef
|
||||
|
||||
define Package/xfrm/description
|
||||
XFRM IPsec Tunnel Interface config support (IPv4 and IPv6) in /etc/config/network.
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Package/xfrm/install
|
||||
$(INSTALL_DIR) $(1)/lib/netifd/proto
|
||||
$(INSTALL_BIN) ./files/xfrm.sh $(1)/lib/netifd/proto/xfrm.sh
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,xfrm))
|
||||
72
package/network/config/xfrm/files/xfrm.sh
Executable file
72
package/network/config/xfrm/files/xfrm.sh
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ -n "$INCLUDE_ONLY" ] || {
|
||||
. /lib/functions.sh
|
||||
. /lib/functions/network.sh
|
||||
. ../netifd-proto.sh
|
||||
init_proto "$@"
|
||||
}
|
||||
|
||||
proto_xfrm_setup() {
|
||||
local cfg="$1"
|
||||
local mode="xfrm"
|
||||
|
||||
local tunlink ifid mtu zone multicast
|
||||
json_get_vars tunlink ifid mtu zone multicast
|
||||
|
||||
[ -z "$tunlink" ] && {
|
||||
proto_notify_error "$cfg" NO_TUNLINK
|
||||
proto_block_restart "$cfg"
|
||||
exit
|
||||
}
|
||||
|
||||
[ -z "$ifid" ] && {
|
||||
proto_notify_error "$cfg" NO_IFID
|
||||
proto_block_restart "$cfg"
|
||||
exit
|
||||
}
|
||||
|
||||
( proto_add_host_dependency "$cfg" '' "$tunlink" )
|
||||
|
||||
proto_init_update "$cfg" 1
|
||||
|
||||
proto_add_tunnel
|
||||
json_add_string mode "$mode"
|
||||
json_add_int mtu "${mtu:-1280}"
|
||||
|
||||
json_add_string link "$tunlink"
|
||||
|
||||
json_add_boolean multicast "${multicast:-1}"
|
||||
|
||||
json_add_object 'data'
|
||||
[ -n "$ifid" ] && json_add_int ifid "$ifid"
|
||||
json_close_object
|
||||
|
||||
proto_close_tunnel
|
||||
|
||||
proto_add_data
|
||||
[ -n "$zone" ] && json_add_string zone "$zone"
|
||||
proto_close_data
|
||||
|
||||
proto_send_update "$cfg"
|
||||
}
|
||||
|
||||
proto_xfrm_teardown() {
|
||||
local cfg="$1"
|
||||
}
|
||||
|
||||
proto_xfrm_init_config() {
|
||||
no_device=1
|
||||
available=1
|
||||
|
||||
proto_config_add_int "mtu"
|
||||
proto_config_add_string "tunlink"
|
||||
proto_config_add_string "zone"
|
||||
proto_config_add_int "ifid"
|
||||
proto_config_add_boolean "multicast"
|
||||
}
|
||||
|
||||
|
||||
[ -n "$INCLUDE_ONLY" ] || {
|
||||
[ -d /sys/module/xfrm_interface ] && add_protocol xfrm
|
||||
}
|
||||
43
package/network/ipv6/464xlat/Makefile
Normal file
43
package/network/ipv6/464xlat/Makefile
Normal file
@@ -0,0 +1,43 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=464xlat
|
||||
PKG_RELEASE:=13
|
||||
|
||||
PKG_SOURCE_DATE:=2018-01-16
|
||||
PKG_MAINTAINER:=Hans Dedecker <dedeckeh@gmail.com>
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/464xlat
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
DEPENDS:=@IPV6 +kmod-nat46 +ip
|
||||
TITLE:=464xlat CLAT support
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
$(call Build/Prepare/Default)
|
||||
$(CP) ./src/* $(PKG_BUILD_DIR)/
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
$(MAKE) -C $(PKG_BUILD_DIR) \
|
||||
CC="$(TARGET_CC)" \
|
||||
CFLAGS="$(TARGET_CFLAGS) -Wall" \
|
||||
LDFLAGS="$(TARGET_LDFLAGS)"
|
||||
endef
|
||||
|
||||
define Package/464xlat/description
|
||||
464xlat provides support to deploy limited IPv4 access services to mobile
|
||||
and wireline IPv6-only edge networks without encapsulation (RFC6877)
|
||||
endef
|
||||
|
||||
define Package/464xlat/install
|
||||
$(INSTALL_DIR) $(1)/lib/netifd/proto
|
||||
$(INSTALL_BIN) ./files/464xlat.sh $(1)/lib/netifd/proto/464xlat.sh
|
||||
$(INSTALL_DIR) $(1)/sbin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/464xlatcfg $(1)/sbin
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,464xlat))
|
||||
118
package/network/ipv6/464xlat/files/464xlat.sh
Executable file
118
package/network/ipv6/464xlat/files/464xlat.sh
Executable file
@@ -0,0 +1,118 @@
|
||||
#!/bin/sh
|
||||
# 464xlat.sh - 464xlat CLAT
|
||||
#
|
||||
# Copyright (c) 2015 Steven Barth <cyrus@openwrt.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2
|
||||
# as published by the Free Software Foundation
|
||||
#
|
||||
# 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 General Public License for more details.
|
||||
|
||||
[ -n "$INCLUDE_ONLY" ] || {
|
||||
. /lib/functions.sh
|
||||
. /lib/functions/network.sh
|
||||
. ../netifd-proto.sh
|
||||
init_proto "$@"
|
||||
}
|
||||
|
||||
proto_464xlat_setup() {
|
||||
local cfg="$1"
|
||||
local iface="$2"
|
||||
local link="464-$cfg"
|
||||
|
||||
local ip6addr ip6prefix tunlink zone
|
||||
json_get_vars ip6addr ip6prefix tunlink zone
|
||||
|
||||
[ "$zone" = "-" ] && zone=""
|
||||
|
||||
( proto_add_host_dependency "$cfg" "::" "$tunlink" )
|
||||
|
||||
if [ -z "$tunlink" ] && ! network_find_wan6 tunlink; then
|
||||
proto_notify_error "$cfg" "NO_WAN_LINK"
|
||||
return
|
||||
fi
|
||||
network_get_device tundev "$tunlink"
|
||||
|
||||
ip6addr=$(464xlatcfg "$link" "$tundev" "$ip6prefix" 192.0.0.1 $ip6addr)
|
||||
if [ -z "$ip6addr" ]; then
|
||||
proto_notify_error "$cfg" "CLAT_CONFIG_FAILED"
|
||||
return
|
||||
fi
|
||||
|
||||
ip -6 rule del from all lookup local
|
||||
ip -6 rule add from all lookup local pref 1
|
||||
ip -6 rule add to $ip6addr lookup prelocal pref 0
|
||||
echo "$ip6addr" > /tmp/464-$cfg-anycast
|
||||
|
||||
proto_init_update "$link" 1
|
||||
proto_add_ipv4_route "0.0.0.0" 0 "" "" 2048
|
||||
proto_add_ipv6_route $ip6addr 128 "" "" "" "" 128
|
||||
|
||||
proto_add_data
|
||||
[ -n "$zone" ] && json_add_string zone "$zone"
|
||||
|
||||
json_add_array firewall
|
||||
[ -z "$zone" ] && zone=$(fw3 -q network $iface 2>/dev/null)
|
||||
|
||||
json_add_object ""
|
||||
json_add_string type nat
|
||||
json_add_string target SNAT
|
||||
json_add_string family inet
|
||||
json_add_string snat_ip 192.0.0.1
|
||||
json_close_object
|
||||
[ -n "$zone" ] && {
|
||||
json_add_object ""
|
||||
json_add_string type rule
|
||||
json_add_string family inet6
|
||||
json_add_string proto all
|
||||
json_add_string direction in
|
||||
json_add_string dest "$zone"
|
||||
json_add_string src "$zone"
|
||||
json_add_string src_ip $ip6addr
|
||||
json_add_string target ACCEPT
|
||||
json_close_object
|
||||
}
|
||||
json_close_array
|
||||
proto_close_data
|
||||
|
||||
proto_send_update "$cfg"
|
||||
}
|
||||
|
||||
proto_464xlat_teardown() {
|
||||
local cfg="$1"
|
||||
local link="464-$cfg"
|
||||
|
||||
[ -f /tmp/464-$cfg-anycast ] || return
|
||||
local ip6addr=$(cat /tmp/464-$cfg-anycast)
|
||||
|
||||
464xlatcfg "$link"
|
||||
|
||||
rm -rf /tmp/464-$cfg-anycast
|
||||
[ -n "$ip6addr" ] && ip -6 rule del to $ip6addr lookup prelocal
|
||||
|
||||
if [ -z "$(ls /tmp/464-*-anycast 2>&-)" ]; then
|
||||
ip -6 rule del from all lookup local
|
||||
ip -6 rule add from all lookup local pref 0
|
||||
fi
|
||||
|
||||
# Kill conntracks SNATed to 192.0.0.1
|
||||
echo 192.0.0.1 > /proc/net/nf_conntrack
|
||||
}
|
||||
|
||||
proto_464xlat_init_config() {
|
||||
no_device=1
|
||||
available=1
|
||||
|
||||
proto_config_add_string "ip6prefix"
|
||||
proto_config_add_string "ip6addr"
|
||||
proto_config_add_string "tunlink"
|
||||
proto_config_add_string "zone"
|
||||
}
|
||||
|
||||
[ -n "$INCLUDE_ONLY" ] || {
|
||||
add_protocol 464xlat
|
||||
}
|
||||
154
package/network/ipv6/464xlat/src/464xlatcfg.c
Normal file
154
package/network/ipv6/464xlat/src/464xlatcfg.c
Normal file
@@ -0,0 +1,154 @@
|
||||
/* 464xlatcfg.c
|
||||
*
|
||||
* Copyright (c) 2015 Steven Barth <cyrus@openwrt.org>
|
||||
* Copyright (c) 2017 Hans Dedecker <dedeckeh@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation
|
||||
*
|
||||
* 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 General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
|
||||
static void sighandler(__attribute__((unused)) int signal)
|
||||
{
|
||||
}
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
char buf[INET6_ADDRSTRLEN], prefix[INET6_ADDRSTRLEN + 4];
|
||||
int pid;
|
||||
|
||||
if (argc <= 1) {
|
||||
fprintf(stderr, "Usage: %s <name> [ifname] [ipv6prefix] [ipv4addr] [ipv6addr]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), "/var/run/%s.pid", argv[1]);
|
||||
FILE *fp = fopen(buf, "r");
|
||||
if (fp) {
|
||||
if (fscanf(fp, "%d", &pid) == 1)
|
||||
kill(pid, SIGTERM);
|
||||
|
||||
unlink(buf);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
if (!argv[2])
|
||||
return 0;
|
||||
|
||||
if (!argv[3] || !argv[4] || !(fp = fopen(buf, "wx")))
|
||||
return 1;
|
||||
|
||||
signal(SIGTERM, SIG_DFL);
|
||||
setvbuf(fp, NULL, _IOLBF, 0);
|
||||
fprintf(fp, "%d\n", getpid());
|
||||
|
||||
prefix[sizeof(prefix) - 1] = 0;
|
||||
strncpy(prefix, argv[3], sizeof(prefix) - 1);
|
||||
|
||||
if (!prefix[0]) {
|
||||
struct addrinfo hints = { .ai_family = AF_INET6 }, *res;
|
||||
if (getaddrinfo("ipv4only.arpa", NULL, &hints, &res) || !res) {
|
||||
sleep(3);
|
||||
if (getaddrinfo("ipv4only.arpa", NULL, &hints, &res) || !res)
|
||||
return 2;
|
||||
}
|
||||
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)res->ai_addr;
|
||||
inet_ntop(AF_INET6, &sin6->sin6_addr, prefix, sizeof(prefix) - 4);
|
||||
strcat(prefix, "/96");
|
||||
freeaddrinfo(res);
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
int sock;
|
||||
struct sockaddr_in6 saddr;
|
||||
|
||||
do {
|
||||
socklen_t saddrlen = sizeof(saddr);
|
||||
struct icmp6_filter filt;
|
||||
|
||||
sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
|
||||
ICMP6_FILTER_SETBLOCKALL(&filt);
|
||||
setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, sizeof(filt));
|
||||
setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, argv[2], strlen(argv[2]));
|
||||
memset(&saddr, 0, sizeof(saddr));
|
||||
saddr.sin6_family = AF_INET6;
|
||||
saddr.sin6_addr.s6_addr32[0] = htonl(0x2001);
|
||||
saddr.sin6_addr.s6_addr32[1] = htonl(0xdb8);
|
||||
if (connect(sock, (struct sockaddr*)&saddr, sizeof(saddr)) ||
|
||||
getsockname(sock, (struct sockaddr*)&saddr, &saddrlen))
|
||||
return 3;
|
||||
|
||||
if (!IN6_IS_ADDR_LINKLOCAL(&saddr.sin6_addr) || argv[5])
|
||||
break;
|
||||
|
||||
close(sock);
|
||||
sleep(3);
|
||||
i++;
|
||||
} while (i < 3);
|
||||
|
||||
struct ipv6_mreq mreq = {saddr.sin6_addr, if_nametoindex(argv[2])};
|
||||
if (!argv[5]) {
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&mreq.ipv6mr_multiaddr))
|
||||
return 5;
|
||||
|
||||
srandom(mreq.ipv6mr_multiaddr.s6_addr32[0] ^ mreq.ipv6mr_multiaddr.s6_addr32[1] ^
|
||||
mreq.ipv6mr_multiaddr.s6_addr32[2] ^ mreq.ipv6mr_multiaddr.s6_addr32[3]);
|
||||
mreq.ipv6mr_multiaddr.s6_addr32[2] = random();
|
||||
mreq.ipv6mr_multiaddr.s6_addr32[3] = random();
|
||||
} else if (inet_pton(AF_INET6, argv[5], &mreq.ipv6mr_multiaddr) != 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (setsockopt(sock, SOL_IPV6, IPV6_JOIN_ANYCAST, &mreq, sizeof(mreq)))
|
||||
return 3;
|
||||
|
||||
inet_ntop(AF_INET6, &mreq.ipv6mr_multiaddr, buf, sizeof(buf));
|
||||
fputs(buf, stdout);
|
||||
fputc('\n', stdout);
|
||||
fflush(stdout);
|
||||
|
||||
FILE *nat46 = fopen("/proc/net/nat46/control", "w");
|
||||
if (!nat46 || fprintf(nat46, "add %s\nconfig %s local.style NONE local.v4 %s/32 local.v6 %s/128 "
|
||||
"remote.style RFC6052 remote.v6 %s\n", argv[1], argv[1], argv[4], buf, prefix) < 0 ||
|
||||
fclose(nat46))
|
||||
return 4;
|
||||
|
||||
if (!(pid = fork())) {
|
||||
fclose(fp);
|
||||
fclose(stdin);
|
||||
fclose(stdout);
|
||||
fclose(stderr);
|
||||
chdir("/");
|
||||
setsid();
|
||||
signal(SIGTERM, sighandler);
|
||||
pause();
|
||||
|
||||
nat46 = fopen("/proc/net/nat46/control", "w");
|
||||
if (nat46) {
|
||||
fprintf(nat46, "del %s\n", argv[1]);
|
||||
fclose(nat46);
|
||||
}
|
||||
} else {
|
||||
rewind(fp);
|
||||
fprintf(fp, "%d\n", pid);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
8
package/network/ipv6/464xlat/src/Makefile
Normal file
8
package/network/ipv6/464xlat/src/Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
all: 464xlatcfg
|
||||
|
||||
464xlatcfg: 464xlatcfg.c
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f 464xlatcfg
|
||||
|
||||
42
package/network/ipv6/6in4/Makefile
Normal file
42
package/network/ipv6/6in4/Makefile
Normal file
@@ -0,0 +1,42 @@
|
||||
#
|
||||
# Copyright (C) 2010-2015 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=6in4
|
||||
PKG_RELEASE:=28
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/6in4
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
DEPENDS:=@IPV6 +kmod-sit +uclient-fetch
|
||||
TITLE:=IPv6-in-IPv4 configuration support
|
||||
MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/6in4/description
|
||||
Provides support for 6in4 tunnels in /etc/config/network.
|
||||
Refer to http://wiki.openwrt.org/doc/uci/network for
|
||||
configuration details.
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Package/6in4/install
|
||||
$(INSTALL_DIR) $(1)/lib/netifd/proto
|
||||
$(INSTALL_BIN) ./files/6in4.sh $(1)/lib/netifd/proto/6in4.sh
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,6in4))
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user