Initial commit

This commit is contained in:
domenico
2025-06-24 16:03:39 +02:00
commit f3256cdaf2
6949 changed files with 1441681 additions and 0 deletions

View File

@@ -0,0 +1,62 @@
#
# 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:=2019-11-22
PKG_SOURCE_VERSION:=8174814a507489ebbe8bb85c1004e1f02919ca82
PKG_MIRROR_HASH:=84e0cca2d47470bdb1788a8ae044cc425be8ff650a1137474ba43a15040085da
PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
PKG_LICENSE:=ISC
PKG_CONFIG_DEPENDS := CONFIG_IPV6
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 +libxtables +kmod-ipt-core +kmod-ipt-conntrack +IPV6:kmod-nf-conntrack6 +kmod-ipt-nat
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
TARGET_CFLAGS += -ffunction-sections -fdata-sections -flto
TARGET_LDFLAGS += -Wl,--gc-sections -flto
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))

View File

@@ -0,0 +1,195 @@
config defaults
option syn_flood 1
option input ACCEPT
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://dev.openwrt.org/ticket/10381
config rule
option name Allow-DHCPv6
option src wan
option proto udp
option src_ip fc00::/6
option dest_ip fc00::/6
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
# 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

View 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

View 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
}

View 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.

View File

@@ -0,0 +1,33 @@
From 4a7df7d8c4e40fd2ce0d9f125755249dee17a8bd Mon Sep 17 00:00:00 2001
From: Yousong Zhou <yszhou4tech@gmail.com>
Date: Fri, 24 Jul 2020 12:52:59 +0800
Subject: [PATCH] zones: apply tcp mss clamping also on ingress path
Fixes FS#3231
Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
Acked-by: Jo-Philipp Wich <jo@mein.io>
(cherry picked from commit e9b90dfac2225927c035f6a76277b850c282dc9a)
---
zones.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/zones.c b/zones.c
index 01fb706..3d54a76 100644
--- a/zones.c
+++ b/zones.c
@@ -552,6 +552,14 @@ print_interface_rule(struct fw3_ipt_handle *handle, struct fw3_state *state,
fw3_ipt_rule_target(r, "TCPMSS");
fw3_ipt_rule_addarg(r, false, "--clamp-mss-to-pmtu", NULL);
fw3_ipt_rule_replace(r, "FORWARD");
+
+ r = fw3_ipt_rule_create(handle, &tcp, dev, NULL, sub, NULL);
+ fw3_ipt_rule_addarg(r, false, "--tcp-flags", "SYN,RST");
+ fw3_ipt_rule_addarg(r, false, "SYN", NULL);
+ fw3_ipt_rule_comment(r, "Zone %s MTU fixing", zone->name);
+ fw3_ipt_rule_target(r, "TCPMSS");
+ fw3_ipt_rule_addarg(r, false, "--clamp-mss-to-pmtu", NULL);
+ fw3_ipt_rule_replace(r, "FORWARD");
}
}
else if (handle->table == FW3_TABLE_RAW)

View File

@@ -0,0 +1,38 @@
From 78d52a28c66ad0fd2af250038fdcf4239ad37bf2 Mon Sep 17 00:00:00 2001
From: Remi NGUYEN VAN <remi.nguyenvan+openwrt@gmail.com>
Date: Sat, 15 Aug 2020 13:50:27 +0900
Subject: [PATCH] options: fix parsing of boolean attributes
Boolean attributes were parsed the same way as string attributes,
so a value of { "bool_attr": "true" } would be parsed correctly, but
{ "bool_attr": true } (without quotes) was parsed as false.
Fixes FS#3284
Signed-off-by: Remi NGUYEN VAN <remi.nguyenvan+openwrt@gmail.com>
---
options.c | 6 ++++++
1 file changed, 6 insertions(+)
--- a/options.c
+++ b/options.c
@@ -1170,6 +1170,9 @@ fw3_parse_blob_options(void *s, const st
if (blobmsg_type(e) == BLOBMSG_TYPE_INT32) {
snprintf(buf, sizeof(buf), "%d", blobmsg_get_u32(e));
v = buf;
+ } else if (blobmsg_type(o) == BLOBMSG_TYPE_BOOL) {
+ snprintf(buf, sizeof(buf), "%d", blobmsg_get_bool(o));
+ v = buf;
} else {
v = blobmsg_get_string(e);
}
@@ -1189,6 +1192,9 @@ fw3_parse_blob_options(void *s, const st
if (blobmsg_type(o) == BLOBMSG_TYPE_INT32) {
snprintf(buf, sizeof(buf), "%d", blobmsg_get_u32(o));
v = buf;
+ } else if (blobmsg_type(o) == BLOBMSG_TYPE_BOOL) {
+ snprintf(buf, sizeof(buf), "%d", blobmsg_get_bool(o));
+ v = buf;
} else {
v = blobmsg_get_string(o);
}

View File

@@ -0,0 +1,45 @@
#
# 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_VERSION:=1
PKG_RELEASE:=11
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))

