Whamcloud - gitweb
LU-2934 lnet: Add LNet Router Priority parameter
[fs/lustre-release.git] / lnet / lnet / config.c
index a20044b..deca792 100644 (file)
@@ -26,6 +26,8 @@
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright (c) 2012, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -100,6 +102,9 @@ lnet_ni_free(struct lnet_ni *ni)
        if (ni->ni_tx_queues != NULL)
                cfs_percpt_free(ni->ni_tx_queues);
 
+       if (ni->ni_cpts != NULL)
+               cfs_expr_list_values_free(ni->ni_cpts, ni->ni_ncpts);
+
 #ifndef __KERNEL__
 # ifdef HAVE_LIBPTHREAD
        pthread_mutex_destroy(&ni->ni_lock);
@@ -109,10 +114,11 @@ lnet_ni_free(struct lnet_ni *ni)
 }
 
 lnet_ni_t *
-lnet_ni_alloc(__u32 net, cfs_list_t *nilist)
+lnet_ni_alloc(__u32 net, struct cfs_expr_list *el, cfs_list_t *nilist)
 {
        struct lnet_tx_queue    *tq;
        struct lnet_ni          *ni;
+       int                     rc;
        int                     i;
 
         if (!lnet_net_unique(net, nilist)) {
@@ -129,12 +135,13 @@ lnet_ni_alloc(__u32 net, cfs_list_t *nilist)
         }
 
 #ifdef __KERNEL__
-       cfs_spin_lock_init(&ni->ni_lock);
+       spin_lock_init(&ni->ni_lock);
 #else
 # ifdef HAVE_LIBPTHREAD
        pthread_mutex_init(&ni->ni_lock, NULL);
 # endif
 #endif
+       CFS_INIT_LIST_HEAD(&ni->ni_cptlist);
        ni->ni_refs = cfs_percpt_alloc(lnet_cpt_table(),
                                       sizeof(*ni->ni_refs[0]));
        if (ni->ni_refs == NULL)
@@ -148,11 +155,31 @@ lnet_ni_alloc(__u32 net, cfs_list_t *nilist)
        cfs_percpt_for_each(tq, i, ni->ni_tx_queues)
                CFS_INIT_LIST_HEAD(&tq->tq_delayed);
 
-        /* LND will fill in the address part of the NID */
-        ni->ni_nid = LNET_MKNID(net, 0);
-        ni->ni_last_alive = cfs_time_current();
-        cfs_list_add_tail(&ni->ni_list, nilist);
-        return ni;
+       if (el == NULL) {
+               ni->ni_cpts  = NULL;
+               ni->ni_ncpts = LNET_CPT_NUMBER;
+       } else {
+               rc = cfs_expr_list_values(el, LNET_CPT_NUMBER, &ni->ni_cpts);
+               if (rc <= 0) {
+                       CERROR("Failed to set CPTs for NI %s: %d\n",
+                              libcfs_net2str(net), rc);
+                       goto failed;
+               }
+
+               LASSERT(rc <= LNET_CPT_NUMBER);
+               if (rc == LNET_CPT_NUMBER) {
+                       LIBCFS_FREE(ni->ni_cpts, rc * sizeof(ni->ni_cpts[0]));
+                       ni->ni_cpts = NULL;
+               }
+
+               ni->ni_ncpts = rc;
+       }
+
+       /* LND will fill in the address part of the NID */
+       ni->ni_nid = LNET_MKNID(net, 0);
+       ni->ni_last_alive = cfs_time_current_sec();
+       cfs_list_add_tail(&ni->ni_list, nilist);
+       return ni;
  failed:
        lnet_ni_free(ni);
        return NULL;
@@ -161,12 +188,14 @@ lnet_ni_alloc(__u32 net, cfs_list_t *nilist)
 int
 lnet_parse_networks(cfs_list_t *nilist, char *networks)
 {
-       int        tokensize = strlen(networks) + 1;
-        char      *tokens;
-        char      *str;
-        lnet_ni_t *ni;
-        __u32      net;
-        int        nnets = 0;
+       struct cfs_expr_list *el = NULL;
+       int             tokensize = strlen(networks) + 1;
+       char            *tokens;
+       char            *str;
+       char            *tmp;
+       struct lnet_ni  *ni;
+       __u32           net;
+       int             nnets = 0;
 
        if (strlen(networks) > LNET_SINGLE_TEXTBUF_NOB) {
                /* _WAY_ conservative */
@@ -184,21 +213,48 @@ lnet_parse_networks(cfs_list_t *nilist, char *networks)
         the_lnet.ln_network_tokens = tokens;
         the_lnet.ln_network_tokens_nob = tokensize;
         memcpy (tokens, networks, tokensize);
-        str = tokens;
+       str = tmp = tokens;
 
        /* Add in the loopback network */
-       ni = lnet_ni_alloc(LNET_MKNET(LOLND, 0), nilist);
+       ni = lnet_ni_alloc(LNET_MKNET(LOLND, 0), NULL, nilist);
        if (ni == NULL)
                goto failed;
 
-        while (str != NULL && *str != 0) {
-                char      *comma = strchr(str, ',');
-                char      *bracket = strchr(str, '(');
-                int        niface;
-               char      *iface;
+       while (str != NULL && *str != 0) {
+               char    *comma = strchr(str, ',');
+               char    *bracket = strchr(str, '(');
+               char    *square = strchr(str, '[');
+               char    *iface;
+               int     niface;
+               int     rc;
+
+               /* NB we don't check interface conflicts here; it's the LNDs
+                * responsibility (if it cares at all) */
+
+               if (square != NULL && (comma == NULL || square < comma)) {
+                       /* i.e: o2ib0(ib0)[1,2], number between square
+                        * brackets are CPTs this NI needs to be bond */
+                       if (bracket != NULL && bracket > square) {
+                               tmp = square;
+                               goto failed_syntax;
+                       }
+
+                       tmp = strchr(square, ']');
+                       if (tmp == NULL) {
+                               tmp = square;
+                               goto failed_syntax;
+                       }
+
+                       rc = cfs_expr_list_parse(square, tmp - square + 1,
+                                                0, LNET_CPT_NUMBER - 1, &el);
+                       if (rc != 0) {
+                               tmp = square;
+                               goto failed_syntax;
+                       }
 
-                /* NB we don't check interface conflicts here; it's the LNDs
-                 * responsibility (if it cares at all) */
+                       while (square <= tmp)
+                               *square++ = ' ';
+               }
 
                 if (bracket == NULL ||
                    (comma != NULL && comma < bracket)) {
@@ -210,16 +266,20 @@ lnet_parse_networks(cfs_list_t *nilist, char *networks)
                        net = libcfs_str2net(cfs_trimwhite(str));
 
                        if (net == LNET_NIDNET(LNET_NID_ANY)) {
-                               lnet_syntax("networks", networks,
-                                            (int)(str - tokens), strlen(str));
                                 LCONSOLE_ERROR_MSG(0x113, "Unrecognised network"
                                                    " type\n");
-                                goto failed;
+                               tmp = str;
+                               goto failed_syntax;
                         }
 
                        if (LNET_NETTYP(net) != LOLND && /* LO is implicit */
-                           lnet_ni_alloc(net, nilist) == NULL)
-                                goto failed;
+                           lnet_ni_alloc(net, el, nilist) == NULL)
+                               goto failed;
+
+                       if (el != NULL) {
+                               cfs_expr_list_free(el);
+                               el = NULL;
+                       }
 
                        str = comma;
                        continue;
@@ -228,24 +288,27 @@ lnet_parse_networks(cfs_list_t *nilist, char *networks)
                *bracket = 0;
                net = libcfs_str2net(cfs_trimwhite(str));
                if (net == LNET_NIDNET(LNET_NID_ANY)) {
-                       lnet_syntax("networks", networks,
-                                   (int)(str - tokens), strlen(str));
-                       goto failed;
+                       tmp = str;
+                       goto failed_syntax;
                }
 
-                nnets++;
-               ni = lnet_ni_alloc(net, nilist);
-                if (ni == NULL)
-                        goto failed;
+               nnets++;
+               ni = lnet_ni_alloc(net, el, nilist);
+               if (ni == NULL)
+                       goto failed;
 
-                niface = 0;
+               if (el != NULL) {
+                       cfs_expr_list_free(el);
+                       el = NULL;
+               }
+
+               niface = 0;
                iface = bracket + 1;
 
                bracket = strchr(iface, ')');
                if (bracket == NULL) {
-                        lnet_syntax("networks", networks,
-                                    (int)(iface - tokens), strlen(iface));
-                        goto failed;
+                       tmp = iface;
+                       goto failed_syntax;
                }
 
                *bracket = 0;
@@ -256,10 +319,8 @@ lnet_parse_networks(cfs_list_t *nilist, char *networks)
 
                        iface = cfs_trimwhite(iface);
                        if (*iface == 0) {
-                               lnet_syntax("networks", networks,
-                                           (int)(iface - tokens),
-                                           strlen(iface));
-                                goto failed;
+                               tmp = iface;
+                               goto failed_syntax;
                         }
 
                         if (niface == LNET_MAX_INTERFACES) {
@@ -279,9 +340,8 @@ lnet_parse_networks(cfs_list_t *nilist, char *networks)
                        *comma = 0;
                        str = cfs_trimwhite(str);
                        if (*str != 0) {
-                                lnet_syntax("networks", networks,
-                                            (int)(str - tokens), strlen(str));
-                                goto failed;
+                               tmp = str;
+                               goto failed_syntax;
                         }
                        str = comma + 1;
                        continue;
@@ -289,22 +349,27 @@ lnet_parse_networks(cfs_list_t *nilist, char *networks)
 
                str = cfs_trimwhite(str);
                if (*str != 0) {
-                        lnet_syntax("networks", networks,
-                                    (int)(str - tokens), strlen(str));
-                        goto failed;
-                }
+                       tmp = str;
+                       goto failed_syntax;
+               }
        }
 
-        LASSERT (!cfs_list_empty(nilist));
-        return 0;
+       LASSERT(!cfs_list_empty(nilist));
+       return 0;
 
+ failed_syntax:
+       lnet_syntax("networks", networks, (int)(tmp - tokens), strlen(tmp));
  failed:
-        while (!cfs_list_empty(nilist)) {
-                ni = cfs_list_entry(nilist->next, lnet_ni_t, ni_list);
+       while (!cfs_list_empty(nilist)) {
+               ni = cfs_list_entry(nilist->next, lnet_ni_t, ni_list);
 
                cfs_list_del(&ni->ni_list);
                lnet_ni_free(ni);
        }
+
+       if (el != NULL)
+               cfs_expr_list_free(el);
+
        LIBCFS_FREE(tokens, tokensize);
        the_lnet.ln_network_tokens = NULL;
 
@@ -549,6 +614,37 @@ lnet_parse_hops (char *str, unsigned int *hops)
                 *hops > 0 && *hops < 256);
 }
 
+#define LNET_PRIORITY_SEPARATOR (':')
+
+int
+lnet_parse_priority(char *str, unsigned int *priority, char **token)
+{
+       int   nob;
+       char *sep;
+       int   len;
+
+       sep = strchr(str, LNET_PRIORITY_SEPARATOR);
+       if (sep == NULL) {
+               *priority = 0;
+               return 0;
+       }
+       len = strlen(sep + 1);
+
+       if ((sscanf((sep+1), "%u%n", priority, &nob) < 1) || (len != nob)) {
+               /* Update the caller's token pointer so it treats the found
+                  priority as the token to report in the error message. */
+               *token += sep - str + 1;
+               return -1;
+       }
+
+       CDEBUG(D_NET, "gateway %s, priority %d, nob %d\n", str, *priority, nob);
+
+       /*
+        * Change priority separator to \0 to be able to parse NID
+        */
+       *sep = '\0';
+       return 0;
+}
 
 int
 lnet_parse_route (char *str, int *im_a_router)
@@ -570,6 +666,7 @@ lnet_parse_route (char *str, int *im_a_router)
         int               myrc = -1;
         unsigned int      hops;
         int               got_hops = 0;
+       unsigned int      priority = 0;
 
        CFS_INIT_LIST_HEAD(&gateways);
        CFS_INIT_LIST_HEAD(&nets);
@@ -637,6 +734,11 @@ lnet_parse_route (char *str, int *im_a_router)
                                     LNET_NETTYP(net) == LOLND)
                                        goto token_error;
                        } else {
+                               rc = lnet_parse_priority(ltb->ltb_text,
+                                                        &priority, &token);
+                               if (rc < 0)
+                                       goto token_error;
+
                                nid = libcfs_str2nid(ltb->ltb_text);
                                if (nid == LNET_NID_ANY ||
                                     LNET_NETTYP(LNET_NIDNET(nid)) == LOLND)
@@ -659,14 +761,14 @@ lnet_parse_route (char *str, int *im_a_router)
                cfs_list_for_each (tmp2, &gateways) {
                        ltb = cfs_list_entry(tmp2, lnet_text_buf_t, ltb_list);
                        nid = libcfs_str2nid(ltb->ltb_text);
-                       LASSERT (nid != LNET_NID_ANY);
+                       LASSERT(nid != LNET_NID_ANY);
 
                         if (lnet_islocalnid(nid)) {
                                 *im_a_router = 1;
                                 continue;
                         }
                         
-                        rc = lnet_add_route (net, hops, nid);
+                       rc = lnet_add_route(net, hops, nid, priority);
                         if (rc != 0) {
                                 CERROR("Can't create route "
                                        "to %s via %s\n",