tcp_init.c 19.3 KB
Newer Older
1
2
3
4
5
6
/* -*- Mode: C; c-basic-offset:4 ; -*- */
/*
 *  (C) 2006 by Argonne National Laboratory.
 *      See COPYRIGHT in top-level directory.
 */

7
#include "tcp_impl.h"
8
9
10
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
11
12
13
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
14

15
#define DBG_IFNAME 0
16

17
#ifdef ENABLE_CHECKPOINTING
18
static int ckpt_restart(void);
19
20
#endif

21
22
23
MPID_nem_netmod_funcs_t MPIDI_nem_tcp_funcs = {
    MPID_nem_tcp_init,
    MPID_nem_tcp_finalize,
24
#ifdef ENABLE_CHECKPOINTING
25
    NULL, /* ckpt_precheck */
26
    ckpt_restart,
27
    NULL, /* ckpt_continue */
28
#endif
29
    MPID_nem_tcp_connpoll,
30
31
32
33
    MPID_nem_tcp_get_business_card,
    MPID_nem_tcp_connect_to_root,
    MPID_nem_tcp_vc_init,
    MPID_nem_tcp_vc_destroy,
34
35
    MPID_nem_tcp_vc_terminate,
    NULL /* anysource iprobe */
36
37
};

38
39
/* in case there are no packet types defined (e.g., they're ifdef'ed out) make sure the array is not zero length */
static MPIDI_CH3_PktHandler_Fcn *pkt_handlers[MPIDI_NEM_TCP_PKT_NUM_TYPES ? MPIDI_NEM_TCP_PKT_NUM_TYPES : 1];
40
41
    

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#undef FUNCNAME
#define FUNCNAME set_up_listener
#undef FCNAME
#define FCNAME MPIDI_QUOTE(FUNCNAME)
static int set_up_listener(void)
{
    int mpi_errno = MPI_SUCCESS;
    int ret;
    MPIDI_STATE_DECL(MPID_STATE_SET_UP_LISTENER);

    MPIDI_FUNC_ENTER(MPID_STATE_SET_UP_LISTENER);

    MPID_nem_tcp_g_lstn_plfd.fd = MPID_nem_tcp_g_lstn_sc.fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    MPIU_ERR_CHKANDJUMP2(MPID_nem_tcp_g_lstn_sc.fd == -1, mpi_errno, MPI_ERR_OTHER, "**sock_create", "**sock_create %s %d", MPIU_Strerror(errno), errno);

    mpi_errno = MPID_nem_tcp_set_sockopts(MPID_nem_tcp_g_lstn_sc.fd);
    if (mpi_errno) MPIU_ERR_POP(mpi_errno);

    MPID_nem_tcp_g_lstn_plfd.events = POLLIN;
    mpi_errno = MPID_nem_tcp_bind(MPID_nem_tcp_g_lstn_sc.fd);
    if (mpi_errno) MPIU_ERR_POP(mpi_errno);

64
    ret = listen(MPID_nem_tcp_g_lstn_sc.fd, SOMAXCONN);
65
66
67
68
69
70
71
72
73
74
75
76
    MPIU_ERR_CHKANDJUMP2(ret == -1, mpi_errno, MPI_ERR_OTHER, "**listen", "**listen %s %d", MPIU_Strerror(errno), errno);  
    MPID_nem_tcp_g_lstn_sc.state.lstate = LISTEN_STATE_LISTENING;
    MPID_nem_tcp_g_lstn_sc.handler = MPID_nem_tcp_state_listening_handler;

fn_exit:
    MPIDI_FUNC_EXIT(MPID_STATE_SET_UP_LISTENER);
    return mpi_errno;
fn_fail:

    goto fn_exit;
}

77
#undef FUNCNAME
78
#define FUNCNAME MPID_nem_tcp_init
79
80
#undef FCNAME
#define FCNAME MPIDI_QUOTE(FUNCNAME)
Darius Buntinas's avatar
Darius Buntinas committed
81
int MPID_nem_tcp_init (MPIDI_PG_t *pg_p, int pg_rank, char **bc_val_p, int *val_max_sz_p)
82
83
{
    int mpi_errno = MPI_SUCCESS;
84
    MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_TCP_INIT);
