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;
291 struct rx_connection *rxconn;
293 AFS_STATCNT(CheckVLServer);
294 /* Ping dead servers to see if they're back */
295 if (!((aserver->flags & SRVR_ISDOWN) || (sa->sa_flags & SRVADDR_ISDOWN))
296 || (aserver->flags & SRVR_ISGONE))
299 return; /* can't do much */
301 tc = afs_ConnByHost(aserver, aserver->cell->vlport,
302 aserver->cell->cellNum, areq, 1, SHARED_LOCK, &rxconn);
305 rx_SetConnDeadTime(rxconn, 3);
308 code = VL_ProbeServer(rxconn);
310 rx_SetConnDeadTime(rxconn, afs_rx_deadtime);
311 afs_PutConn(tc, rxconn, SHARED_LOCK);
313 * If probe worked, or probe call not yet defined (for compatibility
314 * with old vlsevers), then we treat this server as running again
316 if (code == 0 || (code <= -450 && code >= -470)) {
317 if (tc->parent->srvr == sa) {
318 afs_MarkServerUpOrDown(sa, 0);
319 print_internet_address("afs: volume location server ", sa,
327 #ifndef AFS_MINCHANGE /* So that some can increase it in param.h */
328 #define AFS_MINCHANGE 2 /* min change we'll bother with */
330 #ifndef AFS_MAXCHANGEBACK
331 #define AFS_MAXCHANGEBACK 10 /* max seconds we'll set a clock back at once */
335 /*------------------------------------------------------------------------
336 * EXPORTED afs_CountServers
339 * Originally meant to count the number of servers and determining
340 * up/down info, this routine will now simply sum up all of the
341 * server record ages. All other up/down information is kept on the
351 * This routine locks afs_xserver for write for the duration.
354 * Set CM perf stats field sumOfRecordAges for all server record
356 *------------------------------------------------------------------------*/
359 afs_CountServers(void)
361 int currIdx; /*Curr idx into srv table */
362 struct server *currSrvP; /*Ptr to curr server record */
363 afs_int32 currChainLen; /*Length of curr hash chain */
364 osi_timeval_t currTime; /*Current time */
365 osi_timeval_t *currTimeP; /*Ptr to above */
366 afs_int32 srvRecordAge; /*Age of server record, in secs */
367 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to current up/down
368 * info being manipulated */
371 * Write-lock the server table so we don't get any interference.
373 ObtainReadLock(&afs_xserver);
376 * Iterate over each hash index in the server table, walking down each
377 * chain and tallying what we haven't computed from the records there on
378 * the fly. First, though, initialize the tallies that will change.
380 afs_stats_cmperf.srvMaxChainLength = 0;
382 afs_stats_cmperf.fs_UpDown[0].sumOfRecordAges = 0;
383 afs_stats_cmperf.fs_UpDown[0].ageOfYoungestRecord = 0;
384 afs_stats_cmperf.fs_UpDown[0].ageOfOldestRecord = 0;
385 memset(afs_stats_cmperf.fs_UpDown[0].downIncidents, 0,
386 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
388 afs_stats_cmperf.fs_UpDown[1].sumOfRecordAges = 0;
389 afs_stats_cmperf.fs_UpDown[1].ageOfYoungestRecord = 0;
390 afs_stats_cmperf.fs_UpDown[1].ageOfOldestRecord = 0;
391 memset(afs_stats_cmperf.fs_UpDown[1].downIncidents, 0,
392 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
394 afs_stats_cmperf.vl_UpDown[0].sumOfRecordAges = 0;
395 afs_stats_cmperf.vl_UpDown[0].ageOfYoungestRecord = 0;
396 afs_stats_cmperf.vl_UpDown[0].ageOfOldestRecord = 0;
397 memset(afs_stats_cmperf.vl_UpDown[0].downIncidents, 0,
398 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
400 afs_stats_cmperf.vl_UpDown[1].sumOfRecordAges = 0;
401 afs_stats_cmperf.vl_UpDown[1].ageOfYoungestRecord = 0;
402 afs_stats_cmperf.vl_UpDown[1].ageOfOldestRecord = 0;
403 memset(afs_stats_cmperf.vl_UpDown[1].downIncidents, 0,
404 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
407 * Compute the current time, used to figure out server record ages.
409 currTimeP = &currTime;
410 osi_GetuTime(currTimeP);
413 * Sweep the server hash table, tallying all we need to know.
415 for (currIdx = 0; currIdx < NSERVERS; currIdx++) {
417 for (currSrvP = afs_servers[currIdx]; currSrvP;
418 currSrvP = currSrvP->next) {
420 * Bump the current chain length.
425 * Any further tallying for this record will only be done if it has
428 if ((currSrvP->flags & AFS_SERVER_FLAG_ACTIVATED)
429 && currSrvP->addr && currSrvP->cell) {
432 * Compute the current server record's age, then remember it
433 * in the appropriate places.
435 srvRecordAge = currTime.tv_sec - currSrvP->activationTime;
436 upDownP = GetUpDownStats(currSrvP);
437 upDownP->sumOfRecordAges += srvRecordAge;
438 if ((upDownP->ageOfYoungestRecord == 0)
439 || (srvRecordAge < upDownP->ageOfYoungestRecord))
440 upDownP->ageOfYoungestRecord = srvRecordAge;
441 if ((upDownP->ageOfOldestRecord == 0)
442 || (srvRecordAge > upDownP->ageOfOldestRecord))
443 upDownP->ageOfOldestRecord = srvRecordAge;
445 if (currSrvP->numDowntimeIncidents <=
446 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET0)
447 (upDownP->downIncidents[0])++;
448 else if (currSrvP->numDowntimeIncidents <=
449 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET1)
450 (upDownP->downIncidents[1])++;
451 else if (currSrvP->numDowntimeIncidents <=
452 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET2)
453 (upDownP->downIncidents[2])++;
454 else if (currSrvP->numDowntimeIncidents <=
455 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET3)
456 (upDownP->downIncidents[3])++;
457 else if (currSrvP->numDowntimeIncidents <=
458 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET4)
459 (upDownP->downIncidents[4])++;
461 (upDownP->downIncidents[5])++;
464 } /*Current server has been active */
465 } /*Walk this chain */
468 * Before advancing to the next chain, remember facts about this one.
470 if (currChainLen > afs_stats_cmperf.srvMaxChainLength) {
472 * We beat out the former champion (which was initially set to 0
473 * here). Mark down the new winner, and also remember if it's an
476 afs_stats_cmperf.srvMaxChainLength = currChainLen;
477 if (currChainLen > afs_stats_cmperf.srvMaxChainLengthHWM)
478 afs_stats_cmperf.srvMaxChainLengthHWM = currChainLen;
479 } /*Update chain length maximum */
480 } /*For each hash chain */
483 * We're done. Unlock the server table before returning to our caller.
485 ReleaseReadLock(&afs_xserver);
487 } /*afs_CountServers */
491 ForceAllNewConnections(void)
494 struct srvAddr **addrs;
498 ObtainReadLock(&afs_xserver); /* Necessary? */
499 ObtainReadLock(&afs_xsrvAddr);
502 for (i = 0; i < NSERVERS; i++) {
503 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
508 addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
509 osi_Assert(addrs != NULL);
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);
528 CkSrv_MarkUpDown(struct afs_conn **conns, int nconns, afs_int32 *results)
534 for(i = 0; i < nconns; i++){
536 sa = tc->parent->srvr;
538 if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) &&
539 (tc->parent->srvr == sa)) {
541 print_internet_address("afs: file server ", sa, " is back up", 2);
543 ObtainWriteLock(&afs_xserver, 244);
544 ObtainWriteLock(&afs_xsrvAddr, 245);
545 afs_MarkServerUpOrDown(sa, 0);
546 ReleaseWriteLock(&afs_xsrvAddr);
547 ReleaseWriteLock(&afs_xserver);
549 if (afs_waitForeverCount) {
550 afs_osi_Wakeup(&afs_waitForever);
553 if (results[i] < 0) {
556 ForceNewConnections(sa); /* multi homed clients */
563 CkSrv_SetTime(struct rx_connection **rxconns, int nconns, int nservers,
564 struct afs_conn **conns, struct srvAddr **addrs)
567 afs_int32 start, end = 0, delta;
570 afs_int32 *conntimer, *results, *deltas;
574 conntimer = afs_osi_Alloc(nservers * sizeof (afs_int32));
575 osi_Assert(conntimer != NULL);
576 results = afs_osi_Alloc(nservers * sizeof (afs_int32));
577 osi_Assert(results != NULL);
578 deltas = afs_osi_Alloc(nservers * sizeof (afs_int32));
579 osi_Assert(deltas != NULL);
581 /* make sure we're starting from zero */
582 memset(&deltas, 0, sizeof(deltas));
584 start = osi_Time(); /* time the gettimeofday call */
586 if ( afs_setTimeHost == NULL ) {
587 multi_Rx(rxconns,nconns)
589 tv.tv_sec = tv.tv_usec = 0;
591 (afs_uint32 *)&tv.tv_sec, (afs_uint32 *)&tv.tv_usec);
593 sa = tc->parent->srvr;
594 if (conntimer[multi_i] == 1)
595 rx_SetConnDeadTime(rxconns[multi_i], afs_rx_deadtime);
597 results[multi_i]=multi_error;
598 if ((start == end) && !multi_error)
599 deltas[multi_i] = end - tv.tv_sec;
601 } else { /* find and query setTimeHost only */
602 for ( i = 0 ; i < nservers ; i++ ) {
603 if ( conns[i] == NULL || conns[i]->parent->srvr == NULL )
605 if ( conns[i]->parent->srvr->server == afs_setTimeHost ) {
606 tv.tv_sec = tv.tv_usec = 0;
607 results[i] = RXAFS_GetTime(rxconns[i],
608 (afs_uint32 *)&tv.tv_sec,
609 (afs_uint32 *)&tv.tv_usec);
611 if ((start == end) && !results[i])
612 deltas[i] = end - tv.tv_sec;
619 if ( afs_setTimeHost == NULL )
620 CkSrv_MarkUpDown(conns, nconns, results);
621 else /* We lack info for other than this host */
622 CkSrv_MarkUpDown(&conns[i], 1, &results[i]);
625 * If we're supposed to set the time, and the call worked
626 * quickly (same second response) and this is the host we
627 * use for the time and the time is really different, then
628 * really set the time
630 if (afs_setTime != 0) {
631 for (i=0; i<nconns; i++) {
634 sa = tc->parent->srvr;
636 if ((tc->parent->srvr->server == afs_setTimeHost ||
637 /* Sync only to a server in the local cell */
638 (afs_setTimeHost == (struct server *)0 &&
639 afs_IsPrimaryCell(sa->server->cell)))) {
641 char msgbuf[90]; /* strlen("afs: setting clock...") + slop */
642 delta = end - tv.tv_sec; /* how many secs fast we are */
644 afs_setTimeHost = tc->parent->srvr->server;
645 /* see if clock has changed enough to make it worthwhile */
646 if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) {
648 if (delta > AFS_MAXCHANGEBACK) {
649 /* setting clock too far back, just do it a little */
650 tv.tv_sec = end - AFS_MAXCHANGEBACK;
652 tv.tv_sec = end - delta;
654 afs_osi_SetTime(&tv);
656 strcpy(msgbuf, "afs: setting clock back ");
657 if (delta > AFS_MAXCHANGEBACK) {
659 afs_cv2string(&tbuffer[CVBS],
661 afs_strcat(msgbuf, " seconds (of ");
663 afs_cv2string(&tbuffer[CVBS],
666 afs_strcat(msgbuf, ", via ");
667 print_internet_address(msgbuf, sa,
668 "); clock is still fast.",
672 afs_cv2string(&tbuffer[CVBS], delta));
673 afs_strcat(msgbuf, " seconds (via ");
674 print_internet_address(msgbuf, sa, ").", 0);
677 strcpy(msgbuf, "afs: setting clock ahead ");
679 afs_cv2string(&tbuffer[CVBS], -delta));
680 afs_strcat(msgbuf, " seconds (via ");
681 print_internet_address(msgbuf, sa, ").", 0);
683 /* We're only going to set it once; why bother looping? */
689 afs_osi_Free(conntimer, nservers * sizeof(afs_int32));
690 afs_osi_Free(deltas, nservers * sizeof(afs_int32));
691 afs_osi_Free(results, nservers * sizeof(afs_int32));
695 CkSrv_GetCaps(struct rx_connection **rxconns, int nconns, int nservers,
696 struct afs_conn **conns, struct srvAddr **addrs)
703 caps = afs_osi_Alloc(nservers * sizeof (Capabilities));
704 osi_Assert(caps != NULL);
705 memset(caps, 0, nservers * sizeof(Capabilities));
707 results = afs_osi_Alloc(nservers * sizeof (afs_int32));
708 osi_Assert(results != NULL);
711 multi_Rx(rxconns,nconns)
713 multi_RXAFS_GetCapabilities(&caps[multi_i]);
714 results[multi_i] = multi_error;
718 for ( i = 0 ; i < nconns ; i++ ) {
719 ts = addrs[i]->server;
722 ts->capabilities = 0;
723 ts->flags |= SCAPS_KNOWN;
724 if ( results[i] == RXGEN_OPCODE ) {
725 /* Mark server as up - it responded */
729 if ( results[i] >= 0 )
730 /* we currently handle 32-bits of capabilities */
731 if (caps[i].Capabilities_len > 0) {
732 ts->capabilities = caps[i].Capabilities_val[0];
733 xdr_free((xdrproc_t)xdr_Capabilities, &caps[i]);
734 caps[i].Capabilities_val = NULL;
735 caps[i].Capabilities_len = 0;
738 CkSrv_MarkUpDown(conns, nconns, results);
740 afs_osi_Free(caps, nservers * sizeof(Capabilities));
741 afs_osi_Free(results, nservers * sizeof(afs_int32));
744 /* check down servers (if adown), or running servers (if !adown) */
746 afs_CheckServers(int adown, struct cell *acellp)
748 afs_LoopServers(adown?AFS_LS_DOWN:AFS_LS_UP, acellp, 1, CkSrv_GetCaps,
749 afs_setTime?CkSrv_SetTime:NULL);
752 /* adown: AFS_LS_UP - check only up
753 * AFS_LS_DOWN - check only down.
754 * AFS_LS_ALL - check all */
756 afs_LoopServers(int adown, struct cell *acellp, int vlalso,
757 void (*func1) (struct rx_connection **rxconns, int nconns,
758 int nservers, struct afs_conn **conns,
759 struct srvAddr **addrs),
760 void (*func2) (struct rx_connection **rxconns, int nconns,
761 int nservers, struct afs_conn **conns,
762 struct srvAddr **addrs))
764 struct vrequest treq;
767 struct afs_conn *tc = NULL;
772 struct srvAddr **addrs;
773 struct afs_conn **conns;
775 struct rx_connection **rxconns;
776 afs_int32 *conntimer, *results;
778 AFS_STATCNT(afs_CheckServers);
781 * No sense in doing the server checks if we are running in disconnected
784 if (AFS_IS_DISCONNECTED)
787 conns = (struct afs_conn **)0;
788 rxconns = (struct rx_connection **) 0;
792 if ((code = afs_InitReq(&treq, afs_osi_credp)))
794 ObtainReadLock(&afs_xserver); /* Necessary? */
795 ObtainReadLock(&afs_xsrvAddr);
798 for (i = 0; i < NSERVERS; i++) {
799 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
804 addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
805 osi_Assert(addrs != NULL);
807 for (i = 0; i < NSERVERS; i++) {
808 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
809 if (j >= srvAddrCount)
815 ReleaseReadLock(&afs_xsrvAddr);
816 ReleaseReadLock(&afs_xserver);
818 conns = afs_osi_Alloc(j * sizeof(struct afs_conn *));
819 osi_Assert(conns != NULL);
820 rxconns = afs_osi_Alloc(j * sizeof(struct rx_connection *));
821 osi_Assert(rxconns != NULL);
822 conntimer = afs_osi_Alloc(j * sizeof (afs_int32));
823 osi_Assert(conntimer != NULL);
824 results = afs_osi_Alloc(j * sizeof (afs_int32));
825 osi_Assert(results != NULL);
827 for (i = 0; i < j; i++) {
828 struct rx_connection *rxconn;
834 /* See if a cell to check was specified. If it is spec'd and not
835 * this server's cell, just skip the server.
837 if (acellp && acellp != ts->cell)
840 if (((adown==AFS_LS_DOWN) && !(sa->sa_flags & SRVADDR_ISDOWN))
841 || ((adown==AFS_LS_UP) && (sa->sa_flags & SRVADDR_ISDOWN)))
844 /* check vlserver with special code */
845 if (sa->sa_portal == AFS_VLPORT) {
847 CheckVLServer(sa, &treq);
851 if (!ts->cell) /* not really an active server, anyway, it must */
852 continue; /* have just been added by setsprefs */
854 /* get a connection, even if host is down; bumps conn ref count */
855 tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
856 tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
857 1 /*force */ , 1 /*create */ , SHARED_LOCK, &rxconn);
858 afs_PutUser(tu, SHARED_LOCK);
862 if ((sa->sa_flags & SRVADDR_ISDOWN) || afs_HaveCallBacksFrom(sa->server)
863 || (tc->parent->srvr->server == afs_setTimeHost)) {
865 rxconns[nconns]=rxconn;
866 if (sa->sa_flags & SRVADDR_ISDOWN) {
867 rx_SetConnDeadTime(rxconn, 3);
874 } /* Outer loop over addrs */
876 (*func1)(rxconns, nconns, j, conns, addrs);
879 (*func2)(rxconns, nconns, j, conns, addrs);
882 for (i = 0; i < nconns; i++) {
883 if (conntimer[i] == 1)
884 rx_SetConnDeadTime(rxconns[i], afs_rx_deadtime);
885 afs_PutConn(conns[i], rxconns[i], SHARED_LOCK); /* done with it now */
888 afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
889 afs_osi_Free(conns, j * sizeof(struct afs_conn *));
890 afs_osi_Free(rxconns, j * sizeof(struct rx_connection *));
891 afs_osi_Free(conntimer, j * sizeof(afs_int32));
892 afs_osi_Free(results, j * sizeof(afs_int32));
894 } /*afs_CheckServers*/
897 /* find a server structure given the host address */
899 afs_FindServer(afs_int32 aserver, afs_uint16 aport, afsUUID * uuidp,
906 AFS_STATCNT(afs_FindServer);
908 i = afs_uuid_hash(uuidp) % NSERVERS;
909 for (ts = afs_servers[i]; ts; ts = ts->next) {
910 if ((ts->flags & SRVR_MULTIHOMED)
912 (memcmp((char *)uuidp, (char *)&ts->sr_uuid, sizeof(*uuidp))
913 == 0) && (!ts->addr || (ts->addr->sa_portal == aport)))
918 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
919 if ((sa->sa_ip == aserver) && (sa->sa_portal == aport)) {
926 } /*afs_FindServer */
929 /* some code for creating new server structs and setting preferences follows
930 * in the next few lines...
933 #define MAXDEFRANK 60000
934 #define DEFRANK 40000
936 /* Random number generator and constants from KnuthV2 2d ed, p170 */
942 a is 0.73m should be 0.01m .. 0.99m
943 c is more or less immaterial. 1 or a is suggested.
945 NB: LOW ORDER BITS are not very random. To get small random numbers,
946 treat result as <1, with implied binary point, and multiply by
948 NB: Has to be unsigned, since shifts on signed quantities may preserve
951 /* added rxi_getaddr() to try to get as much initial randomness as
952 possible, since at least one customer reboots ALL their clients
953 simultaneously -- so osi_Time is bound to be the same on some of the
954 clients. This is probably OK, but I don't want to see too much of it.
957 #define ranstage(x) (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
962 static afs_int32 state = 0;
965 AFS_STATCNT(afs_random);
970 * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
971 * bits are in a tv_usec
973 state = (t.tv_usec & (~0 << 4)) + (rxi_getaddr() & 0xff);
974 state += (t.tv_sec & 0xff);
975 for (i = 0; i < 30; i++) {
985 /* returns int 0..14 using the high bits of a pseudo-random number instead of
986 the low bits, as the low bits are "less random" than the high ones...
987 slight roundoff error exists, an excercise for the reader.
988 need to multiply by something with lots of ones in it, so multiply by
989 8 or 16 is right out.
992 afs_randomMod15(void)
996 temp = afs_random() >> 4;
997 temp = (temp * 15) >> 28;
1003 afs_randomMod127(void)
1007 temp = afs_random() >> 7;
1008 temp = (temp * 127) >> 25;
1013 /* afs_SortOneServer()
1014 * Sort all of the srvAddrs, of a server struct, by rank from low to high.
1017 afs_SortOneServer(struct server *asp)
1019 struct srvAddr **rootsa, *lowsa, *tsa, *lowprev;
1022 for (rootsa = &(asp->addr); *rootsa; rootsa = &(lowsa->next_sa)) {
1024 lowsa = *rootsa; /* lowest sa is the first one */
1025 lowrank = lowsa->sa_iprank;
1027 for (tsa = *rootsa; tsa->next_sa; tsa = tsa->next_sa) {
1028 rank = tsa->next_sa->sa_iprank;
1029 if (rank < lowrank) {
1031 lowsa = tsa->next_sa;
1032 lowrank = lowsa->sa_iprank;
1035 if (lowprev) { /* found one lower, so rearrange them */
1036 lowprev->next_sa = lowsa->next_sa;
1037 lowsa->next_sa = *rootsa;
1044 * Sort the pointer to servers by the server's rank (its lowest rank).
1045 * It is assumed that the server already has its IP addrs sorted (the
1046 * first being its lowest rank: afs_GetServer() calls afs_SortOneServer()).
1049 afs_SortServers(struct server *aservers[], int count)
1054 AFS_STATCNT(afs_SortServers);
1056 for (i = 0; i < count; i++) {
1059 for (low = i, j = i + 1; j <= count; j++) {
1060 if ((!aservers[j]) || (!aservers[j]->addr))
1062 if ((!aservers[low]) || (!aservers[low]->addr))
1064 if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
1070 aservers[i] = aservers[low];
1074 } /*afs_SortServers */
1076 /* afs_SetServerPrefs is rather system-dependent. It pokes around in kernel
1077 data structures to determine what the local IP addresses and subnet masks
1078 are in order to choose which server(s) are on the local subnet.
1080 As I see it, there are several cases:
1081 1. The server address is one of this host's local addresses. In this case
1082 this server is to be preferred over all others.
1083 2. The server is on the same subnet as one of the this host's local
1084 addresses. (ie, an odd-sized subnet, not class A,B,orC)
1085 3. The server is on the same net as this host (class A,B or C)
1086 4. The server is on a different logical subnet or net than this host, but
1087 this host is a 'metric 0 gateway' to it. Ie, two address-spaces share
1088 one physical medium.
1089 5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
1091 6. This host and the server are disjoint.
1093 That is a rough order of preference. If a point-to-point link has a high
1094 metric, I'm assuming that it is a very slow link, and putting it at the
1095 bottom of the list (at least until RX works better over slow links). If
1096 its metric is 1, I'm assuming that it's relatively fast (T1) and putting
1098 It's not easy to check for case #4, so I'm ignoring it for the time being.
1100 BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
1101 That could be used to prefer certain servers fairly easily. Maybe some
1104 NOTE: this code is very system-dependent, and very dependent on the TCP/IP
1105 protocols (well, addresses that are stored in uint32s, at any rate).
1108 #define IA_DST(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_dstaddr))
1109 #define IA_BROAD(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
1111 /* SA2ULONG takes a sockaddr_in, not a sockaddr (same thing, just cast it!) */
1112 #define SA2ULONG(sa) ((sa)->sin_addr.s_addr)
1117 #define PPWEIGHT 4096
1122 #if defined(AFS_SUN5_ENV) && ! defined(AFS_SUN56_ENV)
1123 #include <inet/common.h>
1124 /* IP interface structure, one per local address */
1125 typedef struct ipif_s {
1126 /**/ struct ipif_s *ipif_next;
1127 struct ill_s *ipif_ill; /* Back pointer to our ill */
1128 long ipif_id; /* Logical unit number */
1129 u_int ipif_mtu; /* Starts at ipif_ill->ill_max_frag */
1130 afs_int32 ipif_local_addr; /* Local IP address for this if. */
1131 afs_int32 ipif_net_mask; /* Net mask for this interface. */
1132 afs_int32 ipif_broadcast_addr; /* Broadcast addr for this interface. */
1133 afs_int32 ipif_pp_dst_addr; /* Point-to-point dest address. */
1134 u_int ipif_flags; /* Interface flags. */
1135 u_int ipif_metric; /* BSD if metric, for compatibility. */
1136 u_int ipif_ire_type; /* LOCAL or LOOPBACK */
1137 mblk_t *ipif_arp_down_mp; /* Allocated at time arp comes up to
1138 * prevent awkward out of mem condition
1141 mblk_t *ipif_saved_ire_mp; /* Allocated for each extra IRE_SUBNET/
1142 * RESOLVER on this interface so that
1143 * they can survive ifconfig down.
1146 * The packet counts in the ipif contain the sum of the
1147 * packet counts in dead IREs that were affiliated with
1150 u_long ipif_fo_pkt_count; /* Forwarded thru our dead IREs */
1151 u_long ipif_ib_pkt_count; /* Inbound packets for our dead IREs */
1152 u_long ipif_ob_pkt_count; /* Outbound packets to our dead IREs */
1154 ipif_multicast_up:1, /* We have joined the allhosts group */
1158 typedef struct ipfb_s {
1159 /**/ struct ipf_s *ipfb_ipf; /* List of ... */
1160 kmutex_t ipfb_lock; /* Protect all ipf in list */
1163 typedef struct ilm_s {
1164 /**/ afs_int32 ilm_addr;
1166 u_int ilm_timer; /* IGMP */
1167 struct ipif_s *ilm_ipif; /* Back pointer to ipif */
1168 struct ilm_s *ilm_next; /* Linked list for each ill */
1171 typedef struct ill_s {
1172 /**/ struct ill_s *ill_next; /* Chained in at ill_g_head. */
1173 struct ill_s **ill_ptpn; /* Pointer to previous next. */
1174 queue_t *ill_rq; /* Read queue. */
1175 queue_t *ill_wq; /* Write queue. */
1177 int ill_error; /* Error value sent up by device. */
1179 ipif_t *ill_ipif; /* Interface chain for this ILL. */
1180 u_int ill_ipif_up_count; /* Number of IPIFs currently up. */
1181 u_int ill_max_frag; /* Max IDU. */
1182 char *ill_name; /* Our name. */
1183 u_int ill_name_length; /* Name length, incl. terminator. */
1184 u_int ill_subnet_type; /* IRE_RESOLVER or IRE_SUBNET. */
1185 u_int ill_ppa; /* Physical Point of Attachment num. */
1187 int ill_sap_length; /* Including sign (for position) */
1188 u_int ill_phys_addr_length; /* Excluding the sap. */
1189 mblk_t *ill_frag_timer_mp; /* Reassembly timer state. */
1190 ipfb_t *ill_frag_hash_tbl; /* Fragment hash list head. */
1192 queue_t *ill_bind_pending_q; /* Queue waiting for DL_BIND_ACK. */
1193 ipif_t *ill_ipif_pending; /* IPIF waiting for DL_BIND_ACK. */
1195 /* ill_hdr_length and ill_hdr_mp will be non zero if
1196 * the underlying device supports the M_DATA fastpath
1200 ilm_t *ill_ilm; /* Multicast mebership for lower ill */
1202 /* All non-nil cells between 'ill_first_mp_to_free' and
1203 * 'ill_last_mp_to_free' are freed in ill_delete.
1205 #define ill_first_mp_to_free ill_hdr_mp
1206 mblk_t *ill_hdr_mp; /* Contains fastpath template */
1207 mblk_t *ill_bcast_mp; /* DLPI header for broadcasts. */
1208 mblk_t *ill_bind_pending; /* T_BIND_REQ awaiting completion. */
1209 mblk_t *ill_resolver_mp; /* Resolver template. */
1210 mblk_t *ill_attach_mp;
1211 mblk_t *ill_bind_mp;
1212 mblk_t *ill_unbind_mp;
1213 mblk_t *ill_detach_mp;
1214 #define ill_last_mp_to_free ill_detach_mp
1216 u_int ill_frag_timer_running:1, ill_needs_attach:1, ill_is_ptp:1,
1217 ill_priv_stream:1, ill_unbind_pending:1, ill_pad_to_bit_31:27;
1218 MI_HRT_DCL(ill_rtime)
1219 MI_HRT_DCL(ill_rtmp)
1223 #ifdef AFS_USERSPACE_IP_ADDR
1225 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1228 * The IP addresses and ranks are determined by afsd (in user space) and
1229 * passed into the kernel at startup time through the AFSOP_ADVISEADDR
1230 * system call. These are stored in the data structure
1231 * called 'afs_cb_interface'.
1233 * struct srvAddr *sa; remote server
1234 * afs_int32 addr; one of my local addr in net order
1235 * afs_uint32 subnetmask; subnet mask of local addr in net order
1239 afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr,
1240 afs_uint32 subnetmask)
1242 afs_uint32 myAddr, myNet, mySubnet, netMask;
1243 afs_uint32 serverAddr;
1245 myAddr = ntohl(addr); /* one of my IP addr in host order */
1246 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1247 subnetmask = ntohl(subnetmask); /* subnet mask in host order */
1249 if (IN_CLASSA(myAddr))
1250 netMask = IN_CLASSA_NET;
1251 else if (IN_CLASSB(myAddr))
1252 netMask = IN_CLASSB_NET;
1253 else if (IN_CLASSC(myAddr))
1254 netMask = IN_CLASSC_NET;
1258 myNet = myAddr & netMask;
1259 mySubnet = myAddr & subnetmask;
1261 if ((serverAddr & netMask) == myNet) {
1262 if ((serverAddr & subnetmask) == mySubnet) {
1263 if (serverAddr == myAddr) { /* same machine */
1264 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1265 } else { /* same subnet */
1266 sa->sa_iprank = afs_min(sa->sa_iprank, HI);
1268 } else { /* same net */
1269 sa->sa_iprank = afs_min(sa->sa_iprank, MED);
1274 #else /* AFS_USERSPACE_IP_ADDR */
1275 #if (! defined(AFS_SUN5_ENV)) && (! defined(AFS_DARWIN_ENV)) && (! defined(AFS_OBSD47_ENV)) && defined(USEIFADDR)
1277 afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
1279 struct sockaddr_in *sin;
1282 if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
1283 if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
1285 if (SA2ULONG(sin) == ntohl(sa->sa_ip)) { /* ie, ME!!! */
1286 sa->sa_iprank = TOPR;
1288 t = HI + ifa->ia_ifp->if_metric; /* case #2 */
1289 if (sa->sa_iprank > t)
1293 t = MED + ifa->ia_ifp->if_metric; /* case #3 */
1294 if (sa->sa_iprank > t)
1298 #ifdef IFF_POINTTOPOINT
1299 /* check for case #4 -- point-to-point link */
1300 if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
1301 && (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
1302 if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1305 t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
1306 if (sa->sa_iprank > t)
1309 #endif /* IFF_POINTTOPOINT */
1311 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1312 #if (defined(AFS_DARWIN_ENV) || defined(AFS_OBSD47_ENV)) && defined(USEIFADDR)
1314 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1317 afsi_SetServerIPRank(struct srvAddr *sa, rx_ifaddr_t ifa)
1319 struct sockaddr sout;
1320 struct sockaddr_in *sin;
1323 afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
1324 afs_uint32 serverAddr;
1326 if (rx_ifaddr_address_family(ifa) != AF_INET)
1328 t = rx_ifaddr_address(ifa, &sout, sizeof(sout));
1330 sin = (struct sockaddr_in *)&sout;
1331 myAddr = ntohl(sin->sin_addr.s_addr); /* one of my IP addr in host order */
1335 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1336 t = rx_ifaddr_netmask(ifa, &sout, sizeof(sout));
1338 sin = (struct sockaddr_in *)&sout;
1339 subnetmask = ntohl(sin->sin_addr.s_addr); /* subnet mask in host order */
1343 t = rx_ifaddr_dstaddress(ifa, &sout, sizeof(sout));
1345 sin = (struct sockaddr_in *)&sout;
1346 myDstaddr = ntohl(sin->sin_addr.s_addr);
1351 if (IN_CLASSA(myAddr))
1352 netMask = IN_CLASSA_NET;
1353 else if (IN_CLASSB(myAddr))
1354 netMask = IN_CLASSB_NET;
1355 else if (IN_CLASSC(myAddr))
1356 netMask = IN_CLASSC_NET;
1360 myNet = myAddr & netMask;
1361 mySubnet = myAddr & subnetmask;
1363 if ((serverAddr & netMask) == myNet) {
1364 if ((serverAddr & subnetmask) == mySubnet) {
1365 if (serverAddr == myAddr) { /* same machine */
1366 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1367 } else { /* same subnet */
1368 sa->sa_iprank = afs_min(sa->sa_iprank, HI + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1370 } else { /* same net */
1371 sa->sa_iprank = afs_min(sa->sa_iprank, MED + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1374 #ifdef IFF_POINTTOPOINT
1375 /* check for case #4 -- point-to-point link */
1376 if ((rx_ifnet_flags(rx_ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
1377 && (myDstaddr == serverAddr)) {
1378 if (rx_ifnet_metric(rx_ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
1381 t = MED + (PPWEIGHT << rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1382 if (sa->sa_iprank > t)
1385 #endif /* IFF_POINTTOPOINT */
1387 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1388 #endif /* else AFS_USERSPACE_IP_ADDR */
1390 #ifdef AFS_SGI62_ENV
1392 afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1395 afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
1396 return 0; /* Never match, so we enumerate everyone */
1398 #endif /* AFS_SGI62_ENV */
1400 afs_SetServerPrefs(struct srvAddr *sa)
1402 #if defined(AFS_USERSPACE_IP_ADDR)
1406 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1407 afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1408 afs_cb_interface.subnetmask[i]);
1410 #else /* AFS_USERSPACE_IP_ADDR */
1411 #if defined(AFS_SUN5_ENV)
1412 #ifdef AFS_SUN510_ENV
1415 extern struct ill_s *ill_g_headp;
1416 long *addr = (long *)ill_g_headp;
1420 int subnet, subnetmask, net, netmask;
1424 #ifdef AFS_SUN510_ENV
1425 rw_enter(&afsifinfo_lock, RW_READER);
1427 for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
1429 if (IN_CLASSA(afsifinfo[i].ipaddr)) {
1430 netmask = IN_CLASSA_NET;
1431 } else if (IN_CLASSB(afsifinfo[i].ipaddr)) {
1432 netmask = IN_CLASSB_NET;
1433 } else if (IN_CLASSC(afsifinfo[i].ipaddr)) {
1434 netmask = IN_CLASSC_NET;
1438 net = afsifinfo[i].ipaddr & netmask;
1442 if (!rx_IsLoopbackAddr(afsifinfo[i].ipaddr)) { /* ignore loopback */
1446 *addrp++ = afsifinfo[i].ipaddr;
1451 /* XXXXXX Do the individual ip ranking below XXXXX */
1452 if ((sa->sa_ip & netmask) == net) {
1453 if ((sa->sa_ip & subnetmask) == subnet) {
1454 if (afsifinfo[i].ipaddr == sa->sa_ip) { /* ie, ME! */
1455 sa->sa_iprank = TOPR;
1457 sa->sa_iprank = HI + afsifinfo[i].metric; /* case #2 */
1460 sa->sa_iprank = MED + afsifinfo[i].metric; /* case #3 */
1463 sa->sa_iprank = LO + afsifinfo[i].metric; /* case #4 */
1465 /* check for case #5 -- point-to-point link */
1466 if ((afsifinfo[i].flags & IFF_POINTOPOINT)
1467 && (afsifinfo[i].dstaddr == sa->sa_ip)) {
1469 if (afsifinfo[i].metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1470 sa->sa_iprank = MAXDEFRANK;
1472 sa->sa_iprank = MED + (PPWEIGHT << afsifinfo[i].metric);
1477 rw_exit(&afsifinfo_lock);
1479 for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
1480 ill = ill->ill_next) {
1481 #ifdef AFS_SUN58_ENV
1482 /* Make sure this is an IPv4 ILL */
1486 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
1487 subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1488 subnetmask = ipif->ipif_net_mask;
1490 * Generate the local net using the local address and
1491 * whate we know about Class A, B and C networks.
1493 if (IN_CLASSA(ipif->ipif_local_addr)) {
1494 netmask = IN_CLASSA_NET;
1495 } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1496 netmask = IN_CLASSB_NET;
1497 } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1498 netmask = IN_CLASSC_NET;
1502 net = ipif->ipif_local_addr & netmask;
1505 if (!rx_IsLoopbackAddr(ipif->ipif_local_addr)) { /* ignore loopback */
1509 *addrp++ = ipif->ipif_local_addr;
1514 /* XXXXXX Do the individual ip ranking below XXXXX */
1515 if ((sa->sa_ip & netmask) == net) {
1516 if ((sa->sa_ip & subnetmask) == subnet) {
1517 if (ipif->ipif_local_addr == sa->sa_ip) { /* ie, ME! */
1518 sa->sa_iprank = TOPR;
1520 sa->sa_iprank = HI + ipif->ipif_metric; /* case #2 */
1523 sa->sa_iprank = MED + ipif->ipif_metric; /* case #3 */
1526 sa->sa_iprank = LO + ipif->ipif_metric; /* case #4 */
1528 /* check for case #5 -- point-to-point link */
1529 if ((ipif->ipif_flags & IFF_POINTOPOINT)
1530 && (ipif->ipif_pp_dst_addr == sa->sa_ip)) {
1532 if (ipif->ipif_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1533 sa->sa_iprank = MAXDEFRANK;
1535 sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1540 #endif /* AFS_SUN510_ENV */
1543 rx_ifnet_t ifn = NULL;
1544 struct in_ifaddr *ifad = (struct in_ifaddr *)0;
1545 struct sockaddr_in *sin;
1548 #ifdef notdef /* clean up, remove this */
1549 for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
1550 for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next) {
1551 if ((IFADDR2SA(ifad)->sa_family == AF_INET)
1552 && !(ifn->if_flags & IFF_LOOPBACK)) {
1557 ((struct sockaddr_in *)IFADDR2SA(ifad))->sin_addr.
1566 ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1568 if (ifn) { /* local, more or less */
1570 if (ifn->if_flags & IFF_LOOPBACK) {
1571 sa->sa_iprank = TOPR;
1574 #endif /* IFF_LOOPBACK */
1575 sin = (struct sockaddr_in *)IA_SIN(ifad);
1576 if (SA2ULONG(sin) == sa->sa_ip) {
1577 sa->sa_iprank = TOPR;
1580 #ifdef IFF_BROADCAST
1581 if (ifn->if_flags & IFF_BROADCAST) {
1582 if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1587 #endif /* IFF_BROADCAST */
1588 #ifdef IFF_POINTOPOINT
1589 if (ifn->if_flags & IFF_POINTOPOINT) {
1590 if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1591 if (ifn->if_metric > 4) {
1595 sa->sa_iprank = ifn->if_metric;
1598 #endif /* IFF_POINTOPOINT */
1599 sa->sa_iprank += MED + ifn->if_metric; /* couldn't find anything better */
1601 #else /* USEIFADDR */
1605 #ifdef AFS_SGI62_ENV
1606 (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1607 (caddr_t) sa, NULL);
1608 #elif defined(AFS_DARWIN80_ENV)
1616 if (!ifnet_list_get(AF_INET, &ifns, &count)) {
1617 for (m = 0; m < count; m++) {
1618 if (!ifnet_get_address_list(ifns[m], &ifads)) {
1619 for (j = 0; ifads[j] != NULL && cnt < ADDRSPERSITE; j++) {
1620 afsi_SetServerIPRank(sa, ifads[j]);
1623 ifnet_free_address_list(ifads);
1626 ifnet_list_free(ifns);
1629 #elif defined(AFS_DARWIN_ENV)
1633 TAILQ_FOREACH(ifn, &ifnet, if_link) {
1634 TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
1635 afsi_SetServerIPRank(sa, ifa);
1637 #elif defined(AFS_FBSD_ENV)
1639 struct in_ifaddr *ifa;
1640 TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
1641 afsi_SetServerIPRank(sa, ifa);
1643 #elif defined(AFS_OBSD_ENV)
1645 extern struct in_ifaddrhead in_ifaddr;
1646 struct in_ifaddr *ifa;
1647 for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1648 afsi_SetServerIPRank(sa, ifa);
1650 #elif defined(AFS_NBSD40_ENV)
1652 extern struct in_ifaddrhead in_ifaddrhead;
1653 struct in_ifaddr *ifa;
1654 for (ifa = in_ifaddrhead.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1655 afsi_SetServerIPRank(sa, ifa);
1659 struct in_ifaddr *ifa;
1660 for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
1661 afsi_SetServerIPRank(sa, ifa);
1664 #endif /* USEIFADDR */
1668 #endif /* AFS_SUN5_ENV */
1669 #endif /* else AFS_USERSPACE_IP_ADDR */
1671 sa->sa_iprank += afs_randomMod15();
1674 } /* afs_SetServerPrefs */
1682 /* afs_FlushServer()
1683 * The addresses on this server struct has changed in some way and will
1684 * clean up all other structures that may reference it.
1685 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1688 afs_FlushServer(struct server *srvp)
1691 struct server *ts, **pts;
1693 /* Find any volumes residing on this server and flush their state */
1694 afs_ResetVolumes(srvp);
1696 /* Flush all callbacks in the all vcaches for this specific server */
1697 afs_FlushServerCBs(srvp);
1699 /* Remove all the callbacks structs */
1701 struct afs_cbr *cb, *cbnext;
1703 ObtainWriteLock(&afs_xvcb, 300);
1704 for (cb = srvp->cbrs; cb; cb = cbnext) {
1707 } srvp->cbrs = (struct afs_cbr *)0;
1708 ReleaseWriteLock(&afs_xvcb);
1711 /* If no more srvAddr structs hanging off of this server struct,
1715 /* Remove the server structure from the cell list - if there */
1716 afs_RemoveCellEntry(srvp);
1718 /* Remove from the afs_servers hash chain */
1719 for (i = 0; i < NSERVERS; i++) {
1720 for (pts = &(afs_servers[i]), ts = *pts; ts;
1721 pts = &(ts->next), ts = *pts) {
1729 *pts = ts->next; /* Found it. Remove it */
1730 afs_osi_Free(ts, sizeof(struct server)); /* Free it */
1736 /* afs_RemoveSrvAddr()
1737 * This removes a SrvAddr structure from its server structure.
1738 * The srvAddr struct is not free'd because it connections may still
1739 * be open to it. It is up to the calling process to make sure it
1740 * remains connected to a server struct.
1741 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1742 * It is not removed from the afs_srvAddrs hash chain.
1745 afs_RemoveSrvAddr(struct srvAddr *sap)
1747 struct srvAddr **psa, *sa;
1754 /* Find the srvAddr in the server's list and remove it */
1755 for (psa = &(srv->addr), sa = *psa; sa; psa = &(sa->next_sa), sa = *psa) {
1763 /* Flush the server struct since it's IP address has changed */
1764 afs_FlushServer(srv);
1768 /* afs_GetCapabilities
1769 * Try and retrieve capabilities of a given file server. Carps on actual
1770 * failure. Servers are not expected to support this RPC. */
1772 afs_GetCapabilities(struct server *ts)
1774 Capabilities caps = {0, NULL};
1775 struct vrequest treq;
1776 struct afs_conn *tc;
1777 struct unixuser *tu;
1778 struct rx_connection *rxconn;
1781 if ( !ts || !ts->cell )
1783 if ( !afs_osi_credp )
1786 if ((code = afs_InitReq(&treq, afs_osi_credp)))
1788 tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
1791 tc = afs_ConnBySA(ts->addr, ts->cell->fsport, ts->cell->cellNum, tu, 0, 1,
1796 /* InitCallBackStateN, triggered by our RPC, may need this */
1797 ReleaseWriteLock(&afs_xserver);
1798 code = RXAFS_GetCapabilities(rxconn, &caps);
1799 ObtainWriteLock(&afs_xserver, 723);
1800 /* we forced a conn above; important we mark it down if needed */
1801 if ((code < 0) && (code != RXGEN_OPCODE)) {
1802 afs_ServerDown(tc->parent->srvr);
1803 ForceNewConnections(tc->parent->srvr); /* multi homed clients */
1805 afs_PutConn(tc, rxconn, SHARED_LOCK);
1806 if ( code && code != RXGEN_OPCODE ) {
1807 afs_warn("RXAFS_GetCapabilities failed with code %d\n", code);
1808 /* better not be anything to free. we failed! */
1812 ts->flags |= SCAPS_KNOWN;
1814 if ( caps.Capabilities_len > 0 ) {
1815 ts->capabilities = caps.Capabilities_val[0];
1816 xdr_free((xdrproc_t)xdr_Capabilities, &caps);
1817 caps.Capabilities_len = 0;
1818 caps.Capabilities_val = NULL;
1824 * Return an updated and properly initialized server structure
1825 * corresponding to the server ID, cell, and port specified.
1826 * If one does not exist, then one will be created.
1827 * aserver and aport must be in NET byte order.
1830 afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers, afs_int32 acell,
1831 u_short aport, afs_int32 locktype, afsUUID * uuidp,
1832 afs_int32 addr_uniquifier)
1834 struct server *oldts = 0, *ts, *newts, *orphts = 0;
1835 struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1836 afs_int32 iphash, k, srvcount = 0;
1837 unsigned int srvhash;
1839 AFS_STATCNT(afs_GetServer);
1841 ObtainSharedLock(&afs_xserver, 13);
1843 /* Check if the server struct exists and is up to date */
1846 panic("afs_GetServer: incorect count of servers");
1847 ObtainReadLock(&afs_xsrvAddr);
1848 ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1849 ReleaseReadLock(&afs_xsrvAddr);
1850 if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1851 /* Found a server struct that is not multihomed and has the
1852 * IP address associated with it. A correct match.
1854 ReleaseSharedLock(&afs_xserver);
1859 panic("afs_GetServer: incorrect count of servers");
1860 ts = afs_FindServer(0, aport, uuidp, locktype);
1861 if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1862 /* Found a server struct that is multihomed and same
1863 * uniqufier (same IP addrs). The above if statement is the
1864 * same as in InstallUVolumeEntry().
1866 ReleaseSharedLock(&afs_xserver);
1870 oldts = ts; /* Will reuse if same uuid */
1873 UpgradeSToWLock(&afs_xserver, 36);
1874 ObtainWriteLock(&afs_xsrvAddr, 116);
1876 srvcount = afs_totalServers;
1878 /* Reuse/allocate a new server structure */
1882 newts = afs_osi_Alloc(sizeof(struct server));
1884 panic("malloc of server struct");
1886 memset(newts, 0, sizeof(struct server));
1888 /* Add the server struct to the afs_servers[] hash chain */
1890 (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
1891 newts->next = afs_servers[srvhash];
1892 afs_servers[srvhash] = newts;
1895 /* Initialize the server structure */
1896 if (uuidp) { /* Multihomed */
1897 newts->sr_uuid = *uuidp;
1898 newts->sr_addr_uniquifier = addr_uniquifier;
1899 newts->flags |= SRVR_MULTIHOMED;
1902 newts->cell = afs_GetCell(acell, 0);
1904 /* For each IP address we are registering */
1905 for (k = 0; k < nservers; k++) {
1906 iphash = SHash(aserverp[k]);
1908 /* Check if the srvAddr structure already exists. If so, remove
1909 * it from its server structure and add it to the new one.
1911 for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
1912 if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
1915 if (oldsa && (oldsa->server != newts)) {
1916 afs_RemoveSrvAddr(oldsa); /* Remove from its server struct */
1917 oldsa->next_sa = newts->addr; /* Add to the new server struct */
1918 newts->addr = oldsa;
1921 /* Reuse/allocate a new srvAddr structure */
1925 newsa = afs_osi_Alloc(sizeof(struct srvAddr));
1927 panic("malloc of srvAddr struct");
1928 afs_totalSrvAddrs++;
1929 memset(newsa, 0, sizeof(struct srvAddr));
1931 /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1932 newsa->next_bkt = afs_srvAddrs[iphash];
1933 afs_srvAddrs[iphash] = newsa;
1935 /* Hang off of the server structure */
1936 newsa->next_sa = newts->addr;
1937 newts->addr = newsa;
1939 /* Initialize the srvAddr Structure */
1940 newsa->sa_ip = aserverp[k];
1941 newsa->sa_portal = aport;
1944 /* Update the srvAddr Structure */
1945 newsa->server = newts;
1946 if (newts->flags & SRVR_ISDOWN)
1947 newsa->sa_flags |= SRVADDR_ISDOWN;
1949 newsa->sa_flags |= SRVADDR_MH;
1951 newsa->sa_flags &= ~SRVADDR_MH;
1953 /* Compute preference values and resort */
1954 if (!newsa->sa_iprank) {
1955 afs_SetServerPrefs(newsa); /* new server rank */
1958 afs_SortOneServer(newts); /* Sort by rank */
1960 /* If we reused the server struct, remove any of its srvAddr
1961 * structs that will no longer be associated with this server.
1963 if (oldts) { /* reused the server struct */
1964 for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
1965 nextsa = orphsa->next_sa;
1966 for (k = 0; k < nservers; k++) {
1967 if (orphsa->sa_ip == aserverp[k])
1968 break; /* belongs */
1971 continue; /* belongs */
1973 /* Have a srvAddr struct. Now get a server struct (if not already) */
1975 orphts = afs_osi_Alloc(sizeof(struct server));
1977 panic("malloc of lo server struct");
1978 memset(orphts, 0, sizeof(struct server));
1981 /* Add the orphaned server to the afs_servers[] hash chain.
1982 * Its iphash does not matter since we never look up the server
1983 * in the afs_servers table by its ip address (only by uuid -
1984 * which this has none).
1986 iphash = SHash(aserverp[k]);
1987 orphts->next = afs_servers[iphash];
1988 afs_servers[iphash] = orphts;
1991 orphts->cell = afs_GetCell(acell, 0);
1994 /* Hang the srvAddr struct off of the server structure. The server
1995 * may have multiple srvAddrs, but it won't be marked multihomed.
1997 afs_RemoveSrvAddr(orphsa); /* remove */
1998 orphsa->next_sa = orphts->addr; /* hang off server struct */
1999 orphts->addr = orphsa;
2000 orphsa->server = orphts;
2001 orphsa->sa_flags |= SRVADDR_NOUSE; /* flag indicating not in use */
2002 orphsa->sa_flags &= ~SRVADDR_MH; /* Not multihomed */
2006 srvcount = afs_totalServers - srvcount; /* # servers added and removed */
2008 struct afs_stats_SrvUpDownInfo *upDownP;
2009 /* With the introduction of this new record, we need to adjust the
2010 * proper individual & global server up/down info.
2012 upDownP = GetUpDownStats(newts);
2013 upDownP->numTtlRecords += srvcount;
2014 afs_stats_cmperf.srvRecords += srvcount;
2015 if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
2016 afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
2019 ReleaseWriteLock(&afs_xsrvAddr);
2021 if ( aport == AFS_FSPORT && !(newts->flags & SCAPS_KNOWN))
2022 afs_GetCapabilities(newts);
2024 ReleaseWriteLock(&afs_xserver);
2026 } /* afs_GetServer */
2029 afs_ActivateServer(struct srvAddr *sap)
2031 osi_timeval_t currTime; /*Filled with current time */
2032 osi_timeval_t *currTimeP; /*Ptr to above */
2033 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record */
2034 struct server *aserver = sap->server;
2036 if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
2038 * This server record has not yet been activated. Go for it,
2039 * recording its ``birth''.
2041 aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
2042 currTimeP = &currTime;
2043 osi_GetuTime(currTimeP);
2044 aserver->activationTime = currTime.tv_sec;
2045 upDownP = GetUpDownStats(aserver);
2046 if (aserver->flags & SRVR_ISDOWN) {
2047 upDownP->numDownRecords++;
2049 upDownP->numUpRecords++;
2050 upDownP->numRecordsNeverDown++;
2056 afs_RemoveAllConns(void)
2059 struct server *ts, *nts;
2062 ObtainReadLock(&afs_xserver);
2063 ObtainWriteLock(&afs_xconn, 1001);
2065 /*printf("Destroying connections ... ");*/
2066 for (i = 0; i < NSERVERS; i++) {
2067 for (ts = afs_servers[i]; ts; ts = nts) {
2069 for (sa = ts->addr; sa; sa = sa->next_sa) {
2071 afs_ReleaseConns(sa->conns);
2077 /*printf("done\n");*/
2079 ReleaseWriteLock(&afs_xconn);
2080 ReleaseReadLock(&afs_xserver);
2085 afs_MarkAllServersUp(void)
2091 ObtainWriteLock(&afs_xserver, 721);
2092 ObtainWriteLock(&afs_xsrvAddr, 722);
2093 for (i = 0; i< NSERVERS; i++) {
2094 for (ts = afs_servers[i]; ts; ts = ts->next) {
2095 for (sa = ts->addr; sa; sa = sa->next_sa) {
2096 afs_MarkServerUpOrDown(sa, 0);
2100 ReleaseWriteLock(&afs_xsrvAddr);
2101 ReleaseWriteLock(&afs_xserver);