This source file includes following definitions.
- opal_btl_usnic_fast_retrans
- opal_btl_usnic_handle_ack
- opal_btl_usnic_ack_send
- opal_btl_usnic_ack_complete
- opal_btl_usnic_ack_timeout
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 #include "opal_config.h"
  11 
  12 #include <errno.h>
  13 #include <string.h>
  14 #include <unistd.h>
  15 
  16 #include "opal/util/output.h"
  17 #include "opal/class/opal_hotel.h"
  18 
  19 #include "btl_usnic.h"
  20 #include "btl_usnic_frag.h"
  21 #include "btl_usnic_endpoint.h"
  22 #include "btl_usnic_module.h"
  23 #include "btl_usnic_ack.h"
  24 #include "btl_usnic_util.h"
  25 #include "btl_usnic_send.h"
  26 #include "btl_usnic_connectivity.h"
  27 
  28 
  29 
  30 
  31 
  32 static void
  33 opal_btl_usnic_fast_retrans(
  34     opal_btl_usnic_endpoint_t *endpoint,
  35     opal_btl_usnic_seq_t ack_seq)
  36 {
  37     opal_btl_usnic_send_segment_t *sseg;
  38     int is;
  39 
  40     is = WINDOW_SIZE_MOD(ack_seq + 1);
  41     sseg = endpoint->endpoint_sent_segs[is];
  42 
  43     
  44     
  45     
  46     
  47     if (sseg == NULL || sseg->ss_hotel_room == -1) {
  48         return;
  49     }
  50 
  51     
  52     opal_hotel_checkout(&endpoint->endpoint_hotel, sseg->ss_hotel_room);
  53     sseg->ss_hotel_room = -1;
  54 
  55     
  56     opal_list_append(&(endpoint->endpoint_module->pending_resend_segs),
  57                      &(sseg->ss_base.us_list.super));
  58 
  59     ++endpoint->endpoint_module->stats.num_fast_retrans;
  60 }
  61 
  62 
  63 
  64 
  65 
  66 
  67 void
  68 opal_btl_usnic_handle_ack(
  69     opal_btl_usnic_endpoint_t *endpoint,
  70     opal_btl_usnic_seq_t ack_seq)
  71 {
  72     opal_btl_usnic_seq_t is;
  73     opal_btl_usnic_send_segment_t *sseg;
  74     opal_btl_usnic_send_frag_t *frag;
  75     opal_btl_usnic_module_t *module;
  76     uint32_t bytes_acked;
  77 
  78     module = endpoint->endpoint_module;
  79 
  80     
  81     if (SEQ_LT(ack_seq, endpoint->endpoint_ack_seq_rcvd)) {
  82 #if MSGDEBUG1
  83         opal_output(0, "Got OLD DUP ACK seq %"UDSEQ" < %"UDSEQ"\n",
  84                 ack_seq, endpoint->endpoint_ack_seq_rcvd);
  85 #endif
  86         ++module->stats.num_old_dup_acks;
  87         return;
  88     }
  89 
  90     
  91 
  92     else if (ack_seq == endpoint->endpoint_ack_seq_rcvd) {
  93         ++module->stats.num_dup_acks;
  94 
  95         opal_btl_usnic_fast_retrans(endpoint, ack_seq);
  96         return;
  97     }
  98 
  99     
 100 
 101     for (is = endpoint->endpoint_ack_seq_rcvd + 1; SEQ_LE(is, ack_seq); ++is) {
 102         sseg = endpoint->endpoint_sent_segs[WINDOW_SIZE_MOD(is)];
 103 
 104 #if MSGDEBUG1
 105         opal_output(0, "  Checking ACK/sent_segs window %p, index %lu, seq %lu, occupied=%p, seg_room=%d",
 106             (void*) endpoint->endpoint_sent_segs,
 107             WINDOW_SIZE_MOD(is), is, (void*)sseg, (sseg?sseg->ss_hotel_room:-2));
 108 #endif
 109 
 110         assert(sseg != NULL);
 111         assert(sseg->ss_base.us_btl_header->pkt_seq == is);
 112 #if MSGDEBUG1
 113         if (sseg->ss_hotel_room == -1) {
 114             opal_output(0, "=== ACKed frag in sent_frags array is not in hotel/enqueued, module %p, endpoint %p, seg %p, seq %" UDSEQ ", slot %lu",
 115                         (void*) module, (void*) endpoint,
 116                         (void*) sseg, is, WINDOW_SIZE_MOD(is));
 117         }
 118 #endif
 119 
 120         
 121 
 122 
 123 
 124         if (OPAL_LIKELY(sseg->ss_hotel_room != -1)) {
 125             opal_hotel_checkout(&endpoint->endpoint_hotel, sseg->ss_hotel_room);
 126             sseg->ss_hotel_room = -1;
 127         }
 128         
 129         else {
 130             opal_list_remove_item((&module->pending_resend_segs),
 131                     &sseg->ss_base.us_list.super);
 132         }
 133 
 134         
 135         bytes_acked = sseg->ss_base.us_btl_header->payload_len;
 136         frag = sseg->ss_parent_frag;
 137 
 138 #if MSGDEBUG1
 139         opal_output(0, "   ACKED seg %p frag %p ack_bytes=%"PRIu32" left=%zd dst_seg[0].seg_addr=%p des_flags=0x%x\n",
 140                 (void*)sseg, (void*)frag, bytes_acked,
 141                 frag->sf_ack_bytes_left - bytes_acked,
 142                 frag->sf_base.uf_local_seg[0].seg_addr.pval,
 143                 frag->sf_base.uf_base.des_flags);
 144 #endif
 145 
 146         
 147 
 148 
 149 
 150 
 151 
 152 
 153 
 154 
 155 
 156 
 157         if (frag->sf_ack_bytes_left == bytes_acked) {
 158 #if BTL_VERSION == 30
 159             if (frag->sf_base.uf_remote_seg[0].seg_addr.pval != NULL) {
 160                 OPAL_BTL_USNIC_DO_PUT_FRAG_CB(module, frag, "put completion");
 161             } else if (frag->sf_base.uf_base.des_flags &
 162                        MCA_BTL_DES_SEND_ALWAYS_CALLBACK) {
 163                 OPAL_BTL_USNIC_DO_SEND_FRAG_CB(module, frag, "send completion");
 164             }
 165 #else
 166             if ((frag->sf_base.uf_remote_seg[0].seg_addr.pval != NULL) ||
 167                 (frag->sf_base.uf_base.des_flags &
 168                  MCA_BTL_DES_SEND_ALWAYS_CALLBACK)) {
 169                 OPAL_BTL_USNIC_DO_SEND_FRAG_CB(module, frag, "send completion");
 170             }
 171 #endif
 172         }
 173 
 174         
 175         sseg->ss_ack_pending = false;
 176         if (sseg->ss_send_posted == 0) {
 177             opal_btl_usnic_release_send_segment(module, frag, sseg);
 178         }
 179 
 180         
 181         
 182         frag->sf_ack_bytes_left -= bytes_acked;
 183 
 184         
 185         opal_btl_usnic_send_frag_return_cond(module, frag);
 186 
 187         
 188         endpoint->endpoint_sent_segs[WINDOW_SIZE_MOD(is)] = NULL;
 189     }
 190 
 191     
 192     endpoint->endpoint_ack_seq_rcvd = ack_seq;
 193 
 194     
 195     opal_btl_usnic_check_rts(endpoint);
 196 }
 197 
 198 
 199 
 200 
 201 int
 202 opal_btl_usnic_ack_send(
 203     opal_btl_usnic_module_t *module,
 204     opal_btl_usnic_endpoint_t *endpoint)
 205 {
 206     opal_btl_usnic_ack_segment_t *ack;
 207 
 208     
 209 
 210     if (module->mod_channels[USNIC_PRIORITY_CHANNEL].credits < 1) {
 211         return OPAL_ERR_OUT_OF_RESOURCE;
 212     }
 213 
 214     
 215     ack = opal_btl_usnic_ack_segment_alloc(module);
 216     if (OPAL_UNLIKELY(NULL == ack)) {
 217         return OPAL_ERR_OUT_OF_RESOURCE;
 218     }
 219 
 220     --module->mod_channels[USNIC_PRIORITY_CHANNEL].credits;
 221 
 222     
 223 
 224     ack->ss_base.us_btl_header->ack_seq =
 225         SEQ_DIFF(endpoint->endpoint_next_contig_seq_to_recv, 1);
 226     ack->ss_len = sizeof(opal_btl_usnic_btl_header_t);
 227 
 228 #if MSGDEBUG1
 229     {
 230         char remote_ip[IPV4STRADDRLEN];
 231         struct opal_btl_usnic_modex_t *modex =
 232             &endpoint->endpoint_remote_modex;
 233         opal_btl_usnic_snprintf_ipv4_addr(remote_ip, sizeof(remote_ip),
 234                                           modex->ipv4_addr,
 235                                           modex->netmask);
 236 
 237 
 238         opal_output(0, "--> Sending ACK, length %d, seq %" UDSEQ " to %s, port %u",
 239                     ack->ss_len,
 240                     ack->ss_base.us_btl_header->ack_seq,
 241                     remote_ip,
 242                     modex->ports[ack->ss_channel]);
 243     }
 244 #endif
 245 
 246     
 247 
 248 
 249     opal_btl_usnic_check_connectivity(module, endpoint);
 250 
 251     
 252     opal_btl_usnic_post_ack(module, endpoint, ack);
 253 
 254     
 255     ++module->stats.num_ack_sends;
 256 
 257     return OPAL_SUCCESS;
 258 }
 259 
 260 
 261 
 262 
 263 void
 264 opal_btl_usnic_ack_complete(opal_btl_usnic_module_t *module,
 265                                    opal_btl_usnic_ack_segment_t *ack)
 266 {
 267     ++module->mod_channels[USNIC_PRIORITY_CHANNEL].credits;
 268     opal_btl_usnic_ack_segment_return(module, ack);
 269     ++module->mod_channels[ack->ss_channel].credits;
 270 }
 271 
 272 
 273 
 274 
 275 
 276 
 277 
 278 void
 279 opal_btl_usnic_ack_timeout(
 280     opal_hotel_t *hotel,
 281     int room_num,
 282     void *occupant)
 283 {
 284     opal_btl_usnic_send_segment_t *seg;
 285     opal_btl_usnic_endpoint_t *endpoint;
 286     opal_btl_usnic_module_t *module;
 287 
 288     seg = (opal_btl_usnic_send_segment_t*) occupant;
 289     endpoint = seg->ss_parent_frag->sf_endpoint;
 290     module = endpoint->endpoint_module;
 291 
 292 #if MSGDEBUG1
 293     {
 294         opal_output(0, "Send timeout!  seg %p, room %d, seq %" UDSEQ "\n",
 295                     (void*)seg, seg->ss_hotel_room,
 296                     seg->ss_base.us_btl_header->pkt_seq);
 297     }
 298 #endif
 299 
 300     
 301     seg->ss_hotel_room = -1;
 302 
 303     
 304     opal_list_append(&(module->pending_resend_segs),
 305                      &(seg->ss_base.us_list.super));
 306 
 307     
 308     ++module->stats.num_timeout_retrans;
 309 }