ibacm's default provider has a fixed number (4) of end-point addresses. An endpoint is associated with the node GUID. Hence, if a system is brought up with VFs enabled, the default provider will not be able to handle the end-point addresses. acmp uses the address of a particular addr_info entry in struct acmp_ep as its addr_context, stored ibacm's data structures. However, since these addresses now may change, due to realloc(), we change the addr_context to a small struct containing a pointer to the end-point and an addr_inx. This way, we can safely get the correct address of a realloc'd addr_info entry. Signed-off-by: Håkon Bugge <haakon.bugge@xxxxxxxxxx> --- ibacm/prov/acmp/src/acmp.c | 49 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/ibacm/prov/acmp/src/acmp.c b/ibacm/prov/acmp/src/acmp.c index f63f1dbf..15316573 100644 --- a/ibacm/prov/acmp/src/acmp.c +++ b/ibacm/prov/acmp/src/acmp.c @@ -68,7 +68,6 @@ #define IB_LID_MCAST_START 0xc000 -#define MAX_EP_ADDR 4 #define MAX_EP_MC 2 enum acmp_state { @@ -170,6 +169,11 @@ struct acmp_addr { struct acmp_ep *ep; }; +struct acmp_addr_ctx { + struct acmp_ep *ep; + int addr_inx; +}; + struct acmp_ep { struct acmp_port *port; struct ibv_cq *cq; @@ -190,7 +194,8 @@ struct acmp_ep { struct list_head active_queue; struct list_head wait_queue; enum acmp_state state; - struct acmp_addr addr_info[MAX_EP_ADDR]; + int nmbr_ep_addrs; + struct acmp_addr *addr_info; atomic_t counters[ACM_MAX_COUNTER]; }; @@ -1046,7 +1051,7 @@ acmp_addr_lookup(struct acmp_ep *ep, uint8_t *addr, uint16_t type) { int i; - for (i = 0; i < MAX_EP_ADDR; i++) { + for (i = 0; i < ep->nmbr_ep_addrs; i++) { if (ep->addr_info[i].type != type) continue; @@ -1602,7 +1607,8 @@ acmp_query(void *addr_context, struct acm_msg *msg, uint64_t id) { struct acmp_request *req; struct ib_sa_mad *mad; - struct acmp_addr *address = addr_context; + struct acmp_addr_ctx *addr_ctx = addr_context; + struct acmp_addr *address = addr_ctx->ep->addr_info + addr_ctx->addr_inx; struct acmp_ep *ep = address->ep; uint8_t status; struct acm_sa_mad *sa_mad; @@ -1944,7 +1950,8 @@ put: static int acmp_resolve(void *addr_context, struct acm_msg *msg, uint64_t id) { - struct acmp_addr *address = addr_context; + struct acmp_addr_ctx *addr_ctx = addr_context; + struct acmp_addr *address = addr_ctx->ep->addr_info + addr_ctx->addr_inx; struct acmp_ep *ep = address->ep; if (ep->state != ACMP_READY) { @@ -2365,25 +2372,41 @@ static int acmp_add_addr(const struct acm_address *addr, void *ep_context, { struct acmp_ep *ep = ep_context; struct acmp_dest *dest; + struct acmp_addr_ctx *addr_ctx; int i; acm_log(2, "\n"); - for (i = 0; (i < MAX_EP_ADDR) && + for (i = 0; (i < ep->nmbr_ep_addrs) && (ep->addr_info[i].type != ACM_ADDRESS_INVALID); i++) ; - if (i == MAX_EP_ADDR) { - acm_log(0, "ERROR - no more space for local address\n"); - return -1; + if (i == ep->nmbr_ep_addrs) { + ++ep->nmbr_ep_addrs; + ep->addr_info = realloc(ep->addr_info, ep->nmbr_ep_addrs * sizeof(*ep->addr_info)); + if (!ep->addr_info) { + --ep->nmbr_ep_addrs; + acm_log(0, "ERROR - no more space for local address\n"); + return -1; + } + /* Added memory is not initialized */ + memset(ep->addr_info + i, 0, sizeof(*ep->addr_info)); } ep->addr_info[i].type = addr->type; memcpy(&ep->addr_info[i].info, &addr->info, sizeof(addr->info)); memcpy(&ep->addr_info[i].addr, addr, sizeof(*addr)); ep->addr_info[i].ep = ep; + addr_ctx = malloc(sizeof(*addr_ctx)); + if (!addr_ctx) { + acm_log(0, "ERROR - unable to alloc address context struct\n"); + return -1; + } + addr_ctx->ep = ep; + addr_ctx->addr_inx = i; + if (loopback_prot != ACMP_LOOPBACK_PROT_LOCAL) { - *addr_context = &ep->addr_info[i]; + *addr_context = addr_ctx; return 0; } @@ -2408,7 +2431,7 @@ static int acmp_add_addr(const struct acm_address *addr, void *ep_context, dest->route_timeout = (uint64_t) ~0ULL; dest->state = ACMP_READY; acmp_put_dest(dest); - *addr_context = &ep->addr_info[i]; + *addr_context = addr_ctx; acm_log(1, "added loopback dest %s\n", dest->name); return 0; @@ -2416,7 +2439,8 @@ static int acmp_add_addr(const struct acm_address *addr, void *ep_context, static void acmp_remove_addr(void *addr_context) { - struct acmp_addr *address = addr_context; + struct acmp_addr_ctx *addr_ctx = addr_context; + struct acmp_addr *address = addr_ctx->ep->addr_info + addr_ctx->addr_inx; struct acmp_device *dev; struct acmp_dest *dest; struct acmp_ep *ep; @@ -2455,6 +2479,7 @@ static void acmp_remove_addr(void *addr_context) pthread_mutex_unlock(&acmp_dev_lock); memset(address, 0, sizeof(*address)); + free(addr_ctx); } static struct acmp_port *acmp_get_port(struct acm_endpoint *endpoint) -- 2.14.3