mirror of
https://github.com/openwrt/packages.git
synced 2026-10-12 05:57:04 +04:00
olsrd: ubus: forget an interface that is already gone
del_interface looked for the active interface (if_ifwithname) and answered "Permission denied" when there was none. That is the normal case when it is called from a hotplug "remove" event: the device is gone, olsrd has seen the link go away and has taken the active interface down by itself. The configured entry stayed in olsr_cnf->interfaces for good. olsrd looks at every configured interface that is not up every NicChgsPollInt seconds (2.5 by default) with ioctl(SIOCGIFFLAGS). For a name that does not exist, the kernel tries to load a module for it (dev_load), twice: "netdev-<name>" and "<name>". On OpenWrt each of these is a run of kmodloader over all modules. A gateway with wireguard tunnels that come and go collects one such entry per tunnel. On an EdgeRouter 4 after 24 days there were 12 of them: 16 to 19 process starts per second, 38 million since boot, about half of one of its four cores. Look for the configured entry instead, take it out of the list, and only take the interface down if it is up. An unknown name is now "Not found". Tested on OpenWrt 25.12 (x86_64, in a container): removing an interface that vanished before, one that is up, an unknown one, two vanished ones in the other order, and adding one again. The same change has been running on an EdgeRouter 4 (mips64) gateway. Signed-off-by: Simon Polack <spolack+git@mailbox.org> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
8b437684c7
commit
40d387f979
2 files changed
+21
-27
No files matched your search
+1
-1
@@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=olsrd
|
||||
PKG_SOURCE_DATE:=2024-06-09
|
||||
PKG_RELEASE:=1
|
||||
PKG_RELEASE:=2
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/OLSR/olsrd.git
|
||||
|
||||
+20
-26
@@ -108,7 +108,7 @@ static int olsrd_ubus_del_interface(struct ubus_context *ctx_local,
|
||||
struct blob_buf b = {0};
|
||||
int ret;
|
||||
char *ifname;
|
||||
struct olsr_if *tmp_if, *del_if;
|
||||
struct olsr_if *del_if, **prev;
|
||||
|
||||
blobmsg_parse(interface_policy, __INTERFACE_MAX, tb, blob_data(msg),
|
||||
blob_len(msg));
|
||||
@@ -118,33 +118,27 @@ static int olsrd_ubus_del_interface(struct ubus_context *ctx_local,
|
||||
|
||||
ifname = blobmsg_get_string(tb[INTERFACE_IFNAME]);
|
||||
|
||||
struct interface_olsr *tmp = if_ifwithname(ifname);
|
||||
|
||||
if (tmp != NULL) {
|
||||
|
||||
struct olsr_if *temp = olsr_cnf->interfaces, *prev;
|
||||
if (temp != NULL && (strcmp(temp->name, ifname) == 0)) {
|
||||
olsr_cnf->interfaces = temp->next;
|
||||
olsr_remove_interface(temp);
|
||||
goto send_reply;
|
||||
}
|
||||
|
||||
while (temp != NULL && (strcmp(temp->name, ifname) != 0)) {
|
||||
prev = temp;
|
||||
temp = temp->next;
|
||||
}
|
||||
|
||||
if (temp == NULL) {
|
||||
goto send_reply;
|
||||
}
|
||||
|
||||
prev->next = temp->next;
|
||||
olsr_remove_interface(temp);
|
||||
} else {
|
||||
return UBUS_STATUS_PERMISSION_DENIED;
|
||||
/*
|
||||
* Look for the configured interface, not for the active one. When the
|
||||
* device is already gone, olsrd has taken the active interface down by
|
||||
* itself, but the configured entry stays and is polled every
|
||||
* NicChgsPollInt seconds forever. The kernel answers each lookup of a
|
||||
* device that does not exist with two calls of modprobe.
|
||||
*/
|
||||
for (prev = &olsr_cnf->interfaces; (del_if = *prev) != NULL;
|
||||
prev = &del_if->next) {
|
||||
if (strcmp(del_if->name, ifname) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
send_reply:
|
||||
if (del_if == NULL)
|
||||
return UBUS_STATUS_NOT_FOUND;
|
||||
|
||||
*prev = del_if->next;
|
||||
|
||||
/* only an interface that is up has something to take down */
|
||||
if (del_if->interf != NULL)
|
||||
olsr_remove_interface(del_if);
|
||||
|
||||
blob_buf_init(&b, 0);
|
||||
blobmsg_add_string(&b, "deleting", ifname);
|
||||
|
||||
Reference in new issue
Block a user