Whamcloud - gitweb
* placeholder (digging out IP interface info)
authoreeb <eeb>
Fri, 6 May 2005 14:25:14 +0000 (14:25 +0000)
committereeb <eeb>
Fri, 6 May 2005 14:25:14 +0000 (14:25 +0000)
lnet/include/lnet/lib-types.h
lnet/klnds/socklnd/socklnd.c
lnet/klnds/socklnd/socklnd.h
lnet/klnds/socklnd/socklnd_cb.c
lnet/klnds/socklnd/socklnd_lib-linux.c
lnet/lnet/api-ni.c
lnet/lnet/config.c

index a6e9ca7..273ffb6 100644 (file)
@@ -313,7 +313,7 @@ typedef struct ptl_nal
         
 } ptl_nal_t;
 
-#define PTL_MAX_INTERFACES   8
+#define PTL_MAX_INTERFACES   16
 
 typedef struct ptl_ni {
         struct list_head  ni_list;              /* chain on apini_nis */
@@ -377,6 +377,9 @@ typedef struct
         struct list_head *apini_lh_hash_table;  /* all extant lib handles, this interface */
         __u64             apini_next_object_cookie; /* cookie generator */
         __u64             apini_interface_cookie; /* uniquely identifies this ni in this epoch */
+
+        char             *apini_network_tokens; /* space for network names */
+        int               apini_network_tokens_nob;
         
         struct list_head  apini_test_peers;
         
index 46f31d9..d6f6180 100644 (file)
@@ -40,25 +40,6 @@ ptl_nal_t ksocknal_nal = {
 
 ksock_nal_data_t        ksocknal_data;
 
-int
-ksocknal_set_mynid(ptl_nid_t nid)
-{
-        ptl_ni_t   *ni = ksocknal_data.ksnd_ni;
-
-        /* FIXME: we have to do this because we call lib_init() at module
-         * insertion time, which is before we have 'mynid' available.  lib_init
-         * sets the NAL's nid, which it uses to tell other nodes where packets
-         * are coming from.  This is not a very graceful solution to this
-         * problem. */
-
-        CDEBUG(D_IOCTL, "setting mynid to %s (old nid=%s)\n",
-               libcfs_nid2str(nid), libcfs_nid2str(ni->ni_nid));
-
-        LASSERT (PTL_NIDNET(nid) == PTL_NIDNET(ni->ni_nid));
-        ni->ni_nid = nid;
-        return (0);
-}
-
 ksock_interface_t *
 ksocknal_ip2iface(__u32 ip)
 {
@@ -66,7 +47,7 @@ ksocknal_ip2iface(__u32 ip)
         ksock_interface_t *iface;
 
         for (i = 0; i < ksocknal_data.ksnd_ninterfaces; i++) {
-                LASSERT(i < SOCKNAL_MAX_INTERFACES);
+                LASSERT(i < PTL_MAX_INTERFACES);
                 iface = &ksocknal_data.ksnd_interfaces[i];
 
                 if (iface->ksni_ipaddr == ip)
@@ -201,7 +182,7 @@ ksocknal_unlink_peer_locked (ksock_peer_t *peer)
         __u32              ip;
 
         for (i = 0; i < peer->ksnp_n_passive_ips; i++) {
-                LASSERT (i < SOCKNAL_MAX_INTERFACES);
+                LASSERT (i < PTL_MAX_INTERFACES);
                 ip = peer->ksnp_passive_ips[i];
 
                 ksocknal_ip2iface(ip)->ksni_npeers--;
@@ -641,7 +622,7 @@ ksocknal_local_ipvec (__u32 *ipaddrs)
 
         nip = ksocknal_data.ksnd_ninterfaces;
         for (i = 0; i < nip; i++) {
-                LASSERT (i < SOCKNAL_MAX_INTERFACES);
+                LASSERT (i < PTL_MAX_INTERFACES);
 
                 ipaddrs[i] = ksocknal_data.ksnd_interfaces[i].ksni_ipaddr;
                 LASSERT (ipaddrs[i] != 0);
@@ -710,8 +691,8 @@ ksocknal_select_ips(ksock_peer_t *peer, __u32 *peerips, int n_peerips)
 
         write_lock_irqsave(global_lock, flags);
 
-        LASSERT (n_peerips <= SOCKNAL_MAX_INTERFACES);
-        LASSERT (ksocknal_data.ksnd_ninterfaces <= SOCKNAL_MAX_INTERFACES);
+        LASSERT (n_peerips <= PTL_MAX_INTERFACES);
+        LASSERT (ksocknal_data.ksnd_ninterfaces <= PTL_MAX_INTERFACES);
 
         n_ips = MIN(n_peerips, ksocknal_data.ksnd_ninterfaces);
 
@@ -810,7 +791,7 @@ ksocknal_create_routes(ksock_peer_t *peer, int port,
 
         write_lock_irqsave(global_lock, flags);
 
-        LASSERT (npeer_ipaddrs <= SOCKNAL_MAX_INTERFACES);
+        LASSERT (npeer_ipaddrs <= PTL_MAX_INTERFACES);
 
         for (i = 0; i < npeer_ipaddrs; i++) {
                 if (newroute != NULL) {
@@ -842,7 +823,7 @@ ksocknal_create_routes(ksock_peer_t *peer, int port,
                 best_nroutes = 0;
                 best_netmatch = 0;
 
-                LASSERT (ksocknal_data.ksnd_ninterfaces <= SOCKNAL_MAX_INTERFACES);
+                LASSERT (ksocknal_data.ksnd_ninterfaces <= PTL_MAX_INTERFACES);
 
                 /* Select interface to connect from */
                 for (j = 0; j < ksocknal_data.ksnd_ninterfaces; j++) {
@@ -993,7 +974,7 @@ ksocknal_create_conn (ksock_route_t *route, struct socket *sock, int type)
 {
         int                passive = (type == SOCKNAL_CONN_NONE);
         rwlock_t          *global_lock = &ksocknal_data.ksnd_global_lock;
-        __u32              ipaddrs[SOCKNAL_MAX_INTERFACES];
+        __u32              ipaddrs[PTL_MAX_INTERFACES];
         int                nipaddrs;
         ptl_nid_t          nid;
         struct list_head  *tmp;
@@ -1249,7 +1230,6 @@ ksocknal_close_conn_locked (ksock_conn_t *conn, int error)
         LASSERT (peer->ksnp_error == 0);
         LASSERT (!conn->ksnc_closing);
         conn->ksnc_closing = 1;
-        atomic_inc (&ksocknal_data.ksnd_nclosing_conns);
 
         /* ksnd_deathrow_conns takes over peer's ref */
         list_del (&conn->ksnc_list);
@@ -1424,7 +1404,6 @@ ksocknal_destroy_conn (ksock_conn_t *conn)
         ksocknal_peer_decref(conn->ksnc_peer);
 
         PORTAL_FREE (conn, sizeof (*conn));
-        atomic_dec (&ksocknal_data.ksnd_nclosing_conns);
 }
 
 int
@@ -1659,7 +1638,7 @@ ksocknal_add_interface(__u32 ipaddress, __u32 netmask)
         if (iface != NULL) {
                 /* silently ignore dups */
                 rc = 0;
-        } else if (ksocknal_data.ksnd_ninterfaces == SOCKNAL_MAX_INTERFACES) {
+        } else if (ksocknal_data.ksnd_ninterfaces == PTL_MAX_INTERFACES) {
                 rc = -ENOSPC;
         } else {
                 iface = &ksocknal_data.ksnd_interfaces[ksocknal_data.ksnd_ninterfaces++];
@@ -1807,17 +1786,16 @@ ksocknal_ctl(ptl_ni_t *ni, unsigned int cmd, void *arg)
                 }
 
                 read_unlock (&ksocknal_data.ksnd_global_lock);
-                break;
-        }
-        case IOC_PORTAL_ADD_INTERFACE: {
-                rc = ksocknal_add_interface(data->ioc_u32[0], /* IP address */
-                                            data->ioc_u32[1]); /* net mask */
-                break;
-        }
-        case IOC_PORTAL_DEL_INTERFACE: {
-                rc = ksocknal_del_interface(data->ioc_u32[0]); /* IP address */
-                break;
+                return rc;
         }
+
+        case IOC_PORTAL_ADD_INTERFACE:
+                return ksocknal_add_interface(data->ioc_u32[0], /* IP address */
+                                              data->ioc_u32[1]); /* net mask */
+
+        case IOC_PORTAL_DEL_INTERFACE:
+                return ksocknal_del_interface(data->ioc_u32[0]); /* IP address */
+
         case IOC_PORTAL_GET_PEER: {
                 ptl_nid_t    nid = 0;
                 __u32        myip = 0;
@@ -1835,65 +1813,65 @@ ksocknal_ctl(ptl_ni_t *ni, unsigned int cmd, void *arg)
                 data->ioc_u32[1] = port;
                 data->ioc_u32[2] = myip;
                 data->ioc_u32[3] = conn_count;
-                break;
-        }
-        case IOC_PORTAL_ADD_PEER: {
-                rc = ksocknal_add_peer (data->ioc_nid,
-                                        data->ioc_u32[0], /* IP */
-                                        data->ioc_u32[1]); /* port */
-                break;
-        }
-        case IOC_PORTAL_DEL_PEER: {
-                rc = ksocknal_del_peer (data->ioc_nid,
-                                        data->ioc_u32[0]); /* IP */
-                break;
+                return 0;
         }
+
+        case IOC_PORTAL_ADD_PEER:
+                return ksocknal_add_peer (data->ioc_nid,
+                                          data->ioc_u32[0], /* IP */
+                                          data->ioc_u32[1]); /* port */
+
+        case IOC_PORTAL_DEL_PEER:
+                return ksocknal_del_peer (data->ioc_nid,
+                                          data->ioc_u32[0]); /* IP */
+
         case IOC_PORTAL_GET_CONN: {
+                int           txmem;
+                int           rxmem;
+                int           nagle;
                 ksock_conn_t *conn = ksocknal_get_conn_by_idx (data->ioc_count);
 
                 if (conn == NULL)
-                        rc = -ENOENT;
-                else {
-                        int   txmem;
-                        int   rxmem;
-                        int   nagle;
+                        return -ENOENT;
+
+                ksocknal_lib_get_conn_tunables(conn, &txmem, &rxmem, &nagle);
+
+                data->ioc_count  = txmem;
+                data->ioc_nid    = conn->ksnc_peer->ksnp_nid;
+                data->ioc_flags  = nagle;
+                data->ioc_u32[0] = conn->ksnc_ipaddr;
+                data->ioc_u32[1] = conn->ksnc_port;
+                data->ioc_u32[2] = conn->ksnc_myipaddr;
+                data->ioc_u32[3] = conn->ksnc_type;
+                data->ioc_u32[4] = conn->ksnc_scheduler -
+                                   ksocknal_data.ksnd_schedulers;
+                data->ioc_u32[5] = rxmem;
+                ksocknal_conn_decref(conn);
+                return 0;
+        }
 
-                        ksocknal_lib_get_conn_tunables(conn, &txmem, &rxmem, &nagle);
+        case IOC_PORTAL_CLOSE_CONNECTION:
+                return ksocknal_close_matching_conns (data->ioc_nid,
+                                                      data->ioc_u32[0]);
+
+        case IOC_PORTAL_REGISTER_MYNID:
+               if (data->ioc_nid == ni->ni_nid)
+                       return 0;
+
+               LASSERT (PTL_NIDNET(data->ioc_nid) == PTL_NIDNET(ni->ni_nid));
+
+               CERROR("obsolete IOC_PORTAL_REGISTER_MYNID for %s(%s)\n",
+                      libcfs_nid2str(data->ioc_nid),
+                      libcfs_nid2str(ni->ni_nid));
+               return 0;
+
+        case IOC_PORTAL_PUSH_CONNECTION:
+                return ksocknal_push (data->ioc_nid);
 
-                        rc = 0;
-                        data->ioc_count  = txmem;
-                        data->ioc_nid    = conn->ksnc_peer->ksnp_nid;
-                        data->ioc_flags  = nagle;
-                        data->ioc_u32[0] = conn->ksnc_ipaddr;
-                        data->ioc_u32[1] = conn->ksnc_port;
-                        data->ioc_u32[2] = conn->ksnc_myipaddr;
-                        data->ioc_u32[3] = conn->ksnc_type;
-                        data->ioc_u32[4] = conn->ksnc_scheduler -
-                                            ksocknal_data.ksnd_schedulers;
-                        data->ioc_u32[5] = rxmem;
-                        ksocknal_conn_decref(conn);
-                }
-                break;
-        }
-        case IOC_PORTAL_CLOSE_CONNECTION: {
-                rc = ksocknal_close_matching_conns (data->ioc_nid,
-                                                    data->ioc_u32[0]);
-                break;
-        }
-        case IOC_PORTAL_REGISTER_MYNID: {
-                rc = ksocknal_set_mynid (data->ioc_nid);
-                break;
-        }
-        case IOC_PORTAL_PUSH_CONNECTION: {
-                rc = ksocknal_push (data->ioc_nid);
-                break;
-        }
         default:
-                rc = -EINVAL;
-                break;
+                return -EINVAL;
         }
-
-        return rc;
+        /* not reached */
 }
 
 void
@@ -2071,11 +2049,6 @@ ksocknal_startup (ptl_ni_t *ni)
                 return PTL_FAIL;
         }
 
-        if (ni->ni_interfaces[0] != NULL) {
-                CERROR("Explicit interface config not supported\n");
-                return PTL_FAIL;
-        }
-        
         memset (&ksocknal_data, 0, sizeof (ksocknal_data)); /* zero pointers */
 
         ksocknal_data.ksnd_ni = ni;             /* temp hack */
@@ -2087,7 +2060,7 @@ ksocknal_startup (ptl_ni_t *ni)
         PORTAL_ALLOC (ksocknal_data.ksnd_peers,
                       sizeof (struct list_head) * ksocknal_data.ksnd_peer_hash_size);
         if (ksocknal_data.ksnd_peers == NULL)
-                return (-ENOMEM);
+                return PTL_FAIL;
 
         for (i = 0; i < ksocknal_data.ksnd_peer_hash_size; i++)
                 CFS_INIT_LIST_HEAD(&ksocknal_data.ksnd_peers[i]);
@@ -2127,10 +2100,8 @@ ksocknal_startup (ptl_ni_t *ni)
         ksocknal_data.ksnd_nschedulers = ksocknal_nsched();
         PORTAL_ALLOC(ksocknal_data.ksnd_schedulers,
                      sizeof(ksock_sched_t) * ksocknal_data.ksnd_nschedulers);
-        if (ksocknal_data.ksnd_schedulers == NULL) {
-                ksocknal_shutdown (ni);
-                return (-ENOMEM);
-        }
+        if (ksocknal_data.ksnd_schedulers == NULL)
+                goto failed;
 
         for (i = 0; i < ksocknal_data.ksnd_nschedulers; i++) {
                 ksock_sched_t *kss = &ksocknal_data.ksnd_schedulers[i];
@@ -2150,8 +2121,7 @@ ksocknal_startup (ptl_ni_t *ni)
                 if (rc != 0) {
                         CERROR("Can't spawn socknal scheduler[%d]: %d\n",
                                i, rc);
-                        ksocknal_shutdown (ni);
-                        return (rc);
+                        goto failed;
                 }
         }
 
@@ -2159,16 +2129,14 @@ ksocknal_startup (ptl_ni_t *ni)
                 rc = ksocknal_thread_start (ksocknal_connd, (void *)((long)i));
                 if (rc != 0) {
                         CERROR("Can't spawn socknal connd: %d\n", rc);
-                        ksocknal_shutdown (ni);
-                        return (rc);
+                        goto failed;
                 }
         }
 
         rc = ksocknal_thread_start (ksocknal_reaper, NULL);
         if (rc != 0) {
                 CERROR ("Can't spawn socknal reaper: %d\n", rc);
-                ksocknal_shutdown (ni);
-                return (rc);
+                goto failed;
         }
 
         if (kpr_forwarding()) {
@@ -2187,20 +2155,16 @@ ksocknal_startup (ptl_ni_t *ni)
 
                         PORTAL_ALLOC(fmb, offsetof(ksock_fmb_t,
                                                    fmb_kiov[pool->fmp_buff_pages]));
-                        if (fmb == NULL) {
-                                ksocknal_shutdown(ni);
-                                return (-ENOMEM);
-                        }
+                        if (fmb == NULL)
+                                goto failed;
 
                         fmb->fmb_pool = pool;
 
                         for (j = 0; j < pool->fmp_buff_pages; j++) {
                                 fmb->fmb_kiov[j].kiov_page = cfs_alloc_page(CFS_ALLOC_STD);
 
-                                if (fmb->fmb_kiov[j].kiov_page == NULL) {
-                                        ksocknal_shutdown (ni);
-                                        return (-ENOMEM);
-                                }
+                                if (fmb->fmb_kiov[j].kiov_page == NULL)
+                                        goto failed;
 
                                 LASSERT(cfs_page_address(fmb->fmb_kiov[j].kiov_page) != NULL);
                         }
@@ -2212,10 +2176,35 @@ ksocknal_startup (ptl_ni_t *ni)
         rc = ksocknal_start_listener();
         if (rc != 0) {
                 CERROR("Can't start listener: %d\n", rc);
-                ksocknal_shutdown(ni);
-                return rc;
+                goto failed;
         }
 
+        if (ni->ni_interfaces[0] == NULL) {
+                rc = ksocknal_lib_enumerate_ifs(ksocknal_data.ksnd_interfaces,
+                                                PTL_MAX_INTERFACES);
+                if (rc != 0)
+                        goto failed;
+
+                if (rc == 0) {
+                        CERROR("Can't find any interfaces\n");
+                        goto failed;
+                }
+        } else {
+                for (i = 0; i < PTL_MAX_INTERFACES; i++) {
+                        if (ni->ni_interfaces[i] == NULL)
+                                break;
+
+                        rc = ksocknal_lib_init_if(&ksocknal_data.ksnd_interfaces[i],
+                                                  ni->ni_interfaces[i]);
+                        if (rc != 0)
+                                goto failed;
+                }
+        }
+
+        ni->ni_nid = PTL_MKNID(PTL_NIDNET(ni->ni_nid),
+                               ksocknal_data.ksnd_interfaces[0].ksni_ipaddr);
+        CDEBUG(D_WARNING, "Set NID to %s\n", libcfs_nid2str(ni->ni_nid));
+        
         /* flag everything initialised */
         ksocknal_data.ksnd_init = SOCKNAL_INIT_ALL;
 
@@ -2223,7 +2212,11 @@ ksocknal_startup (ptl_ni_t *ni)
                "(initial mem %d, incarnation "LPD64")\n",
                pkmem, ksocknal_data.ksnd_incarnation);
         
-        return (0);
+        return PTL_OK;
+
+ failed:
+        ksocknal_shutdown(ni);
+        return PTL_FAIL;
 }
 
 void __exit
index ee7bba4..af55041 100644 (file)
@@ -76,8 +76,6 @@
 #define SOCKNAL_RESCHED         100             /* # scheduler loops before reschedule */
 #define SOCKNAL_ENOMEM_RETRY    CFS_MIN_DELAY   /* jiffies between retries */
 
-#define SOCKNAL_MAX_INTERFACES  16              /* Largest number of interfaces we bind */
-
 #define SOCKNAL_ROUND_ROBIN     0               /* round robin / load balance */
 
 #define SOCKNAL_SINGLE_FRAG_TX      0           /* disable multi-fragment sends */
@@ -120,12 +118,13 @@ typedef struct
         int               ksni_sched:6;         /* which scheduler (assumes < 64) */
 } ksock_irqinfo_t;
 
-typedef struct
+typedef struct                                  /* in-use interface */
 {
         __u32             ksni_ipaddr;          /* interface's IP address */
         __u32             ksni_netmask;         /* interface's network mask */
         int               ksni_nroutes;         /* # routes using (active) */
         int               ksni_npeers;          /* # peers using (passive) */
+        char              ksni_name[16];        /* interface name */
 } ksock_interface_t;
 
 typedef struct
@@ -205,7 +204,7 @@ typedef struct
         ptl_ni_t         *ksnd_ni;              /* NI instance (tmp hack) */
 
         int               ksnd_ninterfaces;
-        ksock_interface_t ksnd_interfaces[SOCKNAL_MAX_INTERFACES]; /* published interfaces */
+        ksock_interface_t ksnd_interfaces[PTL_MAX_INTERFACES]; /* active interfaces */
 } ksock_nal_data_t;
 
 #define SOCKNAL_INIT_NOTHING    0
@@ -382,7 +381,7 @@ typedef struct ksock_peer
         struct list_head    ksnp_tx_queue;      /* waiting packets */
         cfs_time_t          ksnp_last_alive;    /* when (in jiffies) I was last alive */
         int                 ksnp_n_passive_ips; /* # of... */
-        __u32               ksnp_passive_ips[SOCKNAL_MAX_INTERFACES]; /* preferred local interfaces */
+        __u32               ksnp_passive_ips[PTL_MAX_INTERFACES]; /* preferred local interfaces */
 } ksock_peer_t;
 
 typedef struct ksock_connreq
@@ -561,3 +560,7 @@ extern void ksocknal_lib_abort_accept(struct socket *sock);
 
 extern int ksocknal_lib_tunables_init(void);
 extern void ksocknal_lib_tunables_fini(void);
+
+extern int ksocknal_lib_init_if (ksock_interface_t *iface, char *name);
+extern int ksocknal_lib_enumerate_ifs (ksock_interface_t *ifs, int nifs);
+
index 8beaa7c..7a1be2b 100644 (file)
@@ -1698,7 +1698,7 @@ ksocknal_send_hello (ksock_conn_t *conn, __u32 *ipaddrs, int nipaddrs)
         int                 rc;
 
         LASSERT (conn->ksnc_type != SOCKNAL_CONN_NONE);
-        LASSERT (nipaddrs <= SOCKNAL_MAX_INTERFACES);
+        LASSERT (nipaddrs <= PTL_MAX_INTERFACES);
 
         /* No need for getconnsock/putconnsock */
         LASSERT (!conn->ksnc_closing);
@@ -1867,7 +1867,7 @@ ksocknal_recv_hello (ksock_conn_t *conn, ptl_nid_t *nid,
 
         nips = __le32_to_cpu (hdr.payload_length) / sizeof (__u32);
 
-        if (nips > SOCKNAL_MAX_INTERFACES ||
+        if (nips > PTL_MAX_INTERFACES ||
             nips * sizeof(__u32) != __le32_to_cpu (hdr.payload_length)) {
                 CERROR("Bad payload length %d from %s ip %u.%u.%u.%u\n",
                        __le32_to_cpu (hdr.payload_length),
index 14a3427..ff540bd 100644 (file)
@@ -948,6 +948,189 @@ ksocknal_lib_connect_sock(struct socket **sockp, int *fatal,
         return rc;
 }
 
+int
+ksocknal_lib_getifaddr(struct socket *sock, char *name, __u32 *ip, __u32 *mask)
+{
+       mm_segment_t   oldmm = get_fs();
+       struct ifreq   ifr;
+       int            rc;
+       __u32          val;
+
+       LASSERT (strnlen(name, IFNAMSIZ) < IFNAMSIZ);
+       
+       strcpy(ifr.ifr_name, name);
+       ifr.ifr_addr.sa_family = AF_INET;
+       set_fs(KERNEL_DS);
+       rc = sock->ops->ioctl(sock, SIOCGIFADDR, (unsigned long)&ifr);
+       set_fs(oldmm);
+
+       if (rc != 0)
+               return rc;
+
+       val = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
+       *ip = ntohl(val);
+
+       strcpy(ifr.ifr_name, name);
+       ifr.ifr_addr.sa_family = AF_INET;
+       set_fs(KERNEL_DS);
+       rc = sock->ops->ioctl(sock, SIOCGIFNETMASK, (unsigned long)&ifr);
+       set_fs(oldmm);
+       
+       if (rc != 0)
+               return rc;
+       
+       val = ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr;
+       *mask = ntohl(val);
+       return 0;
+}
+
+int
+ksocknal_lib_init_if (ksock_interface_t *iface, char *name)
+{
+       struct socket  *sock;
+       int             rc;
+       int             nob;
+
+       rc = sock_create (PF_INET, SOCK_STREAM, 0, &sock);
+       if (rc != 0) {
+               CERROR ("Can't create socket: %d\n", rc);
+               return rc;
+       }
+       
+       nob = strnlen(name, IFNAMSIZ);
+       if (nob == IFNAMSIZ) {
+               CERROR("Interface name %s too long\n", name);
+               rc -EINVAL;
+       } else {
+               CLASSERT (sizeof(iface->ksni_name) >= IFNAMSIZ);
+               strcpy(iface->ksni_name, name);
+
+               rc = ksocknal_lib_getifaddr(sock, name,
+                                           &iface->ksni_ipaddr,
+                                           &iface->ksni_netmask);
+               if (rc != 0)
+                       CERROR("Can't get IP address for interface %s\n", name);
+       }
+
+       sock_release(sock);
+       return rc;
+}
+
+int
+ksocknal_lib_enumerate_ifs (ksock_interface_t *ifs, int nifs)
+{
+       int             nalloc = PTL_MAX_INTERFACES;
+       char            name[IFNAMSIZ];
+       int             nfound;
+       int             nused;
+       struct socket  *sock;
+       struct ifconf   ifc;
+       struct ifreq   *ifr;
+       mm_segment_t    oldmm = get_fs();
+       __u32           ipaddr;
+       __u32           netmask;
+       int             rc;
+       int             i;
+
+       rc = sock_create (PF_INET, SOCK_STREAM, 0, &sock);
+       if (rc != 0) {
+               CERROR ("Can't create socket: %d\n", rc);
+               return rc;
+       }
+
+       for (;;) {
+               PORTAL_ALLOC(ifr, nalloc * sizeof(*ifr));
+               if (ifr == NULL) {
+                       CERROR ("ENOMEM enumerating up to %d interfaces\n", nalloc);
+                       rc = -ENOMEM;
+                       goto out0;
+               }
+               
+               ifc.ifc_buf = (char *)ifr;
+               ifc.ifc_len = nalloc * sizeof(*ifr);
+               
+               set_fs(KERNEL_DS);
+               rc = sock->ops->ioctl(sock, SIOCGIFCONF, (unsigned long)&ifc);
+               set_fs(oldmm);
+
+               if (rc < 0) {
+                       CERROR ("Error %d enumerating interfaces\n", rc);
+                       goto out1;
+               }
+               
+               LASSERT (rc == 0);
+               nfound = rc/sizeof(*ifr);
+               LASSERT (nfound <= nalloc);
+               
+               if (nfound <= nalloc)
+                       break;
+               
+               /* Assume there are more interfaces */
+               if (nalloc >= 16 * PTL_MAX_INTERFACES) {
+                       CWARN("Too many interfaces: "
+                             "only trying the first %d\n", nfound);
+                       break;
+               }
+
+               nalloc *= 2;
+       }
+
+       for (i = nused = 0; i < nfound; i++) {
+               strncpy(name, ifr[i].ifr_name, IFNAMSIZ); /* ensure terminated name */
+               name[IFNAMSIZ-1] = 0;
+               
+               if (!strncmp(name, "lo", 2)) {
+                       CDEBUG(D_WARNING, "ignoring %s\n", name);
+                       continue;
+               }
+               
+               strcpy(ifr[i].ifr_name, name);
+               set_fs(KERNEL_DS);
+               rc = sock->ops->ioctl(sock, SIOCGIFFLAGS, 
+                                     (unsigned long)&ifr[i]);
+               set_fs(oldmm);
+
+               if (rc != 0) {
+                       CDEBUG(D_WARNING, "Can't get flags for %s\n", name);
+                       continue;
+               }
+
+               if ((ifr[i].ifr_flags & IFF_UP) == 0) {
+                       CDEBUG(D_WARNING, "Interface %s down\n", name);
+                       continue;
+               }
+
+               rc = ksocknal_lib_getifaddr(sock, name, &ipaddr, &netmask);
+               if (rc != 0) {
+                       CDEBUG(D_WARNING, 
+                              "Can't get IP address or netmask for %s\n",
+                              name);
+                       continue;
+               }
+
+               if (nused >= nifs) {
+                       CWARN("Too many available interfaces: "
+                             "only using the first %d\n", nused);
+                       break;
+               }
+               
+               memset(&ifs[nused], 0, sizeof(ifs[nused]));
+               
+               CLASSERT(sizeof(ifs[nused].ksni_name) >= IFNAMSIZ);
+               strcpy(ifs[nused].ksni_name, name);
+               ifs[nused].ksni_ipaddr = ipaddr;
+               ifs[nused].ksni_netmask = netmask;
+               nused++;
+       }
+
+       rc = nused;
+ out1:
+       PORTAL_FREE(ifr, nalloc * sizeof(*ifr));
+ out0:
+       sock_release(sock);
+       return rc;
+}
+
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
 struct tcp_opt *sock2tcp_opt(struct sock *sk)
 {
index c28d2f8..38e1352 100644 (file)
@@ -636,6 +636,10 @@ ptl_shutdown_nalnis (void)
                 ptl_apini.apini_nzombie_nis--;
         }
         PTL_UNLOCK(flags);
+
+        LASSERT (ptl_apini.apini_network_tokens != NULL);
+        PORTAL_FREE(ptl_apini.apini_network_tokens,
+                    ptl_apini.apini_network_tokens_nob);
 }
 
 ptl_err_t
@@ -652,8 +656,8 @@ ptl_startup_nalnis (void)
 
         INIT_LIST_HEAD(&nilist);
         rc = ptl_parse_networks(&nilist, networks);
-        if (rc != PTL_OK)
-                return rc;
+        if (rc != PTL_OK) 
+                goto failed;
         
         while (!list_empty(&nilist)) {
                 ni = list_entry(nilist.next, ptl_ni_t, ni_list);
index 6873cce..badecb4 100644 (file)
@@ -201,6 +201,8 @@ ptl_parse_networks(struct list_head *nilist, char *networks)
                return PTL_FAIL;
         }
 
+        ptl_apini.apini_network_tokens = tokens;
+        ptl_apini.apini_network_tokens_nob = tokensize;
         memcpy (tokens, networks, tokensize);
        str = tokens;
 
@@ -311,7 +313,6 @@ ptl_parse_networks(struct list_head *nilist, char *networks)
                 LCONSOLE_ERROR("No networks specified\n");
                 goto failed;
         }
-       PORTAL_FREE(tokens, tokensize);
         return PTL_OK;
 
  failed:
@@ -322,6 +323,8 @@ ptl_parse_networks(struct list_head *nilist, char *networks)
                 PORTAL_FREE(ni, sizeof(*ni));
         }
        PORTAL_FREE(tokens, tokensize);
+        ptl_apini.apini_network_tokens = NULL;
+
         return PTL_FAIL;
 }