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