1 // Copyright (c) 2015 John Biddiscombe 2 // 3 // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 #ifndef HPX_PARCELSET_POLICIES_LIBFABRIC_LOCALITY_HPP 7 #define HPX_PARCELSET_POLICIES_LIBFABRIC_LOCALITY_HPP 8 9 #include <hpx/runtime/parcelset/locality.hpp> 10 #include <hpx/runtime/serialization/serialize.hpp> 11 #include <hpx/runtime/serialization/array.hpp> 12 // 13 #include <utility> 14 #include <cstring> 15 #include <cstdint> 16 #include <array> 17 #include <rdma/fabric.h> 18 19 // Different providers use different address formats that we must accomodate 20 // in our locality object. 21 #ifdef HPX_PARCELPORT_LIBFABRIC_GNI 22 # define HPX_PARCELPORT_LIBFABRIC_LOCALITY_SIZE 48 23 #endif 24 25 #if defined(HPX_PARCELPORT_LIBFABRIC_VERBS) || \ 26 defined(HPX_PARCELPORT_LIBFABRIC_SOCKETS) || \ 27 defined(HPX_PARCELPORT_LIBFABRIC_PSM2) 28 # define HPX_PARCELPORT_LIBFABRIC_LOCALITY_SIZE 16 29 # define HPX_PARCELPORT_LIBFABRIC_LOCALITY_SOCKADDR 30 #endif 31 32 //typedef struct fid* fi_addr_t; 33 34 namespace hpx { 35 namespace parcelset { 36 namespace policies { 37 namespace libfabric 38 { 39 40 // -------------------------------------------------------------------- 41 // Locality, in this structure we store the informartion required by 42 // libfabric to make a connection to another node. 43 // With libfabric 1.4.x the array contains the fabric ip address stored 44 // as the second uint32_t in the array. For this reason we use an 45 // array of uint32_t rather than uint8_t/char so we can easily access 46 // the ip for debug/validation purposes 47 // -------------------------------------------------------------------- 48 struct locality { 49 50 // the number of 32bit ints stored in our array 51 static const uint32_t array_length = HPX_PARCELPORT_LIBFABRIC_LOCALITY_SIZE/4; 52 static const uint32_t array_size = HPX_PARCELPORT_LIBFABRIC_LOCALITY_SIZE; 53 54 // array type of our locality data 55 typedef std::array<uint32_t, array_length> locality_data; 56 typehpx::parcelset::policies::libfabric::locality57 static const char *type() { 58 return "libfabric"; 59 } 60 localityhpx::parcelset::policies::libfabric::locality61 explicit locality(const locality_data &in_data) 62 { 63 std::memcpy(&data_[0], &in_data[0], array_size); 64 fi_address_ = 0; 65 LOG_DEBUG_MSG("explicit constructing locality from " 66 << ipaddress(ip_address()) << ":" << decnumber(port())); 67 } 68 localityhpx::parcelset::policies::libfabric::locality69 locality() { 70 std::memset(&data_[0], 0x00, array_size); 71 fi_address_ = 0; 72 LOG_DEBUG_MSG("default constructing locality from " 73 << ipaddress(ip_address()) << ":" << decnumber(port())); 74 } 75 localityhpx::parcelset::policies::libfabric::locality76 locality(const locality &other) : data_(other.data_) { 77 fi_address_ = other.fi_address_; 78 LOG_DEBUG_MSG("copy constructing locality with " 79 << ipaddress(ip_address()) << ":" << decnumber(port())); 80 } 81 localityhpx::parcelset::policies::libfabric::locality82 locality(locality &&other) : data_(std::move(other.data_)), 83 fi_address_(other.fi_address_) 84 { 85 LOG_DEBUG_MSG("move constructing locality with " 86 << ipaddress(ip_address()) << ":" << decnumber(port())); 87 } 88 operator =hpx::parcelset::policies::libfabric::locality89 locality & operator = (const locality &other) { 90 data_ = other.data_; 91 fi_address_ = other.fi_address_; 92 LOG_DEBUG_MSG("copy operator locality with " 93 << ipaddress(ip_address()) << ":" << decnumber(port())); 94 return *this; 95 } 96 ip_addresshpx::parcelset::policies::libfabric::locality97 const uint32_t & ip_address() const { 98 #if defined (HPX_PARCELPORT_LIBFABRIC_LOCALITY_SOCKADDR) 99 return reinterpret_cast<const struct sockaddr_in*> 100 (data_.data())->sin_addr.s_addr; 101 #elif defined(HPX_PARCELPORT_LIBFABRIC_GNI) 102 return data_[0]; 103 #else 104 throw fabric_error(0, "unsupported fabric provider, please fix ASAP"); 105 #endif 106 } 107 ip_addresshpx::parcelset::policies::libfabric::locality108 static const uint32_t & ip_address(const locality_data &data) { 109 #if defined (HPX_PARCELPORT_LIBFABRIC_LOCALITY_SOCKADDR) 110 return reinterpret_cast<const struct sockaddr_in*> 111 (&data)->sin_addr.s_addr; 112 #elif defined(HPX_PARCELPORT_LIBFABRIC_GNI) 113 return data[0]; 114 #else 115 throw fabric_error(0, "unsupported fabric provider, please fix ASAP"); 116 #endif 117 } 118 fi_addresshpx::parcelset::policies::libfabric::locality119 fi_addr_t fi_address() const { 120 return fi_address_; 121 } 122 set_fi_addresshpx::parcelset::policies::libfabric::locality123 void set_fi_address(fi_addr_t fi_addr) { 124 fi_address_ = fi_addr; 125 } 126 porthpx::parcelset::policies::libfabric::locality127 uint16_t port() const { 128 uint16_t port = 256*reinterpret_cast<const uint8_t*>(data_.data())[2] 129 + reinterpret_cast<const uint8_t*>(data_.data())[3]; 130 return port; 131 } 132 133 // some condition marking this locality as valid operator boolhpx::parcelset::policies::libfabric::locality134 explicit operator bool() const { 135 return (ip_address() != 0); 136 } 137 savehpx::parcelset::policies::libfabric::locality138 void save(serialization::output_archive & ar) const { 139 ar << data_; 140 } 141 loadhpx::parcelset::policies::libfabric::locality142 void load(serialization::input_archive & ar) { 143 ar >> data_; 144 } 145 fabric_datahpx::parcelset::policies::libfabric::locality146 const void *fabric_data() const { return data_.data(); } 147 fabric_data_writablehpx::parcelset::policies::libfabric::locality148 char *fabric_data_writable() { return reinterpret_cast<char*>(data_.data()); } 149 150 validhpx::parcelset::policies::libfabric::locality151 bool valid() { return true; } 152 153 private: operator ==(locality const & lhs,locality const & rhs)154 friend bool operator==(locality const & lhs, locality const & rhs) { 155 #if defined(HPX_PARCELPORT_LIBFABRIC_HAVE_LOGGING) 156 uint32_t a1 = lhs.ip_address(); 157 uint32_t a2 = rhs.ip_address(); 158 LOG_DEBUG_MSG("Testing array equality " 159 << ipaddress(a1) 160 << ipaddress(a2) 161 ); 162 #endif 163 return (lhs.data_ == rhs.data_); 164 } 165 operator <(locality const & lhs,locality const & rhs)166 friend bool operator<(locality const & lhs, locality const & rhs) { 167 uint32_t a1 = lhs.ip_address(); 168 uint32_t a2 = rhs.ip_address(); 169 return a1 < a2; 170 } 171 operator <<(std::ostream & os,locality const & loc)172 friend std::ostream & operator<<(std::ostream & os, locality const & loc) { 173 boost::io::ios_flags_saver ifs(os); 174 for (uint32_t i=0; i<array_length; ++i) { 175 os << loc.data_[i]; 176 } 177 return os; 178 } 179 180 private: 181 locality_data data_; 182 fi_addr_t fi_address_; 183 }; 184 185 }}}} 186 187 #endif 188 189