View 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 ttl tos zone ikey okey icsum ocsum iseqno oseqno multicast
json_get_vars mtu 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}"
[ -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_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" ] || {
[ -f /lib/modules/$(uname -r)/gre.ko ] && add_protocol gre
[ -f /lib/modules/$(uname -r)/gre.ko ] && add_protocol gretap
[ -f /lib/modules/$(uname -r)/ip6_gre.ko ] && add_protocol grev6
[ -f /lib/modules/$(uname -r)/ip6_gre.ko ] && add_protocol grev6tap
}

View File

@@ -0,0 +1,41 @@
#
# 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_VERSION:=1
PKG_RELEASE:=3
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))

View File

@@ -0,0 +1,91 @@
#!/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
[ -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
( 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"
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"
}
[ -n "$INCLUDE_ONLY" ] || {
add_protocol ipip
}

View File

@@ -0,0 +1,86 @@
#
# 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:=6
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_BUILD_DIR:=$(BUILD_DIR)/dsl_cpe_control-$(PKG_VERSION)
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources/
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
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 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))

View 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}

View 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}

View File

@@ -0,0 +1,65 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2012 OpenWrt.org
START=97
USE_PROCD=1
EXTRA_COMMANDS="status lucistat"
EXTRA_HELP=" status Get DSL status information
lucistat Get status information if lua friendly format"
[ -f /lib/functions/lantiq_dsl.sh ] && . /lib/functions/lantiq_dsl.sh
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
}

View File

@@ -0,0 +1,65 @@
--- a/src/dsl_cpe_cli_access.c 2016-05-27 12:34:43.612485449 -0700
+++ b/src/dsl_cpe_cli_access.c 2016-05-27 12:45:37.491727862 -0700
@@ -1142,7 +1142,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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
{

View File

@@ -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>

View File

@@ -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-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)

View File

@@ -0,0 +1,71 @@
# 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-app
PKG_VERSION:=4.17.18.6
PKG_RELEASE:=2
PKG_BASE_NAME:=dsl_cpe_control
PKG_SOURCE:=$(PKG_BASE_NAME)_vrx-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
PKG_HASH:=da8bb929526a61aea0e153ef524331fcd472a1ebbc6d88ca017735a4f82ece02
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_BASE_NAME)-$(PKG_VERSION)
PKG_LICENSE:=BSD-2-Clause
PKG_BUILD_DEPENDS:=ltq-vdsl
PKG_ASLR_PIE:=0
PKG_FLAGS:=nonshared
include $(INCLUDE_DIR)/package.mk
define Package/ltq-vdsl-app
SECTION:=net
CATEGORY:=Network
TITLE:=Lantiq VDSL userland tool
URL:=http://www.lantiq.com/
DEPENDS:=@TARGET_lantiq_xrx200 +libpthread +librt
endef
define Package/ltq-vdsl-app/description
Userland tool needed to control Lantiq VDSL CPE
endef
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="-DMAX_CLI_PIPES=1" \
--enable-debug \
--disable-dti \
--with-channels-per-line="1" \
#CONFIGURE_ARGS += --enable-model=full
#CONFIGURE_ARGS += --enable-model=lite
#CONFIGURE_ARGS += --enable-model=footprint
CONFIGURE_ARGS += \
--enable-model=typical \
--enable-dsl-pm-showtime \
--disable-dsl-ceoc
#CONFIGURE_ARGS += --enable-model=debug
define Package/ltq-vdsl-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-app))

View 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

View 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

View File

