ucs_status_t ucp_address_unpack(const void *buffer, uint64_t *remote_uuid_p, char *remote_name, size_t max, unsigned *address_count_p, ucp_address_entry_t **address_list_p) { ucp_address_entry_t *address_list, *address; const uct_device_addr_t *dev_addr; ucp_rsc_index_t dev_index; ucp_rsc_index_t md_index; unsigned address_count; int last_dev, last_tl, ep_addr_present; int empty_dev; uint64_t md_flags; size_t dev_addr_len; size_t iface_addr_len; size_t ep_addr_len; uint8_t md_byte; const void *ptr; const void *aptr; ptr = buffer; *remote_uuid_p = *(uint64_t*)ptr; ptr += sizeof(uint64_t); aptr = ucp_address_unpack_string(ptr, remote_name, max); address_count = 0; /* Count addresses */ ptr = aptr; do { if (*(uint8_t*)ptr == UCP_NULL_RESOURCE) { break; } /* md_index */ empty_dev = (*(uint8_t*)ptr) & UCP_ADDRESS_FLAG_EMPTY; ++ptr; /* device address length */ dev_addr_len = (*(uint8_t*)ptr) & ~UCP_ADDRESS_FLAG_LAST; last_dev = (*(uint8_t*)ptr) & UCP_ADDRESS_FLAG_LAST; ++ptr; ptr += dev_addr_len; last_tl = empty_dev; while (!last_tl) { ptr += sizeof(uint16_t); /* tl_name_csum */ ptr += sizeof(ucp_address_packed_iface_attr_t); /* iface attr */ /* iface and ep address lengths */ iface_addr_len = (*(uint8_t*)ptr) & UCP_ADDRESS_FLAG_LEN_MASK; last_tl = (*(uint8_t*)ptr) & UCP_ADDRESS_FLAG_LAST; ep_addr_present = (*(uint8_t*)ptr) & UCP_ADDRESS_FLAG_EP_ADDR; ptr += 1 + iface_addr_len; if (ep_addr_present) { ep_addr_len = *(uint8_t*)ptr; ptr += 1 + ep_addr_len; } ++address_count; ucs_assert(address_count <= UCP_MAX_RESOURCES); } } while (!last_dev); /* Allocate address list */ address_list = ucs_calloc(address_count, sizeof(*address_list), "ucp_address_list"); if (address_list == NULL) { return UCS_ERR_NO_MEMORY; } /* Unpack addresses */ address = address_list; ptr = aptr; dev_index = 0; do { if (*(uint8_t*)ptr == UCP_NULL_RESOURCE) { break; } /* md_index */ md_byte = (*(uint8_t*)ptr); md_index = md_byte & UCP_ADDRESS_FLAG_MD_MASK; md_flags = (md_byte & UCP_ADDRESS_FLAG_MD_ALLOC) ? UCT_MD_FLAG_ALLOC : 0; md_flags |= (md_byte & UCP_ADDRESS_FLAG_MD_REG) ? UCT_MD_FLAG_REG : 0; empty_dev = md_byte & UCP_ADDRESS_FLAG_EMPTY; ++ptr; /* device address length */ dev_addr_len = (*(uint8_t*)ptr) & ~UCP_ADDRESS_FLAG_LAST; last_dev = (*(uint8_t*)ptr) & UCP_ADDRESS_FLAG_LAST; ++ptr; dev_addr = ptr; ptr += dev_addr_len; last_tl = empty_dev; while (!last_tl) { /* tl name */ address->tl_name_csum = *(uint16_t*)ptr; ptr += sizeof(uint16_t); /* tl_name_csum */ ucp_address_unpack_iface_attr(&address->iface_attr, ptr); ptr += sizeof(ucp_address_packed_iface_attr_t); /* tl address length */ iface_addr_len = (*(uint8_t*)ptr) & UCP_ADDRESS_FLAG_LEN_MASK; last_tl = (*(uint8_t*)ptr) & UCP_ADDRESS_FLAG_LAST; ep_addr_present = (*(uint8_t*)ptr) & UCP_ADDRESS_FLAG_EP_ADDR; ++ptr; address->dev_addr = (dev_addr_len > 0) ? dev_addr : NULL; address->md_index = md_index; address->dev_index = dev_index; address->md_flags = md_flags; address->iface_addr = (iface_addr_len > 0) ? ptr : NULL; ptr += iface_addr_len; if (ep_addr_present) { ep_addr_len = *(uint8_t*)ptr; address->ep_addr = (ep_addr_len > 0) ? ptr + 1 : NULL; ptr += 1 + ep_addr_len; } else { address->ep_addr = NULL; } ucs_trace("unpack addr[%d] : md_flags 0x%"PRIx64" tl_flags 0x%"PRIx64" bw %e ovh %e " "lat_ovh %e dev_priority %d", (int)(address - address_list), address->md_flags, address->iface_attr.cap_flags, address->iface_attr.bandwidth, address->iface_attr.overhead, address->iface_attr.lat_ovh, address->iface_attr.priority); ++address; } ++dev_index; } while (!last_dev); *address_count_p = address_count; *address_list_p = address_list; return UCS_OK; }
ucs_status_t ucp_address_unpack(const void *buffer, uint64_t *remote_uuid_p, char *remote_name, size_t max, unsigned *address_count_p, ucp_address_entry_t **address_list_p) { ucp_address_entry_t *address_list, *address; const uct_device_addr_t *dev_addr; ucp_rsc_index_t pd_index; unsigned address_count; int last_dev, last_tl; int empty_dev; size_t dev_addr_len; size_t tl_addr_len; const void *ptr; const void *aptr; ptr = buffer; *remote_uuid_p = *(uint64_t*)ptr; ptr += sizeof(uint64_t); aptr = ucp_address_unpack_string(ptr, remote_name, max); address_count = 0; /* Count addresses */ ptr = aptr; do { if (*(uint8_t*)ptr == UCP_NULL_RESOURCE) { break; } /* pd_index */ pd_index = (*(uint8_t*)ptr) & ~UCP_ADDRESS_FLAG_EMPTY; empty_dev = (*(uint8_t*)ptr) & UCP_ADDRESS_FLAG_EMPTY; ++ptr; /* device address length */ dev_addr_len = (*(uint8_t*)ptr) & ~UCP_ADDRESS_FLAG_LAST; last_dev = (*(uint8_t*)ptr) & UCP_ADDRESS_FLAG_LAST; ++ptr; ptr += dev_addr_len; last_tl = empty_dev; while (!last_tl) { ptr = ucp_address_skip_string(ptr); /* tl_name */ /* tl address length */ tl_addr_len = (*(uint8_t*)ptr) & ~UCP_ADDRESS_FLAG_LAST; last_tl = (*(uint8_t*)ptr) & UCP_ADDRESS_FLAG_LAST; ++ptr; ++address_count; ucs_assert(address_count <= UCP_MAX_RESOURCES); ptr += tl_addr_len; } } while (!last_dev); /* Allocate address list */ address_list = ucs_calloc(address_count, sizeof(*address_list), "ucp_address_list"); if (address_list == NULL) { return UCS_ERR_NO_MEMORY; } /* Unpack addresses */ address = address_list; ptr = aptr; do { if (*(uint8_t*)ptr == UCP_NULL_RESOURCE) { break; } /* pd_index */ pd_index = (*(uint8_t*)ptr) & ~UCP_ADDRESS_FLAG_EMPTY; empty_dev = (*(uint8_t*)ptr) & UCP_ADDRESS_FLAG_EMPTY; ++ptr; /* device address length */ dev_addr_len = (*(uint8_t*)ptr) & ~UCP_ADDRESS_FLAG_LAST; last_dev = (*(uint8_t*)ptr) & UCP_ADDRESS_FLAG_LAST; ++ptr; dev_addr = ptr; ptr += dev_addr_len; last_tl = empty_dev; while (!last_tl) { /* tl name */ ptr = ucp_address_unpack_string(ptr, address->tl_name, UCT_TL_NAME_MAX); /* tl address length */ tl_addr_len = (*(uint8_t*)ptr) & ~UCP_ADDRESS_FLAG_LAST; last_tl = (*(uint8_t*)ptr) & UCP_ADDRESS_FLAG_LAST; ++ptr; address->dev_addr = dev_addr; address->dev_addr_len = dev_addr_len; address->pd_index = pd_index; address->tl_addr = ptr; address->tl_addr_len = tl_addr_len; ++address; ptr += tl_addr_len; } } while (!last_dev); *address_count_p = address_count; *address_list_p = address_list; return UCS_OK; }