]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
solaris-mtu-cleanup-20011005
authorNickolai Zeldovich <kolya@mit.edu>
Fri, 5 Oct 2001 21:44:35 +0000 (21:44 +0000)
committerDerrick Brashear <shadow@dementia.org>
Fri, 5 Oct 2001 21:44:35 +0000 (21:44 +0000)
This patch provides better MTU selection on Solaris, by
  actually going through the list of interfaces and picking
  the correct MTU, rather than assuming 1500.

  It also fixes a small bug in the server preference code,
  which wasn't checking for IPv6 interfaces, and if there
  were any IPv6 interface, it would believe all servers
  were on the local subnet.

src/afs/afs_server.c
src/rx/SOLARIS/rx_knet.c
src/rx/rx_kcommon.c
src/rx/rx_kcommon.h
src/rx/rx_misc.h

index c148ee4b6fa1042f420a6e0fbd8cded49669917b..f60691c498039f0e94d8b871e37e4749a4754c49 100644 (file)
@@ -1084,6 +1084,10 @@ static afs_SetServerPrefs(sa)
 
     if (sa) sa->sa_iprank= 0;
     for (ill = (struct ill_s *)*addr /*ill_g_headp*/; ill; ill = ill->ill_next ) {
+#ifdef AFS_SUN58_ENV
+       /* Make sure this is an IPv4 ILL */
+       if (ill->ill_isv6) continue;
+#endif
        for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next ) {
            subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
            subnetmask = ipif->ipif_net_mask;
index 9598b9179cb46da7aea27c46c2e198166510a046..d884bfc52c00d2477558915ada40478302d418e5 100644 (file)
@@ -27,8 +27,13 @@ RCSID("$Header$");
 #include "../sys/fcntl.h"
 #ifdef AFS_SUN58_ENV
 #include "../netinet/ip6.h"
+#define ipif_local_addr ipif_lcl_addr
+#ifndef V4_PART_OF_V6
+#define V4_PART_OF_V6(v6)       v6.s6_addr32[3]
+#endif
 #endif
 #include "../inet/ip.h"
+#include "../inet/ip_if.h"
 #include "../netinet/udp.h"
 
 /*
@@ -47,9 +52,137 @@ int (*sockfs_sosendmsg)
 int (*sockfs_sosetsockopt)
     (struct sonode *, int, int, void *, int) = NULL;
 
-int rxi_GetIFInfo()
+static afs_uint32 myNetAddrs[ADDRSPERSITE];
+static int myNetMTUs[ADDRSPERSITE];
+static int numMyNetAddrs = 0;
+
+int
+rxi_GetIFInfo()
 {
-    return 0;
+    int i = 0;
+    int different = 0;
+
+    ill_t *ill;
+    ipif_t *ipif;
+    int rxmtu, maxmtu;
+
+    int mtus[ADDRSPERSITE];
+    afs_uint32 addrs[ADDRSPERSITE];
+    afs_uint32 ifinaddr;
+
+    memset(mtus, 0, sizeof(mtus));
+    memset(addrs, 0, sizeof(addrs));
+
+    for (ill = ill_g_head; ill; ill = ill->ill_next) {
+#ifdef AFS_SUN58_ENV
+       /* Make sure this is an IPv4 ILL */
+       if (ill->ill_isv6) continue;
+#endif
+
+       /* Iterate over all the addresses on this ILL */
+       for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
+           if (i >= ADDRSPERSITE) break;
+
+           /* Ignore addresses which are down.. */
+           if (!(ipif->ipif_flags & IFF_UP)) continue;
+
+           /* Compute the Rx interface MTU */
+           rxmtu = (ipif->ipif_mtu - RX_IPUDP_SIZE);
+
+           ifinaddr = ntohl(ipif->ipif_local_addr);
+           if (myNetAddrs[i] != ifinaddr)
+               different++;
+
+           /* Copy interface MTU and address; adjust maxmtu */
+           mtus[i] = rxmtu;
+           rxmtu = rxi_AdjustIfMTU(rxmtu);
+           maxmtu = rxmtu * rxi_nRecvFrags + ((rxi_nRecvFrags-1) *
+                                              UDP_HDR_SIZE);
+           maxmtu = rxi_AdjustMaxMTU(rxmtu, maxmtu);
+           addrs[i] = ifinaddr;
+           i++;
+
+           if (ifinaddr != 0x7f000001 && maxmtu > rx_maxReceiveSize) {
+               rx_maxReceiveSize = MIN( RX_MAX_PACKET_SIZE, maxmtu);
+               rx_maxReceiveSize = MIN( rx_maxReceiveSize,
+                                        rx_maxReceiveSizeUser);
+           }
+       }
+    }
+
+    rx_maxJumboRecvSize = RX_HEADER_SIZE +
+                         rxi_nDgramPackets * RX_JUMBOBUFFERSIZE +
+                         (rxi_nDgramPackets-1) * RX_JUMBOHEADERSIZE;
+    rx_maxJumboRecvSize = MAX(rx_maxJumboRecvSize, rx_maxReceiveSize);
+
+    if (different) {
+       int j;
+
+       for (j = 0; j < i; j++) {
+           myNetMTUs[j] = mtus[j];
+           myNetAddrs[j] = addrs[j];
+       }
+    }
+
+    return different;
+}
+
+int
+rxi_FindIfMTU(addr)
+    afs_uint32 addr;
+{
+    ill_t *ill;
+    ipif_t *ipif;
+    afs_uint32 myAddr, netMask;
+    int match_value = 0;
+    int mtu = -1;
+
+    if (numMyNetAddrs == 0)
+       rxi_GetIFInfo();
+    myAddr = ntohl(addr);
+
+    if      (IN_CLASSA(myAddr)) netMask = IN_CLASSA_NET;
+    else if (IN_CLASSB(myAddr)) netMask = IN_CLASSB_NET;
+    else if (IN_CLASSC(myAddr)) netMask = IN_CLASSC_NET;
+    else                       netMask = 0;
+
+    for (ill = ill_g_head; ill; ill = ill->ill_next) {
+#ifdef AFS_SUN58_ENV
+       /* Make sure this is an IPv4 ILL */
+       if (ill->ill_isv6) continue;
+#endif
+
+       /* Iterate over all the addresses on this ILL */
+       for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
+           afs_uint32 thisAddr, subnetMask;
+           int thisMtu;
+
+           thisAddr   = ipif->ipif_local_addr;
+           subnetMask = ipif->ipif_net_mask;
+           thisMtu    = ipif->ipif_mtu;
+
+           if ((myAddr & netMask) == (thisAddr & netMask)) {
+               if ((myAddr & subnetMask) == (thisAddr & subnetMask)) {
+                   if (myAddr == thisAddr) {
+                       match_value = 4;
+                       mtu = thisMtu;
+                   }
+
+                   if (match_value < 3) {
+                       match_value = 3;
+                       mtu = thisMtu;
+                   }
+               }
+
+               if (match_value < 2) {
+                   match_value = 2;
+                   mtu = thisMtu;
+               }
+           }
+       }
+    }
+
+    return mtu;
 }
 
 /* rxi_NewSocket, rxi_FreeSocket and osi_NetSend are from the now defunct
index 53a57c5736e7bd06f871c369fed47c5f942dc398..8755fb31f4258ae95d888aac995071b738b4ad57 100644 (file)
@@ -343,6 +343,7 @@ register struct rx_peer *pp;
     u_short rxmtu;
     afs_int32 i, mtu;
 
+#ifndef AFS_SUN5_ENV
 #ifdef AFS_USERSPACE_IP_ADDR   
     i = rxi_Findcbi(pp->host);
     if (i == -1) {
@@ -402,6 +403,30 @@ register struct rx_peer *pp;
       pp->ifMTU = RX_REMOTE_PACKET_SIZE;
     }
 #endif/* else AFS_USERSPACE_IP_ADDR */
