This post is a bit long, please please be patient. Thanks very much:)
First of all, I wanna say "where is my original /etc/conf.d/net".
After I emerged baselayout2 and openrc, something I changed(e.g. /etc/conf.d/local.start, /lib/rcscripts/net/arping.sh, etc.) is reserved(That's good:), something is updated by dispatch-conf(normally), but my original /etc/conf.d/net is covered by an empty file without prompt. Why??? I lost all net configs. Sigh
I saw what alex.blackbit posted in thread "openrc support thread"
alex.blackbit wrote:@developers:
baselayout-2 brings feelable speedup during boot. well done.
nevertheless i suggest to add at least a note that the network config files are beeing deleted.
Agree! I have the same feeling and complaining.
Ok, let me talk in this thread.
Why I opened this new thread instead of following that sticky thread "openrc support thread" is that there are too many posts, too many pages, but I want you people to pay much attention to this problem, this openrc problem.
What I'm talking about below is not merely bug, I think, but most may be flaw, may be something need to be changed more proper and easier to use.
When using baselayout1, how to write net config has confused me for some time, not a long time but not a short time either.
The net config example provided is not clear for users who want to config some complicated circumstances. So are the related online docs.
So, in order to get to know those too many variables, and the relationship between them, and how they influence on each other, I have to read the net scripts, including /etc/init.d/net, /lib/rcscripts/net/* and something related. Finally I wrote a perfect net config (at least I think so, but lost with pity:( ), and could employ those vars flexibly, however that's not an easy process.
Now I began to use baselayout2 and openrc. The situation is so much same as using baselayout1. I read some scripts about net in openrc, of cource including net.example. But I am still confused now. More confused.
In
http://www.gentoo.org/doc/en/openrc-migration.xml, I'm told that "/etc/conf.d/net no longer uses bash-style arrays for configuration". And the doc take an example:
Code: Select all
Old style
config_eth0=( "192.168.1.37 netmask 255.255.255.0 brd 192.168.1.255" )
Code: Select all
New style
config_eth0="192.168.1.37 netmask 255.255.255.0 brd 192.168.1.255"
The local net.example also take some examples:
Code: Select all
config_eth0="192.168.0.2/24"
config_eth0="192.168.0.2/24 192.168.0.3/24 192.168.0.4/24"
config_eth0="192.168.0.{2..4}/24"
config_eth0="noop 192.168.0.2/24"
config_eth0="null"
config_eth0="dhcp"
config_eth0="arping"
config_192168000001="192.168.0.2/24"
All the examples forget about one important thing: If /etc/conf.d/net no longer uses bash-style arrays for configuration now, how to represent multi-config in one config variable, how to convert the old bash-style arrays to new style (You would say there is a convertion example above, but that is too simple, that example has only one config in config variable).
These examples above seem to tell users you can separate multi-config by whitespace in one config variable (config_eth0="noop 192.168.0.2/24" and config_eth0="192.168.0.2/24 192.168.0.3/24 192.168.0.4/24").
So you may write a net config like this:
Code: Select all
config_eth0="192.168.0.123/24 arping"
dns_servers_192168000001_001234567890="202.202.202.202"
gateways_eth0="192.168.0.1,00:12:34:56:78:90"
routes_eth0="default via 192.168.0.1"
dns_servers_eth0="192.168.0.1"
(This config is mine actually)
Then /etc/init.d/net.eth0 restart
Then ... congratulations, you got an infinite loop. Net init script perform "add address first; then arping" endlessly.
If change config_eth0 into this:
Code: Select all
config_eth0="192.168.0.123/24
arping"
, everything is right.
This is the problem1.
If you want to set two addresses to eth0 with non-CIDR address style, how do you do? Before, when using baselayout1, you can write like this:
Code: Select all
config_eth0=( "192.168.0.2 netmask 255.255.255.0", "192.168.0.33 netmask 255.255.255.0" )
But now, how to write, as bash array is not supported any longer. Write like this? Separate two config by whitespace too?
Code: Select all
config_eth0="192.168.0.2 netmask 255.255.255.0 192.168.0.33 netmask 255.255.255.0"
Of course, it's invalid. Which whitespace should be considered as the separator of two config? There is no example to explain this case.
This is the problem2.
The "routes" variable has same problem, but fortunately there is an example to show users how to set routes.
Code: Select all
routes_eth0="default via 192.168.0.1
10.0.0.0/8 via 192.168.0.1
::/0"
So you may guess net init script uses newline to separate multi-config in one variable. So you may write two addresses config like this:
Code: Select all
config_eth0="192.168.0.2 netmask 255.255.255.0
192.168.0.33 netmask 255.255.255.0"
But why some "config_eth0" variable still uses whitespace to separate multi-config (see above), and some other variables uses whitespace too(like preferred_aps="'SSID 1' 'SSID 2'").
This is one confusing point. However, you would say if config value contains whitespace of its own, you can not use whitespace as separator, you must use newline instead, that's simple. Yes, maybe you are right, but how do you explain the problem1 above. And neither local net.example nor online docs tell me this explicitily. Neither of them tell me newline is a prefered separator either. So all of these are just guess.
There are so many implicit questions: perfered_aps="'SSID 1' 'SSID 2'" and perfered_aps="SSID 1\nSSID 2", which one is correct or better? Can I use config_eth0="'192.168.0.2 netmask 255.255.255.0' '192.168.0.33 netmask 255.255.255.0'" instead of config_eth0="192.168.0.2 netmask 255.255.255.0\n192.168.0.33 netmask 255.255.255.0"? Why does config_eth0="192.168.0.123/24 arping" cause an infinite loop, however, at least it is valid (the whitespace in its value is not ambiguous).
So in order to understand clearly, I have to read net init scripts (/lib/rc/sh/net.sh, /lib/rc/net/*, etc.) again.
In the net init scripts, the code proves those guess mentioned above.
In /lib/rc/sh/net.sh, there is a variable
Its value is a newline.
And note two functions:
_get_array and
_load_config.
After read them, you can know _get_array convert bash array into one variable, the elements of array is separated by newline in that variable.
_load_config uses newline as the default IFS. In addition, it also supports one-line config separated by whitespace ("noop 192.168.0.123/24" or "192.168.0.2/24 192.168.0.3/24" or "192.168.0.2/24 arping"). The code below is part of _load_config.
Code: Select all
local IFS="$__IFS"
set -- ${config}
# We should support a space separated array for cidr configs
if [ $# = 1 ]; then
unset IFS
set -- ${config}
# Of course, we may have a single address added old style.
case "$2" in
netmask|broadcast|brd|brd+)
local IFS="$__IFS"
set -- ${config}
;;
esac
fi
Ok, after read the code above I know exactly how net init script parse "config_eth0" variable, i.e. I know exactly how to write "config_eth0" variable.
But there is still a problem, the problem1 above. Why "192.168.0.123/24 arping" causes an infinite loop. And this is a bug I am sure.
_load_config parse "192.168.0.123/24 arping" into "192.168.0.123/24" and "arping", so net init script add address "192.168.0.123/24" first, and perform arping_start which is in /lib/rc/net/arping.sh. The bug is just in the latter.
In arping_start, there are such code like this:
Code: Select all
_configure_variables ${conf}
...
# Ensure that we have a valid config - ie arping is no longer there
local IFS="$__IFS"
for i in $(_get_array "config_${IFVAR}"); do
if [ "${i}" = "arping" ]; then
eend 1 "No config found for ${ip} (config_${conf}="...")"
continue 2
fi
done
unset IFS
_load_config
This code means that arping_start convert config_${gateways} to new config_${iface}, and load the new config. If there is no config_${gateways} or config_${gateways} still contains "arping", then _load_config would not be called in order to ensure the old config or the new config which contains "arping" would not be loaded again by mistake. I.e, If the config_${iface} is invalid, if the config_${iface} still contains "arping" (old config or new config which contains "arping"), then _load_config would not be called again, because calling _load_config in this situation would cause an infinite loop.
But the bug is just in this code.
Generally, user would write net config like this to employ arping module.
Code: Select all
config_eth0="arping"
gateways_eth0="192.168.0.1,00:12:34:56:78:90"
config_192168000001_001234567890="192.168.0.123/24"
config_eth0="arping" causes arping_start is called. arping_start calls "_configure_variables ${conf}" to convert config_192168000001_001234567890 to config_eth0, so now config_eth0="192.168.0.123/24", there is not "arping" in config, so arping_start go on to call _load_config to load new config. Everything is ok.
But in my sample above, my net config is:
Code: Select all
config_eth0="192.168.0.123/24 arping"
dns_servers_192168000001_001234567890="202.202.202.202"
gateways_eth0="192.168.0.1,00:12:34:56:78:90"
routes_eth0="default via 192.168.0.1"
dns_servers_eth0="192.168.0.1"
This config is meant to config a static ip address as 192.168.0.123 with netmask 255.255.255.0 and gateway as 192.168.0.1. And if gateway's mac is 00:12:34:56:78:90, dns server is 202.202.202.202, otherwise dns server is 192.168.0.1.
There is no config_192168000001_001234567890 defined. So arping_start should not call _load_config.
In order to confirm whether config is valid or not, arping_start checks if "arping" is one element of the config_${iface} value. There is no config_${gateways} in the above problem-config, so config_${iface} still the old one -- "192.168.0.123/24 arping". "arping" is one element of config_${iface} value, so arping_start should not call _load_config.
But the fact is _load_config is called, "192.168.0.123/24 arping" is loaded again, so net init script add address again, call arping_start again, and arping_start call _load_config again, and net init script add address again, call arping_start again .... Inifinite loop.
Why _load_config is called. Because of this:
Code: Select all
local IFS="$__IFS"
for i in $(_get_array "config_${IFVAR}"); do
arping_start doesn't support one-line config separated by whitespace. To it, only newline can be separator. But in my config, config_eth0="192.168.0.123/24 arping", arping_start considers this as one config, not two. This config has only one element "192.168.0.123/24 arping" which is not "arping", so _local_config is called.
So, come to the conclusion, if
_load_config supports two kinds of separator in config_${iface} variable, newline and whitespace, the other functions which would use config_${iface} variable also need support newline and whitespace both as separator. That means the below code belonging to _load_config need to be reused in place:
Code: Select all
local IFS="$__IFS"
set -- ${config}
# We should support a space separated array for cidr configs
if [ $# = 1 ]; then
unset IFS
set -- ${config}
# Of course, we may have a single address added old style.
case "$2" in
netmask|broadcast|brd|brd+)
local IFS="$__IFS"
set -- ${config}
;;
esac
fi
OK, OK, this post is much longer than I expected. What I'm talking about is the net config is not clear enough to use, the docs miss some important concepts to make things explicit (of course, there are so many examples in docs, but they are just examples, they are not explicit enough to explain some problem) and there is a bug in arping_start (may be in other related functions too).
BTW: when arping_start find the config is not valid, it will print an error message which is "No config found for ${ip} (config_${conf}="...")". But I don't think this message is explicit enough either. Because if somebody defines config_192168000001_001234567890="arping", then he will get the error message: "No config found for ${ip} (config_${conf}="...")", then he will be confused if he hasn't read the code of arping_start.