{"action":"opened","issue":{"url":"https://api.github.com/repos/zehome/MLVPN/issues/84","repository_url":"https://api.github.com/repos/zehome/MLVPN","labels_url":"https://api.github.com/repos/zehome/MLVPN/issues/84/labels{/name}","comments_url":"https://api.github.com/repos/zehome/MLVPN/issues/84/comments","events_url":"https://api.github.com/repos/zehome/MLVPN/issues/84/events","html_url":"https://github.com/zehome/MLVPN/issues/84","id":169563549,"number":84,"title":"Ideas for managing tunnel selection","user":{"login":"markfoodyburton","id":11980189,"avatar_url":"https://avatars.githubusercontent.com/u/11980189?v=3","gravatar_id":"","url":"https://api.github.com/users/markfoodyburton","html_url":"https://github.com/markfoodyburton","followers_url":"https://api.github.com/users/markfoodyburton/followers","following_url":"https://api.github.com/users/markfoodyburton/following{/other_user}","gists_url":"https://api.github.com/users/markfoodyburton/gists{/gist_id}","starred_url":"https://api.github.com/users/markfoodyburton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/markfoodyburton/subscriptions","organizations_url":"https://api.github.com/users/markfoodyburton/orgs","repos_url":"https://api.github.com/users/markfoodyburton/repos","events_url":"https://api.github.com/users/markfoodyburton/events{/privacy}","received_events_url":"https://api.github.com/users/markfoodyburton/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2016-08-05T09:11:14Z","updated_at":"2016-08-05T09:11:14Z","closed_at":null,"body":"Hi, thinking about #64 and #82  - I have tried two experiments.\r\nFirstly, instead of using a 'round robin' selection mechanism, I used a weighted random selection.\r\nAs far as I can tell, in my set up, the effect is minimal, if anything it's somewhat worse. If we think about a round robin mechanism, most of the time, the tunnels take things in turn. With a random approach you are quite likely to get packets following each other on the tunnel. Although the average throughput may be right, this causes the tunnels to get 'peeks' of traffic that they can't deal with... which in the end has a negative impact on performance\r\n\r\nI dont think this will surprise anybody, but I wanted to try :-)\r\n\r\nSecond, for my ADSL connections, I notice, as the links get heavily used the SRTT can go through the roof. Further more, the slower line has a longer SRTT - very approximately related to it's bandwidth (or at least, that is my guess).\r\n\r\nI implemented a mechanism which adjusts the weights for the tunnels based on the SRTT. This is surprisingly successful. In order to avoid the 'random' effect above, the ratio needs to stay fairly steady, e.g. it needs to change slowly. Looks like you need a rolling average of at least 20000 packets. Over which time, the impact of the return going one route or the other should also be minimised.\r\n\r\nDoing this would mean you dont need to supply bandwidth numbers (which are subject to change), and the ratio used adjusts to circumstances.\r\n\r\nHOWEVER - this is favouring one tunnel as opposed to another based on their speed, rather than their bandwidth, which is clearly not the case for anything like a mixed medium environment - and only has any hope of working for common mediums (e.g. some ADSL lines). \r\n\r\nNone the less - this approach seems to work very nicely indeed. Highly unscientifically, I seem to get much steading and marginally higher download and upload speeds. Whats interesting is that the connection seems to 'self adjust' to both the ADSL fluctuations, but also the load imposed on it. During heavy download, the faster download tunnel seems to be favoured for the return path (giving up better throughput overall), while during upload, as the uplinks become saturated, their speed evens out, and we seem to better use the available upload bandwidth!\r\n\r\nThe guts of my approach are below, if anybody wants to try this out themselves, or if you like the approach, let me know and I'll open a pull request.\r\n\r\n`static void\r\nmlvpn_rtun_recalc_weight_srtt()\r\n{\r\n    mlvpn_tunnel_t *t;\r\n    double total_srtt = 0;\r\n    int error = 0;\r\n    \r\n    LIST_FOREACH(t, &rtuns, entries)\r\n    {\r\n        if (t->srtt >= 1000)\r\n            error++;\r\n        total_srtt += (t->srtt);\r\n    }\r\n    if ( error ) {\r\n        log_debug(\"srtt\", \"srtt seems not stable (yet)\");\r\n    } else {\r\n        LIST_FOREACH(t, &rtuns, entries)\r\n        {\r\n            /* useless, but we want to be sure not to divide by 0 ! */\r\n            if (t->srtt > 0 && total_srtt > 0)\r\n            {\r\n              /* lets try moving things a little slower, we'll take a rolling\r\n               * average over lots of  samples... */\r\n              double new=((double)(total_srtt - (t->srtt/)) *100 / (double)total_srtt);\r\n              t->weight = ((t->weight *19999.0) + new)/20000.0;\r\n              log_debug(\"wrr\", \"%s weight = %f (%f %f)\", t->name, t->weight,\r\n                        t->srtt, total_srtt);\r\n            }\r\n        }\r\n    }\r\n}`"}}
{"actor":{"display_login":"markfoodyburton"}}