Whamcloud - gitweb
* First cut multiple TCP networks
authoreeb <eeb>
Wed, 11 May 2005 06:31:57 +0000 (06:31 +0000)
committereeb <eeb>
Wed, 11 May 2005 06:31:57 +0000 (06:31 +0000)
lnet/klnds/socklnd/socklnd.c
lnet/klnds/socklnd/socklnd.h
lnet/klnds/socklnd/socklnd_cb.c

index cfb3474..5bccc6f 100644 (file)
@@ -41,14 +41,15 @@ ptl_nal_t ksocknal_nal = {
 ksock_nal_data_t        ksocknal_data;
 
 ksock_interface_t *
-ksocknal_ip2iface(__u32 ip)
+ksocknal_ip2iface(ptl_ni_t *ni, __u32 ip)
 {
+        ksock_net_t       *net = ni->ni_data;
         int                i;
         ksock_interface_t *iface;
 
-        for (i = 0; i < ksocknal_data.ksnd_ninterfaces; i++) {
+        for (i = 0; i < net->ksnn_ninterfaces; i++) {
                 LASSERT(i < PTL_MAX_INTERFACES);
-                iface = &ksocknal_data.ksnd_interfaces[i];
+                iface = &net->ksnn_interfaces[i];
 
                 if (iface->ksni_ipaddr == ip)
                         return (iface);
@@ -94,8 +95,9 @@ ksocknal_destroy_route (ksock_route_t *route)
 }
 
 ksock_peer_t *
-ksocknal_create_peer (ptl_nid_t nid)
+ksocknal_create_peer (ptl_ni_t *ni, ptl_nid_t nid)
 {
+        ksock_net_t  *net = ni->ni_data;
         ksock_peer_t *peer;
 
         LASSERT (nid != PTL_NID_ANY);
@@ -106,6 +108,7 @@ ksocknal_create_peer (ptl_nid_t nid)
 
         memset (peer, 0, sizeof (*peer));       /* NULL pointers/clear flags etc */
 
+        peer->ksnp_ni = ni;
         peer->ksnp_nid = nid;
         atomic_set (&peer->ksnp_refcount, 1);   /* 1 ref for caller */
         peer->ksnp_closing = 0;
@@ -113,13 +116,15 @@ ksocknal_create_peer (ptl_nid_t nid)
         CFS_INIT_LIST_HEAD (&peer->ksnp_routes);
         CFS_INIT_LIST_HEAD (&peer->ksnp_tx_queue);
 
-        atomic_inc (&ksocknal_data.ksnd_npeers);
+        atomic_inc (&net->ksnn_npeers);
         return (peer);
 }
 
 void
 ksocknal_destroy_peer (ksock_peer_t *peer)
 {
+        ksock_net_t *net = peer->ksnp_ni->ni_data;
+
         CDEBUG (D_NET, "peer %s %p deleted\n", 
                 libcfs_nid2str(peer->ksnp_nid), peer);
 
@@ -134,11 +139,11 @@ ksocknal_destroy_peer (ksock_peer_t *peer)
          * until they are destroyed, so we can be assured that _all_ state to
          * do with this peer has been cleaned up when its refcount drops to
          * zero. */
-        atomic_dec (&ksocknal_data.ksnd_npeers);
+        atomic_dec (&net->ksnn_npeers);
 }
 
 ksock_peer_t *
-ksocknal_find_peer_locked (ptl_nid_t nid)
+ksocknal_find_peer_locked (ptl_ni_t *ni, ptl_nid_t nid)
 {
         struct list_head *peer_list = ksocknal_nid2peerlist (nid);
         struct list_head *tmp;
@@ -150,6 +155,9 @@ ksocknal_find_peer_locked (ptl_nid_t nid)
 
                 LASSERT (!peer->ksnp_closing);
 
+                if (peer->ksnp_ni != ni)
+                        continue;
+
                 if (peer->ksnp_nid != nid)
                         continue;
 
@@ -162,12 +170,12 @@ ksocknal_find_peer_locked (ptl_nid_t nid)
 }
 
 ksock_peer_t *
-ksocknal_find_peer (ptl_nid_t nid)
+ksocknal_find_peer (ptl_ni_t *ni, ptl_nid_t nid)
 {
         ksock_peer_t     *peer;
 
         read_lock (&ksocknal_data.ksnd_global_lock);
-        peer = ksocknal_find_peer_locked (nid);
+        peer = ksocknal_find_peer_locked (ni, nid);
         if (peer != NULL)                       /* +1 ref for caller? */
                 ksocknal_peer_addref(peer);
         read_unlock (&ksocknal_data.ksnd_global_lock);
@@ -185,7 +193,7 @@ ksocknal_unlink_peer_locked (ksock_peer_t *peer)
                 LASSERT (i < PTL_MAX_INTERFACES);
                 ip = peer->ksnp_passive_ips[i];
 
-                ksocknal_ip2iface(ip)->ksni_npeers--;
+                ksocknal_ip2iface(peer->ksnp_ni, ip)->ksni_npeers--;
         }
 
         LASSERT (list_empty(&peer->ksnp_conns));
@@ -294,12 +302,14 @@ ksocknal_associate_route_conn_locked(ksock_route_t *route, ksock_conn_t *conn)
                               HIPQUAD(route->ksnr_myipaddr),
                               HIPQUAD(conn->ksnc_myipaddr));
 
-                        iface = ksocknal_ip2iface(route->ksnr_myipaddr);
+                        iface = ksocknal_ip2iface(route->ksnr_peer->ksnp_ni,
+                                                  route->ksnr_myipaddr);
                         if (iface != NULL)
                                 iface->ksni_nroutes--;
                 }
                 route->ksnr_myipaddr = conn->ksnc_myipaddr;
-                iface = ksocknal_ip2iface(route->ksnr_myipaddr);
+                iface = ksocknal_ip2iface(route->ksnr_peer->ksnp_ni,
+                                          route->ksnr_myipaddr);
                 if (iface != NULL)
                         iface->ksni_nroutes++;
         }