85

86
    MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_TCP_INIT);
87

88
    MPID_nem_net_module_vc_dbg_print_sendq = MPID_nem_tcp_vc_dbg_print_sendq;
89

90
    /* first make sure that our private fields in the vc fit into the area provided  */
91
    MPIU_Assert(sizeof(MPID_nem_tcp_vc_area) <= MPID_NEM_VC_NETMOD_AREA_LEN);
92

93
    /* set up listener socket */
94
95
96
    mpi_errno = set_up_listener();
    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
    
97
    /* create business card */
98
    mpi_errno = MPID_nem_tcp_get_business_card(pg_rank, bc_val_p, val_max_sz_p);
99
    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
100

101
    mpi_errno = MPID_nem_tcp_sm_init();
102
    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
103
    mpi_errno = MPID_nem_tcp_send_init();
104
    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
105

106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#ifdef HAVE_SIGNAL
    {
        /* In order to be able to handle socket errors on our own, we need
           to ignore SIGPIPE.  This may cause problems for programs that
           intend to handle SIGPIPE or count on being killed, but I expect
           such programs are very rare, and I'm not sure what the best
           solution would be anyway. */
        void *ret;

        ret = signal(SIGPIPE, SIG_IGN);
        MPIU_ERR_CHKANDJUMP1(ret == SIG_ERR, mpi_errno, MPI_ERR_OTHER, "**signal", "**signal %s", MPIU_Strerror(errno));
        if (ret != SIG_DFL && ret != SIG_IGN) {
            /* The app has set its own signal handler.  Replace the previous handler. */
            ret = signal(SIGPIPE, ret);
            MPIU_ERR_CHKANDJUMP1(ret == SIG_ERR, mpi_errno, MPI_ERR_OTHER, "**signal", "**signal %s", MPIU_Strerror(errno));
        }
    }
#endif
    
125
 fn_exit:
126
    MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_TCP_INIT);
127
128
129
130
131
132
133
/*     fprintf(stdout, FCNAME " Exit\n"); fflush(stdout); */
    return mpi_errno;
 fn_fail:
/*     fprintf(stdout, "failure. mpi_errno = %d\n", mpi_errno); */
    goto fn_exit;
}

134
135
136
137
138
139
#ifdef ENABLE_CHECKPOINTING

#undef FUNCNAME
#define FUNCNAME ckpt_restart
#undef FCNAME
#define FCNAME MPIDI_QUOTE(FUNCNAME)
140
static int ckpt_restart(void)
141
142
143
{
    int mpi_errno = MPI_SUCCESS;
    MPID_nem_queue_ptr_t dummy ;
144
145
146
    char *publish_bc_orig = NULL;
    char *bc_val          = NULL;
    int val_max_sz;
147
148
149
150
151
    int i;
    MPIDI_STATE_DECL(MPID_STATE_CKPT_RESTART);

    MPIDI_FUNC_ENTER(MPID_STATE_CKPT_RESTART);

152
153
    /* First, clean up.  We didn't shut anything down before the
       checkpoint, so we need to go close and free any resources */
154
155
    mpi_errno = MPID_nem_tcp_ckpt_cleanup();
    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
156
    mpi_errno = MPID_nem_tcp_send_finalize();
157
    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
158
159
160
    mpi_errno = MPID_nem_tcp_sm_finalize();
    if (mpi_errno) MPIU_ERR_POP(mpi_errno);

161
162
163
164
165
    /* Initialize the new business card */
    mpi_errno = MPIDI_CH3I_BCInit(&bc_val, &val_max_sz);
    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
    publish_bc_orig = bc_val;
    
166
    /* Now we can restart */
167
    mpi_errno = MPID_nem_tcp_init(MPIDI_Process.my_pg, MPIDI_Process.my_pg_rank, &bc_val, &val_max_sz);
168
169
    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
    
170
171
172
173
174
    /* publish business card */
    mpi_errno = MPIDI_PG_SetConnInfo(MPIDI_Process.my_pg_rank, (const char *)publish_bc_orig);
    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
    MPIU_Free(publish_bc_orig);

175
176
177
178
179
    for (i = 0; i < MPIDI_Process.my_pg->size; ++i) {
        MPIDI_VC_t *vc;
        MPIDI_CH3I_VC *vc_ch;
        if (i == MPIDI_Process.my_pg_rank)
            continue;
180
        MPIDI_PG_Get_vc(MPIDI_Process.my_pg, i, &vc);
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
        vc_ch = ((MPIDI_CH3I_VC *)vc->channel_private);
        if (!vc_ch->is_local) {
            mpi_errno = vc_ch->ckpt_restart_vc(vc);
            if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        }
    }
    

fn_exit:
    MPIDI_FUNC_EXIT(MPID_STATE_CKPT_RESTART);
    return mpi_errno;
fn_fail:

    goto fn_exit;
}
#endif

