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 }