From 95471502d7c3021fef251e3eeb37d3ec5c19f124 Mon Sep 17 00:00:00 2001 From: Anatoly Mirin Date: Thu, 9 Feb 2023 21:08:53 +0300 Subject: [PATCH] mcastmngr: integrate mcproxy linux/lib/mcast/linux.sh converts mcastmngr UCI params to the mcproxy native conf file. --- .../files/broadcom/lib/mcast/broadcom.sh | 180 +---------------- mcastmngr/files/common/etc/init.d/mcast | 32 ++- .../etc/uci-defaults/61-mcast_config_generate | 21 ++ mcastmngr/files/common/lib/mcast/common.sh | 182 ++++++++++++++++++ mcastmngr/files/linux/etc/firewall.mcast | 2 + .../etc/uci-defaults/60-mcast_config_generate | 12 ++ mcastmngr/files/linux/lib/mcast/linux.sh | 149 +++++++++++++- 7 files changed, 395 insertions(+), 183 deletions(-) create mode 100755 mcastmngr/files/common/lib/mcast/common.sh create mode 100644 mcastmngr/files/linux/etc/firewall.mcast create mode 100644 mcastmngr/files/linux/etc/uci-defaults/60-mcast_config_generate mode change 100644 => 100755 mcastmngr/files/linux/lib/mcast/linux.sh diff --git a/mcastmngr/files/broadcom/lib/mcast/broadcom.sh b/mcastmngr/files/broadcom/lib/mcast/broadcom.sh index 740bb1fd9..5e8018b9c 100755 --- a/mcastmngr/files/broadcom/lib/mcast/broadcom.sh +++ b/mcastmngr/files/broadcom/lib/mcast/broadcom.sh @@ -2,155 +2,23 @@ . /lib/functions.sh . /usr/share/libubox/jshn.sh +. /lib/mcast/common.sh include /lib/network + CONFFILE=/var/mcpd.conf PROG_EXE=/usr/sbin/mcpd -# Parameters available in snooping configuration -igmp_s_enable=0 -igmp_s_version=2 -igmp_s_query_interval=125 -igmp_s_q_resp_interval=100 -igmp_s_last_mem_q_int=10 -igmp_s_fast_leave=1 -igmp_s_robustness=2 -igmp_s_mode=0 -igmp_s_iface="" -igmp_s_exceptions="" - -mld_s_enable=0 -mld_s_version=2 -mld_s_robustness=2 -mld_s_mode=0 -mld_s_iface="" -mld_s_exceptions="" - -# Global params -max_groups=25 -max_msf=10 -max_members=25 -mldv1_unsolicited_report_interval=10 -mldv2_unsolicited_report_interval=1 - -# Parameters available in proxy configuration -igmp_p_enable=0 -igmp_p_version=2 -igmp_query_interval=125 -igmp_q_resp_interval=100 -igmp_last_mem_q_int=10 -igmp_fast_leave=1 -igmp_p_robustness=2 -igmp_p_mode=0 -igmp_p_up_interfaces="" -igmp_p_down_interfaces="" -igmp_p_exceptions="" - -mld_p_enable=0 -mld_p_version=1 -mld_query_interval=125 -mld_q_resp_interval=100 -mld_last_mem_q_int=10 -mld_fast_leave=1 -mld_p_robustness=2 -mld_p_mode=0 -mld_p_up_interfaces="" -mld_p_down_interfaces="" -mld_p_exceptions="" - proxdevs="" ethwan="$(db -q get hw.board.ethernetWanPort)" -read_snooping() { - local config="$1" - local sec_enable - local proto - - config_get sec_enable "$config" enable 0 - config_get proto "$config" proto - - if [ "$sec_enable" == "0" ]; then - return - fi - - if [ "$proto" == "igmp" ]; then - igmp_s_enable=$sec_enable - config_get igmp_s_version "$config" version 2 - config_get igmp_s_query_interval "$config" query_interval 125 - config_get igmp_s_q_resp_interval "$config" query_response_interval 100 - config_get igmp_s_last_mem_q_int "$config" last_member_query_interval 10 - config_get igmp_s_fast_leave "$config" fast_leave 1 - config_get igmp_s_robustness "$config" robustness 2 - config_get igmp_s_mode "$config" snooping_mode 0 - config_get igmp_s_iface "$config" interface - config_get igmp_s_exceptions "$config" filter - return - fi - - if [ "$proto" == "mld" ]; then - mld_s_enable=$sec_enable - config_get mld_s_version "$config" version 2 - config_get mld_s_query_interval "$config" query_interval 125 - config_get mld_s_q_resp_interval "$config" query_response_interval 100 - config_get mld_s_last_mem_q_int "$config" last_member_query_interval 10 - config_get mld_s_fast_leave "$config" fast_leave 1 - config_get mld_s_robustness "$config" robustness 2 - config_get mld_s_mode "$config" snooping_mode 0 - config_get mld_s_iface "$config" interface - config_get mld_s_exceptions "$config" filter - return - fi -} - -read_proxy() { - local config="$1" - local sec_enable - local proto - - config_get sec_enable "$config" enable 0 - config_get proto "$config" proto - - if [ "$sec_enable" == "0" ]; then - return - fi - - if [ "$proto" == "igmp" ]; then - igmp_p_enable=$sec_enable - config_get igmp_p_version "$config" version 2 - config_get igmp_query_interval "$config" query_interval 125 - config_get igmp_q_resp_interval "$config" query_response_interval 100 - config_get igmp_last_mem_q_int "$config" last_member_query_interval 10 - config_get igmp_fast_leave "$config" fast_leave 1 - config_get igmp_p_robustness "$config" robustness 2 - config_get igmp_p_mode "$config" snooping_mode 0 - config_get igmp_p_up_interfaces "$config" upstream_interface - config_get igmp_p_down_interfaces "$config" downstream_interface - config_get igmp_p_exceptions "$config" filter - return - fi - - if [ "$proto" == "mld" ]; then - mld_p_enable=$sec_enable - config_get mld_p_version "$config" version 2 - config_get mld_query_interval "$config" query_interval 125 - config_get mld_q_resp_interval "$config" query_response_interval 100 - config_get mld_last_mem_q_int "$config" last_member_query_interval 10 - config_get mld_fast_leave "$config" fast_leave 1 - config_get mld_p_robustness "$config" robustness 2 - config_get mld_p_mode "$config" snooping_mode 0 - config_get mld_p_up_interfaces "$config" upstream_interface - config_get mld_p_down_interfaces "$config" downstream_interface - config_get mld_p_exceptions "$config" filter - return - fi -} config_snooping_common_params() { local protocol="$1" echo "${protocol}-default-version $2" >> $CONFFILE echo "${protocol}-robustness-value $3" >> $CONFFILE - echo "${protocol}-max-groups $max_groups" >> $CONFFILE + echo "${protocol}-max-groups $max_groups" >> $CONFFILE echo "${protocol}-max-sources $max_msf" >> $CONFFILE echo "${protocol}-max-members $max_members" >> $CONFFILE echo "${protocol}-snooping-enable $4" >> $CONFFILE @@ -254,7 +122,7 @@ configure_mcpd_snooping() { local exceptions local filter_ip="" local fast_leave=0 - + # Configure snooping related params if [ "$protocol" == "igmp" ]; then config_snooping_common_params $protocol $igmp_s_version $igmp_s_robustness $igmp_s_mode @@ -366,44 +234,6 @@ configure_mcpd() { fi } -read_mcast_snooping_params() { - config_load mcast - config_foreach read_snooping snooping -} - -read_mcast_proxy_params() { - config_load mcast - config_foreach read_proxy proxy -} - -config_global_params() { - local igmp_qrv - local igmp_force_version - local mld_qrv - local mld_force_version - - config_load mcast - config_get max_msf igmp max_msf 10 - config_get max_groups igmp max_membership 25 - config_get igmp_qrv igmp qrv 2 - config_get igmp_force_version igmp force_version 0 - - config_get mld_qrv mld qrv 2 - config_get mldv1_unsolicited_report_interval mld mldv1_unsolicited_report_interval 10 - config_get mldv2_unsolicited_report_interval mld mldv2_unsolicited_report_interval 1 - config_get mld_force_version mld force_version 0 - - # mcpd internally writes max_groups and max_msf, no need to modify - # here directly - echo $igmp_qrv > /proc/sys/net/ipv4/igmp_qrv - echo $igmp_force_version > /proc/sys/net/ipv4/conf/all/force_igmp_version - - echo $mld_qrv > /proc/sys/net/ipv6/mld_qrv - echo $mld_force_version > /proc/sys/net/ipv6/conf/all/force_mld_version - echo $mldv1_unsolicited_report_interval > /proc/sys/net/ipv6/conf/all/mldv1_unsolicited_report_interval - echo $mldv2_unsolicited_report_interval > /proc/sys/net/ipv6/conf/all/mldv2_unsolicited_report_interval -} - setup_mcast_mode() { # set the mode at chip to allow both tagged and untagged multicast forwarding bs /b/c iptv lookup_method=group_ip_src_ip @@ -413,6 +243,8 @@ configure_mcast() { rm -f $CONFFILE touch $CONFFILE + # mcpd internally writes max_groups and max_msf, no need to modify + # here directly config_global_params read_mcast_snooping_params diff --git a/mcastmngr/files/common/etc/init.d/mcast b/mcastmngr/files/common/etc/init.d/mcast index 468d89839..25f32cd8a 100755 --- a/mcastmngr/files/common/etc/init.d/mcast +++ b/mcastmngr/files/common/etc/init.d/mcast @@ -14,15 +14,36 @@ service_triggers() { procd_add_reload_trigger network $NAME } +start_mcast_service() { + local param=$@ + + procd_open_instance + + procd_set_param command "${PROG_EXE}" + if [ -n "${param}" ]; then + procd_append_param command ${param} + fi + procd_set_param respawn + + procd_close_instance +} + start_service() { if [ -f "/etc/config/mcast" ]; then configure_mcast fi - procd_open_instance - procd_set_param command "$PROG_EXE" - procd_set_param respawn - procd_close_instance + if [ -z "${PROG_PARAMS}" ]; then + start_mcast_service + return + fi + + local prev_IFS="${IFS}" + IFS=${PROG_PARAMS_SEPARATOR} + for param in ${PROG_PARAMS}; do + IFS="${prev_IFS}" + start_mcast_service ${param} + done } boot() { @@ -31,11 +52,10 @@ boot() { } stop_service() { - service_stop $PROG_EXE + service_stop "${PROG_EXE}" } reload_service() { stop start } - diff --git a/mcastmngr/files/common/etc/uci-defaults/61-mcast_config_generate b/mcastmngr/files/common/etc/uci-defaults/61-mcast_config_generate index 8c850b28a..8113223f5 100644 --- a/mcastmngr/files/common/etc/uci-defaults/61-mcast_config_generate +++ b/mcastmngr/files/common/etc/uci-defaults/61-mcast_config_generate @@ -43,6 +43,27 @@ generate_mcast_config(){ done uci add_list mcast.@proxy[-1].filter="239.0.0.0/8" + + + uci add mcast proxy + uci rename mcast.@proxy[-1]="mc_proxy_MLD" + uci set mcast.@proxy[-1].enable="1" + uci set mcast.@proxy[-1].proto="mld" + uci set mcast.@proxy[-1].version="1" + uci set mcast.@proxy[-1].robustness="2" + uci set mcast.@proxy[-1].query_interval="125" + uci set mcast.@proxy[-1].query_response_interval="100" + uci set mcast.@proxy[-1].last_member_query_interval="10" + uci set mcast.@proxy[-1].fast_leave="1" + uci set mcast.@proxy[-1].snooping_mode="2" + uci add_list mcast.@proxy[-1].downstream_interface="br-lan" + + IFS=" " + for itf in $up_itf; do + uci add_list mcast.@proxy[-1].upstream_interface="$itf" + done + + uci commit mcast } diff --git a/mcastmngr/files/common/lib/mcast/common.sh b/mcastmngr/files/common/lib/mcast/common.sh new file mode 100755 index 000000000..d3063152d --- /dev/null +++ b/mcastmngr/files/common/lib/mcast/common.sh @@ -0,0 +1,182 @@ +#!/bin/sh + +. /lib/functions.sh + +include /lib/network + + +# Parameters available in snooping configuration +igmp_s_enable=0 +igmp_s_version=2 +igmp_s_query_interval=125 +igmp_s_q_resp_interval=100 +igmp_s_last_mem_q_int=10 +igmp_s_fast_leave=1 +igmp_s_robustness=2 +igmp_s_mode=0 +igmp_s_iface="" +igmp_s_exceptions="" + +mld_s_enable=0 +mld_s_version=2 +mld_s_robustness=2 +mld_s_mode=0 +mld_s_iface="" +mld_s_exceptions="" + +# Global params +max_groups=25 +max_msf=10 +max_members=25 +mldv1_unsolicited_report_interval=10 +mldv2_unsolicited_report_interval=1 + +# Parameters available in proxy configuration +igmp_p_enable=0 +igmp_p_version=2 +igmp_query_interval=125 +igmp_q_resp_interval=100 +igmp_last_mem_q_int=10 +igmp_fast_leave=1 +igmp_p_robustness=2 +igmp_p_mode=0 +igmp_p_up_interfaces="" +igmp_p_down_interfaces="" +igmp_p_exceptions="" + +mld_p_enable=0 +mld_p_version=1 +mld_query_interval=125 +mld_q_resp_interval=100 +mld_last_mem_q_int=10 +mld_fast_leave=1 +mld_p_robustness=2 +mld_p_mode=0 +mld_p_up_interfaces="" +mld_p_down_interfaces="" +mld_p_exceptions="" + +read_snooping() { + local config="$1" + local sec_enable + local proto + + config_get sec_enable "$config" enable 0 + config_get proto "$config" proto + + if [ "$sec_enable" == "0" ]; then + return + fi + + if [ "$proto" == "igmp" ]; then + igmp_s_enable=$sec_enable + config_get igmp_s_version "$config" version 2 + config_get igmp_s_query_interval "$config" query_interval 125 + config_get igmp_s_q_resp_interval "$config" query_response_interval 100 + config_get igmp_s_last_mem_q_int "$config" last_member_query_interval 10 + config_get igmp_s_fast_leave "$config" fast_leave 1 + config_get igmp_s_robustness "$config" robustness 2 + config_get igmp_s_mode "$config" snooping_mode 0 + config_get igmp_s_iface "$config" interface + config_get igmp_s_exceptions "$config" filter + return + fi + + if [ "$proto" == "mld" ]; then + mld_s_enable=$sec_enable + config_get mld_s_version "$config" version 2 + config_get mld_s_query_interval "$config" query_interval 125 + config_get mld_s_q_resp_interval "$config" query_response_interval 100 + config_get mld_s_last_mem_q_int "$config" last_member_query_interval 10 + config_get mld_s_fast_leave "$config" fast_leave 1 + config_get mld_s_robustness "$config" robustness 2 + config_get mld_s_mode "$config" snooping_mode 0 + config_get mld_s_iface "$config" interface + config_get mld_s_exceptions "$config" filter + return + fi +} + +read_proxy() { + local config="$1" + local sec_enable + local proto + + config_get sec_enable "$config" enable 0 + config_get proto "$config" proto + + if [ "$sec_enable" == "0" ]; then + return + fi + + if [ "$proto" == "igmp" ]; then + igmp_p_enable=$sec_enable + config_get igmp_p_version "$config" version 2 + config_get igmp_query_interval "$config" query_interval 125 + config_get igmp_q_resp_interval "$config" query_response_interval 100 + config_get igmp_last_mem_q_int "$config" last_member_query_interval 10 + config_get igmp_fast_leave "$config" fast_leave 1 + config_get igmp_p_robustness "$config" robustness 2 + config_get igmp_p_mode "$config" snooping_mode 0 + config_get igmp_p_up_interfaces "$config" upstream_interface + config_get igmp_p_down_interfaces "$config" downstream_interface + config_get igmp_p_exceptions "$config" filter + return + fi + + if [ "$proto" == "mld" ]; then + mld_p_enable=$sec_enable + config_get mld_p_version "$config" version 2 + config_get mld_query_interval "$config" query_interval 125 + config_get mld_q_resp_interval "$config" query_response_interval 100 + config_get mld_last_mem_q_int "$config" last_member_query_interval 10 + config_get mld_fast_leave "$config" fast_leave 1 + config_get mld_p_robustness "$config" robustness 2 + config_get mld_p_mode "$config" snooping_mode 0 + config_get mld_p_up_interfaces "$config" upstream_interface + config_get mld_p_down_interfaces "$config" downstream_interface + config_get mld_p_exceptions "$config" filter + return + fi +} + +read_mcast_snooping_params() { + config_load mcast + config_foreach read_snooping snooping +} + +read_mcast_proxy_params() { + config_load mcast + config_foreach read_proxy proxy +} + +config_global_params() { + local igmp_qrv + local igmp_force_version + local mld_qrv + local mld_force_version + + config_load mcast + config_get max_msf igmp max_msf 10 + config_get max_groups igmp max_membership 25 + config_get igmp_qrv igmp qrv 2 + config_get igmp_force_version igmp force_version 0 + + config_get mld_qrv mld qrv 2 + config_get mldv1_unsolicited_report_interval mld mldv1_unsolicited_report_interval 10 + config_get mldv2_unsolicited_report_interval mld mldv2_unsolicited_report_interval 1 + config_get mld_force_version mld force_version 0 + + if [ "$1" == "set_max_groups_and_sources" ]; then + echo $max_groups > /proc/sys/net/ipv4/igmp_max_memberships + echo $max_msf > /proc/sys/net/ipv4/igmp_max_msf + echo $max_msf > /proc/sys/net/ipv6/mld_max_msf + fi + echo $igmp_qrv > /proc/sys/net/ipv4/igmp_qrv + echo $igmp_force_version > /proc/sys/net/ipv4/conf/all/force_igmp_version + + echo $mld_qrv > /proc/sys/net/ipv6/mld_qrv + echo $mld_force_version > /proc/sys/net/ipv6/conf/all/force_mld_version + echo $mldv1_unsolicited_report_interval > /proc/sys/net/ipv6/conf/all/mldv1_unsolicited_report_interval + echo $mldv2_unsolicited_report_interval > /proc/sys/net/ipv6/conf/all/mldv2_unsolicited_report_interval +} diff --git a/mcastmngr/files/linux/etc/firewall.mcast b/mcastmngr/files/linux/etc/firewall.mcast new file mode 100644 index 000000000..be8e428f0 --- /dev/null +++ b/mcastmngr/files/linux/etc/firewall.mcast @@ -0,0 +1,2 @@ +# Forward multicast packets from wan to lan +iptables -t filter -A zone_wan_forward -p udp -d 224.0.0.0/240.0.0.0 -m comment --comment "!fw3: Allow-Multicast-UDP" -j zone_lan_dest_ACCEPT diff --git a/mcastmngr/files/linux/etc/uci-defaults/60-mcast_config_generate b/mcastmngr/files/linux/etc/uci-defaults/60-mcast_config_generate new file mode 100644 index 000000000..e79d0ece8 --- /dev/null +++ b/mcastmngr/files/linux/etc/uci-defaults/60-mcast_config_generate @@ -0,0 +1,12 @@ +#!/bin/sh + +. /lib/functions.sh + +# Add firewall include instance +uci -q batch <<-EOT + delete firewall.mcast + set firewall.mcast=include + set firewall.mcast.path=/etc/firewall.mcast + set firewall.mcast.reload=1 + commit firewall +EOT diff --git a/mcastmngr/files/linux/lib/mcast/linux.sh b/mcastmngr/files/linux/lib/mcast/linux.sh old mode 100644 new mode 100755 index 4d9361361..3c4c7b201 --- a/mcastmngr/files/linux/lib/mcast/linux.sh +++ b/mcastmngr/files/linux/lib/mcast/linux.sh @@ -1,6 +1,149 @@ #!/bin/sh -configure_mcast() { - #TODO - return 0 +. /lib/mcast/common.sh + +include /lib/network + +CONFFILE= +PROG_EXE=/usr/sbin/mcproxy +PROG_PARAMS= +PROG_PARAMS_SEPARATOR=: + +setup_mcast_mode() { + unused(){ :;} +} + +config_mcproxy_interfaces() { + local upstreams="$1" + local downstreams="$2" + local exceptions="$3" + + local str_up="" + if [ -n "$upstreams" ]; then + for upstream in $upstreams; do + str_up="$str_up \"$upstream\"" + done + fi + + local str_down="" + if [ -n "$downstreams" ]; then + for downstream in $downstreams; do + str_down="$str_down \"$downstream\"" + done + fi + + if [ ! -z $downstream ]; then + echo -e "pinstance main:$str_up ==>$str_down;\n" >> $CONFFILE + fi + + + if [ -z "$exceptions" ] || [ -z "$upstreams" ]; then + return + fi + + for upstream in $upstreams; do + local filter="" + for excp in $exceptions; do + case $excp in + */*) + ip_start="$(ipcalc.sh $excp | grep IP | awk '{print substr($0,4)}')" + ip_end="$(ipcalc.sh $excp | grep BROADCAST | awk '{print substr($0,11)}')" + filter="$filter ($ip_start - $ip_end | *)" + ;; + *) + filter="$filter ($excp | *)" + ;; + esac + done + echo "pinstance main upstream \"$upstream\" in blacklist table{$filter };" >> $CONFFILE + echo "pinstance main upstream \"$upstream\" out blacklist table{$filter };" >> $CONFFILE + done +} + +config_mcproxy_instance() { + local protocol="$1" + local version="$2" + + local robustness= + local query_interval= + local q_resp_interval= + local last_mem_q_int= + local fast_leave=0 + local exceptions= + local upstreams= + local downstreams= + + CONFFILE=/var/etc/mcproxy_"$protocol".conf + rm -f $CONFFILE + touch $CONFFILE + + if [ "$protocol" == "igmp" ]; then + case "$version" in + [1-3]) + echo -e "protocol IGMPv${version};\n" >> $CONFFILE + ;; + *) + echo -e "protocol IGMPv2;\n" >> $CONFFILE + ;; + esac + + robustness=$igmp_p_robustness + query_interval=$igmp_query_interval + q_resp_interval=$igmp_q_resp_interval + last_mem_q_int=$igmp_last_mem_q_int + fast_leave=$igmp_fast_leave + exceptions=$igmp_p_exceptions + + upstreams=$igmp_p_up_interfaces + downstreams=$igmp_p_down_interfaces + elif [ "$protocol" == "mld" ]; then + case "$version" in + [1-2]) + echo -e "protocol MLDv${version};\n" >> $CONFFILE + ;; + *) + echo -e "protocol MLDv2;\n" >> $CONFFILE + ;; + esac + + robustness=$mld_p_robustness + query_interval=$mld_query_interval + q_resp_interval=$mld_q_resp_interval + last_mem_q_int=$mld_last_mem_q_int + fast_leave=$mld_fast_leave + exceptions=$mld_p_exceptions + + upstreams=$mld_p_up_interfaces + downstreams=$mld_p_down_interfaces + fi + + [ -n "$robustness" ] && echo -e "rv $robustness;" >> $CONFFILE + [ -n "$query_interval" ] && echo -e "qi $query_interval;" >> $CONFFILE + [ -n "$q_resp_interval" ] && echo -e "qri $q_resp_interval;" >> $CONFFILE + [ -n "$last_mem_q_int" ] && echo -e "lmqi $last_mem_q_int;" >> $CONFFILE + [ -n "$fast_leave" ] && echo -e "fastleave $fast_leave;\n" >> $CONFFILE + + [ -n "$upstreams" ] && [ -n "$downstreams" ] && + config_mcproxy_interfaces "$upstreams" "$downstreams" "$exceptions" + + PROG_PARAMS="${PROG_PARAMS} -f ${CONFFILE}${PROG_PARAMS_SEPARATOR}" +} + +config_mcproxy() { + if [ "$igmp_p_enable" == "1" ]; then + config_mcproxy_instance igmp "$igmp_p_version" + fi + + if [ "$mld_p_enable" == "1" ]; then + config_mcproxy_instance mld "$mld_p_version" + fi +} + +configure_mcast() { + config_global_params "set_max_groups_and_sources" + + read_mcast_snooping_params + read_mcast_proxy_params + + config_mcproxy }