198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
/*
 * Get a description of the network interface to use for socket communication
 *
 * Here are the steps.  This order of checks is used to provide the 
 * user control over the choice of interface and to avoid, where possible,
 * the use of non-scalable services, such as centeralized name servers.
 *
 * MPICH_INTERFACE_HOSTNAME
 * MPICH_INTERFACE_HOSTNAME_R%d
 * a single (non-localhost) available IP address, if possible
 * gethostbyname(gethostname())
 *
 * We return the following items:
 *
 *    ifname - name of the interface.  This may or may not be the same
 *             as the name returned by gethostname  (in Unix)
 *    ifaddr - This structure includes the interface IP address (as bytes),
 *             and the type (e.g., AF_INET or AF_INET6).  Only 
 *             ipv4 (AF_INET) is used so far.
 */

static int GetSockInterfaceAddr(int myRank, char *ifname, int maxIfname,
                                MPIDU_Sock_ifaddr_t *ifaddr)
{
    char *ifname_string;
    int mpi_errno = MPI_SUCCESS;
    int ifaddrFound = 0;

    /* Set "not found" for ifaddr */
    ifaddr->len = 0;

    /* Check for the name supplied through an environment variable */
    ifname_string = getenv("MPICH_INTERFACE_HOSTNAME");
    if (!ifname_string) {
	/* See if there is a per-process name for the interfaces (e.g.,
	   the process manager only delievers the same values for the 
	   environment to each process */
	char namebuf[1024];
	MPIU_Snprintf( namebuf, sizeof(namebuf), 
		       "MPICH_INTERFACE_HOSTNAME_R%d", myRank );
	ifname_string = getenv( namebuf );
239

240
	if (DBG_IFNAME && ifname_string) {
241
242
243
244
245
	    fprintf( stdout, "Found interface name %s from %s\n", 
		    ifname_string, namebuf );
	    fflush( stdout );
	}
    }
246
    else if (DBG_IFNAME) {
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
	fprintf( stdout, 
		 "Found interface name %s from MPICH_INTERFACE_HOSTNAME\n", 
		 ifname_string );
	fflush( stdout );
    }
	 
    if (!ifname_string) {
	int len;

	/* If we have nothing, then use the host name */
	mpi_errno = MPID_Get_processor_name(ifname, maxIfname, &len );
	ifname_string = ifname;

	/* If we didn't find a specific name, then try to get an IP address
	   directly from the available interfaces, if that is supported on
	   this platform.  Otherwise, we'll drop into the next step that uses 
	   the ifname */
264
	mpi_errno = MPIDI_GetIPInterface( ifaddr, &ifaddrFound );
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
    }
    else {
	/* Copy this name into the output name */
	MPIU_Strncpy( ifname, ifname_string, maxIfname );
    }

    /* If we don't have an IP address, try to get it from the name */
    if (!ifaddrFound) {
	struct hostent *info;
	info = gethostbyname( ifname_string );
	if (info && info->h_addr_list) {
	    /* Use the primary address */
	    ifaddr->len  = info->h_length;
	    ifaddr->type = info->h_addrtype;
	    if (ifaddr->len > sizeof(ifaddr->ifaddr)) {
		/* If the address won't fit in the field, reset to
		   no address */
		ifaddr->len = 0;
		ifaddr->type = -1;
	    }
	    else
286
		MPIU_Memcpy( ifaddr->ifaddr, info->h_addr_list[0], ifaddr->len );
287
288
289
290
291
292
293
294
	}
    }

    return 0;
}


