On Wed, Apr 07, 2021 at 02:17:16PM +0800, Kairui Song wrote:
On Fri, Mar 26, 2021 at 10:46 PM Coiby Xu <coxu(a)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 true)
> if [[ "$mask_expected" != "$mask_actual" ]]; then
> echo $i, "expected=", $mask_expected, "acutal=",
$mask_actual
> fi
> done
>
> 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 false)
> if [[ "$mask_expected" != "$mask_actual" ]]; then
> echo $i, "expected=", $mask_expected, "acutal=",
$mask_actual
> fi
> done
>
> Reported-by: Jie Li <jieli(a)redhat.com>
> Signed-off-by: Coiby Xu <coxu(a)redhat.com>
> ---
> 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 | 115 ++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 113 insertions(+), 2 deletions(-)
>
> diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh
> index 8316589..ea6f7ea 100755
> --- a/dracut-module-setup.sh
> +++ b/dracut-module-setup.sh
> @@ -121,17 +121,123 @@ 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 or not
> +# 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="$2"
> + 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 [[ "$_prefix" -lt 0 || ("$_ipv6" &&
"$_prefix" -gt 128) || \
> + (!"$_ipv6" && "$_prefix" -gt 32) ]]; then
Hi Coiby, I think you missed a space here, should it be like this?
(! "$_ipv6" && "$_prefix" -gt 32) ]]; then
Hi Kairui,
Thanks for catching this error! I will fix it in v3.
> + 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
> + local _ipv6=false
>
> _ipaddr=$(ip addr show dev $_netdev permanent | awk "/ $_srcaddr\/.*
/{print \$2}")
>
> if is_ipv6_address $_srcaddr; then
> _ipv6_flag="-6"
> + _ipv6=true
> fi
>
> if [ -n "$_ipaddr" ]; then
> @@ -144,7 +250,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")
I think we can avoid introduce a new _ipv6 variable by just passing
_ipv6_flag, and detect if the flag is empty in cal_netmask_by_prefix.
> + if [[ "$?" -ne 0 ]]; then
> + derror "Failed to calculate netmask for $_ipaddr"
> + exit 1
> + fi
> fi
> echo -n "${_srcaddr}::${_gateway}:${_netmask}::"
> fi
> --
> 2.31.0
> _______________________________________________
> kexec mailing list -- kexec(a)lists.fedoraproject.org
> To unsubscribe send an email to kexec-leave(a)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
--
Best Regards,
Kairui Song
--
Best regards,
Coiby