From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Cc: Ahmad Fatoum <a.fatoum@pengutronix.de>
Subject: [PATCH v2 1/3] net: ifup: have ifup -a poll for link up in parallel
Date: Mon, 30 Jan 2023 08:20:55 +0100 [thread overview]
Message-ID: <20230130072057.34349-2-a.fatoum@pengutronix.de> (raw)
In-Reply-To: <20230130072057.34349-1-a.fatoum@pengutronix.de>
DHCP is usually fairly quick, but link up check timeout is 10 seconds,
which adds up, especially on systems with bigger DSA switches.
The workaround is to set ethX.mode=disabled for other ports, but let's
improve the default a bit and have barebox poll link ups in parallel, so
instead of (number_of_ports_wihout_link * 10s), we just wait 10s at
most.
For setups where this is a problem, users may revert to ifup in sequence
by doing ifup -a -s.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
v1 -> v2:
- new patch
---
include/net.h | 3 ++
net/eth.c | 28 ++++++++++----
net/ifup.c | 103 ++++++++++++++++++++++++++++++++++++++++----------
3 files changed, 105 insertions(+), 29 deletions(-)
diff --git a/include/net.h b/include/net.h
index 0555b0bd6bed..a7da282412fa 100644
--- a/include/net.h
+++ b/include/net.h
@@ -109,6 +109,7 @@ static inline int eth_send_raw(struct eth_device *edev, void *packet,
int eth_register(struct eth_device* dev); /* Register network device */
void eth_unregister(struct eth_device* dev); /* Unregister network device */
int eth_set_ethaddr(struct eth_device *edev, const char *ethaddr);
+int eth_carrier_poll_once(struct eth_device *edev);
int eth_open(struct eth_device *edev);
void eth_close(struct eth_device *edev);
int eth_send(struct eth_device *edev, void *packet, int length); /* Send a packet */
@@ -511,6 +512,8 @@ int net_icmp_send(struct net_connection *con, int len);
void led_trigger_network(enum led_trigger trigger);
#define IFUP_FLAG_FORCE (1 << 0)
+#define IFUP_FLAG_PARALLEL (1 << 1)
+#define IFUP_FLAG_SKIP_CONF (1 << 2)
int ifup_edev(struct eth_device *edev, unsigned flags);
int ifup(const char *name, unsigned flags);
diff --git a/net/eth.c b/net/eth.c
index 6fb64afea024..ccac5e2a6488 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -176,13 +176,29 @@ int eth_complete(struct string_list *sl, char *instr)
}
#endif
+int eth_carrier_poll_once(struct eth_device *edev)
+{
+ int ret;
+
+ if (!IS_ENABLED(CONFIG_PHYLIB))
+ return 0;
+
+ if (!edev->phydev)
+ return 0;
+
+ ret = phy_update_status(edev->phydev);
+ if (ret)
+ return ret;
+
+ edev->last_link_check = get_time_ns();
+ return edev->phydev->link ? 0 : -ENETDOWN;
+}
+
/*
* Check for link if we haven't done so for longer.
*/
static int eth_carrier_check(struct eth_device *edev, bool may_wait)
{
- int ret;
-
if (!IS_ENABLED(CONFIG_PHYLIB))
return 0;
@@ -190,12 +206,8 @@ static int eth_carrier_check(struct eth_device *edev, bool may_wait)
return 0;
if (!edev->last_link_check ||
- is_timeout(edev->last_link_check, 5 * SECOND)) {
- ret = phy_update_status(edev->phydev);
- if (ret)
- return ret;
- edev->last_link_check = get_time_ns();
- }
+ is_timeout(edev->last_link_check, 5 * SECOND))
+ eth_carrier_poll_once(edev);
if (may_wait && !edev->phydev->link) {
phy_wait_aneg_done(edev->phydev);
diff --git a/net/ifup.c b/net/ifup.c
index e4d5374db3ae..c491ea03c1c8 100644
--- a/net/ifup.c
+++ b/net/ifup.c
@@ -179,6 +179,28 @@ static void set_linux_bootarg(struct eth_device *edev)
}
}
+static int ifup_edev_conf(struct eth_device *edev, unsigned flags)
+{
+ int 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);
+
+ edev->ifup = true;
+
+ return 0;
+}
+
int ifup_edev(struct eth_device *edev, unsigned flags)
{
int ret;
@@ -205,22 +227,10 @@ int ifup_edev(struct eth_device *edev, unsigned flags)
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);
-
- edev->ifup = true;
+ if (flags & IFUP_FLAG_SKIP_CONF)
+ return 1;
- return 0;
+ return ifup_edev_conf(edev, flags);
}
void ifdown_edev(struct eth_device *edev)
@@ -260,9 +270,54 @@ int ifdown(const char *ethname)
static int net_ifup_force_detect;
-int ifup_all(unsigned flags)
+static bool ifup_edev_need_conf(struct eth_device *edev)
+{
+ return edev->active && !edev->ifup &&
+ edev->global_mode != ETH_MODE_DISABLED;
+}
+
+static void __ifup_all_parallel(unsigned flags)
{
struct eth_device *edev;
+ unsigned netdev_count = 0;
+ u64 start;
+ int ret;
+
+ for_each_netdev(edev) {
+ ret = ifup_edev(edev, flags | IFUP_FLAG_SKIP_CONF);
+ if (ret == 1)
+ netdev_count++;
+ }
+
+ start = get_time_ns();
+ while (netdev_count && !is_timeout(start, PHY_AN_TIMEOUT * SECOND)) {
+ for_each_netdev(edev) {
+ if (!ifup_edev_need_conf(edev))
+ continue;
+
+ ret = eth_carrier_poll_once(edev);
+ if (ret)
+ continue;
+
+ ifup_edev_conf(edev, flags);
+ if (!edev->ifup)
+ continue;
+
+ netdev_count--;
+ }
+ }
+}
+
+static void __ifup_all_sequence(unsigned flags)
+{
+ struct eth_device *edev;
+
+ for_each_netdev(edev)
+ ifup_edev(edev, flags);
+}
+
+int ifup_all(unsigned flags)
+{
DIR *dir;
struct dirent *d;
@@ -285,8 +340,10 @@ int ifup_all(unsigned flags)
list_empty(&netdev_list))
device_detect_all();
- for_each_netdev(edev)
- ifup_edev(edev, flags);
+ if (flags & IFUP_FLAG_PARALLEL)
+ __ifup_all_parallel(flags);
+ else
+ __ifup_all_sequence(flags);
return 0;
}
@@ -315,14 +372,17 @@ BAREBOX_MAGICVAR(global.net.ifup_force_detect,
static int do_ifup(int argc, char *argv[])
{
int opt;
- unsigned flags = 0;
+ unsigned flags = IFUP_FLAG_PARALLEL;
int all = 0;
- while ((opt = getopt(argc, argv, "af")) > 0) {
+ while ((opt = getopt(argc, argv, "asf")) > 0) {
switch (opt) {
case 'f':
flags |= IFUP_FLAG_FORCE;
break;
+ case 's':
+ flags &= ~IFUP_FLAG_PARALLEL;
+ break;
case 'a':
all = 1;
break;
@@ -346,13 +406,14 @@ BAREBOX_CMD_HELP_TEXT("/env/network/<intf> file. See Documentation/user/networki
BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-a", "bring up all interfaces")
+BAREBOX_CMD_HELP_OPT ("-s", "bring up interfaces in sequence, not in parallel")
BAREBOX_CMD_HELP_OPT ("-f", "Force. Configure even if ip already set")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(ifup)
.cmd = do_ifup,
BAREBOX_CMD_DESC("bring a network interface up")
- BAREBOX_CMD_OPTS("[-af] [INTF]")
+ BAREBOX_CMD_OPTS("[-asf] [INTF]")
BAREBOX_CMD_GROUP(CMD_GRP_NET)
BAREBOX_CMD_COMPLETE(eth_complete)
BAREBOX_CMD_HELP(cmd_ifup_help)
--
2.30.2
next prev parent reply other threads:[~2023-01-30 17:30 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-01-30 7:20 [PATCH v2 0/3] net: ifup: greatly reduce ifup -a time for multiple network interface Ahmad Fatoum
2023-01-30 7:20 ` Ahmad Fatoum [this message]
2023-01-30 7:20 ` [PATCH v2 2/3] net: ifup: have ifup -a1 stop at first DHCP-set global.net.server Ahmad Fatoum
2023-01-30 7:20 ` [PATCH v2 3/3] defaultenv-2: automount: use ifup -a1 for NFS/TFTP automounts Ahmad Fatoum
2023-02-03 8:05 ` [PATCH v2 0/3] net: ifup: greatly reduce ifup -a time for multiple network interface Sascha Hauer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230130072057.34349-2-a.fatoum@pengutronix.de \
--to=a.fatoum@pengutronix.de \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox