PUD: do not consider nodes with an infinite ETX as cluster leaders
[olsrd.git] / lib / pud / src / uplinkGateway.c
1 #include "uplinkGateway.h"
2
3 /* Plugin includes */
4
5 /* OLSRD includes */
6 #include "gateway.h"
7 #include "tc_set.h"
8 #include "ipcalc.h"
9 #include "olsr_types.h"
10 #include "lq_plugin.h"
11
12 /* System includes */
13 #include <stddef.h>
14 #include <stdbool.h>
15 #include <sys/socket.h>
16
17 /**
18  * Determine the speed on which a gateway is chosen
19  * @param uplink the uplink speed of the gateway
20  * @param downlink the downlink speed of the gateway
21  * @return the speed
22  */
23 static inline unsigned long long gw_speed(struct gateway_entry *gw) {
24         return (gw->uplink + gw->downlink);
25 }
26
27 /**
28  * Determine the best gateway for uplink: this is the cluster leader.
29  *
30  * Loop over all gateways to find the best one and return it.
31  * When no best gateway is found then we return ourselves so that the behaviour
32  * degrades gracefully.
33  *
34  * A gateway is better when the sum of its uplink and downlink are greater than
35  * the previous best gateway. In case of a tie, the lowest IP address wins.
36  *
37  * This code is copied from lib/txtinfo/src/olsrd_txtinfo.c, function ipc_print_gateway.
38  * It adjusted for best gateway selection but otherwise kept the same as much
39  * as possible.
40  *
41  * @return
42  * a pointer to the IP address of the best gateway
43  */
44 union olsr_ip_addr * getBestUplinkGateway(void) {
45         struct gateway_entry *gw_best = NULL;
46         unsigned long long gw_best_value = 0;
47         struct gateway_entry *gw;
48
49         OLSR_FOR_ALL_GATEWAY_ENTRIES(gw) {
50                 bool eval4 = false;
51                 bool eval6 = false;
52
53                 struct tc_entry * tc = olsr_lookup_tc_entry(&gw->originator);
54                 if (tc == NULL) {
55                         continue;
56                 }
57
58                 /* do not consider nodes with an infinite ETX */
59                 if (tc->path_cost == ROUTE_COST_BROKEN) {
60                         continue;
61                 }
62
63                 if (gw == olsr_get_ipv4_inet_gateway(NULL)) {
64                         eval4 = true;
65                 } else if (gw->ipv4
66                                 && (olsr_cnf->ip_version == AF_INET || olsr_cnf->use_niit)
67                                 && (olsr_cnf->smart_gw_allow_nat || !gw->ipv4nat)) {
68                         eval4 = true;
69                 }
70
71                 if (gw == olsr_get_ipv6_inet_gateway(NULL)) {
72                         eval6 = true;
73                 } else if (gw->ipv6 && olsr_cnf->ip_version == AF_INET6) {
74                         eval6 = true;
75                 }
76
77                 if (eval4 || eval6) {
78                         unsigned long long gw_value = gw_speed(gw);
79                         if (gw_value > gw_best_value) {
80                                 gw_best = gw;
81                                 gw_best_value = gw_value;
82                         } else if (gw_value == gw_best_value) {
83                                 bool gwHaslowerIpAddress = false;
84                                 if (eval4) {
85                                         gwHaslowerIpAddress = (ip4cmp(&gw->originator.v4,
86                                                         &gw_best->originator.v4) < 0);
87                                 } else /* eval6 */{
88                                         gwHaslowerIpAddress = (ip6cmp(&gw->originator.v6,
89                                                         &gw_best->originator.v6) < 0);
90                                 }
91                                 if (gwHaslowerIpAddress) {
92                                         gw_best = gw;
93                                         gw_best_value = gw_value;
94                                 }
95                         }
96                 }
97         } OLSR_FOR_ALL_GATEWAY_ENTRIES_END(gw)
98
99         if (!gw_best) {
100                 /* degrade gracefully */
101                 return &olsr_cnf->main_addr;
102         }
103
104         return &gw_best->originator;
105 }