OFED 1.5.2 introduced a kernel patch that disables looping
back multicast messages to the sending QP.  This capability
was enabled by default.  The current ACM address resolution
protocol depends on this feature of multicast.  To handle
the case where multicast loopback has been disabled, add an
option to ACM to resolve loopback addresses using local data
only.  This option is enabled by default.

When loopback resolution is set to 'local', ACM will automatically
insert a loopback destination into each endpoint.  Requests
to resolve a loopback address will find this destination
and use it to respond to client requests.

Signed-off-by: Sean Hefty <sean.he...@intel.com>
---
change from v1:
Used acm configuration option to specify loopback resolution rather
than reading from mlx4 module parameter file.

 acm_opts.cfg |    8 +++++++
 src/acm.c    |   62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/acme.c   |    8 +++++++
 3 files changed, 78 insertions(+), 0 deletions(-)

diff --git a/acm_opts.cfg b/acm_opts.cfg
index 3dbb0c6..65faac9 100644
--- a/acm_opts.cfg
+++ b/acm_opts.cfg
@@ -41,6 +41,14 @@ addr_prot acm
 
 route_prot sa
 
+# loopback_prot:
+# Address and route resolution protocol to resolve local addresses
+# Supported protocols are:
+# none - Use same protocols defined for addr_prot and route_prot
+# local - Resolve information used locally available data
+
+loopback_prot local
+
 # server_port:
 # TCP port number that the server listens on.
 # If this value is changed, then a corresponding change is required for
diff --git a/src/acm.c b/src/acm.c
index 77194ff..099518e 100644
--- a/src/acm.c
+++ b/src/acm.c
@@ -69,6 +69,12 @@ enum acm_route_prot
        ACM_ROUTE_PROT_SA
 };
 
+enum acm_loopback_prot
+{
+       ACM_LOOPBACK_PROT_NONE,
+       ACM_LOOPBACK_PROT_LOCAL
+};
+
 /*
  * Nested locking order: dest -> ep, dest -> port
  */
@@ -204,6 +210,7 @@ static char log_file[128] = "stdout";
 static int log_level = 0;
 static enum acm_addr_prot addr_prot = ACM_ADDR_PROT_ACM;
 static enum acm_route_prot route_prot = ACM_ROUTE_PROT_ACM;
+static enum acm_loopback_prot loopback_prot = ACM_LOOPBACK_PROT_LOCAL;
 static short server_port = 6125;
 static int timeout = 2000;
 static int retries = 15;
@@ -2133,6 +2140,16 @@ static enum acm_route_prot acm_convert_route_prot(char 
*param)
        return route_prot;
 }
 
+static enum acm_loopback_prot acm_convert_loopback_prot(char *param)
+{
+       if (!stricmp("none", param))
+               return ACM_LOOPBACK_PROT_NONE;
+       else if (!stricmp("local", param))
+               return ACM_LOOPBACK_PROT_LOCAL;
+
+       return loopback_prot;
+}
+
 static enum ibv_rate acm_get_rate(uint8_t width, uint8_t speed)
 {
        switch (width) {
@@ -2294,6 +2311,43 @@ static int acm_assign_ep_names(struct acm_ep *ep)
        return !index;
 }
 
+static int acm_init_ep_loopback(struct acm_ep *ep)
+{
+       struct acm_dest *dest;
+       int i;
+
+       acm_log(2, "\n");
+       if (loopback_prot != ACM_LOOPBACK_PROT_LOCAL)
+               return 0;
+
+       for (i = 0; i < MAX_EP_ADDR && ep->addr_type[i]; i++) {
+               dest = acm_acquire_dest(ep, ep->addr_type[i], ep->addr[i].addr);
+               if (!dest) {
+                       acm_format_name(0, log_data, sizeof log_data,
+                                       ep->addr_type[i], ep->addr[i].addr,
+                                       sizeof ep->addr[i].addr);
+                       acm_log(0, "ERROR - unable to create loopback dest 
%s\n", log_data);
+                       return -1;
+               }
+
+               ibv_query_gid(ep->port->dev->verbs, ep->port->port_num,
+                             0, &dest->path.sgid);
+
+               dest->path.dgid = dest->path.sgid;
+               dest->path.dlid = dest->path.slid = htons(ep->port->lid);
+               dest->path.reversible_numpath = IBV_PATH_RECORD_REVERSIBLE;
+               dest->path.pkey = htons(ep->pkey);
+               dest->path.mtu = (uint8_t) ep->port->mtu;
+               dest->path.rate = (uint8_t) ep->port->rate;
+
+               dest->remote_qpn = ep->qp->qp_num;
+               dest->state = ACM_READY;
+               acm_put_dest(dest);
+               acm_log(1, "added loopback dest %s\n", dest->name);
+       }
+       return 0;
+}
+
 static int acm_activate_ep(struct acm_port *port, struct acm_ep *ep, uint16_t 
pkey_index)
 {
        struct ibv_qp_init_attr init_attr;
@@ -2383,6 +2437,11 @@ static int acm_activate_ep(struct acm_port *port, struct 
acm_ep *ep, uint16_t pk
        if (ret)
                goto err2;
 
+       ret = acm_init_ep_loopback(ep);
+       if (ret) {
+               acm_log(0, "ERROR - unable to init loopback\n");
+               goto err2;
+       }
        return 0;
 
 err2:
@@ -2599,6 +2658,8 @@ static void acm_set_options(void)
                        addr_prot = acm_convert_addr_prot(value);
                else if (!stricmp("route_prot", opt))
                        route_prot = acm_convert_route_prot(value);
+               else if (!stricmp("loopback_prot", opt))
+                       loopback_prot = acm_convert_loopback_prot(value);
                else if (!stricmp("server_port", opt))
                        server_port = (short) atoi(value);
                else if (!stricmp("timeout", opt))
@@ -2627,6 +2688,7 @@ static void acm_log_options(void)
        acm_log(0, "log level %d\n", log_level);
        acm_log(0, "address resolution %d\n", addr_prot);
        acm_log(0, "route resolution %d\n", route_prot);
+       acm_log(0, "loopback resolution %d\n", loopback_prot);
        acm_log(0, "server_port %d\n", server_port);
        acm_log(0, "timeout %d ms\n", timeout);
        acm_log(0, "retries %d\n", retries);
diff --git a/src/acme.c b/src/acme.c
index e03679f..b54738e 100644
--- a/src/acme.c
+++ b/src/acme.c
@@ -121,6 +121,14 @@ static void gen_opts_temp(FILE *f)
        fprintf(f, "\n");
        fprintf(f, "route_prot sa\n");
        fprintf(f, "\n");
+       fprintf(f, "# loopback_prot:\n");
+       fprintf(f, "# Address and route resolution protocol to resolve local 
addresses\n");
+       fprintf(f, "# Supported protocols are:\n");
+       fprintf(f, "# none - Use same protocols defined for addr_prot and 
route_prot\n");
+       fprintf(f, "# local - Resolve information used locally available 
data\n");
+       fprintf(f, "\n");
+       fprintf(f, "loopback_prot local\n");
+       fprintf(f, "\n");
        fprintf(f, "# server_port:\n");
        fprintf(f, "# TCP port number that the server listens on.\n");
        fprintf(f, "# If this value is changed, then a corresponding change is 
required for\n");


--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to