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

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

converted all uses of memcpy to the macro MPIU_Memcpy

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    {
236        char ifname[256];
237        unsigned char *p;
238        if (ifaddr.len > 0 && ifaddr.type == AF_INET)
239        {
240            p = (unsigned char *)(ifaddr.ifaddr);
241            MPIU_Snprintf( ifname, sizeof(ifname), "%u.%u.%u.%u", p[0], p[1], p[2], p[3] );
242            MPIU_DBG_MSG_S(CH3_CONNECT,VERBOSE,"ifname = %s",ifname );
243            mpi_errno = MPIU_Str_add_string_arg(bc_val_p, val_max_sz_p, MPIDI_CH3I_IFNAME_KEY, ifname);
244            if (mpi_errno != MPIU_STR_SUCCESS)
245            {
246                if (mpi_errno == MPIU_STR_NOMEM)
247                {
248                    MPIU_ERR_SETANDJUMP(mpi_errno, MPI_ERR_OTHER, "**buscard_len");
249                }
250                else
251                {
252                    MPIU_ERR_SETANDJUMP(mpi_errno, MPI_ERR_OTHER, "**buscard");
253                }
254            }
255        }
256    }
257
258    /*     printf("MPID_nem_tcp_get_business_card. port=%d\n", sock_id.sin_port); */
259
260 fn_exit:
261/*     fprintf(stdout, "MPID_nem_tcp_get_business_card Exit, mpi_errno=%d\n", mpi_errno); fflush(stdout); */
262    MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_TCP_GET_BUSINESS_CARD);
263    return mpi_errno;
264 fn_fail:
265    goto fn_exit;
266}
267
268#undef FUNCNAME
269#define FUNCNAME MPID_nem_tcp_connect_to_root
270#undef FCNAME
271#define FCNAME MPIDI_QUOTE(FUNCNAME)
272int MPID_nem_tcp_connect_to_root (const char *business_card, MPIDI_VC_t *new_vc)
273{
274    int mpi_errno = MPI_SUCCESS;
275    struct in_addr addr;
276    MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_TCP_CONNECT_TO_ROOT);
277
278    MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_TCP_CONNECT_TO_ROOT);
279
280    /* vc is already allocated before reaching this point */
281
282    mpi_errno = MPID_nem_tcp_get_addr_port_from_bc(business_card, &addr, &(VC_FIELD(new_vc, sock_id).sin_port));
283    VC_FIELD(new_vc, sock_id).sin_addr.s_addr = addr.s_addr;
284    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
285
286    mpi_errno = MPIDI_GetTagFromPort(business_card, &new_vc->port_name_tag);
287    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
288    MPID_nem_tcp_connect(new_vc); 
289
290 fn_exit:
291    MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_TCP_CONNECT_TO_ROOT);
292    return mpi_errno;
293
294 fn_fail:
295    goto fn_exit;
296}
297
298#undef FUNCNAME
299#define FUNCNAME MPID_nem_tcp_vc_init
300#undef FCNAME
301#define FCNAME MPIDI_QUOTE(FUNCNAME)
302int MPID_nem_tcp_vc_init (MPIDI_VC_t *vc)
303{
304    int mpi_errno = MPI_SUCCESS;
305    MPIDI_CH3I_VC *vc_ch = (MPIDI_CH3I_VC *)vc->channel_private;
306    MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_TCP_VC_INIT);
307
308    MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_TCP_VC_INIT);
309
310    vc_ch->state = MPID_NEM_TCP_VC_STATE_DISCONNECTED;
311   
312    vc->sendNoncontig_fn      = MPID_nem_tcp_SendNoncontig;
313    vc_ch->iStartContigMsg    = MPID_nem_tcp_iStartContigMsg;
314    vc_ch->iSendContig        = MPID_nem_tcp_iSendContig;
315    memset(&VC_FIELD(vc, sock_id), 0, sizeof(VC_FIELD(vc, sock_id)));
316    VC_FIELD(vc, sock_id).sin_family = AF_INET;
317
318    vc_ch->next = NULL;
319    vc_ch->prev = NULL;
320
321    ASSIGN_SC_TO_VC(vc, NULL);
322    VC_FIELD(vc, send_queue).head = VC_FIELD(vc, send_queue).tail = NULL;
323
324    VC_FIELD(vc, sc_ref_count) = 0;
325
326    MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_TCP_VC_INIT);
327    return mpi_errno;
328}
329
330#undef FUNCNAME
331#define FUNCNAME MPID_nem_tcp_vc_destroy
332#undef FCNAME
333#define FCNAME MPIDI_QUOTE(FUNCNAME)
334int MPID_nem_tcp_vc_destroy(MPIDI_VC_t *vc)
335{
336    int mpi_errno = MPI_SUCCESS;
337
338    /* currently do nothing */
339#if 0
340    struct pollfd *plfd;
341    sockconn_t *sc;
342
343    sc = VC_FIELD(vc, sc);
344    if (sc == NULL)
345        goto fn_exit;
346
347    plfd = &MPID_nem_tcp_plfd_tbl[sc->index];
348#endif
349
350    return mpi_errno;
351}
352
353
354/*
355   FIXME: this is the same function as in socksm.c
356   This should be removed and use only one function eventually.
357*/
358   
359#undef FUNCNAME
360#define FUNCNAME MPID_nem_tcp_get_addr_port_from_bc
361#undef FCNAME
362#define FCNAME MPIDI_QUOTE(FUNCNAME)
363int MPID_nem_tcp_get_addr_port_from_bc(const char *business_card, struct in_addr *addr, in_port_t *port)
364{
365    int mpi_errno = MPI_SUCCESS;
366    int ret;
367    int port_int;
368    /*char desc_str[256];*/
369    char ifname[256];
370    MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_TCP_GET_ADDR_PORT_FROM_BC);
371
372    MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_TCP_GET_ADDR_PORT_FROM_BC);
373   
374    /*     fprintf(stdout, FCNAME " Enter\n"); fflush(stdout); */
375    /* desc_str is only used for debugging
376    ret = MPIU_Str_get_string_arg (business_card, MPIDI_CH3I_HOST_DESCRIPTION_KEY, desc_str, sizeof(desc_str));
377    MPIU_ERR_CHKANDJUMP (ret != MPIU_STR_SUCCESS, mpi_errno, MPI_ERR_OTHER, "**argstr_missinghost");
378    */
379
380    /* sizeof(in_port_t) != sizeof(int) on most platforms, so we need to use
381     * port_int as the arg to MPIU_Str_get_int_arg. */
382    ret = MPIU_Str_get_int_arg (business_card, MPIDI_CH3I_PORT_KEY, &port_int);
383    /* MPIU_STR_FAIL is not a valid MPI error code so we store the result in ret
384     * instead of mpi_errno. */
385    MPIU_ERR_CHKANDJUMP (ret != MPIU_STR_SUCCESS, mpi_errno, MPI_ERR_OTHER, "**argstr_missingport");
386    MPIU_Assert((port_int >> (8*sizeof(*port))) == 0); /* ensure port_int isn't too large for *port */
387    *port = htons((in_port_t)port_int);
388
389    ret = MPIU_Str_get_string_arg(business_card, MPIDI_CH3I_IFNAME_KEY, ifname, sizeof(ifname));
390    MPIU_ERR_CHKANDJUMP (ret != MPIU_STR_SUCCESS, mpi_errno, MPI_ERR_OTHER, "**argstr_missingifname");
391
392    ret = inet_pton (AF_INET, (const char *)ifname, addr);
393    MPIU_ERR_CHKANDJUMP(ret == 0, mpi_errno,MPI_ERR_OTHER,"**ifnameinvalid");
394    MPIU_ERR_CHKANDJUMP(ret < 0, mpi_errno, MPI_ERR_OTHER, "**afinetinvalid");
395   
396 fn_exit:
397/*     fprintf(stdout, FCNAME " Exit\n"); fflush(stdout); */
398    MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_TCP_GET_ADDR_PORT_FROM_BC);
399    return mpi_errno;
400 fn_fail:
401/*     fprintf(stdout, "failure. mpi_errno = %d\n", mpi_errno); */
402    MPIU_DBG_MSG_FMT(NEM_SOCK_DET, VERBOSE, (MPIU_DBG_FDEST, "failure. mpi_errno = %d", mpi_errno));
403    goto fn_exit;
404}
405
406/* MPID_nem_tcp_bind -- if MPICH_PORT_RANGE is set, this
407   binds the socket to an available port number in the range.
408   Otherwise, it binds it to any addr and any port */
409#undef FUNCNAME
410#define FUNCNAME MPID_nem_tcp_bind
411#undef FCNAME
412#define FCNAME MPIDI_QUOTE(FUNCNAME)
413int MPID_nem_tcp_bind (int sockfd)
414{
415    int mpi_errno = MPI_SUCCESS;
416    int ret;
417    struct sockaddr_in sin;
418    int port, low_port, high_port;
419    MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_TCP_BIND);
420
421    MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_TCP_BIND);
422   
423    low_port = 0;
424    high_port = 0;
425
426/*     fprintf(stdout, FCNAME " Enter\n"); fflush(stdout); */
427    MPIU_GetEnvRange( "MPICH_PORT_RANGE", &low_port, &high_port );
428    MPIU_ERR_CHKANDJUMP (low_port < 0 || low_port > high_port, mpi_errno, MPI_ERR_OTHER, "**badportrange");
429
430    /* if MPICH_PORT_RANGE is not set, low_port and high_port are 0 so bind will use any available port */
431    ret = 0;
432    for (port = low_port; port <= high_port; ++port)
433    {
434        memset ((void *)&sin, 0, sizeof(sin));
435        sin.sin_family      = AF_INET;
436        sin.sin_addr.s_addr = htonl(INADDR_ANY);
437        sin.sin_port        = htons(port);
438
439        ret = bind (sockfd, (struct sockaddr *)&sin, sizeof(sin));
440        if (ret == 0)
441            break;
442       
443        /* check for real error */
444        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));
445    }
446    /* check if an available port was found */
447    MPIU_ERR_CHKANDJUMP3 (ret == -1, mpi_errno, MPI_ERR_OTHER, "**sock|poll|bind", "**sock|poll|bind %d %d %s", port, errno, MPIU_Strerror (errno));
448
449 fn_exit:
450/*     if (ret == 0) */
451/*         fprintf(stdout, "sockfd=%d  port=%d bound\n", sockfd, port); */
452/*     fprintf(stdout, FCNAME " Exit\n"); fflush(stdout); */
453    MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_TCP_BIND);
454    return mpi_errno;
455 fn_fail:
456/*     fprintf(stdout, "failure. mpi_errno = %d\n", mpi_errno); */
457    MPIU_DBG_MSG_FMT(NEM_SOCK_DET, VERBOSE, (MPIU_DBG_FDEST, "failure. mpi_errno = %d", mpi_errno));
458    goto fn_exit;
459}
460
461
462#undef FUNCNAME
463#define FUNCNAME MPID_nem_tcp_vc_terminate
464#undef FCNAME
465#define FCNAME MPIDI_QUOTE(FUNCNAME)
466int MPID_nem_tcp_vc_terminate (MPIDI_VC_t *vc)
467{
468    int mpi_errno = MPI_SUCCESS;
469    MPIDI_STATE_DECL(MPID_NEM_TCP_VC_TERMINATE);
470
471    MPIDI_FUNC_ENTER(MPID_NEM_TCP_VC_TERMINATE);
472
473    mpi_errno = MPID_nem_tcp_cleanup(vc);
474    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
475   
476 fn_exit:
477    MPIDI_FUNC_EXIT(MPID_NEM_TCP_VC_TERMINATE);
478    return mpi_errno;
479 fn_fail:
480    MPIU_DBG_MSG_FMT(NEM_SOCK_DET, VERBOSE, (MPIU_DBG_FDEST, "failure. mpi_errno = %d", mpi_errno));
481    goto fn_exit;
482}
Note: See TracBrowser for help on using the browser.