@@ -0,0 +1,316 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2012 OpenWrt.org
START=97
USE_PROCD=1
EXTRA_COMMANDS="status lucistat"
EXTRA_HELP=" status Get DSL status information
lucistat Get status information if lua friendly format"
[ -f /lib/functions/lantiq_dsl.sh ] && . /lib/functions/lantiq_dsl.sh
#
# 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 ADSL autoboot script. Used for SNR margin tweak
autoboot_script() {
echo "[WaitForConfiguration]={
locs 0 $1
}
[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
}
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
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
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}" ] || {
# for SNR offset setting
autoboot_script "$snr"
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() {
# do not use dsl_cmd to not block when this is locked up by some other proess
echo quit > /tmp/pipe/dsl_cpe0_cmd
DSL_NOTIFICATION_TYPE="DSL_INTERFACE_STATUS" \
DSL_INTERFACE_STATUS="DOWN" \
/sbin/dsl_notify.sh
}

View 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"

View File

@@ -0,0 +1,22 @@
--- 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, \
--- a/src/dsl_cpe_control.c
+++ b/src/dsl_cpe_control.c
@@ -6761,7 +6761,7 @@ DSL_int_t dsl_cpe_daemon (
for (nDevice = 0; nDevice < DSL_CPE_MAX_DSL_ENTITIES; nDevice++)
{
#if defined(INCLUDE_DSL_CPE_API_VRX)
- sprintf (device, "%s/%d", DSL_CPE_DEVICE_NAME, nDevice);
+ sprintf (device, "%s%d", DSL_CPE_DEVICE_NAME, nDevice);
#else
sprintf (device, "%s", DSL_CPE_DEVICE_NAME);
#endif /* defined(INCLUDE_DSL_CPE_API_VRX)*/

View File

@@ -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"

View File

@@ -0,0 +1,11 @@
--- 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),

View File

@@ -0,0 +1,46 @@
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:=2021-01-09
PKG_SOURCE_VERSION:=753c351bc729967a691d99e27693be5aec334028
PKG_MIRROR_HASH:=e7d95bde520fc660d0a49e28c5bb50fff3071d7f48fe7fc3fc610f38edfc7df1
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
PKG_LICENSE:=GPL-2.0
PKG_LICENSE_FILES:=
PKG_BUILD_PARALLEL:=1
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
TITLE:=OpenWrt Network Interface Configuration Daemon
endef
TARGET_CFLAGS += \
-I$(STAGING_DIR)/usr/include/libnl-tiny \
-I$(STAGING_DIR)/usr/include \
-flto
TARGET_LDFLAGS += -flto -fuse-linker-plugin
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)/
$(CP) $(PKG_BUILD_DIR)/scripts/* $(1)/lib/netifd/
endef
$(eval $(call BuildPackage,netifd))

View File

@@ -0,0 +1,6 @@
[ ifup = "$ACTION" ] && {
uci_toggle_state network "$INTERFACE" up 1
[ -n "$DEVICE" ] && {
uci_toggle_state network "$INTERFACE" ifname "$DEVICE"
}
}

View File

@@ -0,0 +1,67 @@
#!/bin/sh
[ "$ACTION" = add ] || exit
NPROCS="$(grep -c "^processor.*:" /proc/cpuinfo)"
[ "$NPROCS" -gt 1 ] || exit
PROC_MASK="$(( (1 << $NPROCS) - 1 ))"
find_irq_cpu() {
local dev="$1"
local match="$(grep -m 1 "$dev\$" /proc/interrupts)"
local cpu=0
[ -n "$match" ] && {
set -- $match
shift
for cur in `seq 1 $NPROCS`; do
[ "$1" -gt 0 ] && {
cpu=$(($cur - 1))
break
}
shift
done
}
echo "$cpu"
}
set_hex_val() {
local file="$1"
local val="$2"
val="$(printf %x "$val")"
[ -n "$DEBUG" ] && echo "$file = $val"
echo "$val" > "$file"
}
default_ps="$(uci get "network.@globals[0].default_ps")"
[ -n "$default_ps" -a "$default_ps" != 1 ] && exit 0
exec 512>/var/lock/smp_tune.lock
flock 512 || exit 1
for dev in /sys/class/net/*; do
[ -d "$dev" ] || continue
# ignore virtual interfaces
[ -n "$(ls "${dev}/" | grep '^lower_')" ] && continue
[ -d "${dev}/device" ] || continue
device="$(readlink "${dev}/device")"
device="$(basename "$device")"
irq_cpu="$(find_irq_cpu "$device")"
irq_cpu_mask="$((1 << $irq_cpu))"
for q in ${dev}/queues/rx-*; do
set_hex_val "$q/rps_cpus" "$(($PROC_MASK & ~$irq_cpu_mask))"
done
ntxq="$(ls -d ${dev}/queues/tx-* | wc -l)"
idx=$(($irq_cpu + 1))
for q in ${dev}/queues/tx-*; do
set_hex_val "$q/xps_cpus" "$((1 << $idx))"
let "idx = idx + 1"
[ "$idx" -ge "$NPROCS" ] && idx=0
done
done

View File

@@ -0,0 +1,149 @@
#!/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
}
service_running() {
ubus -t 30 wait_for network.interface
/sbin/wifi reload_legacy
}
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
}

View File

@@ -0,0 +1,110 @@
#!/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
eval "$(ipcalc.sh "$ip/$mask")";ip_net="$NETWORK"
local i
for i in $router; do
local gw_net
eval "$(ipcalc.sh "$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
proto_add_data
[ -n "$ZONE" ] && json_add_string zone "$ZONE"
[ -n "$ntpsrv" ] && json_add_string ntpserver "$ntpsrv"
[ -n "$timesvr" ] && json_add_string timeserver "$timesvr"
[ -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"
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 "$@"
exit 0

View File

@@ -0,0 +1,88 @@
#!/bin/sh
[ -L /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 'release: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 release reqopts defaultreqopts iface6rd sendopts delegate zone6rd zone mtu6rd customroutes classlessroute
json_get_vars ipaddr hostname clientid vendorid broadcast release 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=
[ "$release" = 1 ] && release="-R" || release=
[ -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 $release $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

View 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"
}

View 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)"

View File

@@ -0,0 +1 @@
ifup

View 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\" }"

View File

@@ -0,0 +1,77 @@
#!/bin/sh
ifup_all=
setup_wifi=
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"
setup_wifi=1
;;
*) echo "Invalid command: $0";;
esac
while :; do
case "$1" in
-a)
ifup_all=1
shift
;;
-w)
setup_wifi=
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
[ -n "$setup_wifi" ] && /sbin/wifi up
exit
else
ubus -S list "network.interface.$1" > /dev/null || {
echo "Interface $1 not found"
exit
}
if_call "$1"
fi
if [ -n "$setup_wifi" ] && grep -sq config /etc/config/wireless; then
. /lib/functions.sh
find_related_radios() {
local wdev wnet
config_get wdev "$1" device
config_get wnet "$1" network
if [ -n "$wdev" ]; then
for wnet in $wnet; do
if [ "$wnet" = "$network" ]; then
append radio_devs "$wdev" "$N"
fi
done
fi
}
network="$1"
config_load wireless
config_foreach find_related_radios wifi-iface
for dev in $(echo "$radio_devs" | sort -u); do
/sbin/wifi up "$dev"
done
fi

View 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: ifconfig $interface $ip netmask ${subnet:-255.255.255.0} broadcast ${broadcast:-+}"
ifconfig $interface $ip netmask ${subnet:-255.255.255.0} broadcast ${broadcast:-+}
[ -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)
ifconfig "$interface" 0.0.0.0
;;
renew)
setup_interface update
;;
bound)
setup_interface ifup
;;
esac
# user rules
[ -f /etc/udhcpc.user ] && . /etc/udhcpc.user
exit 0

View 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:=2
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))

View 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

View File

@@ -0,0 +1,2 @@
#!/bin/sh
[ "$ACTION" = ifup ] && /etc/init.d/qos enabled && /usr/lib/qos/generate.sh interface "$INTERFACE" | sh

View 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
}

View File

@@ -0,0 +1,4 @@
#!/bin/sh
qos-stop
/usr/lib/qos/generate.sh all | sh

View 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"

View 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

View File

@@ -0,0 +1,542 @@
#!/bin/sh
[ -e /lib/functions.sh ] && . /lib/functions.sh || . ./functions.sh
[ -x /sbin/modprobe ] && {
insmod="modprobe"
rmmod="$insmod -r"
} || {
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}="ifconfig $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

View File

@@ -0,0 +1,106 @@
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
}
}
}

View 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:=2
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))

View File

@@ -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

View File

@@ -0,0 +1,15 @@
#!/bin/sh
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__

View 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

View 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

View 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:

View File

@@ -0,0 +1,57 @@
#
# 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
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_CFLAGS += -flto
TARGET_LDFLAGS += -flto=jobserver
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))

View 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
}

View 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

View File

@@ -0,0 +1,387 @@
/*
* 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
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);
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);
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;
}

View 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;
}
}

View 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

View File

@@ -0,0 +1,246 @@
/*
* 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_port")) {
char *devn = NULL, *port = NULL, *port_err = NULL;
int port_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, "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);
} else 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);
}
}
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;
}

View File

@@ -0,0 +1,74 @@
#
# 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_VERSION:=1
PKG_RELEASE:=3
PKG_LICENSE:=GPL-2.0
include $(INCLUDE_DIR)/package.mk
define Package/vti/Default
SECTION:=net
CATEGORY:=Network
MAINTAINER:=Andre Valentin <avalentin@marcant.net>
PKGARCH:=all
endef
define Package/vti
$(call Package/vti/Default)
TITLE:=Virtual IPsec Tunnel Interface config support
endef
define Package/vti/description
Virtual IPsec Tunnel Interface config support (IPv4 and IPv6) in /etc/config/network.
endef
define Package/vtiv4
$(call Package/vti/Default)
TITLE:=Virtual IPsec Tunnel Interface (IPv4) config support
DEPENDS:=@(PACKAGE_vti) +kmod-ip-vti
endef
define Package/vtiv4/description
Virtual IPsec Tunnel Interface config support (IPv4) in /etc/config/network.
endef
define Package/vtiv6
$(call Package/vti/Default)
TITLE:=Virtual IPsec Tunnel Interface (IPv6) config support
DEPENDS:=@(PACKAGE_vti) @IPV6 +kmod-ip6-vti
endef
define Package/vtiv6/description
Virtual IPsec Tunnel Interface config support (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
define Package/vtiv4/install
:
endef
define Package/vtiv6/install
:
endef
$(eval $(call BuildPackage,vti))
$(eval $(call BuildPackage,vtiv4))
$(eval $(call BuildPackage,vtiv6))

View 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" ] || {
[ -f /lib/modules/$(uname -r)/ip_vti.ko ] && add_protocol vti
[ -f /lib/modules/$(uname -r)/ip6_vti.ko ] && add_protocol vti6
}

View File

@@ -0,0 +1,33 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=vxlan
PKG_RELEASE:=3
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))

View File

@@ -0,0 +1,152 @@
#!/bin/sh
[ -n "$INCLUDE_ONLY" ] || {
. /lib/functions.sh
. /lib/functions/network.sh
. ../netifd-proto.sh
init_proto "$@"
}
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
json_get_vars port vid ttl tos mtu macaddr zone rxcsum txcsum
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 "$macaddr" ] && json_add_string macaddr "$macaddr"
[ -n "$rxcsum" ] && json_add_boolean rxcsum "$rxcsum"
[ -n "$txcsum" ] && json_add_boolean txcsum "$txcsum"
json_close_object
proto_close_tunnel
proto_add_data
[ -n "$zone" ] && json_add_string zone "$zone"
proto_close_data
proto_send_update "$cfg"
}
proto_vxlan_setup() {
local cfg="$1"
local ipaddr peeraddr
json_get_vars ipaddr peeraddr tunlink
[ -z "$peeraddr" ] && {
proto_notify_error "$cfg" "MISSING_ADDRESS"
proto_block_restart "$cfg"
exit
}
( proto_add_host_dependency "$cfg" '' "$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
}
vxlan_generic_setup "$cfg" 'vxlan' "$ipaddr" "$peeraddr"
}
proto_vxlan6_setup() {
local cfg="$1"
local ip6addr peer6addr
json_get_vars ip6addr peer6addr tunlink
[ -z "$peer6addr" ] && {
proto_notify_error "$cfg" "MISSING_ADDRESS"
proto_block_restart "$cfg"
exit
}
( proto_add_host_dependency "$cfg" '' "$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
proto_notify_error "$cfg" "NO_WAN_LINK"
exit
fi
}
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_boolean "rxcsum"
proto_config_add_boolean "txcsum"
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
}

View File

@@ -0,0 +1,39 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=xfrm
PKG_VERSION:=1
PKG_RELEASE:=2
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))

View File

@@ -0,0 +1,69 @@
#!/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
json_get_vars tunlink ifid mtu zone
[ -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_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"
}
[ -n "$INCLUDE_ONLY" ] || {
[ -f /lib/modules/$(uname -r)/xfrm_interface.ko -o -d /sys/module/xfrm_interface ] && add_protocol xfrm
}