@@ -377,7 +387,8 @@ ksocknal_del_route_locked (ksock_route_t *route)
         }
 
         if (route->ksnr_myipaddr != 0) {
-                iface = ksocknal_ip2iface(route->ksnr_myipaddr);
+                iface = ksocknal_ip2iface(route->ksnr_peer->ksnp_ni,
+                                          route->ksnr_myipaddr);
                 if (iface != NULL)
                         iface->ksni_nroutes--;
         }
@@ -395,7 +406,7 @@ ksocknal_del_route_locked (ksock_route_t *route)
 }
 
 int
-ksocknal_add_peer (ptl_nid_t nid, __u32 ipaddr, int port)
+ksocknal_add_peer (ptl_ni_t *ni, ptl_nid_t nid, __u32 ipaddr, int port)
 {
         unsigned long      flags;
         struct list_head  *tmp;
@@ -408,7 +419,7 @@ ksocknal_add_peer (ptl_nid_t nid, __u32 ipaddr, int port)
                 return (-EINVAL);
 
         /* Have a brand new peer ready... */
-        peer = ksocknal_create_peer (nid);
+        peer = ksocknal_create_peer(ni, nid);
         if (peer == NULL)
                 return (-ENOMEM);
 
@@ -420,7 +431,7 @@ ksocknal_add_peer (ptl_nid_t nid, __u32 ipaddr, int port)
 
         write_lock_irqsave (&ksocknal_data.ksnd_global_lock, flags);
 
-        peer2 = ksocknal_find_peer_locked (nid);
+        peer2 = ksocknal_find_peer_locked (ni, nid);
         if (peer2 != NULL) {
                 ksocknal_peer_decref(peer);
                 peer = peer2;
@@ -508,7 +519,7 @@ ksocknal_del_peer_locked (ksock_peer_t *peer, __u32 ip)
 }
 
 int
-ksocknal_del_peer (ptl_nid_t nid, __u32 ip)
+ksocknal_del_peer (ptl_ni_t *ni, ptl_nid_t nid, __u32 ip)
 {
         unsigned long      flags;
         struct list_head  *ptmp;
@@ -532,6 +543,9 @@ ksocknal_del_peer (ptl_nid_t nid, __u32 ip)
                 list_for_each_safe (ptmp, pnxt, &ksocknal_data.ksnd_peers[i]) {
                         peer = list_entry (ptmp, ksock_peer_t, ksnp_list);
 
+                        if (peer->ksnp_ni != ni)
+                                continue;
+
                         if (!(nid == PTL_NID_ANY || peer->ksnp_nid == nid))
                                 continue;
 
@@ -613,18 +627,19 @@ ksocknal_choose_scheduler_locked (unsigned int irq)
 }
 
 int
-ksocknal_local_ipvec (__u32 *ipaddrs)
+ksocknal_local_ipvec (ptl_ni_t *ni, __u32 *ipaddrs)
 {
+        ksock_net_t       *net = ni->ni_data;
         int                i;
         int                nip;
 
         read_lock (&ksocknal_data.ksnd_global_lock);
 
-        nip = ksocknal_data.ksnd_ninterfaces;
+        nip = net->ksnn_ninterfaces;
         for (i = 0; i < nip; i++) {
                 LASSERT (i < PTL_MAX_INTERFACES);
 
-                ipaddrs[i] = ksocknal_data.ksnd_interfaces[i].ksni_ipaddr;
+                ipaddrs[i] = net->ksnn_interfaces[i].ksni_ipaddr;
                 LASSERT (ipaddrs[i] != 0);
         }
 
@@ -668,6 +683,7 @@ int
 ksocknal_select_ips(ksock_peer_t *peer, __u32 *peerips, int n_peerips)
 {
         rwlock_t           *global_lock = &ksocknal_data.ksnd_global_lock;
+        ksock_net_t        *net = peer->ksnp_ni->ni_data;
         unsigned long       flags;
         ksock_interface_t  *iface;
         ksock_interface_t  *best_iface;
@@ -692,9 +708,9 @@ ksocknal_select_ips(ksock_peer_t *peer, __u32 *peerips, int n_peerips)
         write_lock_irqsave(global_lock, flags);
 
         LASSERT (n_peerips <= PTL_MAX_INTERFACES);
-        LASSERT (ksocknal_data.ksnd_ninterfaces <= PTL_MAX_INTERFACES);
+        LASSERT (net->ksnn_ninterfaces <= PTL_MAX_INTERFACES);
 
-        n_ips = MIN(n_peerips, ksocknal_data.ksnd_ninterfaces);
+        n_ips = MIN(n_peerips, net->ksnn_ninterfaces);
 
         for (i = 0; peer->ksnp_n_passive_ips < n_ips; i++) {
                 /*              ^ yes really... */
@@ -708,7 +724,7 @@ ksocknal_select_ips(ksock_peer_t *peer, __u32 *peerips, int n_peerips)
                 if (i < peer->ksnp_n_passive_ips) {
                         /* Old interface. */
                         ip = peer->ksnp_passive_ips[i];
-                        best_iface = ksocknal_ip2iface(ip);
+                        best_iface = ksocknal_ip2iface(peer->ksnp_ni, ip);
 
                         /* peer passive ips are kept up to date */
                         LASSERT(best_iface != NULL);
@@ -720,8 +736,8 @@ ksocknal_select_ips(ksock_peer_t *peer, __u32 *peerips, int n_peerips)
                         best_netmatch = 0;
                         best_npeers = 0;
 
-                        for (j = 0; j < ksocknal_data.ksnd_ninterfaces; j++) {
-                                iface = &ksocknal_data.ksnd_interfaces[j];
+                        for (j = 0; j < net->ksnn_ninterfaces; j++) {
+                                iface = &net->ksnn_interfaces[j];
                                 ip = iface->ksni_ipaddr;
 
                                 for (k = 0; k < peer->ksnp_n_passive_ips; k++)
@@ -773,6 +789,8 @@ ksocknal_create_routes(ksock_peer_t *peer, int port,
 {
         ksock_route_t      *newroute = NULL;
         rwlock_t           *global_lock = &ksocknal_data.ksnd_global_lock;
+        ptl_ni_t           *ni = peer->ksnp_ni;
+        ksock_net_t        *net = ni->ni_data;
         unsigned long       flags;
         struct list_head   *rtmp;
         ksock_route_t      *route;
@@ -823,11 +841,11 @@ ksocknal_create_routes(ksock_peer_t *peer, int port,
                 best_nroutes = 0;
                 best_netmatch = 0;
 
-                LASSERT (ksocknal_data.ksnd_ninterfaces <= PTL_MAX_INTERFACES);
+                LASSERT (net->ksnn_ninterfaces <= PTL_MAX_INTERFACES);
 
                 /* Select interface to connect from */
-                for (j = 0; j < ksocknal_data.ksnd_ninterfaces; j++) {
-                        iface = &ksocknal_data.ksnd_interfaces[j];
+                for (j = 0; j < net->ksnn_ninterfaces; j++) {
+                        iface = &net->ksnn_interfaces[j];
 
                         /* Using this interface already? */
                         list_for_each(rtmp, &peer->ksnp_routes) {
@@ -1027,7 +1045,7 @@ ksocknal_create_conn (ksock_route_t *route, struct socket *sock, int type)
 
         if (!passive) {
                 /* Active connection sends HELLO eagerly */
-                rc = ksocknal_local_ipvec(ipaddrs);
+                rc = ksocknal_local_ipvec(route->ksnr_peer->ksnp_ni, ipaddrs);
                 if (rc < 0)
                         goto failed_1;
                 nipaddrs = rc;
@@ -1050,7 +1068,23 @@ ksocknal_create_conn (ksock_route_t *route, struct socket *sock, int type)
                 peer = route->ksnr_peer;
                 ksocknal_peer_addref(peer);
         } else {
-                peer = ksocknal_create_peer(nid);
+                ptl_ni_t *ni = ptl_net2ni(PTL_NIDNET(nid));
+
+                if (ni == NULL) {
+                        CERROR("Refusing connection attempt "
+                               "(no matching net)\n");
+                        rc = -ECONNREFUSED;
+                        goto failed_1;
+                }
+                
+                peer = ksocknal_create_peer(ni, nid);
+
+                /* lose extra ref from ptl_net2ni NB we wait for all the peers
+                 * to be deleted before ni teardown can complete; i.e. ni can't
+                 * disappear until all its peer table entries has gone so
+                 * there's no to account the peer's refs on ni. */
+                ptl_ni_decref(ni);
+
                 if (peer == NULL) {
                         rc = -ENOMEM;
                         goto failed_1;
@@ -1058,7 +1092,7 @@ ksocknal_create_conn (ksock_route_t *route, struct socket *sock, int type)
 
                 write_lock_irqsave(global_lock, flags);
 
-                peer2 = ksocknal_find_peer_locked(nid);
+                peer2 = ksocknal_find_peer_locked(ni, nid);
                 if (peer2 == NULL) {
                         /* NB this puts an "empty" peer in the peer
                          * table (which takes my ref) */
@@ -1346,8 +1380,7 @@ ksocknal_terminate_conn (ksock_conn_t *conn)
         ksocknal_connsock_decref(conn);
 
         if (notify)
-                kpr_notify (ksocknal_data.ksnd_ni, peer->ksnp_nid,
-                            0, then);
+                kpr_notify (peer->ksnp_ni, peer->ksnp_nid, 0, then);
 }
 
 void
@@ -1386,11 +1419,11 @@ ksocknal_destroy_conn (ksock_conn_t *conn)
                        ", ip %d.%d.%d.%d:%d, with error\n",
                        libcfs_nid2str(conn->ksnc_peer->ksnp_nid),
                        HIPQUAD(conn->ksnc_ipaddr), conn->ksnc_port);
-                ptl_finalize (ksocknal_data.ksnd_ni, NULL, 
+                ptl_finalize (conn->ksnc_peer->ksnp_ni, NULL, 
                               conn->ksnc_cookie, PTL_FAIL);
                 break;
         case SOCKNAL_RX_BODY_FWD:
-                ksocknal_fmb_callback (ksocknal_data.ksnd_ni,
+                ksocknal_fmb_callback (conn->ksnc_peer->ksnp_ni,
                                        conn->ksnc_cookie, -ECONNABORTED);
                 break;
         case SOCKNAL_RX_HEADER:
@@ -1565,7 +1598,7 @@ ksocknal_push_peer (ksock_peer_t *peer)
 }
 
 int
-ksocknal_push (ptl_nid_t nid)
+ksocknal_push (ptl_ni_t *ni, ptl_nid_t nid)
 {
         ksock_peer_t      *peer;
         struct list_head  *tmp;
@@ -1575,7 +1608,7 @@ ksocknal_push (ptl_nid_t nid)
         int                rc = -ENOENT;
 
         if (nid != PTL_NID_ANY) {
-                peer = ksocknal_find_peer (nid);
+                peer = ksocknal_find_peer (ni, nid);
 
                 if (peer != NULL) {
                         rc = 0;
@@ -1616,8 +1649,9 @@ ksocknal_push (ptl_nid_t nid)
 }
 
 int
-ksocknal_add_interface(__u32 ipaddress, __u32 netmask)
+ksocknal_add_interface(ptl_ni_t *ni, __u32 ipaddress, __u32 netmask)
 {
+        ksock_net_t       *net = ni->ni_data;
         unsigned long      flags;
         ksock_interface_t *iface;
         int                rc;
@@ -1634,14 +1668,14 @@ ksocknal_add_interface(__u32 ipaddress, __u32 netmask)
 
         write_lock_irqsave(&ksocknal_data.ksnd_global_lock, flags);
 
-        iface = ksocknal_ip2iface(ipaddress);
+        iface = ksocknal_ip2iface(ni, ipaddress);
         if (iface != NULL) {
                 /* silently ignore dups */
                 rc = 0;
-        } else if (ksocknal_data.ksnd_ninterfaces == PTL_MAX_INTERFACES) {
+        } else if (net->ksnn_ninterfaces == PTL_MAX_INTERFACES) {
                 rc = -ENOSPC;
         } else {
-                iface = &ksocknal_data.ksnd_interfaces[ksocknal_data.ksnd_ninterfaces++];
+                iface = &net->ksnn_interfaces[net->ksnn_ninterfaces++];
 
                 iface->ksni_ipaddr = ipaddress;
                 iface->ksni_netmask = netmask;
@@ -1716,8 +1750,9 @@ ksocknal_peer_del_interface_locked(ksock_peer_t *peer, __u32 ipaddr)
 }
 
 int
-ksocknal_del_interface(__u32 ipaddress)
+ksocknal_del_interface(ptl_ni_t *ni, __u32 ipaddress)
 {
+        ksock_net_t       *net = ni->ni_data;
         int                rc = -ENOENT;
         unsigned long      flags;
         struct list_head  *tmp;
@@ -1729,8 +1764,8 @@ ksocknal_del_interface(__u32 ipaddress)
 
         write_lock_irqsave(&ksocknal_data.ksnd_global_lock, flags);
 
-        for (i = 0; i < ksocknal_data.ksnd_ninterfaces; i++) {
-                this_ip = ksocknal_data.ksnd_interfaces[i].ksni_ipaddr;
+        for (i = 0; i < net->ksnn_ninterfaces; i++) {
+                this_ip = net->ksnn_interfaces[i].ksni_ipaddr;
 
                 if (!(ipaddress == 0 ||
                       ipaddress == this_ip))
@@ -1738,16 +1773,19 @@ ksocknal_del_interface(__u32 ipaddress)
 
                 rc = 0;
 
-                for (j = i+1; j < ksocknal_data.ksnd_ninterfaces; j++)
-                        ksocknal_data.ksnd_interfaces[j-1] =
-                                ksocknal_data.ksnd_interfaces[j];
+                for (j = i+1; j < net->ksnn_ninterfaces; j++)
+                        net->ksnn_interfaces[j-1] =
+                                net->ksnn_interfaces[j];
 
-                ksocknal_data.ksnd_ninterfaces--;
+                net->ksnn_ninterfaces--;
 
                 for (j = 0; j < ksocknal_data.ksnd_peer_hash_size; j++) {
                         list_for_each_safe(tmp, nxt, &ksocknal_data.ksnd_peers[j]) {
                                 peer = list_entry(tmp, ksock_peer_t, ksnp_list);
 
+                                if (peer->ksnp_ni != ni)
+                                        continue;
+
                                 ksocknal_peer_del_interface_locked(peer, this_ip);
                         }
                 }
@@ -1764,20 +1802,19 @@ ksocknal_ctl(ptl_ni_t *ni, unsigned int cmd, void *arg)
         struct portal_ioctl_data *data = arg;
         int rc;
 
-        LASSERT(ni == ksocknal_data.ksnd_ni);
-
         switch(cmd) {
         case IOC_PORTAL_GET_INTERFACE: {
+                ksock_net_t       *net = ni->ni_data;
                 ksock_interface_t *iface;
 
                 read_lock (&ksocknal_data.ksnd_global_lock);
 
                 if (data->ioc_count < 0 ||
-                    data->ioc_count >= ksocknal_data.ksnd_ninterfaces) {
+                    data->ioc_count >= net->ksnn_ninterfaces) {
                         rc = -ENOENT;
                 } else {
                         rc = 0;
-                        iface = &ksocknal_data.ksnd_interfaces[data->ioc_count];
+                        iface = &net->ksnn_interfaces[data->ioc_count];
 
                         data->ioc_u32[0] = iface->ksni_ipaddr;
                         data->ioc_u32[1] = iface->ksni_netmask;
@@ -1790,11 +1827,13 @@ ksocknal_ctl(ptl_ni_t *ni, unsigned int cmd, void *arg)
         }
 
         case IOC_PORTAL_ADD_INTERFACE:
-                return ksocknal_add_interface(data->ioc_u32[0], /* IP address */
+                return ksocknal_add_interface(ni,
+                                              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 */
+                return ksocknal_del_interface(ni, 
+                                              data->ioc_u32[0]); /* IP address */
 
         case IOC_PORTAL_GET_PEER: {
                 ptl_nid_t    nid = 0;
@@ -1817,12 +1856,14 @@ ksocknal_ctl(ptl_ni_t *ni, unsigned int cmd, void *arg)
         }
 
         case IOC_PORTAL_ADD_PEER:
-                return ksocknal_add_peer (data->ioc_nid,
+                return ksocknal_add_peer (ni,
+                                          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,
+                return ksocknal_del_peer (ni,
+                                          data->ioc_nid,
                                           data->ioc_u32[0]); /* IP */
 
         case IOC_PORTAL_GET_CONN: {
@@ -1866,7 +1907,7 @@ ksocknal_ctl(ptl_ni_t *ni, unsigned int cmd, void *arg)
                return 0;
 
         case IOC_PORTAL_PUSH_CONNECTION:
-                return ksocknal_push (data->ioc_nid);
+                return ksocknal_push (ni, data->ioc_nid);
 
         default:
                 return -EINVAL;
@@ -1916,15 +1957,14 @@ ksocknal_free_buffers (void)
 }
 
 void
-ksocknal_shutdown (ptl_ni_t *ni)
+ksocknal_base_shutdown (void)
 {
         ksock_sched_t *sched;
         int            i;
 
         CDEBUG(D_MALLOC, "before NAL cleanup: kmem %d\n",
                atomic_read (&portal_kmemory));
-
-        LASSERT(ni == ksocknal_data.ksnd_ni);
+        LASSERT (ksocknal_data.ksnd_nnets == 0);
 
         switch (ksocknal_data.ksnd_init) {
         default:
@@ -1944,20 +1984,6 @@ ksocknal_shutdown (ptl_ni_t *ni)
                 /* fall through */
 
         case SOCKNAL_INIT_DATA:
-                /* Delete all peers */
-                ksocknal_del_peer(PTL_NID_ANY, 0);
-
-                /* Wait for all peer state to clean up */
-                i = 2;
-                while (atomic_read (&ksocknal_data.ksnd_npeers) != 0) {
-                        i++;
-                        CDEBUG(((i & (-i)) == i) ? D_WARNING : D_NET, /* power of 2? */
-                               "waiting for %d peers to disconnect\n",
-                               atomic_read (&ksocknal_data.ksnd_npeers));
-                        ksocknal_pause(cfs_time_seconds(1));
-                }
-
-                LASSERT (atomic_read (&ksocknal_data.ksnd_npeers) == 0);
                 LASSERT (ksocknal_data.ksnd_peers != NULL);
                 for (i = 0; i < ksocknal_data.ksnd_peer_hash_size; i++) {
                         LASSERT (list_empty (&ksocknal_data.ksnd_peers[i]));
@@ -2018,8 +2044,8 @@ ksocknal_shutdown (ptl_ni_t *ni)
 }
 
 
-void
-ksocknal_init_incarnation (void)
+__u64
+ksocknal_new_incarnation (void)
 {
         struct timeval tv;
 
@@ -2030,32 +2056,22 @@ ksocknal_init_incarnation (void)
 
         do_gettimeofday(&tv);
 
-        ksocknal_data.ksnd_incarnation =
-                (((__u64)tv.tv_sec) * 1000000) + tv.tv_usec;
+        return (((__u64)tv.tv_sec) * 1000000) + tv.tv_usec;
 }
 
 ptl_err_t
-ksocknal_startup (ptl_ni_t *ni)
+ksocknal_base_startup (void)
 {
         int               pkmem = atomic_read(&portal_kmemory);
         int               rc;
         int               i;
         int               j;
 
-        LASSERT (ni->ni_nal == &ksocknal_nal);
-
-        if (ksocknal_data.ksnd_init != SOCKNAL_INIT_NOTHING) {
-                CERROR ("Only 1 instance supported\n");
-                return PTL_FAIL;
-        }
+        LASSERT (ksocknal_data.ksnd_init == SOCKNAL_INIT_NOTHING);
+        LASSERT (ksocknal_data.ksnd_nnets == 0);
 
         memset (&ksocknal_data, 0, sizeof (ksocknal_data)); /* zero pointers */
 
-        ksocknal_data.ksnd_ni = ni;             /* temp hack */
-        ni->ni_data = &ksocknal_data;
-
-        ksocknal_init_incarnation();
-
         ksocknal_data.ksnd_peer_hash_size = SOCKNAL_PEER_HASH_SIZE;
         PORTAL_ALLOC (ksocknal_data.ksnd_peers,
                       sizeof (struct list_head) * ksocknal_data.ksnd_peer_hash_size);
@@ -2172,53 +2188,127 @@ ksocknal_startup (ptl_ni_t *ni)
                         list_add(&fmb->fmb_list, &pool->fmp_idle_fmbs);
                 }
         }
+        
+        rc = ksocknal_start_listener();
+        if (rc != 0) {
+                CERROR("Can't start listener: %d\n", rc);
+                goto failed;
+        }
+
+        /* flag everything initialised */
+        ksocknal_data.ksnd_init = SOCKNAL_INIT_ALL;
+
+        printk(KERN_INFO 
+               "Lustre: Routing socket NAL loaded (initial mem %d)\n", pkmem);
+        
+        return PTL_OK;
+
+ failed:
+        ksocknal_base_shutdown();
+        return PTL_FAIL;
+}
+
+void
+ksocknal_shutdown (ptl_ni_t *ni)
+{
+        ksock_net_t    *net = ni->ni_data;
+        int             i;
+
+        LASSERT(ksocknal_data.ksnd_init == SOCKNAL_INIT_ALL);
+        LASSERT(ksocknal_data.ksnd_nnets > 0);
+
+        /* Delete all peers */
+        ksocknal_del_peer(ni, PTL_NID_ANY, 0);
+
+        /* Wait for all peer state to clean up */
+        i = 2;
+        while (atomic_read (&net->ksnn_npeers) != 0) {
+                i++;
+                CDEBUG(((i & (-i)) == i) ? D_WARNING : D_NET, /* power of 2? */
+                       "waiting for %d peers to disconnect\n",
+                       atomic_read (&net->ksnn_npeers));
+                ksocknal_pause(cfs_time_seconds(1));
+        }
+
+        for (i = 0; i < net->ksnn_ninterfaces; i++) {
+                LASSERT (net->ksnn_interfaces[i].ksni_npeers == 0);
+                LASSERT (net->ksnn_interfaces[i].ksni_nroutes == 0);
+        }
+
+        PORTAL_FREE(net, sizeof(*net));
+        
+        ksocknal_data.ksnd_nnets--;
+        if (ksocknal_data.ksnd_nnets == 0)
+                ksocknal_base_shutdown();
+}
+
+ptl_err_t
+ksocknal_startup (ptl_ni_t *ni)
+{
+        ksock_net_t  *net;
+        int           rc;
+        int           i;
+
+        LASSERT (ni->ni_nal == &ksocknal_nal);
+
+        if (ksocknal_data.ksnd_init == SOCKNAL_INIT_NOTHING) {
+                rc = ksocknal_base_startup();
+                if (rc != PTL_OK)
+                        return rc;
+        }
+        
+        PORTAL_ALLOC(net, sizeof(*net));
+        if (net == NULL)
+                goto fail_0;
+                
+        memset(net, 0, sizeof(*net));
+        
+        net->ksnn_incarnation = ksocknal_new_incarnation();
+        ni->ni_data = net;
 
         if (ni->ni_interfaces[0] == NULL) {
-                rc = ksocknal_lib_enumerate_ifs(ksocknal_data.ksnd_interfaces,
+                rc = ksocknal_lib_enumerate_ifs(net->ksnn_interfaces,
                                                 PTL_MAX_INTERFACES);
                 if (rc < 0)
-                        goto failed;
+                        goto fail_1;
 
                 if (rc == 0) {
                         CERROR("Can't find any interfaces\n");
-                        goto failed;
+                        goto fail_1;
                 }
+                
+                net->ksnn_ninterfaces = rc;
         } 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],
+                        rc = ksocknal_lib_init_if(&net->ksnn_interfaces[i],
                                                   ni->ni_interfaces[i]);
                         if (rc != 0)
-                                goto failed;
+                                goto fail_1;
                 }
+                net->ksnn_ninterfaces = i;
         }
 
         ni->ni_nid = PTL_MKNID(PTL_NIDNET(ni->ni_nid),
-                               ksocknal_data.ksnd_interfaces[0].ksni_ipaddr);
+                               net->ksnn_interfaces[0].ksni_ipaddr);
         CDEBUG(D_WARNING, "Set NID to %s\n", libcfs_nid2str(ni->ni_nid));
-        
-        rc = ksocknal_start_listener();
-        if (rc != 0) {
-                CERROR("Can't start listener: %d\n", rc);
-                goto failed;
-        }
 
-        /* flag everything initialised */
-        ksocknal_data.ksnd_init = SOCKNAL_INIT_ALL;
+        ksocknal_data.ksnd_nnets++;
 
-        printk(KERN_INFO "Lustre: Routing socket NAL loaded "
-               "(initial mem %d, incarnation "LPD64")\n",
-               pkmem, ksocknal_data.ksnd_incarnation);
-        
         return PTL_OK;
+        
+ fail_1:
+        PORTAL_FREE(net, sizeof(*net));
+ fail_0:
+        if (ksocknal_data.ksnd_nnets == 0)
+                ksocknal_base_shutdown();
 
- failed:
-        ksocknal_shutdown(ni);
         return PTL_FAIL;
 }
 
+
 void __exit
 ksocknal_module_fini (void)
 {
index af55041..de3cb63 100644 (file)
@@ -157,8 +157,16 @@ typedef struct
 
 typedef struct
 {
+        __u64             ksnn_incarnation;     /* my epoch */
+        atomic_t          ksnn_npeers;          /* # peers */
+        int               ksnn_ninterfaces;     /* IP interfaces */
+        ksock_interface_t ksnn_interfaces[PTL_MAX_INTERFACES];
+} ksock_net_t;
+
+typedef struct
+{
         int               ksnd_init;            /* initialisation state */
-        __u64             ksnd_incarnation;     /* my epoch */
+        int               ksnd_nnets;           /* # networks set up */
 
         int               ksnd_listener_shutdown; /* listener start/stop/rc */
         struct socket    *ksnd_listener_sock;   /* listener's socket */
@@ -173,11 +181,6 @@ typedef struct
         int               ksnd_nschedulers;     /* # schedulers */
         ksock_sched_t    *ksnd_schedulers;      /* their state */
 
-        atomic_t          ksnd_npeers;          /* total # peers extant */
-        atomic_t          ksnd_nclosing_conns;  /* # closed conns extant */
-
-        void             *ksnd_router;          /* router callback arg */
-
         ksock_fmb_pool_t  ksnd_small_fmp;       /* small message forwarding buffers */
         ksock_fmb_pool_t  ksnd_large_fmp;       /* large message forwarding buffers */
 
@@ -201,10 +204,6 @@ typedef struct
 
         ksock_irqinfo_t   ksnd_irqinfo[NR_IRQS];/* irq->scheduler lookup */
 
-        ptl_ni_t         *ksnd_ni;              /* NI instance (tmp hack) */
-
-        int               ksnd_ninterfaces;
-        ksock_interface_t ksnd_interfaces[PTL_MAX_INTERFACES]; /* active interfaces */
 } ksock_nal_data_t;
 
 #define SOCKNAL_INIT_NOTHING    0
@@ -380,6 +379,7 @@ typedef struct ksock_peer
         struct list_head    ksnp_routes;        /* routes */
         struct list_head    ksnp_tx_queue;      /* waiting packets */
         cfs_time_t          ksnp_last_alive;    /* when (in jiffies) I was last alive */
+        ptl_ni_t           *ksnp_ni;            /* which network */
         int                 ksnp_n_passive_ips; /* # of... */
         __u32               ksnp_passive_ips[PTL_MAX_INTERFACES]; /* preferred local interfaces */
 } ksock_peer_t;
@@ -505,9 +505,9 @@ ptl_err_t ksocknal_recv_pages(ptl_ni_t *ni, void *private,
                               size_t mlen, size_t rlen);
 
 
-extern int ksocknal_add_peer(ptl_nid_t nid, __u32 ip, int port);
-extern ksock_peer_t *ksocknal_find_peer_locked (ptl_nid_t nid);
-extern ksock_peer_t *ksocknal_find_peer (ptl_nid_t nid);
+extern int ksocknal_add_peer(ptl_ni_t *ni, ptl_nid_t nid, __u32 ip, int port);
+extern ksock_peer_t *ksocknal_find_peer_locked (ptl_ni_t *ni, ptl_nid_t nid);
+extern ksock_peer_t *ksocknal_find_peer (ptl_ni_t *ni, ptl_nid_t nid);
 extern int ksocknal_create_conn (ksock_route_t *route,
                                  struct socket *sock, int type);
 extern void ksocknal_close_conn_locked (ksock_conn_t *conn, int why);
index e9fb82a..c6fc466 100644 (file)
@@ -378,7 +378,7 @@ ksocknal_tx_done (ksock_tx_t *tx, int asynch)
         }
 
         if (tx->tx_isfwd) {             /* was a forwarded packet? */
-                kpr_fwd_done (ksocknal_data.ksnd_ni,
+                kpr_fwd_done (tx->tx_conn->ksnc_peer->ksnp_ni,
                               KSOCK_TX_2_KPR_FWD_DESC (tx), 
                               (tx->tx_resid == 0) ? 0 : -ECONNABORTED);
                 EXIT;
@@ -388,7 +388,7 @@ ksocknal_tx_done (ksock_tx_t *tx, int asynch)
         /* local send */
         ltx = KSOCK_TX_2_KSOCK_LTX (tx);
 
-        ptl_finalize (ksocknal_data.ksnd_ni, 
+        ptl_finalize (tx->tx_conn->ksnc_peer->ksnp_ni, 
                       ltx->ltx_private, ltx->ltx_cookie,
                       (tx->tx_resid == 0) ? PTL_OK : PTL_FAIL);
 
@@ -682,7 +682,7 @@ ksocknal_find_connecting_route_locked (ksock_peer_t *peer)
 }
 
 int
-ksocknal_launch_packet (ksock_tx_t *tx, ptl_nid_t nid, int routing)
+ksocknal_launch_packet (ptl_ni_t *ni, ksock_tx_t *tx, ptl_nid_t nid, int routing)
 {
         unsigned long     flags;
         ksock_peer_t     *peer;
@@ -715,7 +715,7 @@ ksocknal_launch_packet (ksock_tx_t *tx, ptl_nid_t nid, int routing)
         
  again:
         if (create_peer) {
-                rc = ksocknal_add_peer(nid, (__u32)nid,
+                rc = ksocknal_add_peer(ni, nid, PTL_NIDADDR(nid),
                                        *ksocknal_tunables.ksnd_port);
                 if (rc != 0) {
                         CERROR("Can't add peer %s: %d\n",
@@ -726,7 +726,7 @@ ksocknal_launch_packet (ksock_tx_t *tx, ptl_nid_t nid, int routing)
         
 #if !SOCKNAL_ROUND_ROBIN
         read_lock (g_lock);
-        peer = ksocknal_find_peer_locked(nid);
+        peer = ksocknal_find_peer_locked(ni, nid);
         if (peer != NULL) {
                 if (ksocknal_find_connectable_route_locked(peer) == NULL) {
                         conn = ksocknal_find_conn_locked (tx, peer);
@@ -746,7 +746,7 @@ ksocknal_launch_packet (ksock_tx_t *tx, ptl_nid_t nid, int routing)
 #endif
         write_lock_irqsave(g_lock, flags);
 
-        peer = ksocknal_find_peer_locked(nid);
+        peer = ksocknal_find_peer_locked(ni, nid);
         if (peer == NULL) {
                 write_unlock_irqrestore(g_lock, flags);
 
@@ -880,7 +880,7 @@ ksocknal_sendmsg(ptl_ni_t        *ni,
                                          payload_offset, payload_nob);
         }
 
-        rc = ksocknal_launch_packet(&ltx->ltx_tx, target.nid, routing);
+        rc = ksocknal_launch_packet(ni, &ltx->ltx_tx, target.nid, routing);
         if (rc == 0)
                 return (PTL_OK);
         
@@ -924,7 +924,7 @@ ksocknal_fwd_packet (ptl_ni_t *ni, kpr_fwd_desc_t *fwd)
                 libcfs_nid2str(fwd->kprfd_gateway_nid), 
                 libcfs_nid2str(fwd->kprfd_target_nid));
 
-        routing = (nid != ksocknal_data.ksnd_ni->ni_nid);
+        routing = (nid != ni->ni_nid);
         if (!routing)
                 nid = fwd->kprfd_target_nid;
 
@@ -939,7 +939,7 @@ ksocknal_fwd_packet (ptl_ni_t *ni, kpr_fwd_desc_t *fwd)
         ftx->ftx_tx.tx_nkiov = fwd->kprfd_niov;
         ftx->ftx_tx.tx_kiov  = fwd->kprfd_kiov;
 
-        rc = ksocknal_launch_packet (&ftx->ftx_tx, nid, routing);
+        rc = ksocknal_launch_packet (ni, &ftx->ftx_tx, nid, routing);
         if (rc != 0)
                 kpr_fwd_done (ni, fwd, rc);
 }
@@ -1106,7 +1106,7 @@ ksocknal_init_fmb (ksock_conn_t *conn, ksock_fmb_t *fmb)
                         libcfs_nid2str(le64_to_cpu(conn->ksnc_hdr.src_nid)), 
                         libcfs_nid2str(dest_nid));
 
-                kpr_fwd_start (ksocknal_data.ksnd_ni, &fmb->fmb_fwd);
+                kpr_fwd_start (conn->ksnc_peer->ksnp_ni, &fmb->fmb_fwd);
 
                 ksocknal_new_packet (conn, 0);  /* on to next packet */
                 return (1);
@@ -1133,7 +1133,6 @@ ksocknal_init_fmb (ksock_conn_t *conn, ksock_fmb_t *fmb)
 void
 ksocknal_fwd_parse (ksock_conn_t *conn)
 {
-        ksock_peer_t *peer;
         ptl_nid_t     dest_nid = le64_to_cpu(conn->ksnc_hdr.dest_nid);
         ptl_nid_t     src_nid = le64_to_cpu(conn->ksnc_hdr.src_nid);
         int           body_len = le32_to_cpu(conn->ksnc_hdr.payload_length);
@@ -1157,7 +1156,7 @@ ksocknal_fwd_parse (ksock_conn_t *conn)
         }
 
         if (PTL_NIDNET(conn->ksnc_hdr.dest_nid) ==
-            PTL_NIDNET(ksocknal_data.ksnd_ni->ni_nid)) {
+            PTL_NIDNET(conn->ksnc_peer->ksnp_ni->ni_nid)) {
                 /* should have gone direct */
                 CERROR ("dropping packet from %s for %s: "
                         "target is a peer\n",
@@ -1315,7 +1314,7 @@ ksocknal_process_receive (ksock_conn_t *conn)
         case SOCKNAL_RX_HEADER:
                 if (conn->ksnc_hdr.type != cpu_to_le32(PTL_MSG_HELLO) &&
                     le64_to_cpu(conn->ksnc_hdr.dest_nid) != 
-                    ksocknal_data.ksnd_ni->ni_nid) {
+                    conn->ksnc_peer->ksnp_ni->ni_nid) {
                         /* This packet isn't for me */
                         ksocknal_fwd_parse (conn);
                         switch (conn->ksnc_rx_state) {
@@ -1332,7 +1331,7 @@ ksocknal_process_receive (ksock_conn_t *conn)
                 }
 
                 /* sets wanted_len, iovs etc */
-                rc = ptl_parse(ksocknal_data.ksnd_ni, &conn->ksnc_hdr, conn);
+                rc = ptl_parse(conn->ksnc_peer->ksnp_ni, &conn->ksnc_hdr, conn);
 
                 if (rc != PTL_OK) {
                         /* I just received garbage: give up on this conn */
@@ -1348,7 +1347,7 @@ ksocknal_process_receive (ksock_conn_t *conn)
 
         case SOCKNAL_RX_BODY:
                 /* payload all received */
-                ptl_finalize(ksocknal_data.ksnd_ni, NULL, conn->ksnc_cookie, PTL_OK);
+                ptl_finalize(conn->ksnc_peer->ksnp_ni, NULL, conn->ksnc_cookie, PTL_OK);
                 /* Fall through */
 
         case SOCKNAL_RX_SLOP:
@@ -1367,7 +1366,7 @@ ksocknal_process_receive (ksock_conn_t *conn)
                 /* forward the packet. NB ksocknal_init_fmb() put fmb into
                  * conn->ksnc_cookie */
                 fmb = (ksock_fmb_t *)conn->ksnc_cookie;
-                kpr_fwd_start (ksocknal_data.ksnd_ni, &fmb->fmb_fwd);
+                kpr_fwd_start (conn->ksnc_peer->ksnp_ni, &fmb->fmb_fwd);
 
                 /* no slop in forwarded packets */
                 LASSERT (conn->ksnc_rx_nob_left == 0);
@@ -1690,6 +1689,8 @@ int
 ksocknal_send_hello (ksock_conn_t *conn, __u32 *ipaddrs, int nipaddrs)
 {
         /* CAVEAT EMPTOR: this byte flips 'ipaddrs' */
+        ptl_ni_t           *ni = conn->ksnc_peer->ksnp_ni;
+        ksock_net_t        *net = ni->ni_data;
         struct socket      *sock = conn->ksnc_sock;
         ptl_hdr_t           hdr;
         ptl_magicversion_t *hmv = (ptl_magicversion_t *)&hdr.dest_nid;
@@ -1707,13 +1708,12 @@ ksocknal_send_hello (ksock_conn_t *conn, __u32 *ipaddrs, int nipaddrs)
         hmv->version_major = cpu_to_le16 (PORTALS_PROTO_VERSION_MAJOR);
         hmv->version_minor = cpu_to_le16 (PORTALS_PROTO_VERSION_MINOR);
 
-        hdr.src_nid        = cpu_to_le64 (ksocknal_data.ksnd_ni->ni_nid);
+        hdr.src_nid        = cpu_to_le64 (ni->ni_nid);
         hdr.type           = cpu_to_le32 (PTL_MSG_HELLO);
         hdr.payload_length = cpu_to_le32 (nipaddrs * sizeof(*ipaddrs));
 
         hdr.msg.hello.type = cpu_to_le32 (conn->ksnc_type);
-        hdr.msg.hello.incarnation =
-                cpu_to_le64 (ksocknal_data.ksnd_incarnation);
+        hdr.msg.hello.incarnation = cpu_to_le64 (net->ksnn_incarnation);
 
         /* Receiver is eager */
         rc = ksocknal_lib_sock_write (sock, &hdr, sizeof(hdr));