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"
37 #include "afs/sysincludes.h" /* Standard vendor system headers */
40 #if !defined(AFS_LINUX20_ENV)
43 #include <netinet/in.h>
46 #include "h/hashing.h"
48 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV)
49 #include <netinet/in_var.h>
50 #endif /* AFS_HPUX110_ENV */
52 #include <net/if_var.h>
54 #endif /* !defined(UKERNEL) */
56 #include "afsincludes.h" /* Afs-based standard headers */
57 #include "afs/afs_stats.h" /* afs statistics */
58 #include "rx/rx_multi.h"
60 #if defined(AFS_SUN56_ENV)
62 #include <inet/common.h>
63 #if defined(AFS_SUN58_ENV)
64 # include <netinet/ip6.h>
65 # define ipif_local_addr ipif_lcl_addr
66 # ifndef V4_PART_OF_V6
67 # define V4_PART_OF_V6(v6) v6.s6_addr32[3]
73 /* Exported variables */
74 afs_rwlock_t afs_xserver; /* allocation lock for servers */
75 struct server *afs_setTimeHost = 0; /* last host we used for time */
76 struct server *afs_servers[NSERVERS]; /* Hashed by server`s uuid & 1st ip */
77 afs_rwlock_t afs_xsrvAddr; /* allocation lock for srvAddrs */
78 struct srvAddr *afs_srvAddrs[NSERVERS]; /* Hashed by server's ip */
81 /* debugging aids - number of alloc'd server and srvAddr structs. */
82 int afs_reuseServers = 0;
83 int afs_reuseSrvAddrs = 0;
84 int afs_totalServers = 0;
85 int afs_totalSrvAddrs = 0;
89 static struct afs_stats_SrvUpDownInfo *
90 GetUpDownStats(struct server *srv)
92 struct afs_stats_SrvUpDownInfo *upDownP;
93 u_short fsport = AFS_FSPORT;
96 fsport = srv->cell->fsport;
98 if (srv->addr->sa_portal == fsport)
99 upDownP = afs_stats_cmperf.fs_UpDown;
101 upDownP = afs_stats_cmperf.vl_UpDown;
103 if (srv->cell && afs_IsPrimaryCell(srv->cell))
104 return &upDownP[AFS_STATS_UPDOWN_IDX_SAME_CELL];
106 return &upDownP[AFS_STATS_UPDOWN_IDX_DIFF_CELL];
110 /*------------------------------------------------------------------------
111 * afs_MarkServerUpOrDown
114 * Mark the given server up or down, and track its uptime stats.
117 * a_serverP : Ptr to server record to fiddle with.
118 * a_isDown : Is the server is to be marked down?
124 * The CM server structures must be write-locked.
128 *------------------------------------------------------------------------*/
131 afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
133 struct server *a_serverP = sa->server;
135 osi_timeval_t currTime, *currTimeP; /*Current time */
136 afs_int32 downTime; /*Computed downtime, in seconds */
137 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record */
140 * If the server record is marked the same as the new status we've
141 * been fed, then there isn't much to be done.
143 if ((a_isDown && (sa->sa_flags & SRVADDR_ISDOWN))
144 || (!a_isDown && !(sa->sa_flags & SRVADDR_ISDOWN)))
148 sa->sa_flags |= SRVADDR_ISDOWN;
149 for (sap = a_serverP->addr; sap; sap = sap->next_sa) {
150 if (!(sap->sa_flags & SRVADDR_ISDOWN)) {
151 /* Not all ips are up so don't bother with the
152 * server's up/down stats */
157 * All ips are down we treat the whole server down
159 a_serverP->flags |= SRVR_ISDOWN;
161 * If this was our time server, search for another time server
163 if (a_serverP == afs_setTimeHost)
166 sa->sa_flags &= ~SRVADDR_ISDOWN;
167 /* If any ips are up, the server is also marked up */
168 a_serverP->flags &= ~SRVR_ISDOWN;
169 for (sap = a_serverP->addr; sap; sap = sap->next_sa) {
170 if (sap->sa_flags & SRVADDR_ISDOWN) {
171 /* Not all ips are up so don't bother with the
172 * server's up/down stats */
179 * Compute the current time and which overall stats record is to be
180 * updated; we'll need them one way or another.
182 currTimeP = &currTime;
183 osi_GetuTime(currTimeP);
185 upDownP = GetUpDownStats(a_serverP);
189 * Server going up -> down; remember the beginning of this
192 a_serverP->lastDowntimeStart = currTime.tv_sec;
194 (upDownP->numDownRecords)++;
195 (upDownP->numUpRecords)--;
196 } /*Server being marked down */
199 * Server going down -> up; remember everything about this
200 * newly-completed downtime incident.
202 downTime = currTime.tv_sec - a_serverP->lastDowntimeStart;
203 (a_serverP->numDowntimeIncidents)++;
204 a_serverP->sumOfDowntimes += downTime;
206 (upDownP->numUpRecords)++;
207 (upDownP->numDownRecords)--;
208 (upDownP->numDowntimeIncidents)++;
209 if (a_serverP->numDowntimeIncidents == 1)
210 (upDownP->numRecordsNeverDown)--;
211 upDownP->sumOfDowntimes += downTime;
212 if ((upDownP->shortestDowntime == 0)
213 || (downTime < upDownP->shortestDowntime))
214 upDownP->shortestDowntime = downTime;
215 if ((upDownP->longestDowntime == 0)
216 || (downTime > upDownP->longestDowntime))
217 upDownP->longestDowntime = downTime;
220 if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET0)
221 (upDownP->downDurations[0])++;
222 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET1)
223 (upDownP->downDurations[1])++;
224 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET2)
225 (upDownP->downDurations[2])++;
226 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET3)
227 (upDownP->downDurations[3])++;
228 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET4)
229 (upDownP->downDurations[4])++;
230 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET5)
231 (upDownP->downDurations[5])++;
233 (upDownP->downDurations[6])++;
235 } /*Server being marked up */
237 } /*MarkServerUpOrDown */
241 afs_ServerDown(struct srvAddr *sa)
243 struct server *aserver = sa->server;
245 AFS_STATCNT(ServerDown);
246 if (aserver->flags & SRVR_ISDOWN || sa->sa_flags & SRVADDR_ISDOWN)
248 afs_MarkServerUpOrDown(sa, SRVR_ISDOWN);
249 if (sa->sa_portal == aserver->cell->vlport)
250 print_internet_address
251 ("afs: Lost contact with volume location server ", sa, "", 1);
253 print_internet_address("afs: Lost contact with file server ", sa, "",
259 /* return true if we have any callback promises from this server */
261 afs_HaveCallBacksFrom(struct server *aserver)
267 AFS_STATCNT(HaveCallBacksFrom);
268 now = osi_Time(); /* for checking for expired callbacks */
269 for (i = 0; i < VCSIZE; i++) { /* for all guys in the hash table */
270 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
272 * Check to see if this entry has an unexpired callback promise
273 * from the required host
275 if (aserver == tvc->callback && tvc->cbExpires >= now
276 && ((tvc->f.states & CRO) == 0))
282 } /*HaveCallBacksFrom */
286 CheckVLServer(struct srvAddr *sa, struct vrequest *areq)
288 struct server *aserver = sa->server;
292 AFS_STATCNT(CheckVLServer);
293 /* Ping dead servers to see if they're back */
294 if (!((aserver->flags & SRVR_ISDOWN) || (sa->sa_flags & SRVADDR_ISDOWN))
295 || (aserver->flags & SRVR_ISGONE))
298 return; /* can't do much */
300 tc = afs_ConnByHost(aserver, aserver->cell->vlport,
301 aserver->cell->cellNum, areq, 1, SHARED_LOCK);
304 rx_SetConnDeadTime(tc->id, 3);
307 code = VL_ProbeServer(tc->id);
309 rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
310 afs_PutConn(tc, SHARED_LOCK);
312 * If probe worked, or probe call not yet defined (for compatibility
313 * with old vlsevers), then we treat this server as running again
315 if (code == 0 || (code <= -450 && code >= -470)) {
316 if (tc->parent->srvr == sa) {
317 afs_MarkServerUpOrDown(sa, 0);
318 print_internet_address("afs: volume location server ", sa,
326 #ifndef AFS_MINCHANGE /* So that some can increase it in param.h */
327 #define AFS_MINCHANGE 2 /* min change we'll bother with */
329 #ifndef AFS_MAXCHANGEBACK
330 #define AFS_MAXCHANGEBACK 10 /* max seconds we'll set a clock back at once */
334 /*------------------------------------------------------------------------
335 * EXPORTED afs_CountServers
338 * Originally meant to count the number of servers and determining
339 * up/down info, this routine will now simply sum up all of the
340 * server record ages. All other up/down information is kept on the
350 * This routine locks afs_xserver for write for the duration.
353 * Set CM perf stats field sumOfRecordAges for all server record
355 *------------------------------------------------------------------------*/
358 afs_CountServers(void)
360 int currIdx; /*Curr idx into srv table */
361 struct server *currSrvP; /*Ptr to curr server record */
362 afs_int32 currChainLen; /*Length of curr hash chain */
363 osi_timeval_t currTime; /*Current time */
364 osi_timeval_t *currTimeP; /*Ptr to above */
365 afs_int32 srvRecordAge; /*Age of server record, in secs */
366 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to current up/down
367 * info being manipulated */
370 * Write-lock the server table so we don't get any interference.
372 ObtainReadLock(&afs_xserver);
375 * Iterate over each hash index in the server table, walking down each
376 * chain and tallying what we haven't computed from the records there on
377 * the fly. First, though, initialize the tallies that will change.
379 afs_stats_cmperf.srvMaxChainLength = 0;
381 afs_stats_cmperf.fs_UpDown[0].sumOfRecordAges = 0;
382 afs_stats_cmperf.fs_UpDown[0].ageOfYoungestRecord = 0;
383 afs_stats_cmperf.fs_UpDown[0].ageOfOldestRecord = 0;
384 memset(afs_stats_cmperf.fs_UpDown[0].downIncidents, 0,
385 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
387 afs_stats_cmperf.fs_UpDown[1].sumOfRecordAges = 0;
388 afs_stats_cmperf.fs_UpDown[1].ageOfYoungestRecord = 0;
389 afs_stats_cmperf.fs_UpDown[1].ageOfOldestRecord = 0;
390 memset(afs_stats_cmperf.fs_UpDown[1].downIncidents, 0,
391 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
393 afs_stats_cmperf.vl_UpDown[0].sumOfRecordAges = 0;
394 afs_stats_cmperf.vl_UpDown[0].ageOfYoungestRecord = 0;
395 afs_stats_cmperf.vl_UpDown[0].ageOfOldestRecord = 0;
396 memset(afs_stats_cmperf.vl_UpDown[0].downIncidents, 0,
397 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
399 afs_stats_cmperf.vl_UpDown[1].sumOfRecordAges = 0;
400 afs_stats_cmperf.vl_UpDown[1].ageOfYoungestRecord = 0;
401 afs_stats_cmperf.vl_UpDown[1].ageOfOldestRecord = 0;
402 memset(afs_stats_cmperf.vl_UpDown[1].downIncidents, 0,
403 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
406 * Compute the current time, used to figure out server record ages.
408 currTimeP = &currTime;
409 osi_GetuTime(currTimeP);
412 * Sweep the server hash table, tallying all we need to know.
414 for (currIdx = 0; currIdx < NSERVERS; currIdx++) {
416 for (currSrvP = afs_servers[currIdx]; currSrvP;
417 currSrvP = currSrvP->next) {
419 * Bump the current chain length.
424 * Any further tallying for this record will only be done if it has
427 if ((currSrvP->flags & AFS_SERVER_FLAG_ACTIVATED)
428 && currSrvP->addr && currSrvP->cell) {
431 * Compute the current server record's age, then remember it
432 * in the appropriate places.
434 srvRecordAge = currTime.tv_sec - currSrvP->activationTime;
435 upDownP = GetUpDownStats(currSrvP);
436 upDownP->sumOfRecordAges += srvRecordAge;
437 if ((upDownP->ageOfYoungestRecord == 0)
438 || (srvRecordAge < upDownP->ageOfYoungestRecord))
439 upDownP->ageOfYoungestRecord = srvRecordAge;
440 if ((upDownP->ageOfOldestRecord == 0)
441 || (srvRecordAge > upDownP->ageOfOldestRecord))
442 upDownP->ageOfOldestRecord = srvRecordAge;
444 if (currSrvP->numDowntimeIncidents <=
445 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET0)
446 (upDownP->downIncidents[0])++;
447 else if (currSrvP->numDowntimeIncidents <=
448 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET1)
449 (upDownP->downIncidents[1])++;
450 else if (currSrvP->numDowntimeIncidents <=
451 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET2)
452 (upDownP->downIncidents[2])++;
453 else if (currSrvP->numDowntimeIncidents <=
454 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET3)
455 (upDownP->downIncidents[3])++;
456 else if (currSrvP->numDowntimeIncidents <=
457 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET4)
458 (upDownP->downIncidents[4])++;
460 (upDownP->downIncidents[5])++;
463 } /*Current server has been active */
464 } /*Walk this chain */
467 * Before advancing to the next chain, remember facts about this one.
469 if (currChainLen > afs_stats_cmperf.srvMaxChainLength) {
471 * We beat out the former champion (which was initially set to 0
472 * here). Mark down the new winner, and also remember if it's an
475 afs_stats_cmperf.srvMaxChainLength = currChainLen;
476 if (currChainLen > afs_stats_cmperf.srvMaxChainLengthHWM)
477 afs_stats_cmperf.srvMaxChainLengthHWM = currChainLen;
478 } /*Update chain length maximum */
479 } /*For each hash chain */
482 * We're done. Unlock the server table before returning to our caller.
484 ReleaseReadLock(&afs_xserver);
486 } /*afs_CountServers */
490 ForceAllNewConnections(void)
493 struct srvAddr **addrs;
497 ObtainReadLock(&afs_xserver); /* Necessary? */
498 ObtainReadLock(&afs_xsrvAddr);
501 for (i = 0; i < NSERVERS; i++) {
502 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
507 addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
508 osi_Assert(addrs != NULL);
510 for (i = 0; i < NSERVERS; i++) {
511 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
512 if (j >= srvAddrCount)
518 ReleaseReadLock(&afs_xsrvAddr);
519 ReleaseReadLock(&afs_xserver);
520 for (i = 0; i < j; i++) {
522 ForceNewConnections(sa);
526 /* check down servers (if adown), or running servers (if !adown) */
528 afs_CheckServers(int adown, struct cell *acellp)
530 struct vrequest treq;
536 afs_int32 start, end = 0, delta;
541 struct srvAddr **addrs;
542 struct afs_conn **conns;
544 struct rx_connection **rxconns;
545 afs_int32 *conntimer, *deltas, *results;
546 Capabilities *caps = NULL;
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));
575 osi_Assert(addrs != NULL);
577 for (i = 0; i < NSERVERS; i++) {
578 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
579 if (j >= srvAddrCount)
585 ReleaseReadLock(&afs_xsrvAddr);
586 ReleaseReadLock(&afs_xserver);
588 conns = afs_osi_Alloc(j * sizeof(struct afs_conn *));
589 osi_Assert(conns != NULL);
590 rxconns = afs_osi_Alloc(j * sizeof(struct rx_connection *));
591 osi_Assert(rxconns != NULL);
592 conntimer = afs_osi_Alloc(j * sizeof (afs_int32));
593 osi_Assert(conntimer != NULL);
594 deltas = afs_osi_Alloc(j * sizeof (afs_int32));
595 osi_Assert(deltas != NULL);
596 results = afs_osi_Alloc(j * sizeof (afs_int32));
597 osi_Assert(results != NULL);
599 caps = afs_osi_Alloc(j * sizeof (Capabilities));
600 osi_Assert(caps != NULL);
601 memset(caps, 0, j * sizeof(Capabilities));
603 for (i = 0; i < j; i++) {
610 /* See if a cell to check was specified. If it is spec'd and not
611 * this server's cell, just skip the server.
613 if (acellp && acellp != ts->cell)
616 if ((!adown && (sa->sa_flags & SRVADDR_ISDOWN))
617 || (adown && !(sa->sa_flags & SRVADDR_ISDOWN)))
620 /* check vlserver with special code */
621 if (sa->sa_portal == AFS_VLPORT) {
622 CheckVLServer(sa, &treq);
626 if (!ts->cell) /* not really an active server, anyway, it must */
627 continue; /* have just been added by setsprefs */
629 /* get a connection, even if host is down; bumps conn ref count */
630 tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
631 tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
632 1 /*force */ , 1 /*create */ , SHARED_LOCK);
633 afs_PutUser(tu, SHARED_LOCK);
637 if ((sa->sa_flags & SRVADDR_ISDOWN) || afs_HaveCallBacksFrom(sa->server)
638 || (tc->parent->srvr->server == afs_setTimeHost)) {
640 rxconns[nconns]=tc->id;
641 if (sa->sa_flags & SRVADDR_ISDOWN) {
642 rx_SetConnDeadTime(tc->id, 3);
649 } /* Outer loop over addrs */
652 multi_Rx(rxconns,nconns)
654 multi_RXAFS_GetCapabilities(&caps[multi_i]);
655 results[multi_i] = multi_error;
659 for ( i = 0 ; i < nconns ; i++ ) {
660 ts = addrs[i]->server;
663 ts->capabilities = 0;
664 ts->flags |= SCAPS_KNOWN;
665 if ( results[i] == RXGEN_OPCODE ) {
666 /* Mark server as up - it responded */
670 if ( results[i] >= 0 )
671 /* we currently handle 32-bits of capabilities */
672 if (caps[i].Capabilities_len > 0) {
673 ts->capabilities = caps[i].Capabilities_val[0];
674 xdr_free((xdrproc_t)xdr_Capabilities, &caps[i]);
675 caps[i].Capabilities_val = NULL;
676 caps[i].Capabilities_len = 0;
680 if ( afs_setTime != 0 ) {
681 start = osi_Time(); /* time the gettimeofday call */
683 if ( afs_setTimeHost == NULL ) {
684 multi_Rx(rxconns,nconns)
686 tv.tv_sec = tv.tv_usec = 0;
688 (afs_uint32 *)&tv.tv_sec, (afs_uint32 *)&tv.tv_usec);
690 sa = tc->parent->srvr;
691 if (conntimer[multi_i] == 1)
692 rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
694 results[multi_i]=multi_error;
695 if ((start == end) && !multi_error)
696 deltas[multi_i] = end - tv.tv_sec;
699 else { /* find and query setTimeHost only */
700 for ( i = 0 ; i < j ; i++ ) {
701 if ( conns[i] == NULL || conns[i]->parent->srvr == NULL )
703 if ( conns[i]->parent->srvr->server == afs_setTimeHost ) {
704 tv.tv_sec = tv.tv_usec = 0;
705 results[i] = RXAFS_GetTime(rxconns[i],
706 (afs_uint32 *)&tv.tv_sec, (afs_uint32 *)&tv.tv_usec);
708 if ((start == end) && !results[i])
709 deltas[i] = end - tv.tv_sec;
717 for(i=0;i<nconns;i++){
719 sa = tc->parent->srvr;
721 if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) && (tc->parent->srvr == sa)) {
723 print_internet_address("afs: file server ", sa, " is back up", 2);
725 ObtainWriteLock(&afs_xserver, 244);
726 ObtainWriteLock(&afs_xsrvAddr, 245);
727 afs_MarkServerUpOrDown(sa, 0);
728 ReleaseWriteLock(&afs_xsrvAddr);
729 ReleaseWriteLock(&afs_xserver);
731 if (afs_waitForeverCount) {
732 afs_osi_Wakeup(&afs_waitForever);
735 if ((results[i] < 0) && (results[i] != RXGEN_OPCODE)) {
738 ForceNewConnections(sa); /* multi homed clients */
744 * If we're supposed to set the time, and the call worked
745 * quickly (same second response) and this is the host we
746 * use for the time and the time is really different, then
747 * really set the time
749 if (afs_setTime != 0) {
750 for (i=0; i<nconns; i++) {
753 sa = tc->parent->srvr;
755 if ((tc->parent->srvr->server == afs_setTimeHost ||
756 /* Sync only to a server in the local cell */
757 (afs_setTimeHost == (struct server *)0 &&
758 afs_IsPrimaryCell(sa->server->cell)))) {
760 char msgbuf[90]; /* strlen("afs: setting clock...") + slop */
761 delta = end - tv.tv_sec; /* how many secs fast we are */
763 afs_setTimeHost = tc->parent->srvr->server;
764 /* see if clock has changed enough to make it worthwhile */
765 if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) {
767 if (delta > AFS_MAXCHANGEBACK) {
768 /* setting clock too far back, just do it a little */
769 tv.tv_sec = end - AFS_MAXCHANGEBACK;
771 tv.tv_sec = end - delta;
773 afs_osi_SetTime(&tv);
775 strcpy(msgbuf, "afs: setting clock back ");
776 if (delta > AFS_MAXCHANGEBACK) {
778 afs_cv2string(&tbuffer[CVBS],
780 afs_strcat(msgbuf, " seconds (of ");
782 afs_cv2string(&tbuffer[CVBS],
785 afs_strcat(msgbuf, ", via ");
786 print_internet_address(msgbuf, sa,
787 "); clock is still fast.",
791 afs_cv2string(&tbuffer[CVBS], delta));
792 afs_strcat(msgbuf, " seconds (via ");
793 print_internet_address(msgbuf, sa, ").", 0);
796 strcpy(msgbuf, "afs: setting clock ahead ");
798 afs_cv2string(&tbuffer[CVBS], -delta));
799 afs_strcat(msgbuf, " seconds (via ");
800 print_internet_address(msgbuf, sa, ").", 0);
802 /* We're only going to set it once; why bother looping? */
808 for (i = 0; i < nconns; i++) {
809 afs_PutConn(conns[i], SHARED_LOCK); /* done with it now */
812 afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
813 afs_osi_Free(conns, j * sizeof(struct afs_conn *));
814 afs_osi_Free(rxconns, j * sizeof(struct rx_connection *));
815 afs_osi_Free(conntimer, j * sizeof(afs_int32));
816 afs_osi_Free(deltas, j * sizeof(afs_int32));
817 afs_osi_Free(results, j * sizeof(afs_int32));
818 afs_osi_Free(caps, j * sizeof(Capabilities));
820 } /*afs_CheckServers*/
823 /* find a server structure given the host address */
825 afs_FindServer(afs_int32 aserver, afs_uint16 aport, afsUUID * uuidp,
832 AFS_STATCNT(afs_FindServer);
834 i = afs_uuid_hash(uuidp) % NSERVERS;
835 for (ts = afs_servers[i]; ts; ts = ts->next) {
836 if ((ts->flags & SRVR_MULTIHOMED)
838 (memcmp((char *)uuidp, (char *)&ts->sr_uuid, sizeof(*uuidp))
839 == 0) && (!ts->addr || (ts->addr->sa_portal == aport)))
844 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
845 if ((sa->sa_ip == aserver) && (sa->sa_portal == aport)) {
852 } /*afs_FindServer */
855 /* some code for creating new server structs and setting preferences follows
856 * in the next few lines...
859 #define MAXDEFRANK 60000
860 #define DEFRANK 40000
862 /* Random number generator and constants from KnuthV2 2d ed, p170 */
868 a is 0.73m should be 0.01m .. 0.99m
869 c is more or less immaterial. 1 or a is suggested.
871 NB: LOW ORDER BITS are not very random. To get small random numbers,
872 treat result as <1, with implied binary point, and multiply by
874 NB: Has to be unsigned, since shifts on signed quantities may preserve
877 /* added rxi_getaddr() to try to get as much initial randomness as
878 possible, since at least one customer reboots ALL their clients
879 simultaneously -- so osi_Time is bound to be the same on some of the
880 clients. This is probably OK, but I don't want to see too much of it.
883 #define ranstage(x) (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
888 static afs_int32 state = 0;
891 AFS_STATCNT(afs_random);
896 * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
897 * bits are in a tv_usec
899 state = (t.tv_usec & (~0 << 4)) + (rxi_getaddr() & 0xff);
900 state += (t.tv_sec & 0xff);
901 for (i = 0; i < 30; i++) {
911 /* returns int 0..14 using the high bits of a pseudo-random number instead of
912 the low bits, as the low bits are "less random" than the high ones...
913 slight roundoff error exists, an excercise for the reader.
914 need to multiply by something with lots of ones in it, so multiply by
915 8 or 16 is right out.
918 afs_randomMod15(void)
922 temp = afs_random() >> 4;
923 temp = (temp * 15) >> 28;
929 afs_randomMod127(void)
933 temp = afs_random() >> 7;
934 temp = (temp * 127) >> 25;
939 /* afs_SortOneServer()
940 * Sort all of the srvAddrs, of a server struct, by rank from low to high.
943 afs_SortOneServer(struct server *asp)
945 struct srvAddr **rootsa, *lowsa, *tsa, *lowprev;
948 for (rootsa = &(asp->addr); *rootsa; rootsa = &(lowsa->next_sa)) {
950 lowsa = *rootsa; /* lowest sa is the first one */
951 lowrank = lowsa->sa_iprank;
953 for (tsa = *rootsa; tsa->next_sa; tsa = tsa->next_sa) {
954 rank = tsa->next_sa->sa_iprank;
955 if (rank < lowrank) {
957 lowsa = tsa->next_sa;
958 lowrank = lowsa->sa_iprank;
961 if (lowprev) { /* found one lower, so rearrange them */
962 lowprev->next_sa = lowsa->next_sa;
963 lowsa->next_sa = *rootsa;
970 * Sort the pointer to servers by the server's rank (its lowest rank).
971 * It is assumed that the server already has its IP addrs sorted (the
972 * first being its lowest rank: afs_GetServer() calls afs_SortOneServer()).
975 afs_SortServers(struct server *aservers[], int count)
980 AFS_STATCNT(afs_SortServers);
982 for (i = 0; i < count; i++) {
985 for (low = i, j = i + 1; j <= count; j++) {
986 if ((!aservers[j]) || (!aservers[j]->addr))
988 if ((!aservers[low]) || (!aservers[low]->addr))
990 if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
996 aservers[i] = aservers[low];
1000 } /*afs_SortServers */
1002 /* afs_SetServerPrefs is rather system-dependent. It pokes around in kernel
1003 data structures to determine what the local IP addresses and subnet masks
1004 are in order to choose which server(s) are on the local subnet.
1006 As I see it, there are several cases:
1007 1. The server address is one of this host's local addresses. In this case
1008 this server is to be preferred over all others.
1009 2. The server is on the same subnet as one of the this host's local
1010 addresses. (ie, an odd-sized subnet, not class A,B,orC)
1011 3. The server is on the same net as this host (class A,B or C)
1012 4. The server is on a different logical subnet or net than this host, but
1013 this host is a 'metric 0 gateway' to it. Ie, two address-spaces share
1014 one physical medium.
1015 5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
1017 6. This host and the server are disjoint.
1019 That is a rough order of preference. If a point-to-point link has a high
1020 metric, I'm assuming that it is a very slow link, and putting it at the
1021 bottom of the list (at least until RX works better over slow links). If
1022 its metric is 1, I'm assuming that it's relatively fast (T1) and putting
1024 It's not easy to check for case #4, so I'm ignoring it for the time being.
1026 BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
1027 That could be used to prefer certain servers fairly easily. Maybe some
1030 NOTE: this code is very system-dependent, and very dependent on the TCP/IP
1031 protocols (well, addresses that are stored in uint32s, at any rate).
1034 #define IA_DST(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_dstaddr))
1035 #define IA_BROAD(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
1037 /* SA2ULONG takes a sockaddr_in, not a sockaddr (same thing, just cast it!) */
1038 #define SA2ULONG(sa) ((sa)->sin_addr.s_addr)
1043 #define PPWEIGHT 4096
1048 #if defined(AFS_SUN5_ENV) && ! defined(AFS_SUN56_ENV)
1049 #include <inet/common.h>
1050 /* IP interface structure, one per local address */
1051 typedef struct ipif_s {
1052 /**/ struct ipif_s *ipif_next;
1053 struct ill_s *ipif_ill; /* Back pointer to our ill */
1054 long ipif_id; /* Logical unit number */
1055 u_int ipif_mtu; /* Starts at ipif_ill->ill_max_frag */
1056 afs_int32 ipif_local_addr; /* Local IP address for this if. */
1057 afs_int32 ipif_net_mask; /* Net mask for this interface. */
1058 afs_int32 ipif_broadcast_addr; /* Broadcast addr for this interface. */
1059 afs_int32 ipif_pp_dst_addr; /* Point-to-point dest address. */
1060 u_int ipif_flags; /* Interface flags. */
1061 u_int ipif_metric; /* BSD if metric, for compatibility. */
1062 u_int ipif_ire_type; /* LOCAL or LOOPBACK */
1063 mblk_t *ipif_arp_down_mp; /* Allocated at time arp comes up to
1064 * prevent awkward out of mem condition
1067 mblk_t *ipif_saved_ire_mp; /* Allocated for each extra IRE_SUBNET/
1068 * RESOLVER on this interface so that
1069 * they can survive ifconfig down.
1072 * The packet counts in the ipif contain the sum of the
1073 * packet counts in dead IREs that were affiliated with
1076 u_long ipif_fo_pkt_count; /* Forwarded thru our dead IREs */
1077 u_long ipif_ib_pkt_count; /* Inbound packets for our dead IREs */
1078 u_long ipif_ob_pkt_count; /* Outbound packets to our dead IREs */
1080 ipif_multicast_up:1, /* We have joined the allhosts group */
1084 typedef struct ipfb_s {
1085 /**/ struct ipf_s *ipfb_ipf; /* List of ... */
1086 kmutex_t ipfb_lock; /* Protect all ipf in list */
1089 typedef struct ilm_s {
1090 /**/ afs_int32 ilm_addr;
1092 u_int ilm_timer; /* IGMP */
1093 struct ipif_s *ilm_ipif; /* Back pointer to ipif */
1094 struct ilm_s *ilm_next; /* Linked list for each ill */
1097 typedef struct ill_s {
1098 /**/ struct ill_s *ill_next; /* Chained in at ill_g_head. */
1099 struct ill_s **ill_ptpn; /* Pointer to previous next. */
1100 queue_t *ill_rq; /* Read queue. */
1101 queue_t *ill_wq; /* Write queue. */
1103 int ill_error; /* Error value sent up by device. */
1105 ipif_t *ill_ipif; /* Interface chain for this ILL. */
1106 u_int ill_ipif_up_count; /* Number of IPIFs currently up. */
1107 u_int ill_max_frag; /* Max IDU. */
1108 char *ill_name; /* Our name. */
1109 u_int ill_name_length; /* Name length, incl. terminator. */
1110 u_int ill_subnet_type; /* IRE_RESOLVER or IRE_SUBNET. */
1111 u_int ill_ppa; /* Physical Point of Attachment num. */
1113 int ill_sap_length; /* Including sign (for position) */
1114 u_int ill_phys_addr_length; /* Excluding the sap. */
1115 mblk_t *ill_frag_timer_mp; /* Reassembly timer state. */
1116 ipfb_t *ill_frag_hash_tbl; /* Fragment hash list head. */
1118 queue_t *ill_bind_pending_q; /* Queue waiting for DL_BIND_ACK. */
1119 ipif_t *ill_ipif_pending; /* IPIF waiting for DL_BIND_ACK. */
1121 /* ill_hdr_length and ill_hdr_mp will be non zero if
1122 * the underlying device supports the M_DATA fastpath
1126 ilm_t *ill_ilm; /* Multicast mebership for lower ill */
1128 /* All non-nil cells between 'ill_first_mp_to_free' and
1129 * 'ill_last_mp_to_free' are freed in ill_delete.
1131 #define ill_first_mp_to_free ill_hdr_mp
1132 mblk_t *ill_hdr_mp; /* Contains fastpath template */
1133 mblk_t *ill_bcast_mp; /* DLPI header for broadcasts. */
1134 mblk_t *ill_bind_pending; /* T_BIND_REQ awaiting completion. */
1135 mblk_t *ill_resolver_mp; /* Resolver template. */
1136 mblk_t *ill_attach_mp;
1137 mblk_t *ill_bind_mp;
1138 mblk_t *ill_unbind_mp;
1139 mblk_t *ill_detach_mp;
1140 #define ill_last_mp_to_free ill_detach_mp
1142 u_int ill_frag_timer_running:1, ill_needs_attach:1, ill_is_ptp:1,
1143 ill_priv_stream:1, ill_unbind_pending:1, ill_pad_to_bit_31:27;
1144 MI_HRT_DCL(ill_rtime)
1145 MI_HRT_DCL(ill_rtmp)
1149 #ifdef AFS_USERSPACE_IP_ADDR
1151 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1154 * The IP addresses and ranks are determined by afsd (in user space) and
1155 * passed into the kernel at startup time through the AFSOP_ADVISEADDR
1156 * system call. These are stored in the data structure
1157 * called 'afs_cb_interface'.
1159 * struct srvAddr *sa; remote server
1160 * afs_int32 addr; one of my local addr in net order
1161 * afs_uint32 subnetmask; subnet mask of local addr in net order
1165 afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr,
1166 afs_uint32 subnetmask)
1168 afs_uint32 myAddr, myNet, mySubnet, netMask;
1169 afs_uint32 serverAddr;
1171 myAddr = ntohl(addr); /* one of my IP addr in host order */
1172 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1173 subnetmask = ntohl(subnetmask); /* subnet mask in host order */
1175 if (IN_CLASSA(myAddr))
1176 netMask = IN_CLASSA_NET;
1177 else if (IN_CLASSB(myAddr))
1178 netMask = IN_CLASSB_NET;
1179 else if (IN_CLASSC(myAddr))
1180 netMask = IN_CLASSC_NET;
1184 myNet = myAddr & netMask;
1185 mySubnet = myAddr & subnetmask;
1187 if ((serverAddr & netMask) == myNet) {
1188 if ((serverAddr & subnetmask) == mySubnet) {
1189 if (serverAddr == myAddr) { /* same machine */
1190 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1191 } else { /* same subnet */
1192 sa->sa_iprank = afs_min(sa->sa_iprank, HI);
1194 } else { /* same net */
1195 sa->sa_iprank = afs_min(sa->sa_iprank, MED);
1200 #else /* AFS_USERSPACE_IP_ADDR */
1201 #if (! defined(AFS_SUN5_ENV)) && (! defined(AFS_DARWIN_ENV)) && (! defined(AFS_OBSD47_ENV)) && defined(USEIFADDR)
1203 afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
1205 struct sockaddr_in *sin;
1208 if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
1209 if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
1211 if (SA2ULONG(sin) == ntohl(sa->sa_ip)) { /* ie, ME!!! */
1212 sa->sa_iprank = TOPR;
1214 t = HI + ifa->ia_ifp->if_metric; /* case #2 */
1215 if (sa->sa_iprank > t)
1219 t = MED + ifa->ia_ifp->if_metric; /* case #3 */
1220 if (sa->sa_iprank > t)
1224 #ifdef IFF_POINTTOPOINT
1225 /* check for case #4 -- point-to-point link */
1226 if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
1227 && (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
1228 if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1231 t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
1232 if (sa->sa_iprank > t)
1235 #endif /* IFF_POINTTOPOINT */
1237 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1238 #if (defined(AFS_DARWIN_ENV) || defined(AFS_OBSD47_ENV)) && defined(USEIFADDR)
1240 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1243 afsi_SetServerIPRank(struct srvAddr *sa, rx_ifaddr_t ifa)
1245 struct sockaddr sout;
1246 struct sockaddr_in *sin;
1249 afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
1250 afs_uint32 serverAddr;
1252 if (rx_ifaddr_address_family(ifa) != AF_INET)
1254 t = rx_ifaddr_address(ifa, &sout, sizeof(sout));
1256 sin = (struct sockaddr_in *)&sout;
1257 myAddr = ntohl(sin->sin_addr.s_addr); /* one of my IP addr in host order */
1261 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1262 t = rx_ifaddr_netmask(ifa, &sout, sizeof(sout));
1264 sin = (struct sockaddr_in *)&sout;
1265 subnetmask = ntohl(sin->sin_addr.s_addr); /* subnet mask in host order */
1269 t = rx_ifaddr_dstaddress(ifa, &sout, sizeof(sout));
1271 sin = (struct sockaddr_in *)&sout;
1272 myDstaddr = ntohl(sin->sin_addr.s_addr);
1277 if (IN_CLASSA(myAddr))
1278 netMask = IN_CLASSA_NET;
1279 else if (IN_CLASSB(myAddr))
1280 netMask = IN_CLASSB_NET;
1281 else if (IN_CLASSC(myAddr))
1282 netMask = IN_CLASSC_NET;
1286 myNet = myAddr & netMask;
1287 mySubnet = myAddr & subnetmask;
1289 if ((serverAddr & netMask) == myNet) {
1290 if ((serverAddr & subnetmask) == mySubnet) {
1291 if (serverAddr == myAddr) { /* same machine */
1292 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1293 } else { /* same subnet */
1294 sa->sa_iprank = afs_min(sa->sa_iprank, HI + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1296 } else { /* same net */
1297 sa->sa_iprank = afs_min(sa->sa_iprank, MED + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1300 #ifdef IFF_POINTTOPOINT
1301 /* check for case #4 -- point-to-point link */
1302 if ((rx_ifnet_flags(rx_ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
1303 && (myDstaddr == serverAddr)) {
1304 if (rx_ifnet_metric(rx_ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
1307 t = MED + (PPWEIGHT << rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1308 if (sa->sa_iprank > t)
1311 #endif /* IFF_POINTTOPOINT */
1313 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1314 #endif /* else AFS_USERSPACE_IP_ADDR */
1316 #ifdef AFS_SGI62_ENV
1318 afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1321 afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
1322 return 0; /* Never match, so we enumerate everyone */
1324 #endif /* AFS_SGI62_ENV */
1326 afs_SetServerPrefs(struct srvAddr *sa)
1328 #if defined(AFS_USERSPACE_IP_ADDR)
1332 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1333 afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1334 afs_cb_interface.subnetmask[i]);
1336 #else /* AFS_USERSPACE_IP_ADDR */
1337 #if defined(AFS_SUN5_ENV)
1338 #ifdef AFS_SUN510_ENV
1341 extern struct ill_s *ill_g_headp;
1342 long *addr = (long *)ill_g_headp;
1346 int subnet, subnetmask, net, netmask;
1350 #ifdef AFS_SUN510_ENV
1351 rw_enter(&afsifinfo_lock, RW_READER);
1353 for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
1355 if (IN_CLASSA(afsifinfo[i].ipaddr)) {
1356 netmask = IN_CLASSA_NET;
1357 } else if (IN_CLASSB(afsifinfo[i].ipaddr)) {
1358 netmask = IN_CLASSB_NET;
1359 } else if (IN_CLASSC(afsifinfo[i].ipaddr)) {
1360 netmask = IN_CLASSC_NET;
1364 net = afsifinfo[i].ipaddr & netmask;
1368 if (!rx_IsLoopbackAddr(afsifinfo[i].ipaddr)) { /* ignore loopback */
1372 *addrp++ = afsifinfo[i].ipaddr;
1377 /* XXXXXX Do the individual ip ranking below XXXXX */
1378 if ((sa->sa_ip & netmask) == net) {
1379 if ((sa->sa_ip & subnetmask) == subnet) {
1380 if (afsifinfo[i].ipaddr == sa->sa_ip) { /* ie, ME! */
1381 sa->sa_iprank = TOPR;
1383 sa->sa_iprank = HI + afsifinfo[i].metric; /* case #2 */
1386 sa->sa_iprank = MED + afsifinfo[i].metric; /* case #3 */
1389 sa->sa_iprank = LO + afsifinfo[i].metric; /* case #4 */
1391 /* check for case #5 -- point-to-point link */
1392 if ((afsifinfo[i].flags & IFF_POINTOPOINT)
1393 && (afsifinfo[i].dstaddr == sa->sa_ip)) {
1395 if (afsifinfo[i].metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1396 sa->sa_iprank = MAXDEFRANK;
1398 sa->sa_iprank = MED + (PPWEIGHT << afsifinfo[i].metric);
1403 rw_exit(&afsifinfo_lock);
1405 for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
1406 ill = ill->ill_next) {
1407 #ifdef AFS_SUN58_ENV
1408 /* Make sure this is an IPv4 ILL */
1412 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
1413 subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1414 subnetmask = ipif->ipif_net_mask;
1416 * Generate the local net using the local address and
1417 * whate we know about Class A, B and C networks.
1419 if (IN_CLASSA(ipif->ipif_local_addr)) {
1420 netmask = IN_CLASSA_NET;
1421 } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1422 netmask = IN_CLASSB_NET;
1423 } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1424 netmask = IN_CLASSC_NET;
1428 net = ipif->ipif_local_addr & netmask;
1431 if (!rx_IsLoopbackAddr(ipif->ipif_local_addr)) { /* ignore loopback */
1435 *addrp++ = ipif->ipif_local_addr;
1440 /* XXXXXX Do the individual ip ranking below XXXXX */
1441 if ((sa->sa_ip & netmask) == net) {
1442 if ((sa->sa_ip & subnetmask) == subnet) {
1443 if (ipif->ipif_local_addr == sa->sa_ip) { /* ie, ME! */
1444 sa->sa_iprank = TOPR;
1446 sa->sa_iprank = HI + ipif->ipif_metric; /* case #2 */
1449 sa->sa_iprank = MED + ipif->ipif_metric; /* case #3 */
1452 sa->sa_iprank = LO + ipif->ipif_metric; /* case #4 */
1454 /* check for case #5 -- point-to-point link */
1455 if ((ipif->ipif_flags & IFF_POINTOPOINT)
1456 && (ipif->ipif_pp_dst_addr == sa->sa_ip)) {
1458 if (ipif->ipif_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1459 sa->sa_iprank = MAXDEFRANK;
1461 sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1466 #endif /* AFS_SUN510_ENV */
1469 rx_ifnet_t ifn = NULL;
1470 struct in_ifaddr *ifad = (struct in_ifaddr *)0;
1471 struct sockaddr_in *sin;
1474 #ifdef notdef /* clean up, remove this */
1475 for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
1476 for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next) {
1477 if ((IFADDR2SA(ifad)->sa_family == AF_INET)
1478 && !(ifn->if_flags & IFF_LOOPBACK)) {
1483 ((struct sockaddr_in *)IFADDR2SA(ifad))->sin_addr.
1492 ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1494 if (ifn) { /* local, more or less */
1496 if (ifn->if_flags & IFF_LOOPBACK) {
1497 sa->sa_iprank = TOPR;
1500 #endif /* IFF_LOOPBACK */
1501 sin = (struct sockaddr_in *)IA_SIN(ifad);
1502 if (SA2ULONG(sin) == sa->sa_ip) {
1503 sa->sa_iprank = TOPR;
1506 #ifdef IFF_BROADCAST
1507 if (ifn->if_flags & IFF_BROADCAST) {
1508 if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1513 #endif /* IFF_BROADCAST */
1514 #ifdef IFF_POINTOPOINT
1515 if (ifn->if_flags & IFF_POINTOPOINT) {
1516 if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1517 if (ifn->if_metric > 4) {
1521 sa->sa_iprank = ifn->if_metric;
1524 #endif /* IFF_POINTOPOINT */
1525 sa->sa_iprank += MED + ifn->if_metric; /* couldn't find anything better */
1527 #else /* USEIFADDR */
1531 #ifdef AFS_SGI62_ENV
1532 (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1533 (caddr_t) sa, NULL);
1534 #elif defined(AFS_DARWIN80_ENV)
1542 if (!ifnet_list_get(AF_INET, &ifns, &count)) {
1543 for (m = 0; m < count; m++) {
1544 if (!ifnet_get_address_list(ifns[m], &ifads)) {
1545 for (j = 0; ifads[j] != NULL && cnt < ADDRSPERSITE; j++) {
1546 afsi_SetServerIPRank(sa, ifads[j]);
1549 ifnet_free_address_list(ifads);
1552 ifnet_list_free(ifns);
1555 #elif defined(AFS_DARWIN_ENV)
1559 TAILQ_FOREACH(ifn, &ifnet, if_link) {
1560 TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
1561 afsi_SetServerIPRank(sa, ifa);
1563 #elif defined(AFS_FBSD_ENV)
1565 struct in_ifaddr *ifa;
1566 TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
1567 afsi_SetServerIPRank(sa, ifa);
1569 #elif defined(AFS_OBSD_ENV)
1571 extern struct in_ifaddrhead in_ifaddr;
1572 struct in_ifaddr *ifa;
1573 for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1574 afsi_SetServerIPRank(sa, ifa);
1576 #elif defined(AFS_NBSD40_ENV)
1578 extern struct in_ifaddrhead in_ifaddrhead;
1579 struct in_ifaddr *ifa;
1580 for (ifa = in_ifaddrhead.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1581 afsi_SetServerIPRank(sa, ifa);
1585 struct in_ifaddr *ifa;
1586 for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
1587 afsi_SetServerIPRank(sa, ifa);
1590 #endif /* USEIFADDR */
1594 #endif /* AFS_SUN5_ENV */
1595 #endif /* else AFS_USERSPACE_IP_ADDR */
1597 sa->sa_iprank += afs_randomMod15();
1600 } /* afs_SetServerPrefs */
1608 /* afs_FlushServer()
1609 * The addresses on this server struct has changed in some way and will
1610 * clean up all other structures that may reference it.
1611 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1614 afs_FlushServer(struct server *srvp)
1617 struct server *ts, **pts;
1619 /* Find any volumes residing on this server and flush their state */
1620 afs_ResetVolumes(srvp);
1622 /* Flush all callbacks in the all vcaches for this specific server */
1623 afs_FlushServerCBs(srvp);
1625 /* Remove all the callbacks structs */
1627 struct afs_cbr *cb, *cbnext;
1629 ObtainWriteLock(&afs_xvcb, 300);
1630 for (cb = srvp->cbrs; cb; cb = cbnext) {
1633 } srvp->cbrs = (struct afs_cbr *)0;
1634 ReleaseWriteLock(&afs_xvcb);
1637 /* If no more srvAddr structs hanging off of this server struct,
1641 /* Remove the server structure from the cell list - if there */
1642 afs_RemoveCellEntry(srvp);
1644 /* Remove from the afs_servers hash chain */
1645 for (i = 0; i < NSERVERS; i++) {
1646 for (pts = &(afs_servers[i]), ts = *pts; ts;
1647 pts = &(ts->next), ts = *pts) {
1655 *pts = ts->next; /* Found it. Remove it */
1656 afs_osi_Free(ts, sizeof(struct server)); /* Free it */
1662 /* afs_RemoveSrvAddr()
1663 * This removes a SrvAddr structure from its server structure.
1664 * The srvAddr struct is not free'd because it connections may still
1665 * be open to it. It is up to the calling process to make sure it
1666 * remains connected to a server struct.
1667 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1668 * It is not removed from the afs_srvAddrs hash chain.
1671 afs_RemoveSrvAddr(struct srvAddr *sap)
1673 struct srvAddr **psa, *sa;
1680 /* Find the srvAddr in the server's list and remove it */
1681 for (psa = &(srv->addr), sa = *psa; sa; psa = &(sa->next_sa), sa = *psa) {
1689 /* Flush the server struct since it's IP address has changed */
1690 afs_FlushServer(srv);
1694 /* afs_GetCapabilities
1695 * Try and retrieve capabilities of a given file server. Carps on actual
1696 * failure. Servers are not expected to support this RPC. */
1698 afs_GetCapabilities(struct server *ts)
1700 Capabilities caps = {0, NULL};
1701 struct vrequest treq;
1702 struct afs_conn *tc;
1703 struct unixuser *tu;
1706 if ( !ts || !ts->cell )
1708 if ( !afs_osi_credp )
1711 if ((code = afs_InitReq(&treq, afs_osi_credp)))
1713 tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
1716 tc = afs_ConnBySA(ts->addr, ts->cell->fsport, ts->cell->cellNum, tu, 0, 1,
1720 /* InitCallBackStateN, triggered by our RPC, may need this */
1721 ReleaseWriteLock(&afs_xserver);
1722 code = RXAFS_GetCapabilities(tc->id, &caps);
1723 ObtainWriteLock(&afs_xserver, 723);
1724 /* we forced a conn above; important we mark it down if needed */
1725 if ((code < 0) && (code != RXGEN_OPCODE)) {
1726 afs_ServerDown(tc->parent->srvr);
1727 ForceNewConnections(tc->parent->srvr); /* multi homed clients */
1729 afs_PutConn(tc, SHARED_LOCK);
1730 if ( code && code != RXGEN_OPCODE ) {
1731 afs_warn("RXAFS_GetCapabilities failed with code %d\n", code);
1732 /* better not be anything to free. we failed! */
1736 ts->flags |= SCAPS_KNOWN;
1738 if ( caps.Capabilities_len > 0 ) {
1739 ts->capabilities = caps.Capabilities_val[0];
1740 xdr_free((xdrproc_t)xdr_Capabilities, &caps);
1741 caps.Capabilities_len = 0;
1742 caps.Capabilities_val = NULL;
1748 * Return an updated and properly initialized server structure
1749 * corresponding to the server ID, cell, and port specified.
1750 * If one does not exist, then one will be created.
1751 * aserver and aport must be in NET byte order.
1754 afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers, afs_int32 acell,
1755 u_short aport, afs_int32 locktype, afsUUID * uuidp,
1756 afs_int32 addr_uniquifier)
1758 struct server *oldts = 0, *ts, *newts, *orphts = 0;
1759 struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1761 afs_int32 iphash, k, srvcount = 0;
1762 unsigned int srvhash;
1764 AFS_STATCNT(afs_GetServer);
1766 ObtainSharedLock(&afs_xserver, 13);
1768 /* Check if the server struct exists and is up to date */
1771 panic("afs_GetServer: incorect count of servers");
1772 ObtainReadLock(&afs_xsrvAddr);
1773 ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1774 ReleaseReadLock(&afs_xsrvAddr);
1775 if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1776 /* Found a server struct that is not multihomed and has the
1777 * IP address associated with it. A correct match.
1779 ReleaseSharedLock(&afs_xserver);
1784 panic("afs_GetServer: incorrect count of servers");
1785 ts = afs_FindServer(0, aport, uuidp, locktype);
1786 if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1787 /* Found a server struct that is multihomed and same
1788 * uniqufier (same IP addrs). The above if statement is the
1789 * same as in InstallUVolumeEntry().
1791 ReleaseSharedLock(&afs_xserver);
1795 oldts = ts; /* Will reuse if same uuid */
1798 UpgradeSToWLock(&afs_xserver, 36);
1799 ObtainWriteLock(&afs_xsrvAddr, 116);
1801 srvcount = afs_totalServers;
1803 /* Reuse/allocate a new server structure */
1807 newts = afs_osi_Alloc(sizeof(struct server));
1809 panic("malloc of server struct");
1811 memset(newts, 0, sizeof(struct server));
1813 /* Add the server struct to the afs_servers[] hash chain */
1815 (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
1816 newts->next = afs_servers[srvhash];
1817 afs_servers[srvhash] = newts;
1820 /* Initialize the server structure */
1821 if (uuidp) { /* Multihomed */
1822 newts->sr_uuid = *uuidp;
1823 newts->sr_addr_uniquifier = addr_uniquifier;
1824 newts->flags |= SRVR_MULTIHOMED;
1827 newts->cell = afs_GetCell(acell, 0);
1829 fsport = (newts->cell ? newts->cell->fsport : AFS_FSPORT);
1831 /* For each IP address we are registering */
1832 for (k = 0; k < nservers; k++) {
1833 iphash = SHash(aserverp[k]);
1835 /* Check if the srvAddr structure already exists. If so, remove
1836 * it from its server structure and add it to the new one.
1838 for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
1839 if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
1842 if (oldsa && (oldsa->server != newts)) {
1843 afs_RemoveSrvAddr(oldsa); /* Remove from its server struct */
1844 oldsa->next_sa = newts->addr; /* Add to the new server struct */
1845 newts->addr = oldsa;
1848 /* Reuse/allocate a new srvAddr structure */
1852 newsa = afs_osi_Alloc(sizeof(struct srvAddr));
1854 panic("malloc of srvAddr struct");
1855 afs_totalSrvAddrs++;
1856 memset(newsa, 0, sizeof(struct srvAddr));
1858 /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1859 newsa->next_bkt = afs_srvAddrs[iphash];
1860 afs_srvAddrs[iphash] = newsa;
1862 /* Hang off of the server structure */
1863 newsa->next_sa = newts->addr;
1864 newts->addr = newsa;
1866 /* Initialize the srvAddr Structure */
1867 newsa->sa_ip = aserverp[k];
1868 newsa->sa_portal = aport;
1871 /* Update the srvAddr Structure */
1872 newsa->server = newts;
1873 if (newts->flags & SRVR_ISDOWN)
1874 newsa->sa_flags |= SRVADDR_ISDOWN;
1876 newsa->sa_flags |= SRVADDR_MH;
1878 newsa->sa_flags &= ~SRVADDR_MH;
1880 /* Compute preference values and resort */
1881 if (!newsa->sa_iprank) {
1882 afs_SetServerPrefs(newsa); /* new server rank */
1885 afs_SortOneServer(newts); /* Sort by rank */
1887 /* If we reused the server struct, remove any of its srvAddr
1888 * structs that will no longer be associated with this server.
1890 if (oldts) { /* reused the server struct */
1891 for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
1892 nextsa = orphsa->next_sa;
1893 for (k = 0; k < nservers; k++) {
1894 if (orphsa->sa_ip == aserverp[k])
1895 break; /* belongs */
1898 continue; /* belongs */
1900 /* Have a srvAddr struct. Now get a server struct (if not already) */
1902 orphts = afs_osi_Alloc(sizeof(struct server));
1904 panic("malloc of lo server struct");
1905 memset(orphts, 0, sizeof(struct server));
1908 /* Add the orphaned server to the afs_servers[] hash chain.
1909 * Its iphash does not matter since we never look up the server
1910 * in the afs_servers table by its ip address (only by uuid -
1911 * which this has none).
1913 iphash = SHash(aserverp[k]);
1914 orphts->next = afs_servers[iphash];
1915 afs_servers[iphash] = orphts;
1918 orphts->cell = afs_GetCell(acell, 0);
1921 /* Hang the srvAddr struct off of the server structure. The server
1922 * may have multiple srvAddrs, but it won't be marked multihomed.
1924 afs_RemoveSrvAddr(orphsa); /* remove */
1925 orphsa->next_sa = orphts->addr; /* hang off server struct */
1926 orphts->addr = orphsa;
1927 orphsa->server = orphts;
1928 orphsa->sa_flags |= SRVADDR_NOUSE; /* flag indicating not in use */
1929 orphsa->sa_flags &= ~SRVADDR_MH; /* Not multihomed */
1933 srvcount = afs_totalServers - srvcount; /* # servers added and removed */
1935 struct afs_stats_SrvUpDownInfo *upDownP;
1936 /* With the introduction of this new record, we need to adjust the
1937 * proper individual & global server up/down info.
1939 upDownP = GetUpDownStats(newts);
1940 upDownP->numTtlRecords += srvcount;
1941 afs_stats_cmperf.srvRecords += srvcount;
1942 if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
1943 afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
1946 ReleaseWriteLock(&afs_xsrvAddr);
1948 if ( aport == AFS_FSPORT && !(newts->flags & SCAPS_KNOWN))
1949 afs_GetCapabilities(newts);
1951 ReleaseWriteLock(&afs_xserver);
1953 } /* afs_GetServer */
1956 afs_ActivateServer(struct srvAddr *sap)
1958 osi_timeval_t currTime; /*Filled with current time */
1959 osi_timeval_t *currTimeP; /*Ptr to above */
1960 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record */
1961 struct server *aserver = sap->server;
1963 if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
1965 * This server record has not yet been activated. Go for it,
1966 * recording its ``birth''.
1968 aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
1969 currTimeP = &currTime;
1970 osi_GetuTime(currTimeP);
1971 aserver->activationTime = currTime.tv_sec;
1972 upDownP = GetUpDownStats(aserver);
1973 if (aserver->flags & SRVR_ISDOWN) {
1974 upDownP->numDownRecords++;
1976 upDownP->numUpRecords++;
1977 upDownP->numRecordsNeverDown++;
1983 afs_RemoveAllConns(void)
1986 struct server *ts, *nts;
1989 ObtainReadLock(&afs_xserver);
1990 ObtainWriteLock(&afs_xconn, 1001);
1992 /*printf("Destroying connections ... ");*/
1993 for (i = 0; i < NSERVERS; i++) {
1994 for (ts = afs_servers[i]; ts; ts = nts) {
1996 for (sa = ts->addr; sa; sa = sa->next_sa) {
1998 afs_ReleaseConns(sa->conns);
2004 /*printf("done\n");*/
2006 ReleaseWriteLock(&afs_xconn);
2007 ReleaseReadLock(&afs_xserver);
2012 afs_MarkAllServersUp(void)
2018 ObtainWriteLock(&afs_xserver, 721);
2019 ObtainWriteLock(&afs_xsrvAddr, 722);
2020 for (i = 0; i< NSERVERS; i++) {
2021 for (ts = afs_servers[i]; ts; ts = ts->next) {
2022 for (sa = ts->addr; sa; sa = sa->next_sa) {
2023 afs_MarkServerUpOrDown(sa, 0);
2027 ReleaseWriteLock(&afs_xsrvAddr);
2028 ReleaseWriteLock(&afs_xserver);