root/mpich2/trunk/src/mpid/ch3/channels/nemesis/nemesis/netmod/tcp/tcp_init.c @ 4865

Revision 4865, 16.0 KB (checked in by buntinas, 5 months ago)

stomped some warnings

Line 
1/* -*- Mode: C; c-basic-offset:4 ; -*- */
2/*
3 *  (C) 2006 by Argonne National Laboratory.
4 *      See COPYRIGHT in top-level directory.
5 */
6
7#include "tcp_impl.h"
8#include <sys/types.h>
9#include <sys/socket.h>
10#include <arpa/inet.h>
11
12#define DBG_IFNAME 0
13
14MPID_nem_netmod_funcs_t MPIDI_nem_tcp_funcs = {
15    MPID_nem_tcp_init,
16    MPID_nem_tcp_finalize,
17    MPID_nem_tcp_ckpt_shutdown,
18    MPID_nem_tcp_connpoll,
19    MPID_nem_tcp_send,
20    MPID_nem_tcp_get_business_card,
21    MPID_nem_tcp_connect_to_root,
22    MPID_nem_tcp_vc_init,
23    MPID_nem_tcp_vc_destroy,
24    MPID_nem_tcp_vc_terminate
25};
26
27#define MPIDI_CH3I_PORT_KEY "port"
28#define MPIDI_CH3I_HOST_DESCRIPTION_KEY "description"
29#define MPIDI_CH3I_IFNAME_KEY "ifname"
30
31#undef FUNCNAME
32#define FUNCNAME MPID_nem_tcp_init
33#undef FCNAME
34#define FCNAME MPIDI_QUOTE(FUNCNAME)
35int MPID_nem_tcp_init (MPID_nem_queue_ptr_t proc_recv_queue, MPID_nem_queue_ptr_t proc_free_queue,
36                                 MPID_nem_cell_ptr_t proc_elements, int num_proc_elements, MPID_nem_cell_ptr_t module_elements,
37                                 int num_module_elements, MPID_nem_queue_ptr_t *module_free_queue,
38                                 int ckpt_restart, MPIDI_PG_t *pg_p, int pg_rank, char **bc_val_p, int *val_max_sz_p)
39{
40    int mpi_errno = MPI_SUCCESS;
41    int ret;
42    MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_TCP_INIT);
43
44    MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_TCP_INIT);
45
46    MPID_nem_net_module_vc_dbg_print_sendq = MPID_nem_tcp_vc_dbg_print_sendq;
47
48    /* first make sure that our private fields in the vc fit into the area provided  */
49    MPIU_Assert(sizeof(MPID_nem_tcp_vc_area) <= MPID_NEM_VC_NETMOD_AREA_LEN);
50
51    /* set up listener socket */
52/*     fprintf(stdout, FCNAME " Enter\n"); fflush(stdout); */
53    MPID_nem_tcp_g_lstn_plfd.fd = MPID_nem_tcp_g_lstn_sc.fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
54    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);
55
56    mpi_errno = MPID_nem_tcp_set_sockopts (MPID_nem_tcp_g_lstn_sc.fd);
57    if (mpi_errno) MPIU_ERR_POP (mpi_errno);
58
59    MPID_nem_tcp_g_lstn_plfd.events = POLLIN;
60    mpi_errno = MPID_nem_tcp_bind (MPID_nem_tcp_g_lstn_sc.fd);
61    if (mpi_errno) MPIU_ERR_POP (mpi_errno);
62
63    ret = listen (MPID_nem_tcp_g_lstn_sc.fd, SOMAXCONN);             
64    MPIU_ERR_CHKANDJUMP2 (ret == -1, mpi_errno, MPI_ERR_OTHER, "**listen", "**listen %s %d", errno, MPIU_Strerror (errno)); 
65    MPID_nem_tcp_g_lstn_sc.state.lstate = LISTEN_STATE_LISTENING;
66    MPID_nem_tcp_g_lstn_sc.handler = MPID_nem_tcp_state_listening_handler;
67
68    /* create business card */
69    mpi_errno = MPID_nem_tcp_get_business_card(pg_rank, bc_val_p, val_max_sz_p);
70    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
71
72    *module_free_queue = NULL;
73
74    mpi_errno = MPID_nem_tcp_sm_init();
75    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
76    mpi_errno = MPID_nem_tcp_send_init();
77    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
78
79
80 fn_exit:
81    MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_TCP_INIT);
82/*     fprintf(stdout, FCNAME " Exit\n"); fflush(stdout); */
83    return mpi_errno;
84 fn_fail:
85/*     fprintf(stdout, "failure. mpi_errno = %d\n", mpi_errno); */
86    goto fn_exit;
87}
88
89/*
90 * Get a description of the network interface to use for socket communication
91 *
92 * Here are the steps.  This order of checks is used to provide the
93 * user control over the choice of interface and to avoid, where possible,
94 * the use of non-scalable services, such as centeralized name servers.
95 *
96 * MPICH_INTERFACE_HOSTNAME
97 * MPICH_INTERFACE_HOSTNAME_R%d
98 * a single (non-localhost) available IP address, if possible
99 * gethostbyname(gethostname())
100 *
101 * We return the following items:
102 *
103 *    ifname - name of the interface.  This may or may not be the same
104 *             as the name returned by gethostname  (in Unix)
105 *    ifaddr - This structure includes the interface IP address (as bytes),
106 *             and the type (e.g., AF_INET or AF_INET6).  Only
107 *             ipv4 (AF_INET) is used so far.
108 */
109
110static int GetSockInterfaceAddr(int myRank, char *ifname, int maxIfname,
111                                MPIDU_Sock_ifaddr_t *ifaddr)
112{
113    char *ifname_string;
114    int mpi_errno = MPI_SUCCESS;
115    int ifaddrFound = 0;
116
117    /* Set "not found" for ifaddr */
118    ifaddr->len = 0;
119
120    /* Check for the name supplied through an environment variable */
121    ifname_string = getenv("MPICH_INTERFACE_HOSTNAME");
122    if (!ifname_string) {
123        /* See if there is a per-process name for the interfaces (e.g.,
124           the process manager only delievers the same values for the
125           environment to each process */
126        char namebuf[1024];
127        MPIU_Snprintf( namebuf, sizeof(namebuf), 
128                       "MPICH_INTERFACE_HOSTNAME_R%d", myRank );
129        ifname_string = getenv( namebuf );
130
131        if (DBG_IFNAME && ifname_string) {
132            fprintf( stdout, "Found interface name %s from %s\n", 
133                    ifname_string, namebuf );
134            fflush( stdout );
135        }
136    }
137    else if (DBG_IFNAME) {
138        fprintf( stdout, 
139                 "Found interface name %s from MPICH_INTERFACE_HOSTNAME\n", 
140                 ifname_string );
141        fflush( stdout );
142    }
143         
144    if (!ifname_string) {
145        int len;
146
147        /* If we have nothing, then use the host name */
148        mpi_errno = MPID_Get_processor_name(ifname, maxIfname, &len );
149        ifname_string = ifname;
150
151        /* If we didn't find a specific name, then try to get an IP address
152           directly from the available interfaces, if that is supported on
153           this platform.  Otherwise, we'll drop into the next step that uses
154           the ifname */
155        mpi_errno = MPIDI_GetIPInterface( ifaddr, &ifaddrFound );
156    }
157    else {
158        /* Copy this name into the output name */
159        MPIU_Strncpy( ifname, ifname_string, maxIfname );
160    }
161
162    /* If we don't have an IP address, try to get it from the name */
163    if (!ifaddrFound) {
164        struct hostent *info;
165        info = gethostbyname( ifname_string );
166        if (info && info->h_addr_list) {
167            /* Use the primary address */
168            ifaddr->len  = info->h_length;
169            ifaddr->type = info->h_addrtype;
170            if (ifaddr->len > sizeof(ifaddr->ifaddr)) {
171                /* If the address won't fit in the field, reset to
172                   no address */
173                ifaddr->len = 0;
174                ifaddr->type = -1;
175            }
176            else
177                MPIU_Memcpy( ifaddr->ifaddr, info->h_addr_list[0], ifaddr->len );
178        }
179    }
180
181    return 0;
182}
183
184
185#undef FUNCNAME
186#define FUNCNAME MPID_nem_tcp_get_business_card
187#undef FCNAME
188#define FCNAME MPIDI_QUOTE(FUNCNAME)
189int MPID_nem_tcp_get_business_card (int my_rank, char **bc_val_p, int *val_max_sz_p)
190{
191    int mpi_errno = MPI_SUCCESS;
192    MPIDU_Sock_ifaddr_t ifaddr;
193    char ifname[MAX_HOST_DESCRIPTION_LEN];
194    int ret;
195    struct sockaddr_in sock_id;
196    socklen_t len;
197    MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_TCP_GET_BUSINESS_CARD);
198
199    MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_TCP_GET_BUSINESS_CARD);
200   
201    mpi_errno = GetSockInterfaceAddr(my_rank, ifname, sizeof(ifname), &ifaddr);
202    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
203   
204   
205    mpi_errno = MPIU_Str_add_string_arg(bc_val_p, val_max_sz_p, MPIDI_CH3I_HOST_DESCRIPTION_KEY, ifname);
206    if (mpi_errno != MPIU_STR_SUCCESS)
207    {
208        if (mpi_errno == MPIU_STR_NOMEM)
209        {
210            MPIU_ERR_SETANDJUMP(mpi_errno, MPI_ERR_OTHER, "**buscard_len");
211        }
212        else
213        {
214            MPIU_ERR_SETANDJUMP(mpi_errno, MPI_ERR_OTHER, "**buscard");
215        }
216    }
217
218    len = sizeof(sock_id);
219    ret = getsockname (MPID_nem_tcp_g_lstn_sc.fd, (struct sockaddr *)&sock_id, &len);
220    MPIU_ERR_CHKANDJUMP1 (ret == -1, mpi_errno, MPI_ERR_OTHER, "**getsockname", "**getsockname %s", MPIU_Strerror (errno));
221
222    mpi_errno = MPIU_Str_add_int_arg (bc_val_p, val_max_sz_p, MPIDI_CH3I_PORT_KEY, ntohs(sock_id.sin_port));
223    if (mpi_errno != MPIU_STR_SUCCESS)
224    {
225        if (mpi_errno == MPIU_STR_NOMEM)
226        {
227            MPIU_ERR_SETANDJUMP(mpi_errno, MPI_ERR_OTHER, "**buscard_len");
228        }
229        else
230        {
231            MPIU_ERR_SETANDJUMP(mpi_errno, MPI_ERR_OTHER, "**buscard");
232        }
233    }
234   
235    if (ifaddr.len > 0 && ifaddr.type == AF_INET)
236    {
237        unsigned char *p;
238        p = (unsigned char *)(ifaddr.ifaddr);
239        MPIU_Snprintf( ifname, sizeof(ifname), "%u.%u.%u.%u", p[0], p[1], p[2], p[3] );
240        MPIU_DBG_MSG_S(CH3_CONNECT,VERBOSE,"ifname = %s",ifname );
241        mpi_errno = MPIU_Str_add_string_arg(bc_val_p, val_max_sz_p, MPIDI_CH3I_IFNAME_KEY, ifname);
242        if (mpi_errno != MPIU_STR_SUCCESS)
243        {
244            if (mpi_errno == MPIU_STR_NOMEM)
245            {
246                MPIU_ERR_SETANDJUMP(mpi_errno, MPI_ERR_OTHER, "**buscard_len");
247            }
248            else
249            {
250                MPIU_ERR_SETANDJUMP(mpi_errno, MPI_ERR_OTHER, "**buscard");
251            }
252        }
253    }
254   
255
256    /*     printf("MPID_nem_tcp_get_business_card. port=%d\n", sock_id.sin_port); */
257
258 fn_exit:
259/*     fprintf(stdout, "MPID_nem_tcp_get_business_card Exit, mpi_errno=%d\n", mpi_errno); fflush(stdout); */
260    MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_TCP_GET_BUSINESS_CARD);
261    return mpi_errno;
262 fn_fail:
263    goto fn_exit;
264}
265
266#undef FUNCNAME
267#define FUNCNAME MPID_nem_tcp_connect_to_root
268#undef FCNAME
269#define FCNAME MPIDI_QUOTE(FUNCNAME)
270int MPID_nem_tcp_connect_to_root (const char *business_card, MPIDI_VC_t *new_vc)
271{
272    int mpi_errno = MPI_SUCCESS;
273    struct in_addr addr;
274    MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_TCP_CONNECT_TO_ROOT);
275
276    MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_TCP_CONNECT_TO_ROOT);
277
278    /* vc is already allocated before reaching this point */
279
280    mpi_errno = MPID_nem_tcp_get_addr_port_from_bc(business_card, &addr, &(VC_FIELD(new_vc, sock_id).sin_port));
281    VC_FIELD(new_vc, sock_id).sin_addr.s_addr = addr.s_addr;
282    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
283
284    mpi_errno = MPIDI_GetTagFromPort(business_card, &new_vc->port_name_tag);
285    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
286    MPID_nem_tcp_connect(new_vc); 
287
288 fn_exit:
289    MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_TCP_CONNECT_TO_ROOT);
290    return mpi_errno;
291
292 fn_fail:
293    goto fn_exit;
294}
295
296#undef FUNCNAME
297#define FUNCNAME MPID_nem_tcp_vc_init
298#undef FCNAME
299#define FCNAME MPIDI_QUOTE(FUNCNAME)
300int MPID_nem_tcp_vc_init (MPIDI_VC_t *vc)
301{
302    int mpi_errno = MPI_SUCCESS;
303    MPIDI_CH3I_VC *vc_ch = (MPIDI_CH3I_VC *)vc->channel_private;
304    MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_TCP_VC_INIT);
305
306    MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_TCP_VC_INIT);
307
308    vc_ch->state = MPID_NEM_TCP_VC_STATE_DISCONNECTED;
309   
310    vc->sendNoncontig_fn      = MPID_nem_tcp_SendNoncontig;
311    vc_ch->iStartContigMsg    = MPID_nem_tcp_iStartContigMsg;
312    vc_ch->iSendContig        = MPID_nem_tcp_iSendContig;
313    memset(&VC_FIELD(vc, sock_id), 0, sizeof(VC_FIELD(vc, sock_id)));
314    VC_FIELD(vc, sock_id).sin_family = AF_INET;
315
316    vc_ch->next = NULL;
317    vc_ch->prev = NULL;
318
319    ASSIGN_SC_TO_VC(vc, NULL);
320    VC_FIELD(vc, send_queue).head = VC_FIELD(vc, send_queue).tail = NULL;
321
322    VC_FIELD(vc, sc_ref_count) = 0;
323
324    MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_TCP_VC_INIT);
325    return mpi_errno;
326}
327
328#undef FUNCNAME
329#define FUNCNAME MPID_nem_tcp_vc_destroy
330#undef FCNAME
331#define FCNAME MPIDI_QUOTE(FUNCNAME)
332int MPID_nem_tcp_vc_destroy(MPIDI_VC_t *vc)
333{
334    int mpi_errno = MPI_SUCCESS;
335
336    /* currently do nothing */
337#if 0
338    struct pollfd *plfd;
339    sockconn_t *sc;
340
341    sc = VC_FIELD(vc, sc);
342    if (sc == NULL)
343        goto fn_exit;
344
345    plfd = &MPID_nem_tcp_plfd_tbl[sc->index];
346#endif
347
348    return mpi_errno;
349}
350
351
352/*
353   FIXME: this is the same function as in socksm.c
354   This should be removed and use only one function eventually.
355*/
356   
357#undef FUNCNAME
358#define FUNCNAME MPID_nem_tcp_get_addr_port_from_bc
359#undef FCNAME
360#define FCNAME MPIDI_QUOTE(FUNCNAME)
361int MPID_nem_tcp_get_addr_port_from_bc(const char *business_card, struct in_addr *addr, in_port_t *port)
362{
363    int mpi_errno = MPI_SUCCESS;
364    int ret;
365    int port_int;
366    /*char desc_str[256];*/
367    char ifname[256];
368    MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_TCP_GET_ADDR_PORT_FROM_BC);
369
370    MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_TCP_GET_ADDR_PORT_FROM_BC);
371   
372    /*     fprintf(stdout, FCNAME " Enter\n"); fflush(stdout); */
373    /* desc_str is only used for debugging
374    ret = MPIU_Str_get_string_arg (business_card, MPIDI_CH3I_HOST_DESCRIPTION_KEY, desc_str, sizeof(desc_str));
375    MPIU_ERR_CHKANDJUMP (ret != MPIU_STR_SUCCESS, mpi_errno, MPI_ERR_OTHER, "**argstr_missinghost");
376    */
377
378    /* sizeof(in_port_t) != sizeof(int) on most platforms, so we need to use
379     * port_int as the arg to MPIU_Str_get_int_arg. */
380    ret = MPIU_Str_get_int_arg (business_card, MPIDI_CH3I_PORT_KEY, &port_int);
381    /* MPIU_STR_FAIL is not a valid MPI error code so we store the result in ret
382     * instead of mpi_errno. */
383    MPIU_ERR_CHKANDJUMP (ret != MPIU_STR_SUCCESS, mpi_errno, MPI_ERR_OTHER, "**argstr_missingport");
384    MPIU_Assert((port_int >> (8*sizeof(*port))) == 0); /* ensure port_int isn't too large for *port */
385    *port = htons((in_port_t)port_int);
386
387    ret = MPIU_Str_get_string_arg(business_card, MPIDI_CH3I_IFNAME_KEY, ifname, sizeof(ifname));
388    MPIU_ERR_CHKANDJUMP (ret != MPIU_STR_SUCCESS, mpi_errno, MPI_ERR_OTHER, "**argstr_missingifname");
389
390    ret = inet_pton (AF_INET, (const char *)ifname, addr);
391    MPIU_ERR_CHKANDJUMP(ret == 0, mpi_errno,MPI_ERR_OTHER,"**ifnameinvalid");
392    MPIU_ERR_CHKANDJUMP(ret < 0, mpi_errno, MPI_ERR_OTHER, "**afinetinvalid");
393   
394 fn_exit:
395/*     fprintf(stdout, FCNAME " Exit\n"); fflush(stdout); */
396    MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_TCP_GET_ADDR_PORT_FROM_BC);
397    return mpi_errno;
398 fn_fail:
399/*     fprintf(stdout, "failure. mpi_errno = %d\n", mpi_errno); */
400    MPIU_DBG_MSG_FMT(NEM_SOCK_DET, VERBOSE, (MPIU_DBG_FDEST, "failure. mpi_errno = %d", mpi_errno));
401    goto fn_exit;
402}
403
404/* MPID_nem_tcp_bind -- if MPICH_PORT_RANGE is set, this
405   binds the socket to an available port number in the range.
406   Otherwise, it binds it to any addr and any port */
407#undef FUNCNAME
408#define FUNCNAME MPID_nem_tcp_bind
409#undef FCNAME
410#define FCNAME MPIDI_QUOTE(FUNCNAME)
411int MPID_nem_tcp_bind (int sockfd)
412{
413    int mpi_errno = MPI_SUCCESS;
414    int ret;
415    struct sockaddr_in sin;
416    int port, low_port, high_port;
417    MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_TCP_BIND);
418
419    MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_TCP_BIND);
420   
421    low_port = 0;
422    high_port = 0;
423
424/*     fprintf(stdout, FCNAME " Enter\n"); fflush(stdout); */
425    MPIU_GetEnvRange( "MPICH_PORT_RANGE", &low_port, &high_port );
426    MPIU_ERR_CHKANDJUMP (low_port < 0 || low_port > high_port, mpi_errno, MPI_ERR_OTHER, "**badportrange");
427
428    /* if MPICH_PORT_RANGE is not set, low_port and high_port are 0 so bind will use any available port */
429    ret = 0;
430    for (port = low_port; port <= high_port; ++port)
431    {
432        memset ((void *)&sin, 0, sizeof(sin));
433        sin.sin_family      = AF_INET;
434        sin.sin_addr.s_addr = htonl(INADDR_ANY);
435        sin.sin_port        = htons(port);
436
437        ret = bind (sockfd, (struct sockaddr *)&sin, sizeof(sin));
438        if (ret == 0)
439            break;
440       
441        /* check for real error */
442        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));
443    }
444    /* check if an available port was found */
445    MPIU_ERR_CHKANDJUMP3 (ret == -1, mpi_errno, MPI_ERR_OTHER, "**sock|poll|bind", "**sock|poll|bind %d %d %s", port, errno, MPIU_Strerror (errno));
446
447 fn_exit:
448/*     if (ret == 0) */
449/*         fprintf(stdout, "sockfd=%d  port=%d bound\n", sockfd, port); */
450/*     fprintf(stdout, FCNAME " Exit\n"); fflush(stdout); */
451    MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_TCP_BIND);
452    return mpi_errno;
453 fn_fail:
454/*     fprintf(stdout, "failure. mpi_errno = %d\n", mpi_errno); */
455    MPIU_DBG_MSG_FMT(NEM_SOCK_DET, VERBOSE, (MPIU_DBG_FDEST, "failure. mpi_errno = %d", mpi_errno));
456    goto fn_exit;
457}
458
459
460#undef FUNCNAME
461#define FUNCNAME MPID_nem_tcp_vc_terminate
462#undef FCNAME
463#define FCNAME MPIDI_QUOTE(FUNCNAME)
464int MPID_nem_tcp_vc_terminate (MPIDI_VC_t *vc)
465{
466    int mpi_errno = MPI_SUCCESS;
467    MPIDI_STATE_DECL(MPID_NEM_TCP_VC_TERMINATE);
468
469    MPIDI_FUNC_ENTER(MPID_NEM_TCP_VC_TERMINATE);
470
471    mpi_errno = MPID_nem_tcp_cleanup(vc);
472    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
473   
474 fn_exit:
475    MPIDI_FUNC_EXIT(MPID_NEM_TCP_VC_TERMINATE);
476    return mpi_errno;
477 fn_fail:
478    MPIU_DBG_MSG_FMT(NEM_SOCK_DET, VERBOSE, (MPIU_DBG_FDEST, "failure. mpi_errno = %d", mpi_errno));
479    goto fn_exit;
480}
Note: See TracBrowser for help on using the browser.