int ompi_btl_usnic_find_ip(ompi_btl_usnic_module_t *module, uint8_t mac[6])
{
    int i;
    uint8_t localmac[6];
    char addr_string[32], mac_string[32];
    struct sockaddr sa;
    struct sockaddr_in *sai;

    /* Loop through all IP interfaces looking for the one with the
       right MAC */
    for (i = opal_ifbegin(); i != -1; i = opal_ifnext(i)) {
        if (OPAL_SUCCESS == opal_ifindextomac(i, localmac)) {

            /* Is this the MAC I'm looking for? */
            if (0 != memcmp(mac, localmac, 6)) {
                continue;
            }

            /* Yes, it is! */
            if (OPAL_SUCCESS != opal_ifindextoname(i, module->if_name, 
                                                   sizeof(module->if_name)) ||
                OPAL_SUCCESS != opal_ifindextoaddr(i, &sa, sizeof(sa)) ||
                OPAL_SUCCESS != opal_ifindextomask(i, &module->if_cidrmask,
                                                   sizeof(module->if_cidrmask)) ||
                OPAL_SUCCESS != opal_ifindextomac(i, module->if_mac) ||
                OPAL_SUCCESS != opal_ifindextomtu(i, &module->if_mtu)) {
                continue;
            }

            sai = (struct sockaddr_in *) &sa;
            memcpy(&module->if_ipv4_addr, &sai->sin_addr, 4);

            /* Save this information to my local address field on the
               module so that it gets sent in the modex */
            module->local_addr.ipv4_addr = module->if_ipv4_addr;
            module->local_addr.cidrmask = module->if_cidrmask;

            /* Since verbs doesn't offer a way to get standard
               Ethernet MTUs (as of libibverbs 1.1.5, the MTUs are
               enums, and don't inlcude values for 1500 or 9000), look
               up the MTU in the corresponding enic interface. */
            module->local_addr.mtu = module->if_mtu;

            inet_ntop(AF_INET, &(module->if_ipv4_addr),
                      addr_string, sizeof(addr_string));
            ompi_btl_usnic_sprintf_mac(mac_string, mac);
            opal_output_verbose(5, mca_btl_base_verbose,
                                "btl:usnic: found usNIC device corresponds to IP device %s, %s/%d, MAC %s",
                                module->if_name, addr_string, module->if_cidrmask, 
                                mac_string);
            return OMPI_SUCCESS;
        }
    }

    return OMPI_ERR_NOT_FOUND;
}
Esempio n. 2
0
/*
 * Find and assign system netmask for the address of the uDAPL BTL
 * module, but only if udapl_if_mask has not been set by the "--mca
 * btl_udapl_if_mask" parameter. This routine will either find
 * the system netmask or set the value to 0.
 *
 * @param udapl_btl (IN)      BTL module
 *
 * @return                    OMPI_SUCCESS or OMPI_ERROR
 */
