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 afs_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;
543 struct afs_conn **conns;
545 struct rx_connection **rxconns;
546 afs_int32 *conntimer, *deltas, *results;
548 AFS_STATCNT(afs_CheckServers);
551 * No sense in doing the server checks if we are running in disconnected
554 if (AFS_IS_DISCONNECTED)
557 conns = (struct afs_conn **)0;
558 rxconns = (struct rx_connection **) 0;
562 if ((code = afs_InitReq(&treq, afs_osi_credp)))
564 ObtainReadLock(&afs_xserver); /* Necessary? */
565 ObtainReadLock(&afs_xsrvAddr);
568 for (i = 0; i < NSERVERS; i++) {
569 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
574 addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
576 for (i = 0; i < NSERVERS; i++) {
577 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
578 if (j >= srvAddrCount)
584 ReleaseReadLock(&afs_xsrvAddr);
585 ReleaseReadLock(&afs_xserver);
587 conns = (struct afs_conn **)afs_osi_Alloc(j * sizeof(struct afs_conn *));
588 rxconns = (struct rx_connection **)afs_osi_Alloc(j * sizeof(struct rx_connection *));
589 conntimer = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
590 deltas = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
591 results = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
593 for (i = 0; i < j; i++) {
600 /* See if a cell to check was specified. If it is spec'd and not
601 * this server's cell, just skip the server.
603 if (acellp && acellp != ts->cell)
606 if ((!adown && (sa->sa_flags & SRVADDR_ISDOWN))
607 || (adown && !(sa->sa_flags & SRVADDR_ISDOWN)))
610 /* check vlserver with special code */
611 if (sa->sa_portal == AFS_VLPORT) {
612 CheckVLServer(sa, &treq);
616 if (!ts->cell) /* not really an active server, anyway, it must */
617 continue; /* have just been added by setsprefs */
619 /* get a connection, even if host is down; bumps conn ref count */
620 tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
621 tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
622 1 /*force */ , 1 /*create */ , SHARED_LOCK);
623 afs_PutUser(tu, SHARED_LOCK);
627 if ((sa->sa_flags & SRVADDR_ISDOWN) || afs_HaveCallBacksFrom(sa->server)
628 || (tc->srvr->server == afs_setTimeHost)) {
630 rxconns[nconns]=tc->id;
631 if (sa->sa_flags & SRVADDR_ISDOWN) {
632 rx_SetConnDeadTime(tc->id, 3);
639 } /* Outer loop over addrs */
641 start = osi_Time(); /* time the gettimeofday call */
643 multi_Rx(rxconns,nconns)
645 tv.tv_sec = tv.tv_usec = 0;
646 multi_RXAFS_GetTime(&tv.tv_sec, &tv.tv_usec);
649 if (conntimer[multi_i] == 1)
650 rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
652 results[multi_i]=multi_error;
653 if ((start == end) && !multi_error)
654 deltas[multi_i] = end - tv.tv_sec;
659 for(i=0;i<nconns;i++){
663 if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) && (tc->srvr == sa)) {
665 print_internet_address("afs: file server ", sa, " is back up", 2);
667 ObtainWriteLock(&afs_xserver, 244);
668 ObtainWriteLock(&afs_xsrvAddr, 245);
669 afs_MarkServerUpOrDown(sa, 0);
670 ReleaseWriteLock(&afs_xsrvAddr);
671 ReleaseWriteLock(&afs_xserver);
673 if (afs_waitForeverCount) {
674 afs_osi_Wakeup(&afs_waitForever);
677 if (results[i] < 0) {
680 ForceNewConnections(sa); /* multi homed clients */
686 * If we're supposed to set the time, and the call worked
687 * quickly (same second response) and this is the host we
688 * use for the time and the time is really different, then
689 * really set the time
691 if (afs_setTime != 0) {
692 for (i=0; i<nconns; i++) {
697 if ((tc->srvr->server == afs_setTimeHost ||
698 /* Sync only to a server in the local cell */
699 (afs_setTimeHost == (struct server *)0 &&
700 afs_IsPrimaryCell(sa->server->cell)))) {
702 char msgbuf[90]; /* strlen("afs: setting clock...") + slop */
703 delta = end - tv.tv_sec; /* how many secs fast we are */
705 afs_setTimeHost = tc->srvr->server;
706 /* see if clock has changed enough to make it worthwhile */
707 if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) {
709 if (delta > AFS_MAXCHANGEBACK) {
710 /* setting clock too far back, just do it a little */
711 tv.tv_sec = end - AFS_MAXCHANGEBACK;
713 tv.tv_sec = end - delta;
715 afs_osi_SetTime(&tv);
717 strcpy(msgbuf, "afs: setting clock back ");
718 if (delta > AFS_MAXCHANGEBACK) {
720 afs_cv2string(&tbuffer[CVBS],
722 afs_strcat(msgbuf, " seconds (of ");
724 afs_cv2string(&tbuffer[CVBS],
727 afs_strcat(msgbuf, ", via ");
728 print_internet_address(msgbuf, sa,
729 "); clock is still fast.",
733 afs_cv2string(&tbuffer[CVBS], delta));
734 afs_strcat(msgbuf, " seconds (via ");
735 print_internet_address(msgbuf, sa, ").", 0);
738 strcpy(msgbuf, "afs: setting clock ahead ");
740 afs_cv2string(&tbuffer[CVBS], -delta));
741 afs_strcat(msgbuf, " seconds (via ");
742 print_internet_address(msgbuf, sa, ").", 0);
744 /* We're only going to set it once; why bother looping? */
750 for (i = 0; i < nconns; i++) {
751 afs_PutConn(conns[i], SHARED_LOCK); /* done with it now */
754 afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
755 afs_osi_Free(conns, j * sizeof(struct afs_conn *));
756 afs_osi_Free(rxconns, j * sizeof(struct rx_connection *));
757 afs_osi_Free(conntimer, j * sizeof(afs_int32));
758 afs_osi_Free(deltas, j * sizeof(afs_int32));
759 afs_osi_Free(results, j * sizeof(afs_int32));
761 } /*afs_CheckServers*/
764 /* find a server structure given the host address */
766 afs_FindServer(afs_int32 aserver, afs_uint16 aport, afsUUID * uuidp,
773 AFS_STATCNT(afs_FindServer);
775 i = afs_uuid_hash(uuidp) % NSERVERS;
776 for (ts = afs_servers[i]; ts; ts = ts->next) {
777 if ((ts->flags & SRVR_MULTIHOMED)
779 (memcmp((char *)uuidp, (char *)&ts->sr_uuid, sizeof(*uuidp))
780 == 0) && (!ts->addr || (ts->addr->sa_portal == aport)))
785 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
786 if ((sa->sa_ip == aserver) && (sa->sa_portal == aport)) {
793 } /*afs_FindServer */
796 /* some code for creating new server structs and setting preferences follows
797 * in the next few lines...
800 #define MAXDEFRANK 60000
801 #define DEFRANK 40000
803 /* Random number generator and constants from KnuthV2 2d ed, p170 */
809 a is 0.73m should be 0.01m .. 0.99m
810 c is more or less immaterial. 1 or a is suggested.
812 NB: LOW ORDER BITS are not very random. To get small random numbers,
813 treat result as <1, with implied binary point, and multiply by
815 NB: Has to be unsigned, since shifts on signed quantities may preserve
818 /* added rxi_getaddr() to try to get as much initial randomness as
819 possible, since at least one customer reboots ALL their clients
820 simultaneously -- so osi_Time is bound to be the same on some of the
821 clients. This is probably OK, but I don't want to see too much of it.
824 #define ranstage(x) (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
829 static afs_int32 state = 0;
832 AFS_STATCNT(afs_random);
837 * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
838 * bits are in a tv_usec
840 state = (t.tv_usec & (~0 << 4)) + (rxi_getaddr() & 0xff);
841 state += (t.tv_sec & 0xff);
842 for (i = 0; i < 30; i++) {
852 /* returns int 0..14 using the high bits of a pseudo-random number instead of
853 the low bits, as the low bits are "less random" than the high ones...
854 slight roundoff error exists, an excercise for the reader.
855 need to multiply by something with lots of ones in it, so multiply by
856 8 or 16 is right out.
859 afs_randomMod15(void)
863 temp = afs_random() >> 4;
864 temp = (temp * 15) >> 28;
870 afs_randomMod127(void)
874 temp = afs_random() >> 7;
875 temp = (temp * 127) >> 25;
880 /* afs_SortOneServer()
881 * Sort all of the srvAddrs, of a server struct, by rank from low to high.
884 afs_SortOneServer(struct server *asp)
886 struct srvAddr **rootsa, *lowsa, *tsa, *lowprev;
889 for (rootsa = &(asp->addr); *rootsa; rootsa = &(lowsa->next_sa)) {
891 lowsa = *rootsa; /* lowest sa is the first one */
892 lowrank = lowsa->sa_iprank;
894 for (tsa = *rootsa; tsa->next_sa; tsa = tsa->next_sa) {
895 rank = tsa->next_sa->sa_iprank;
896 if (rank < lowrank) {
898 lowsa = tsa->next_sa;
899 lowrank = lowsa->sa_iprank;
902 if (lowprev) { /* found one lower, so rearrange them */
903 lowprev->next_sa = lowsa->next_sa;
904 lowsa->next_sa = *rootsa;
911 * Sort the pointer to servers by the server's rank (its lowest rank).
912 * It is assumed that the server already has its IP addrs sorted (the
913 * first being its lowest rank: afs_GetServer() calls afs_SortOneServer()).
916 afs_SortServers(struct server *aservers[], int count)
921 AFS_STATCNT(afs_SortServers);
923 for (i = 0; i < count; i++) {
926 for (low = i, j = i + 1; j <= count; j++) {
927 if ((!aservers[j]) || (!aservers[j]->addr))
929 if ((!aservers[low]) || (!aservers[low]->addr))
931 if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
937 aservers[i] = aservers[low];
941 } /*afs_SortServers */
943 /* afs_SetServerPrefs is rather system-dependent. It pokes around in kernel
944 data structures to determine what the local IP addresses and subnet masks
945 are in order to choose which server(s) are on the local subnet.
947 As I see it, there are several cases:
948 1. The server address is one of this host's local addresses. In this case
949 this server is to be preferred over all others.
950 2. The server is on the same subnet as one of the this host's local
951 addresses. (ie, an odd-sized subnet, not class A,B,orC)
952 3. The server is on the same net as this host (class A,B or C)
953 4. The server is on a different logical subnet or net than this host, but
954 this host is a 'metric 0 gateway' to it. Ie, two address-spaces share
956 5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
958 6. This host and the server are disjoint.
960 That is a rough order of preference. If a point-to-point link has a high
961 metric, I'm assuming that it is a very slow link, and putting it at the
962 bottom of the list (at least until RX works better over slow links). If
963 its metric is 1, I'm assuming that it's relatively fast (T1) and putting
965 It's not easy to check for case #4, so I'm ignoring it for the time being.
967 BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
968 That could be used to prefer certain servers fairly easily. Maybe some
971 NOTE: this code is very system-dependent, and very dependent on the TCP/IP
972 protocols (well, addresses that are stored in uint32s, at any rate).
975 #define IA_DST(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_dstaddr))
976 #define IA_BROAD(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
978 /* SA2ULONG takes a sockaddr_in, not a sockaddr (same thing, just cast it!) */
979 #define SA2ULONG(sa) ((sa)->sin_addr.s_addr)
984 #define PPWEIGHT 4096
989 #if defined(AFS_SUN5_ENV) && ! defined(AFS_SUN56_ENV)
990 #include <inet/common.h>
991 /* IP interface structure, one per local address */
992 typedef struct ipif_s {
993 /**/ struct ipif_s *ipif_next;
994 struct ill_s *ipif_ill; /* Back pointer to our ill */
995 long ipif_id; /* Logical unit number */
996 u_int ipif_mtu; /* Starts at ipif_ill->ill_max_frag */
997 afs_int32 ipif_local_addr; /* Local IP address for this if. */
998 afs_int32 ipif_net_mask; /* Net mask for this interface. */
999 afs_int32 ipif_broadcast_addr; /* Broadcast addr for this interface. */
1000 afs_int32 ipif_pp_dst_addr; /* Point-to-point dest address. */
1001 u_int ipif_flags; /* Interface flags. */
1002 u_int ipif_metric; /* BSD if metric, for compatibility. */
1003 u_int ipif_ire_type; /* LOCAL or LOOPBACK */
1004 mblk_t *ipif_arp_down_mp; /* Allocated at time arp comes up to
1005 * prevent awkward out of mem condition
1008 mblk_t *ipif_saved_ire_mp; /* Allocated for each extra IRE_SUBNET/
1009 * RESOLVER on this interface so that
1010 * they can survive ifconfig down.
1013 * The packet counts in the ipif contain the sum of the
1014 * packet counts in dead IREs that were affiliated with
1017 u_long ipif_fo_pkt_count; /* Forwarded thru our dead IREs */
1018 u_long ipif_ib_pkt_count; /* Inbound packets for our dead IREs */
1019 u_long ipif_ob_pkt_count; /* Outbound packets to our dead IREs */
1021 ipif_multicast_up:1, /* We have joined the allhosts group */
1025 typedef struct ipfb_s {
1026 /**/ struct ipf_s *ipfb_ipf; /* List of ... */
1027 kmutex_t ipfb_lock; /* Protect all ipf in list */
1030 typedef struct ilm_s {
1031 /**/ afs_int32 ilm_addr;
1033 u_int ilm_timer; /* IGMP */
1034 struct ipif_s *ilm_ipif; /* Back pointer to ipif */
1035 struct ilm_s *ilm_next; /* Linked list for each ill */
1038 typedef struct ill_s {
1039 /**/ struct ill_s *ill_next; /* Chained in at ill_g_head. */
1040 struct ill_s **ill_ptpn; /* Pointer to previous next. */
1041 queue_t *ill_rq; /* Read queue. */
1042 queue_t *ill_wq; /* Write queue. */
1044 int ill_error; /* Error value sent up by device. */
1046 ipif_t *ill_ipif; /* Interface chain for this ILL. */
1047 u_int ill_ipif_up_count; /* Number of IPIFs currently up. */
1048 u_int ill_max_frag; /* Max IDU. */
1049 char *ill_name; /* Our name. */
1050 u_int ill_name_length; /* Name length, incl. terminator. */
1051 u_int ill_subnet_type; /* IRE_RESOLVER or IRE_SUBNET. */
1052 u_int ill_ppa; /* Physical Point of Attachment num. */
1054 int ill_sap_length; /* Including sign (for position) */
1055 u_int ill_phys_addr_length; /* Excluding the sap. */
1056 mblk_t *ill_frag_timer_mp; /* Reassembly timer state. */
1057 ipfb_t *ill_frag_hash_tbl; /* Fragment hash list head. */
1059 queue_t *ill_bind_pending_q; /* Queue waiting for DL_BIND_ACK. */
1060 ipif_t *ill_ipif_pending; /* IPIF waiting for DL_BIND_ACK. */
1062 /* ill_hdr_length and ill_hdr_mp will be non zero if
1063 * the underlying device supports the M_DATA fastpath
1067 ilm_t *ill_ilm; /* Multicast mebership for lower ill */
1069 /* All non-nil cells between 'ill_first_mp_to_free' and
1070 * 'ill_last_mp_to_free' are freed in ill_delete.
1072 #define ill_first_mp_to_free ill_hdr_mp
1073 mblk_t *ill_hdr_mp; /* Contains fastpath template */
1074 mblk_t *ill_bcast_mp; /* DLPI header for broadcasts. */
1075 mblk_t *ill_bind_pending; /* T_BIND_REQ awaiting completion. */
1076 mblk_t *ill_resolver_mp; /* Resolver template. */
1077 mblk_t *ill_attach_mp;
1078 mblk_t *ill_bind_mp;
1079 mblk_t *ill_unbind_mp;
1080 mblk_t *ill_detach_mp;
1081 #define ill_last_mp_to_free ill_detach_mp
1083 u_int ill_frag_timer_running:1, ill_needs_attach:1, ill_is_ptp:1,
1084 ill_priv_stream:1, ill_unbind_pending:1, ill_pad_to_bit_31:27;
1085 MI_HRT_DCL(ill_rtime)
1086 MI_HRT_DCL(ill_rtmp)
1090 #ifdef AFS_USERSPACE_IP_ADDR
1092 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1095 * The IP addresses and ranks are determined by afsd (in user space) and
1096 * passed into the kernel at startup time through the AFSOP_ADVISEADDR
1097 * system call. These are stored in the data structure
1098 * called 'afs_cb_interface'.
1100 * struct srvAddr *sa; remote server
1101 * afs_int32 addr; one of my local addr in net order
1102 * afs_uint32 subnetmask; subnet mask of local addr in net order
1106 afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr,
1107 afs_uint32 subnetmask)
1109 afs_uint32 myAddr, myNet, mySubnet, netMask;
1110 afs_uint32 serverAddr;
1112 myAddr = ntohl(addr); /* one of my IP addr in host order */
1113 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1114 subnetmask = ntohl(subnetmask); /* subnet mask in host order */
1116 if (IN_CLASSA(myAddr))
1117 netMask = IN_CLASSA_NET;
1118 else if (IN_CLASSB(myAddr))
1119 netMask = IN_CLASSB_NET;
1120 else if (IN_CLASSC(myAddr))
1121 netMask = IN_CLASSC_NET;
1125 myNet = myAddr & netMask;
1126 mySubnet = myAddr & subnetmask;
1128 if ((serverAddr & netMask) == myNet) {
1129 if ((serverAddr & subnetmask) == mySubnet) {
1130 if (serverAddr == myAddr) { /* same machine */
1131 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1132 } else { /* same subnet */
1133 sa->sa_iprank = afs_min(sa->sa_iprank, HI);
1135 } else { /* same net */
1136 sa->sa_iprank = afs_min(sa->sa_iprank, MED);
1141 #else /* AFS_USERSPACE_IP_ADDR */
1142 #if (! defined(AFS_SUN5_ENV)) && !defined(AFS_DARWIN60_ENV) && defined(USEIFADDR)
1144 afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
1146 struct sockaddr_in *sin;
1149 if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
1150 if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
1152 if (SA2ULONG(sin) == ntohl(sa->sa_ip)) { /* ie, ME!!! */
1153 sa->sa_iprank = TOPR;
1155 t = HI + ifa->ia_ifp->if_metric; /* case #2 */
1156 if (sa->sa_iprank > t)
1160 t = MED + ifa->ia_ifp->if_metric; /* case #3 */
1161 if (sa->sa_iprank > t)
1165 #ifdef IFF_POINTTOPOINT
1166 /* check for case #4 -- point-to-point link */
1167 if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
1168 && (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
1169 if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1172 t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
1173 if (sa->sa_iprank > t)
1176 #endif /* IFF_POINTTOPOINT */
1178 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1179 #if defined(AFS_DARWIN60_ENV) && defined(USEIFADDR)
1181 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1184 afsi_SetServerIPRank(sa, ifa)
1186 #ifdef AFS_DARWIN80_ENV
1192 struct sockaddr sout;
1193 struct sockaddr_in *sin;
1196 afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
1197 afs_uint32 serverAddr;
1199 if (ifaddr_address_family(ifa) != AF_INET)
1201 t = ifaddr_address(ifa, &sout, sizeof(sout));
1203 sin = (struct sockaddr_in *)&sout;
1204 myAddr = ntohl(sin->sin_addr.s_addr); /* one of my IP addr in host order */
1208 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1209 t = ifaddr_netmask(ifa, &sout, sizeof(sout));
1211 sin = (struct sockaddr_in *)&sout;
1212 subnetmask = ntohl(sin->sin_addr.s_addr); /* subnet mask in host order */
1216 t = ifaddr_dstaddress(ifa, &sout, sizeof(sout));
1218 sin = (struct sockaddr_in *)&sout;
1219 myDstaddr = sin->sin_addr.s_addr;
1224 if (IN_CLASSA(myAddr))
1225 netMask = IN_CLASSA_NET;
1226 else if (IN_CLASSB(myAddr))
1227 netMask = IN_CLASSB_NET;
1228 else if (IN_CLASSC(myAddr))
1229 netMask = IN_CLASSC_NET;
1233 myNet = myAddr & netMask;
1234 mySubnet = myAddr & subnetmask;
1236 if ((serverAddr & netMask) == myNet) {
1237 if ((serverAddr & subnetmask) == mySubnet) {
1238 if (serverAddr == myAddr) { /* same machine */
1239 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1240 } else { /* same subnet */
1241 sa->sa_iprank = afs_min(sa->sa_iprank, HI + ifnet_metric(ifaddr_ifnet(ifa)));
1243 } else { /* same net */
1244 sa->sa_iprank = afs_min(sa->sa_iprank, MED + ifnet_metric(ifaddr_ifnet(ifa)));
1247 #ifdef IFF_POINTTOPOINT
1248 /* check for case #4 -- point-to-point link */
1249 if ((ifnet_flags(ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
1250 && (myDstaddr == serverAddr)) {
1251 if (ifnet_metric(ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
1254 t = MED + (PPWEIGHT << ifnet_metric(ifaddr_ifnet(ifa)));
1255 if (sa->sa_iprank > t)
1258 #endif /* IFF_POINTTOPOINT */
1260 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1261 #endif /* else AFS_USERSPACE_IP_ADDR */
1263 #ifdef AFS_SGI62_ENV
1266 afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1268 afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
1269 return 0; /* Never match, so we enumerate everyone */
1271 #endif /* AFS_SGI62_ENV */
1272 static int afs_SetServerPrefs(struct srvAddr *sa) {
1273 #if defined(AFS_USERSPACE_IP_ADDR)
1277 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1278 afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1279 afs_cb_interface.subnetmask[i]);
1281 #else /* AFS_USERSPACE_IP_ADDR */
1282 #if defined(AFS_SUN5_ENV)
1283 #ifdef AFS_SUN510_ENV
1286 extern struct ill_s *ill_g_headp;
1287 long *addr = (long *)ill_g_headp;
1291 int subnet, subnetmask, net, netmask;
1295 #ifdef AFS_SUN510_ENV
1296 rw_enter(&afsifinfo_lock, RW_READER);
1298 for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
1300 if (IN_CLASSA(afsifinfo[i].ipaddr)) {
1301 netmask = IN_CLASSA_NET;
1302 } else if (IN_CLASSB(afsifinfo[i].ipaddr)) {
1303 netmask = IN_CLASSB_NET;
1304 } else if (IN_CLASSC(afsifinfo[i].ipaddr)) {
1305 netmask = IN_CLASSC_NET;
1309 net = afsifinfo[i].ipaddr & netmask;
1313 if (afsifinfo[i].ipaddr != 0x7f000001) { /* ignore loopback */
1317 *addrp++ = afsifinfo[i].ipaddr;
1322 /* XXXXXX Do the individual ip ranking below XXXXX */
1323 if ((sa->sa_ip & netmask) == net) {
1324 if ((sa->sa_ip & subnetmask) == subnet) {
1325 if (afsifinfo[i].ipaddr == sa->sa_ip) { /* ie, ME! */
1326 sa->sa_iprank = TOPR;
1328 sa->sa_iprank = HI + afsifinfo[i].metric; /* case #2 */
1331 sa->sa_iprank = MED + afsifinfo[i].metric; /* case #3 */
1334 sa->sa_iprank = LO + afsifinfo[i].metric; /* case #4 */
1336 /* check for case #5 -- point-to-point link */
1337 if ((afsifinfo[i].flags & IFF_POINTOPOINT)
1338 && (afsifinfo[i].dstaddr == sa->sa_ip)) {
1340 if (afsifinfo[i].metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1341 sa->sa_iprank = MAXDEFRANK;
1343 sa->sa_iprank = MED + (PPWEIGHT << afsifinfo[i].metric);
1348 rw_exit(&afsifinfo_lock);
1350 for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
1351 ill = ill->ill_next) {
1352 #ifdef AFS_SUN58_ENV
1353 /* Make sure this is an IPv4 ILL */
1357 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
1358 subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1359 subnetmask = ipif->ipif_net_mask;
1361 * Generate the local net using the local address and
1362 * whate we know about Class A, B and C networks.
1364 if (IN_CLASSA(ipif->ipif_local_addr)) {
1365 netmask = IN_CLASSA_NET;
1366 } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1367 netmask = IN_CLASSB_NET;
1368 } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1369 netmask = IN_CLASSC_NET;
1373 net = ipif->ipif_local_addr & netmask;
1376 if (ipif->ipif_local_addr != 0x7f000001) { /* ignore loopback */
1380 *addrp++ = ipif->ipif_local_addr;
1385 /* XXXXXX Do the individual ip ranking below XXXXX */
1386 if ((sa->sa_ip & netmask) == net) {
1387 if ((sa->sa_ip & subnetmask) == subnet) {
1388 if (ipif->ipif_local_addr == sa->sa_ip) { /* ie, ME! */
1389 sa->sa_iprank = TOPR;
1391 sa->sa_iprank = HI + ipif->ipif_metric; /* case #2 */
1394 sa->sa_iprank = MED + ipif->ipif_metric; /* case #3 */
1397 sa->sa_iprank = LO + ipif->ipif_metric; /* case #4 */
1399 /* check for case #5 -- point-to-point link */
1400 if ((ipif->ipif_flags & IFF_POINTOPOINT)
1401 && (ipif->ipif_pp_dst_addr == sa->sa_ip)) {
1403 if (ipif->ipif_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1404 sa->sa_iprank = MAXDEFRANK;
1406 sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1411 #endif /* AFS_SUN510_ENV */
1414 struct ifnet *ifn = NULL;
1415 struct in_ifaddr *ifad = (struct in_ifaddr *)0;
1416 struct sockaddr_in *sin;
1419 #ifdef notdef /* clean up, remove this */
1420 for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
1421 for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next) {
1422 if ((IFADDR2SA(ifad)->sa_family == AF_INET)
1423 && !(ifn->if_flags & IFF_LOOPBACK)) {
1428 ((struct sockaddr_in *)IFADDR2SA(ifad))->sin_addr.
1437 ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1439 if (ifn) { /* local, more or less */
1441 if (ifn->if_flags & IFF_LOOPBACK) {
1442 sa->sa_iprank = TOPR;
1445 #endif /* IFF_LOOPBACK */
1446 sin = (struct sockaddr_in *)IA_SIN(ifad);
1447 if (SA2ULONG(sin) == sa->sa_ip) {
1448 sa->sa_iprank = TOPR;
1451 #ifdef IFF_BROADCAST
1452 if (ifn->if_flags & IFF_BROADCAST) {
1453 if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1458 #endif /* IFF_BROADCAST */
1459 #ifdef IFF_POINTOPOINT
1460 if (ifn->if_flags & IFF_POINTOPOINT) {
1461 if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1462 if (ifn->if_metric > 4) {
1466 sa->sa_iprank = ifn->if_metric;
1469 #endif /* IFF_POINTOPOINT */
1470 sa->sa_iprank += MED + ifn->if_metric; /* couldn't find anything better */
1472 #else /* USEIFADDR */
1476 #ifdef AFS_SGI62_ENV
1477 (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1478 (caddr_t) sa, NULL);
1479 #elif defined(AFS_DARWIN80_ENV)
1487 if (!ifnet_list_get(AF_INET, &ifn, &count)) {
1488 for (m = 0; m < count; m++) {
1489 if (!ifnet_get_address_list(ifn[m], &ifads)) {
1490 for (j = 0; ifads[j] != NULL && cnt < ADDRSPERSITE; j++) {
1491 afsi_SetServerIPRank(sa, ifads[j]);
1494 ifnet_free_address_list(ifads);
1497 ifnet_list_free(ifn);
1500 #elif defined(AFS_DARWIN60_ENV)
1504 TAILQ_FOREACH(ifn, &ifnet, if_link) {
1505 TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
1506 afsi_SetServerIPRank(sa, ifa);
1508 #elif defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1510 struct in_ifaddr *ifa;
1511 TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
1512 afsi_SetServerIPRank(sa, ifa);
1514 #elif defined(AFS_OBSD_ENV)
1516 extern struct in_ifaddrhead in_ifaddr;
1517 struct in_ifaddr *ifa;
1518 for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1519 afsi_SetServerIPRank(sa, ifa);
1523 struct in_ifaddr *ifa;
1524 for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
1525 afsi_SetServerIPRank(sa, ifa);
1529 #endif /* USEIFADDR */
1530 #endif /* AFS_SUN5_ENV */
1531 #endif /* else AFS_USERSPACE_IP_ADDR */
1533 sa->sa_iprank += afs_randomMod15();
1536 } /* afs_SetServerPrefs */
1544 /* afs_FlushServer()
1545 * The addresses on this server struct has changed in some way and will
1546 * clean up all other structures that may reference it.
1547 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1549 void afs_FlushServer(struct server *srvp) {
1551 struct server *ts, **pts;
1553 /* Find any volumes residing on this server and flush their state */
1554 afs_ResetVolumes(srvp);
1556 /* Flush all callbacks in the all vcaches for this specific server */
1557 afs_FlushServerCBs(srvp);
1559 /* Remove all the callbacks structs */
1561 struct afs_cbr *cb, *cbnext;
1563 MObtainWriteLock(&afs_xvcb, 300);
1564 for (cb = srvp->cbrs; cb; cb = cbnext) {
1567 } srvp->cbrs = (struct afs_cbr *)0;
1568 ReleaseWriteLock(&afs_xvcb);
1571 /* If no more srvAddr structs hanging off of this server struct,
1575 /* Remove the server structure from the cell list - if there */
1576 afs_RemoveCellEntry(srvp);
1578 /* Remove from the afs_servers hash chain */
1579 for (i = 0; i < NSERVERS; i++) {
1580 for (pts = &(afs_servers[i]), ts = *pts; ts;
1581 pts = &(ts->next), ts = *pts) {
1589 *pts = ts->next; /* Found it. Remove it */
1590 afs_osi_Free(ts, sizeof(struct server)); /* Free it */
1596 /* afs_RemoveSrvAddr()
1597 * This removes a SrvAddr structure from its server structure.
1598 * The srvAddr struct is not free'd because it connections may still
1599 * be open to it. It is up to the calling process to make sure it
1600 * remains connected to a server struct.
1601 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1602 * It is not removed from the afs_srvAddrs hash chain.
1604 void afs_RemoveSrvAddr(struct srvAddr *sap) {
1605 struct srvAddr **psa, *sa;
1612 /* Find the srvAddr in the server's list and remove it */
1613 for (psa = &(srv->addr), sa = *psa; sa; psa = &(sa->next_sa), sa = *psa) {
1621 /* Flush the server struct since it's IP address has changed */
1622 afs_FlushServer(srv);
1627 * Return an updated and properly initialized server structure
1628 * corresponding to the server ID, cell, and port specified.
1629 * If one does not exist, then one will be created.
1630 * aserver and aport must be in NET byte order.
1632 struct server *afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers,
1633 afs_int32 acell, u_short aport,
1634 afs_int32 locktype, afsUUID * uuidp,
1635 afs_int32 addr_uniquifier) {
1636 struct server *oldts = 0, *ts, *newts, *orphts = 0;
1637 struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1639 afs_int32 iphash, k, srvcount = 0;
1640 unsigned int srvhash;
1642 AFS_STATCNT(afs_GetServer);
1644 ObtainSharedLock(&afs_xserver, 13);
1646 /* Check if the server struct exists and is up to date */
1649 panic("afs_GetServer: incorect count of servers");
1650 ObtainReadLock(&afs_xsrvAddr);
1651 ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1652 ReleaseReadLock(&afs_xsrvAddr);
1653 if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1654 /* Found a server struct that is not multihomed and has the
1655 * IP address associated with it. A correct match.
1657 ReleaseSharedLock(&afs_xserver);
1662 panic("afs_GetServer: incorrect count of servers");
1663 ts = afs_FindServer(0, aport, uuidp, locktype);
1664 if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1665 /* Found a server struct that is multihomed and same
1666 * uniqufier (same IP addrs). The above if statement is the
1667 * same as in InstallUVolumeEntry().
1669 ReleaseSharedLock(&afs_xserver);
1673 oldts = ts; /* Will reuse if same uuid */
1676 UpgradeSToWLock(&afs_xserver, 36);
1677 ObtainWriteLock(&afs_xsrvAddr, 116);
1679 srvcount = afs_totalServers;
1681 /* Reuse/allocate a new server structure */
1685 newts = (struct server *)afs_osi_Alloc(sizeof(struct server));
1687 panic("malloc of server struct");
1689 memset((char *)newts, 0, sizeof(struct server));
1691 /* Add the server struct to the afs_servers[] hash chain */
1693 (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
1694 newts->next = afs_servers[srvhash];
1695 afs_servers[srvhash] = newts;
1698 /* Initialize the server structure */
1699 if (uuidp) { /* Multihomed */
1700 newts->sr_uuid = *uuidp;
1701 newts->sr_addr_uniquifier = addr_uniquifier;
1702 newts->flags |= SRVR_MULTIHOMED;
1705 newts->cell = afs_GetCell(acell, 0);
1707 fsport = (newts->cell ? newts->cell->fsport : AFS_FSPORT);
1709 /* For each IP address we are registering */
1710 for (k = 0; k < nservers; k++) {
1711 iphash = SHash(aserverp[k]);
1713 /* Check if the srvAddr structure already exists. If so, remove
1714 * it from its server structure and add it to the new one.
1716 for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
1717 if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
1720 if (oldsa && (oldsa->server != newts)) {
1721 afs_RemoveSrvAddr(oldsa); /* Remove from its server struct */
1722 oldsa->next_sa = newts->addr; /* Add to the new server struct */
1723 newts->addr = oldsa;
1726 /* Reuse/allocate a new srvAddr structure */
1730 newsa = (struct srvAddr *)afs_osi_Alloc(sizeof(struct srvAddr));
1732 panic("malloc of srvAddr struct");
1733 afs_totalSrvAddrs++;
1734 memset((char *)newsa, 0, sizeof(struct srvAddr));
1736 /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1737 newsa->next_bkt = afs_srvAddrs[iphash];
1738 afs_srvAddrs[iphash] = newsa;
1740 /* Hang off of the server structure */
1741 newsa->next_sa = newts->addr;
1742 newts->addr = newsa;
1744 /* Initialize the srvAddr Structure */
1745 newsa->sa_ip = aserverp[k];
1746 newsa->sa_portal = aport;
1749 /* Update the srvAddr Structure */
1750 newsa->server = newts;
1751 if (newts->flags & SRVR_ISDOWN)
1752 newsa->sa_flags |= SRVADDR_ISDOWN;
1754 newsa->sa_flags |= SRVADDR_MH;
1756 newsa->sa_flags &= ~SRVADDR_MH;
1758 /* Compute preference values and resort */
1759 if (!newsa->sa_iprank) {
1760 afs_SetServerPrefs(newsa); /* new server rank */
1763 afs_SortOneServer(newts); /* Sort by rank */
1765 /* If we reused the server struct, remove any of its srvAddr
1766 * structs that will no longer be associated with this server.
1768 if (oldts) { /* reused the server struct */
1769 for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
1770 nextsa = orphsa->next_sa;
1771 for (k = 0; k < nservers; k++) {
1772 if (orphsa->sa_ip == aserverp[k])
1773 break; /* belongs */
1776 continue; /* belongs */
1778 /* Have a srvAddr struct. Now get a server struct (if not already) */
1781 (struct server *)afs_osi_Alloc(sizeof(struct server));
1783 panic("malloc of lo server struct");
1784 memset((char *)orphts, 0, sizeof(struct server));
1787 /* Add the orphaned server to the afs_servers[] hash chain.
1788 * Its iphash does not matter since we never look up the server
1789 * in the afs_servers table by its ip address (only by uuid -
1790 * which this has none).
1792 iphash = SHash(aserverp[k]);
1793 orphts->next = afs_servers[iphash];
1794 afs_servers[iphash] = orphts;
1797 orphts->cell = afs_GetCell(acell, 0);
1800 /* Hang the srvAddr struct off of the server structure. The server
1801 * may have multiple srvAddrs, but it won't be marked multihomed.
1803 afs_RemoveSrvAddr(orphsa); /* remove */
1804 orphsa->next_sa = orphts->addr; /* hang off server struct */
1805 orphts->addr = orphsa;
1806 orphsa->server = orphts;
1807 orphsa->sa_flags |= SRVADDR_NOUSE; /* flag indicating not in use */
1808 orphsa->sa_flags &= ~SRVADDR_MH; /* Not multihomed */
1812 srvcount = afs_totalServers - srvcount; /* # servers added and removed */
1814 struct afs_stats_SrvUpDownInfo *upDownP;
1815 /* With the introduction of this new record, we need to adjust the
1816 * proper individual & global server up/down info.
1818 upDownP = GetUpDownStats(newts);
1819 upDownP->numTtlRecords += srvcount;
1820 afs_stats_cmperf.srvRecords += srvcount;
1821 if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
1822 afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
1825 ReleaseWriteLock(&afs_xsrvAddr);
1826 ReleaseWriteLock(&afs_xserver);
1828 } /* afs_GetServer */
1830 void afs_ActivateServer(struct srvAddr *sap) {
1831 osi_timeval_t currTime; /*Filled with current time */
1832 osi_timeval_t *currTimeP; /*Ptr to above */
1833 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record */
1834 struct server *aserver = sap->server;
1836 if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
1838 * This server record has not yet been activated. Go for it,
1839 * recording its ``birth''.
1841 aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
1842 currTimeP = &currTime;
1843 osi_GetuTime(currTimeP);
1844 aserver->activationTime = currTime.tv_sec;
1845 upDownP = GetUpDownStats(aserver);
1846 if (aserver->flags & SRVR_ISDOWN) {
1847 upDownP->numDownRecords++;
1849 upDownP->numUpRecords++;
1850 upDownP->numRecordsNeverDown++;
1855 void afs_RemoveAllConns()
1858 struct server *ts, *nts;
1860 struct afs_conn *tc, *ntc;
1862 ObtainReadLock(&afs_xserver);
1863 ObtainWriteLock(&afs_xconn, 1001);
1865 /*printf("Destroying connections ... ");*/
1866 for (i = 0; i < NSERVERS; i++) {
1867 for (ts = afs_servers[i]; ts; ts = nts) {
1869 for (sa = ts->addr; sa; sa = sa->next_sa) {
1875 rx_DestroyConnection(tc->id);
1877 afs_osi_Free(tc, sizeof(struct afs_conn));
1885 /*printf("done\n");*/
1887 ReleaseWriteLock(&afs_xconn);
1888 ReleaseReadLock(&afs_xserver);
1892 void afs_MarkAllServersUp()
1898 ObtainWriteLock(&afs_xserver, 721);
1899 ObtainWriteLock(&afs_xsrvAddr, 722);
1900 for (i = 0; i< NSERVERS; i++) {
1901 for (ts = afs_servers[i]; ts; ts = ts->next) {
1902 for (sa = ts->addr; sa; sa = sa->next_sa) {
1903 afs_MarkServerUpOrDown(sa, 0);
1907 ReleaseWriteLock(&afs_xsrvAddr);
1908 ReleaseWriteLock(&afs_xserver);
1911 void shutdown_server()
1915 for (i = 0; i < NSERVERS; i++) {
1916 struct server *ts, *next;
1918 ts = afs_servers[i];
1921 afs_osi_Free(ts, sizeof(struct server));
1926 for (i = 0; i < NSERVERS; i++) {
1927 struct srvAddr *sa, *next;
1929 sa = afs_srvAddrs[i];
1931 next = sa->next_bkt;
1932 afs_osi_Free(sa, sizeof(struct srvAddr));