From 442e3f9b5231c517a63dbbbbbae4ffa18d9a8292 Mon Sep 17 00:00:00 2001 From: Coiby Xu Date: Mon, 13 Sep 2021 22:13:44 +0800 Subject: [PATCH 01/11] Fix error for vlan over team network interface 6f9235887f7817085aabfcc67bf4a6d68e474264 ("module-setup.sh: enable vlan on team interface") skips establishing teaming network by mistake. Although it could use one of slave netifs to establish connection to transfer vmcore to remote fs, it breaks the implicit assumption of creating an identical network topology to the 1st kernel. Fixes: 6f92358 ("module-setup.sh: enable vlan on team interface") Signed-off-by: Coiby Xu --- dracut-module-setup.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh index 4c6096a..68fd9cb 100755 --- a/dracut-module-setup.sh +++ b/dracut-module-setup.sh @@ -437,6 +437,9 @@ kdump_setup_vlan() { elif kdump_is_bond "$_phydev"; then (kdump_setup_bond "$_phydev" "$(get_nmcli_connection_apath_by_ifname "$_phydev")") || exit 1 echo " vlan=$(kdump_setup_ifname "$_netdev"):$_phydev" > "${initdir}/etc/cmdline.d/43vlan.conf" + elif kdump_is_team "$_phydev"; then + (kdump_setup_team "$_phydev") || exit 1 + echo " vlan=$(kdump_setup_ifname "$_netdev"):$_phydev" > "${initdir}/etc/cmdline.d/43vlan.conf" else _kdumpdev="$(kdump_setup_ifname "$_phydev")" echo " vlan=$(kdump_setup_ifname "$_netdev"):$_kdumpdev ifname=$_kdumpdev:$_netmac" > "${initdir}/etc/cmdline.d/43vlan.conf" From 6039ac2ddaa1b7c6c3722fc31cca72206ad9b55e Mon Sep 17 00:00:00 2001 From: Coiby Xu Date: Thu, 9 Sep 2021 11:35:52 +0800 Subject: [PATCH 02/11] Add functions to copy NetworkManage connection profiles to the initramfs Each network interface is manged by a NM connection. Given a list of network interface names, copy the NetworkManager (NM) connection profiles i.e. .nmconnection files to the kdump initramfs. Signed-off-by: Coiby Xu --- dracut-module-setup.sh | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh index 68fd9cb..b46a5cb 100755 --- a/dracut-module-setup.sh +++ b/dracut-module-setup.sh @@ -346,6 +346,37 @@ kdump_setup_ifname() { echo "$_ifname" } +_install_nmconnections() { + local _dev _nmconnection_file_path _nmconnection_name _initrd_nmconnection_file_path + + for _dev in "${!nmconnection_map[@]}"; do + _nmconnection_file_path=${nmconnection_map[$_dev]} + _nmconnection_name=$(basename "$_nmconnection_file_path") + _initrd_nmconnection_file_path="/etc/NetworkManager/system-connections/$_nmconnection_name" + inst "$_nmconnection_file_path" "$_initrd_nmconnection_file_path" + done +} + + +kdump_install_nmconnections() { + declare -A nmconnection_map ipv4_usage ipv6_usage + local _netifs _netif + + _netifs=$1 + + for _netif in $_netifs; do + nmconnection_map[$_netif]=$_netif + done + + while IFS=: read -r _netif _nmconn; do + if [[ -v "nmconnection_map[$_netif]" ]] ; then + nmconnection_map[$_netif]="$_nmconn" + fi + done <<< "$(nmcli -t -f device,filename connection show --active)" + + _install_nmconnections +} + kdump_setup_bridge() { local _netdev=$1 local _brif _dev _mac _kdumpdev From 520a862c74073d439a5944b49cdc0056367a5868 Mon Sep 17 00:00:00 2001 From: Coiby Xu Date: Wed, 30 Mar 2022 08:50:42 +0800 Subject: [PATCH 03/11] Clone NM connection profiles to support legacy ifcfg automatically NetworkManager defaults to use keyfile i.e. .nmconnnection file but still supports reading ifcfg-* file [1]. Make use of "nmcli connection clone --temporary" to automatically convert a ifcfg-* file to a .nmconnection file. And it's also better to modify the cloned .nmconnection. [1] https://fedoraproject.org/wiki/Changes/NetworkManager_keyfile_instead_of_ifcfg_rh Signed-off-by: Coiby Xu --- dracut-module-setup.sh | 59 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh index b46a5cb..d9c5132 100755 --- a/dracut-module-setup.sh +++ b/dracut-module-setup.sh @@ -1,10 +1,21 @@ #!/bin/bash +_DRACUT_KDUMP_NM_TMP_DIR="/tmp/$$-DRACUT_KDUMP_NM" + +cleanup() { + rm -rf "$_DRACUT_KDUMP_NM_TMP_DIR" +} + +# shellcheck disable=SC2154 # known issue of shellcheck https://github.com/koalaman/shellcheck/issues/1299 +trap 'ret=$?; cleanup; exit $ret;' EXIT + kdump_module_init() { if ! [[ -d "${initdir}/tmp" ]]; then mkdir -p "${initdir}/tmp" fi + mkdir -p "$_DRACUT_KDUMP_NM_TMP_DIR" + . /lib/kdump/kdump-lib.sh } @@ -346,6 +357,50 @@ kdump_setup_ifname() { echo "$_ifname" } +_clone_nmconnection() { + local _clone_output _name _unique_id + + _unique_id=$1 + _name=$(nmcli --get-values connection.id connection show "$_unique_id") + if _clone_output=$(nmcli connection clone --temporary "$_unique_id" "$_name"); then + sed -E -n "s/.* \(.*\) cloned as.*\((.*)\)\.$/\1/p" <<< "$_clone_output" + return 0 + fi + + return 1 +} + +# Clone NM connection profiles +# +# This function makes use of "nmcli clone" to automatically convert ifcfg-* +# files to Networkmanager .nmconnection connection profiles and also modify the +# properties of .nmconnection if necessary. +clone_nmconnections() { + local _dev _cloned_nmconnection_file_path _tmp_nmconnection_file_path _old_uuid _uuid + + for _dev in "${!nmconnection_map[@]}"; do + _nmconnection_file_path=${nmconnection_map[$_dev]} + _old_uuid=$(nmcli --get-values connection.uuid connection show "$_nmconnection_file_path") + + if ! _uuid=$(_clone_nmconnection "$_old_uuid"); then + derror "Failed to clone $_old_uuid" + exit 1 + fi + + can_ipv4_or_ipv6_fail "$_uuid" "$_dev" + + _cloned_nmconnection_file_path=$(nmcli --get-values UUID,FILENAME connection show | sed -n "s/^${_uuid}://p") + _tmp_nmconnection_file_path=$_DRACUT_KDUMP_NM_TMP_DIR/$(basename "$_nmconnection_file_path") + cp "$_cloned_nmconnection_file_path" "$_tmp_nmconnection_file_path" + # change uuid back to old value in case it's refered by other connection + # profile e.g. connection.master could be interface name of the master + # device or UUID of the master connection. + sed -i -E "s/(^uuid=).*$/\1${_old_uuid}/g" "$_tmp_nmconnection_file_path" + nmconnection_map[$_dev]=$_tmp_nmconnection_file_path + nmcli connection del "$_uuid" &> >(ddebug) + done +} + _install_nmconnections() { local _dev _nmconnection_file_path _nmconnection_name _initrd_nmconnection_file_path @@ -374,6 +429,7 @@ kdump_install_nmconnections() { fi done <<< "$(nmcli -t -f device,filename connection show --active)" + clone_nmconnections _install_nmconnections } @@ -569,6 +625,8 @@ kdump_install_net() { local _static _proto _ip_conf _ip_opts _ifname_opts local _znet_netdev _znet_conpath + clone_nmconnections + _destaddr=$(kdump_get_remote_ip "$1") _route=$(kdump_get_ip_route "$_destaddr") _srcaddr=$(kdump_get_ip_route_field "$_route" "src") @@ -639,6 +697,7 @@ kdump_install_net() { echo "kdumpnic=$kdumpnic" > "${initdir}/etc/cmdline.d/60kdumpnic.conf" echo "bootdev=$kdumpnic" > "${initdir}/etc/cmdline.d/70bootdev.conf" fi + } # install etc/kdump/pre.d and /etc/kdump/post.d From 31daf710afac78ac8e277d9cdc4242bcb6825d27 Mon Sep 17 00:00:00 2001 From: Coiby Xu Date: Thu, 8 Sep 2022 17:06:19 +0800 Subject: [PATCH 04/11] Determine whether IPv4 or IPv6 is needed According to `man nm-online`, "By default, connections have the ipv4.may-fail and ipv6.may-fail properties set to yes; this means that NetworkManager waits for one of the two address families to complete configuration before considering the connection activated. If you need a specific address family configured before network-online.target is reached, set the corresponding may-fail property to no." If a NIC has an IPv4 or IPv6 address, set the corresponding may-fail property to no. Otherwise, dumping vmcore over IPv6 could fail because only IPv4 network is ready or vice versa. If only IPv4 is used, disable IPv6 otherwise and vice versa. Signed-off-by: Coiby Xu --- dracut-module-setup.sh | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh index d9c5132..5a5000d 100755 --- a/dracut-module-setup.sh +++ b/dracut-module-setup.sh @@ -357,6 +357,24 @@ kdump_setup_ifname() { echo "$_ifname" } +use_ipv4_or_ipv6() { + local _netif=$1 _uuid=$2 + + if [[ -v "ipv4_usage[$_netif]" ]]; then + nmcli connection modify --temporary "$_uuid" ipv4.may-fail no &> >(ddebug) + fi + + if [[ -v "ipv6_usage[$_netif]" ]]; then + nmcli connection modify --temporary "$_uuid" ipv6.may-fail no &> >(ddebug) + fi + + if [[ -v "ipv4_usage[$_netif]" ]] && [[ ! -v "ipv6_usage[$_netif]" ]]; then + nmcli connection modify --temporary "$_uuid" ipv4.method disabled &> >(ddebug) + elif [[ ! -v "ipv4_usage[$_netif]" ]] && [[ -v "ipv6_usage[$_netif]" ]]; then + nmcli connection modify --temporary "$_uuid" ipv6.method disabled &> >(ddebug) + fi +} + _clone_nmconnection() { local _clone_output _name _unique_id @@ -387,7 +405,7 @@ clone_nmconnections() { exit 1 fi - can_ipv4_or_ipv6_fail "$_uuid" "$_dev" + use_ipv4_or_ipv6 "$_uuid" "$_dev" _cloned_nmconnection_file_path=$(nmcli --get-values UUID,FILENAME connection show | sed -n "s/^${_uuid}://p") _tmp_nmconnection_file_path=$_DRACUT_KDUMP_NM_TMP_DIR/$(basename "$_nmconnection_file_path") @@ -429,6 +447,14 @@ kdump_install_nmconnections() { fi done <<< "$(nmcli -t -f device,filename connection show --active)" + while IFS=: read -r _ifname _ip_proc; do + if [[ $_ip_proc == 6 ]]; then + ipv6_usage[$_ifname]=1 + elif [[ $_ip_proc == 4 ]]; then + ipv4_usage[$_ifname]=1 + fi + done < $_TMP_KDUMP_NETIFS_IPv46 + clone_nmconnections _install_nmconnections } From 05f4ad14bb915e9423bbf610ae7d009d44bbc0c7 Mon Sep 17 00:00:00 2001 From: Coiby Xu Date: Thu, 8 Sep 2022 17:27:42 +0800 Subject: [PATCH 05/11] Truly wait for network connectivity to be established nm-wait-online-initrd.service installed by dracut's 35-networkmanager module calls nm-online with "-s" which means it returns immediately when NetworkManager logs "startup complete". Thus it doesn't truly wait for network connectivity to be established [1]. Remove "-s" to avoid this undesirable effect. There are two benefits brought by this approach, - ssh/nfs dumping won't fail because of that the network is not ready [2] - users don't need to use workarounds like rd.net.carrier.timeout to make sure network is ready [1] https://bugzilla.redhat.com/show_bug.cgi?id=1485712 [2] https://bugzilla.redhat.com/show_bug.cgi?id=1909014 Signed-off-by: Coiby Xu --- dracut-module-setup.sh | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh index 5a5000d..b2951a0 100755 --- a/dracut-module-setup.sh +++ b/dracut-module-setup.sh @@ -375,6 +375,19 @@ use_ipv4_or_ipv6() { fi } +# nm-wait-online-initrd.service installed by dracut's 35-networkmanager +# module call nm-online with "-s" thus it doesn't wait for network connectivity +# to be established. Remove "-s" to avoid this undesirable effect. +wait_for_network_connectivity() { + local _nm_wait_online_service_file + + _nm_wait_online_service_file="$initdir/usr/lib/systemd/system/nm-wait-online-initrd.service" + [[ ! -f $_nm_wait_online_service_file ]] && return + + sed -i -E "/^ExecStart=\/usr\/bin\/nm-online/ { + s/ -s / /;}" "$_nm_wait_online_service_file" +} + _clone_nmconnection() { local _clone_output _name _unique_id @@ -1197,6 +1210,8 @@ install() { inst "ip" fi + wait_for_network_connectivity + # For the lvm type target under kdump, in /etc/lvm/lvm.conf we can # safely replace "reserved_memory=XXXX"(default value is 8192) with # "reserved_memory=1024" to lower memory pressure under kdump. We do From f9c5e17eb7fa77a2521bd9b175276f4bf0f7aa84 Mon Sep 17 00:00:00 2001 From: Coiby Xu Date: Fri, 17 Sep 2021 13:02:07 +0800 Subject: [PATCH 06/11] Stop dracut 35network-manager from running nm-initrd-generator kexec-tools depends on dracut's 35network-manager module which will call nm-initrd-generator. We don't want nm-initrd-generator to generate connection profiles since we will copy them from 1st kernel to kdump kernel initramfs. NetworkManager >= 1.35.2 won't generate connection profiles if there's a connection dir with rd.neednet. For Fedora/RHEL, this connection dir is /etc/NetworkManager/system-connections. For the details, please refer to the NetworkManager commit 79885656d3 ("initrd: don't add a connection if there's a connection dir with rd.neednet") [1]. Before the release of NetworkManager >= 1.35.2, we need to mask /usr/libexec/nm-initrd-generator. [1] https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1010 Signed-off-by: Coiby Xu --- dracut-module-setup.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh index b2951a0..8cfcbb0 100755 --- a/dracut-module-setup.sh +++ b/dracut-module-setup.sh @@ -664,8 +664,6 @@ kdump_install_net() { local _static _proto _ip_conf _ip_opts _ifname_opts local _znet_netdev _znet_conpath - clone_nmconnections - _destaddr=$(kdump_get_remote_ip "$1") _route=$(kdump_get_ip_route "$_destaddr") _srcaddr=$(kdump_get_ip_route_field "$_route" "src") @@ -724,6 +722,11 @@ kdump_install_net() { echo "rd.neednet" >> "${initdir}/etc/cmdline.d/50neednet.conf" fi + # Stop dracut 35network-manger to calling nm-initrd-generator. + # Note this line of code can be removed after NetworkManager >= 1.35.2 + # gets released. + echo > "${initdir}/usr/libexec/nm-initrd-generator" + # Save netdev used for kdump as cmdline # Whoever calling kdump_install_net() is setting up the default gateway, # ie. bootdev/kdumpnic. So don't override the setting if calling From 197babd57aed4f5c984c8e49d60403bc2c7cb47f Mon Sep 17 00:00:00 2001 From: Coiby Xu Date: Thu, 9 Sep 2021 12:23:57 +0800 Subject: [PATCH 07/11] Set up kdump network by directly copying NM connection profile to initrd This patch setup kdump network by directly copying NM connection profile(s) for different network setup including bond, bridge, vlan, and team. For vlan network, rename phydev to parent_netif to improve code readability. With the new approach, the related code to build up dracut cmdline parameter such rd.route, ip and etc can be cleaned up. And there is no need to to setup dns when copying .nmconnection directly to initrd either. Note the bootdev dracut command line parameter is only used by dracut's 35network-legacy and network-manager doesn't use it, remove related code as well. Signed-off-by: Coiby Xu --- dracut-module-setup.sh | 266 +++++++---------------------------------- 1 file changed, 43 insertions(+), 223 deletions(-) diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh index 8cfcbb0..38fe87d 100755 --- a/dracut-module-setup.sh +++ b/dracut-module-setup.sh @@ -2,6 +2,13 @@ _DRACUT_KDUMP_NM_TMP_DIR="/tmp/$$-DRACUT_KDUMP_NM" +_TMP_KDUMP_NETIFS="$_DRACUT_KDUMP_NM_TMP_DIR/kdump_netifs" +_TMP_KDUMP_NETIFS_IPv46="$_DRACUT_KDUMP_NM_TMP_DIR/kdump_netifs_ipv46" + +_save_kdump_netifs() { + echo -n " $1" >> "$_TMP_KDUMP_NETIFS" +} + cleanup() { rm -rf "$_DRACUT_KDUMP_NM_TMP_DIR" } @@ -15,6 +22,8 @@ kdump_module_init() { fi mkdir -p "$_DRACUT_KDUMP_NM_TMP_DIR" + echo -n > "$_TMP_KDUMP_NETIFS" + echo -n > "$_TMP_KDUMP_NETIFS_IPv46" . /lib/kdump/kdump-lib.sh } @@ -95,39 +104,6 @@ source_ifcfg_file() { fi } -kdump_setup_dns() { - local _netdev="$1" - local _conpath="$2" - local _nameserver _dns _tmp array - local _dnsfile=${initdir}/etc/cmdline.d/42dns.conf - - _tmp=$(get_nmcli_field_by_conpath "IP4.DNS" "$_conpath") - # shellcheck disable=SC2206 - array=(${_tmp//|/ }) - if [[ ${array[*]} ]]; then - for _dns in "${array[@]}"; do - echo "nameserver=$_dns" >> "$_dnsfile" - done - else - dwarning "Failed to get DNS info via nmcli output. Now try sourcing ifcfg script" - source_ifcfg_file "$_netdev" - [[ -n $DNS1 ]] && echo "nameserver=$DNS1" > "$_dnsfile" - [[ -n $DNS2 ]] && echo "nameserver=$DNS2" >> "$_dnsfile" - fi - - while read -r content; do - _nameserver=$(echo "$content" | grep ^nameserver) - [[ -z $_nameserver ]] && continue - - _dns=$(echo "$_nameserver" | awk '{print $2}') - [[ -z $_dns ]] && continue - - if [[ ! -f $_dnsfile ]] || ! grep -q "$_dns" "$_dnsfile"; then - echo "nameserver=$_dns" >> "$_dnsfile" - fi - done < "/etc/resolv.conf" -} - # $1: repeat times # $2: string to be repeated # $3: separator @@ -238,89 +214,6 @@ cal_netmask_by_prefix() { fi } -#$1: netdev name -#$2: srcaddr -#if it use static ip echo it, or echo null -kdump_static_ip() { - local _netdev="$1" _srcaddr="$2" kdumpnic="$3" _ipv6_flag - local _netmask _gateway _ipaddr _target _nexthop _prefix - - _ipaddr=$(ip addr show dev "$_netdev" permanent | awk "/ $_srcaddr\/.* /{print \$2}") - - if is_ipv6_address "$_srcaddr"; then - _ipv6_flag="-6" - fi - - if [[ -n $_ipaddr ]]; then - _gateway=$(ip $_ipv6_flag route list dev "$_netdev" \ - | awk '/^default /{print $3}' | head -n 1) - - if [[ "x" != "x"$_ipv6_flag ]]; then - # _ipaddr="2002::56ff:feb6:56d5/64", _netmask is the number after "/" - _netmask=${_ipaddr#*\/} - _srcaddr="[$_srcaddr]" - _gateway="[$_gateway]" - else - _prefix=$(cut -d'/' -f2 <<< "$_ipaddr") - if ! _netmask=$(cal_netmask_by_prefix "$_prefix" "$_ipv6_flag"); then - derror "Failed to calculate netmask for $_ipaddr" - exit 1 - fi - fi - echo -n "${_srcaddr}::${_gateway}:${_netmask}::" - fi - - /sbin/ip $_ipv6_flag route show | grep -v default \ - | grep ".*via.* $_netdev " | grep -v "^[[:space:]]*nexthop" \ - | while read -r _route; do - _target=$(echo "$_route" | awk '{print $1}') - _nexthop=$(echo "$_route" | awk '{print $3}') - if [[ "x" != "x"$_ipv6_flag ]]; then - _target="[$_target]" - _nexthop="[$_nexthop]" - fi - echo "rd.route=$_target:$_nexthop:$kdumpnic" - done >> "${initdir}/etc/cmdline.d/45route-static.conf" - - kdump_handle_mulitpath_route "$_netdev" "$_srcaddr" "$kdumpnic" -} - -kdump_handle_mulitpath_route() { - local _netdev="$1" _srcaddr="$2" kdumpnic="$3" _ipv6_flag - local _target _nexthop _route _weight _max_weight _rule - - if is_ipv6_address "$_srcaddr"; then - _ipv6_flag="-6" - fi - - while IFS="" read -r _route; do - if [[ $_route =~ [[:space:]]+nexthop ]]; then - _route=${_route##[[:space:]]} - # Parse multipath route, using previous _target - [[ $_target == 'default' ]] && continue - [[ $_route =~ .*via.*\ $_netdev ]] || continue - - _weight=$(echo "$_route" | cut -d ' ' -f7) - if [[ $_weight -gt $_max_weight ]]; then - _nexthop=$(echo "$_route" | cut -d ' ' -f3) - _max_weight=$_weight - if [[ "x" != "x"$_ipv6_flag ]]; then - _rule="rd.route=[$_target]:[$_nexthop]:$kdumpnic" - else - _rule="rd.route=$_target:$_nexthop:$kdumpnic" - fi - fi - else - [[ -n $_rule ]] && echo "$_rule" - _target=$(echo "$_route" | cut -d ' ' -f1) - _rule="" _max_weight=0 _weight=0 - fi - done >> "${initdir}/etc/cmdline.d/45route-static.conf" \ - <<< "$(/sbin/ip $_ipv6_flag route show)" - - [[ -n $_rule ]] && echo "$_rule" >> "${initdir}/etc/cmdline.d/45route-static.conf" -} - kdump_get_mac_addr() { cat "/sys/class/net/$1/address" } @@ -443,7 +336,6 @@ _install_nmconnections() { done } - kdump_install_nmconnections() { declare -A nmconnection_map ipv4_usage ipv6_usage local _netifs _netif @@ -474,102 +366,55 @@ kdump_install_nmconnections() { kdump_setup_bridge() { local _netdev=$1 - local _brif _dev _mac _kdumpdev + local _dev for _dev in "/sys/class/net/$_netdev/brif/"*; do [[ -e $_dev ]] || continue _dev=${_dev##*/} - _kdumpdev=$_dev if kdump_is_bond "$_dev"; then - (kdump_setup_bond "$_dev" "$(get_nmcli_connection_apath_by_ifname "$_dev")") || exit 1 + (kdump_setup_bond "$_dev") || exit 1 elif kdump_is_team "$_dev"; then kdump_setup_team "$_dev" elif kdump_is_vlan "$_dev"; then kdump_setup_vlan "$_dev" - else - _mac=$(kdump_get_mac_addr "$_dev") - _kdumpdev=$(kdump_setup_ifname "$_dev") - echo -n " ifname=$_kdumpdev:$_mac" >> "${initdir}/etc/cmdline.d/41bridge.conf" fi - _brif+="$_kdumpdev," + _save_kdump_netifs "$_dev" done - echo " bridge=$_netdev:${_brif%,}" >> "${initdir}/etc/cmdline.d/41bridge.conf" } -# drauct takes bond=[::[:]] syntax to parse -# bond. For example: -# bond=bond0:eth0,eth1:mode=balance-rr kdump_setup_bond() { local _netdev="$1" - local _conpath="$2" - local _dev _mac _slaves _kdumpdev _bondoptions - for _dev in $(cat "/sys/class/net/$_netdev/bonding/slaves"); do - _mac=$(kdump_get_perm_addr "$_dev") - _kdumpdev=$(kdump_setup_ifname "$_dev") - echo -n " ifname=$_kdumpdev:$_mac" >> "${initdir}/etc/cmdline.d/42bond.conf" - _slaves+="$_kdumpdev," + local _dev + + for _dev in $(< "/sys/class/net/$_netdev/bonding/slaves"); do + _save_kdump_netifs "$_dev" done - echo -n " bond=$_netdev:${_slaves%,}" >> "${initdir}/etc/cmdline.d/42bond.conf" - - _bondoptions=$(get_nmcli_field_by_conpath "bond.options" "$_conpath") - - if [[ -z $_bondoptions ]]; then - dwarning "Failed to get bond configuration via nmlci output. Now try sourcing ifcfg script." - source_ifcfg_file "$_netdev" - _bondoptions="$(echo "$BONDING_OPTS" | xargs echo | tr " " ",")" - fi - - if [[ -z $_bondoptions ]]; then - derror "Get empty bond options" - exit 1 - fi - - echo ":$_bondoptions" >> "${initdir}/etc/cmdline.d/42bond.conf" } kdump_setup_team() { local _netdev=$1 - local _dev _mac _slaves _kdumpdev + local _dev for _dev in $(teamnl "$_netdev" ports | awk -F':' '{print $2}'); do - _mac=$(kdump_get_perm_addr "$_dev") - _kdumpdev=$(kdump_setup_ifname "$_dev") - echo -n " ifname=$_kdumpdev:$_mac" >> "${initdir}/etc/cmdline.d/44team.conf" - _slaves+="$_kdumpdev," + _save_kdump_netifs "$_dev" done - echo " team=$_netdev:${_slaves%,}" >> "${initdir}/etc/cmdline.d/44team.conf" - #Buggy version teamdctl outputs to stderr! - #Try to use the latest version of teamd. - if ! teamdctl "$_netdev" config dump > "${initdir}/tmp/$$-$_netdev.conf"; then - derror "teamdctl failed." - exit 1 - fi - inst_dir /etc/teamd - inst_simple "${initdir}/tmp/$$-$_netdev.conf" "/etc/teamd/$_netdev.conf" - rm -f "${initdir}/tmp/$$-$_netdev.conf" } kdump_setup_vlan() { local _netdev=$1 - local _phydev - local _netmac - local _kdumpdev + local _parent_netif - _phydev="$(awk '/^Device:/{print $2}' /proc/net/vlan/"$_netdev")" - _netmac="$(kdump_get_mac_addr "$_phydev")" + _parent_netif="$(awk '/^Device:/{print $2}' /proc/net/vlan/"$_netdev")" #Just support vlan over bond and team - if kdump_is_bridge "$_phydev"; then + if kdump_is_bridge "$_parent_netif"; then derror "Vlan over bridge is not supported!" exit 1 - elif kdump_is_bond "$_phydev"; then - (kdump_setup_bond "$_phydev" "$(get_nmcli_connection_apath_by_ifname "$_phydev")") || exit 1 - echo " vlan=$(kdump_setup_ifname "$_netdev"):$_phydev" > "${initdir}/etc/cmdline.d/43vlan.conf" - elif kdump_is_team "$_phydev"; then - (kdump_setup_team "$_phydev") || exit 1 - echo " vlan=$(kdump_setup_ifname "$_netdev"):$_phydev" > "${initdir}/etc/cmdline.d/43vlan.conf" - else - _kdumpdev="$(kdump_setup_ifname "$_phydev")" - echo " vlan=$(kdump_setup_ifname "$_netdev"):$_kdumpdev ifname=$_kdumpdev:$_netmac" > "${initdir}/etc/cmdline.d/43vlan.conf" + elif kdump_is_bond "$_parent_netif"; then + (kdump_setup_bond "$_parent_netif") || exit 1 + elif kdump_is_team "$_parent_netif"; then + (kdump_setup_team "$_parent_netif") || exit 1 fi + + _save_kdump_netifs "$_parent_netif" } # find online znet device @@ -660,16 +505,13 @@ kdump_get_remote_ip() { # initramfs accessing giving destination # $1: destination host kdump_install_net() { - local _destaddr _srcaddr _route _netdev _conpath kdumpnic - local _static _proto _ip_conf _ip_opts _ifname_opts + local _destaddr _srcaddr _route _netdev kdumpnic _ip_proc local _znet_netdev _znet_conpath _destaddr=$(kdump_get_remote_ip "$1") _route=$(kdump_get_ip_route "$_destaddr") _srcaddr=$(kdump_get_ip_route_field "$_route" "src") _netdev=$(kdump_get_ip_route_field "$_route" "dev") - _conpath=$(get_nmcli_connection_apath_by_ifname "$_netdev") - _netmac=$(kdump_get_mac_addr "$_netdev") kdumpnic=$(kdump_setup_ifname "$_netdev") _znet_netdev=$(find_online_znet_device) @@ -681,41 +523,16 @@ kdump_install_net() { fi fi - _static=$(kdump_static_ip "$_netdev" "$_srcaddr" "$kdumpnic") - if [[ -n $_static ]]; then - _proto=none - elif is_ipv6_address "$_srcaddr"; then - _proto=auto6 - else - _proto=dhcp - fi - - _ip_conf="${initdir}/etc/cmdline.d/40ip.conf" - _ip_opts=" ip=${_static}$kdumpnic:${_proto}" - - # dracut doesn't allow duplicated configuration for same NIC, even they're exactly the same. - # so we have to avoid adding duplicates - # We should also check /proc/cmdline for existing ip=xx arg. - # For example, iscsi boot will specify ip=xxx arg in cmdline. - if [[ ! -f $_ip_conf ]] || ! grep -q "$_ip_opts" "$_ip_conf" \ - && ! grep -q "ip=[^[:space:]]*$_netdev" /proc/cmdline; then - echo "$_ip_opts" >> "$_ip_conf" - fi - if kdump_is_bridge "$_netdev"; then kdump_setup_bridge "$_netdev" elif kdump_is_bond "$_netdev"; then - (kdump_setup_bond "$_netdev" "$_conpath") || exit 1 + (kdump_setup_bond "$_netdev") || exit 1 elif kdump_is_team "$_netdev"; then kdump_setup_team "$_netdev" elif kdump_is_vlan "$_netdev"; then kdump_setup_vlan "$_netdev" - else - _ifname_opts=" ifname=$kdumpnic:$_netmac" - echo "$_ifname_opts" >> "$_ip_conf" fi - - kdump_setup_dns "$_netdev" "$_conpath" + _save_kdump_netifs "$_netdev" if [[ ! -f ${initdir}/etc/cmdline.d/50neednet.conf ]]; then # network-manager module needs this parameter @@ -727,19 +544,17 @@ kdump_install_net() { # gets released. echo > "${initdir}/usr/libexec/nm-initrd-generator" - # Save netdev used for kdump as cmdline - # Whoever calling kdump_install_net() is setting up the default gateway, - # ie. bootdev/kdumpnic. So don't override the setting if calling - # kdump_install_net() for another time. For example, after setting eth0 as - # the default gate way for network dump, eth1 in the fence kdump path will - # call kdump_install_net again and we don't want eth1 to be the default - # gateway. - if [[ ! -f ${initdir}/etc/cmdline.d/60kdumpnic.conf ]] \ - && [[ ! -f ${initdir}/etc/cmdline.d/70bootdev.conf ]]; then + if [[ ! -f ${initdir}/etc/cmdline.d/60kdumpnic.conf ]]; then echo "kdumpnic=$kdumpnic" > "${initdir}/etc/cmdline.d/60kdumpnic.conf" - echo "bootdev=$kdumpnic" > "${initdir}/etc/cmdline.d/70bootdev.conf" fi + if is_ipv6_address "$_srcaddr"; then + _ip_proc=6 + else + _ip_proc=4 + fi + + echo "$_netdev" "$_ip_proc" >> "$_TMP_KDUMP_NETIFS_IPv46" } # install etc/kdump/pre.d and /etc/kdump/post.d @@ -1215,6 +1030,11 @@ install() { wait_for_network_connectivity + _netifs=$(cat "$_TMP_KDUMP_NETIFS") + if [[ -n "$_netifs" ]]; then + kdump_install_nmconnections "$_netifs" + fi + # For the lvm type target under kdump, in /etc/lvm/lvm.conf we can # safely replace "reserved_memory=XXXX"(default value is 8192) with # "reserved_memory=1024" to lower memory pressure under kdump. We do From 38108118fdf9f00b0c929475e382a3c692d5e0fb Mon Sep 17 00:00:00 2001 From: Coiby Xu Date: Thu, 9 Sep 2021 11:50:00 +0800 Subject: [PATCH 08/11] Reduce kdump memory consumption by not letting NetworkManager manage unneeded network interfaces By default, NetworkManger will manage all the network interfaces and try to set interface IFF_UP to get carrier state. Regardless of whether the network interface is connected to a cable or not, the NIC driver will allocate memory resources for e.g. ring buffers when setting IFF_UP. This could be a waste of memory. For example it's found i40e consumes ~15GB on a power machine. On this machine, i40e manages four interfaces but only one interface is valid. This patch use "managed=false" to tell NetworkManager to not manage network interfaces that are not needed by kdump by putting /etc/NetworkManager/conf.d/10-kdump-netif.conf in the initramfs. Signed-off-by: Coiby Xu --- dracut-module-setup.sh | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh index 38fe87d..9634eac 100755 --- a/dracut-module-setup.sh +++ b/dracut-module-setup.sh @@ -1,7 +1,6 @@ #!/bin/bash _DRACUT_KDUMP_NM_TMP_DIR="/tmp/$$-DRACUT_KDUMP_NM" - _TMP_KDUMP_NETIFS="$_DRACUT_KDUMP_NM_TMP_DIR/kdump_netifs" _TMP_KDUMP_NETIFS_IPv46="$_DRACUT_KDUMP_NM_TMP_DIR/kdump_netifs_ipv46" @@ -364,6 +363,29 @@ kdump_install_nmconnections() { _install_nmconnections } +kdump_install_nm_netif_allowlist() { + local _netif _except_netif _netif_allowlist _netif_allowlist_nm_conf + + for _netif in $1; do + _per_mac=$(kdump_get_perm_addr "$_netif") + if [[ "$_per_mac" != 'not set' ]]; then + _except_netif="mac:$_per_mac" + else + _except_netif="interface-name:$_netif" + fi + _netif_allowlist="${_netif_allowlist}except:${_except_netif};" + done + + _netif_allowlist_nm_conf=$_DRACUT_KDUMP_NM_TMP_DIR/netif_allowlist_nm_conf + cat <<- EOF > "$_netif_allowlist_nm_conf" + [device-others] + match-device=${_netif_allowlist} + managed=false + EOF + + inst "$_netif_allowlist_nm_conf" "/etc/NetworkManager/conf.d/10-kdump-netif.conf" +} + kdump_setup_bridge() { local _netdev=$1 local _dev @@ -969,7 +991,7 @@ remove_cpu_online_rule() { } install() { - local arch + local arch _netifs kdump_module_init kdump_install_conf @@ -1033,6 +1055,7 @@ install() { _netifs=$(cat "$_TMP_KDUMP_NETIFS") if [[ -n "$_netifs" ]]; then kdump_install_nmconnections "$_netifs" + kdump_install_nm_netif_allowlist "$_netifs" fi # For the lvm type target under kdump, in /etc/lvm/lvm.conf we can From 92184499dfd0918bb5971508af89fa4a26ad4085 Mon Sep 17 00:00:00 2001 From: Coiby Xu Date: Thu, 19 May 2022 11:39:25 +0800 Subject: [PATCH 09/11] Reduce kdump memory consumption by only installing needed NIC drivers Even after having asked NM to stop managing a unneeded NIC, a NIC driver may still waste memory. For example, mlx5_core uses a substantial amount of memory during driver initialization, ======== Report format module_summary: ======== Module mlx5_core using 350.2MB (89650 pages), peak allocation 367.4MB (94056 pages) Module squashfs using 13.1MB (3360 pages), peak allocation 13.1MB (3360 pages) Module overlay using 2.1MB (550 pages), peak allocation 2.2MB (555 pages) Module dns_resolver using 0.9MB (219 pages), peak allocation 5.2MB (1338 pages) Module mlxfw using 0.7MB (172 pages), peak allocation 5.3MB (1349 pages) ======== Report format module_summary END ======== ======== Report format module_top: ======== Top stack usage of module mlx5_core: (null) Pages: 89650 (peak: 94056) ret_from_fork (0xffffda088b4165f8) Pages: 60007 (peak: 60007) kthread (0xffffda088b4bd7e4) Pages: 60007 (peak: 60007) worker_thread (0xffffda088b4b48d0) Pages: 60007 (peak: 60007) process_one_work (0xffffda088b4b3f40) Pages: 60007 (peak: 60007) work_for_cpu_fn (0xffffda088b4aef00) Pages: 53906 (peak: 53906) local_pci_probe (0xffffda088b9e1e44) Pages: 53906 (peak: 53906) probe_one mlx5_core (0xffffda084f899cc8) Pages: 53518 (peak: 53518) mlx5_init_one mlx5_core (0xffffda084f8994ac) Pages: 49756 (peak: 49756) mlx5_function_setup.constprop.0 mlx5_core (0xffffda084f899100) Pages: 44434 (eak: 44434) mlx5_satisfy_startup_pages mlx5_core (0xffffda084f8a4f24) Pages: 44434 (peak: 44434) mlx5_function_setup.constprop.0 mlx5_core (0xffffda084f899078) Pages: 5285 (peak: 5285) mlx5_cmd_init mlx5_core (0xffffda084f89e414) Pages: 4818 (peak: 4818) mlx5_alloc_cmd_msg mlx5_core (0xffffda084f89aaa0) Pages: 4403 (peak: 4403) This memory consumption is completely unnecessary when kdump doesn't need this NIC. Only install needed NIC drivers to prevent this kind of waste. Note 1. this patch depends on [1] to ask dracut to not install NIC drivers. 2. "ethtool -i" somehow fails to get the vlan driver 3. team.ko doesn't depend on the team mode drivers so we need to install the team mode drivers manually. [1] https://github.com/dracutdevs/dracut/pull/1789 Signed-off-by: Coiby Xu --- dracut-module-setup.sh | 31 +++++++++++++++++++++++++++++++ mkdumprd | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh index 9634eac..477c38d 100755 --- a/dracut-module-setup.sh +++ b/dracut-module-setup.sh @@ -386,6 +386,36 @@ kdump_install_nm_netif_allowlist() { inst "$_netif_allowlist_nm_conf" "/etc/NetworkManager/conf.d/10-kdump-netif.conf" } +_get_nic_driver() { + ethtool -i "$1" | sed -n -E "s/driver: (.*)/\1/p" +} + +kdump_install_nic_driver() { + local _netif _driver _drivers + + _drivers=() + + for _netif in $1; do + _driver=$(_get_nic_driver "$_netif") + if [[ -z $_driver ]]; then + derror "Failed to get the driver of $_netif" + exit 1 + fi + + if [[ $_driver == "802.1Q VLAN Support" ]]; then + # ethtool somehow doesn't return the driver name for a VLAN NIC + _driver=8021q + elif [[ $_driver == "team" ]]; then + # install the team mode drivers like team_mode_roundrobin.ko as well + _driver='=drivers/net/team' + fi + + _drivers+=("$_driver") + done + + instmods "${_drivers[@]}" +} + kdump_setup_bridge() { local _netdev=$1 local _dev @@ -1056,6 +1086,7 @@ install() { if [[ -n "$_netifs" ]]; then kdump_install_nmconnections "$_netifs" kdump_install_nm_netif_allowlist "$_netifs" + kdump_install_nic_driver "$_netifs" fi # For the lvm type target under kdump, in /etc/lvm/lvm.conf we can diff --git a/mkdumprd b/mkdumprd index 3e250e0..4a40f86 100644 --- a/mkdumprd +++ b/mkdumprd @@ -27,7 +27,7 @@ SAVE_PATH=$(get_save_path) OVERRIDE_RESETTABLE=0 extra_modules="" -dracut_args=(--add kdumpbase --quiet --hostonly --hostonly-cmdline --hostonly-i18n --hostonly-mode strict -o "plymouth resume ifcfg earlykdump") +dracut_args=(--add kdumpbase --quiet --hostonly --hostonly-cmdline --hostonly-i18n --hostonly-mode strict --hostonly-nics '' -o "plymouth resume ifcfg earlykdump") MKDUMPRD_TMPDIR="$(mktemp -d -t mkdumprd.XXXXXX)" [ -d "$MKDUMPRD_TMPDIR" ] || perror_exit "dracut: mktemp -p -d -t dracut.XXXXXX failed." From 8ac940570d516e6370faab98536a75b856131332 Mon Sep 17 00:00:00 2001 From: Coiby Xu Date: Thu, 23 Sep 2021 14:25:01 +0800 Subject: [PATCH 10/11] Address the cases where a NIC has a different name in kdump kernel A NIC may get a different name in the kdump kernel from 1st kernel in cases like, - kernel assigned network interface names are not persistent e.g. [1] - there is an udev rule to rename the NIC in the 1st kernel but the kdump initrd may not have that rule e.g. [2] If NM tries to match a NIC with a connection profile based on NIC name i.e. connection.interface-name, it will fail the above bases. A simple solution is to ask NM to match a connection profile by MAC address. Note we don't need to do this for user-created NICs like vlan, bridge and bond. An remaining issue is passing the name of a NIC via the kdumpnic dracut command line parameter which requires passing ifname=: to have fixed NIC name. But we can simply drop this requirement. kdumpnic is needed because kdump needs to get the IP by NIC name and use the IP to created a dumping folder named "{IP}-{DATE}". We can simply pass the IP to the kdump kernel directly via a new dracut command line parameter kdumpip instead. In addition to the benefit of simplifying the code, there are other three benefits brought by this approach, - make use of whatever network to transfer the vmcore. Because as long as we have the network to we don't care which NIC is active. - if obtained IP in the kdump kernel is different from the one in the 1st kernel. "{IP}-{DATE}" would better tell where the dumped vmcore comes from. - without passing ifname=: to kdump initrd, the issue of there are two interfaces with the same MAC address for Azure Hyper-V NIC SR-IOV [3] is resolved automatically. [1] https://bugzilla.redhat.com/show_bug.cgi?id=1121778 [2] https://bugzilla.redhat.com/show_bug.cgi?id=810107 [3] https://bugzilla.redhat.com/show_bug.cgi?id=1962421 Signed-off-by: Coiby Xu --- dracut-kdump.sh | 39 +++++++++++++++------------- dracut-module-setup.sh | 58 +++++++++++++++--------------------------- kdump-lib-initramfs.sh | 14 ++++++++++ 3 files changed, 56 insertions(+), 55 deletions(-) diff --git a/dracut-kdump.sh b/dracut-kdump.sh index f4456a1..6708924 100755 --- a/dracut-kdump.sh +++ b/dracut-kdump.sh @@ -478,25 +478,28 @@ save_vmcore_dmesg_ssh() get_host_ip() { - if is_nfs_dump_target || is_ssh_dump_target; then - kdumpnic=$(getarg kdumpnic=) - if [ -z "$kdumpnic" ]; then - derror "failed to get kdumpnic!" - return 1 - fi - if ! kdumphost=$(ip addr show dev "$kdumpnic" | grep '[ ]*inet'); then - derror "wrong kdumpnic: $kdumpnic" - return 1 - fi - kdumphost=$(echo "$kdumphost" | head -n 1 | awk '{print $2}') - kdumphost="${kdumphost%%/*}" - if [ -z "$kdumphost" ]; then - derror "wrong kdumpnic: $kdumpnic" - return 1 - fi - HOST_IP=$kdumphost + + if ! is_nfs_dump_target && ! is_ssh_dump_target; then + return 0 fi - return 0 + + _kdump_remote_ip=$(getarg kdump_remote_ip=) + + if [ -z "$_kdump_remote_ip" ]; then + derror "failed to get remote IP address!" + return 1 + fi + _route=$(kdump_get_ip_route "$_kdump_remote_ip") + _netdev=$(kdump_get_ip_route_field "$_route" "dev") + + if ! _kdumpip=$(ip addr show dev "$_netdev" | grep '[ ]*inet'); then + derror "Failed to get IP of $_netdev" + return 1 + fi + + _kdumpip=$(echo "$_kdumpip" | head -n 1 | awk '{print $2}') + _kdumpip="${_kdumpip%%/*}" + HOST_IP=$_kdumpip } read_kdump_confs() diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh index 477c38d..cf9eeff 100755 --- a/dracut-module-setup.sh +++ b/dracut-module-setup.sh @@ -229,26 +229,6 @@ kdump_get_perm_addr() { fi } -# Prefix kernel assigned names with "kdump-". EX: eth0 -> kdump-eth0 -# Because kernel assigned names are not persistent between 1st and 2nd -# kernel. We could probably end up with eth0 being eth1, eth0 being -# eth1, and naming conflict happens. -kdump_setup_ifname() { - local _ifname - - # If ifname already has 'kdump-' prefix, we must be switching from - # fadump to kdump. Skip prefixing 'kdump-' in this case as adding - # another prefix may truncate the ifname. Since an ifname with - # 'kdump-' is already persistent, this should be fine. - if [[ $1 =~ eth* ]] && [[ ! $1 =~ ^kdump-* ]]; then - _ifname="kdump-$1" - else - _ifname="$1" - fi - - echo "$_ifname" -} - use_ipv4_or_ipv6() { local _netif=$1 _uuid=$2 @@ -293,6 +273,20 @@ _clone_nmconnection() { return 1 } +_match_nmconnection_by_mac() { + local _unique_id _dev _mac _mac_field + + _unique_id=$1 + _dev=$2 + + _mac=$(kdump_get_perm_addr "$_dev") + if [[ $_mac != 'not set' ]]; then + _mac_field=$(nmcli --get-values connection.type connection show "$_unique_id").mac-address + nmcli connection modify --temporary "$_unique_id" "$_mac_field" "$_mac" &> >(ddebug) + nmcli connection modify --temporary "$_unique_id" "connection.interface-name" "" &> >(ddebug) + fi +} + # Clone NM connection profiles # # This function makes use of "nmcli clone" to automatically convert ifcfg-* @@ -312,6 +306,10 @@ clone_nmconnections() { use_ipv4_or_ipv6 "$_uuid" "$_dev" + # For physical NIC i.e. non-user created NIC, ask NM to match a + # connection profile based on MAC address + _match_nmconnection_by_mac "$_uuid" "$_dev" + _cloned_nmconnection_file_path=$(nmcli --get-values UUID,FILENAME connection show | sed -n "s/^${_uuid}://p") _tmp_nmconnection_file_path=$_DRACUT_KDUMP_NM_TMP_DIR/$(basename "$_nmconnection_file_path") cp "$_cloned_nmconnection_file_path" "$_tmp_nmconnection_file_path" @@ -527,19 +525,6 @@ kdump_setup_znet() { echo "rd.znet=${NETTYPE},${SUBCHANNELS},${_options} rd.znet_ifname=$_netdev:${SUBCHANNELS}" > "${initdir}/etc/cmdline.d/30znet.conf" } -kdump_get_ip_route() { - local _route - if ! _route=$(/sbin/ip -o route get to "$1" 2>&1); then - derror "Bad kdump network destination: $1" - exit 1 - fi - echo "$_route" -} - -kdump_get_ip_route_field() { - echo "$1" | sed -n -e "s/^.*\<$2\>\s\+\(\S\+\).*$/\1/p" -} - kdump_get_remote_ip() { local _remote _remote_temp _remote=$(get_remote_host "$1") @@ -557,14 +542,13 @@ kdump_get_remote_ip() { # initramfs accessing giving destination # $1: destination host kdump_install_net() { - local _destaddr _srcaddr _route _netdev kdumpnic _ip_proc + local _destaddr _srcaddr _route _netdev _ip_proc local _znet_netdev _znet_conpath _destaddr=$(kdump_get_remote_ip "$1") _route=$(kdump_get_ip_route "$_destaddr") _srcaddr=$(kdump_get_ip_route_field "$_route" "src") _netdev=$(kdump_get_ip_route_field "$_route" "dev") - kdumpnic=$(kdump_setup_ifname "$_netdev") _znet_netdev=$(find_online_znet_device) if [[ -n $_znet_netdev ]]; then @@ -596,8 +580,8 @@ kdump_install_net() { # gets released. echo > "${initdir}/usr/libexec/nm-initrd-generator" - if [[ ! -f ${initdir}/etc/cmdline.d/60kdumpnic.conf ]]; then - echo "kdumpnic=$kdumpnic" > "${initdir}/etc/cmdline.d/60kdumpnic.conf" + if [[ ! -f ${initdir}/etc/cmdline.d/60kdumpip.conf ]]; then + echo "kdump_remote_ip=$_destaddr" > "${initdir}/etc/cmdline.d/60kdumpip.conf" fi if is_ipv6_address "$_srcaddr"; then diff --git a/kdump-lib-initramfs.sh b/kdump-lib-initramfs.sh index 84e6bf7..74bd9ec 100755 --- a/kdump-lib-initramfs.sh +++ b/kdump-lib-initramfs.sh @@ -131,3 +131,17 @@ is_fs_dump_target() { [ -n "$(kdump_get_conf_val "ext[234]\|xfs\|btrfs\|minix")" ] } + +kdump_get_ip_route() +{ + if ! _route=$(/sbin/ip -o route get to "$1" 2>&1); then + derror "Bad kdump network destination: $1" + exit 1 + fi + echo "$_route" +} + +kdump_get_ip_route_field() +{ + echo "$1" | sed -n -e "s/^.*\<$2\>\s\+\(\S\+\).*$/\1/p" +} From 2c098ae1e4d44bd921d5504194beb0626c9e4bdf Mon Sep 17 00:00:00 2001 From: Coiby Xu Date: Thu, 23 Sep 2021 15:26:00 +0800 Subject: [PATCH 11/11] Simplify setup_znet by copying connection profile to initrd /usr/lib/udev/ccw_init [1] shipped by s390utils extracts the values of SUBCHANNELS, NETTYPE and LAYER2 from /etc/sysconfig/network-scripts/ifcfg-* or /etc/NetworkManager/system-connections/*.nmconnection to activate znet network device. If the connection profile is copied to initrd, there is no need to set up the "rd.znet" dracut cmdline parameter. There are two cases addressed by this commit, 1. znet network interface is a slave of bonding/teaming/vlan/bridging network. The connection profile has been copied to initrd by kdump_copy_nmconnection_file and it contains the info needed by ccw_init. 2. znet network interface is a slave of bonding/teaming/vlan/bridging network. The corresponding ifcfg-*/*.nmconnection file may not contain info like SUBCHANNELS [2]. In this case, copy the ifcfg-*/*.nmconnection file that has this info to the kdump initrd. Also to prevent the copied connection profile from being chosen by NM, set connection.autoconnect=false for this connection profile. Note 1. ccw_init doesn't care if SUBCHANNELS, NETTYPE and LAYER2 comes from an active NM profile or not. If an inactive NM profile contains this info, it needs to be copied to the kdump initrd as well. 2. "rd.znet_ifname=$_netdev:${SUBCHANNELS}" is no needed because now there is no renaming of s390x network interfaces when reusing NetworkManager profiles. rd.znet_ifname was introduced in commit ce0305d ("Add a new option 'rd.znet_ifname' in order to use it in udev rules") to address the special case of non-persistent MAC address by renaming a network interface by SUBCHANNELS. [1] https://src.fedoraproject.org/rpms/s390utils/blob/rawhide/f/ccw_init [2] https://bugzilla.redhat.com/show_bug.cgi?id=2064708 Signed-off-by: Coiby Xu --- dracut-module-setup.sh | 65 ++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh index cf9eeff..5338dbb 100755 --- a/dracut-module-setup.sh +++ b/dracut-module-setup.sh @@ -495,34 +495,46 @@ find_online_znet_device() { echo -n "$ifname" } -# setup s390 znet cmdline -# $1: netdev (ifname) -# $2: nmcli connection path +_find_znet_nmconnection() { + LANG=C grep -s -E -i -l \ + "^s390-subchannels=([0-9]\.[0-9]\.[a-f0-9]+;){0,2}" \ + "$1"/*.nmconnection | LC_ALL=C sed -e "$2" +} + +# setup s390 znet +# +# Note part of code is extracted from ccw_init provided by s390utils kdump_setup_znet() { - local _netdev="$1" - local _conpath="$2" - local s390_prefix="802-3-ethernet.s390-" - local _options="" - local NETTYPE - local SUBCHANNELS + local _config_file _unique_name _NM_conf_dir + local __sed_discard_ignored_files='/\(~\|\.bak\|\.old\|\.orig\|\.rpmnew\|\.rpmorig\|\.rpmsave\)$/d' - NETTYPE=$(get_nmcli_field_by_conpath "${s390_prefix}nettype" "$_conpath") - SUBCHANNELS=$(get_nmcli_field_by_conpath "${s390_prefix}subchannels" "$_conpath") - _options=$(get_nmcli_field_by_conpath "${s390_prefix}options" "$_conpath") + _NM_conf_dir="/etc/NetworkManager/system-connections" - if [[ -z $NETTYPE || -z $SUBCHANNELS || -z $_options ]]; then - dwarning "Failed to get znet configuration via nmlci output. Now try sourcing ifcfg script." - source_ifcfg_file "$_netdev" - for i in $OPTIONS; do - _options=${_options},$i - done + _config_file=$(_find_znet_nmconnection "$initdir/$_NM_conf_dir" "$__sed_discard_ignored_files") + if [[ -n "$_config_file" ]]; then + ddebug "$_config_file has already contained the znet config" + return fi - if [[ -z $NETTYPE || -z $SUBCHANNELS || -z $_options ]]; then - exit 1 + _config_file=$(LANG=C grep -s -E -i -l \ + "^[[:space:]]*SUBCHANNELS=['\"]?([0-9]\.[0-9]\.[a-f0-9]+,){0,2}" \ + /etc/sysconfig/network-scripts/ifcfg-* \ + | LC_ALL=C sed -e "$__sed_discard_ignored_files") + + if [[ -n "$_config_file" ]]; then + LANG=c grep 'SUBCHANNELS\|NETTYPE\|OPTIONS' "$_config_file" > "$initdir/$_config_file" + else + _config_file=$(_find_znet_nmconnection "$_NM_conf_dir" "$__sed_discard_ignored_files") + fi + + if [[ -n "$_config_file" ]]; then + _unique_name=$(cat /proc/sys/kernel/random/uuid) + nmcli connection clone --temporary "$_config_file" "$_unique_name" &> >(ddebug) + nmcli connection modify --temporary "$_unique_name" connection.autoconnect false + inst "/run/NetworkManager/system-connections/${_unique_name}.nmconnection" "${_NM_conf_dir}/${_unique_name}.nmconnection" + nmcli connection del "$_unique_name" &> >(ddebug) fi - echo "rd.znet=${NETTYPE},${SUBCHANNELS},${_options} rd.znet_ifname=$_netdev:${SUBCHANNELS}" > "${initdir}/etc/cmdline.d/30znet.conf" } kdump_get_remote_ip() { @@ -543,22 +555,12 @@ kdump_get_remote_ip() { # $1: destination host kdump_install_net() { local _destaddr _srcaddr _route _netdev _ip_proc - local _znet_netdev _znet_conpath _destaddr=$(kdump_get_remote_ip "$1") _route=$(kdump_get_ip_route "$_destaddr") _srcaddr=$(kdump_get_ip_route_field "$_route" "src") _netdev=$(kdump_get_ip_route_field "$_route" "dev") - _znet_netdev=$(find_online_znet_device) - if [[ -n $_znet_netdev ]]; then - _znet_conpath=$(get_nmcli_connection_apath_by_ifname "$_znet_netdev") - if ! (kdump_setup_znet "$_znet_netdev" "$_znet_conpath"); then - derror "Failed to set up znet" - exit 1 - fi - fi - if kdump_is_bridge "$_netdev"; then kdump_setup_bridge "$_netdev" elif kdump_is_bond "$_netdev"; then @@ -1069,6 +1071,7 @@ install() { _netifs=$(cat "$_TMP_KDUMP_NETIFS") if [[ -n "$_netifs" ]]; then kdump_install_nmconnections "$_netifs" + [[ -n "$(find_online_znet_device)" ]] && kdump_setup_znet kdump_install_nm_netif_allowlist "$_netifs" kdump_install_nic_driver "$_netifs" fi