/* * allocate a wait queue node, and insert it in the list */ static ibcm_arp_prwqn_t * ibcm_arp_create_prwqn(ibcm_arp_streams_t *ib_s, ibt_ip_addr_t *dst_addr, ibt_ip_addr_t *src_addr) { ibcm_arp_prwqn_t *wqnp; IBTF_DPRINTF_L4(cmlog, "ibcm_arp_create_prwqn(ib_s: 0x%p)", ib_s); if (dst_addr == NULL) { return (NULL); } if ((wqnp = kmem_zalloc(sizeof (ibcm_arp_prwqn_t), KM_NOSLEEP)) == NULL) { return (NULL); } wqnp->dst_addr = *dst_addr; if (src_addr) { wqnp->usrc_addr = *src_addr; } wqnp->ib_str = ib_s; wqnp->ifproto = (dst_addr->family == AF_INET) ? ETHERTYPE_IP : ETHERTYPE_IPV6; ib_s->wqnp = wqnp; IBTF_DPRINTF_L4(cmlog, "ibcm_arp_create_prwqn: Return wqnp: %p", wqnp); return (wqnp); }
ibt_status_t ibcm_arp_get_ibds(ibcm_arp_ibd_insts_t *ibdp, sa_family_t family_loc) { #ifdef DEBUG int i; #endif IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibds(%p)", ibdp); ibcm_arp_get_ibd_insts(ibdp); IBTF_DPRINTF_L3(cmlog, "ibcm_arp_get_ibds: Found %d ibd instances", ibdp->ibcm_arp_ibd_cnt); if (ibdp->ibcm_arp_ibd_cnt == 0) return (IBT_SRC_IP_NOT_FOUND); /* Get the IP addresses of active ports. */ if (!ibcm_arp_get_ibd_ipaddr(ibdp, family_loc)) { IBTF_DPRINTF_L2(cmlog, "ibcm_arp_get_ibds: failed to get " "ibd instance: IBT_SRC_IP_NOT_FOUND"); ibcm_arp_free_ibds(ibdp); return (IBT_SRC_IP_NOT_FOUND); } #ifdef DEBUG for (i = 0; i < ibdp->ibcm_arp_ibd_cnt; i++) { char my_buf[INET6_ADDRSTRLEN]; ibcm_arp_ip_t *aip = &ibdp->ibcm_arp_ip[i]; IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibds: Linkid %d Family %d " "PKey 0x%lX \n HCAGUID 0x%llX SGID %llX:%llX", aip->ip_linkid, aip->ip_inet_family, aip->ip_pkey, aip->ip_hca_guid, aip->ip_port_gid.gid_prefix, aip->ip_port_gid.gid_guid); if (aip->ip_inet_family == AF_INET) { IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibds: IPV4: %s", inet_ntop(AF_INET, &aip->ip_cm_sin.sin_addr, my_buf, sizeof (my_buf))); } else if (aip->ip_inet_family == AF_INET6) { IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibds: IPV6: %s", inet_ntop(AF_INET6, &aip->ip_cm_sin6.sin6_addr, my_buf, sizeof (my_buf))); } else { IBTF_DPRINTF_L2(cmlog, "ibcm_arp_get_ibds: Unknown " "Family %d", aip->ip_inet_family); } } #endif return (IBT_SUCCESS); }
static void ibcm_arp_get_ibd_insts(ibcm_arp_ibd_insts_t *ibds) { ibcm_arp_ip_t *ipp; ib_gid_t port_gid; ibt_part_attr_t *attr_list, *attr; int nparts; if ((ibt_get_all_part_attr(&attr_list, &nparts) != IBT_SUCCESS) || (nparts == 0)) { IBTF_DPRINTF_L2(cmlog, "ibcm_arp_get_ibd_insts: Failed to " "IB Part List - %d", nparts); ibds->ibcm_arp_ibd_alloc = 0; ibds->ibcm_arp_ibd_cnt = 0; ibds->ibcm_arp_ip = NULL; return; } IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibd_insts: Found %d IB Part List", nparts); ibds->ibcm_arp_ibd_alloc = nparts; ibds->ibcm_arp_ibd_cnt = 0; ibds->ibcm_arp_ip = (ibcm_arp_ip_t *)kmem_zalloc( nparts * sizeof (ibcm_arp_ip_t), KM_SLEEP); attr = attr_list; while (nparts--) { if (ibt_get_port_state_byguid(attr->pa_hca_guid, attr->pa_port, &port_gid, NULL) == IBT_SUCCESS) { ipp = &ibds->ibcm_arp_ip[ibds->ibcm_arp_ibd_cnt]; ipp->ip_linkid = attr->pa_plinkid; ipp->ip_pkey = attr->pa_pkey; ipp->ip_hca_guid = attr->pa_hca_guid; ipp->ip_port_gid = port_gid; ibds->ibcm_arp_ibd_cnt++; IBTF_DPRINTF_L4(cmlog, "PartAttr: p-linkid %lX, " "d-linkid %lX, pkey 0x%lX", ipp->ip_linkid, attr->pa_dlinkid, ipp->ip_pkey); IBTF_DPRINTF_L4(cmlog, "hca_guid 0x%llX, " "port_gid %llX \n attr-port_guid %llX", ipp->ip_hca_guid, ipp->ip_port_gid.gid_guid, attr->pa_port_guid); } attr++; } (void) ibt_free_part_attr(attr_list, ibds->ibcm_arp_ibd_alloc); }
static ibcm_arp_ip_t * ibcm_arp_lookup(ibcm_arp_ibd_insts_t *ibds, char *linkname) { datalink_id_t linkid; int i; IBTF_DPRINTF_L4(cmlog, "ibcm_arp_lookup: linkname = %s", linkname); /* * If at first we don't succeed, try again, just in case it is in * hiding. The first call requires the datalink management daemon * (the authorative source of information about name to id mapping) * to be present and answering upcalls, the second does not. */ if (dls_mgmt_get_linkid(linkname, &linkid) != 0) { if (dls_devnet_macname2linkid(linkname, &linkid) != 0) { IBTF_DPRINTF_L2(cmlog, "ibcm_arp_lookup: could not " "get linkid from linkname (%s)", linkname); return (NULL); } } for (i = 0; i < ibds->ibcm_arp_ibd_cnt; i++) { if (ibds->ibcm_arp_ip[i].ip_linkid == linkid) return (&ibds->ibcm_arp_ip[i]); } IBTF_DPRINTF_L2(cmlog, "ibcm_arp_lookup: returning NULL for " "linkname (%s)", linkname); return (NULL); }
/* * delete a wait queue node from the list. * assumes mutex is acquired */ void ibcm_arp_delete_prwqn(ibcm_arp_prwqn_t *wqnp) { ibcm_arp_streams_t *ib_s; IBTF_DPRINTF_L4(cmlog, "ibcm_arp_delete_prwqn(%p)", wqnp); ib_s = wqnp->ib_str; ib_s->wqnp = NULL; kmem_free(wqnp, sizeof (ibcm_arp_prwqn_t)); }
/* * callback for resolver lookups, both for success and failure. * If Address resolution was succesful: return GID info. */ static void ibcm_resolver_ack(ip2mac_t *ip2macp, void *arg) { ibcm_arp_prwqn_t *wqnp = (ibcm_arp_prwqn_t *)arg; ibcm_arp_streams_t *ib_s; uchar_t *cp; int err = 0; IBTF_DPRINTF_L4(cmlog, "ibcm_resolver_ack(%p, %p)", ip2macp, wqnp); ib_s = wqnp->ib_str; mutex_enter(&ib_s->lock); if (ip2macp->ip2mac_err != 0) { wqnp->flags &= ~IBCM_ARP_PR_RESOLVE_PENDING; cv_broadcast(&ib_s->cv); err = EHOSTUNREACH; goto user_callback; } if (!ibcm_check_sockdl(&ip2macp->ip2mac_ha)) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_ack: Error: " "interface %s is not IB\n", wqnp->ifname); err = EHOSTUNREACH; goto user_callback; } cp = (uchar_t *)LLADDR(&ip2macp->ip2mac_ha); bcopy(cp, &wqnp->dst_mac, IPOIB_ADDRL); /* * at this point we have src/dst gid's derived from the mac addresses * now get the hca, port */ bcopy(&wqnp->src_mac.ipoib_gidpref, &wqnp->sgid, sizeof (ib_gid_t)); bcopy(&wqnp->dst_mac.ipoib_gidpref, &wqnp->dgid, sizeof (ib_gid_t)); IBCM_H2N_GID(wqnp->sgid); IBCM_H2N_GID(wqnp->dgid); user_callback: ib_s->status = err; ib_s->done = B_TRUE; /* lock is held by the caller. */ cv_signal(&ib_s->cv); mutex_exit(&ib_s->lock); }
int ibcm_resolver_pr_lookup(ibcm_arp_streams_t *ib_s, ibt_ip_addr_t *dst_addr, ibt_ip_addr_t *src_addr, zoneid_t myzoneid) { ibcm_arp_prwqn_t *wqnp; ire_t *ire = NULL; ipif_t *ipif = NULL; ill_t *ill = NULL; ill_t *hwaddr_ill = NULL; ip_stack_t *ipst; ipaddr_t setsrcv4; in6_addr_t setsrcv6; IBCM_PRINT_IP("ibcm_arp_pr_lookup: SRC", src_addr); IBCM_PRINT_IP("ibcm_arp_pr_lookup: DST", dst_addr); if ((wqnp = ibcm_arp_create_prwqn(ib_s, dst_addr, src_addr)) == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ibcm_arp_create_prwqn failed"); ib_s->status = ENOMEM; return (1); } ipst = netstack_find_by_zoneid(myzoneid)->netstack_ip; if (dst_addr->family == AF_INET) { /* * get an ire for the destination adress. * Note that we can't use MATCH_IRE_ILL since that would * require that the first ill we find have ire_ill set. */ setsrcv4 = INADDR_ANY; ire = ire_route_recursive_v4(dst_addr->un.ip4addr, 0, NULL, myzoneid, NULL, MATCH_IRE_DSTONLY, B_TRUE, 0, ipst, &setsrcv4, NULL, NULL); ASSERT(ire != NULL); if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_route_recursive_v4 failed"); ib_s->status = EFAULT; goto fail; } ill = ire_nexthop_ill(ire); if (ill == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_nexthop_ill failed"); ib_s->status = EFAULT; goto fail; } /* Pick a source address */ if (ip_select_source_v4(ill, setsrcv4, dst_addr->un.ip4addr, INADDR_ANY, myzoneid, ipst, &wqnp->src_addr.un.ip4addr, NULL, NULL) != 0) { ib_s->status = EADDRNOTAVAIL; goto fail; } wqnp->gateway.un.ip4addr = ire->ire_gateway_addr; wqnp->netmask.un.ip4addr = ire->ire_mask; wqnp->src_addr.family = wqnp->gateway.family = wqnp->netmask.family = AF_INET; } else if (dst_addr->family == AF_INET6) { /* * get an ire for the destination adress. * Note that we can't use MATCH_IRE_ILL since that would * require that the first ill we find have ire_ill set. Thus * we compare ire_ill against ipif_ill after the lookup. */ setsrcv6 = ipv6_all_zeros; ire = ire_route_recursive_v6(&dst_addr->un.ip6addr, 0, NULL, myzoneid, NULL, MATCH_IRE_DSTONLY, B_TRUE, 0, ipst, &setsrcv6, NULL, NULL); ASSERT(ire != NULL); if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_route_recursive_v6 failed"); ib_s->status = EFAULT; goto fail; } ill = ire_nexthop_ill(ire); if (ill == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_nexthop_ill failed"); ib_s->status = EFAULT; goto fail; } /* Pick a source address */ if (ip_select_source_v6(ill, &setsrcv6, &dst_addr->un.ip6addr, myzoneid, ipst, B_FALSE, IPV6_PREFER_SRC_DEFAULT, &wqnp->src_addr.un.ip6addr, NULL, NULL) != 0) { ib_s->status = EADDRNOTAVAIL; goto fail; } wqnp->gateway.un.ip6addr = ire->ire_gateway_addr_v6; wqnp->netmask.un.ip6addr = ire->ire_mask_v6; wqnp->src_addr.family = wqnp->gateway.family = wqnp->netmask.family = AF_INET6; } (void) strlcpy(wqnp->ifname, ill->ill_name, sizeof (wqnp->ifname)); /* * For IPMP data addresses, we need to use the hardware address of the * interface bound to the given address. */ if (IS_IPMP(ill)) { if (wqnp->src_addr.family == AF_INET) { ipif = ipif_lookup_addr(wqnp->src_addr.un.ip4addr, ill, myzoneid, ipst); } else { ipif = ipif_lookup_addr_v6(&wqnp->src_addr.un.ip6addr, ill, myzoneid, ipst); } if (ipif == NULL) { ib_s->status = ENETUNREACH; goto fail; } if ((hwaddr_ill = ipmp_ipif_hold_bound_ill(ipif)) == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "no bound ill for IPMP interface %s", ill->ill_name); ib_s->status = EFAULT; goto fail; } } else { hwaddr_ill = ill; ill_refhold(hwaddr_ill); /* for symmetry */ } if ((ib_s->status = ibcm_arp_check_interface(hwaddr_ill)) != 0) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ibcm_arp_check_interface failed"); goto fail; } bcopy(hwaddr_ill->ill_phys_addr, &wqnp->src_mac, hwaddr_ill->ill_phys_addr_length); IBTF_DPRINTF_L4(cmlog, "ibcm_resolver_pr_lookup: outgoing if:%s", wqnp->ifname); /* * at this stage, we have the source address and the IB * interface, now get the destination mac address from * arp or ipv6 drivers */ ib_s->status = ibcm_nce_lookup(wqnp, ill, myzoneid); if (ib_s->status != 0) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ibcm_nce_lookup failed: %d", ib_s->status); goto fail; } ill_refrele(hwaddr_ill); ill_refrele(ill); ire_refrele(ire); if (ipif != NULL) ipif_refrele(ipif); netstack_rele(ipst->ips_netstack); IBTF_DPRINTF_L4(cmlog, "ibcm_resolver_pr_lookup: Return: 0x%p", wqnp); return (0); fail: if (hwaddr_ill != NULL) ill_refrele(hwaddr_ill); if (ill != NULL) ill_refrele(ill); if (ire != NULL) ire_refrele(ire); if (ipif != NULL) ipif_refrele(ipif); ibcm_arp_delete_prwqn(wqnp); netstack_rele(ipst->ips_netstack); return (1); }
int ibcm_resolver_pr_lookup(ibcm_arp_streams_t *ib_s, ibt_ip_addr_t *dst_addr, ibt_ip_addr_t *src_addr) { ibcm_arp_prwqn_t *wqnp; ire_t *ire = NULL; ipif_t *ipif = NULL; ill_t *ill = NULL; ill_t *hwaddr_ill = NULL; ip_stack_t *ipst; int len; ipaddr_t setsrcv4; in6_addr_t setsrcv6; IBCM_PRINT_IP("ibcm_arp_pr_lookup: SRC", src_addr); IBCM_PRINT_IP("ibcm_arp_pr_lookup: DST", dst_addr); if ((wqnp = ibcm_arp_create_prwqn(ib_s, dst_addr, src_addr)) == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ibcm_arp_create_prwqn failed"); ib_s->status = ENOMEM; return (1); } ipst = netstack_find_by_zoneid(GLOBAL_ZONEID)->netstack_ip; if (dst_addr->family == AF_INET) { /* * A local address is always specified, and it is used * to find the zoneid. */ ipif = ipif_lookup_addr(src_addr->un.ip4addr, NULL, ALL_ZONES, ipst); if (ipif == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ipif_lookup_addr failed"); ib_s->status = EFAULT; goto fail; } /* * get an ire for the destination adress. * Note that we can't use MATCH_IRE_ILL since that would * require that the first ill we find have ire_ill set. Thus * we compare ire_ill against ipif_ill after the lookup. */ setsrcv4 = INADDR_ANY; ire = ire_route_recursive_v4(dst_addr->un.ip4addr, 0, NULL, ipif->ipif_zoneid, NULL, MATCH_IRE_DSTONLY, B_TRUE, 0, ipst, &setsrcv4, NULL, NULL); ASSERT(ire != NULL); if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_route_recursive_v4 failed"); ib_s->status = EFAULT; goto fail; } ill = ire_nexthop_ill(ire); if (ill == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_nexthop_ill failed"); ib_s->status = EFAULT; goto fail; } if (ill != ipif->ipif_ill) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "wrong ill"); ib_s->status = EFAULT; goto fail; } wqnp->gateway.un.ip4addr = ire->ire_gateway_addr; wqnp->netmask.un.ip4addr = ire->ire_mask; wqnp->src_addr.un.ip4addr = src_addr->un.ip4addr; wqnp->src_addr.family = wqnp->gateway.family = wqnp->netmask.family = AF_INET; } else if (dst_addr->family == AF_INET6) { /* * A local address is always specified, and it is used * to find the zoneid. * We should really match on scopeid for link locals here. */ ipif = ipif_lookup_addr_v6(&src_addr->un.ip6addr, NULL, ALL_ZONES, ipst); if (ipif == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ipif_lookup_addr_v6 failed"); ib_s->status = EFAULT; goto fail; } /* * get an ire for the destination adress. * Note that we can't use MATCH_IRE_ILL since that would * require that the first ill we find have ire_ill set. Thus * we compare ire_ill against ipif_ill after the lookup. */ setsrcv6 = ipv6_all_zeros; ire = ire_route_recursive_v6(&dst_addr->un.ip6addr, 0, NULL, ipif->ipif_zoneid, NULL, MATCH_IRE_DSTONLY, B_TRUE, 0, ipst, &setsrcv6, NULL, NULL); ASSERT(ire != NULL); if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_route_recursive_v6 failed"); ib_s->status = EFAULT; goto fail; } ill = ire_nexthop_ill(ire); if (ill == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_nexthop_ill failed"); ib_s->status = EFAULT; goto fail; } if (ill != ipif->ipif_ill) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "wrong ill"); ib_s->status = EFAULT; goto fail; } wqnp->gateway.un.ip6addr = ire->ire_gateway_addr_v6; wqnp->netmask.un.ip6addr = ire->ire_mask_v6; wqnp->src_addr.un.ip6addr = src_addr->un.ip6addr; wqnp->src_addr.family = wqnp->gateway.family = wqnp->netmask.family = AF_INET6; } (void) strlcpy(wqnp->ifname, ill->ill_name, sizeof (wqnp->ifname)); /* * For IPMP data addresses, we need to use the hardware address of the * interface bound to the given address. */ if (IS_IPMP(ill)) { if ((hwaddr_ill = ipmp_ipif_hold_bound_ill(ipif)) == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "no bound ill for IPMP interface %s", ill->ill_name); ib_s->status = EFAULT; goto fail; } } else { hwaddr_ill = ill; ill_refhold(hwaddr_ill); /* for symmetry */ } if ((ib_s->status = ibcm_arp_check_interface(hwaddr_ill)) != 0) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ibcm_arp_check_interface failed"); goto fail; } bcopy(hwaddr_ill->ill_phys_addr, &wqnp->src_mac, hwaddr_ill->ill_phys_addr_length); IBTF_DPRINTF_L4(cmlog, "ibcm_resolver_pr_lookup: outgoing if:%s", wqnp->ifname); /* * if the user supplied a address, then verify rts returned * the same address */ if (wqnp->usrc_addr.family) { len = (wqnp->usrc_addr.family == AF_INET) ? IP_ADDR_LEN : sizeof (in6_addr_t); if (bcmp(&wqnp->usrc_addr.un, &wqnp->src_addr.un, len)) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "srcaddr mismatch:%d", ENETUNREACH); goto fail; } } /* * at this stage, we have the source address and the IB * interface, now get the destination mac address from * arp or ipv6 drivers */ ib_s->status = ibcm_nce_lookup(wqnp, ill, getzoneid()); if (ib_s->status != 0) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ibcm_nce_lookup failed: %d", ib_s->status); goto fail; } ill_refrele(hwaddr_ill); ill_refrele(ill); ire_refrele(ire); ipif_refrele(ipif); netstack_rele(ipst->ips_netstack); IBTF_DPRINTF_L4(cmlog, "ibcm_resolver_pr_lookup: Return: 0x%p", wqnp); return (0); fail: if (hwaddr_ill != NULL) ill_refrele(hwaddr_ill); if (ill != NULL) ill_refrele(ill); if (ire != NULL) ire_refrele(ire); if (ipif != NULL) ipif_refrele(ipif); ibcm_arp_delete_prwqn(wqnp); netstack_rele(ipst->ips_netstack); return (1); }
ibt_status_t ibcm_arp_get_ibaddr(zoneid_t myzoneid, ibt_ip_addr_t srcaddr, ibt_ip_addr_t destaddr, ib_gid_t *sgid, ib_gid_t *dgid, ibt_ip_addr_t *saddrp) { ibcm_arp_streams_t *ib_s; ibcm_arp_prwqn_t *wqnp; int ret = 0; int len; IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibaddr(%d, %p, %p, %p, %p, %p)", myzoneid, srcaddr, destaddr, sgid, dgid, saddrp); ib_s = (ibcm_arp_streams_t *)kmem_zalloc(sizeof (ibcm_arp_streams_t), KM_SLEEP); mutex_init(&ib_s->lock, NULL, MUTEX_DEFAULT, NULL); cv_init(&ib_s->cv, NULL, CV_DRIVER, NULL); mutex_enter(&ib_s->lock); ib_s->done = B_FALSE; mutex_exit(&ib_s->lock); ret = ibcm_resolver_pr_lookup(ib_s, &destaddr, &srcaddr, myzoneid); IBTF_DPRINTF_L3(cmlog, "ibcm_arp_get_ibaddr: ibcm_resolver_pr_lookup " "returned: %d", ret); if (ret == 0) { mutex_enter(&ib_s->lock); while (ib_s->done != B_TRUE) cv_wait(&ib_s->cv, &ib_s->lock); mutex_exit(&ib_s->lock); } mutex_enter(&ib_s->lock); wqnp = ib_s->wqnp; if (ib_s->status == 0) { if (sgid) *sgid = wqnp->sgid; if (dgid) *dgid = wqnp->dgid; /* * If the user supplied a address, then verify we got * for the same address. */ if (wqnp->usrc_addr.family && sgid) { len = (wqnp->usrc_addr.family == AF_INET) ? IP_ADDR_LEN : sizeof (in6_addr_t); if (bcmp(&wqnp->usrc_addr.un, &wqnp->src_addr.un, len)) { IBTF_DPRINTF_L3(cmlog, "ibcm_arp_get_ibaddr: " "srcaddr mismatch"); /* Clean-up old data, and reset the done flag */ ibcm_arp_delete_prwqn(wqnp); ib_s->done = B_FALSE; mutex_exit(&ib_s->lock); ret = ibcm_resolver_pr_lookup(ib_s, &srcaddr, &srcaddr, myzoneid); if (ret == 0) { mutex_enter(&ib_s->lock); while (ib_s->done != B_TRUE) cv_wait(&ib_s->cv, &ib_s->lock); mutex_exit(&ib_s->lock); } mutex_enter(&ib_s->lock); wqnp = ib_s->wqnp; if (ib_s->status == 0) { if (sgid) *sgid = wqnp->dgid; if (saddrp) bcopy(&wqnp->src_addr, saddrp, sizeof (ibt_ip_addr_t)); IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibaddr: " "SGID: %llX:%llX DGID: %llX:%llX", sgid->gid_prefix, sgid->gid_guid, dgid->gid_prefix, dgid->gid_guid); ibcm_arp_delete_prwqn(wqnp); } else if (ret == 0) { if (wqnp) kmem_free(wqnp, sizeof (ibcm_arp_prwqn_t)); } goto arp_ibaddr_done; } } if (saddrp) bcopy(&wqnp->src_addr, saddrp, sizeof (ibt_ip_addr_t)); IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibaddr: SGID: %llX:%llX" " DGID: %llX:%llX", sgid->gid_prefix, sgid->gid_guid, dgid->gid_prefix, dgid->gid_guid); ibcm_arp_delete_prwqn(wqnp); } else if (ret == 0) { /* * We come here only when lookup has returned empty (failed) * via callback routine. * i.e. ib_s->status is non-zero, while ret is zero. */ if (wqnp) kmem_free(wqnp, sizeof (ibcm_arp_prwqn_t)); } arp_ibaddr_done: ret = ib_s->status; mutex_exit(&ib_s->lock); arp_ibaddr_error: mutex_destroy(&ib_s->lock); cv_destroy(&ib_s->cv); kmem_free(ib_s, sizeof (ibcm_arp_streams_t)); if (ret) return (IBT_FAILURE); else return (IBT_SUCCESS); }
/* * Fill in `ibds' with IP addresses tied to IFT_IB IP interfaces. Returns * B_TRUE if at least one address was filled in. */ static boolean_t ibcm_arp_get_ibd_ipaddr(ibcm_arp_ibd_insts_t *ibds, sa_family_t family_loc) { int i, nifs, naddr = 0; uint_t bufsize; struct lifconf lifc; struct lifreq *lifrp, lifr_copy; ibcm_arp_ip_t *ipp; lifgroupinfo_t lifgr; int err; char ifname[LIFNAMSIZ + 1]; uint64_t ifflags = 0; zoneid_t ifzoneid; if (ibcm_do_lifconf(&lifc, &bufsize, family_loc) != 0) return (B_FALSE); nifs = lifc.lifc_len / sizeof (struct lifreq); IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibd_ipaddr: Family %d, nifs %d", family_loc, nifs); for (lifrp = lifc.lifc_req, i = 0; i < nifs; i++, lifrp++) { if (lifrp->lifr_type != IFT_IB) continue; IBTF_DPRINTF_L4(cmlog, "\nInterface# : %d", i); IBTF_DPRINTF_L4(cmlog, "lifr_name : %s, lifr_family :%X, " "lifr_type : 0x%lX", lifrp->lifr_name, lifrp->lifr_addr.ss_family, lifrp->lifr_type); (void) strlcpy(ifname, lifrp->lifr_name, LIFNAMSIZ); /* Get ZoneId. */ lifr_copy = *lifrp; ifzoneid = 0; err = ibcm_do_ip_ioctl(SIOCGLIFZONE, sizeof (struct lifreq), &lifr_copy); if (err != 0) { IBTF_DPRINTF_L2(cmlog, "IFZONE ioctl Failed: err = %d", err); } else { IBTF_DPRINTF_L4(cmlog, "lifr_zoneid : 0x%X", lifr_copy.lifr_zoneid); ifzoneid = lifr_copy.lifr_zoneid; } /* Get IfIndex. */ lifr_copy = *lifrp; err = ibcm_do_ip_ioctl(SIOCGLIFINDEX, sizeof (struct lifreq), &lifr_copy); if (err != 0) { IBTF_DPRINTF_L2(cmlog, "IFINDEX ioctl Failed: err = %d", err); } else IBTF_DPRINTF_L4(cmlog, "lifr_index : 0x%X", lifr_copy.lifr_index); /* Get Interface flags. */ lifr_copy = *lifrp; err = ibcm_do_ip_ioctl(SIOCGLIFFLAGS, sizeof (struct lifreq), &lifr_copy); if (err != 0) { IBTF_DPRINTF_L2(cmlog, "IFFLAGS ioctl Failed: err = %d", err); } else { ifflags = lifr_copy.lifr_flags; IBTF_DPRINTF_L4(cmlog, "lifr_flags : 0x%llX", ifflags); } lifr_copy = *lifrp; err = ibcm_do_ip_ioctl(SIOCGLIFGROUPNAME, sizeof (struct lifreq), &lifr_copy); if (err != 0) { IBTF_DPRINTF_L3(cmlog, "IFGroupName ioctl Failed: " "err = %d", err); } if (lifr_copy.lifr_groupname[0] != '\0') { IBTF_DPRINTF_L4(cmlog, "lifr_groupname : %s", lifr_copy.lifr_groupname); (void) strlcpy(lifgr.gi_grname, lifr_copy.lifr_groupname, LIFGRNAMSIZ); err = ibcm_do_ip_ioctl(SIOCGLIFGROUPINFO, sizeof (struct lifgroupinfo), &lifgr); if (err != 0) { IBTF_DPRINTF_L2(cmlog, "IFGroupINFO ioctl " "Failed: err = %d", err); } else { IBTF_DPRINTF_L4(cmlog, "lifgroupinfo details"); IBTF_DPRINTF_L4(cmlog, "grname : %s, grifname :" " %s, m4ifname : %s, m6ifname : %s", lifgr.gi_grname, lifgr.gi_grifname, lifgr.gi_m4ifname, lifgr.gi_m6ifname); IBTF_DPRINTF_L4(cmlog, "gi_bcifname : %s", lifgr.gi_bcifname); IBTF_DPRINTF_L4(cmlog, "gi_v4 %d, gi_v6 %d, " "gi_nv4 %d, gi_nv6 %d, gi_mactype %d", lifgr.gi_v4, lifgr.gi_v6, lifgr.gi_nv4, lifgr.gi_nv6, lifgr.gi_mactype); (void) strlcpy(ifname, lifgr.gi_bcifname, LIFNAMSIZ); } } if ((ipp = ibcm_arp_lookup(ibds, ifname)) == NULL) continue; ipp->ip_zoneid = ifzoneid; /* Copy back the zoneid info */ switch (lifrp->lifr_addr.ss_family) { case AF_INET: ipp->ip_inet_family = AF_INET; bcopy(&lifrp->lifr_addr, &ipp->ip_cm_sin, sizeof (struct sockaddr_in)); naddr++; break; case AF_INET6: ipp->ip_inet_family = AF_INET6; bcopy(&lifrp->lifr_addr, &ipp->ip_cm_sin6, sizeof (struct sockaddr_in6)); naddr++; break; } } kmem_free(lifc.lifc_buf, bufsize); return (naddr > 0); }