Make the Rx deadtime a tunable variable, either with a kernel debugger
[openafs.git] / src / afs / afs_server.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * Implements:
12  * afs_MarkServerUpOrDown
13  * afs_ServerDown
14  * afs_CountServers
15  * afs_CheckServers
16  * afs_FindServer
17  * afs_random
18  * afs_randomMod127
19  * afs_SortServers
20  * afsi_SetServerIPRank
21  * afs_GetServer
22  * afs_ActivateServer
23  * 
24  *
25  * Local:
26  * HaveCallBacksFrom
27  * CheckVLServer
28  * afs_SortOneServer
29  * afs_SetServerPrefs
30  * 
31  */
32 #include <afsconfig.h>
33 #include "afs/param.h"
34
35 RCSID("$Header$");
36
37 #include "afs/stds.h"
38 #include "afs/sysincludes.h"    /* Standard vendor system headers */
39
40 #if !defined(UKERNEL)
41 #include <net/if.h>
42 #include <netinet/in.h>
43
44 #ifdef AFS_SGI62_ENV
45 #include "h/hashing.h"
46 #endif
47 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN60_ENV)
48 #include <netinet/in_var.h>
49 #endif /* AFS_HPUX110_ENV */
50 #ifdef AFS_DARWIN60_ENV
51 #include <net/if_var.h>
52 #endif
53 #endif /* !defined(UKERNEL) */
54
55 #include "afsincludes.h"        /* Afs-based standard headers */
56 #include "afs/afs_stats.h"   /* afs statistics */
57
58 #if     defined(AFS_SUN56_ENV)
59 #include <inet/led.h>
60 #include <inet/common.h>
61 #if     defined(AFS_SUN58_ENV)
62 # include <netinet/ip6.h>
63 # define ipif_local_addr ipif_lcl_addr
64 #  ifndef V4_PART_OF_V6
65 #  define V4_PART_OF_V6(v6)       v6.s6_addr32[3]
66 #  endif
67 # endif
68 #include <inet/ip.h>
69 #endif
70
71 /* Exported variables */
72 afs_rwlock_t afs_xserver;               /* allocation lock for servers */
73 struct server *afs_setTimeHost=0;       /* last host we used for time */
74 struct server *afs_servers[NSERVERS];    /* Hashed by server`s uuid & 1st ip */
75 afs_rwlock_t afs_xsrvAddr;              /* allocation lock for srvAddrs */
76 struct srvAddr *afs_srvAddrs[NSERVERS];  /* Hashed by server's ip */
77
78
79 /* debugging aids - number of alloc'd server and srvAddr structs. */
80 int afs_reuseServers  = 0;
81 int afs_reuseSrvAddrs = 0;
82 int afs_totalServers  = 0;
83 int afs_totalSrvAddrs = 0;
84
85
86
87 static struct afs_stats_SrvUpDownInfo *
88 GetUpDownStats(struct server *srv)
89 {
90     struct afs_stats_SrvUpDownInfo *upDownP;
91     u_short fsport = AFS_FSPORT;
92
93     if (srv->cell)
94         fsport = srv->cell->fsport;
95
96     if (srv->addr->sa_portal == fsport)
97         upDownP = afs_stats_cmperf.fs_UpDown;
98     else
99         upDownP = afs_stats_cmperf.vl_UpDown;
100
101     if (srv->cell && afs_IsPrimaryCell(srv->cell))
102         return &upDownP[AFS_STATS_UPDOWN_IDX_SAME_CELL];
103     else
104         return &upDownP[AFS_STATS_UPDOWN_IDX_DIFF_CELL];
105 }
106
107
108 /*------------------------------------------------------------------------
109  * afs_MarkServerUpOrDown
110  *
111  * Description:
112  *      Mark the given server up or down, and track its uptime stats.
113  *
114  * Arguments:
115  *      a_serverP : Ptr to server record to fiddle with.
116  *      a_isDown  : Is the server is to be marked down?
117  *
118  * Returns:
119  *      Nothing.
120  *
121  * Environment:
122  *      The CM server structures must be write-locked.
123  *
124  * Side Effects:
125  *      As advertised.
126  *------------------------------------------------------------------------*/
127
128 void afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
129 {
130     register struct server *a_serverP = sa->server;
131     register struct srvAddr *sap;
132     osi_timeval_t currTime, *currTimeP;     /*Current time*/
133     afs_int32 downTime;                      /*Computed downtime, in seconds*/
134     struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record*/
135
136     /*
137      * If the server record is marked the same as the new status we've
138      * been fed, then there isn't much to be done.
139      */
140     if (( a_isDown &&  (sa->sa_flags & SRVADDR_ISDOWN)) || 
141         (!a_isDown && !(sa->sa_flags & SRVADDR_ISDOWN)))
142         return;
143
144     if (a_isDown) {
145         sa->sa_flags |= SRVADDR_ISDOWN;
146         for (sap = a_serverP->addr; sap; sap = sap->next_sa) {
147             if (!(sap->sa_flags & SRVADDR_ISDOWN)) {
148                 /* Not all ips are up so don't bother with the
149                  * server's up/down stats */
150                 return;
151             }
152         }    
153         /* 
154          * All ips are down we treat the whole server down
155          */
156         a_serverP->flags |= SRVR_ISDOWN;
157         /*
158          * If this was our time server, search for another time server
159          */
160         if (a_serverP == afs_setTimeHost)
161             afs_setTimeHost = 0;
162     } else {
163         sa->sa_flags &= ~SRVADDR_ISDOWN;
164         /* If any ips are up, the server is also marked up */
165         a_serverP->flags &= ~SRVR_ISDOWN;
166         for (sap = a_serverP->addr; sap; sap = sap->next_sa) {
167             if (sap->sa_flags & SRVADDR_ISDOWN) {
168                 /* Not all ips are up so don't bother with the
169                  * server's up/down stats */
170                 return;
171             }
172         }    
173     }
174 #ifndef AFS_NOSTATS
175     /*
176      * Compute the current time and which overall stats record is to be
177      * updated; we'll need them one way or another.
178      */
179     currTimeP = &currTime;
180     osi_GetuTime(currTimeP);
181
182     upDownP = GetUpDownStats(a_serverP);
183
184     if (a_isDown) {
185         /*
186          * Server going up -> down; remember the beginning of this
187          * downtime incident.
188          */
189         a_serverP->lastDowntimeStart = currTime.tv_sec;
190
191         (upDownP->numDownRecords)++;
192         (upDownP->numUpRecords)--;
193     } /*Server being marked down*/
194     else {
195         /*
196          * Server going down -> up; remember everything about this
197          * newly-completed downtime incident.
198          */
199         downTime = currTime.tv_sec - a_serverP->lastDowntimeStart;
200         (a_serverP->numDowntimeIncidents)++;
201         a_serverP->sumOfDowntimes += downTime;
202
203         (upDownP->numUpRecords)++;
204         (upDownP->numDownRecords)--;
205         (upDownP->numDowntimeIncidents)++;
206         if (a_serverP->numDowntimeIncidents == 1)
207             (upDownP->numRecordsNeverDown)--;
208         upDownP->sumOfDowntimes += downTime;
209         if ((upDownP->shortestDowntime == 0) ||
210             (downTime < upDownP->shortestDowntime))
211             upDownP->shortestDowntime = downTime;
212         if ((upDownP->longestDowntime == 0) ||
213             (downTime > upDownP->longestDowntime))
214             upDownP->longestDowntime = downTime;
215
216
217         if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET0)
218             (upDownP->downDurations[0])++;
219         else
220             if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET1)
221                 (upDownP->downDurations[1])++;
222         else
223             if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET2)
224                 (upDownP->downDurations[2])++;
225         else
226             if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET3)
227                 (upDownP->downDurations[3])++;
228         else
229             if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET4)
230                 (upDownP->downDurations[4])++;
231         else
232             if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET5)
233                 (upDownP->downDurations[5])++;
234         else
235             (upDownP->downDurations[6])++;
236
237     } /*Server being marked up*/
238 #endif
239 } /*MarkServerUpOrDown*/
240
241
242 void afs_ServerDown(struct srvAddr *sa)
243 {
244     register struct server *aserver = sa->server;
245
246     AFS_STATCNT(ServerDown);
247     if (aserver->flags & SRVR_ISDOWN || sa->sa_flags & SRVADDR_ISDOWN)
248         return;
249     afs_MarkServerUpOrDown(sa, SRVR_ISDOWN);
250     if (sa->sa_portal == aserver->cell->vlport)
251          print_internet_address("afs: Lost contact with volume location server ",
252                                sa, "", 1);
253     else
254          print_internet_address("afs: Lost contact with file server ", sa, "", 1);
255
256 } /*ServerDown*/
257
258
259 /* return true if we have any callback promises from this server */
260 static int HaveCallBacksFrom(struct server *aserver)
261 {
262     register afs_int32 now;
263     register int i;
264     register struct vcache *tvc;
265
266     AFS_STATCNT(HaveCallBacksFrom);
267     now = osi_Time();       /* for checking for expired callbacks */
268     for(i=0;i<VCSIZE;i++) { /* for all guys in the hash table */
269         for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
270             /*
271              * Check to see if this entry has an unexpired callback promise
272              * from the required host
273              */
274             if (aserver == tvc->callback && tvc->cbExpires >= now
275                 && ((tvc->states & CRO) == 0))
276                 return 1;
277         }
278     }
279     return 0;
280
281 } /*HaveCallBacksFrom*/
282
283
284 static void CheckVLServer(register struct srvAddr *sa, struct vrequest *areq)
285 {
286     register struct server *aserver = sa->server;
287     register struct conn *tc;
288     register afs_int32 code;
289
290     AFS_STATCNT(CheckVLServer);
291     /* Ping dead servers to see if they're back */
292     if (!((aserver->flags & SRVR_ISDOWN) || (sa->sa_flags & SRVADDR_ISDOWN)) || (aserver->flags & SRVR_ISGONE))
293         return;
294     if (!aserver->cell)
295         return; /* can't do much */
296
297     tc = afs_ConnByHost(aserver, aserver->cell->vlport, 
298                         aserver->cell->cellNum, areq, 1, SHARED_LOCK);
299     if (!tc)
300         return;
301     rx_SetConnDeadTime(tc->id, 3);
302
303     RX_AFS_GUNLOCK();
304     code = VL_ProbeServer(tc->id);
305     RX_AFS_GLOCK();
306     rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
307     afs_PutConn(tc, SHARED_LOCK);
308     /*
309      * If probe worked, or probe call not yet defined (for compatibility
310      * with old vlsevers), then we treat this server as running again
311      */
312     if (code == 0 || (code <= -450 && code >= -470)) {
313         if (tc->srvr == sa) {
314             afs_MarkServerUpOrDown(sa, 0);
315             print_internet_address("afs: volume location server ",
316                                    sa, " is back up", 2);
317         }
318     }
319
320 } /*CheckVLServer*/
321
322
323 #ifndef AFS_MINCHANGE   /* So that some can increase it in param.h */
324 #define AFS_MINCHANGE 2         /* min change we'll bother with */
325 #endif
326 #ifndef AFS_MAXCHANGEBACK
327 #define AFS_MAXCHANGEBACK 10    /* max seconds we'll set a clock back at once */
328 #endif
329
330
331 /*------------------------------------------------------------------------
332  * EXPORTED afs_CountServers
333  *
334  * Description:
335  *      Originally meant to count the number of servers and determining
336  *      up/down info, this routine will now simply sum up all of the
337  *      server record ages.  All other up/down information is kept on the
338  *      fly.
339  *
340  * Arguments:
341  *      None.
342  *
343  * Returns:
344  *      Nothing.
345  *
346  * Environment:
347  *      This routine locks afs_xserver for write for the duration.
348  *
349  * Side Effects:
350  *      Set CM perf stats field sumOfRecordAges for all server record
351  *      entries.
352  *------------------------------------------------------------------------*/
353
354 void afs_CountServers(void)
355 {
356     int currIdx;                                /*Curr idx into srv table*/
357     struct server *currSrvP;                    /*Ptr to curr server record*/
358     afs_int32 currChainLen;                             /*Length of curr hash chain*/
359     osi_timeval_t currTime;                     /*Current time*/
360     osi_timeval_t *currTimeP;                   /*Ptr to above*/
361     afs_int32 srvRecordAge;                             /*Age of server record, in secs*/
362     struct afs_stats_SrvUpDownInfo *upDownP;    /*Ptr to current up/down
363                                                   info being manipulated*/
364
365     /*
366      * Write-lock the server table so we don't get any interference.
367      */
368     ObtainReadLock(&afs_xserver);
369
370     /*
371      * Iterate over each hash index in the server table, walking down each
372      * chain and tallying what we haven't computed from the records there on
373      * the fly.  First, though, initialize the tallies that will change.
374      */
375     afs_stats_cmperf.srvMaxChainLength = 0;
376
377     afs_stats_cmperf.fs_UpDown[0].sumOfRecordAges     = 0;
378     afs_stats_cmperf.fs_UpDown[0].ageOfYoungestRecord = 0;
379     afs_stats_cmperf.fs_UpDown[0].ageOfOldestRecord   = 0;
380     memset((char *) afs_stats_cmperf.fs_UpDown[0].downIncidents, 0, AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
381
382     afs_stats_cmperf.fs_UpDown[1].sumOfRecordAges     = 0;
383     afs_stats_cmperf.fs_UpDown[1].ageOfYoungestRecord = 0;
384     afs_stats_cmperf.fs_UpDown[1].ageOfOldestRecord   = 0;
385     memset((char *) afs_stats_cmperf.fs_UpDown[1].downIncidents, 0, AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
386
387     afs_stats_cmperf.vl_UpDown[0].sumOfRecordAges     = 0;
388     afs_stats_cmperf.vl_UpDown[0].ageOfYoungestRecord = 0;
389     afs_stats_cmperf.vl_UpDown[0].ageOfOldestRecord   = 0;
390     memset((char *) afs_stats_cmperf.vl_UpDown[0].downIncidents, 0, AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
391
392     afs_stats_cmperf.vl_UpDown[1].sumOfRecordAges     = 0;
393     afs_stats_cmperf.vl_UpDown[1].ageOfYoungestRecord = 0;
394     afs_stats_cmperf.vl_UpDown[1].ageOfOldestRecord   = 0;
395     memset((char *) afs_stats_cmperf.vl_UpDown[1].downIncidents, 0, AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
396
397     /*
398      * Compute the current time, used to figure out server record ages.
399      */
400     currTimeP = &currTime;
401     osi_GetuTime(currTimeP);
402
403     /*
404      * Sweep the server hash table, tallying all we need to know.
405      */
406     for (currIdx = 0; currIdx < NSERVERS; currIdx++) {
407         currChainLen = 0;
408         for (currSrvP = afs_servers[currIdx]; currSrvP; currSrvP = currSrvP->next) {
409             /*
410              * Bump the current chain length.
411              */
412             currChainLen++;
413
414             /*
415              * Any further tallying for this record will only be done if it has
416              * been activated. 
417              */
418             if ( (currSrvP->flags & AFS_SERVER_FLAG_ACTIVATED) &&
419                   currSrvP->addr && currSrvP->cell ) {
420
421                 /*
422                  * Compute the current server record's age, then remember it
423                  * in the appropriate places.
424                  */
425                 srvRecordAge = currTime.tv_sec - currSrvP->activationTime;
426                 upDownP = GetUpDownStats(currSrvP);
427                 upDownP->sumOfRecordAges += srvRecordAge;
428                 if ((upDownP->ageOfYoungestRecord == 0) ||
429                     (srvRecordAge < upDownP->ageOfYoungestRecord))
430                     upDownP->ageOfYoungestRecord = srvRecordAge;
431                 if ((upDownP->ageOfOldestRecord == 0) ||
432                     (srvRecordAge > upDownP->ageOfOldestRecord))
433                     upDownP->ageOfOldestRecord = srvRecordAge;
434
435                 if (currSrvP->numDowntimeIncidents <=
436                     AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET0)
437                     (upDownP->downIncidents[0])++;
438                 else
439                     if (currSrvP->numDowntimeIncidents <=
440                         AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET1)
441                         (upDownP->downIncidents[1])++;
442                 else
443                     if (currSrvP->numDowntimeIncidents <=
444                         AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET2)
445                         (upDownP->downIncidents[2])++;
446                 else
447                     if (currSrvP->numDowntimeIncidents <=
448                         AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET3)
449                         (upDownP->downIncidents[3])++;
450                 else
451                     if (currSrvP->numDowntimeIncidents <=
452                         AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET4)
453                         (upDownP->downIncidents[4])++;
454                 else
455                     (upDownP->downIncidents[5])++;
456
457
458             } /*Current server has been active*/
459         } /*Walk this chain*/
460
461         /*
462          * Before advancing to the next chain, remember facts about this one.
463          */
464         if (currChainLen > afs_stats_cmperf.srvMaxChainLength) {
465             /*
466              * We beat out the former champion (which was initially set to 0
467              * here).  Mark down the new winner, and also remember if it's an
468              * all-time winner.
469              */
470             afs_stats_cmperf.srvMaxChainLength = currChainLen;
471             if (currChainLen > afs_stats_cmperf.srvMaxChainLengthHWM)
472                 afs_stats_cmperf.srvMaxChainLengthHWM = currChainLen;
473         } /*Update chain length maximum*/
474     } /*For each hash chain*/
475
476     /*
477      * We're done.  Unlock the server table before returning to our caller.
478      */
479     ReleaseReadLock(&afs_xserver);
480
481 } /*afs_CountServers*/
482
483
484 /* check down servers (if adown), or running servers (if !adown) */
485 void afs_CheckServers(int adown, struct cell *acellp)
486 {
487     struct vrequest treq;
488     struct server *ts;
489     struct srvAddr *sa;
490     struct conn *tc;
491     afs_int32 i, j;
492     afs_int32 code;
493     afs_int32 start, end, delta;
494     osi_timeval_t tv;
495     int setTimer;
496     struct unixuser *tu;
497     char tbuffer[CVBS];
498     int srvAddrCount;
499     struct srvAddr **addrs;
500     XSTATS_DECLS;
501
502     AFS_STATCNT(afs_CheckServers);
503     if ((code = afs_InitReq(&treq, &afs_osi_cred))) return;
504     ObtainReadLock(&afs_xserver);  /* Necessary? */
505     ObtainReadLock(&afs_xsrvAddr);      
506
507     srvAddrCount = 0;
508     for (i=0;i<NSERVERS;i++) {
509         for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) { 
510             srvAddrCount++;
511         }
512     }
513
514     addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
515     j = 0;
516     for (i=0;i<NSERVERS;i++) {
517         for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) { 
518             if (j >= srvAddrCount) break;
519             addrs[j++] = sa;
520         }
521     }
522
523     ReleaseReadLock(&afs_xsrvAddr);     
524     ReleaseReadLock(&afs_xserver);
525
526     for (i=0; i<j; i++) {
527         sa = addrs[i];
528         ts = sa->server;
529         if (!ts)
530             continue;
531
532         /* See if a cell to check was specified.  If it is spec'd and not
533          * this server's cell, just skip the server.
534          */
535         if (acellp && acellp != ts->cell)
536             continue;
537
538         if ((!adown && (sa->sa_flags & SRVADDR_ISDOWN)) ||
539             (adown && !(sa->sa_flags & SRVADDR_ISDOWN)))
540             continue;
541
542         /* check vlserver with special code */
543         if (sa->sa_portal == AFS_VLPORT) {
544             CheckVLServer(sa, &treq);
545             continue;
546         }
547
548         if (!ts->cell) /* not really an active server, anyway, it must */
549             continue;  /* have just been added by setsprefs */ 
550
551         /* get a connection, even if host is down; bumps conn ref count */
552         tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
553         tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
554                           1/*force*/, 1/*create*/, SHARED_LOCK);
555         afs_PutUser(tu, SHARED_LOCK);
556         if (!tc) continue;
557
558         if ((sa->sa_flags & SRVADDR_ISDOWN) || HaveCallBacksFrom(ts) ||
559             (tc->srvr->server == afs_setTimeHost)) {
560             if (sa->sa_flags & SRVADDR_ISDOWN) {
561                 rx_SetConnDeadTime(tc->id, 3);
562                 setTimer = 1;
563             } else {
564                 setTimer = 0;
565             }
566
567             XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETTIME);
568             start = osi_Time();         /* time the gettimeofday call */
569             RX_AFS_GUNLOCK();
570             code = RXAFS_GetTime(tc->id, (afs_int32 *)&tv.tv_sec, (afs_int32 *)&tv.tv_usec);
571             RX_AFS_GLOCK();
572             end = osi_Time();
573             XSTATS_END_TIME;
574             /*
575              * If we're supposed to set the time, and the call worked
576              * quickly (same second response) and this is the host we
577              * use for the time and the time is really different, then
578              * really set the time
579              */
580             if (code == 0 && start == end && afs_setTime != 0 &&
581                 (tc->srvr->server == afs_setTimeHost ||
582                 /* Sync only to a server in the local cell */
583                 (afs_setTimeHost == (struct server *)0 &&
584                  afs_IsPrimaryCell(ts->cell)))) {
585
586                 char msgbuf[90];  /* strlen("afs: setting clock...") + slop */
587                 /* set the time */
588                 delta = end - tv.tv_sec;   /* how many secs fast we are */
589                 /* see if clock has changed enough to make it worthwhile */
590                 if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) {
591                     if (delta > AFS_MAXCHANGEBACK) {
592                         /* setting clock too far back, just do it a little */
593                         tv.tv_sec = end - AFS_MAXCHANGEBACK;
594                     }
595                     afs_osi_SetTime(&tv);
596                     if (delta > 0) {
597                         strcpy(msgbuf, "afs: setting clock back ");
598                         if (delta > AFS_MAXCHANGEBACK) {
599                             afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], AFS_MAXCHANGEBACK));
600                             afs_strcat(msgbuf, " seconds (of ");
601                             afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], delta - AFS_MAXCHANGEBACK));
602                             afs_strcat(msgbuf, ", via ");
603                             print_internet_address(msgbuf, sa, "); clock is still fast.", 0);
604                         } else {
605                             afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], delta));
606                             afs_strcat(msgbuf, " seconds (via ");
607                             print_internet_address(msgbuf, sa, ").", 0);
608                         }
609                     } else {
610                         strcpy(msgbuf, "afs: setting clock ahead ");
611                         afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], -delta));
612                         afs_strcat(msgbuf, " seconds (via ");
613                         print_internet_address(msgbuf, sa, ").", 0);
614                     }
615                 }
616                 afs_setTimeHost = tc->srvr->server;
617             }
618             if (setTimer)
619                 rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
620             if (code >= 0 && (sa->sa_flags & SRVADDR_ISDOWN) && (tc->srvr == sa)) {
621                 /* server back up */
622                 print_internet_address("afs: file server ", sa, " is back up", 2);
623
624                 ObtainWriteLock(&afs_xserver, 244);
625                 ObtainWriteLock(&afs_xsrvAddr, 245);    
626                 afs_MarkServerUpOrDown(sa, 0);
627                 ReleaseWriteLock(&afs_xsrvAddr);
628                 ReleaseWriteLock(&afs_xserver);
629
630                 if (afs_waitForeverCount) {
631                     afs_osi_Wakeup(&afs_waitForever);
632                 }
633             } else {
634                 if (code < 0) {
635                     /* server crashed */
636                     afs_ServerDown(sa);
637                     ForceNewConnections(sa);  /* multi homed clients */
638                 }
639             }
640         }
641
642         afs_PutConn(tc, SHARED_LOCK);   /* done with it now */
643     } /* Outer loop over addrs */
644
645     afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
646
647 } /*afs_CheckServers*/
648
649
650 /* find a server structure given the host address */
651 struct server *afs_FindServer (afs_int32 aserver, ushort aport,
652                                afsUUID *uuidp, afs_int32 locktype)
653 {
654     struct server *ts;
655     struct srvAddr *sa;
656     int i;
657
658     AFS_STATCNT(afs_FindServer);
659     if (uuidp) {
660         i = afs_uuid_hash(uuidp) % NSERVERS;
661         for (ts = afs_servers[i]; ts; ts = ts->next) {
662             if ( (ts->flags & SRVR_MULTIHOMED) &&
663                  (memcmp((char *)uuidp, (char *)&ts->sr_uuid, sizeof(*uuidp)) == 0) &&
664                  (!ts->addr || (ts->addr->sa_portal == aport)) )
665                 return ts;
666         }
667     } else {
668         i = SHash(aserver);
669         for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
670             if ((sa->sa_ip == aserver) && (sa->sa_portal == aport)) {
671               return sa->server;
672             }
673         }
674     }
675     return NULL;
676
677 } /*afs_FindServer*/
678
679
680 /* some code for creating new server structs and setting preferences follows
681  * in the next few lines...
682  */
683
684 #define MAXDEFRANK 60000
685 #define DEFRANK    40000
686
687 /* Random number generator and constants from KnuthV2 2d ed, p170 */
688
689 /* Rules:
690    X = (aX + c) % m
691    m is a power of two 
692    a % 8 is 5
693    a is 0.73m  should be 0.01m .. 0.99m
694    c is more or less immaterial.  1 or a is suggested.
695   
696 NB:  LOW ORDER BITS are not very random.  To get small random numbers,
697      treat result as <1, with implied binary point, and multiply by 
698      desired modulus.
699 NB:  Has to be unsigned, since shifts on signed quantities may preserve
700      the sign bit.
701 */
702 /* added rxi_getaddr() to try to get as much initial randomness as 
703    possible, since at least one customer reboots ALL their clients 
704    simultaneously -- so osi_Time is bound to be the same on some of the
705    clients.  This is probably OK, but I don't want to see too much of it.
706 */
707
708 #define ranstage(x)     (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
709
710 unsigned int afs_random(void)
711 {
712     static afs_int32 state = 0;
713     register int i;
714
715     AFS_STATCNT(afs_random);
716     if (!state) {
717         osi_timeval_t t;
718         osi_GetTime(&t);
719         /*
720          * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
721          * bits are in a tv_usec
722          */
723         state = (t.tv_usec & (~0 << 4) ) + (rxi_getaddr() & 0xff); 
724         state += (t.tv_sec & 0xff);
725         for (i=0;i<30;i++) {
726             ranstage(state);
727         }
728     }
729
730     ranstage(state);
731     return (state);
732
733 } /*afs_random*/
734
735 /* returns int 0..14 using the high bits of a pseudo-random number instead of
736    the low bits, as the low bits are "less random" than the high ones...
737    slight roundoff error exists, an excercise for the reader.
738    need to multiply by something with lots of ones in it, so multiply by 
739    8 or 16 is right out.
740  */
741 int afs_randomMod15(void)
742 {
743 afs_uint32 temp;
744
745 temp = afs_random() >> 4;
746 temp = (temp *15) >> 28;
747
748 return temp;
749 }
750
751 int afs_randomMod127(void)
752 {
753 afs_uint32 temp;
754
755 temp = afs_random() >> 7;
756 temp = (temp *127) >> 25;
757
758 return temp;
759 }
760
761 /* afs_SortOneServer()
762  * Sort all of the srvAddrs, of a server struct, by rank from low to high.
763  */
764 void afs_SortOneServer(struct server *asp)
765 {
766    struct srvAddr **rootsa, *lowsa, *tsa, *lowprev;
767    int lowrank, rank;
768       
769    for (rootsa=&(asp->addr); *rootsa; rootsa=&(lowsa->next_sa)) {
770       lowprev = NULL;
771       lowsa   = *rootsa;             /* lowest sa is the first one */
772       lowrank = lowsa->sa_iprank;
773
774       for (tsa=*rootsa; tsa->next_sa; tsa=tsa->next_sa) {
775          rank = tsa->next_sa->sa_iprank;
776          if (rank < lowrank) {
777             lowprev = tsa;
778             lowsa   = tsa->next_sa;
779             lowrank = lowsa->sa_iprank;
780          }
781       }
782       if (lowprev) { /* found one lower, so rearrange them */
783          lowprev->next_sa = lowsa->next_sa;
784          lowsa->next_sa   = *rootsa;
785          *rootsa          = lowsa;
786       }
787    }
788 }
789     
790 /* afs_SortServer()
791  * Sort the pointer to servers by the server's rank (its lowest rank).
792  * It is assumed that the server already has its IP addrs sorted (the
793  * first being its lowest rank: afs_GetServer() calls afs_SortOneServer()).
794  */
795 void afs_SortServers(struct server *aservers[], int count)
796 {
797     struct server *ts;
798     int i, j, low;
799
800     AFS_STATCNT(afs_SortServers);
801
802     for (i=0; i<count; i++) {
803        if (!aservers[i]) break;
804        for (low=i,j=i+1; j<=count; j++) {
805            if ((!aservers[j]) || (!aservers[j]->addr)) 
806                break;
807            if ((!aservers[low]) || (!aservers[low]->addr))
808                break;
809            if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
810                low = j;
811            }
812        }
813        if (low != i) {
814           ts = aservers[i]; 
815           aservers[i] = aservers[low];
816           aservers[low] = ts;
817        }
818     }
819 } /*afs_SortServers*/
820
821 /* afs_SetServerPrefs is rather system-dependent.  It pokes around in kernel
822    data structures to determine what the local IP addresses and subnet masks 
823    are in order to choose which server(s) are on the local subnet.
824
825    As I see it, there are several cases:
826    1. The server address is one of this host's local addresses.  In this case
827           this server is to be preferred over all others.
828    2. The server is on the same subnet as one of the this host's local
829       addresses.  (ie, an odd-sized subnet, not class A,B,orC)
830    3. The server is on the same net as this host (class A,B or C)
831    4. The server is on a different logical subnet or net than this host, but
832    this host is a 'metric 0 gateway' to it.  Ie, two address-spaces share
833    one physical medium.
834    5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the 
835    server.
836    6. This host and the server are disjoint.
837
838    That is a rough order of preference.  If a point-to-point link has a high
839    metric, I'm assuming that it is a very slow link, and putting it at the 
840    bottom of the list (at least until RX works better over slow links).  If 
841    its metric is 1, I'm assuming that it's relatively fast (T1) and putting 
842    it ahead of #6.
843    It's not easy to check for case #4, so I'm ignoring it for the time being.
844
845    BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
846    That could be used to prefer certain servers fairly easily.  Maybe some 
847    other time...
848
849    NOTE: this code is very system-dependent, and very dependent on the TCP/IP
850    protocols (well, addresses that are stored in uint32s, at any rate).
851  */
852
853 #define IA_DST(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_dstaddr))
854 #define IA_BROAD(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
855
856 /* SA2ULONG takes a sockaddr_in, not a sockaddr (same thing, just cast it!) */
857 #define SA2ULONG(sa) ((sa)->sin_addr.s_addr)
858 #define TOPR 5000
859 #define HI  20000
860 #define MED 30000
861 #define LO DEFRANK
862 #define PPWEIGHT 4096
863
864 #define USEIFADDR
865
866  
867 #if     defined(AFS_SUN5_ENV) && ! defined(AFS_SUN56_ENV)
868 #include <inet/common.h>
869 /* IP interface structure, one per local address */
870 typedef struct ipif_s {                 /**/
871         struct ipif_s   * ipif_next;
872         struct ill_s    * ipif_ill;     /* Back pointer to our ill */
873         long    ipif_id;                /* Logical unit number */
874         u_int   ipif_mtu;               /* Starts at ipif_ill->ill_max_frag */
875         afs_int32       ipif_local_addr;        /* Local IP address for this if. */
876         afs_int32       ipif_net_mask;          /* Net mask for this interface. */
877         afs_int32       ipif_broadcast_addr;    /* Broadcast addr for this interface. */
878         afs_int32       ipif_pp_dst_addr;       /* Point-to-point dest address. */
879         u_int   ipif_flags;             /* Interface flags. */
880         u_int   ipif_metric;            /* BSD if metric, for compatibility. */
881         u_int   ipif_ire_type;          /* LOCAL or LOOPBACK */
882         mblk_t  * ipif_arp_down_mp;     /* Allocated at time arp comes up to
883                                          * prevent awkward out of mem condition
884                                          * later
885                                          */
886         mblk_t  * ipif_saved_ire_mp;    /* Allocated for each extra IRE_SUBNET/
887                                          * RESOLVER on this interface so that
888                                          * they can survive ifconfig down.
889                                          */
890         /*
891          * The packet counts in the ipif contain the sum of the
892          * packet counts in dead IREs that were affiliated with
893          * this ipif.
894          */
895         u_long  ipif_fo_pkt_count;      /* Forwarded thru our dead IREs */
896         u_long  ipif_ib_pkt_count;      /* Inbound packets for our dead IREs */
897         u_long  ipif_ob_pkt_count;      /* Outbound packets to our dead IREs */
898         unsigned int
899                 ipif_multicast_up : 1,  /* We have joined the allhosts group */
900                 : 0;
901 } ipif_t;
902
903 typedef struct ipfb_s {                 /**/
904         struct ipf_s    * ipfb_ipf;     /* List of ... */
905         kmutex_t        ipfb_lock;      /* Protect all ipf in list */
906 } ipfb_t;
907
908 typedef struct ilm_s {                  /**/
909         afs_int32               ilm_addr;
910         int             ilm_refcnt;
911         u_int           ilm_timer;      /* IGMP */
912         struct ipif_s   * ilm_ipif;     /* Back pointer to ipif */
913         struct ilm_s    * ilm_next;     /* Linked list for each ill */
914 } ilm_t;
915
916 typedef struct ill_s {                  /**/
917         struct  ill_s   * ill_next;     /* Chained in at ill_g_head. */
918         struct  ill_s   ** ill_ptpn;    /* Pointer to previous next. */
919         queue_t * ill_rq;               /* Read queue. */
920         queue_t * ill_wq;               /* Write queue. */
921
922         int     ill_error;              /* Error value sent up by device. */
923
924         ipif_t  * ill_ipif;             /* Interface chain for this ILL. */
925         u_int   ill_ipif_up_count;      /* Number of IPIFs currently up. */
926         u_int   ill_max_frag;           /* Max IDU. */
927         char    * ill_name;             /* Our name. */
928         u_int   ill_name_length;        /* Name length, incl. terminator. */
929         u_int   ill_subnet_type;        /* IRE_RESOLVER or IRE_SUBNET. */
930         u_int   ill_ppa;                /* Physical Point of Attachment num. */
931         u_long  ill_sap;
932         int     ill_sap_length;         /* Including sign (for position) */
933         u_int   ill_phys_addr_length;   /* Excluding the sap. */
934         mblk_t  * ill_frag_timer_mp;    /* Reassembly timer state. */
935         ipfb_t  * ill_frag_hash_tbl;    /* Fragment hash list head. */
936
937         queue_t * ill_bind_pending_q;   /* Queue waiting for DL_BIND_ACK. */
938         ipif_t  * ill_ipif_pending;     /* IPIF waiting for DL_BIND_ACK. */
939
940         /* ill_hdr_length and ill_hdr_mp will be non zero if
941          * the underlying device supports the M_DATA fastpath
942          */
943         int     ill_hdr_length;
944
945         ilm_t   * ill_ilm;              /* Multicast mebership for lower ill */
946
947         /* All non-nil cells between 'ill_first_mp_to_free' and
948          * 'ill_last_mp_to_free' are freed in ill_delete.
949          */
950 #define ill_first_mp_to_free    ill_hdr_mp
951         mblk_t  * ill_hdr_mp;           /* Contains fastpath template */
952         mblk_t  * ill_bcast_mp;         /* DLPI header for broadcasts. */
953         mblk_t  * ill_bind_pending;     /* T_BIND_REQ awaiting completion. */
954         mblk_t  * ill_resolver_mp;      /* Resolver template. */
955         mblk_t  * ill_attach_mp;
956         mblk_t  * ill_bind_mp;
957         mblk_t  * ill_unbind_mp;
958         mblk_t  * ill_detach_mp;
959 #define ill_last_mp_to_free     ill_detach_mp
960
961         u_int
962                 ill_frag_timer_running : 1,
963                 ill_needs_attach : 1,
964                 ill_is_ptp : 1,
965                 ill_priv_stream : 1,
966                 ill_unbind_pending : 1,
967
968                 ill_pad_to_bit_31 : 27;
969         MI_HRT_DCL(ill_rtime)
970         MI_HRT_DCL(ill_rtmp)
971 } ill_t;
972 #endif
973
974 #ifdef AFS_USERSPACE_IP_ADDR
975 #ifndef afs_min
976 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
977 #endif
978 /*
979  * The IP addresses and ranks are determined by afsd (in user space) and
980  * passed into the kernel at startup time through the AFSOP_ADVISEADDR
981  * system call. These are stored in the data structure 
982  * called 'afs_cb_interface'. 
983  *
984  * struct srvAddr *sa;         remote server
985  * afs_int32 addr;                one of my local addr in net order
986  * afs_uint32 subnetmask;         subnet mask of local addr in net order
987  *
988  */
989 int afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr, afs_uint32 subnetmask)
990 {
991    afs_uint32 myAddr, myNet, mySubnet, netMask;
992    afs_uint32 serverAddr ; 
993
994    myAddr = ntohl(addr);          /* one of my IP addr in host order */
995    serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
996    subnetmask = ntohl(subnetmask);/* subnet mask in host order */
997
998    if      ( IN_CLASSA(myAddr) ) netMask = IN_CLASSA_NET;
999    else if ( IN_CLASSB(myAddr) ) netMask = IN_CLASSB_NET;
1000    else if ( IN_CLASSC(myAddr) ) netMask = IN_CLASSC_NET;
1001    else                          netMask = 0;
1002
1003    myNet    =  myAddr & netMask;
1004    mySubnet =  myAddr & subnetmask;
1005
1006    if ( (serverAddr & netMask ) == myNet ) {
1007       if ( (serverAddr & subnetmask ) == mySubnet) {
1008          if ( serverAddr == myAddr ) {    /* same machine */
1009            sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1010          } else {                           /* same subnet */
1011             sa->sa_iprank = afs_min(sa->sa_iprank, HI);
1012          }
1013       } else {                               /* same net */
1014          sa->sa_iprank = afs_min(sa->sa_iprank, MED);
1015       }
1016    }
1017 }
1018 #else /* AFS_USERSPACE_IP_ADDR */
1019 #if (! defined(AFS_SUN5_ENV)) && !defined(AFS_DARWIN60_ENV) && defined(USEIFADDR)
1020 void afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
1021 {
1022     struct sockaddr_in *sin;
1023     int t;
1024     
1025     if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
1026         if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
1027             sin=IA_SIN(ifa);
1028             if ( SA2ULONG(sin) == ntohl(sa->sa_ip)) {   /* ie, ME!!!  */
1029                 sa->sa_iprank = TOPR;
1030             } else { 
1031                 t = HI + ifa->ia_ifp->if_metric; /* case #2 */
1032                 if (sa->sa_iprank > t)
1033                     sa->sa_iprank = t;
1034             }
1035         } else {
1036             t = MED + ifa->ia_ifp->if_metric;/* case #3 */
1037             if (sa->sa_iprank > t)
1038                 sa->sa_iprank = t;
1039         }
1040     }
1041 #ifdef  IFF_POINTTOPOINT
1042     /* check for case #4 -- point-to-point link */
1043     if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT) &&
1044         (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
1045         if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED)/PPWEIGHT) 
1046             t = MAXDEFRANK;
1047         else 
1048             t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
1049         if (sa->sa_iprank > t)
1050             sa->sa_iprank = t;
1051     }
1052 #endif /* IFF_POINTTOPOINT */
1053 }
1054 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR)*/
1055 #if defined(AFS_DARWIN60_ENV) && defined(USEIFADDR)
1056 #ifndef afs_min
1057 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1058 #endif
1059 void
1060 afsi_SetServerIPRank(sa, ifa)
1061     struct srvAddr *sa;
1062     struct ifaddr *ifa;
1063 {
1064     struct sockaddr_in *sin;
1065     int t;
1066     
1067    afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
1068    afs_uint32 serverAddr ; 
1069
1070    if (ifa->ifa_addr->sa_family != AF_INET)
1071       return;
1072    sin=(struct sockaddr_in *)ifa->ifa_addr;
1073    myAddr = ntohl(sin->sin_addr.s_addr);   /* one of my IP addr in host order */
1074    serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1075    sin=(struct sockaddr_in *)ifa->ifa_netmask;
1076    subnetmask = ntohl(sin->sin_addr.s_addr);/* subnet mask in host order */
1077    sin=(struct sockaddr_in *)ifa->ifa_dstaddr;
1078    if (sin)
1079       myDstaddr=sin->sin_addr.s_addr;
1080
1081    if      ( IN_CLASSA(myAddr) ) netMask = IN_CLASSA_NET;
1082    else if ( IN_CLASSB(myAddr) ) netMask = IN_CLASSB_NET;
1083    else if ( IN_CLASSC(myAddr) ) netMask = IN_CLASSC_NET;
1084    else                          netMask = 0;
1085
1086    myNet    =  myAddr & netMask;
1087    mySubnet =  myAddr & subnetmask;
1088
1089    if ( (serverAddr & netMask ) == myNet ) {
1090       if ( (serverAddr & subnetmask ) == mySubnet) {
1091          if ( serverAddr == myAddr ) {    /* same machine */
1092            sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1093          } else {                           /* same subnet */
1094             sa->sa_iprank = afs_min(sa->sa_iprank, HI + ifa->ifa_metric);
1095          }
1096       } else {                               /* same net */
1097          sa->sa_iprank = afs_min(sa->sa_iprank, MED + ifa->ifa_metric);
1098       }
1099    }
1100 #ifdef  IFF_POINTTOPOINT
1101     /* check for case #4 -- point-to-point link */
1102     if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT) &&
1103         (myDstaddr == serverAddr))) {
1104         if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED)/PPWEIGHT) 
1105             t = MAXDEFRANK;
1106         else 
1107             t = MED + (PPWEIGHT << ifa->->ifa_metric);
1108         if (sa->sa_iprank > t)
1109             sa->sa_iprank = t;
1110     }
1111 #endif /* IFF_POINTTOPOINT */
1112 }
1113 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR)*/
1114 #endif /* else AFS_USERSPACE_IP_ADDR */
1115
1116 #ifdef AFS_SGI62_ENV
1117 static int
1118 afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1119                 caddr_t arg2)
1120 {
1121    afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr*)h);
1122    return 0; /* Never match, so we enumerate everyone */
1123 }
1124 #endif /* AFS_SGI62_ENV */
1125
1126 static int afs_SetServerPrefs(struct srvAddr *sa)
1127 {
1128 #if     defined(AFS_USERSPACE_IP_ADDR)
1129     int i;
1130
1131     sa->sa_iprank = LO;
1132     for (i=0; i<afs_cb_interface.numberOfInterfaces; i++) {
1133        afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1134                                 afs_cb_interface.subnetmask[i]);
1135     }
1136 #else   /* AFS_USERSPACE_IP_ADDR */
1137 #if     defined(AFS_SUN5_ENV)
1138     extern struct ill_s *ill_g_headp;
1139     ill_t *ill;
1140     ipif_t * ipif;
1141     int subnet, subnetmask, net, netmask;
1142     long *addr = (long *) ill_g_headp;
1143
1144     if (sa) sa->sa_iprank= 0;
1145     for (ill = (struct ill_s *)*addr /*ill_g_headp*/; ill; ill = ill->ill_next ) {
1146 #ifdef AFS_SUN58_ENV
1147         /* Make sure this is an IPv4 ILL */
1148         if (ill->ill_isv6) continue;
1149 #endif
1150         for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next ) {
1151             subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1152             subnetmask = ipif->ipif_net_mask;
1153             /*
1154              * Generate the local net using the local address and 
1155              * whate we know about Class A, B and C networks.
1156              */
1157             if (IN_CLASSA(ipif->ipif_local_addr)) {
1158                 netmask = IN_CLASSA_NET;
1159             } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1160                 netmask = IN_CLASSB_NET;
1161             } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1162                 netmask = IN_CLASSC_NET;
1163             } else {
1164                 netmask = 0;
1165             }
1166             net = ipif->ipif_local_addr & netmask;
1167 #ifdef notdef 
1168             if (!s) {
1169                 if (ipif->ipif_local_addr != 0x7f000001) { /* ignore loopback */
1170                     *cnt += 1;
1171                     if (*cnt > 16) return;
1172                     *addrp++ = ipif->ipif_local_addr;
1173                 }
1174             } else
1175 #endif /* notdef */
1176               {
1177                 /* XXXXXX Do the individual ip ranking below XXXXX */
1178                 if ((sa->sa_ip & netmask) == net) {
1179                     if ((sa->sa_ip & subnetmask) == subnet) {
1180                         if (ipif->ipif_local_addr == sa->sa_ip) {  /* ie, ME!  */
1181                             sa->sa_iprank = TOPR;
1182                         } else { 
1183                             sa->sa_iprank = HI + ipif->ipif_metric; /* case #2 */
1184                         }
1185                     }  else {
1186                         sa->sa_iprank = MED + ipif->ipif_metric;   /* case #3 */
1187                     }
1188                 } else {
1189                     sa->sa_iprank = LO + ipif->ipif_metric;     /* case #4 */
1190                 }
1191                 /* check for case #5 -- point-to-point link */
1192                 if ((ipif->ipif_flags & IFF_POINTOPOINT) &&
1193                     (ipif->ipif_pp_dst_addr == sa->sa_ip )) {
1194
1195                     if (ipif->ipif_metric >= (MAXDEFRANK - MED)/PPWEIGHT) 
1196                         sa->sa_iprank = MAXDEFRANK;
1197                     else 
1198                         sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1199                 }
1200             }
1201         }
1202     }
1203 #else
1204 #ifndef USEIFADDR
1205     struct ifnet *ifn = NULL;
1206     struct in_ifaddr *ifad = (struct in_ifaddr *) 0;
1207     struct sockaddr_in *sin;
1208
1209     if (!sa) {
1210 #ifdef notdef /* clean up, remove this */
1211         for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
1212             for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next){
1213                if ((IFADDR2SA(ifad)->sa_family == AF_INET) 
1214                    && !(ifn->if_flags & IFF_LOOPBACK)) {
1215                   *cnt += 1;
1216                   if (*cnt > 16) return;
1217                   *addrp++ = ((struct sockaddr_in *) IFADDR2SA(ifad))->sin_addr.s_addr;
1218                 }
1219             }
1220         }
1221 #endif /* notdef */
1222         return;
1223     }
1224     sa->sa_iprank= 0;
1225 #ifdef  ADAPT_MTU
1226     ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1227 #endif
1228     if (ifn) {  /* local, more or less */
1229 #ifdef IFF_LOOPBACK
1230       if (ifn->if_flags & IFF_LOOPBACK) {
1231         sa->sa_iprank = TOPR;
1232         goto end;
1233       }
1234 #endif /* IFF_LOOPBACK */
1235       sin = (struct sockaddr_in *) IA_SIN(ifad);
1236       if (SA2ULONG(sin) == sa->sa_ip) {
1237         sa->sa_iprank = TOPR;
1238         goto end;
1239       }
1240 #ifdef IFF_BROADCAST
1241       if (ifn->if_flags & IFF_BROADCAST) {
1242          if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1243             sa->sa_iprank = HI;
1244             goto end;
1245           }
1246        }
1247 #endif /* IFF_BROADCAST */
1248 #ifdef IFF_POINTOPOINT
1249       if (ifn->if_flags & IFF_POINTOPOINT) {
1250         if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1251           if (ifn->if_metric > 4) {
1252             sa->sa_iprank = LO;
1253             goto end;
1254           }
1255           else sa->sa_iprank = ifn->if_metric;
1256         }
1257       }
1258 #endif /* IFF_POINTOPOINT */
1259       sa->sa_iprank += MED + ifn->if_metric;      /* couldn't find anything better */
1260     }
1261         
1262 #else /* USEIFADDR */
1263     
1264     if (sa) sa->sa_iprank= LO;
1265 #ifdef AFS_SGI62_ENV
1266     (void) hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1267                      (caddr_t)sa, NULL);
1268 #elif defined(AFS_DARWIN60_ENV)
1269     {
1270         struct ifnet *ifn;
1271         struct ifaddr *ifa;
1272         TAILQ_FOREACH(ifn , &ifnet, if_link) {
1273             TAILQ_FOREACH(ifa , &ifn->if_addrhead, ifa_link) {
1274                 afsi_SetServerIPRank(sa, ifa);
1275             }
1276         }
1277     }
1278 #elif defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1279     {
1280         struct in_ifaddr *ifa;
1281         TAILQ_FOREACH(ifa , &in_ifaddrhead, ia_link) {
1282             afsi_SetServerIPRank(sa, ifa);
1283         }
1284     }
1285 #elif defined(AFS_OBSD_ENV)
1286     {
1287         extern struct in_ifaddrhead in_ifaddr;
1288         struct in_ifaddr *ifa;
1289         for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1290             afsi_SetServerIPRank(sa, ifa);
1291     }
1292 #else
1293     {
1294         struct in_ifaddr *ifa;
1295         for ( ifa = in_ifaddr; ifa; ifa = ifa->ia_next ) {
1296             afsi_SetServerIPRank(sa, ifa);
1297         }
1298     }
1299 #endif
1300
1301   end: 
1302 #endif /* USEIFADDR */
1303 #endif /* AFS_SUN5_ENV */
1304 #endif /* else AFS_USERSPACE_IP_ADDR */
1305
1306     if (sa) sa->sa_iprank += afs_randomMod15();
1307
1308     return 0;
1309 }  /* afs_SetServerPrefs */
1310
1311 #undef TOPR
1312 #undef HI
1313 #undef MED
1314 #undef LO
1315 #undef PPWEIGHT
1316
1317 /* afs_FlushServer()
1318  * The addresses on this server struct has changed in some way and will
1319  * clean up all other structures that may reference it.
1320  * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1321  */
1322 void afs_FlushServer(struct server *srvp)
1323 {
1324   afs_int32 i;
1325   struct server  *ts, **pts;
1326
1327   /* Find any volumes residing on this server and flush their state */
1328   afs_ResetVolumes(srvp);
1329
1330   /* Flush all callbacks in the all vcaches for this specific server */
1331   afs_FlushServerCBs(srvp);
1332
1333   /* Remove all the callbacks structs */
1334   if (srvp->cbrs) {
1335      struct afs_cbr *cb, *cbnext;
1336
1337      MObtainWriteLock(&afs_xvcb, 300);
1338      for (cb=srvp->cbrs; cb; cb=cbnext) {
1339         cbnext = cb->next;
1340         afs_FreeCBR(cb);
1341      }
1342      srvp->cbrs = (struct afs_cbr *)0;
1343      ReleaseWriteLock(&afs_xvcb);
1344   }
1345   
1346   /* If no more srvAddr structs hanging off of this server struct,
1347    * then clean it up.
1348    */
1349   if (!srvp->addr) {
1350      /* Remove the server structure from the cell list - if there */
1351      afs_RemoveCellEntry(srvp);
1352
1353      /* Remove from the afs_servers hash chain */
1354      for (i=0; i<NSERVERS; i++) {
1355         for (pts=&(afs_servers[i]), ts=*pts; ts; pts=&(ts->next), ts=*pts) {
1356            if (ts == srvp) break;
1357         }
1358         if (ts) break;
1359      }
1360      if (ts) {
1361         *pts = ts->next;                /* Found it. Remove it */
1362         afs_osi_Free(ts, sizeof(struct server)); /* Free it */
1363         afs_totalServers--;
1364      }
1365   }
1366 }
1367
1368 /* afs_RemoveSrvAddr()
1369  * This removes a SrvAddr structure from its server structure.
1370  * The srvAddr struct is not free'd because it connections may still
1371  * be open to it. It is up to the calling process to make sure it
1372  * remains connected to a server struct.
1373  * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1374  *    It is not removed from the afs_srvAddrs hash chain.
1375  */
1376 void afs_RemoveSrvAddr(struct srvAddr *sap)
1377 {
1378   struct srvAddr **psa, *sa;
1379   struct server  *srv;
1380
1381   if (!sap) return;
1382   srv = sap->server;
1383
1384   /* Find the srvAddr in the server's list and remove it */
1385   for (psa=&(srv->addr), sa=*psa; sa; psa=&(sa->next_sa), sa=*psa) {
1386      if (sa == sap) break;
1387   }
1388   if (sa) {
1389      *psa = sa->next_sa;
1390      sa->next_sa = 0;
1391      sa->server  = 0;
1392
1393      /* Flush the server struct since it's IP address has changed */
1394      afs_FlushServer(srv);
1395   }
1396 }
1397
1398 /* afs_GetServer()
1399  * Return an updated and properly initialized server structure
1400  * corresponding to the server ID, cell, and port specified.
1401  * If one does not exist, then one will be created.
1402  * aserver and aport must be in NET byte order.
1403  */
1404 struct server *afs_GetServer(afs_uint32 *aserverp, afs_int32 nservers,
1405                              afs_int32 acell, u_short aport,
1406                              afs_int32 locktype, afsUUID *uuidp,
1407                              afs_int32 addr_uniquifier)
1408 {
1409     struct server  *oldts=0, *ts, *newts, *orphts=0;
1410     struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1411     u_short fsport;
1412     afs_int32 iphash, k, srvcount=0;
1413     unsigned int srvhash;
1414
1415     AFS_STATCNT(afs_GetServer);
1416
1417     ObtainSharedLock(&afs_xserver,13);
1418
1419     /* Check if the server struct exists and is up to date */
1420     if (!uuidp) {
1421        if (nservers != 1) panic("afs_GetServer: incorect count of servers");
1422        ObtainReadLock(&afs_xsrvAddr);   
1423        ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1424        ReleaseReadLock(&afs_xsrvAddr);  
1425        if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1426           /* Found a server struct that is not multihomed and has the
1427            * IP address associated with it. A correct match.
1428            */
1429           ReleaseSharedLock(&afs_xserver);
1430           return(ts);
1431        }
1432     } else {
1433        if (nservers <= 0) panic("afs_GetServer: incorrect count of servers");
1434        ts = afs_FindServer(0, aport, uuidp, locktype);
1435        if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1436           /* Found a server struct that is multihomed and same
1437            * uniqufier (same IP addrs). The above if statement is the
1438            * same as in InstallUVolumeEntry().
1439            */
1440           ReleaseSharedLock(&afs_xserver);
1441           return ts;
1442        }
1443        if (ts) oldts = ts;      /* Will reuse if same uuid */
1444     }
1445
1446     UpgradeSToWLock(&afs_xserver,36);
1447     ObtainWriteLock(&afs_xsrvAddr,116); 
1448
1449     srvcount = afs_totalServers;
1450
1451     /* Reuse/allocate a new server structure */
1452     if (oldts) {
1453        newts = oldts; 
1454     } else {
1455        newts = (struct server *) afs_osi_Alloc(sizeof(struct server));
1456        if (!newts) panic("malloc of server struct");
1457        afs_totalServers++;
1458        memset((char *)newts, 0, sizeof(struct server));
1459
1460        /* Add the server struct to the afs_servers[] hash chain */
1461        srvhash = (uuidp ? (afs_uuid_hash(uuidp)%NSERVERS) : SHash(aserverp[0]));
1462        newts->next = afs_servers[srvhash];
1463        afs_servers[srvhash] = newts;
1464     }
1465
1466     /* Initialize the server structure */
1467     if (uuidp) { /* Multihomed */
1468        newts->sr_uuid            = *uuidp;
1469        newts->sr_addr_uniquifier = addr_uniquifier;
1470        newts->flags             |= SRVR_MULTIHOMED;
1471     }
1472     if (acell) newts->cell = afs_GetCell(acell, 0);
1473
1474     fsport = (newts->cell ? newts->cell->fsport : AFS_FSPORT);
1475
1476     /* For each IP address we are registering */
1477     for (k=0; k<nservers; k++) {
1478        iphash = SHash(aserverp[k]);
1479
1480        /* Check if the srvAddr structure already exists. If so, remove
1481         * it from its server structure and add it to the new one.
1482         */
1483        for (oldsa=afs_srvAddrs[iphash]; oldsa; oldsa=oldsa->next_bkt) {
1484           if ( (oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport) ) break;
1485        }
1486        if (oldsa && (oldsa->server != newts)) {
1487           afs_RemoveSrvAddr(oldsa);     /* Remove from its server struct */
1488           oldsa->next_sa = newts->addr; /* Add to the  new server struct */
1489           newts->addr    = oldsa;
1490        }
1491
1492        /* Reuse/allocate a new srvAddr structure */
1493        if (oldsa) {
1494           newsa = oldsa;
1495        } else {
1496           newsa = (struct srvAddr *) afs_osi_Alloc(sizeof(struct srvAddr));
1497           if (!newsa) panic("malloc of srvAddr struct");
1498           afs_totalSrvAddrs++;
1499           memset((char *)newsa, 0, sizeof(struct srvAddr));
1500
1501           /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1502           newsa->next_bkt = afs_srvAddrs[iphash];
1503           afs_srvAddrs[iphash] = newsa;
1504
1505           /* Hang off of the server structure  */
1506           newsa->next_sa = newts->addr;
1507           newts->addr    = newsa;
1508
1509           /* Initialize the srvAddr Structure */
1510           newsa->sa_ip     = aserverp[k];
1511           newsa->sa_portal = aport;
1512        }
1513
1514        /* Update the srvAddr Structure */
1515        newsa->server    = newts;
1516        if (newts->flags & SRVR_ISDOWN)
1517           newsa->sa_flags |= SRVADDR_ISDOWN;
1518        if (uuidp) newsa->sa_flags |=  SRVADDR_MH;
1519        else       newsa->sa_flags &= ~SRVADDR_MH;
1520
1521        /* Compute preference values and resort */
1522        if (!newsa->sa_iprank) {
1523           if (aport == fsport) { 
1524              afs_SetServerPrefs(newsa);    /* new fileserver rank */
1525           } else {
1526              newsa->sa_iprank = 10000 + afs_randomMod127(); /* new vlserver rank */
1527           }
1528        }
1529     }
1530     afs_SortOneServer(newts);     /* Sort by rank */
1531
1532     /* If we reused the server struct, remove any of its srvAddr
1533      * structs that will no longer be associated with this server.
1534      */
1535     if (oldts) {    /* reused the server struct */
1536        for (orphsa=newts->addr; orphsa; orphsa=nextsa) {
1537           nextsa = orphsa->next_sa;
1538           for (k=0; k<nservers; k++) {
1539              if (orphsa->sa_ip == aserverp[k]) break; /* belongs */
1540           }
1541           if (k < nservers) continue;                 /* belongs */
1542
1543           /* Have a srvAddr struct. Now get a server struct (if not already) */
1544           if (!orphts) {
1545              orphts = (struct server *) afs_osi_Alloc(sizeof(struct server));
1546              if (!orphts) panic("malloc of lo server struct");
1547              memset((char *)orphts, 0, sizeof(struct server));
1548              afs_totalServers++;
1549
1550              /* Add the orphaned server to the afs_servers[] hash chain.
1551               * Its iphash does not matter since we never look up the server
1552               * in the afs_servers table by its ip address (only by uuid - 
1553               * which this has none).
1554               */
1555              iphash = SHash(aserverp[k]);
1556              orphts->next = afs_servers[iphash];
1557              afs_servers[iphash] = orphts;
1558
1559              if (acell) orphts->cell = afs_GetCell(acell, 0);
1560           }
1561
1562           /* Hang the srvAddr struct off of the server structure. The server
1563            * may have multiple srvAddrs, but it won't be marked multihomed.
1564            */
1565           afs_RemoveSrvAddr(orphsa);                 /* remove */
1566           orphsa->next_sa   = orphts->addr;          /* hang off server struct */
1567           orphts->addr      = orphsa;
1568           orphsa->server    = orphts;
1569           orphsa->sa_flags |= SRVADDR_NOUSE;         /* flag indicating not in use */
1570           orphsa->sa_flags &= ~SRVADDR_MH;           /* Not multihomed */
1571        }
1572     }
1573
1574     srvcount = afs_totalServers - srvcount;  /* # servers added and removed */
1575     if (srvcount) {
1576        struct afs_stats_SrvUpDownInfo *upDownP;
1577        /* With the introduction of this new record, we need to adjust the
1578         * proper individual & global server up/down info.
1579         */
1580        upDownP = GetUpDownStats(newts);
1581        upDownP->numTtlRecords      += srvcount;
1582        afs_stats_cmperf.srvRecords += srvcount;
1583        if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
1584           afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
1585     }
1586
1587     ReleaseWriteLock(&afs_xsrvAddr);    
1588     ReleaseWriteLock(&afs_xserver);
1589     return(newts);
1590 } /* afs_GetServer */
1591
1592 void afs_ActivateServer(struct srvAddr *sap) 
1593 {
1594    osi_timeval_t currTime;              /*Filled with current time*/
1595    osi_timeval_t *currTimeP;            /*Ptr to above*/
1596    struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record*/
1597    struct server *aserver = sap->server;
1598
1599    if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
1600       /*
1601        * This server record has not yet been activated.  Go for it,
1602        * recording its ``birth''.
1603        */
1604       aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
1605       currTimeP = &currTime;
1606       osi_GetuTime(currTimeP);
1607       aserver->activationTime = currTime.tv_sec;
1608       upDownP = GetUpDownStats(aserver);
1609       if (aserver->flags & SRVR_ISDOWN) {
1610          upDownP->numDownRecords++;
1611       } else {
1612          upDownP->numUpRecords++;
1613          upDownP->numRecordsNeverDown++;
1614       }
1615    }
1616 }