From ccd0d4e69243600e5f05eeaa5a5d8f7d96d9d7e4 Mon Sep 17 00:00:00 2001 From: Tomaz Zaman Date: Wed, 12 Aug 2026 21:00:45 +0200 Subject: [PATCH 55/72] cmmqos: UCI front-end for cmm CEETM QoS (S4) New mono package (package/mono/cmmqos) -- the ./source half pairing ASK item 7. /etc/config/cmmqos gives full set-qm coverage (interface/channel/classque/dscp/ingress/sec/ff+expt rates); a procd init renders it to 'set qm' directives and applies them live via 'cmm -c qm-config', with a reload trigger so 'uci commit cmmqos' reapplies. Off by default; disabling + reload flushes QoS via qm-config's flush-then-apply. Added to mono_gateway-dk DEVICE_PACKAGES. Co-Authored-By: Claude Fable 5 --- package/mono/cmmqos/Makefile | 45 +++++++ package/mono/cmmqos/files/cmmqos.config | 81 +++++++++++++ package/mono/cmmqos/files/cmmqos.init | 135 +++++++++++++++++++++ target/linux/layerscape/image/armv8_64b.mk | 3 +- 4 files changed, 263 insertions(+), 1 deletion(-) create mode 100644 package/mono/cmmqos/Makefile create mode 100644 package/mono/cmmqos/files/cmmqos.config create mode 100644 package/mono/cmmqos/files/cmmqos.init diff --git a/package/mono/cmmqos/Makefile b/package/mono/cmmqos/Makefile new file mode 100644 index 0000000000..36c30d4b3e --- /dev/null +++ b/package/mono/cmmqos/Makefile @@ -0,0 +1,45 @@ +# +# Mono Gateway — UCI front-end for the ASK cmm queue manager (CEETM QoS). +# +include $(TOPDIR)/rules.mk + +PKG_NAME:=cmmqos +PKG_VERSION:=1 +PKG_RELEASE:=1 + +PKG_LICENSE:=GPL-2.0 +PKG_MAINTAINER:=Mono + +include $(INCLUDE_DIR)/package.mk + +define Package/cmmqos + SECTION:=net + CATEGORY:=Network + SUBMENU:=Firewall + TITLE:=Mono Gateway CEETM QoS (cmm qm-config front-end) + DEPENDS:=@TARGET_layerscape +cmm + PKGARCH:=all +endef + +define Package/cmmqos/description + UCI front-end for the ASK cmm queue manager: CEETM egress shaping, + DSCP->queue maps and ingress policing. Renders /etc/config/cmmqos into + cmm 'set qm' directives and applies them live via 'cmm -c qm-config' + (item 7) without restarting cmm, which would drop the fast path. + Off by default (config cmmqos 'global' option enabled '0'). +endef + +define Package/cmmqos/conffiles +/etc/config/cmmqos +endef + +define Build/Compile +endef + +define Package/cmmqos/install + $(INSTALL_DIR) $(1)/etc/config $(1)/etc/init.d + $(INSTALL_CONF) ./files/cmmqos.config $(1)/etc/config/cmmqos + $(INSTALL_BIN) ./files/cmmqos.init $(1)/etc/init.d/cmmqos +endef + +$(eval $(call BuildPackage,cmmqos)) diff --git a/package/mono/cmmqos/files/cmmqos.config b/package/mono/cmmqos/files/cmmqos.config new file mode 100644 index 0000000000..01aea3d33a --- /dev/null +++ b/package/mono/cmmqos/files/cmmqos.config @@ -0,0 +1,81 @@ +# Mono Gateway CEETM QoS — UCI front-end for cmm's queue manager. +# Rendered to 'set qm ...' directives (see cmm module_qm.c) and applied +# live via 'cmm -c qm-config' — no cmm restart. Rates are in Kbps. +# Off unless 'global' enabled = 1. Disabling + reloading flushes all QoS. + +config cmmqos 'global' + option enabled '0' + +# --- Per-interface egress shaper --------------------------------------- +# set qm interface qos {on|off} +# set qm interface shaper [on|off] [rate ] [bucketsize ] +#config interface +# option name 'eth3' +# option qos 'on' +# option shaper 'on' +# option rate '900000' +# option bucketsize '' + +# --- CEETM channel (1-8) ----------------------------------------------- +# set qm channel assign interface +# set qm channel shaper [on|off] [rate ] [bucketsize] +# set qm channel wbfq chshaper [on|off] [priority 0-6] +#config channel +# option id '1' +# option assign_interface 'eth3' +# option shaper 'on' +# option rate '900000' +# option wbfq_chshaper 'on' +# option wbfq_priority '3' + +# --- Class queue on a channel (type pq | wbfq) ------------------------- +# set qm channel classque [qdepth ] [priority ..] (pq) +# set qm channel classque [qdepth ] [weight 1-255] (wbfq) +# set qm channel classque cqshaper [on|off] [rate ] +#config classque +# option channel '1' +# option index '0' +# option type 'wbfq' +# option qdepth '' +# option weight '10' +# option priority '' +# option cqshaper 'on' +# option cqrate '100000' + +# --- DSCP -> channel/queue map ----------------------------------------- +# set qm dscp-to-fqmap enable +# set qm dscp-to-fqmap dscp <0-63> channel-id <0-7> classqueue <0-15> +# each 'dscp' list entry = " " +#config dscp_map +# option interface 'eth3' +# option enabled 'on' +# list dscp '46 0 0' +# list dscp '0 1 15' + +# --- Ingress policing -------------------------------------------------- +# set qm ingress queue <0-7|default> policer {on|off} +# set qm ingress queue <1-7|default> [cir <>] [pir <>] +#config ingress +# option queue '1' +# option policer 'on' +# option cir '1000000' +# option pir '1000000' + +# --- SEC (IPsec) rate -------------------------------------------------- +# set qm sec_rate [cir] [pir] [cbs] [pbs] +#config sec_rate +# option cir '' +# option pir '' +# option cbs '' +# option pbs '' + +# --- Fast-forward / exception rate ------------------------------------- +# set qm ff_rate [cir <>] [pir <>] +# set qm expt_rate +#config rate +# option type 'ff' +# option port 'eth3' +# option cir '' +# option pir '' +# option val1 '' +# option val2 '' diff --git a/package/mono/cmmqos/files/cmmqos.init b/package/mono/cmmqos/files/cmmqos.init new file mode 100644 index 0000000000..18328eccc9 --- /dev/null +++ b/package/mono/cmmqos/files/cmmqos.init @@ -0,0 +1,135 @@ +#!/bin/sh /etc/rc.common +# Mono Gateway CEETM QoS. Renders /etc/config/cmmqos into cmm 'set qm' +# directives and applies them live via 'cmm -c qm-config' (no cmm restart, +# which would drop the fast path). Disabling + reloading applies an empty +# config, which item 7's qm-config flushes-then-applies == QoS off. + +USE_PROCD=1 +START=55 +STOP=09 + +CONF=/tmp/cmmqos.conf +BOARD="mono,gateway-dk" + +qm() { printf 'set qm %s\n' "$*" >> "$CONF"; } + +render_interface() { + local name qos shaper rate bucketsize + config_get name "$1" name; [ -n "$name" ] || return 0 + config_get qos "$1" qos + [ -n "$qos" ] && qm "interface $name qos $qos" + config_get shaper "$1" shaper + [ -n "$shaper" ] && { + config_get rate "$1" rate; config_get bucketsize "$1" bucketsize + qm "interface $name shaper $shaper${rate:+ rate $rate}${bucketsize:+ bucketsize $bucketsize}" + } +} + +render_channel() { + local id assign_interface shaper rate bucketsize wbfq_chshaper wbfq_priority + config_get id "$1" id; [ -n "$id" ] || return 0 + config_get assign_interface "$1" assign_interface + [ -n "$assign_interface" ] && qm "channel $id assign interface $assign_interface" + config_get shaper "$1" shaper + [ -n "$shaper" ] && { + config_get rate "$1" rate; config_get bucketsize "$1" bucketsize + qm "channel $id shaper $shaper${rate:+ rate $rate}${bucketsize:+ bucketsize $bucketsize}" + } + config_get wbfq_chshaper "$1" wbfq_chshaper + [ -n "$wbfq_chshaper" ] && { + config_get wbfq_priority "$1" wbfq_priority + qm "channel $id wbfq chshaper $wbfq_chshaper${wbfq_priority:+ priority $wbfq_priority}" + } +} + +render_classque() { + local channel index type qdepth weight priority cqshaper cqrate + config_get channel "$1" channel; config_get index "$1" index + [ -n "$channel" ] && [ -n "$index" ] || return 0 + config_get type "$1" type + config_get qdepth "$1" qdepth; config_get weight "$1" weight + config_get priority "$1" priority + case "$type" in + wbfq) qm "channel $channel classque $index${qdepth:+ qdepth $qdepth}${weight:+ weight $weight}" ;; + *) qm "channel $channel classque $index${qdepth:+ qdepth $qdepth}${priority:+ priority $priority}" ;; + esac + config_get cqshaper "$1" cqshaper + [ -n "$cqshaper" ] && { + config_get cqrate "$1" cqrate + qm "channel $channel classque $index cqshaper $cqshaper${cqrate:+ rate $cqrate}" + } +} + +render_dscp_map() { + local interface enabled + config_get interface "$1" interface; [ -n "$interface" ] || return 0 + config_get enabled "$1" enabled + [ "$enabled" = "on" ] && qm "dscp-to-fqmap $interface enable" + DSCP_IF="$interface" + config_list_foreach "$1" dscp render_dscp_entry +} +render_dscp_entry() { + set -- $1 # " " + [ -n "$3" ] && qm "dscp-to-fqmap $DSCP_IF dscp $1 channel-id $2 classqueue $3" +} + +render_ingress() { + local queue policer cir pir + config_get queue "$1" queue; [ -n "$queue" ] || return 0 + config_get policer "$1" policer + [ -n "$policer" ] && qm "ingress queue $queue policer $policer" + config_get cir "$1" cir; config_get pir "$1" pir + [ -n "$cir$pir" ] && qm "ingress queue $queue${cir:+ cir $cir}${pir:+ pir $pir}" +} + +render_sec_rate() { + local cir pir cbs pbs + config_get cir "$1" cir; config_get pir "$1" pir + config_get cbs "$1" cbs; config_get pbs "$1" pbs + qm "sec_rate${cir:+ cir $cir}${pir:+ pir $pir}${cbs:+ cbs $cbs}${pbs:+ pbs $pbs}" +} + +render_rate() { + local type port cir pir val1 val2 + config_get type "$1" type; config_get port "$1" port + case "$type" in + ff) config_get cir "$1" cir; config_get pir "$1" pir + qm "ff_rate $port${cir:+ cir $cir}${pir:+ pir $pir}" ;; + expt) config_get val1 "$1" val1; config_get val2 "$1" val2 + [ -n "$val2" ] && qm "expt_rate $port $val1 $val2" ;; + esac +} + +apply() { + [ "$(board_name)" = "$BOARD" ] || return 0 + pgrep -x cmm >/dev/null 2>&1 || { logger -t cmmqos "cmm not running - deferring QoS apply"; return 0; } + + config_load cmmqos + local enabled; config_get_bool enabled global enabled 0 + + : > "$CONF" + if [ "$enabled" = "1" ]; then + echo "# generated by cmmqos.init from /etc/config/cmmqos - do not edit" >> "$CONF" + config_foreach render_interface interface + config_foreach render_channel channel + config_foreach render_classque classque + config_foreach render_dscp_map dscp_map + config_foreach render_ingress ingress + config_foreach render_sec_rate sec_rate + config_foreach render_rate rate + fi + # enabled=0 -> empty file -> qm-config flushes-then-applies == QoS off + + if cmm -c "qm-config $CONF" >/dev/null 2>&1; then + [ "$enabled" = "1" ] \ + && logger -t cmmqos "applied $(grep -c '^set qm' "$CONF") QoS directives" \ + || logger -t cmmqos "flushed QoS (disabled)" + else + logger -t cmmqos "ERROR: cmm rejected the QoS config (qm-config failed)" + return 1 + fi +} + +start_service() { apply; } +reload_service() { apply; } +service_triggers() { procd_add_reload_trigger cmmqos; } diff --git a/target/linux/layerscape/image/armv8_64b.mk b/target/linux/layerscape/image/armv8_64b.mk index b174536d81..10b91ea279 100644 --- a/target/linux/layerscape/image/armv8_64b.mk +++ b/target/linux/layerscape/image/armv8_64b.mk @@ -463,7 +463,8 @@ define Device/mono_gateway-dk block-mount kmod-usb-storage-uas kmod-fs-exfat kmod-fs-ntfs3 \ kmod-fs-vfat smartmontools usbutils pciutils i2c-tools \ tmux vim-full curl rsync jq less bind-dig openssh-sftp-server \ - usign ca-bundle file ip-full resize2fs mono-update-check + usign ca-bundle file ip-full resize2fs mono-update-check \ + cmmqos KERNEL_NAME := Image KERNEL := kernel-bin | gzip FILESYSTEMS := ext4 -- 2.47.3