#undef FUNCNAME
295
#define FUNCNAME MPID_nem_tcp_get_business_card
296
297
#undef FCNAME
#define FCNAME MPIDI_QUOTE(FUNCNAME)
298
int MPID_nem_tcp_get_business_card (int my_rank, char **bc_val_p, int *val_max_sz_p)
299
300
{
    int mpi_errno = MPI_SUCCESS;
301
    int str_errno = MPIU_STR_SUCCESS;
302
303
304
305
306
    MPIDU_Sock_ifaddr_t ifaddr;
    char ifname[MAX_HOST_DESCRIPTION_LEN];
    int ret;
    struct sockaddr_in sock_id;
    socklen_t len;
307
    MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_TCP_GET_BUSINESS_CARD);
308

309
    MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_TCP_GET_BUSINESS_CARD);
310
311
312
313
314
    
    mpi_errno = GetSockInterfaceAddr(my_rank, ifname, sizeof(ifname), &ifaddr);
    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
    
    
315
316
317
318
    str_errno = MPIU_Str_add_string_arg(bc_val_p, val_max_sz_p, MPIDI_CH3I_HOST_DESCRIPTION_KEY, ifname);
    if (str_errno) {
        MPIU_ERR_CHKANDJUMP(str_errno == MPIU_STR_NOMEM, mpi_errno, MPI_ERR_OTHER, "**buscard_len");
        MPIU_ERR_SETANDJUMP(mpi_errno, MPI_ERR_OTHER, "**buscard");
319
320
321
    }

    len = sizeof(sock_id);
322
    ret = getsockname (MPID_nem_tcp_g_lstn_sc.fd, (struct sockaddr *)&sock_id, &len);
323
    MPIU_ERR_CHKANDJUMP1 (ret == -1, mpi_errno, MPI_ERR_OTHER, "**getsockname", "**getsockname %s", MPIU_Strerror (errno));
324

325
326
327
328
    str_errno = MPIU_Str_add_int_arg (bc_val_p, val_max_sz_p, MPIDI_CH3I_PORT_KEY, ntohs(sock_id.sin_port));
    if (str_errno) {
        MPIU_ERR_CHKANDJUMP(str_errno == MPIU_STR_NOMEM, mpi_errno, MPI_ERR_OTHER, "**buscard_len");
        MPIU_ERR_SETANDJUMP(mpi_errno, MPI_ERR_OTHER, "**buscard");
329
    }
330
331
    
    if (ifaddr.len > 0 && ifaddr.type == AF_INET)
332
    {
333
334
335
336
        unsigned char *p;
        p = (unsigned char *)(ifaddr.ifaddr);
        MPIU_Snprintf( ifname, sizeof(ifname), "%u.%u.%u.%u", p[0], p[1], p[2], p[3] );
        MPIU_DBG_MSG_S(CH3_CONNECT,VERBOSE,"ifname = %s",ifname );
337
338
339
340
        str_errno = MPIU_Str_add_string_arg(bc_val_p, val_max_sz_p, MPIDI_CH3I_IFNAME_KEY, ifname);
        if (str_errno) {
            MPIU_ERR_CHKANDJUMP(str_errno == MPIU_STR_NOMEM, mpi_errno, MPI_ERR_OTHER, "**buscard_len");
            MPIU_ERR_SETANDJUMP(mpi_errno, MPI_ERR_OTHER, "**buscard");
341
        }
342
    }
343
    
344

345
    /*     printf("MPID_nem_tcp_get_business_card. port=%d\n", sock_id.sin_port); */
346
347

 fn_exit:
348
349
/*     fprintf(stdout, "MPID_nem_tcp_get_business_card Exit, mpi_errno=%d\n", mpi_errno); fflush(stdout); */
    MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_TCP_GET_BUSINESS_CARD);