+#else /* AFS_SUN5_ENV */
+    mtu = rxi_FindIfMTU(pp->host);
+
+    if (mtu <= 0) {
+       pp->timeout.sec = 3;
+       /* pp->timeout.usec = 0; */
+       pp->ifMTU = RX_REMOTE_PACKET_SIZE;
+    } else {
+       pp->timeout.sec = 2;
+       /* pp->timeout.usec = 0; */
+       pp->ifMTU = MIN(RX_MAX_PACKET_SIZE, rx_MyMaxSendSize);
+    }
+
+    if (mtu > 0) {
+       /* Diminish the packet size to one based on the MTU given by
+        * the interface. */
+       if (mtu > (RX_IPUDP_SIZE + RX_HEADER_SIZE)) {
+           rxmtu = mtu - RX_IPUDP_SIZE;
+           if (rxmtu < pp->ifMTU) pp->ifMTU = rxmtu;
+       }
+    } else {   /* couldn't find the interface, so assume the worst */
+       pp->ifMTU = RX_REMOTE_PACKET_SIZE;
+    }
+#endif /* AFS_SUN5_ENV */
 #else /* ADAPT_MTU */
     pp->rateFlag = 2;   /* start timing after two full packets */
     pp->timeout.sec = 2;
index a11c14537c0dba1dcaca4e4cc89b2b3b1ae98284..92b2bc33265d8ba97a6f6d84b6d7b075b6992a64 100644 (file)
@@ -111,6 +111,7 @@ extern rxk_portRocks_t rxk_portRocks;
 
 extern struct osi_socket *rxk_NewSocket(short aport);
 extern struct ifnet *rxi_FindIfnet();
+extern int rxi_FindIfMTU();
 
 extern int rxk_initDone;
 
index 743a44a22139b947fbd5a7511973f5f95fdae075..1f66c25c8d020f3b3a9e7f11b92b25e3b9999c5b 100644 (file)
 #ifndef _RX_MISC_H_
 #define _RX_MISC_H_
 
-#ifndef        AFS_SUN5_ENV
 #define MISCMTU
 #define ADAPT_MTU
-#endif
 
-#if defined(AFS_SUN5_ENV) && !defined(KERNEL)
-#define MISCMTU
-#define ADAPT_MTU
+#if defined(AFS_SUN5_ENV)
 #include <sys/sockio.h>
 #include <sys/fcntl.h>
 #endif