2 * Copyright 2000, International Business Machines Corporation and others.
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
12 * afs_MarkServerUpOrDown
20 * afsi_SetServerIPRank
32 #include <afsconfig.h>
33 #include "afs/param.h"
39 #include "afs/sysincludes.h" /* Standard vendor system headers */
42 #if !defined(AFS_LINUX20_ENV)
45 #include <netinet/in.h>
48 #include "h/hashing.h"
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>
56 #endif /* !defined(UKERNEL) */
58 #include "afsincludes.h" /* Afs-based standard headers */
59 #include "afs/afs_stats.h" /* afs statistics */
60 #include "rx/rx_multi.h"
62 #if defined(AFS_SUN56_ENV)
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]
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 */
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;
91 static struct afs_stats_SrvUpDownInfo *
92 GetUpDownStats(struct server *srv)
94 struct afs_stats_SrvUpDownInfo *upDownP;
95 u_short fsport = AFS_FSPORT;
98 fsport = srv->cell->fsport;
100 if (srv->addr->sa_portal == fsport)
101 upDownP = afs_stats_cmperf.fs_UpDown;
103 upDownP = afs_stats_cmperf.vl_UpDown;
105 if (srv->cell && afs_IsPrimaryCell(srv->cell))
106 return &upDownP[AFS_STATS_UPDOWN_IDX_SAME_CELL];
108 return &upDownP[AFS_STATS_UPDOWN_IDX_DIFF_CELL];
112 /*------------------------------------------------------------------------
113 * afs_MarkServerUpOrDown
116 * Mark the given server up or down, and track its uptime stats.
119 * a_serverP : Ptr to server record to fiddle with.
120 * a_isDown : Is the server is to be marked down?
126 * The CM server structures must be write-locked.
130 *------------------------------------------------------------------------*/
133 afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
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 */
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.
145 if ((a_isDown && (sa->sa_flags & SRVADDR_ISDOWN))
146 || (!a_isDown && !(sa->sa_flags & SRVADDR_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 */
159 * All ips are down we treat the whole server down
161 a_serverP->flags |= SRVR_ISDOWN;
163 * If this was our time server, search for another time server
165 if (a_serverP == afs_setTimeHost)
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 */
181 * Compute the current time and which overall stats record is to be
182 * updated; we'll need them one way or another.
184 currTimeP = &currTime;
185 osi_GetuTime(currTimeP);
187 upDownP = GetUpDownStats(a_serverP);
191 * Server going up -> down; remember the beginning of this
194 a_serverP->lastDowntimeStart = currTime.tv_sec;
196 (upDownP->numDownRecords)++;
197 (upDownP->numUpRecords)--;
198 } /*Server being marked down */
201 * Server going down -> up; remember everything about this
202 * newly-completed downtime incident.
204 downTime = currTime.tv_sec - a_serverP->lastDowntimeStart;
205 (a_serverP->numDowntimeIncidents)++;
206 a_serverP->sumOfDowntimes += downTime;
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;
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])++;
235 (upDownP->downDurations[6])++;
237 } /*Server being marked up */
239 } /*MarkServerUpOrDown */
243 afs_ServerDown(struct srvAddr *sa)
245 register struct server *aserver = sa->server;
247 AFS_STATCNT(ServerDown);
248 if (aserver->flags & SRVR_ISDOWN || sa->sa_flags & SRVADDR_ISDOWN)
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);
255 print_internet_address("afs: Lost contact with file server ", sa, "",
261 /* return true if we have any callback promises from this server */
263 afs_HaveCallBacksFrom(struct server *aserver)
265 register afs_int32 now;
267 register struct vcache *tvc;
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) {
274 * Check to see if this entry has an unexpired callback promise
275 * from the required host
277 if (aserver == tvc->callback && tvc->cbExpires >= now
278 && ((tvc->states & CRO) == 0))
284 } /*HaveCallBacksFrom */
288 CheckVLServer(register struct srvAddr *sa, struct vrequest *areq)
290 register struct server *aserver = sa->server;
291 register struct conn *tc;
292 register afs_int32 code;
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))
300 return; /* can't do much */
302 tc = afs_ConnByHost(aserver, aserver->cell->vlport,
303 aserver->cell->cellNum, areq, 1, SHARED_LOCK);
306 rx_SetConnDeadTime(tc->id, 3);
309 code = VL_ProbeServer(tc->id);
311 rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
312 afs_PutConn(tc, SHARED_LOCK);
314 * If probe worked, or probe call not yet defined (for compatibility
315 * with old vlsevers), then we treat this server as running again
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,
328 #ifndef AFS_MINCHANGE /* So that some can increase it in param.h */
329 #define AFS_MINCHANGE 2 /* min change we'll bother with */
331 #ifndef AFS_MAXCHANGEBACK
332 #define AFS_MAXCHANGEBACK 10 /* max seconds we'll set a clock back at once */
336 /*------------------------------------------------------------------------
337 * EXPORTED afs_CountServers
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
352 * This routine locks afs_xserver for write for the duration.
355 * Set CM perf stats field sumOfRecordAges for all server record
357 *------------------------------------------------------------------------*/
360 afs_CountServers(void)
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 */
372 * Write-lock the server table so we don't get any interference.
374 ObtainReadLock(&afs_xserver);
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.
381 afs_stats_cmperf.srvMaxChainLength = 0;
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));
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));
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));
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));
408 * Compute the current time, used to figure out server record ages.
410 currTimeP = &currTime;
411 osi_GetuTime(currTimeP);
414 * Sweep the server hash table, tallying all we need to know.
416 for (currIdx = 0; currIdx < NSERVERS; currIdx++) {
418 for (currSrvP = afs_servers[currIdx]; currSrvP;
419 currSrvP = currSrvP->next) {
421 * Bump the current chain length.
426 * Any further tallying for this record will only be done if it has
429 if ((currSrvP->flags & AFS_SERVER_FLAG_ACTIVATED)
430 && currSrvP->addr && currSrvP->cell) {
433 * Compute the current server record's age, then remember it
434 * in the appropriate places.
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;
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])++;
462 (upDownP->downIncidents[5])++;
465 } /*Current server has been active */
466 } /*Walk this chain */
469 * Before advancing to the next chain, remember facts about this one.
471 if (currChainLen > afs_stats_cmperf.srvMaxChainLength) {
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
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 */
484 * We're done. Unlock the server table before returning to our caller.
486 ReleaseReadLock(&afs_xserver);
488 } /*afs_CountServers */
492 ForceAllNewConnections()
495 struct srvAddr **addrs;
499 ObtainReadLock(&afs_xserver); /* Necessary? */
500 ObtainReadLock(&afs_xsrvAddr);
503 for (i = 0; i < NSERVERS; i++) {
504 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
509 addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
511 for (i = 0; i < NSERVERS; i++) {
512 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
513 if (j >= srvAddrCount)
519 ReleaseReadLock(&afs_xsrvAddr);
520 ReleaseReadLock(&afs_xserver);
521 for (i = 0; i < j; i++) {
523 ForceNewConnections(sa);
527 /* check down servers (if adown), or running servers (if !adown) */
529 afs_CheckServers(int adown, struct cell *acellp)
531 struct vrequest treq;
537 afs_int32 start, end = 0, delta;
542 struct srvAddr **addrs;
545 struct rx_connection **rxconns;
546 afs_int32 *conntimer, *deltas, *results;
548 AFS_STATCNT(afs_CheckServers);
550 conns = (struct conn **)0;
551 rxconns = (struct rx_connection **) 0;
555 if ((code = afs_InitReq(&treq, afs_osi_credp)))
557 ObtainReadLock(&afs_xserver); /* Necessary? */
558 ObtainReadLock(&afs_xsrvAddr);
561 for (i = 0; i < NSERVERS; i++) {
562 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
567 addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
569 for (i = 0; i < NSERVERS; i++) {
570 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
571 if (j >= srvAddrCount)
577 ReleaseReadLock(&afs_xsrvAddr);
578 ReleaseReadLock(&afs_xserver);
580 conns = (struct conn **)afs_osi_Alloc(j * sizeof(struct conn *));
581 rxconns = (struct rx_connection **)afs_osi_Alloc(j * sizeof(struct rx_connection *));
582 conntimer = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
583 deltas = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
584 results = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
586 for (i = 0; i < j; i++) {
593 /* See if a cell to check was specified. If it is spec'd and not
594 * this server's cell, just skip the server.
596 if (acellp && acellp != ts->cell)
599 if ((!adown && (sa->sa_flags & SRVADDR_ISDOWN))
600 || (adown && !(sa->sa_flags & SRVADDR_ISDOWN)))
603 /* check vlserver with special code */
604 if (sa->sa_portal == AFS_VLPORT) {
605 CheckVLServer(sa, &treq);
609 if (!ts->cell) /* not really an active server, anyway, it must */
610 continue; /* have just been added by setsprefs */
612 /* get a connection, even if host is down; bumps conn ref count */
613 tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
614 tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
615 1 /*force */ , 1 /*create */ , SHARED_LOCK);
616 afs_PutUser(tu, SHARED_LOCK);
620 if ((sa->sa_flags & SRVADDR_ISDOWN) || afs_HaveCallBacksFrom(sa->server)
621 || (tc->srvr->server == afs_setTimeHost)) {
623 rxconns[nconns]=tc->id;
624 if (sa->sa_flags & SRVADDR_ISDOWN) {
625 rx_SetConnDeadTime(tc->id, 3);
632 } /* Outer loop over addrs */
634 start = osi_Time(); /* time the gettimeofday call */
636 multi_Rx(rxconns,nconns)
638 tv.tv_sec = tv.tv_usec = 0;
639 multi_RXAFS_GetTime(&tv.tv_sec, &tv.tv_usec);
642 if (conntimer[multi_i] == 1)
643 rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
645 results[multi_i]=multi_error;
646 if ((start == end) && !multi_error)
647 deltas[multi_i] = end - tv.tv_sec;
652 for(i=0;i<nconns;i++){
656 if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) && (tc->srvr == sa)) {
658 print_internet_address("afs: file server ", sa, " is back up", 2);
660 ObtainWriteLock(&afs_xserver, 244);
661 ObtainWriteLock(&afs_xsrvAddr, 245);
662 afs_MarkServerUpOrDown(sa, 0);
663 ReleaseWriteLock(&afs_xsrvAddr);
664 ReleaseWriteLock(&afs_xserver);
666 if (afs_waitForeverCount) {
667 afs_osi_Wakeup(&afs_waitForever);
670 if (results[i] < 0) {
673 ForceNewConnections(sa); /* multi homed clients */
679 * If we're supposed to set the time, and the call worked
680 * quickly (same second response) and this is the host we
681 * use for the time and the time is really different, then
682 * really set the time
684 if (afs_setTime != 0) {
685 for (i=0; i<nconns; i++) {
690 if ((tc->srvr->server == afs_setTimeHost ||
691 /* Sync only to a server in the local cell */
692 (afs_setTimeHost == (struct server *)0 &&
693 afs_IsPrimaryCell(sa->server->cell)))) {
695 char msgbuf[90]; /* strlen("afs: setting clock...") + slop */
696 delta = end - tv.tv_sec; /* how many secs fast we are */
698 afs_setTimeHost = tc->srvr->server;
699 /* see if clock has changed enough to make it worthwhile */
700 if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) {
702 if (delta > AFS_MAXCHANGEBACK) {
703 /* setting clock too far back, just do it a little */
704 tv.tv_sec = end - AFS_MAXCHANGEBACK;
706 tv.tv_sec = end - delta;
708 afs_osi_SetTime(&tv);
710 strcpy(msgbuf, "afs: setting clock back ");
711 if (delta > AFS_MAXCHANGEBACK) {
713 afs_cv2string(&tbuffer[CVBS],
715 afs_strcat(msgbuf, " seconds (of ");
717 afs_cv2string(&tbuffer[CVBS],
720 afs_strcat(msgbuf, ", via ");
721 print_internet_address(msgbuf, sa,
722 "); clock is still fast.",
726 afs_cv2string(&tbuffer[CVBS], delta));
727 afs_strcat(msgbuf, " seconds (via ");
728 print_internet_address(msgbuf, sa, ").", 0);
731 strcpy(msgbuf, "afs: setting clock ahead ");
733 afs_cv2string(&tbuffer[CVBS], -delta));
734 afs_strcat(msgbuf, " seconds (via ");
735 print_internet_address(msgbuf, sa, ").", 0);
737 /* We're only going to set it once; why bother looping? */
743 for (i = 0; i < nconns; i++) {
744 afs_PutConn(conns[i], SHARED_LOCK); /* done with it now */
747 afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
748 afs_osi_Free(conns, j * sizeof(struct conn *));
749 afs_osi_Free(rxconns, j * sizeof(struct rx_connection *));
750 afs_osi_Free(conntimer, j * sizeof(afs_int32));
751 afs_osi_Free(deltas, j * sizeof(afs_int32));
752 afs_osi_Free(results, j * sizeof(afs_int32));
754 } /*afs_CheckServers*/
757 /* find a server structure given the host address */
759 afs_FindServer(afs_int32 aserver, afs_uint16 aport, afsUUID * uuidp,
766 AFS_STATCNT(afs_FindServer);
768 i = afs_uuid_hash(uuidp) % NSERVERS;
769 for (ts = afs_servers[i]; ts; ts = ts->next) {
770 if ((ts->flags & SRVR_MULTIHOMED)
772 (memcmp((char *)uuidp, (char *)&ts->sr_uuid, sizeof(*uuidp))
773 == 0) && (!ts->addr || (ts->addr->sa_portal == aport)))
778 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
779 if ((sa->sa_ip == aserver) && (sa->sa_portal == aport)) {
786 } /*afs_FindServer */
789 /* some code for creating new server structs and setting preferences follows
790 * in the next few lines...
793 #define MAXDEFRANK 60000
794 #define DEFRANK 40000
796 /* Random number generator and constants from KnuthV2 2d ed, p170 */
802 a is 0.73m should be 0.01m .. 0.99m
803 c is more or less immaterial. 1 or a is suggested.
805 NB: LOW ORDER BITS are not very random. To get small random numbers,
806 treat result as <1, with implied binary point, and multiply by
808 NB: Has to be unsigned, since shifts on signed quantities may preserve
811 /* added rxi_getaddr() to try to get as much initial randomness as
812 possible, since at least one customer reboots ALL their clients
813 simultaneously -- so osi_Time is bound to be the same on some of the
814 clients. This is probably OK, but I don't want to see too much of it.
817 #define ranstage(x) (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
822 static afs_int32 state = 0;
825 AFS_STATCNT(afs_random);
830 * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
831 * bits are in a tv_usec
833 state = (t.tv_usec & (~0 << 4)) + (rxi_getaddr() & 0xff);
834 state += (t.tv_sec & 0xff);
835 for (i = 0; i < 30; i++) {
845 /* returns int 0..14 using the high bits of a pseudo-random number instead of
846 the low bits, as the low bits are "less random" than the high ones...
847 slight roundoff error exists, an excercise for the reader.
848 need to multiply by something with lots of ones in it, so multiply by
849 8 or 16 is right out.
852 afs_randomMod15(void)
856 temp = afs_random() >> 4;
857 temp = (temp * 15) >> 28;
863 afs_randomMod127(void)
867 temp = afs_random() >> 7;
868 temp = (temp * 127) >> 25;
873 /* afs_SortOneServer()
874 * Sort all of the srvAddrs, of a server struct, by rank from low to high.
877 afs_SortOneServer(struct server *asp)
879 struct srvAddr **rootsa, *lowsa, *tsa, *lowprev;
882 for (rootsa = &(asp->addr); *rootsa; rootsa = &(lowsa->next_sa)) {
884 lowsa = *rootsa; /* lowest sa is the first one */
885 lowrank = lowsa->sa_iprank;
887 for (tsa = *rootsa; tsa->next_sa; tsa = tsa->next_sa) {
888 rank = tsa->next_sa->sa_iprank;
889 if (rank < lowrank) {
891 lowsa = tsa->next_sa;
892 lowrank = lowsa->sa_iprank;
895 if (lowprev) { /* found one lower, so rearrange them */
896 lowprev->next_sa = lowsa->next_sa;
897 lowsa->next_sa = *rootsa;
904 * Sort the pointer to servers by the server's rank (its lowest rank).
905 * It is assumed that the server already has its IP addrs sorted (the
906 * first being its lowest rank: afs_GetServer() calls afs_SortOneServer()).
909 afs_SortServers(struct server *aservers[], int count)
914 AFS_STATCNT(afs_SortServers);
916 for (i = 0; i < count; i++) {
919 for (low = i, j = i + 1; j <= count; j++) {
920 if ((!aservers[j]) || (!aservers[j]->addr))
922 if ((!aservers[low]) || (!aservers[low]->addr))
924 if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
930 aservers[i] = aservers[low];
934 } /*afs_SortServers */
936 /* afs_SetServerPrefs is rather system-dependent. It pokes around in kernel
937 data structures to determine what the local IP addresses and subnet masks
938 are in order to choose which server(s) are on the local subnet.
940 As I see it, there are several cases:
941 1. The server address is one of this host's local addresses. In this case
942 this server is to be preferred over all others.
943 2. The server is on the same subnet as one of the this host's local
944 addresses. (ie, an odd-sized subnet, not class A,B,orC)
945 3. The server is on the same net as this host (class A,B or C)
946 4. The server is on a different logical subnet or net than this host, but
947 this host is a 'metric 0 gateway' to it. Ie, two address-spaces share
949 5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
951 6. This host and the server are disjoint.
953 That is a rough order of preference. If a point-to-point link has a high
954 metric, I'm assuming that it is a very slow link, and putting it at the
955 bottom of the list (at least until RX works better over slow links). If
956 its metric is 1, I'm assuming that it's relatively fast (T1) and putting
958 It's not easy to check for case #4, so I'm ignoring it for the time being.
960 BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
961 That could be used to prefer certain servers fairly easily. Maybe some
964 NOTE: this code is very system-dependent, and very dependent on the TCP/IP
965 protocols (well, addresses that are stored in uint32s, at any rate).
968 #define IA_DST(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_dstaddr))
969 #define IA_BROAD(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
971 /* SA2ULONG takes a sockaddr_in, not a sockaddr (same thing, just cast it!) */
972 #define SA2ULONG(sa) ((sa)->sin_addr.s_addr)
977 #define PPWEIGHT 4096
982 #if defined(AFS_SUN5_ENV) && ! defined(AFS_SUN56_ENV)
983 #include <inet/common.h>
984 /* IP interface structure, one per local address */
985 typedef struct ipif_s {
986 /**/ struct ipif_s *ipif_next;
987 struct ill_s *ipif_ill; /* Back pointer to our ill */
988 long ipif_id; /* Logical unit number */
989 u_int ipif_mtu; /* Starts at ipif_ill->ill_max_frag */
990 afs_int32 ipif_local_addr; /* Local IP address for this if. */
991 afs_int32 ipif_net_mask; /* Net mask for this interface. */
992 afs_int32 ipif_broadcast_addr; /* Broadcast addr for this interface. */
993 afs_int32 ipif_pp_dst_addr; /* Point-to-point dest address. */
994 u_int ipif_flags; /* Interface flags. */
995 u_int ipif_metric; /* BSD if metric, for compatibility. */
996 u_int ipif_ire_type; /* LOCAL or LOOPBACK */
997 mblk_t *ipif_arp_down_mp; /* Allocated at time arp comes up to
998 * prevent awkward out of mem condition
1001 mblk_t *ipif_saved_ire_mp; /* Allocated for each extra IRE_SUBNET/
1002 * RESOLVER on this interface so that
1003 * they can survive ifconfig down.
1006 * The packet counts in the ipif contain the sum of the
1007 * packet counts in dead IREs that were affiliated with
1010 u_long ipif_fo_pkt_count; /* Forwarded thru our dead IREs */
1011 u_long ipif_ib_pkt_count; /* Inbound packets for our dead IREs */
1012 u_long ipif_ob_pkt_count; /* Outbound packets to our dead IREs */
1014 ipif_multicast_up:1, /* We have joined the allhosts group */
1018 typedef struct ipfb_s {
1019 /**/ struct ipf_s *ipfb_ipf; /* List of ... */
1020 kmutex_t ipfb_lock; /* Protect all ipf in list */
1023 typedef struct ilm_s {
1024 /**/ afs_int32 ilm_addr;
1026 u_int ilm_timer; /* IGMP */
1027 struct ipif_s *ilm_ipif; /* Back pointer to ipif */
1028 struct ilm_s *ilm_next; /* Linked list for each ill */
1031 typedef struct ill_s {
1032 /**/ struct ill_s *ill_next; /* Chained in at ill_g_head. */
1033 struct ill_s **ill_ptpn; /* Pointer to previous next. */
1034 queue_t *ill_rq; /* Read queue. */
1035 queue_t *ill_wq; /* Write queue. */
1037 int ill_error; /* Error value sent up by device. */
1039 ipif_t *ill_ipif; /* Interface chain for this ILL. */
1040 u_int ill_ipif_up_count; /* Number of IPIFs currently up. */
1041 u_int ill_max_frag; /* Max IDU. */
1042 char *ill_name; /* Our name. */
1043 u_int ill_name_length; /* Name length, incl. terminator. */
1044 u_int ill_subnet_type; /* IRE_RESOLVER or IRE_SUBNET. */
1045 u_int ill_ppa; /* Physical Point of Attachment num. */
1047 int ill_sap_length; /* Including sign (for position) */
1048 u_int ill_phys_addr_length; /* Excluding the sap. */
1049 mblk_t *ill_frag_timer_mp; /* Reassembly timer state. */
1050 ipfb_t *ill_frag_hash_tbl; /* Fragment hash list head. */
1052 queue_t *ill_bind_pending_q; /* Queue waiting for DL_BIND_ACK. */
1053 ipif_t *ill_ipif_pending; /* IPIF waiting for DL_BIND_ACK. */
1055 /* ill_hdr_length and ill_hdr_mp will be non zero if
1056 * the underlying device supports the M_DATA fastpath
1060 ilm_t *ill_ilm; /* Multicast mebership for lower ill */
1062 /* All non-nil cells between 'ill_first_mp_to_free' and
1063 * 'ill_last_mp_to_free' are freed in ill_delete.
1065 #define ill_first_mp_to_free ill_hdr_mp
1066 mblk_t *ill_hdr_mp; /* Contains fastpath template */
1067 mblk_t *ill_bcast_mp; /* DLPI header for broadcasts. */
1068 mblk_t *ill_bind_pending; /* T_BIND_REQ awaiting completion. */
1069 mblk_t *ill_resolver_mp; /* Resolver template. */
1070 mblk_t *ill_attach_mp;
1071 mblk_t *ill_bind_mp;
1072 mblk_t *ill_unbind_mp;
1073 mblk_t *ill_detach_mp;
1074 #define ill_last_mp_to_free ill_detach_mp
1076 u_int ill_frag_timer_running:1, ill_needs_attach:1, ill_is_ptp:1,
1077 ill_priv_stream:1, ill_unbind_pending:1, ill_pad_to_bit_31:27;
1078 MI_HRT_DCL(ill_rtime)
1079 MI_HRT_DCL(ill_rtmp)
1083 #ifdef AFS_USERSPACE_IP_ADDR
1085 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1088 * The IP addresses and ranks are determined by afsd (in user space) and
1089 * passed into the kernel at startup time through the AFSOP_ADVISEADDR
1090 * system call. These are stored in the data structure
1091 * called 'afs_cb_interface'.
1093 * struct srvAddr *sa; remote server
1094 * afs_int32 addr; one of my local addr in net order
1095 * afs_uint32 subnetmask; subnet mask of local addr in net order
1099 afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr,
1100 afs_uint32 subnetmask)
1102 afs_uint32 myAddr, myNet, mySubnet, netMask;
1103 afs_uint32 serverAddr;
1105 myAddr = ntohl(addr); /* one of my IP addr in host order */
1106 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1107 subnetmask = ntohl(subnetmask); /* subnet mask in host order */
1109 if (IN_CLASSA(myAddr))
1110 netMask = IN_CLASSA_NET;
1111 else if (IN_CLASSB(myAddr))
1112 netMask = IN_CLASSB_NET;
1113 else if (IN_CLASSC(myAddr))
1114 netMask = IN_CLASSC_NET;
1118 myNet = myAddr & netMask;
1119 mySubnet = myAddr & subnetmask;
1121 if ((serverAddr & netMask) == myNet) {
1122 if ((serverAddr & subnetmask) == mySubnet) {
1123 if (serverAddr == myAddr) { /* same machine */
1124 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1125 } else { /* same subnet */
1126 sa->sa_iprank = afs_min(sa->sa_iprank, HI);
1128 } else { /* same net */
1129 sa->sa_iprank = afs_min(sa->sa_iprank, MED);
1134 #else /* AFS_USERSPACE_IP_ADDR */
1135 #if (! defined(AFS_SUN5_ENV)) && !defined(AFS_DARWIN60_ENV) && defined(USEIFADDR)
1137 afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
1139 struct sockaddr_in *sin;
1142 if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
1143 if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
1145 if (SA2ULONG(sin) == ntohl(sa->sa_ip)) { /* ie, ME!!! */
1146 sa->sa_iprank = TOPR;
1148 t = HI + ifa->ia_ifp->if_metric; /* case #2 */
1149 if (sa->sa_iprank > t)
1153 t = MED + ifa->ia_ifp->if_metric; /* case #3 */
1154 if (sa->sa_iprank > t)
1158 #ifdef IFF_POINTTOPOINT
1159 /* check for case #4 -- point-to-point link */
1160 if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
1161 && (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
1162 if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1165 t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
1166 if (sa->sa_iprank > t)
1169 #endif /* IFF_POINTTOPOINT */
1171 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1172 #if defined(AFS_DARWIN60_ENV) && defined(USEIFADDR)
1174 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1177 afsi_SetServerIPRank(sa, ifa)
1179 #ifdef AFS_DARWIN80_ENV
1185 struct sockaddr sout;
1186 struct sockaddr_in *sin;
1189 afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
1190 afs_uint32 serverAddr;
1192 if (ifaddr_address_family(ifa) != AF_INET)
1194 t = ifaddr_address(ifa, &sout, sizeof(sout));
1196 sin = (struct sockaddr_in *)&sout;
1197 myAddr = ntohl(sin->sin_addr.s_addr); /* one of my IP addr in host order */
1201 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1202 t = ifaddr_netmask(ifa, &sout, sizeof(sout));
1204 sin = (struct sockaddr_in *)&sout;
1205 subnetmask = ntohl(sin->sin_addr.s_addr); /* subnet mask in host order */
1209 t = ifaddr_dstaddress(ifa, &sout, sizeof(sout));
1211 sin = (struct sockaddr_in *)&sout;
1212 myDstaddr = sin->sin_addr.s_addr;
1217 if (IN_CLASSA(myAddr))
1218 netMask = IN_CLASSA_NET;
1219 else if (IN_CLASSB(myAddr))
1220 netMask = IN_CLASSB_NET;
1221 else if (IN_CLASSC(myAddr))
1222 netMask = IN_CLASSC_NET;
1226 myNet = myAddr & netMask;
1227 mySubnet = myAddr & subnetmask;
1229 if ((serverAddr & netMask) == myNet) {
1230 if ((serverAddr & subnetmask) == mySubnet) {
1231 if (serverAddr == myAddr) { /* same machine */
1232 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1233 } else { /* same subnet */
1234 sa->sa_iprank = afs_min(sa->sa_iprank, HI + ifnet_metric(ifaddr_ifnet(ifa)));
1236 } else { /* same net */
1237 sa->sa_iprank = afs_min(sa->sa_iprank, MED + ifnet_metric(ifaddr_ifnet(ifa)));
1240 #ifdef IFF_POINTTOPOINT
1241 /* check for case #4 -- point-to-point link */
1242 if ((ifnet_flags(ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
1243 && (myDstaddr == serverAddr)) {
1244 if (ifnet_metric(ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
1247 t = MED + (PPWEIGHT << ifnet_metric(ifaddr_ifnet(ifa)));
1248 if (sa->sa_iprank > t)
1251 #endif /* IFF_POINTTOPOINT */
1253 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1254 #endif /* else AFS_USERSPACE_IP_ADDR */
1256 #ifdef AFS_SGI62_ENV
1259 afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1261 afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
1262 return 0; /* Never match, so we enumerate everyone */
1264 #endif /* AFS_SGI62_ENV */
1265 static int afs_SetServerPrefs(struct srvAddr *sa) {
1266 #if defined(AFS_USERSPACE_IP_ADDR)
1270 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1271 afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1272 afs_cb_interface.subnetmask[i]);
1274 #else /* AFS_USERSPACE_IP_ADDR */
1275 #if defined(AFS_SUN5_ENV)
1276 #ifdef AFS_SUN510_ENV
1279 extern struct ill_s *ill_g_headp;
1280 long *addr = (long *)ill_g_headp;
1284 int subnet, subnetmask, net, netmask;
1288 #ifdef AFS_SUN510_ENV
1289 rw_enter(&afsifinfo_lock, RW_READER);
1291 for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
1293 if (IN_CLASSA(afsifinfo[i].ipaddr)) {
1294 netmask = IN_CLASSA_NET;
1295 } else if (IN_CLASSB(afsifinfo[i].ipaddr)) {
1296 netmask = IN_CLASSB_NET;
1297 } else if (IN_CLASSC(afsifinfo[i].ipaddr)) {
1298 netmask = IN_CLASSC_NET;
1302 net = afsifinfo[i].ipaddr & netmask;
1306 if (afsifinfo[i].ipaddr != 0x7f000001) { /* ignore loopback */
1310 *addrp++ = afsifinfo[i].ipaddr;
1315 /* XXXXXX Do the individual ip ranking below XXXXX */
1316 if ((sa->sa_ip & netmask) == net) {
1317 if ((sa->sa_ip & subnetmask) == subnet) {
1318 if (afsifinfo[i].ipaddr == sa->sa_ip) { /* ie, ME! */
1319 sa->sa_iprank = TOPR;
1321 sa->sa_iprank = HI + afsifinfo[i].metric; /* case #2 */
1324 sa->sa_iprank = MED + afsifinfo[i].metric; /* case #3 */
1327 sa->sa_iprank = LO + afsifinfo[i].metric; /* case #4 */
1329 /* check for case #5 -- point-to-point link */
1330 if ((afsifinfo[i].flags & IFF_POINTOPOINT)
1331 && (afsifinfo[i].dstaddr == sa->sa_ip)) {
1333 if (afsifinfo[i].metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1334 sa->sa_iprank = MAXDEFRANK;
1336 sa->sa_iprank = MED + (PPWEIGHT << afsifinfo[i].metric);
1341 rw_exit(&afsifinfo_lock);
1343 for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
1344 ill = ill->ill_next) {
1345 #ifdef AFS_SUN58_ENV
1346 /* Make sure this is an IPv4 ILL */
1350 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
1351 subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1352 subnetmask = ipif->ipif_net_mask;
1354 * Generate the local net using the local address and
1355 * whate we know about Class A, B and C networks.
1357 if (IN_CLASSA(ipif->ipif_local_addr)) {
1358 netmask = IN_CLASSA_NET;
1359 } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1360 netmask = IN_CLASSB_NET;
1361 } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1362 netmask = IN_CLASSC_NET;
1366 net = ipif->ipif_local_addr & netmask;
1369 if (ipif->ipif_local_addr != 0x7f000001) { /* ignore loopback */
1373 *addrp++ = ipif->ipif_local_addr;
1378 /* XXXXXX Do the individual ip ranking below XXXXX */
1379 if ((sa->sa_ip & netmask) == net) {
1380 if ((sa->sa_ip & subnetmask) == subnet) {
1381 if (ipif->ipif_local_addr == sa->sa_ip) { /* ie, ME! */
1382 sa->sa_iprank = TOPR;
1384 sa->sa_iprank = HI + ipif->ipif_metric; /* case #2 */
1387 sa->sa_iprank = MED + ipif->ipif_metric; /* case #3 */
1390 sa->sa_iprank = LO + ipif->ipif_metric; /* case #4 */
1392 /* check for case #5 -- point-to-point link */
1393 if ((ipif->ipif_flags & IFF_POINTOPOINT)
1394 && (ipif->ipif_pp_dst_addr == sa->sa_ip)) {
1396 if (ipif->ipif_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1397 sa->sa_iprank = MAXDEFRANK;
1399 sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1404 #endif /* AFS_SUN510_ENV */
1407 struct ifnet *ifn = NULL;
1408 struct in_ifaddr *ifad = (struct in_ifaddr *)0;
1409 struct sockaddr_in *sin;
1412 #ifdef notdef /* clean up, remove this */
1413 for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
1414 for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next) {
1415 if ((IFADDR2SA(ifad)->sa_family == AF_INET)
1416 && !(ifn->if_flags & IFF_LOOPBACK)) {
1421 ((struct sockaddr_in *)IFADDR2SA(ifad))->sin_addr.
1430 ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1432 if (ifn) { /* local, more or less */
1434 if (ifn->if_flags & IFF_LOOPBACK) {
1435 sa->sa_iprank = TOPR;
1438 #endif /* IFF_LOOPBACK */
1439 sin = (struct sockaddr_in *)IA_SIN(ifad);
1440 if (SA2ULONG(sin) == sa->sa_ip) {
1441 sa->sa_iprank = TOPR;
1444 #ifdef IFF_BROADCAST
1445 if (ifn->if_flags & IFF_BROADCAST) {
1446 if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1451 #endif /* IFF_BROADCAST */
1452 #ifdef IFF_POINTOPOINT
1453 if (ifn->if_flags & IFF_POINTOPOINT) {
1454 if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1455 if (ifn->if_metric > 4) {
1459 sa->sa_iprank = ifn->if_metric;
1462 #endif /* IFF_POINTOPOINT */
1463 sa->sa_iprank += MED + ifn->if_metric; /* couldn't find anything better */
1465 #else /* USEIFADDR */
1469 #ifdef AFS_SGI62_ENV
1470 (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1471 (caddr_t) sa, NULL);
1472 #elif defined(AFS_DARWIN80_ENV)
1480 if (!ifnet_list_get(AF_INET, &ifn, &count)) {
1481 for (m = 0; m < count; m++) {
1482 if (!ifnet_get_address_list(ifn[m], &ifads)) {
1483 for (j = 0; ifads[j] != NULL && cnt < ADDRSPERSITE; j++) {
1484 afsi_SetServerIPRank(sa, ifads[j]);
1487 ifnet_free_address_list(ifads);
1490 ifnet_list_free(ifn);
1493 #elif defined(AFS_DARWIN60_ENV)
1497 TAILQ_FOREACH(ifn, &ifnet, if_link) {
1498 TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
1499 afsi_SetServerIPRank(sa, ifa);
1501 #elif defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1503 struct in_ifaddr *ifa;
1504 TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
1505 afsi_SetServerIPRank(sa, ifa);
1507 #elif defined(AFS_OBSD_ENV)
1509 extern struct in_ifaddrhead in_ifaddr;
1510 struct in_ifaddr *ifa;
1511 for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1512 afsi_SetServerIPRank(sa, ifa);
1516 struct in_ifaddr *ifa;
1517 for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
1518 afsi_SetServerIPRank(sa, ifa);
1522 #endif /* USEIFADDR */
1523 #endif /* AFS_SUN5_ENV */
1524 #endif /* else AFS_USERSPACE_IP_ADDR */
1526 sa->sa_iprank += afs_randomMod15();
1529 } /* afs_SetServerPrefs */
1537 /* afs_FlushServer()
1538 * The addresses on this server struct has changed in some way and will
1539 * clean up all other structures that may reference it.
1540 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1542 void afs_FlushServer(struct server *srvp) {
1544 struct server *ts, **pts;
1546 /* Find any volumes residing on this server and flush their state */
1547 afs_ResetVolumes(srvp);
1549 /* Flush all callbacks in the all vcaches for this specific server */
1550 afs_FlushServerCBs(srvp);
1552 /* Remove all the callbacks structs */
1554 struct afs_cbr *cb, *cbnext;
1556 MObtainWriteLock(&afs_xvcb, 300);
1557 for (cb = srvp->cbrs; cb; cb = cbnext) {
1560 } srvp->cbrs = (struct afs_cbr *)0;
1561 ReleaseWriteLock(&afs_xvcb);
1564 /* If no more srvAddr structs hanging off of this server struct,
1568 /* Remove the server structure from the cell list - if there */
1569 afs_RemoveCellEntry(srvp);
1571 /* Remove from the afs_servers hash chain */
1572 for (i = 0; i < NSERVERS; i++) {
1573 for (pts = &(afs_servers[i]), ts = *pts; ts;
1574 pts = &(ts->next), ts = *pts) {
1582 *pts = ts->next; /* Found it. Remove it */
1583 afs_osi_Free(ts, sizeof(struct server)); /* Free it */
1589 /* afs_RemoveSrvAddr()
1590 * This removes a SrvAddr structure from its server structure.
1591 * The srvAddr struct is not free'd because it connections may still
1592 * be open to it. It is up to the calling process to make sure it
1593 * remains connected to a server struct.
1594 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1595 * It is not removed from the afs_srvAddrs hash chain.
1597 void afs_RemoveSrvAddr(struct srvAddr *sap) {
1598 struct srvAddr **psa, *sa;
1605 /* Find the srvAddr in the server's list and remove it */
1606 for (psa = &(srv->addr), sa = *psa; sa; psa = &(sa->next_sa), sa = *psa) {
1614 /* Flush the server struct since it's IP address has changed */
1615 afs_FlushServer(srv);
1620 * Return an updated and properly initialized server structure
1621 * corresponding to the server ID, cell, and port specified.
1622 * If one does not exist, then one will be created.
1623 * aserver and aport must be in NET byte order.
1625 struct server *afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers,
1626 afs_int32 acell, u_short aport,
1627 afs_int32 locktype, afsUUID * uuidp,
1628 afs_int32 addr_uniquifier) {
1629 struct server *oldts = 0, *ts, *newts, *orphts = 0;
1630 struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1632 afs_int32 iphash, k, srvcount = 0;
1633 unsigned int srvhash;
1635 AFS_STATCNT(afs_GetServer);
1637 ObtainSharedLock(&afs_xserver, 13);
1639 /* Check if the server struct exists and is up to date */
1642 panic("afs_GetServer: incorect count of servers");
1643 ObtainReadLock(&afs_xsrvAddr);
1644 ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1645 ReleaseReadLock(&afs_xsrvAddr);
1646 if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1647 /* Found a server struct that is not multihomed and has the
1648 * IP address associated with it. A correct match.
1650 ReleaseSharedLock(&afs_xserver);
1655 panic("afs_GetServer: incorrect count of servers");
1656 ts = afs_FindServer(0, aport, uuidp, locktype);
1657 if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1658 /* Found a server struct that is multihomed and same
1659 * uniqufier (same IP addrs). The above if statement is the
1660 * same as in InstallUVolumeEntry().
1662 ReleaseSharedLock(&afs_xserver);
1666 oldts = ts; /* Will reuse if same uuid */
1669 UpgradeSToWLock(&afs_xserver, 36);
1670 ObtainWriteLock(&afs_xsrvAddr, 116);
1672 srvcount = afs_totalServers;
1674 /* Reuse/allocate a new server structure */
1678 newts = (struct server *)afs_osi_Alloc(sizeof(struct server));
1680 panic("malloc of server struct");
1682 memset((char *)newts, 0, sizeof(struct server));
1684 /* Add the server struct to the afs_servers[] hash chain */
1686 (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
1687 newts->next = afs_servers[srvhash];
1688 afs_servers[srvhash] = newts;
1691 /* Initialize the server structure */
1692 if (uuidp) { /* Multihomed */
1693 newts->sr_uuid = *uuidp;
1694 newts->sr_addr_uniquifier = addr_uniquifier;
1695 newts->flags |= SRVR_MULTIHOMED;
1698 newts->cell = afs_GetCell(acell, 0);
1700 fsport = (newts->cell ? newts->cell->fsport : AFS_FSPORT);
1702 /* For each IP address we are registering */
1703 for (k = 0; k < nservers; k++) {
1704 iphash = SHash(aserverp[k]);
1706 /* Check if the srvAddr structure already exists. If so, remove
1707 * it from its server structure and add it to the new one.
1709 for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
1710 if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
1713 if (oldsa && (oldsa->server != newts)) {
1714 afs_RemoveSrvAddr(oldsa); /* Remove from its server struct */
1715 oldsa->next_sa = newts->addr; /* Add to the new server struct */
1716 newts->addr = oldsa;
1719 /* Reuse/allocate a new srvAddr structure */
1723 newsa = (struct srvAddr *)afs_osi_Alloc(sizeof(struct srvAddr));
1725 panic("malloc of srvAddr struct");
1726 afs_totalSrvAddrs++;
1727 memset((char *)newsa, 0, sizeof(struct srvAddr));
1729 /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1730 newsa->next_bkt = afs_srvAddrs[iphash];
1731 afs_srvAddrs[iphash] = newsa;
1733 /* Hang off of the server structure */
1734 newsa->next_sa = newts->addr;
1735 newts->addr = newsa;
1737 /* Initialize the srvAddr Structure */
1738 newsa->sa_ip = aserverp[k];
1739 newsa->sa_portal = aport;
1742 /* Update the srvAddr Structure */
1743 newsa->server = newts;
1744 if (newts->flags & SRVR_ISDOWN)
1745 newsa->sa_flags |= SRVADDR_ISDOWN;
1747 newsa->sa_flags |= SRVADDR_MH;
1749 newsa->sa_flags &= ~SRVADDR_MH;
1751 /* Compute preference values and resort */
1752 if (!newsa->sa_iprank) {
1753 afs_SetServerPrefs(newsa); /* new server rank */
1756 afs_SortOneServer(newts); /* Sort by rank */
1758 /* If we reused the server struct, remove any of its srvAddr
1759 * structs that will no longer be associated with this server.
1761 if (oldts) { /* reused the server struct */
1762 for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
1763 nextsa = orphsa->next_sa;
1764 for (k = 0; k < nservers; k++) {
1765 if (orphsa->sa_ip == aserverp[k])
1766 break; /* belongs */
1769 continue; /* belongs */
1771 /* Have a srvAddr struct. Now get a server struct (if not already) */
1774 (struct server *)afs_osi_Alloc(sizeof(struct server));
1776 panic("malloc of lo server struct");
1777 memset((char *)orphts, 0, sizeof(struct server));
1780 /* Add the orphaned server to the afs_servers[] hash chain.
1781 * Its iphash does not matter since we never look up the server
1782 * in the afs_servers table by its ip address (only by uuid -
1783 * which this has none).
1785 iphash = SHash(aserverp[k]);
1786 orphts->next = afs_servers[iphash];
1787 afs_servers[iphash] = orphts;
1790 orphts->cell = afs_GetCell(acell, 0);
1793 /* Hang the srvAddr struct off of the server structure. The server
1794 * may have multiple srvAddrs, but it won't be marked multihomed.
1796 afs_RemoveSrvAddr(orphsa); /* remove */
1797 orphsa->next_sa = orphts->addr; /* hang off server struct */
1798 orphts->addr = orphsa;
1799 orphsa->server = orphts;
1800 orphsa->sa_flags |= SRVADDR_NOUSE; /* flag indicating not in use */
1801 orphsa->sa_flags &= ~SRVADDR_MH; /* Not multihomed */
1805 srvcount = afs_totalServers - srvcount; /* # servers added and removed */
1807 struct afs_stats_SrvUpDownInfo *upDownP;
1808 /* With the introduction of this new record, we need to adjust the
1809 * proper individual & global server up/down info.
1811 upDownP = GetUpDownStats(newts);
1812 upDownP->numTtlRecords += srvcount;
1813 afs_stats_cmperf.srvRecords += srvcount;
1814 if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
1815 afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
1818 ReleaseWriteLock(&afs_xsrvAddr);
1819 ReleaseWriteLock(&afs_xserver);
1821 } /* afs_GetServer */
1823 void afs_ActivateServer(struct srvAddr *sap) {
1824 osi_timeval_t currTime; /*Filled with current time */
1825 osi_timeval_t *currTimeP; /*Ptr to above */
1826 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record */
1827 struct server *aserver = sap->server;
1829 if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
1831 * This server record has not yet been activated. Go for it,
1832 * recording its ``birth''.
1834 aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
1835 currTimeP = &currTime;
1836 osi_GetuTime(currTimeP);
1837 aserver->activationTime = currTime.tv_sec;
1838 upDownP = GetUpDownStats(aserver);
1839 if (aserver->flags & SRVR_ISDOWN) {
1840 upDownP->numDownRecords++;
1842 upDownP->numUpRecords++;
1843 upDownP->numRecordsNeverDown++;
1849 void shutdown_server()
1853 for (i = 0; i < NSERVERS; i++) {
1854 struct server *ts, *next;
1856 ts = afs_servers[i];
1859 afs_osi_Free(ts, sizeof(struct server));
1864 for (i = 0; i < NSERVERS; i++) {
1865 struct srvAddr *sa, *next;
1867 sa = afs_srvAddrs[i];
1869 next = sa->next_bkt;
1870 afs_osi_Free(sa, sizeof(struct srvAddr));