1 #ifndef GATEWAY_COSTS_H_
2 #define GATEWAY_COSTS_H_
4 /*
5  * Weighing of the path costs:
6  *
7  * exitUm = the gateway exit link uplink   bandwidth, in Mbps
8  * exitDm = the gateway exit link downlink bandwidth, in Mbps
9  * WexitU = the gateway exit link uplink   bandwidth weight   (configured)
10  * WexitD = the gateway exit link downlink bandwidth weight   (configured)
11  * Wetx   = the ETX path cost weight                          (configured)
12  * Detx   = the ETX path cost divider                         (configured)
13  *
14  *                     WexitU   WexitD   Wetx
15  * path_cost_weight =  ------ + ------ + ---- * path_cost
16  *                     exitUm   exitDm   Detx
17  *
18  * Since the gateway exit link bandwidths are in Kbps, the following formula
19  * is used to convert them to the desired Mbps:
20  *
21  *       bwK
22  * bwM = ----       bwK = bandwidth in Kbps
23  *       1000       bwM = bandwidth in Mbps
24  *
25  * exitUk = the gateway exit link uplink   bandwidth, in Kbps
26  * exitDk = the gateway exit link downlink bandwidth, in Kbps
27  *
28  *                     1000 * WexitU   1000 * WexitD   Wetx
29  * path_cost_weight =  ------------- + ------------- + ---- * path_cost
30  *                         exitUk          exitDk      Detx
31  *
32  *
33  * Analysis of the required bit width of the result:
34  *
35  * exitUk    = [1,   320,000,000] = 29 bits
36  * exitDk    = [1,   320,000,000] = 29 bits
37  * WexitU    = [1,           255] =  8 bits
38  * WexitD    = [1,           255] =  8 bits
39  * Wetx      = [1,           255] =  8 bits
40  * Detx      = [1, 4,294,967,295] = 32 bits
41  * path_cost = [1, 4,294,967,295] = 32 bits
42  *
43  *                         1000 * 255   1000 * 255   255
44  * path_cost_weight(max) = ---------- + ---------- + --- * 4,294,967,295
45  *                              1             1       1
46  *
47  * path_cost_weight(max) = 0x3E418    + 0x3E418    + 0xFEFFFFFF01
48  * path_cost_weight(max) = 0xFF0007C731
49  *
50  * Because we can multiply 0xFF0007C731 by 2^24 without overflowing an
51  * unsigned 64 bits number, we could do this to increase accuracy.
52  *
53  * However, since we also want to implement this in Java, which doesn't support
54  * unsigned types, we multiply 0xFF0007C731 by 2^23 without overflowing a
55  * signed 64 bits number.
56  */
58 #include "stdint.h"
59 #include "stdbool.h"
61 #ifdef __cplusplus
62 extern "C" {
63 #endif /* __cplusplus */
65   /**
66    * Structure to keep weighing factors for the gw_costs_weigh function
67    */
68   struct costs_weights {
69       uint8_t WexitU;
70       uint8_t WexitD;
71       uint8_t Wetx;
72       uint32_t Detx;
73   };
75   /**
76    * Weigh the path costs and the gateway bandwidth.
77    *
78    * If the ETX divider is zero, then no weighing is performed and only the path
79    * costs are considered (classic behaviour), but scaled to a 64 bit number.
80    *
81    * If path_cost is the maximum AND path_cost < max_cost_etx_max then
82    * the gateway costs are equal to path_cost.
83    *
84    * @param up true when the relevant interface is up
85    * @param weights the weights for the calculation
86    * @param path_cost the (ETX) path cost to the gateway
87    * @param max_cost_etx_max the maximum (ETX) path cost for when path_costs is the maximum
88    * to take the calculation shortcut.
89    * @param exitUk the gateway exit link uplink bandwidth (in kbps)
90    * @param exitDk the gateway exit link downlink bandwidth (in kbps)
91    * @return the weighed path cost, INT64_MAX when up is false or when exitUk and/or exitDk are zero
92    */
93   int64_t gw_costs_weigh(bool up, const struct costs_weights weights, uint32_t path_cost, uint32_t max_cost_etx_max, uint32_t exitUk, uint32_t exitDk);
95 #ifdef __cplusplus
96 }
97 #endif /* __cplusplus */
99 #endif /* GATEWAY_COSTS_H_ */