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 c148ee4..f60691c 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 9598b91..d884bfc 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 53a57c5..8755fb3 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 a11c145..92b2bc3 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 743a44a..1f66c25 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