1 /* 2 * Copyright (c) 2015-2016 Cray Inc. All rights reserved. 3 * Copyright (c) 2015-2017 Los Alamos National Security, LLC. All rights reserved. 4 * 5 * This software is available to you under a choice of one of two 6 * licenses. You may choose to be licensed under the terms of the GNU 7 * General Public License (GPL) Version 2, available from the file 8 * COPYING in the main directory of this source tree, or the 9 * BSD license below: 10 * 11 * Redistribution and use in source and binary forms, with or 12 * without modification, are permitted provided that the following 13 * conditions are met: 14 * 15 * - Redistributions of source code must retain the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer. 18 * 19 * - Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials 22 * provided with the distribution. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 * SOFTWARE. 32 */ 33 34 #ifndef _GNIX_DATAGRAM_H_ 35 #define _GNIX_DATAGRAM_H_ 36 37 #include "gnix.h" 38 39 /* 40 * GNI datagram related structs and defines. 41 * The GNI_EpPostDataWId, etc. are used to manage 42 * connecting VC's for the FI_EP_RDM endpoint 43 * type. 44 * 45 * There are two types of datagrams used by the 46 * gni provider: bound (bnd) datagrams and wildcard (wc) 47 * datagrams. 48 * 49 * Bound datagrams are those that are bound to a particular 50 * target nic address by means of the GNI_EpBind function 51 * When a bound datagram is submitted to the datagram system via 52 * a GNI_EpPostDataWId, kgni forwards the datagram to 53 * the target node/cdm_id. Note that once a datagram exchange 54 * has been completed, the datagram can be unbound using 55 * the GNI_EpUnbind, and subsequently reused to target a different 56 * gni nic address/cdm_id. 57 * 58 * Wildcard datagrams have semantics similar to listening 59 * sockets. When a wildcard datagram is submitted to the 60 * datagram system, kgni adds the datagram to the list of 61 * datagrams to match for the given gni nic/cdm_id. When an 62 * incoming bound datagram matches the wildcard, the datagram 63 * exchange is completed. 64 */ 65 66 /** 67 * Set of attributes that can be used as an argument to gnix_dgram_hndl_alloc 68 * 69 * @var timeout_needed pointer to a function which returns true 70 * if a timeout is needed in the call to 71 * GNI_EpPostdataWaitById to insure progress 72 * @var timeout_progress pointer to a function should be invoked 73 * by the datagram engine to progress 74 * the state of the consumer of the datagram 75 * functionality. 76 * @var timeout_data pointer to data supplied as the argument to 77 * the timeout_needed and timeout_progress methods 78 * @var timeout the timeout value in milliseconds to be 79 * supplied to GNI_EpPostdataWaitById if 80 * timeout_needed returns to true 81 */ 82 struct gnix_dgram_hndl_attr { 83 bool (*timeout_needed)(void *); 84 void (*timeout_progress)(void *); 85 void *timeout_data; 86 uint32_t timeout; 87 }; 88 89 /** 90 * Datagram allocator struct 91 * 92 * @var cm_nic pointer to a previously allocated cm_nic with 93 * which this datagram is associated 94 * @var bnd_dgram_free_list head of free list for bound datagrams 95 * @var bnd_dgram_active_list head of active list for bound datagrams 96 * @var wc_dgram_free_list head of free list of wildcard datagrams 97 * @var wc_dgram_active_list head of active list of wildcard datagrams 98 * @var dgram_base starting address of memory block from 99 * which datagram structures are allocated 100 * @var timeout_needed In the case of FI_PROGRESS_AUTO, invoke this 101 * method prior to call to GNI_EpPostDataWaitById 102 * to check if we need to timeout in order to 103 * progress datagrams which had been stalled 104 * due to GNI_RC_ERROR_RESOURCE. 105 * @var lock lock to protect dgram lists 106 * @var progress_thread pthread id of progress thread for this 107 * datagram allocator 108 * @var n_dgrams number of bound datagrams managed by the 109 * datagram allocator 110 * @var n_wc_dgrams number of wildcard datagrams managed by 111 * the datagram allocator 112 * @var timeout time in milliseconds to wait for datagram to 113 * complete. By default set to -1 (infinite timeout), 114 * but can be set to handle cases where a timeout 115 * is required when using FI_PROGRESS_AUTO for 116 * control progress. 117 */ 118 struct gnix_dgram_hndl { 119 struct gnix_cm_nic *cm_nic; 120 struct dlist_entry bnd_dgram_free_list; 121 struct dlist_entry bnd_dgram_active_list; 122 struct dlist_entry wc_dgram_free_list; 123 struct dlist_entry wc_dgram_active_list; 124 struct gnix_datagram *dgram_base; 125 bool (*timeout_needed)(void *); 126 void (*timeout_progress)(void *); 127 void *timeout_data; 128 fastlock_t lock; 129 pthread_t progress_thread; 130 int n_dgrams; 131 int n_wc_dgrams; 132 uint32_t timeout; 133 }; 134 135 enum gnix_dgram_type { 136 GNIX_DGRAM_WC = 100, 137 GNIX_DGRAM_BND 138 }; 139 140 enum gnix_dgram_state { 141 GNIX_DGRAM_STATE_FREE, 142 GNIX_DGRAM_STATE_ACTIVE 143 }; 144 145 enum gnix_dgram_buf { 146 GNIX_DGRAM_IN_BUF, 147 GNIX_DGRAM_OUT_BUF 148 }; 149 150 enum gnix_dgram_poll_type { 151 GNIX_DGRAM_NOBLOCK, 152 GNIX_DGRAM_BLOCK 153 }; 154 155 /** 156 * @brief GNI datagram structure 157 * 158 * @var list list element for managing datagrams in llists 159 * @var free_list_head pointer to free list head from which 160 * this datagram is allocated 161 * @var gni_ep GNI ep used for posting this datagram to GNI 162 * @var nic gnix connection management (cm) nic with which 163 * this datagram is associated 164 * @var target_addr target address to which this datagram is to be 165 * delivered which posted to GNI (applicable only 166 * for bound datagrams) 167 * @var state state of the datagram (see enum gnix_dgram_state) 168 * @var type datagram type (bound or wildcard) 169 * @var d_hndl pointer to datagram handle this datagram is 170 * associated 171 * @var pre_post_clbk_fn Call back function to be called prior to 172 * to the call to GNI_EpPostDataWId. This callback 173 * is invoked while the lock is held on the cm nic. 174 * @var post_post_clbk_fn Call back function to be called following 175 * a call to GNI_EpPostDataWId. This callback 176 * is invoked while the lock is held on the cm nic. 177 * @var callback_fn Call back function to be called following 178 * a call GNI_EpPostDataTestById and a datagram 179 * is returned in any of the following GNI 180 * post state states: GNI_POST_TIMEOUT, 181 * GNI_POST_TERMINATED, GNI_POST_ERROR, or 182 * GNI_POST_COMPLETED. The cm nic lock is 183 * not held when this callback is invoked. 184 * @var r_index_in_buf Internal index for tracking where to unstart 185 * a unpack request on the GNIX_DGRAM_IN_BUF buffer 186 * of the datagram. 187 * @var w_index_in_buf Internal index for tracking where to unstart 188 * a pack request on the GNIX_DGRAM_IN_BUF buffer 189 * of the datagram. 190 * @var r_index_out_buf Internal index for tracking where to unstart 191 * a unpack request on the GNIX_DGRAM_OUT_BUF buffer 192 * of the datagram. 193 * @var w_index_out_buf Internal index for tracking where to unstart 194 * a pack request on the GNIX_DGRAM_OUT_BUF buffer 195 * of the datagram. 196 * @var cache Pointer that can be used by datagram user to track 197 * data associated with the datagram transaction. 198 * @var dgram_in_buf Internal buffer used for the IN data to be 199 * posted to the GNI. 200 * @var dgram_out_buf Internal buffer used for the OUT data to be 201 * posted to the GNI. 202 */ 203 struct gnix_datagram { 204 struct dlist_entry list; 205 struct dlist_entry *free_list_head; 206 gni_ep_handle_t gni_ep; 207 struct gnix_cm_nic *cm_nic; 208 struct gnix_address target_addr; 209 enum gnix_dgram_state state; 210 enum gnix_dgram_type type; 211 struct gnix_dgram_hndl *d_hndl; 212 int (*pre_post_clbk_fn)(struct gnix_datagram *, 213 int *); 214 int (*post_post_clbk_fn)(struct gnix_datagram *, 215 gni_return_t); 216 int (*callback_fn)(struct gnix_datagram *, 217 struct gnix_address, 218 gni_post_state_t); 219 int r_index_in_buf; 220 int w_index_in_buf; 221 int r_index_out_buf; 222 int w_index_out_buf; 223 void *cache; 224 char dgram_in_buf[GNI_DATAGRAM_MAXSIZE]; 225 char dgram_out_buf[GNI_DATAGRAM_MAXSIZE]; 226 }; 227 228 /* 229 * prototypes for gni datagram internal functions 230 */ 231 232 /** 233 * @brief Allocates a handle to a datagram allocator instance 234 * 235 * @param[in] cm_nic pointer to previously allocated gnix_cm_nic object 236 * @param[in] attr optional pointer to a gnix_dgram_hndl_attr 237 * structure 238 * @param[in] progress progress model to be used for this cm_nic 239 * (see fi_domain man page) 240 * @param[out] handl_ptr location in which the address of the allocated 241 * datagram allocator handle is to be returned 242 * @return FI_SUCCESS Upon successfully creating a datagram allocator. 243 * @return -FI_ENOMEM Insufficient memory to create datagram allocator 244 * @return -FI_EINVAL Upon getting an invalid fabric or cm_nic handle 245 * @return -FI_EAGAIN In the case of FI_PROGRESS_AUTO, system lacked 246 * resources to spawn a progress thread. 247 */ 248 int _gnix_dgram_hndl_alloc(struct gnix_cm_nic *cm_nic, 249 enum fi_progress progress, 250 const struct gnix_dgram_hndl_attr *attr, 251 struct gnix_dgram_hndl **hndl_ptr); 252 253 /** 254 * @brief Frees a handle to a datagram allocator and associated internal 255 * structures 256 * 257 * @param[in] hndl pointer to previously allocated datagram allocator 258 * instance 259 * @return FI_SUCCESS Upon successfully freeing the datagram allocator 260 * handle and associated internal structures 261 * @return -FI_EINVAL Invalid handle to a datagram allocator was supplied 262 * as input 263 */ 264 int _gnix_dgram_hndl_free(struct gnix_dgram_hndl *hndl); 265 266 /** 267 * @brief Allocates a datagram 268 * 269 * @param[in] hndl pointer to previously allocated datagram allocator 270 * instance 271 * @param[in] type datagram type - wildcard or bound 272 * @param[out] d_ptr location in which the address of the allocated 273 * datagram is to be returned 274 * @return FI_SUCCESS Upon successfully allocating a datagram 275 * @return -FI_EAGAIN Temporarily insufficient resources to allocate 276 * a datagram. The associated cm_nic needs to be 277 * progressed. 278 */ 279 int _gnix_dgram_alloc(struct gnix_dgram_hndl *hndl, 280 enum gnix_dgram_type type, 281 struct gnix_datagram **d_ptr); 282 283 /** 284 * @brief Frees a datagram 285 * 286 * @param[in] d pointer to previously allocated datagram 287 * datagram is to be returned 288 * @return FI_SUCCESS Upon successfully freeing a datagram 289 * @return -FI_EINVAL Invalid argument was supplied 290 * @return -FI_EOPBADSTAT Datagram is currently in an internal state where 291 * it cannot be freed 292 */ 293 int _gnix_dgram_free(struct gnix_datagram *d); 294 295 /** 296 * @brief Post a wildcard datagram to the GNI datagram state engine 297 * 298 * @param[in] d pointer to previously allocated datagram 299 * @return FI_SUCCESS Upon successfully posting a wildcard datagram 300 * @return -FI_EINVAL Invalid argument was supplied 301 * @return -FI_ENOMEM Insufficient memory to post datagram 302 * @return -FI_EMSGSIZE Payload for datagram exceeds internally 303 * supported size (see GNI_DATAGRAM_MAXSIZE in 304 * gni_pub.h) 305 */ 306 int _gnix_dgram_wc_post(struct gnix_datagram *d); 307 308 /** 309 * @brief Post a bound datagram to the GNI datagram state engine 310 * 311 * @param[in] d pointer to previously allocated datagram 312 * @return FI_SUCCESS Upon successfully posting a wildcard datagram 313 * @return -FI_EINVAL Invalid argument was supplied 314 * @return -FI_ENOMEM Insufficient memory to post datagram 315 * @return -FI_BUSY Only one outstanding datagram to a given 316 8 target address is allowed 317 * @return -FI_EMSGSIZE Payload for datagram exceeds internally 318 * supported size (see GNI_DATAGRAM_MAXSIZE in 319 * gni_pub.h) 320 */ 321 int _gnix_dgram_bnd_post(struct gnix_datagram *d); 322 323 /** 324 * @brief Pack the buffer of a previously allocated datagram 325 * with application data 326 * @param[in] d pointer to previously allocated datagram 327 * @param[in] gnix_dgram_buf which buffer into which to pack data 328 * @param[in] data pointer to data to be packed 329 * @param[in] nbytes number of bytes to pack 330 * @return (> 0) number of bytes packed 331 * @return -FI_EINVAL Invalid argument was supplied 332 * @return -FI_ENOSPC Insufficient space for data 333 */ 334 ssize_t _gnix_dgram_pack_buf(struct gnix_datagram *d, enum gnix_dgram_buf, 335 void *data, uint32_t nbytes); 336 337 /** 338 * @brief Unpack the buffer of a previously allocated datagram 339 * with application data 340 * @param[in] d pointer to previously allocated datagram 341 * @param[in] gnix_dgram_buf which buffer from which to unpack data 342 * @param[in] data address into which the data is to be unpacked 343 * @param[in] nbytes number of bytes to unpacked 344 * @return (> 0) number of bytes unpacked 345 */ 346 ssize_t _gnix_dgram_unpack_buf(struct gnix_datagram *d, enum gnix_dgram_buf, 347 void *data, uint32_t nbytes); 348 349 /** 350 * @brief rewind the internal pointers to datagram buffers to 351 * beginning of the internal buffers 352 * @param[in] d pointer to previously allocated datagram 353 * @param[in] gnix_dgram_buf which buffer to rewind 354 * @param[in] data address into which the data is to be unpacked 355 * @param[in] nbytes number of bytes to unpacked 356 * @return FI_SUCCESS Upon successfully rewinding internal buffer 357 * pointers 358 */ 359 int _gnix_dgram_rewind_buf(struct gnix_datagram *d, enum gnix_dgram_buf); 360 361 /** 362 * @brief poll datagram handle to progress the underlying cm_nic's 363 * progress engine 364 * @param[in] hndl_ptr handle to a previously allocated datagram 365 * allocator 366 * @param[in] type progress type (blocking or non-blocking) 367 * @return FI_SUCCESS Upon successfully progressing the state 368 * engine 369 */ 370 int _gnix_dgram_poll(struct gnix_dgram_hndl *hndl_ptr, 371 enum gnix_dgram_poll_type type); 372 373 374 #endif /* _GNIX_DATAGRAM_H_ */ 375