Recently, dracut-network drops depedency on dhcp-client which requires ipcalc. Thus the dependency chain "kexec-tools -> dracut-network -> dhcp-client -> ipcalc" is broken. When NIC is configured to a static IP, kexec-tools depended on "ipcalc -m" to get netmask. This commit implements the shell equivalent of "ipcalc -m".
The following test code shows cal_netmask_by_prefix is consistent with "ipcalc -m",
#!/bin/bash . dracut-module-setup.sh
for i in {0..128}; do mask_expected=$(ipcalc -m fe::/$i| cut -d"=" -f2) mask_actual=$(cal_netmask_by_prefix $i "-6") if [[ "$mask_expected" != "$mask_actual" ]]; then echo "prefix="$i, "expected="$mask_expected, "acutal="$mask_actual exit fi done
echo "IPv6 tests passed"
for i in {0..32}; do mask_expected=$(ipcalc -m 8.8.8.8/$i| cut -d"=" -f2) mask_actual=$(cal_netmask_by_prefix $i "") if [[ "$mask_expected" != "$mask_actual" ]]; then echo "prefix="$i, "expected="$mask_expected, "acutal="$mask_actual exit fi done
echo "IPv4 tests passed"
i=-2 res=$(cal_netmask_by_prefix "$i" "") if [[ $? -ne 1 ]]; then echo "cal_netmask_by_prefix should exit when prefix<0" exit fi
res=$(cal_netmask_by_prefix "$i" "") if [[ $? -ne 1 ]]; then echo "cal_netmask_by_prefix should exit when prefix<0" exit fi
i=33 $(cal_netmask_by_prefix $i "") if [[ $? -ne 1 ]]; then echo "cal_netmask_by_prefix should exit when prefix>32 for IPv4" exit fi
i=129 $(cal_netmask_by_prefix $i "-6") if [[ $? -ne 1 ]]; then echo "cal_netmask_by_prefix should exit when prefix>128 for IPv4" exit fi
echo "Bad prefixes tests passed"
echo "All tests passed"
Reported-by: Jie Li jieli@redhat.com Signed-off-by: Coiby Xu coxu@redhat.com --- v3 -> v2: 1. Don't introduce "boolean" _ipv6 in kdump_static_ip and don't use fake boolean true/false which is not reliable [Kairui] 2. use ((1)) and((0)) to tell if it's IPv6 or not instead 3. Add tests for bad prefixes
v1 -> v2: 1. Check subshell exit code when calling cal_netmask_by_prefix 2. Stop using die when bad prefix is passed to cal_netmask_by_prefix 3. Remove trailing spaces --- dracut-module-setup.sh | 119 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 2 deletions(-)
diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh index 8316589..aeb2e45 100755 --- a/dracut-module-setup.sh +++ b/dracut-module-setup.sh @@ -121,12 +121,122 @@ kdump_setup_dns() { done < "/etc/resolv.conf" }
+# $1: repeat times +# $2: string to be repeated +# $3: separator +repeatedly_join_str() { + local _count="$1" + local _str="$2" + local _separator="$3" + local i _res + + if [[ "$_count" -le 0 ]]; then + echo -n "" + return + fi + + i=0 + _res="$_str" + ((_count--)) + + while [[ "$i" -lt "$_count" ]]; do + ((i++)) + _res="${_res}${_separator}${_str}" + done + echo -n "$_res" +} + +# $1: prefix +# $2: ipv6_flag="-6" indicates it's IPv6 +# Given a prefix, calculate the netmask (equivalent of "ipcalc -m") +# by concatenating three parts, +# 1) the groups with all bits set 1 +# 2) a group with partial bits set to 0 +# 3) the groups with all bits set to 0 +cal_netmask_by_prefix() { + local _prefix="$1" + local _ipv6_flag="$2" _ipv6 + local _bits_per_octet=8 + local _count _res _octets_per_group _octets_total _seperator _total_groups + local _max_group_value _max_group_value_repr _bits_per_group _tmp _zero_bits + + if [[ "$_ipv6_flag" == "-6" ]]; then + _ipv6=1 + else + _ipv6=0 + fi + + if [[ "$_prefix" -lt 0 || "$_prefix" -gt 128 ]] || \ + (((!_ipv6)) && [[ "$_prefix" -gt 32 ]]); then + derror "Bad prefix:$_prefix for calculating netmask" + exit 1 + fi + + if ((_ipv6)); then + _octets_per_group=2 + _octets_total=16 + _seperator=":" + else + _octets_per_group=1 + _octets_total=4 + _seperator="." + fi + + _total_groups=$((_octets_total/_octets_per_group)) + _bits_per_group=$((_octets_per_group * _bits_per_octet)) + _max_group_value=$(((1 << _bits_per_group) - 1)) + + if ((_ipv6)); then + _max_group_value_repr=$(printf "%x" $_max_group_value) + else + _max_group_value_repr="$_max_group_value" + fi + + _count=$((_prefix/_octets_per_group/_bits_per_octet)) + _first_part=$(repeatedly_join_str "$_count" "$_max_group_value_repr" "$_seperator") + _res="$_first_part" + + _tmp=$((_octets_total*_bits_per_octet-_prefix)) + _zero_bits=$(expr $_tmp % $_bits_per_group) + if [[ "$_zero_bits" -ne 0 ]]; then + _second_part=$((_max_group_value >> _zero_bits << _zero_bits)) + if ((_ipv6)); then + _second_part=$(printf "%x" $_second_part) + fi + ((_count++)) + if [[ -z "$_first_part" ]]; then + _res="$_second_part" + else + _res="${_first_part}${_seperator}${_second_part}" + fi + fi + + _count=$((_total_groups-_count)) + if [[ "$_count" -eq 0 ]]; then + echo -n "$_res" + return + fi + + if ((_ipv6)) && [[ "$_count" -gt 1 ]] ; then + # use condensed notion for IPv6 + _third_part=":" + else + _third_part=$(repeatedly_join_str "$_count" "0" "$_seperator") + fi + + if [[ -z "$_res" ]] && ((!_ipv6)) ; then + echo -n "${_third_part}" + else + echo -n "${_res}${_seperator}${_third_part}" + fi +} + #$1: netdev name #$2: srcaddr #if it use static ip echo it, or echo null kdump_static_ip() { local _netdev="$1" _srcaddr="$2" _ipv6_flag - local _netmask _gateway _ipaddr _target _nexthop + local _netmask _gateway _ipaddr _target _nexthop _prefix
_ipaddr=$(ip addr show dev $_netdev permanent | awk "/ $_srcaddr/.* /{print $2}")
@@ -144,7 +254,12 @@ kdump_static_ip() { _srcaddr="[$_srcaddr]" _gateway="[$_gateway]" else - _netmask=$(ipcalc -m $_ipaddr | cut -d'=' -f2) + _prefix=$(cut -d'/' -f2 <<< "$_ipaddr") + _netmask=$(cal_netmask_by_prefix "$_prefix" "$_ipv6_flag") + if [[ "$?" -ne 0 ]]; then + derror "Failed to calculate netmask for $_ipaddr" + exit 1 + fi fi echo -n "${_srcaddr}::${_gateway}:${_netmask}::" fi
A shell equivalent of "ipcalc -m" has been implemented.
Signed-off-by: Coiby Xu coxu@redhat.com --- kexec-tools.spec | 1 - 1 file changed, 1 deletion(-)
diff --git a/kexec-tools.spec b/kexec-tools.spec index 00cf64c..d24c439 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -63,7 +63,6 @@ Requires: dracut >= 050 Requires: dracut-network >= 050 Recommends: dracut-squash >= 050 Requires: ethtool -Requires: ipcalc BuildRequires: make BuildRequires: zlib-devel elfutils-devel glib2-devel bzip2-devel ncurses-devel bison flex lzo-devel snappy-devel BuildRequires: pkgconfig intltool gettext
On Thu, Apr 8, 2021 at 11:52 AM Coiby Xu coxu@redhat.com wrote:
Recently, dracut-network drops depedency on dhcp-client which requires ipcalc. Thus the dependency chain "kexec-tools -> dracut-network -> dhcp-client -> ipcalc" is broken. When NIC is configured to a static IP, kexec-tools depended on "ipcalc -m" to get netmask. This commit implements the shell equivalent of "ipcalc -m".
The following test code shows cal_netmask_by_prefix is consistent with "ipcalc -m",
#!/bin/bash . dracut-module-setup.sh for i in {0..128}; do mask_expected=$(ipcalc -m fe::/$i| cut -d"=" -f2) mask_actual=$(cal_netmask_by_prefix $i "-6") if [[ "$mask_expected" != "$mask_actual" ]]; then echo "prefix="$i, "expected="$mask_expected, "acutal="$mask_actual exit fi done echo "IPv6 tests passed" for i in {0..32}; do mask_expected=$(ipcalc -m 8.8.8.8/$i| cut -d"=" -f2) mask_actual=$(cal_netmask_by_prefix $i "") if [[ "$mask_expected" != "$mask_actual" ]]; then echo "prefix="$i, "expected="$mask_expected, "acutal="$mask_actual exit fi done echo "IPv4 tests passed" i=-2 res=$(cal_netmask_by_prefix "$i" "") if [[ $? -ne 1 ]]; then echo "cal_netmask_by_prefix should exit when prefix<0" exit fi res=$(cal_netmask_by_prefix "$i" "") if [[ $? -ne 1 ]]; then echo "cal_netmask_by_prefix should exit when prefix<0" exit fi i=33 $(cal_netmask_by_prefix $i "") if [[ $? -ne 1 ]]; then echo "cal_netmask_by_prefix should exit when prefix>32 for IPv4" exit fi i=129 $(cal_netmask_by_prefix $i "-6") if [[ $? -ne 1 ]]; then echo "cal_netmask_by_prefix should exit when prefix>128 for IPv4" exit fi echo "Bad prefixes tests passed" echo "All tests passed"
Reported-by: Jie Li jieli@redhat.com Signed-off-by: Coiby Xu coxu@redhat.com
v3 -> v2: 1. Don't introduce "boolean" _ipv6 in kdump_static_ip and don't use fake boolean true/false which is not reliable [Kairui] 2. use ((1)) and((0)) to tell if it's IPv6 or not instead 3. Add tests for bad prefixes
v1 -> v2: 1. Check subshell exit code when calling cal_netmask_by_prefix 2. Stop using die when bad prefix is passed to cal_netmask_by_prefix 3. Remove trailing spaces
dracut-module-setup.sh | 119 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 2 deletions(-)
diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh index 8316589..aeb2e45 100755 --- a/dracut-module-setup.sh +++ b/dracut-module-setup.sh @@ -121,12 +121,122 @@ kdump_setup_dns() { done < "/etc/resolv.conf" }
+# $1: repeat times +# $2: string to be repeated +# $3: separator +repeatedly_join_str() {
- local _count="$1"
- local _str="$2"
- local _separator="$3"
- local i _res
- if [[ "$_count" -le 0 ]]; then
echo -n ""
return
- fi
- i=0
- _res="$_str"
- ((_count--))
- while [[ "$i" -lt "$_count" ]]; do
((i++))
_res="${_res}${_separator}${_str}"
- done
- echo -n "$_res"
+}
+# $1: prefix +# $2: ipv6_flag="-6" indicates it's IPv6 +# Given a prefix, calculate the netmask (equivalent of "ipcalc -m") +# by concatenating three parts, +# 1) the groups with all bits set 1 +# 2) a group with partial bits set to 0 +# 3) the groups with all bits set to 0 +cal_netmask_by_prefix() {
- local _prefix="$1"
- local _ipv6_flag="$2" _ipv6
- local _bits_per_octet=8
- local _count _res _octets_per_group _octets_total _seperator _total_groups
- local _max_group_value _max_group_value_repr _bits_per_group _tmp _zero_bits
- if [[ "$_ipv6_flag" == "-6" ]]; then
_ipv6=1
- else
_ipv6=0
- fi
- if [[ "$_prefix" -lt 0 || "$_prefix" -gt 128 ]] || \
(((!_ipv6)) && [[ "$_prefix" -gt 32 ]]); then
derror "Bad prefix:$_prefix for calculating netmask"
exit 1
- fi
- if ((_ipv6)); then
_octets_per_group=2
_octets_total=16
_seperator=":"
- else
_octets_per_group=1
_octets_total=4
_seperator="."
- fi
- _total_groups=$((_octets_total/_octets_per_group))
- _bits_per_group=$((_octets_per_group * _bits_per_octet))
- _max_group_value=$(((1 << _bits_per_group) - 1))
- if ((_ipv6)); then
_max_group_value_repr=$(printf "%x" $_max_group_value)
- else
_max_group_value_repr="$_max_group_value"
- fi
- _count=$((_prefix/_octets_per_group/_bits_per_octet))
- _first_part=$(repeatedly_join_str "$_count" "$_max_group_value_repr" "$_seperator")
- _res="$_first_part"
- _tmp=$((_octets_total*_bits_per_octet-_prefix))
- _zero_bits=$(expr $_tmp % $_bits_per_group)
- if [[ "$_zero_bits" -ne 0 ]]; then
_second_part=$((_max_group_value >> _zero_bits << _zero_bits))
if ((_ipv6)); then
_second_part=$(printf "%x" $_second_part)
fi
((_count++))
if [[ -z "$_first_part" ]]; then
_res="$_second_part"
else
_res="${_first_part}${_seperator}${_second_part}"
fi
- fi
- _count=$((_total_groups-_count))
- if [[ "$_count" -eq 0 ]]; then
echo -n "$_res"
return
- fi
- if ((_ipv6)) && [[ "$_count" -gt 1 ]] ; then
# use condensed notion for IPv6
_third_part=":"
- else
_third_part=$(repeatedly_join_str "$_count" "0" "$_seperator")
- fi
- if [[ -z "$_res" ]] && ((!_ipv6)) ; then
echo -n "${_third_part}"
- else
echo -n "${_res}${_seperator}${_third_part}"
- fi
+}
#$1: netdev name #$2: srcaddr #if it use static ip echo it, or echo null kdump_static_ip() { local _netdev="$1" _srcaddr="$2" _ipv6_flag
- local _netmask _gateway _ipaddr _target _nexthop
local _netmask _gateway _ipaddr _target _nexthop _prefix
_ipaddr=$(ip addr show dev $_netdev permanent | awk "/ $_srcaddr/.* /{print $2}")
@@ -144,7 +254,12 @@ kdump_static_ip() { _srcaddr="[$_srcaddr]" _gateway="[$_gateway]" else
_netmask=$(ipcalc -m $_ipaddr | cut -d'=' -f2)
_prefix=$(cut -d'/' -f2 <<< "$_ipaddr")
_netmask=$(cal_netmask_by_prefix "$_prefix" "$_ipv6_flag")
if [[ "$?" -ne 0 ]]; then
derror "Failed to calculate netmask for $_ipaddr"
exit 1
fifi fi echo -n "${_srcaddr}::${_gateway}:${_netmask}::"
-- 2.31.0 _______________________________________________ kexec mailing list -- kexec@lists.fedoraproject.org To unsubscribe send an email to kexec-leave@lists.fedoraproject.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/kexec@lists.fedoraproject.org Do not reply to spam on the list, report it: https://pagure.io/fedora-infrastructure
Looks good and acked for the two patch, just found some trivial code style issue I can fix when merging.
Acked-by: Kairui Song kasong@redhat.com
On Fri, Apr 16, 2021 at 07:09:24PM +0800, Kairui Song wrote:
On Thu, Apr 8, 2021 at 11:52 AM Coiby Xu coxu@redhat.com wrote:
Recently, dracut-network drops depedency on dhcp-client which requires ipcalc. Thus the dependency chain "kexec-tools -> dracut-network -> dhcp-client -> ipcalc" is broken. When NIC is configured to a static IP, kexec-tools depended on "ipcalc -m" to get netmask. This commit implements the shell equivalent of "ipcalc -m".
The following test code shows cal_netmask_by_prefix is consistent with "ipcalc -m",
#!/bin/bash . dracut-module-setup.sh for i in {0..128}; do mask_expected=$(ipcalc -m fe::/$i| cut -d"=" -f2) mask_actual=$(cal_netmask_by_prefix $i "-6") if [[ "$mask_expected" != "$mask_actual" ]]; then echo "prefix="$i, "expected="$mask_expected, "acutal="$mask_actual exit fi done echo "IPv6 tests passed" for i in {0..32}; do mask_expected=$(ipcalc -m 8.8.8.8/$i| cut -d"=" -f2) mask_actual=$(cal_netmask_by_prefix $i "") if [[ "$mask_expected" != "$mask_actual" ]]; then echo "prefix="$i, "expected="$mask_expected, "acutal="$mask_actual exit fi done echo "IPv4 tests passed" i=-2 res=$(cal_netmask_by_prefix "$i" "") if [[ $? -ne 1 ]]; then echo "cal_netmask_by_prefix should exit when prefix<0" exit fi res=$(cal_netmask_by_prefix "$i" "") if [[ $? -ne 1 ]]; then echo "cal_netmask_by_prefix should exit when prefix<0" exit fi i=33 $(cal_netmask_by_prefix $i "") if [[ $? -ne 1 ]]; then echo "cal_netmask_by_prefix should exit when prefix>32 for IPv4" exit fi i=129 $(cal_netmask_by_prefix $i "-6") if [[ $? -ne 1 ]]; then echo "cal_netmask_by_prefix should exit when prefix>128 for IPv4" exit fi echo "Bad prefixes tests passed" echo "All tests passed"
Reported-by: Jie Li jieli@redhat.com Signed-off-by: Coiby Xu coxu@redhat.com
v3 -> v2: 1. Don't introduce "boolean" _ipv6 in kdump_static_ip and don't use fake boolean true/false which is not reliable [Kairui] 2. use ((1)) and((0)) to tell if it's IPv6 or not instead 3. Add tests for bad prefixes
v1 -> v2: 1. Check subshell exit code when calling cal_netmask_by_prefix 2. Stop using die when bad prefix is passed to cal_netmask_by_prefix 3. Remove trailing spaces
dracut-module-setup.sh | 119 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 2 deletions(-)
diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh index 8316589..aeb2e45 100755 --- a/dracut-module-setup.sh +++ b/dracut-module-setup.sh @@ -121,12 +121,122 @@ kdump_setup_dns() { done < "/etc/resolv.conf" }
+# $1: repeat times +# $2: string to be repeated +# $3: separator +repeatedly_join_str() {
- local _count="$1"
- local _str="$2"
- local _separator="$3"
- local i _res
- if [[ "$_count" -le 0 ]]; then
echo -n ""
return
- fi
- i=0
- _res="$_str"
- ((_count--))
- while [[ "$i" -lt "$_count" ]]; do
((i++))
_res="${_res}${_separator}${_str}"
- done
- echo -n "$_res"
+}
+# $1: prefix +# $2: ipv6_flag="-6" indicates it's IPv6 +# Given a prefix, calculate the netmask (equivalent of "ipcalc -m") +# by concatenating three parts, +# 1) the groups with all bits set 1 +# 2) a group with partial bits set to 0 +# 3) the groups with all bits set to 0 +cal_netmask_by_prefix() {
- local _prefix="$1"
- local _ipv6_flag="$2" _ipv6
- local _bits_per_octet=8
- local _count _res _octets_per_group _octets_total _seperator _total_groups
- local _max_group_value _max_group_value_repr _bits_per_group _tmp _zero_bits
- if [[ "$_ipv6_flag" == "-6" ]]; then
_ipv6=1
- else
_ipv6=0
- fi
- if [[ "$_prefix" -lt 0 || "$_prefix" -gt 128 ]] || \
(((!_ipv6)) && [[ "$_prefix" -gt 32 ]]); then
derror "Bad prefix:$_prefix for calculating netmask"
exit 1
- fi
- if ((_ipv6)); then
_octets_per_group=2
_octets_total=16
_seperator=":"
- else
_octets_per_group=1
_octets_total=4
_seperator="."
- fi
- _total_groups=$((_octets_total/_octets_per_group))
- _bits_per_group=$((_octets_per_group * _bits_per_octet))
- _max_group_value=$(((1 << _bits_per_group) - 1))
- if ((_ipv6)); then
_max_group_value_repr=$(printf "%x" $_max_group_value)
- else
_max_group_value_repr="$_max_group_value"
- fi
- _count=$((_prefix/_octets_per_group/_bits_per_octet))
- _first_part=$(repeatedly_join_str "$_count" "$_max_group_value_repr" "$_seperator")
- _res="$_first_part"
- _tmp=$((_octets_total*_bits_per_octet-_prefix))
- _zero_bits=$(expr $_tmp % $_bits_per_group)
- if [[ "$_zero_bits" -ne 0 ]]; then
_second_part=$((_max_group_value >> _zero_bits << _zero_bits))
if ((_ipv6)); then
_second_part=$(printf "%x" $_second_part)
fi
((_count++))
if [[ -z "$_first_part" ]]; then
_res="$_second_part"
else
_res="${_first_part}${_seperator}${_second_part}"
fi
- fi
- _count=$((_total_groups-_count))
- if [[ "$_count" -eq 0 ]]; then
echo -n "$_res"
return
- fi
- if ((_ipv6)) && [[ "$_count" -gt 1 ]] ; then
# use condensed notion for IPv6
_third_part=":"
- else
_third_part=$(repeatedly_join_str "$_count" "0" "$_seperator")
- fi
- if [[ -z "$_res" ]] && ((!_ipv6)) ; then
echo -n "${_third_part}"
- else
echo -n "${_res}${_seperator}${_third_part}"
- fi
+}
#$1: netdev name #$2: srcaddr #if it use static ip echo it, or echo null kdump_static_ip() { local _netdev="$1" _srcaddr="$2" _ipv6_flag
- local _netmask _gateway _ipaddr _target _nexthop
local _netmask _gateway _ipaddr _target _nexthop _prefix
_ipaddr=$(ip addr show dev $_netdev permanent | awk "/ $_srcaddr/.* /{print $2}")
@@ -144,7 +254,12 @@ kdump_static_ip() { _srcaddr="[$_srcaddr]" _gateway="[$_gateway]" else
_netmask=$(ipcalc -m $_ipaddr | cut -d'=' -f2)
_prefix=$(cut -d'/' -f2 <<< "$_ipaddr")
_netmask=$(cal_netmask_by_prefix "$_prefix" "$_ipv6_flag")
if [[ "$?" -ne 0 ]]; then
derror "Failed to calculate netmask for $_ipaddr"
exit 1
fifi fi echo -n "${_srcaddr}::${_gateway}:${_netmask}::"
-- 2.31.0 _______________________________________________ kexec mailing list -- kexec@lists.fedoraproject.org To unsubscribe send an email to kexec-leave@lists.fedoraproject.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/kexec@lists.fedoraproject.org Do not reply to spam on the list, report it: https://pagure.io/fedora-infrastructure
Looks good and acked for the two patch, just found some trivial code style issue I can fix when merging.
Acked-by: Kairui Song kasong@redhat.com
Thanks!
-- Best Regards, Kairui Song