diff --git a/Kconfig b/Kconfig index 54f91b8cd329169206f82f544ee1277c415d8e82..fce814d4857de870987debcf24ffc8e0fefb5e06 100644 --- a/Kconfig +++ b/Kconfig @@ -1,6 +1,20 @@ mainmenu "White Rabbit Switch configuration" +config DOTCONF_URL + + string "URL for a run-time replacement of dot-config" + help + The White Rabbit Switch is configured at run-time, + according to a dot-config .config file. The file + is the same .config you are defining now. If you + select an empty string, dot-config is not replaced + at run time. Otherwise, tftp://, ftp:// or http:// + URLs are allowed. Names are allowed if you configured + a DNS server. The special strings IPADDR and MACADDR + are substituted before retrieving the file. + Example: "tftp://morgana/wrs-config-IPADDR" + config BR2_CONFIGFILE string "Configuration file for Buildroot" default "wrs_release_br2_config" diff --git a/build/scripts/wrs_build_wraprootfs b/build/scripts/wrs_build_wraprootfs index 68f9a02cfa9b742bf228fdbcb7ac44789bb437cd..f60ac3afea313f2e94d25ef4177fd0e9a84d1629 100755 --- a/build/scripts/wrs_build_wraprootfs +++ b/build/scripts/wrs_build_wraprootfs @@ -32,7 +32,8 @@ ROOTFS_INITRAMFS="$WRS_OUTPUT_DIR/images/wrs-initramfs.gz" cat > $TMPSCRIPT << EOF . $WRS_BASE_DIR/../.config -mkdir -p $TMPFS/wr +mkdir -p $TMPFS/wr/etc +cp $WRS_BASE_DIR/../.config $TMPFS/wr/etc/dot-config cp -r $rootfs_vanilla/* $TMPFS cp -r $WRS_OUTPUT_DIR/images/wr/* $TMPFS/wr @@ -46,42 +47,6 @@ rm -rf $TMPFS/dev (cd $TMPFS && tar xzf $DEVTAR) (cd $TMPFS && ln -fs sbin/init .) -if [ ! -z "$CONFIG_NTP_SERVER" ]; then - echo "ntpserver $CONFIG_NTP_SERVER" > $TMPFS/wr/etc/wr_date.conf -fi - -if [ ! -z "$CONFIG_DNS_SERVER" ]; then - rm -f $TMPFS/etc/resolv.conf - echo "nameserver $CONFIG_DNS_SERVER" > $TMPFS/etc/resolv.conf - if [ ! -z "$CONFIG_DNS_DOMAIN" ]; then - echo "domain $CONFIG_DNS_DOMAIN" >> $TMPFS/etc/resolv.conf - fi -fi - -if [ "$CONFIG_REMOTE_SYSLOG_UDP" = "y" ]; then - sed -i 's/@@remote-host/@remote-host/' $TMPFS/etc/rsyslog.conf -fi -if [ ! -z "$CONFIG_REMOTE_SYSLOG_SERVER" ]; then - sed -i '/remote-host/ s/^##//' $TMPFS/etc/rsyslog.conf - sed -i 's/remote-host/$CONFIG_REMOTE_SYSLOG_SERVER/' $TMPFS/etc/rsyslog.conf -fi - -# Fix SNMP values: for all not-empty configs remove commend and replace value -cfgfile="$TMPFS/wr/etc/snmpd.conf" -set | grep CONFIG_SNMP | sed 's/=/ /' | while read varname value; do - if [ -z "\$value" ]; then continue; fi - sed -i "/\$varname/ s/^#//" \$cfgfile - sed -i "/\$varname/ s/\$varname/\$value/" \$cfgfile -done - -# Fix log values -cfgfile="$TMPFS/wr/sbin/start-daemons.sh" -set | grep CONFIG_WRS_LOG | sed 's/=/ /' | while read varname value; do - if [ -z "\$value" ]; then continue; fi - sed -i "/\$varname/ s,\$varname,\$value," \$cfgfile -done - - mkdir -p $TMPFS/root/.ssh #cat $HOME/.ssh/id_?sa.pub >> $TMPFS/root/.ssh/authorized_keys if [ -f $WRS_BASE_DIR/authorized_keys ]; then diff --git a/doc/wrs-developer-manual.in b/doc/wrs-developer-manual.in index 6ca9947ffc6da5a49c1d430af5033cf73a31d901..958959fae93dbdea86c257ddba96b20cdae16395 100644 --- a/doc/wrs-developer-manual.in +++ b/doc/wrs-developer-manual.in @@ -177,12 +177,11 @@ After release 3.3, we decided to add @i{Kconfig} support. This means that the first build step is expected to be ``@t{make menuconfig}'', like it happens for the kernel. The default configuration is selected by default when one of the build scripts is run, so the procedure for -the final user is the same as for v3.3 and earlier. A build with a -non-default configuration, however, is not considered as -``supported'', and @i{Kconfig} is there mainly to help developers try -new packages and setups without changing the repository or -introducing problems for other users. For some more information about -@i{Kconfig} in this package, see the @i{@sc{wrs} User's Manual}. +the final user is the same as for v3.3 and earlier. + +After release 4.1 we support dynamic reconfiguration. As opposed +to build-time configuration, run-time configuration is expected to +be frequent, and it's thus documented in the @i{@sc{wrs} Users' Manual}. The build system is set up as a mix of scripts and makefiles. Every sub-package is built by its own script and/or Makefile, and configuration is @@ -451,14 +450,9 @@ to be used at installation time. See @ref{Flashing Procedure} for details. Some details of the complete firmware archive depend on the values of active @t{Kconfig} variables. If no manual configuration is performed, -what applies is @t{configs/wrs_release_defconfig}. - -If you want to customize your configuration to install several -switches pre-configured for your network, we suggest you rebuild -the @i{firmware} archive after running @t{make menuconfig} to select -your own values - -@c FIXME FIXME FIXME: Store kconfig and build info in the archive itself +what applies is @t{configs/wrs_release_defconfig}. Please note that +we now support dynamic reconfiguration at run-time. See the @i{@sc{wrs} +Users' Manual}. @c -------------------------------------------------------------------------- @node Rebuilding Parts @@ -811,7 +805,11 @@ The main components are: @end table -The most important tools in @file{userspace/tools} are the following: +@sc{wrs} user space includes also some tools and scripts. Tools +are build from source files in @file{userspace/tools} while the +scripts are copied directly from @file{userspace/rootfs_override/wr/bin}. + +The following tools and scripts are provided: @table @file @@ -838,7 +836,7 @@ The most important tools in @file{userspace/tools} are the following: The program is a simple program for talking with serial ports. @item wr_phytool - A tool to read and write PHY registers in the switch + A tool to read and write PHY registers in the switch. @item wr_mon A simple monitor of White Rabbit status. It prints to @i{stdout} @@ -880,6 +878,20 @@ The most important tools in @file{userspace/tools} are the following: for each port and for the RTU daemon. The @t{--help} option lists all configuration items of the tool. +@item apply_dot-config + The script is used to apply @t{dot-config} settings to the + current configuration files. It is run at boot time before + any service is started. The @t{dot-config} mechanism is + documented in the @i{@sc{wrs} Users' Manual}. + +@item change_dot-config + This script changes the current @t{dot-config} file. It is + designed to be the back-end of the web interface, when changing + configuration items. The script does nothing to @i{apply} + the changes, and it only performs editing. + It is the responsibility of the caller to ensure the proper + service is restarted with the new configuration. + @item sdb-read The tool, copied from the @t{fpga-config-space} project, is documented in the next section, diff --git a/doc/wrs-user-manual.in b/doc/wrs-user-manual.in index f1edcca47fae7ced46480269facc7ea04937fc58..39e55d505cfd882bb860b656c6642d4dcc49d201 100644 --- a/doc/wrs-user-manual.in +++ b/doc/wrs-user-manual.in @@ -281,28 +281,121 @@ only be performed by the manufacturer, not the final user. @c ########################################################################## -@node Kconfig Support -@chapter Kconfig Support +@node Configuration of the Device +@chapter Configuration of the Device After release 3.3 of this software package, we added Kconfig support -to wr-switch-sw. The user can ignore this step: building as usual -from a fresh checkout of @t{wr-switch-sw} silently selects -the default configuration. +to wr-switch-sw. If you build your software image (as documented +in the @i{@sc{wrs} Developer's Manual}), you can make some +configuration choices for your customized firmware image. But most +users are not expected to rebuild. + +After release 4.1, we moved most of the configuration to run-time +(rather than build-time): the @t{.config} file that you create +with a ``@t{make menuconfig}'' or equivalent command, is now copied +to the @sc{wrs} filesystem and used during boot. Moreover, the +switch can download a new configuration at boot time, if so +configured. This allows customization of each installed switch +through a central server, without modifying the filesystem image in +each specimen. -You may exploit this @t{Kconfig} option to build firmware images -preconfigured for your own network. +@c ========================================================================== +@node Dynamic WRS Configuration +@section Dynamic WRS Configuration + +The switch can boot using its internal @sc{nand} memory or as an NFS-Root +host. In the latter case configuration can be changed on the server, +and if a unit is replaced, a change in the @sc{dhcp} database is all +that's needed to recover network operation. But this option implies +some network traffic on your management network, as well as an NFS +server able to host all of your switches. + +When a switch is booted from internal storage, we used to rely on +internal configuration (either selected at build time or modified +using @i{ssh} or the web interface). This approach doesn't scale +well to large installation, because if a device needs to be replaced, +its own configuration is lost. + +With @i{dynamic configuration}, each @sc{wrs} device loads its own +configuration file each time it is booted, and applies the choices +before starting any service. The name of the configuration file can +include the @sc{mac} or @sc{ip} address of the device, to allow +running several switches with different configurations in the same +network. + +@c ========================================================================== +@node The Configuration File +@section The Configuration File + +The main configuration file for the @sc{wrs} is +@t{/wr/etc/dot-config}. You create this file by running ``@t{make +menuconfig}'' within @t{wr-switch-sw}, and making your choices. +You can also edit the text file, or run other configurators: @t{make xconfig}, +@t{make gconfig}, @t{make config}. + +The configuration step creates @t{.config}, that you can copy to your +@sc{wrs} as @t{/wr/etc/dot-config}. After reboot, you'll see your +choices in effect. + +The first configuration choice is @t{CONFIG_DOTCONF_URL}. If the +selected string is not empty, the Switch will download a new @t{dot-config} +file, and replace the copy in local storage if it is different. If +the string is empty, no network access is performed. + +@t{CONFIG_DOTCONF_URL} is of the form +``@i{protocol}@t{://}@i{host}@t{/}@i{pathname}''. The special upper-case +strings @t{IPADDR} and @t{MACADDR} are substituted with the current +addresses of the management port of the switch. + +The three parts of the URL are as follows: + +@table @i + +@item protocol + + We support @t{http}, @t{ftp} and @t{tftp}. Any other protocols + result in an error, and the @t{dot-config} file is not replaced. + +@item host + + The host can be an IP address, or a name. In order to use + a name you must specify a valid @t{CONFIG_DNS_SERVER} and + optionally @t{CONFIG_DNS_DOMAIN}. The values + in the current @t{dot-config} are used to load the new file. + +@item path + + The pathname can include directory components and @t{IPADDR} + or @t{MACADDR} (or both). + +@end table + +For example this is a valid configuration for run-time update: + +@smallexample + CONFIG_DOTCONF_URL="tftp://morgana/wrs-config-IPADDR" + CONFIG_DNS_SERVER="192.168.16.1" + CONFIG_DNS_DOMAIN="i.gnudd.com" +@end smallexample + +And it results, in my case, in @t{wrs-config-192.168.16.9} being +served to the @sc{wrs}. -To change configuration, you are expected to run ``@t{make -menuconfig}'' (or @i{gconfig} or @i{kconfig} or the old text-mode -@i{config}) from the top-level directory of @i{wr-switch-sw}. To -silently enact the default configuration, run ``@t{make defconfig}'' -(this is done by the normal build if no configuration is present). +Please remember that the new @t{dot-config} should include a valid +@t{DOTCONF_URL} setting, or you won't be able to update the configuration +at the next boot. In any case, you can always copy a configuration +file using @i{ssh}, or use the web interface to change the configuration. +Changes performed using the web interface are immediately active, because +the web server takes proper action; the new file copied over with @i{ssh}, +or any hand-edits, are only effective at next boot, unless overwritten by +a remote configuration file. -The released firmware image uses the default configuration, but we'll -soon offer the option to change most of these values at boot-time -(by downloading configuration from a network server) or run-time. +@c ========================================================================== +@node Configuration Items that Apply at Build Time +@section Configuration Items that Apply at Build Time -The following configuration options are available +The following items in @t{dot-config} are used at build time; changing +them in the installed version has no effect: @table @code @@ -313,6 +406,31 @@ The following configuration options are available @t{configs/buildroot} directory; an absolute pathname is used unchanged. +@item CONFIG_KEEP_ROOTFS + + A boolean option for developers: if set the build script does + not delete the temporary copy of the generated filesystem and + reports its pathname in the build messages. + +@end table + +@c ========================================================================== +@node Configuration Items that Apply at Run Time +@section Configuration Items that Apply at Run Time + +The following items in @t{dot-config} are used at run time: at every +boot the value (the old one or the just-downloaded one) is used in the +appropriate way, before the respective service is started. When the +value is changed by the web interface, proper action is taken. + +@table @code + +@item CONFIG_DOTCONF_URL + + The location of a config file to be used at a replacement + the next time the system boots. See @ref{Dynamic WRS Configuration} + and @ref{The Configuration File} for details. + @item CONFIG_NTP_SERVER The NTP server used to prime White Rabbit time, at system boot. @@ -358,12 +476,6 @@ The following configuration options are available unknown facility names will generate a runtime error on the switch. All three strings default to ``@t{daemon.info}''. -@item CONFIG_KEEP_ROOTFS - - A boolean option for developers: if set the build script does - not delete the temporary copy of the generated filesystem and - reports its pathname in the build messages. - @end table @c ############################################################################ diff --git a/userspace/rootfs_override/etc/init.d/S20dot-config b/userspace/rootfs_override/etc/init.d/S20dot-config new file mode 100755 index 0000000000000000000000000000000000000000..6a31d3dc4f89887d3884ceef51721ca7ac69b511 --- /dev/null +++ b/userspace/rootfs_override/etc/init.d/S20dot-config @@ -0,0 +1,56 @@ +#!/bin/sh + +# This script applies the dot-config. It is a boot script, but actual +# functionality is moved to a separate binary, so the web interface +# could edit dot-config and run /wr/bin/apply_dot-config like we do here, +# without the need to rember wheter this is S20 or S10 during boot. + +# First, read dot-config to get the new location, if any. +dotconfig=/wr/etc/dot-config +tmpconfig=/tmp/dot-config + +if [ -f $dotconfig ]; then + . $dotconfig +fi + +# Create /etc/resolv.conf, so we can use it. /etc is ramdisk anyways +if [ ! -z "$CONFIG_DNS_SERVER" ]; then + echo "nameserver $CONFIG_DNS_SERVER" > /etc/resolv.conf + if [ ! -z "$CONFIG_DNS_DOMAIN" ]; then + echo "domain $CONFIG_DNS_DOMAIN" >> /etc/resolv.conf + fi +fi + +# If we are expected to get a new dot-conf, do it +if [ -n "$CONFIG_DOTCONF_URL" ]; then + # replace IPADDR and MACADDR, to have a device-specific name + macaddr=$(cat /sys/class/net/eth0/address) + ipaddr=$(ifconfig eth0 | grep inet | cut -d: -f 2 | cut '-d ' -f 1) + URL=$(echo $CONFIG_DOTCONF_URL | \ + sed -e s/MACADDR/$macaddr/ -e s/IPADDR/$ipaddr/) + # split the parts, as we need to handle tftp by hand + proto=$(echo $URL | cut -d: -f 1) + host=$(echo $URL | cut -d/ -f 3) + filename=$(echo $URL | cut -d/ -f 4-) + + rm -f $tmpconfig + case $proto in + http|ftp) + wget $URL -O $tmpconfig + ;; + tftp) + tftp -g -r "$filename" -l $tmpconfig $host + ;; + *) + echo "Invalid URL for dot-config: \"$URL\"" >& 2 + ;; + esac + # If it exists and it is not empty or awfully small, trust it + if [ -f $tmpconfig ] && + [ $(cat $tmpconfig | wc -c) -gt 200 ]; then + cmp -s $tmpconfig $dotconfig || cp $tmpconfig $dotconfig + fi +fi + +# Finally, apply what we have, be it old or new +. /wr/bin/apply_dot-config diff --git a/userspace/rootfs_override/etc/rsyslog.conf b/userspace/rootfs_override/etc/rsyslog.conf.in similarity index 100% rename from userspace/rootfs_override/etc/rsyslog.conf rename to userspace/rootfs_override/etc/rsyslog.conf.in diff --git a/userspace/rootfs_override/wr/bin/apply_dot-config b/userspace/rootfs_override/wr/bin/apply_dot-config new file mode 100755 index 0000000000000000000000000000000000000000..8194a2dfbb9c34c61e97be4a0d580d76086d6e2a --- /dev/null +++ b/userspace/rootfs_override/wr/bin/apply_dot-config @@ -0,0 +1,77 @@ +#!/bin/sh + +# This script applies the current dot-config to make +# the choices users wanted. You can change the dot-config on flash, +# and call this script to apply changes (please note that some changes +# require restarting running processes). The script is called at +# every boot by /etc/init.d/S20dot-config + +# We create a temporary file in /tmp, to avoid wearing flash if not +# needed. Then we replace the real file if different. + +T=$(mktemp /tmp/config-XXXXXX) + +copy_conf() { + # busybox cmp exits 1 or 2 according to GNU man page + for dest in $*; do + cmp -s $T $1 || cp $T $1 + done +} + +# Check and complain, but we need to edit some files even if unconfigured. +if [ -f /wr/etc/dot-config ]; then + . /wr/etc/dot-config + configured=true +else + echo "No /wr/etc/dot-config to use" >& 2 + configured=false +fi + +##### Actual configuration actions start here. + +# A non-existent wr_date.conf means no NTP. So "rm" if unconfigured +if [ ! -z "$CONFIG_NTP_SERVER" ]; then + echo "ntpserver $CONFIG_NTP_SERVER" > $T + copy_conf /wr/etc/wr_date.conf +else + rm -f /wr/etc/wr_date.conf +fi + +# /etc/resolv.conf can be empty, so start empty +> $T +if [ ! -z "$CONFIG_DNS_SERVER" ]; then + echo "nameserver $CONFIG_DNS_SERVER" >> $T + if [ ! -z "$CONFIG_DNS_DOMAIN" ]; then + echo "domain $CONFIG_DNS_DOMAIN" >> $T + fi +fi +copy_conf /etc/resolv.conf /usr/etc/resolv.conf + +# rsyslog.conf is created from a template file, and busybox sed has -i +cp /usr/etc/rsyslog.conf.in $T +if [ "$CONFIG_REMOTE_SYSLOG_UDP" = "y" ]; then + sed -i 's/@@remote-host/@remote-host/' $T +fi +if [ ! -z "$CONFIG_REMOTE_SYSLOG_SERVER" ]; then + sed -i '/remote-host/ s/^##//' $T + sed -i "s/remote-host/$CONFIG_REMOTE_SYSLOG_SERVER/" $T +fi +copy_conf /etc/rsyslog.conf /usr/etc/rsyslog.conf + +# Fix SNMP values: for all not-empty configs remove comment and replace value +cp /wr/etc/snmpd.conf.in $T +set | grep CONFIG_SNMP | sed 's/=/ /' | while read varname value; do + if [ -z "$value" ]; then continue; fi + sed -i "/$varname/ s/^#//" $T + sed -i "/$varname/ s/$varname/$value/" $T +done +copy_conf /wr/etc/snmpd.conf + +# Fix log values +cp /wr/sbin/start-daemons.sh.in $T +set | grep CONFIG_WRS_LOG | sed 's/=/ /' | while read varname value; do + if [ -z "$value" ]; then continue; fi + sed -i "/$varname/ s,$varname,$value," $T +done +copy_conf /wr/sbin/start-daemons.sh + diff --git a/userspace/rootfs_override/wr/bin/change_dot-config b/userspace/rootfs_override/wr/bin/change_dot-config new file mode 100755 index 0000000000000000000000000000000000000000..5d80a5898bf50569b2e4fd6f09e9d9d256aa0908 --- /dev/null +++ b/userspace/rootfs_override/wr/bin/change_dot-config @@ -0,0 +1,26 @@ +#!/bin/sh + +# Change a configuration item in dot-config. "=n" is special and it means +# the option is being unset. "=y" remains unquoted, all the rest is quoted. +# We still lack support for integers, not used in wrs' .config so far. + +dotconfig="/wr/etc/dot-config" + +for action in "$*"; do + # We accept both CONFIG_THIS= and THIS= + item="CONFIG_$(echo $action | cut -d= -f 1 | sed 's/^CONFIG_//')" + value=$(echo $action | cut -d= -f 2) + if [ "$value" = "n" ]; then + line="# $item is not set" + + else + if [ "$value" = "y" ]; then + line="${item}=y" + else + line="${item}=\"$value\"" + fi + fi + # now, a config item may be a substring of another one: careful + sed -i -e "/^${item}=/d" -e "/# ${item} is/d" $dotconfig + echo $line >> $dotconfig +done diff --git a/userspace/rootfs_override/wr/etc/snmpd.conf b/userspace/rootfs_override/wr/etc/snmpd.conf.in similarity index 100% rename from userspace/rootfs_override/wr/etc/snmpd.conf rename to userspace/rootfs_override/wr/etc/snmpd.conf.in diff --git a/userspace/rootfs_override/wr/sbin/start-daemons.sh b/userspace/rootfs_override/wr/sbin/start-daemons.sh.in similarity index 100% rename from userspace/rootfs_override/wr/sbin/start-daemons.sh rename to userspace/rootfs_override/wr/sbin/start-daemons.sh.in