pex: improve handling of a longer list of PEX hosts
authorFelix Fietkau <nbd@nbd.name>
Fri, 16 Sep 2022 13:25:20 +0000 (15:25 +0200)
committerFelix Fietkau <nbd@nbd.name>
Fri, 16 Sep 2022 16:56:53 +0000 (18:56 +0200)
Instead of rotating and picking one every 5 seconds, pick one from the list
every 500ms, but enforce a minimum interval of 10 seconds per host between
pings

Signed-off-by: Felix Fietkau <nbd@nbd.name>
pex.c
pex.h

diff --git a/pex.c b/pex.c
index 3f28f5137bcc9979e106469de17861ae0e222ba5..2b83f5d9cb0ed55784f2fcc2bad433b7404a7707 100644 (file)
--- a/pex.c
+++ b/pex.c
@@ -253,6 +253,8 @@ network_pex_host_request_update(struct network *net, struct network_pex_host *ho
        char addrstr[INET6_ADDRSTRLEN];
        uint64_t version = 0;
 
+       host->last_ping = unet_gettime();
+
        if (net->net_data_len)
                version = net->net_data_version;
 
@@ -282,23 +284,27 @@ network_pex_request_update_cb(struct uloop_timeout *t)
 {
        struct network *net = container_of(t, struct network, pex.request_update_timer);
        struct network_pex *pex = &net->pex;
-       struct network_pex_host *host;
+       struct network_pex_host *host, *tmp;
+       uint64_t now = unet_gettime();
 
-       uloop_timeout_set(t, 5000);
+       uloop_timeout_set(t, 500);
 
-retry:
        if (list_empty(&pex->hosts))
                return;
 
-       host = list_first_entry(&pex->hosts, struct network_pex_host, list);
-       if (host->timeout && host->timeout < unet_gettime()) {
-               list_del(&host->list);
-               free(host);
-               goto retry;
-       }
+       list_for_each_entry_safe(host, tmp, &pex->hosts, list) {
+               if (host->timeout && host->timeout < now) {
+                       list_del(&host->list);
+                       free(host);
+                       continue;
+               }
+
+               if (host->last_ping + 10 >= now)
+                       continue;
 
-       list_move_tail(&host->list, &pex->hosts);
-       network_pex_host_request_update(net, host);
+               list_move_tail(&host->list, &pex->hosts);
+               network_pex_host_request_update(net, host);
+       }
 }
 
 void network_pex_init(struct network *net)
@@ -701,13 +707,17 @@ void network_pex_create_host(struct network *net, union network_endpoint *ep,
 {
        struct network_pex *pex = &net->pex;
        struct network_pex_host *host;
+       uint64_t now = unet_gettime();
        bool new_host = false;
 
        list_for_each_entry(host, &pex->hosts, list) {
                if (memcmp(&host->endpoint, ep, sizeof(host->endpoint)) != 0)
                        continue;
 
-               list_move_tail(&host->list, &pex->hosts);
+               if (host->last_ping + 10 < now) {
+                       list_move_tail(&host->list, &pex->hosts);
+                       network_pex_host_request_update(net, host);
+               }
                goto out;
        }
 
@@ -719,7 +729,6 @@ void network_pex_create_host(struct network *net, union network_endpoint *ep,
 out:
        if (timeout && (new_host || host->timeout))
                host->timeout = timeout + unet_gettime();
-       network_pex_host_request_update(net, host);
 }
 
 static void
diff --git a/pex.h b/pex.h
index acaf372befc83b82aa8e04845fe6d8559e6b805b..18f323ef2a1771f71f2c0b7be12a6325c90848ae 100644 (file)
--- a/pex.h
+++ b/pex.h
@@ -15,6 +15,7 @@ struct network_pex_host {
        struct list_head list;
        uint64_t timeout;
        uint64_t last_active;
+       uint64_t last_ping;
        union network_endpoint endpoint;
 };