350
351
352
353
354
355
    return mpi_errno;
 fn_fail:
    goto fn_exit;
}

#undef FUNCNAME
356
#define FUNCNAME MPID_nem_tcp_connect_to_root
357
358
#undef FCNAME
#define FCNAME MPIDI_QUOTE(FUNCNAME)
359
int MPID_nem_tcp_connect_to_root (const char *business_card, MPIDI_VC_t *new_vc)
360
361
{
    int mpi_errno = MPI_SUCCESS;
362
    struct in_addr addr;
363
    MPID_nem_tcp_vc_area *vc_tcp = VC_TCP(new_vc);
364
    MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_TCP_CONNECT_TO_ROOT);
365

366
    MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_TCP_CONNECT_TO_ROOT);
367
368
369

    /* vc is already allocated before reaching this point */

370
371
    mpi_errno = MPID_nem_tcp_get_addr_port_from_bc(business_card, &addr, &vc_tcp->sock_id.sin_port);
    vc_tcp->sock_id.sin_addr.s_addr = addr.s_addr;
372
373
    if (mpi_errno) MPIU_ERR_POP(mpi_errno);

374
375
    mpi_errno = MPIDI_GetTagFromPort(business_card, &new_vc->port_name_tag);
    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
376
377
    mpi_errno = MPID_nem_tcp_connect(new_vc);
    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
378
379

 fn_exit:
380
    MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_TCP_CONNECT_TO_ROOT);
381
    return mpi_errno;
382
383
384

 fn_fail:
    goto fn_exit;
385
386
387
}

#undef FUNCNAME
388
#define FUNCNAME MPID_nem_tcp_vc_init
389
390
#undef FCNAME
#define FCNAME MPIDI_QUOTE(FUNCNAME)
391
int MPID_nem_tcp_vc_init (MPIDI_VC_t *vc)
392
393
394
{
    int mpi_errno = MPI_SUCCESS;
    MPIDI_CH3I_VC *vc_ch = (MPIDI_CH3I_VC *)vc->channel_private;
395
    MPID_nem_tcp_vc_area *vc_tcp = VC_TCP(vc);
396
    MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_TCP_VC_INIT);
397

398
    MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_TCP_VC_INIT);
399

400
    vc_tcp->state = MPID_NEM_TCP_VC_STATE_DISCONNECTED;
401
    
402
403
404
405
406
407
408
409
410
411
412
413
414
415
    vc->sendNoncontig_fn   = MPID_nem_tcp_SendNoncontig;
    vc_ch->iStartContigMsg = MPID_nem_tcp_iStartContigMsg;
    vc_ch->iSendContig     = MPID_nem_tcp_iSendContig;
#ifdef ENABLE_CHECKPOINTING
    vc_ch->ckpt_pause_send_vc = MPID_nem_tcp_ckpt_pause_send_vc;
    vc_ch->ckpt_continue_vc   = MPID_nem_tcp_ckpt_continue_vc;
    vc_ch->ckpt_restart_vc    = MPID_nem_tcp_ckpt_restart_vc;

    pkt_handlers[MPIDI_NEM_TCP_PKT_UNPAUSE] = MPID_nem_tcp_pkt_unpause_handler;
#endif

    vc_ch->pkt_handler = pkt_handlers;
    vc_ch->num_pkt_handlers = MPIDI_NEM_TCP_PKT_NUM_TYPES;

416
417
    memset(&vc_tcp->sock_id, 0, sizeof(vc_tcp->sock_id));
    vc_tcp->sock_id.sin_family = AF_INET;
418
419
420

    vc_ch->next = NULL;
    vc_ch->prev = NULL;
421

422
423
    ASSIGN_SC_TO_VC(vc_tcp, NULL);
    vc_tcp->send_queue.head = vc_tcp->send_queue.tail = NULL;
424

425
426
427
    vc_tcp->send_paused = FALSE;
    vc_tcp->paused_send_queue.head = vc_tcp->paused_send_queue.tail = NULL;

428
    vc_tcp->sc_ref_count = 0;