static int mca_btl_udapl_assign_netmask(mca_btl_udapl_module_t* udapl_btl)
{
    struct sockaddr *saddr;
    struct sockaddr_in *btl_addr;
    char btl_addr_string[INET_ADDRSTRLEN]; 
    char btl_ifname[INET_ADDRSTRLEN];

    /* Setting if_mask to 0 informs future steps to assume all
     * addresses are reachable.
     */
    udapl_btl->udapl_if_mask = 0; 

    if (mca_btl_udapl_component.udapl_compare_subnet) {
        /* go get system netmask value */

        /* use generic address to find address family */
        saddr = (struct sockaddr *)&(udapl_btl->udapl_addr.addr);

        if (saddr->sa_family == AF_INET) {

            btl_addr = (struct sockaddr_in *)saddr;

            /*
             * Retrieve the netmask of the udapl btl address. To
             * accomplish this requires 4 steps and the use of an opal
             * utility. This same utility is used by the tcp oob.
             * Steps:
             *     1. Get string value of known udapl btl module address.
             *     2. Use string value to find the interface name of address.
             *     3. Use interface name to find its index.
             *     4. From the index get the netmask.
             */

            /* retrieve string value of udapl btl address */
            inet_ntop(AF_INET, (void *) &btl_addr->sin_addr,
                btl_addr_string, INET_ADDRSTRLEN);

            /* use address string to retrieve associated interface name */
            if (OPAL_SUCCESS != 
                opal_ifaddrtoname(btl_addr_string,
                    btl_ifname, INET_ADDRSTRLEN)) {

                BTL_UDAPL_VERBOSE_HELP(VERBOSE_SHOW_HELP,
                    ("help-mpi-btl-udapl.txt", "interface not found",
                        true, ompi_process_info.nodename, btl_addr_string));

                return OMPI_ERROR;
            }

            /* use interface name to retrieve index;  then
             * use index to retrieve udapl btl address netmask
             */
            if (OPAL_SUCCESS != 
                opal_ifindextomask(opal_ifnametoindex(btl_ifname),
                    &(udapl_btl->udapl_if_mask), sizeof(udapl_btl->udapl_if_mask))) {

                BTL_UDAPL_VERBOSE_HELP(VERBOSE_SHOW_HELP,
                    ("help-mpi-btl-udapl.txt", "netmask not found",
                        true, ompi_process_info.nodename, btl_addr_string));

                return OMPI_ERROR;
            }

            /* report if_mask used by address */
            BTL_UDAPL_VERBOSE_OUTPUT(VERBOSE_INFORM,
                ("uDAPL BTL address %s : if_mask = %d",
                btl_addr_string, udapl_btl->udapl_if_mask));

        } else {
            /* current uDAPL BTL does not support IPv6 */
            BTL_UDAPL_VERBOSE_HELP(VERBOSE_SHOW_HELP,
                ("help-mpi-btl-udapl.txt", "IPv4 only",
                    true, ompi_process_info.nodename));

            return OMPI_ERROR;
        }
    }

    return OMPI_SUCCESS;
}
Esempio n. 3
0
int mca_oob_tcp_addr_get_next(mca_oob_tcp_addr_t* addr, struct sockaddr* retval)
{
    static uint32_t i_have = MCA_OOB_TCP_ADDR_UNCLASSIFIED; /* my own capabilities */
    
    if((NULL == addr) || (0 == addr->addr_count)) {
        return ORTE_ERROR;
    }
    
    if(MCA_OOB_TCP_ADDR_UNCLASSIFIED == addr->addr_matched) {
        orte_std_cntr_t i=0;
        for(i=addr->addr_next; i<addr->addr_count; i++) {
            opal_list_item_t *item;
            for (item = opal_list_get_first(&mca_oob_tcp_component.tcp_available_devices) ;
                 item != opal_list_get_end(&mca_oob_tcp_component.tcp_available_devices) ;
                 item = opal_list_get_next(item)) {
                mca_oob_tcp_device_t *dev = (mca_oob_tcp_device_t*) item;
                uint32_t inmask;

                opal_ifindextomask(dev->if_index, &inmask, sizeof(inmask));

                /* Decide which address to try first; note that we're
                    called multiple times and each time we need to
                    present a different address
                    
                    Precedence rules:
                    
                    - IPv4public has the highest priority
                    - when IPv4private + IPv6, use IPv6 (this should
                      be changed when there is something like a CellID)
                    */
                if (true == opal_net_addr_isipv4public ((struct sockaddr*) &dev->if_addr)) {
                    i_have |= MCA_OOB_TCP_ADDR_IPV4public;
                }
                
                if (true == opal_net_addr_isipv4public ((struct sockaddr*)&addr->addr_inet[i])) {
                    addr->addr_matched |= MCA_OOB_TCP_ADDR_IPV4public;
                }
                
                if ((MCA_OOB_TCP_ADDR_IPV4public ==
                     (i_have & MCA_OOB_TCP_ADDR_IPV4public)) &&
                    (MCA_OOB_TCP_ADDR_IPV4public ==
                     (addr->addr_matched & MCA_OOB_TCP_ADDR_IPV4public))) {
                    addr->addr_next = i;
                    goto done;
                }
                
                if (AF_INET6 == dev->if_addr.ss_family) {
                    i_have |= MCA_OOB_TCP_ADDR_IPV6;
                }
                
                if (AF_INET6 ==
                    ((struct sockaddr_in6*)&addr->addr_inet[i])->sin6_family) {
                    addr->addr_matched |= MCA_OOB_TCP_ADDR_IPV6;
                    addr->addr_next = i;
                    goto done;
                }
                
                /* if match on network prefix - start here */
                /* Bug, FIXME: This code is dangerous, it will prefer
                    local addresses even if they point to wrong hosts
                    (the multicluster problem).
                    
                    We need more magic to select the best address
                    
                    adi@2006-09-30
                */
                if(opal_net_samenetwork((struct sockaddr*) &dev->if_addr,
                                        (struct sockaddr*)&addr->addr_inet[i],
                                        inmask)) {
                    addr->addr_matched |= MCA_OOB_TCP_ADDR_MATCHED;
                    addr->addr_next = i;
                    goto done;
                }
            }
        }
done:
        ; /* NOP */
    }

    if (addr->addr_inet[addr->addr_next].ss_family == AF_INET) {
        memcpy(retval, &addr->addr_inet[addr->addr_next],
               sizeof(struct sockaddr_in));
    } else {
        memcpy(retval, &addr->addr_inet[addr->addr_next],
               sizeof(struct sockaddr_in6));
    }

    if(++addr->addr_next >= addr->addr_count)
        addr->addr_next = 0;
    return ORTE_SUCCESS;
}
static int mca_btl_sctp_create(int if_index, const char* if_name)
{
    if(mca_btl_sctp_component.sctp_if_11) {

        char param[256];
        struct mca_btl_sctp_module_t* btl = (struct mca_btl_sctp_module_t *)malloc(sizeof(mca_btl_sctp_module_t));
        if(NULL == btl) {
            return OMPI_ERR_OUT_OF_RESOURCE;
        }
        memcpy(btl, &mca_btl_sctp_module, sizeof(mca_btl_sctp_module));
        OBJ_CONSTRUCT(&btl->sctp_endpoints, opal_list_t);
        mca_btl_sctp_component.sctp_btls[mca_btl_sctp_component.sctp_num_btls++] = btl;

        /* initialize the btl */
        btl->sctp_ifindex = if_index;
#if MCA_BTL_SCTP_STATISTICS
        btl->sctp_bytes_recv = 0;
        btl->sctp_bytes_sent = 0;
        btl->sctp_send_handler = 0;
#endif
        opal_ifindextoaddr(if_index, (struct sockaddr*)&btl->sctp_ifaddr, sizeof(btl->sctp_ifaddr));
        /* prepare for bind call later before connect */
        btl->sctp_ifaddr.sin_family = AF_INET;
#ifdef FREEBSD
        btl->sctp_ifaddr.sin_len = sizeof(struct sockaddr);
#endif
        btl->sctp_ifaddr.sin_port = 0;       
        opal_ifindextomask(if_index, (uint32_t *)&btl->sctp_ifmask, sizeof(btl->sctp_ifmask));

        /* allow user to specify interface bandwidth */
        sprintf(param, "bandwidth_%s", if_name);
        btl->super.btl_bandwidth = mca_btl_sctp_param_register_int(param, 0);

        /* allow user to override/specify latency ranking */
        sprintf(param, "latency_%s", if_name);
        btl->super.btl_latency = mca_btl_sctp_param_register_int(param, 0);

#if 0 && OPAL_ENABLE_DEBUG
        BTL_OUTPUT(("interface: %s bandwidth %d latency %d",
                    if_name, btl->super.btl_bandwidth, btl->super.btl_latency));
#endif
        return OMPI_SUCCESS;
    }

    else {
        /* 1 to many */
        struct mca_btl_sctp_module_t* btl;
        char param[256];
        struct sockaddr_in next_ifaddr;
        socklen_t len = sizeof(struct sockaddr_in);
        opal_socklen_t addrlen;
        
        /* check if this is the first time this function is being called */
        if(0 == mca_btl_sctp_component.sctp_num_btls) {

            /* fill in btl struct with first interface's information (arbitary) */

            btl = (struct mca_btl_sctp_module_t *)malloc(sizeof(mca_btl_sctp_module_t));
            if(NULL == btl) {
                return OMPI_ERR_OUT_OF_RESOURCE;
            }
            memcpy(btl, &mca_btl_sctp_module, sizeof(mca_btl_sctp_module));
            OBJ_CONSTRUCT(&btl->sctp_endpoints, opal_list_t);
            mca_btl_sctp_component.sctp_btls[mca_btl_sctp_component.sctp_num_btls++] = btl;

            /* initialize the btl */
            btl->sctp_ifindex = if_index;
#if MCA_BTL_SCTP_STATISTICS
            btl->sctp_bytes_recv = 0;
            btl->sctp_bytes_sent = 0;
            btl->sctp_send_handler = 0;
#endif
            opal_ifindextoaddr(if_index, (struct sockaddr*)&btl->sctp_ifaddr, sizeof(btl->sctp_ifaddr));
            opal_ifindextomask(if_index, (uint32_t *)&btl->sctp_ifmask, sizeof(btl->sctp_ifmask));

            /* allow user to specify interface bandwidth */
            sprintf(param, "bandwidth_%s", if_name);
            btl->super.btl_bandwidth = mca_btl_sctp_param_register_int(param, 0);

            /* allow user to override/specify latency ranking */
            sprintf(param, "latency_%s", if_name);
            btl->super.btl_latency = mca_btl_sctp_param_register_int(param, 0);

#if 0 && OPAL_ENABLE_DEBUG
            BTL_OUTPUT(("interface: %s bandwidth %d latency %d",
                        if_name, btl->super.btl_bandwidth, btl->super.btl_latency));
#endif
            /* call bind to this (initial) addr */
            opal_ifindextoaddr(if_index, (struct sockaddr*)&next_ifaddr, sizeof(next_ifaddr));
            next_ifaddr.sin_family = AF_INET;
#ifdef FREEBSD
            next_ifaddr.sin_len = sizeof(struct sockaddr);
#endif
            next_ifaddr.sin_port = 0;

            if(bind(mca_btl_sctp_component.sctp_listen_sd, (struct sockaddr *) &next_ifaddr, len) < 0) {
                return OMPI_ERR_FATAL;
            }

            /* resolve system assignend port */
            addrlen = sizeof(struct sockaddr_in);
            if(getsockname(mca_btl_sctp_component.sctp_listen_sd, (struct sockaddr*)&next_ifaddr, &addrlen) < 0) {
                BTL_ERROR(("getsockname() failed with errno=%d", opal_socket_errno));
                return OMPI_ERROR;
            }
            /* need to get the port after the first bind call for subsequent
             *  sctp_bindx calls.
             */
            mca_btl_sctp_component.sctp_listen_port = next_ifaddr.sin_port;
            
        } 

        else {
            next_ifaddr.sin_port = htons((unsigned short) mca_btl_sctp_component.sctp_listen_port);

            /* add this addr to bindx */
            opal_ifindextoaddr(if_index, (struct sockaddr*)&next_ifaddr, sizeof(next_ifaddr));
            next_ifaddr.sin_family = AF_INET;
#ifdef FREEBSD
            next_ifaddr.sin_len = sizeof(struct sockaddr);
#endif

            if(sctp_bindx(mca_btl_sctp_component.sctp_listen_sd, (struct sockaddr *) &next_ifaddr,
                          1, SCTP_BINDX_ADD_ADDR) < 0) {
                return OMPI_ERR_FATAL;
            }

        }

        return OMPI_SUCCESS;
    }
}