static int sock_check_table_in(struct sock_av *_av, struct sockaddr_in *addr, fi_addr_t *fi_addr, int count, uint64_t flags, void *context, int index) { void *new_addr; int i, j, ret = 0; char sa_ip[INET_ADDRSTRLEN]; struct sock_av_addr *av_addr; size_t new_count, table_sz, old_sz; if ((_av->attr.flags & FI_EVENT) && !_av->eq) return -FI_ENOEQ; if (_av->attr.flags & FI_READ) { for (i = 0; i < count; i++) { for (j = 0; j < _av->table_hdr->stored; j++) { if (!sock_av_is_valid_address(&addr[i])) { if (fi_addr) fi_addr[i] = FI_ADDR_NOTAVAIL; sock_av_report_error(_av, context, i, FI_EINVAL); continue; } av_addr = &_av->table[j]; if (memcmp(&av_addr->addr, &addr[i], sizeof(struct sockaddr_in)) == 0) { SOCK_LOG_DBG("Found addr in shared av\n"); if (fi_addr) fi_addr[i] = (fi_addr_t)j; ret++; } } } sock_av_report_success(_av, context, ret, flags); return (_av->attr.flags & FI_EVENT) ? 0 : ret; } for (i = 0, ret = 0; i < count; i++) { if (_av->table_hdr->stored == _av->table_hdr->size) { if (_av->table_hdr->req_sz) { if (fi_addr) fi_addr[i] = FI_ADDR_NOTAVAIL; sock_av_report_error(_av, context, i, FI_ENOSPC); SOCK_LOG_ERROR("Cannot insert to AV table\n"); continue; } else { new_count = _av->table_hdr->size * 2; table_sz = SOCK_AV_TABLE_SZ(new_count, _av->attr.name); old_sz = SOCK_AV_TABLE_SZ(_av->table_hdr->size, _av->attr.name); if (_av->attr.name) { new_addr = sock_mremap(_av->table_hdr, old_sz, table_sz); if (new_addr == MAP_FAILED) { if (fi_addr) fi_addr[i] = FI_ADDR_NOTAVAIL; sock_av_report_error(_av, context, i, FI_ENOMEM); continue; } _av->idx_arr[_av->table_hdr->stored] = _av->table_hdr->stored; } else { new_addr = realloc(_av->table_hdr, table_sz); if (!new_addr) { if (fi_addr) fi_addr[i] = FI_ADDR_NOTAVAIL; sock_av_report_error(_av, context, i, FI_ENOMEM); continue; } } _av->table_hdr = new_addr; _av->table_hdr->size = new_count; sock_update_av_table(_av, new_count); } } if (!sock_av_is_valid_address(&addr[i])) { if (fi_addr) fi_addr[i] = FI_ADDR_NOTAVAIL; sock_av_report_error(_av, context, i, FI_EINVAL); continue; } av_addr = &_av->table[_av->table_hdr->stored]; memcpy(sa_ip, inet_ntoa((&addr[i])->sin_addr), INET_ADDRSTRLEN); SOCK_LOG_DBG("AV-INSERT:dst_addr: family: %d, IP is %s, port: %d\n", ((struct sockaddr_in *)&addr[i])->sin_family, sa_ip, ntohs(((struct sockaddr_in *)&addr[i])->sin_port)); memcpy(&av_addr->addr, &addr[i], sizeof(struct sockaddr_in)); if (fi_addr) fi_addr[i] = (fi_addr_t)_av->table_hdr->stored; av_addr->valid = 1; _av->table_hdr->stored++; ret++; } sock_av_report_success(_av, context, ret, flags); return (_av->attr.flags & FI_EVENT) ? 0 : ret; }
int sock_av_open(struct fid_domain *domain, struct fi_av_attr *attr, struct fid_av **av, void *context) { int ret = 0; struct sock_domain *dom; struct sock_av *_av; size_t table_sz; if (!attr || sock_verify_av_attr(attr)) return -FI_EINVAL; if (attr->type == FI_AV_UNSPEC) attr->type = FI_AV_TABLE; dom = container_of(domain, struct sock_domain, dom_fid); if (dom->attr.av_type != FI_AV_UNSPEC && dom->attr.av_type != attr->type) return -FI_EINVAL; _av = calloc(1, sizeof(*_av)); if (!_av) return -FI_ENOMEM; _av->attr = *attr; _av->attr.count = (attr->count) ? attr->count : sock_av_def_sz; table_sz = SOCK_AV_TABLE_SZ(_av->attr.count, attr->name); if (attr->name) { ret = ofi_shm_map(&_av->shm, attr->name, table_sz, attr->flags & FI_READ, (void**)&_av->table_hdr); if (ret || _av->table_hdr == MAP_FAILED) { SOCK_LOG_ERROR("map failed\n"); ret = -FI_EINVAL; goto err; } _av->idx_arr = (uint64_t *)(_av->table_hdr + 1); _av->attr.map_addr = _av->idx_arr; attr->map_addr = _av->attr.map_addr; SOCK_LOG_DBG("Updating map_addr: %p\n", _av->attr.map_addr); if (attr->flags & FI_READ) { if (_av->table_hdr->size != _av->attr.count) { ret = -FI_EINVAL; goto err2; } } else { _av->table_hdr->size = _av->attr.count; _av->table_hdr->stored = 0; } _av->shared = 1; } else { _av->table_hdr = calloc(1, table_sz); if (!_av->table_hdr) { ret = -FI_ENOMEM; goto err; } _av->table_hdr->size = _av->attr.count; _av->table_hdr->req_sz = attr->count; } sock_update_av_table(_av, _av->attr.count); _av->av_fid.fid.fclass = FI_CLASS_AV; _av->av_fid.fid.context = context; _av->av_fid.fid.ops = &sock_av_fi_ops; switch (attr->type) { case FI_AV_MAP: _av->av_fid.ops = &sock_am_ops; break; case FI_AV_TABLE: _av->av_fid.ops = &sock_at_ops; break; default: ret = -FI_EINVAL; goto err2; } atomic_initialize(&_av->ref, 0); atomic_inc(&dom->ref); _av->domain = dom; switch (dom->info.addr_format) { case FI_SOCKADDR_IN: _av->addrlen = sizeof(struct sockaddr_in); break; default: SOCK_LOG_ERROR("Invalid address format: only IPv4 supported\n"); ret = -FI_EINVAL; goto err2; } _av->rx_ctx_bits = attr->rx_ctx_bits; _av->mask = attr->rx_ctx_bits ? ((uint64_t)1 << (64 - attr->rx_ctx_bits)) - 1 : ~0; *av = &_av->av_fid; return 0; err2: if(attr->name) { ofi_shm_unmap(&_av->shm); } else { if(_av->table_hdr && _av->table_hdr != MAP_FAILED) free(_av->table_hdr); } err: free(_av); return ret; }
int sock_av_open(struct fid_domain *domain, struct fi_av_attr *attr, struct fid_av **av, void *context) { int ret = 0; struct sock_domain *dom; struct sock_av *_av; size_t table_sz, i; int flags = O_RDWR; struct stat mapstat; if (!attr || sock_verify_av_attr(attr)) return -FI_EINVAL; if (attr && attr->type == FI_AV_UNSPEC) attr->type = FI_AV_TABLE; dom = container_of(domain, struct sock_domain, dom_fid); if (dom->attr.av_type != FI_AV_UNSPEC && attr && dom->attr.av_type != attr->type) return -FI_EINVAL; _av = calloc(1, sizeof(*_av)); if (!_av) return -FI_ENOMEM; _av->attr = *attr; _av->attr.count = (attr->count) ? attr->count : sock_av_def_sz; table_sz = SOCK_AV_TABLE_SZ(_av->attr.count, attr->name); if (attr->name) { _av->name = calloc(1, strlen(attr->name) + 1); if (!_av->name) { ret = -FI_ENOMEM; goto err1; } sprintf(_av->name, "/%s", attr->name); if (!(attr->flags & FI_READ)) flags |= O_CREAT; for (i = 0; i < strlen(_av->name); i++) if (_av->name[i] == ' ') _av->name[i] = '_'; SOCK_LOG_DBG("Creating shm segment :%s (size: %lu)\n", _av->name, table_sz); _av->shared_fd = shm_open(_av->name, flags, S_IRUSR | S_IWUSR); if (_av->shared_fd < 0) { SOCK_LOG_ERROR("shm_open failed\n"); ret = -FI_EINVAL; goto err2; } if (fstat(_av->shared_fd, &mapstat)) { SOCK_LOG_ERROR("failed to do fstat: %s\n", strerror(errno)); goto err_shm; } if (mapstat.st_size == 0) { if (ftruncate(_av->shared_fd, table_sz)) { SOCK_LOG_ERROR("ftruncate failed: %s\n", strerror(errno)); goto err_shm; } } else if (mapstat.st_size < table_sz) { SOCK_LOG_ERROR("shm file too small\n"); goto err_shm; } _av->table_hdr = mmap(NULL, table_sz, PROT_READ | PROT_WRITE, MAP_SHARED, _av->shared_fd, 0); _av->idx_arr = (uint64_t *)(_av->table_hdr + 1); _av->attr.map_addr = _av->idx_arr; attr->map_addr = _av->attr.map_addr; SOCK_LOG_DBG("Updating map_addr: %p\n", _av->attr.map_addr); if (attr->flags & FI_READ) { if (_av->table_hdr->size != _av->attr.count) { ret = -FI_EINVAL; goto err2; } } else { _av->table_hdr->size = _av->attr.count; _av->table_hdr->stored = 0; } if (_av->table_hdr == MAP_FAILED) { SOCK_LOG_ERROR("mmap failed\n"); shm_unlink(_av->name); ret = -FI_EINVAL; goto err2; } } else { _av->table_hdr = calloc(1, table_sz); if (!_av->table_hdr) { ret = -FI_ENOMEM; goto err3; } _av->table_hdr->size = _av->attr.count; _av->table_hdr->req_sz = attr->count; } sock_update_av_table(_av, _av->attr.count); _av->av_fid.fid.fclass = FI_CLASS_AV; _av->av_fid.fid.context = context; _av->av_fid.fid.ops = &sock_av_fi_ops; switch (attr->type) { case FI_AV_MAP: _av->av_fid.ops = &sock_am_ops; break; case FI_AV_TABLE: _av->av_fid.ops = &sock_at_ops; break; default: ret = -FI_EINVAL; goto err3; } atomic_initialize(&_av->ref, 0); atomic_inc(&dom->ref); _av->domain = dom; switch (dom->info.addr_format) { case FI_SOCKADDR_IN: _av->addrlen = sizeof(struct sockaddr_in); break; default: SOCK_LOG_ERROR("Invalid address format: only IPv4 supported\n"); ret = -FI_EINVAL; goto err3; } _av->rx_ctx_bits = attr->rx_ctx_bits; _av->mask = attr->rx_ctx_bits ? ((uint64_t)1 << (64 - attr->rx_ctx_bits)) - 1 : ~0; *av = &_av->av_fid; return 0; err_shm: shm_unlink(_av->name); ret = -FI_EINVAL; goto err2; err3: free(_av->table_hdr); err2: free(_av->name); err1: free(_av); return ret; }