Description: Currently kdump doesn't support ipv6 nfs/ssh dump. Ipv6 is the latest version of the Internet Protocal. so it is a significant feture for kdump to enhance to support ipv6.
Solutions: Since dracut has supported ipv6 now, it is easy to change the kdump code to support ipv6. Just need pass the right _ip_opts to the second kernle. What is the main difference in userspace bettwen ipv4 and ipv6 is the ip address format. For ipv6 nfs dump: if ipv6 address type is link scope, /etc/kdump.conf should be edited like "nfs [fe80::5054:ff:fe48:ca80%eth0]:/mnt" else /etc/kdump.conf should be edited like "nfs [2001:db8:0:f101::2]:/mnt" For ipv6 ssh dump if ipv6 address type is link scope, /etc/kdump.conf should be edited like "ssh root at fe80::5054:ff:fe48:ca80%eth0" else /etc/kdump.conf should be edited like "ssh root at 2001:db8:0:f101::2"
What this patch do is: a): Add a function is_ipv6_target to tell what version of Internet Protocal (ipv4/ipv6) kdump will use to dump to remote target. b): Modify kdump_install_net to handle ipv6 configuration in /etc/kdump.conf correctly. Get the ipv6 address from /etc/kdump.conf is more complicated than ipv4 because the difference configuration format mentioned above. c): Based on the ip address type, using corresponding ip address as HOST_IP in second kernel.
It was tested for IPV6 and IPV4 address in beaker machine and passed.
Note: 1): Currntly only f19 support remount a nfs target in ipv6. detail in https: //bugzilla.redhat.com/show_bug.cgi?id=1099761. If using in f20, you can comment out "mount -o remount,rw $_mp || return 1" in kdump.sh line 105. 2): If Using static ipv6 address and configuring nfs/ssh with hostname of remote target, MUST add a ipv6 DNS in ifcfg-devname.
How to create a ipv6 enviromnet. 1): Reserving two beaker machine with family fedora. 2): Choosing a beaker machine as a nfs/ssh server and delete it's ipv4 address by "ip address del ipv4-address dev nicname" 3): Configuring the /etc/kdump.conf like mentioned above.
Signed-off-by: Arthur Zou zzou@redhat.com Signed-off-by: Minfei Huang mhuang@redhat.com --- Change in v3: - using the command getenv ahost to get address information. - suport static ipv6 route Change in v2: - modify patch format
dracut-kdump.sh | 8 +++-- dracut-module-setup.sh | 80 +++++++++++++++++++++++++++++++++++--------------- kdump-lib.sh | 33 +++++++++++++++++++++ 3 files changed, 96 insertions(+), 25 deletions(-)
diff --git a/dracut-kdump.sh b/dracut-kdump.sh index 600e84e..9f12084 100755 --- a/dracut-kdump.sh +++ b/dracut-kdump.sh @@ -121,9 +121,13 @@ get_host_ip() then kdumpnic=$(getarg kdumpnic=) [ -z "$kdumpnic" ] && echo "kdump: failed to get kdumpnic!" && return 1 - _host=`ip addr show dev $kdumpnic|grep 'inet '` + if is_ipv6_target; then + _host=`ip addr show dev $kdumpnic|grep 'inet6'` + else + _host=`ip addr show dev $kdumpnic|grep 'inet '` + fi [ $? -ne 0 ] && echo "kdump: wrong kdumpnic: $kdumpnic" && return 1 - _host="${_host##*inet }" + _host=`echo $_host | cut -d' ' -f2` _host="${_host%%/*}" [ -z "$_host" ] && echo "kdump: wrong kdumpnic: $kdumpnic" && return 1 HOST_IP=$_host diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh index 38801de..7fb3d96 100755 --- a/dracut-module-setup.sh +++ b/dracut-module-setup.sh @@ -70,20 +70,33 @@ kdump_setup_dns() { #$2: srcaddr #if it use static ip echo it, or echo null kdump_static_ip() { - local _netmask _gateway + local _netmask _gateway _ipaddr local _netdev="$1" _srcaddr="$2" - local _ipaddr=$(ip addr show dev $_netdev permanent | \ + + if is_ipv6_target; then + _ipaddr=$(ip addr show dev $_netdev permanent | \ + awk "/ $_srcaddr/.* /{print $2}") + if [ -n "$_ipaddr" ]; then + _gateway=$(ip -6 route list dev $_netdev | awk '/^default /{print $3}') + echo -n "[${_srcaddr}]::[${_gateway}]:64::" + fi + /sbin/ip -6 route show | grep -v default | grep "^[1-9a-f].*via.* $_netdev "|\ + while read line; do + echo $line | awk '{printf("rd.route=[%s]:[%s]:%s\n", $1, $3, $5)}' + done >> ${initdir}/etc/cmdline.d/45route-static.conf + else + _ipaddr=$(ip addr show dev $_netdev permanent | \ awk "/ $_srcaddr/.* $_netdev$/{print $2}") - if [ -n "$_ipaddr" ]; then - _netmask=$(ipcalc -m $_ipaddr | cut -d'=' -f2) - _gateway=$(ip route list dev $_netdev | awk '/^default /{print $3}') - echo -n "${_srcaddr}::${_gateway}:${_netmask}::" + if [ -n "$_ipaddr" ]; then + _netmask=$(ipcalc -m $_ipaddr | cut -d'=' -f2) + _gateway=$(ip route list dev $_netdev | awk '/^default /{print $3}') + echo -n "${_srcaddr}::${_gateway}:${_netmask}::" + fi + /sbin/ip route show | grep -v default | grep "^[[:digit:]].*via.* $_netdev " |\ + while read line; do + echo $line | awk '{printf("rd.route=%s:%s:%s\n", $1, $3, $5)}' + done >> ${initdir}/etc/cmdline.d/45route-static.conf fi - - /sbin/ip route show | grep -v default | grep "^[[:digit:]].*via.* $_netdev " |\ - while read line; do - echo $line | awk '{printf("rd.route=%s:%s:%s\n", $1, $3, $5)}' - done >> ${initdir}/etc/cmdline.d/45route-static.conf }
kdump_get_mac_addr() { @@ -264,24 +277,43 @@ kdump_install_net() { local _server _netdev _srcaddr local config_val="$1"
- _server=`echo $config_val | sed 's/.*@//' | cut -d':' -f1` + _server=`get_remote_host $config_val`
- _need_dns=`echo $_server|grep "[a-zA-Z]"` - [ -n "$_need_dns" ] && _server=`getent hosts $_server|cut -d' ' -f1` + if is_ipv6_target; then + _need_dns=`echo $_server|grep "[:]"` + [ -z "$_need_dns" ] && _server=`getent hosts $_server| head -n 1 | cut -d' ' -f1` + else + _need_dns=`echo $_server|grep "[a-zA-Z]"` + [ -n "$_need_dns" ] && _server=`getent hosts $_server| head -n 1 | cut -d' ' -f1` + fi
_netdev=`/sbin/ip route get to $_server 2>&1` [ $? != 0 ] && echo "Bad kdump location: $config_val" && exit 1
- #the field in the ip output changes if we go to another subnet - if [ -n "`echo $_netdev | grep via`" ] - then - # we are going to a different subnet - _srcaddr=`echo $_netdev|awk '{print $7}'|head -n 1` - _netdev=`echo $_netdev|awk '{print $5;}'|head -n 1` + if is_ipv6_target; then + #the field in the ip output changes if we go to another subnet + if [ -n "`echo $_netdev | grep via`" ] + then + # we are going to a different subnet + _srcaddr=`echo $_netdev|awk '{print $9}'|head -n 1` + _netdev=`echo $_netdev|awk '{print $7;}'|head -n 1` + else + # we are on the same subnet + _srcaddr=`echo $_netdev|awk '{print $7}'|head -n 1` + _netdev=`echo $_netdev|awk '{print $5}'|head -n 1` + fi else - # we are on the same subnet - _srcaddr=`echo $_netdev|awk '{print $5}'|head -n 1` - _netdev=`echo $_netdev|awk '{print $3}'|head -n 1` + #the field in the ip output changes if we go to another subnet + if [ -n "`echo $_netdev | grep via`" ] + then + # we are going to a different subnet + _srcaddr=`echo $_netdev|awk '{print $7}'|head -n 1` + _netdev=`echo $_netdev|awk '{print $5;}'|head -n 1` + else + # we are on the same subnet + _srcaddr=`echo $_netdev|awk '{print $5}'|head -n 1` + _netdev=`echo $_netdev|awk '{print $3}'|head -n 1` + fi fi
kdump_setup_netdev "${_netdev}" "${_srcaddr}" @@ -583,6 +615,8 @@ install() { inst "/bin/date" "/bin/date" inst "/bin/sync" "/bin/sync" inst "/bin/cut" "/bin/cut" + inst "/bin/getent" "/bin/getent" + inst "/bin/head" "/bin/head" inst "/sbin/makedumpfile" "/sbin/makedumpfile" inst "/sbin/vmcore-dmesg" "/sbin/vmcore-dmesg" inst "/lib/kdump/kdump-lib.sh" "/lib/kdump-lib.sh" diff --git a/kdump-lib.sh b/kdump-lib.sh index a20c6e8..0ec810a 100755 --- a/kdump-lib.sh +++ b/kdump-lib.sh @@ -138,3 +138,36 @@ check_save_path_fs() fi }
+# get ip address or hostname from nfs/ssh config value +get_remote_host() +{ + local _config_val=$1 + + # in ipv6, the _config_val format is [xxxx:xxxx::xxxx%eth0]:/mnt/nfs or + # username at xxxx:xxxx::xxxx%eth0. what we need is just xxxx:xxxx::xxxx + _config_val=${_config_val#*@} + _config_val=${_config_val%:/*} + _config_val=${_config_val#[} + _config_val=${_config_val%]} + _config_val=${_config_val%%*} + echo $_config_val +} + +# check the remote server ip address tpye +is_ipv6_target() +{ + local _server _server_tmp + + if is_ssh_dump_target; then + _server=`get_option_value ssh` + elif is_nfs_dump_target; then + _server=`get_option_value nfs` + fi + + [ -z "$_server" ] && return 1 + _server=`get_remote_host $_server` + _server_tmp=$_server + _server=`getent ahosts $_server | head -n 1 | cut -d' ' -f1` + _server=${_server:-$_server_tmp} + echo $_server | grep -q ":" +}