[PATCH 17/21] net: Provide new way to configure network devices
Sascha Hauer
s.hauer at pengutronix.de
Fri Nov 24 00:12:33 PST 2017
This provides a new way to configure network interfaces based
on nvvars. A network interface can now be configured with variables
in the nv.dev.<ethname>.* namespace. There is a new network device
parameter "mode" which specifies the mode used to obtain IP settings.
The mode can be "dhcp", "static" or "disabled":
nv.dev.eth0.mode=dhcp
(ipaddr, netmask are ignored in this setting)
nv.dev.eth0.mode=static
nv.dev.eth0.ipaddr=192.168.0.17
nv.dev.eth0.netmask=255.255.0.0
nv.dev.eth0.mode=disabled
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
include/net.h | 6 ++
net/eth.c | 15 ++++
net/ifup.c | 235 +++++++++++++++++++++++++++++++++++++---------------------
3 files changed, 172 insertions(+), 84 deletions(-)
diff --git a/include/net.h b/include/net.h
index c72197b2f0..9b57dad909 100644
--- a/include/net.h
+++ b/include/net.h
@@ -61,6 +61,11 @@ struct eth_device {
IPaddr_t netmask;
char ethaddr[6];
char *bootarg;
+
+#define ETH_MODE_DHCP 0
+#define ETH_MODE_STATIC 1
+#define ETH_MODE_DISABLED 2
+ unsigned int global_mode;
};
#define dev_to_edev(d) container_of(d, struct eth_device, dev)
@@ -469,6 +474,7 @@ void led_trigger_network(enum led_trigger trigger);
#define IFUP_FLAG_FORCE (1 << 0)
+int ifup_edev(struct eth_device *edev);
int ifup(const char *name, unsigned flags);
int ifup_all(unsigned flags);
diff --git a/net/eth.c b/net/eth.c
index a8f21b2277..a9869f7d9d 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -21,12 +21,18 @@
#include <command.h>
#include <complete.h>
#include <driver.h>
+#include <unistd.h>
#include <init.h>
+#include <dhcp.h>
#include <net.h>
#include <of.h>
#include <linux/phy.h>
#include <errno.h>
#include <malloc.h>
+#include <globalvar.h>
+#include <environment.h>
+#include <linux/ctype.h>
+#include <linux/stat.h>
static uint64_t last_link_check;
@@ -340,6 +346,12 @@ late_initcall(eth_register_of_fixup);
extern IPaddr_t net_serverip;
extern IPaddr_t net_gateway;
+static const char * const eth_mode_names[] = {
+ [ETH_MODE_DHCP] = "dhcp",
+ [ETH_MODE_STATIC] = "static",
+ [ETH_MODE_DISABLED] = "disabled",
+};
+
int eth_register(struct eth_device *edev)
{
struct device_d *dev = &edev->dev;
@@ -378,6 +390,9 @@ int eth_register(struct eth_device *edev)
edev->ethaddr, edev);
edev->bootarg = xstrdup("");
dev_add_param_string(dev, "linux.bootargs", NULL, NULL, &edev->bootarg, NULL);
+ dev_add_param_enum(dev, "mode", NULL, NULL, &edev->global_mode,
+ eth_mode_names, ARRAY_SIZE(eth_mode_names),
+ NULL);
if (edev->init)
edev->init(edev);
diff --git a/net/ifup.c b/net/ifup.c
index a65956bba1..7df9f587cd 100644
--- a/net/ifup.c
+++ b/net/ifup.c
@@ -25,116 +25,147 @@
#include <dhcp.h>
#include <net.h>
#include <fs.h>
+#include <globalvar.h>
+#include <string.h>
+#include <driver.h>
#include <linux/stat.h>
-static int eth_discover(const char *name)
+static int eth_discover(char *file)
{
- char *cmd_discover;
struct stat s;
int ret;
- cmd_discover = basprintf("/env/network/%s-discover", name);
-
- ret = stat(cmd_discover, &s);
- if (ret)
+ ret = stat(file, &s);
+ if (ret) {
+ ret = 0;
goto out;
+ }
- ret = run_command(cmd_discover);
+ ret = run_command(file);
if (ret) {
- pr_err("Running '%s' failed with %d\n", cmd_discover, ret);
+ pr_err("Running '%s' failed with %d\n", file, ret);
goto out;
}
out:
- free(cmd_discover);
+ free(file);
return ret;
}
-static char *vars[] = {
- "ipaddr",
- "netmask",
- "gateway",
- "serverip",
-};
-
-static int eth_set_param(struct device_d *dev, const char *param)
+static int eth_discover_ethname(const char *ethname)
{
- const char *value = getenv(param);
-
- if (!value)
- return 0;
- if (!*value)
- return 0;
+ return eth_discover(basprintf("/env/network/%s-discover", ethname));
+}
- return dev_set_param(dev, param, value);
+static int eth_discover_file(const char *filename)
+{
+ return eth_discover(basprintf("/env/network/%s", filename));
}
-int ifup(const char *name, unsigned flags)
+static int source_env_network(struct eth_device *edev)
{
- int ret;
- char *cmd;
- const char *ip;
- int i;
- struct device_d *dev;
- struct eth_device *edev = eth_get_byname(name);
+ char *vars[] = {
+ "ipaddr",
+ "netmask",
+ "gateway",
+ "serverip",
+ "ethaddr",
+ "ip",
+ };
+ IPaddr_t ipaddr, netmask, gateway, serverip;
+ unsigned char ethaddr[6];
+ char *file, *cmd;
+ const char *ethaddrstr, *modestr;
+ int ret, mode, ethaddr_valid = 0, i;
+ struct stat s;
- if (edev && edev->ipaddr && !(flags & IFUP_FLAG_FORCE))
+ file = basprintf("/env/network/%s", edev->devname);
+ ret = stat(file, &s);
+ if (ret) {
+ free(file);
return 0;
+ }
- env_push_context();
+ dev_info(&edev->dev, "/env/network/%s is deprecated.\n"
+ "Use nv.dev.%s.* nvvars to configure your network device instead\n",
+ edev->devname, edev->devname);
- setenv("ip", "");
+ env_push_context();
for (i = 0; i < ARRAY_SIZE(vars); i++)
setenv(vars[i], "");
- cmd = basprintf("source /env/network/%s", name);
-
+ cmd = basprintf("source /env/network/%s", edev->devname);
ret = run_command(cmd);
if (ret) {
pr_err("Running '%s' failed with %d\n", cmd, ret);
goto out;
}
- eth_discover(name);
+ ipaddr = getenv_ip("ipaddr");
+ netmask = getenv_ip("netmask");
+ gateway = getenv_ip("gateway");
+ serverip = getenv_ip("serverip");
+ ethaddrstr = getenv("ethaddr");
+ if (ethaddrstr && *ethaddrstr) {
+ ret = string_to_ethaddr(ethaddrstr, ethaddr);
+ if (ret) {
+ dev_err(&edev->dev, "Cannot parse ethaddr \"%s\"\n", ethaddrstr);
+ ret = -EINVAL;
+ goto out;
+ }
+ ethaddr_valid = 1;
+ }
- dev = get_device_by_name(name);
- if (!dev) {
- pr_err("Cannot find device %s\n", name);
+ modestr = getenv("ip");
+ if (!modestr) {
+ dev_err(&edev->dev, "No mode specified in \"ip\" variable\n");
+ ret = -EINVAL;
goto out;
}
- ret = eth_set_param(dev, "ethaddr");
- if (ret)
+ if (!strcmp(modestr, "static")) {
+ mode = ETH_MODE_STATIC;
+ } else if (!strcmp(modestr, "dhcp")) {
+ mode = ETH_MODE_DHCP;
+ } else {
+ dev_err(&edev->dev, "Invalid ip mode \"%s\" found\n", modestr);
+ ret = -EINVAL;
goto out;
+ }
- ip = getenv("ip");
- if (!ip)
- ip = "";
+ edev->global_mode = mode;
- if (!strcmp(ip, "dhcp")) {
- IPaddr_t serverip;
+ if (ethaddr_valid)
+ memcpy(edev->ethaddr, ethaddr, 6);
- serverip = getenv_ip("serverip");
+ if (mode == ETH_MODE_STATIC) {
+ edev->ipaddr = ipaddr;
+ edev->netmask = netmask;
+ if (gateway)
+ net_set_gateway(gateway);
if (serverip)
- net_set_serverip(serverip, false);
+ net_set_serverip(serverip, true);
+ }
- ret = dhcp(edev, NULL);
- if (ret)
- goto out;
- dev_set_param(dev, "linux.bootargs", "ip=dhcp");
- } else if (!strcmp(ip, "static")) {
+ ret = 0;
+
+out:
+ env_pop_context();
+ free(cmd);
+ free(file);
+
+ return ret;
+}
+
+static void set_linux_bootarg(struct eth_device *edev)
+{
+ if (edev->global_mode == ETH_MODE_STATIC) {
char *bootarg;
IPaddr_t serverip;
IPaddr_t gateway;
- for (i = 0; i < ARRAY_SIZE(vars); i++) {
- ret = eth_set_param(dev, vars[i]);
- if (ret)
- goto out;
- }
-
serverip = net_get_serverip();
gateway = net_get_gateway();
@@ -143,46 +174,82 @@ int ifup(const char *name, unsigned flags)
&serverip,
&gateway,
&edev->netmask);
- dev_set_param(dev, "linux.bootargs", bootarg);
+ dev_set_param(&edev->dev, "linux.bootargs", bootarg);
free(bootarg);
- } else {
- pr_err("unknown ip type: %s\n", ip);
- ret = -EINVAL;
- goto out;
+ } else if (edev->global_mode == ETH_MODE_DHCP) {
+ dev_set_param(&edev->dev, "linux.bootargs", "ip=dhcp");
}
+}
- ret = 0;
-out:
- env_pop_context();
- free(cmd);
+int ifup_edev(struct eth_device *edev)
+{
+ int ret;
- return ret;
+ if (edev->global_mode == ETH_MODE_DISABLED)
+ return 0;
+
+ ret = source_env_network(edev);
+ if (ret)
+ return ret;
+
+ if (edev->global_mode == ETH_MODE_DHCP) {
+ if (IS_ENABLED(CONFIG_NET_DHCP)) {
+ ret = dhcp(edev, NULL);
+ } else {
+ dev_err(&edev->dev, "DHCP support not available\n");
+ ret = -ENOSYS;
+ }
+ if (ret)
+ return ret;
+ }
+
+ set_linux_bootarg(edev);
+
+ return 0;
+}
+
+int ifup(const char *ethname, unsigned flags)
+{
+ struct eth_device *edev;
+ int ret;
+
+ ret = eth_discover_ethname(ethname);
+ if (ret)
+ return ret;
+
+ edev = eth_get_byname(ethname);
+ if (!edev)
+ return -ENODEV;
+
+ return ifup_edev(edev);
}
int ifup_all(unsigned flags)
{
+ struct eth_device *edev;
DIR *dir;
struct dirent *d;
dir = opendir("/env/network");
- if (!dir)
- return -ENOENT;
-
- while ((d = readdir(dir))) {
- if (*d->d_name == '.')
- continue;
- /*
- * Skip xxx-discover files since these are no
- * network configuration files, but scripts to bring
- * up network interface xxx.
- */
- if (strstr(d->d_name, "-discover"))
- continue;
- ifup(d->d_name, flags);
+ if (dir) {
+
+ while ((d = readdir(dir))) {
+ if (*d->d_name == '.')
+ continue;
+ if (!strstr(d->d_name, "-discover"))
+ continue;
+
+ eth_discover_file(d->d_name);
+ }
}
closedir(dir);
+ device_detect_all();
+
+ for_each_netdev(edev)
+ ifup_edev(edev);
+
return 0;
}
--
2.11.0
More information about the barebox
mailing list