This source file includes following definitions.
- netlink_init
- netlink_fini
- netlink_reachable
- get_weights
- calculate_weight
1
2
3
4
5
6
7
8
9
10
11
12
13
14 #include "opal_config.h"
15 #include "opal/constants.h"
16 #include "opal/types.h"
17
18 #ifdef HAVE_MATH_H
19 #include <math.h>
20 #endif
21
22 #include "opal/util/net.h"
23 #include "opal/util/string_copy.h"
24 #include "opal/mca/reachable/base/base.h"
25 #include "reachable_netlink.h"
26 #include "libnl_utils.h"
27
28 enum connection_quality {
29 CQ_NO_CONNECTION = 0,
30 CQ_DIFFERENT_NETWORK = 50,
31 CQ_SAME_NETWORK = 100
32 };
33
34
35 static int init_counter = 0;
36
37 static int get_weights(opal_if_t *local_if, opal_if_t *remote_if);
38 static int calculate_weight(int bandwidth_local, int bandwidth_remote,
39 int connection_quality);
40
41 static int netlink_init(void)
42 {
43 ++init_counter;
44
45 return OPAL_SUCCESS;
46 }
47
48 static int netlink_fini(void)
49 {
50 --init_counter;
51
52 return OPAL_SUCCESS;
53 }
54
55
56
57
58
59
60
61
62 static opal_reachable_t* netlink_reachable(opal_list_t *local_if,
63 opal_list_t *remote_if)
64 {
65 opal_reachable_t *reachable_results = NULL;
66 int i, j;
67 opal_if_t *local_iter, *remote_iter;
68
69 reachable_results = opal_reachable_allocate(local_if->opal_list_length,
70 remote_if->opal_list_length);
71 if (NULL == reachable_results) {
72 return NULL;
73 }
74
75 i = 0;
76 OPAL_LIST_FOREACH(local_iter, local_if, opal_if_t) {
77 j = 0;
78 OPAL_LIST_FOREACH(remote_iter, remote_if, opal_if_t) {
79 reachable_results->weights[i][j] = get_weights(local_iter, remote_iter);
80 j++;
81 }
82 i++;
83 }
84
85 return reachable_results;
86 }
87
88
89 static int get_weights(opal_if_t *local_if, opal_if_t *remote_if)
90 {
91 char str_local[128], str_remote[128], *conn_type;
92 int outgoing_interface, ret, weight, has_gateway;
93
94
95
96 opal_string_copy(str_local,
97 opal_net_get_hostname((struct sockaddr *)&local_if->if_addr),
98 sizeof(str_local));
99 str_local[sizeof(str_local) - 1] = '\0';
100 opal_string_copy(str_remote,
101 opal_net_get_hostname((struct sockaddr *)&remote_if->if_addr),
102 sizeof(str_remote));
103 str_remote[sizeof(str_remote) - 1] = '\0';
104
105
106 weight = calculate_weight(0, 0, CQ_NO_CONNECTION);
107
108 if (AF_INET == local_if->af_family && AF_INET == remote_if->af_family) {
109 uint32_t local_ip, remote_ip;
110
111 local_ip = (uint32_t)((struct sockaddr_in *)&(local_if->if_addr))->sin_addr.s_addr;
112 remote_ip = (uint32_t)((struct sockaddr_in *)&(remote_if->if_addr))->sin_addr.s_addr;
113 outgoing_interface = local_if->if_kernel_index;
114
115 ret = opal_reachable_netlink_rt_lookup(local_ip,
116 remote_ip,
117 outgoing_interface,
118 &has_gateway);
119 if (0 == ret) {
120 if (0 == has_gateway) {
121 conn_type = "IPv4 SAME NETWORK";
122 weight = calculate_weight(local_if->if_bandwidth,
123 remote_if->if_bandwidth,
124 CQ_SAME_NETWORK);
125 } else {
126 conn_type = "IPv4 DIFFERENT NETWORK";
127 weight = calculate_weight(local_if->if_bandwidth,
128 remote_if->if_bandwidth,
129 CQ_DIFFERENT_NETWORK);
130 }
131 } else {
132 conn_type = "IPv4 NO CONNECTION";
133 weight = calculate_weight(0, 0, CQ_NO_CONNECTION);
134 }
135
136 #if OPAL_ENABLE_IPV6
137 } else if (AF_INET6 == local_if->af_family && AF_INET6 == remote_if->af_family) {
138 struct in6_addr *local_ip, *remote_ip;
139
140 local_ip = &((struct sockaddr_in6 *)&(local_if->if_addr))->sin6_addr;
141 remote_ip = &((struct sockaddr_in6 *)&(remote_if->if_addr))->sin6_addr;
142 outgoing_interface = local_if->if_kernel_index;
143
144 ret = opal_reachable_netlink_rt_lookup6(local_ip,
145 remote_ip,
146 outgoing_interface,
147 &has_gateway);
148
149 if (0 == ret) {
150 if (0 == has_gateway) {
151 conn_type = "IPv6 SAME NETWORK";
152 weight = calculate_weight(local_if->if_bandwidth,
153 remote_if->if_bandwidth,
154 CQ_SAME_NETWORK);
155 } else {
156 conn_type = "IPv6 DIFFERENT NETWORK";
157 weight = calculate_weight(local_if->if_bandwidth,
158 remote_if->if_bandwidth,
159 CQ_DIFFERENT_NETWORK);
160 }
161 } else {
162 conn_type = "IPv6 NO CONNECTION";
163 weight = calculate_weight(0, 0, CQ_NO_CONNECTION);
164 }
165 #endif
166
167 } else {
168
169
170 conn_type = "Address type mismatch";
171 weight = calculate_weight(0, 0, CQ_NO_CONNECTION);
172 }
173
174 opal_output_verbose(20, opal_reachable_base_framework.framework_output,
175 "reachable:netlink: path from %s to %s: %s",
176 str_local, str_remote, conn_type);
177
178 return weight;
179 }
180
181
182 const opal_reachable_base_module_t opal_reachable_netlink_module = {
183 netlink_init,
184 netlink_fini,
185 netlink_reachable
186 };
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215 static int calculate_weight(int bandwidth_local, int bandwidth_remote,
216 int connection_quality)
217 {
218 int weight = connection_quality * (MIN(bandwidth_local, bandwidth_remote) +
219 1.0/(1.0 + (double)abs(bandwidth_local - bandwidth_remote)));
220 return weight;
221 }