429
430
    
    vc_tcp->connect_retry_count = 0;
431

432
    MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_TCP_VC_INIT);
433
434
435
436
    return mpi_errno;
}

#undef FUNCNAME
437
#define FUNCNAME MPID_nem_tcp_vc_destroy
438
439
#undef FCNAME
#define FCNAME MPIDI_QUOTE(FUNCNAME)
440
int MPID_nem_tcp_vc_destroy(MPIDI_VC_t *vc)
441
{
442
443
444
    int mpi_errno = MPI_SUCCESS;

    /* currently do nothing */
445

446
    return mpi_errno;
447
448
449
}


450
451
452
453
454
/* 
   FIXME: this is the same function as in socksm.c 
   This should be removed and use only one function eventually.
*/
   
455
#undef FUNCNAME
456
#define FUNCNAME MPID_nem_tcp_get_addr_port_from_bc
457
458
#undef FCNAME
#define FCNAME MPIDI_QUOTE(FUNCNAME)
459
int MPID_nem_tcp_get_addr_port_from_bc(const char *business_card, struct in_addr *addr, in_port_t *port)
460
461
462
{
    int mpi_errno = MPI_SUCCESS;
    int ret;
463
    int port_int;
464
    /*char desc_str[256];*/
465
    char ifname[256];
466
    MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_TCP_GET_ADDR_PORT_FROM_BC);
467

468
    MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_TCP_GET_ADDR_PORT_FROM_BC);
469
470
    
    /*     fprintf(stdout, FCNAME " Enter\n"); fflush(stdout); */
471
472
    /* desc_str is only used for debugging
    ret = MPIU_Str_get_string_arg (business_card, MPIDI_CH3I_HOST_DESCRIPTION_KEY, desc_str, sizeof(desc_str));
473
    MPIU_ERR_CHKANDJUMP (ret != MPIU_STR_SUCCESS, mpi_errno, MPI_ERR_OTHER, "**argstr_missinghost");
474
    */
475

476
477
    /* sizeof(in_port_t) != sizeof(int) on most platforms, so we need to use
     * port_int as the arg to MPIU_Str_get_int_arg. */
478
479
480
481
    ret = MPIU_Str_get_int_arg (business_card, MPIDI_CH3I_PORT_KEY, &port_int);
    /* MPIU_STR_FAIL is not a valid MPI error code so we store the result in ret
     * instead of mpi_errno. */
    MPIU_ERR_CHKANDJUMP (ret != MPIU_STR_SUCCESS, mpi_errno, MPI_ERR_OTHER, "**argstr_missingport");
482
483
    MPIU_Assert((port_int >> (8*sizeof(*port))) == 0); /* ensure port_int isn't too large for *port */
    *port = htons((in_port_t)port_int);
484
485
486

    ret = MPIU_Str_get_string_arg(business_card, MPIDI_CH3I_IFNAME_KEY, ifname, sizeof(ifname));
    MPIU_ERR_CHKANDJUMP (ret != MPIU_STR_SUCCESS, mpi_errno, MPI_ERR_OTHER, "**argstr_missingifname");
487

488
489
490
491
492
493
    ret = inet_pton (AF_INET, (const char *)ifname, addr);
    MPIU_ERR_CHKANDJUMP(ret == 0, mpi_errno,MPI_ERR_OTHER,"**ifnameinvalid");
    MPIU_ERR_CHKANDJUMP(ret < 0, mpi_errno, MPI_ERR_OTHER, "**afinetinvalid");
    
 fn_exit:
/*     fprintf(stdout, FCNAME " Exit\n"); fflush(stdout); */
494
    MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_TCP_GET_ADDR_PORT_FROM_BC);
495
496
497
498
499
500
501
    return mpi_errno;
 fn_fail:
/*     fprintf(stdout, "failure. mpi_errno = %d\n", mpi_errno); */
    MPIU_DBG_MSG_FMT(NEM_SOCK_DET, VERBOSE, (MPIU_DBG_FDEST, "failure. mpi_errno = %d", mpi_errno));
    goto fn_exit;
}

