netmode: Add support for SupportedArguments

This commit is contained in:
Vivek Kumar Dutta 2025-05-21 16:22:13 +05:30
parent 1d31c5f795
commit 36490a7cda
No known key found for this signature in database
GPG key ID: 4E09F5AD8265FD4C
5 changed files with 286 additions and 51 deletions

View file

@ -8,7 +8,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=netmode
PKG_VERSION:=1.1.1
PKG_VERSION:=1.1.2
PKG_RELEASE:=1
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
PKG_LICENSE:=GPL-2.0-only

View file

@ -3,7 +3,7 @@
"Device.{BBF_VENDOR_PREFIX}NetMode.": {
"type": "object",
"protocols": [
"cwmp",
"cwmp",
"usp"
],
"description": "Datamodel vendor extension to support easy switching between wan types, a reboot is required in some cases after switching the mode",
@ -16,7 +16,7 @@
"write": true,
"description": "Enable/Disable WAN switching using netmode",
"protocols": [
"cwmp",
"cwmp",
"usp"
],
"mapping": [
@ -38,9 +38,9 @@
"type": "string",
"read": true,
"write": true,
"description": "Current applied netmode value",
"description": "Current configured netmode value",
"protocols": [
"cwmp",
"cwmp",
"usp"
],
"flags": [
@ -68,6 +68,7 @@
"write": false,
"description": "SupportedModes Number of entries in the current config",
"protocols": [
"cwmp",
"usp"
],
"mapping": [
@ -88,10 +89,10 @@
"Device.{BBF_VENDOR_PREFIX}NetMode.SupportedModes.{i}.": {
"type": "object",
"protocols": [
"cwmp",
"cwmp",
"usp"
],
"access": true,
"access": false,
"array": true,
"description": "Object to list supported wan modes",
"mapping": [
@ -112,6 +113,7 @@
"write": false,
"description": "Name of the wan mode, it has to be unique and in sync with /etc/netmodes/",
"protocols": [
"cwmp",
"usp"
],
"flags": [
@ -132,6 +134,7 @@
"write": false,
"description": "Human readable description for this mode",
"protocols": [
"cwmp",
"usp"
],
"mapping": [
@ -142,25 +145,123 @@
}
]
},
"Args": {
"type": "string",
"SupportedArgumentsNumberOfEntries": {
"type": "unsignedInt",
"read": true,
"write": true,
"description": "Input args for this mode",
"write": false,
"description": "SupportedModes Number of entries in the current config",
"protocols": [
"cwmp",
"usp"
],
"flags": [
"Secure"
"mapping": [
{
"type": "uci",
"uci": {
"file": "netmode",
"section": {
"type": "supported_args"
},
"option": {
"name": "@Count"
}
}
}
]
},
"Device.{BBF_VENDOR_PREFIX}NetMode.SupportedModes.{i}.SupportedArguments.{i}.": {
"type": "object",
"protocols": [
"cwmp",
"usp"
],
"access": false,
"array": true,
"description": "Extra arguments for this Mode",
"mapping": [
{
"type": "uci_sec",
"data": "@Parent",
"list": "args"
"type": "uci",
"uci": {
"file": "netmode",
"section": {
"type": "supported_args"
},
"dmmapfile": "dmmap_netmode"
}
}
]
],
"Name": {
"type": "string",
"read": true,
"write": false,
"description": "Name of the argument",
"protocols": [
"cwmp",
"usp"
],
"mapping": [
{
"type": "uci_sec",
"data": "@Parent",
"key": "name"
}
]
},
"Description": {
"type": "string",
"read": true,
"write": false,
"description": "Human readable description for this Argument",
"protocols": [
"cwmp",
"usp"
],
"mapping": [
{
"type": "uci_sec",
"data": "@Parent",
"key": "description"
}
]
},
"Required": {
"type": "boolean",
"read": true,
"write": false,
"description": "If Required is true, then Name and Value is mandatory for mode to apply",
"protocols": [
"cwmp",
"usp"
],
"mapping": [
{
"type": "uci_sec",
"data": "@Parent",
"key": "required"
}
]
},
"Value": {
"type": "string",
"read": true,
"write": true,
"description": "Value for this SupportedArguments Name, get on this parameter result into empty output",
"protocols": [
"cwmp",
"usp"
],
"flags": [
"Secure"
],
"mapping": [
{
"type": "uci_sec",
"data": "@Parent",
"key": "value"
}
]
}
}
}
}
}
}

View file

@ -6,18 +6,110 @@ USE_PROCD=1
. /lib/functions.sh
MODEDIR="/etc/netmodes"
SUPP_MODES_SEC=""
_log() {
logger -s -p user.info -t "netmode" "$*"
}
libnetmode_exec() {
when="$1"
# Execute /lib/netmode scripts
if [ -d /lib/netmode/$when ]; then
logger -s -p user.info -t "netmode" "Executing /lib/netmode/$when scripts"
_log "Executing /lib/netmode/$when scripts"
for script in $(ls /lib/netmode/$when/); do
sh /lib/netmode/$when/$script
done
fi
}
_get_modes_sec_name() {
local sec mode name
sec="${1}"
mode="${2}"
config_get name ${1} name ""
if [ "${name}" = "${mode}" ]; then
SUPP_MODES_SEC="${sec}"
break;
fi
}
_set_env_args() {
local sec name value required dm_parent
sec="${1}"
config_get_bool required ${sec} required "0"
config_get name ${sec} name ""
config_get value ${sec} value ""
config_get dm_parent ${sec} dm_parent ""
if [ -z "${dm_parent}" ]; then
continue;
fi
if [ "${dm_parent}" != "${SUPP_MODES_SEC}" ]; then
continue;
fi
if [ "${required}" -eq "1" ]; then
if [ -z "${name}" -o -z "${value}" ]; then
_log "Can't apply mode, name[${name}] or value[${value}] is missing"
exit 0
fi
fi
if [ -n "${name}" -a -n "${value}" ]; then
export NETMODE_${name}="${value}"
fi
}
configure_env_vars() {
local mode
mode="${1}"
if [ -z "${mode}" ]; then
_log "mode info missing"
exit 0
fi
SUPP_MODES_SEC=""
config_load "netmode"
config_foreach _get_modes_sec_name supported_modes "${mode}"
if [ -z "${SUPP_MODES_SEC}" ]; then
_log "mode ${mode} not found in uci"
exit 0
fi
config_foreach _set_env_args supported_args
}
cleanup_arg_values() {
local dm_parent
config_get dm_parent ${1} dm_parent ""
if [ "${dm_parent}" = "${SUPP_MODES_SEC}" ]; then
uci -q set netmode.${1}.value=""
fi
}
cleanup_env_vars() {
for e in $(env); do
if echo ${e} |grep -q "^NETMODE_"; then
unset ${e}
fi
done
if [ -n "${SUPP_MODES_SEC}" ]; then
config_load "netmode"
config_foreach cleanup_arg_values supported_args
uci commit netmode
fi
}
start_service() {
[ -f /etc/config/netmode ] || return
@ -26,7 +118,7 @@ start_service() {
[ $enabled -eq 0 ] && return
# Get the desired netmode from config
config_get mode global mode
config_get mode global mode ""
# Check if netmode is set as boot environment parameter
[ -n "$mode" ] || mode="$(fw_printenv -n netmode 2>/dev/null)"
# Return if mode is not set
@ -37,18 +129,16 @@ start_service() {
# Return if desired mode is same as last saved mode
[ "$mode" == "$lastmode" ] && return
# Save mode as last mode
[ -d $MODEDIR ] || mkdir -p $MODEDIR
echo "$mode" > $MODEDIR/.last_mode
logger -s -p user.info -t "netmode" "Switching to $mode Mode" >/dev/console
_log "Switching to [${mode}] Mode" >/dev/console
# Configure env variables
configure_env_vars ${mode}
# Execute netmode generic pre-mode-switch scripts
libnetmode_exec "pre"
# Copy netmode UCI config files
if [ -d $MODEDIR/$mode/uci ]; then
logger -s -p user.info -t "netmode" "Copying $MODEDIR/$mode/uci/* to /etc/config/"
_log "Copying $MODEDIR/$mode/uci/* to /etc/config/"
cp $MODEDIR/$mode/uci/* /etc/config/ 2>/dev/null
fi
@ -57,7 +147,7 @@ start_service() {
# Execute mode specific scripts
if [ -d $MODEDIR/$mode/scripts ]; then
logger -s -p user.info -t "netmode" "Executing $MODEDIR/$mode/scripts/* scripts"
_log "Executing $MODEDIR/$mode/scripts/* scripts"
for script in $(ls $MODEDIR/$mode/scripts/); do
sh $MODEDIR/$mode/scripts/$script
done
@ -65,6 +155,12 @@ start_service() {
# Execute netmode generic post-mode-switch scripts
libnetmode_exec "post"
cleanup_env_vars "${mode}"
# Save mode as last mode
[ -d $MODEDIR ] || mkdir -p $MODEDIR
echo "$mode" > $MODEDIR/.last_mode
_log "Switching to Mode [${mode}] done, last mode updated" >/dev/console
}
service_triggers()

View file

@ -1,21 +1,31 @@
{
"mode": "routed-dhcp",
"supported_modes": [
{
"name": "routed-dhcp",
"description": "WAN with DHCP proto (Layer 3)"
},
{
"name": "routed-pppoe",
"description": "WAN with PPPoE (Layer 3)",
"args": [
"username:test",
"password:testpass123"
]
},
{
"name": "bridged",
"description": "Bridged mode (Layer 2)"
}
]
"#mode": "routed-pppoe",
"supported_modes": [
{
"name": "routed-dhcp",
"description": "WAN with DHCP proto (Layer 3)"
},
{
"name": "routed-pppoe",
"description": "WAN with PPPoE (Layer 3)",
"supported_args": [
{
"name": "username",
"description": "PPoE username",
"required": true,
"#value": "TestUser"
},
{
"name": "password",
"description": "PPoE password",
"required": true,
"#value": "TestPassword"
}
]
},
{
"name": "bridged",
"description": "Bridged mode (Layer 2)"
}
]
}

View file

@ -4,6 +4,7 @@
. /usr/share/libubox/jshn.sh
COUNT=1
SUPP_ARGS=1
SUPPORTED_MODE="/etc/netmodes/supported_modes.json"
if [ ! -f "/etc/config/netmode" ]; then
@ -14,6 +15,35 @@ if [ ! -f "${SUPPORTED_MODE}" ]; then
exit 0
fi
configure_supp_modes_args()
{
local obj inst name description required value parent
obj="${1}"
inst="${2}"
parent="${3}"
if [ -z "${inst}" ]; then
return 0
fi
json_select ${inst}
json_get_var name name
json_get_var description description
json_get_var value value
json_get_var required required
uci -q set netmode.${parent}_supprted_args_${SUPP_ARGS}=supported_args
uci -q set netmode.${parent}_supprted_args_${SUPP_ARGS}.name="${name}"
uci -q set netmode.${parent}_supprted_args_${SUPP_ARGS}.description="${description}"
uci -q set netmode.${parent}_supprted_args_${SUPP_ARGS}.required="${required}"
uci -q set netmode.${parent}_supprted_args_${SUPP_ARGS}.value="${value}"
uci -q set netmode.${parent}_supprted_args_${SUPP_ARGS}.dm_parent="${parent}"
json_select ..
SUPP_ARGS="$((SUPP_ARGS + 1))"
}
configure_supp_modes()
{
local obj inst name description args
@ -28,18 +58,16 @@ configure_supp_modes()
json_select ${inst}
json_get_var name name
json_get_var description description
json_get_values args args
if [ -d "/etc/netmodes/${name}" ]; then
uci -q set netmode.mode_${COUNT}=supported_modes
uci -q set netmode.mode_${COUNT}.name="${name}"
uci -q set netmode.mode_${COUNT}.description="${description}"
for arg in ${args}; do
uci -q add_list netmode.mode_${COUNT}.args="${arg}"
done
fi
SUPP_ARGS=1
json_for_each_item configure_supp_modes_args supported_args mode_${COUNT}
json_select ..
COUNT="$((COUNT + 1))"
}