502
/* MPID_nem_tcp_bind -- if MPICH_PORT_RANGE is set, this
503
504
505
   binds the socket to an available port number in the range.
   Otherwise, it binds it to any addr and any port */
#undef FUNCNAME
506
#define FUNCNAME MPID_nem_tcp_bind
507
508
#undef FCNAME
#define FCNAME MPIDI_QUOTE(FUNCNAME)
509
int MPID_nem_tcp_bind (int sockfd)
510
511
512
513
514
{
    int mpi_errno = MPI_SUCCESS;
    int ret;
    struct sockaddr_in sin;
    int port, low_port, high_port;
515
    MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_TCP_BIND);
516

517
    MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_TCP_BIND);
518
519
520
521
522
   
    low_port = 0;
    high_port = 0;

/*     fprintf(stdout, FCNAME " Enter\n"); fflush(stdout); */
523
    MPL_env2range( "MPICH_PORT_RANGE", &low_port, &high_port );
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
    MPIU_ERR_CHKANDJUMP (low_port < 0 || low_port > high_port, mpi_errno, MPI_ERR_OTHER, "**badportrange");

    /* if MPICH_PORT_RANGE is not set, low_port and high_port are 0 so bind will use any available port */
    ret = 0;
    for (port = low_port; port <= high_port; ++port)
    {
        memset ((void *)&sin, 0, sizeof(sin));
        sin.sin_family      = AF_INET;
        sin.sin_addr.s_addr = htonl(INADDR_ANY);
        sin.sin_port        = htons(port);

        ret = bind (sockfd, (struct sockaddr *)&sin, sizeof(sin));
        if (ret == 0)
            break;
        
        /* check for real error */
540
        MPIU_ERR_CHKANDJUMP3 (errno != EADDRINUSE && errno != EADDRNOTAVAIL, mpi_errno, MPI_ERR_OTHER, "**sock|poll|bind", "**sock|poll|bind %d %d %s", port, errno, MPIU_Strerror (errno));
541
542
    }
    /* check if an available port was found */
543
    MPIU_ERR_CHKANDJUMP3 (ret == -1, mpi_errno, MPI_ERR_OTHER, "**sock|poll|bind", "**sock|poll|bind %d %d %s", port, errno, MPIU_Strerror (errno));
544
545
546
547
548

 fn_exit:
/*     if (ret == 0) */
/*         fprintf(stdout, "sockfd=%d  port=%d bound\n", sockfd, port); */
/*     fprintf(stdout, FCNAME " Exit\n"); fflush(stdout); */
549
    MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_TCP_BIND);
550
551
552
553
554
555
556
    return mpi_errno;
 fn_fail:
/*     fprintf(stdout, "failure. mpi_errno = %d\n", mpi_errno); */
    MPIU_DBG_MSG_FMT(NEM_SOCK_DET, VERBOSE, (MPIU_DBG_FDEST, "failure. mpi_errno = %d", mpi_errno));
    goto fn_exit;
}

557

558
#undef FUNCNAME
559
#define FUNCNAME MPID_nem_tcp_vc_terminate
560
561
#undef FCNAME
#define FCNAME MPIDI_QUOTE(FUNCNAME)
562
int MPID_nem_tcp_vc_terminate (MPIDI_VC_t *vc)
563
{
564
    int mpi_errno = MPI_SUCCESS;
565
    MPIDI_STATE_DECL(MPID_NEM_TCP_VC_TERMINATE);
566

567
    MPIDI_FUNC_ENTER(MPID_NEM_TCP_VC_TERMINATE);
568

569
    mpi_errno = MPID_nem_tcp_cleanup(vc);
570
    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
571
572
    
 fn_exit:
573
    MPIDI_FUNC_EXIT(MPID_NEM_TCP_VC_TERMINATE);
574
575
576
577
    return mpi_errno;
 fn_fail:
    MPIU_DBG_MSG_FMT(NEM_SOCK_DET, VERBOSE, (MPIU_DBG_FDEST, "failure. mpi_errno = %d", mpi_errno));
    goto fn_exit;
578
579
}