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);
527 CkSrv_MarkUpDown(struct afs_conn **conns, int nconns, afs_int32 *results)
533 for(i = 0; i < nconns; i++){
535 sa = tc->parent->srvr;
537 if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) &&
538 (tc->parent->srvr == sa)) {
540 print_internet_address("afs: file server ", sa, " is back up", 2);
542 ObtainWriteLock(&afs_xserver, 244);
543 ObtainWriteLock(&afs_xsrvAddr, 245);
544 afs_MarkServerUpOrDown(sa, 0);
545 ReleaseWriteLock(&afs_xsrvAddr);
546 ReleaseWriteLock(&afs_xserver);
548 if (afs_waitForeverCount) {
549 afs_osi_Wakeup(&afs_waitForever);
552 if (results[i] < 0) {
555 ForceNewConnections(sa); /* multi homed clients */
562 CkSrv_SetTime(struct rx_connection **rxconns, int nconns, int nservers,
563 struct afs_conn **conns, struct srvAddr **addrs)
566 afs_int32 start, end = 0, delta;
569 afs_int32 *conntimer, *results, *deltas;
573 conntimer = afs_osi_Alloc(nservers * sizeof (afs_int32));
574 osi_Assert(conntimer != NULL);
575 results = afs_osi_Alloc(nservers * sizeof (afs_int32));
576 osi_Assert(results != NULL);
577 deltas = afs_osi_Alloc(nservers * sizeof (afs_int32));
578 osi_Assert(deltas != NULL);
580 /* make sure we're starting from zero */
581 memset(&deltas, 0, sizeof(deltas));
583 start = osi_Time(); /* time the gettimeofday call */
585 if ( afs_setTimeHost == NULL ) {
586 multi_Rx(rxconns,nconns)
588 tv.tv_sec = tv.tv_usec = 0;
590 (afs_uint32 *)&tv.tv_sec, (afs_uint32 *)&tv.tv_usec);
592 sa = tc->parent->srvr;
593 if (conntimer[multi_i] == 1)
594 rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
596 results[multi_i]=multi_error;
597 if ((start == end) && !multi_error)
598 deltas[multi_i] = end - tv.tv_sec;
600 } else { /* find and query setTimeHost only */
601 for ( i = 0 ; i < nservers ; i++ ) {
602 if ( conns[i] == NULL || conns[i]->parent->srvr == NULL )
604 if ( conns[i]->parent->srvr->server == afs_setTimeHost ) {
605 tv.tv_sec = tv.tv_usec = 0;
606 results[i] = RXAFS_GetTime(rxconns[i],
607 (afs_uint32 *)&tv.tv_sec,
608 (afs_uint32 *)&tv.tv_usec);
610 if ((start == end) && !results[i])
611 deltas[i] = end - tv.tv_sec;
618 if ( afs_setTimeHost == NULL )
619 CkSrv_MarkUpDown(conns, nconns, results);
620 else /* We lack info for other than this host */
621 CkSrv_MarkUpDown(&conns[i], 1, &results[i]);
624 * If we're supposed to set the time, and the call worked
625 * quickly (same second response) and this is the host we
626 * use for the time and the time is really different, then
627 * really set the time
629 if (afs_setTime != 0) {
630 for (i=0; i<nconns; i++) {
633 sa = tc->parent->srvr;
635 if ((tc->parent->srvr->server == afs_setTimeHost ||
636 /* Sync only to a server in the local cell */
637 (afs_setTimeHost == (struct server *)0 &&
638 afs_IsPrimaryCell(sa->server->cell)))) {
640 char msgbuf[90]; /* strlen("afs: setting clock...") + slop */
641 delta = end - tv.tv_sec; /* how many secs fast we are */
643 afs_setTimeHost = tc->parent->srvr->server;
644 /* see if clock has changed enough to make it worthwhile */
645 if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) {
647 if (delta > AFS_MAXCHANGEBACK) {
648 /* setting clock too far back, just do it a little */
649 tv.tv_sec = end - AFS_MAXCHANGEBACK;
651 tv.tv_sec = end - delta;
653 afs_osi_SetTime(&tv);
655 strcpy(msgbuf, "afs: setting clock back ");
656 if (delta > AFS_MAXCHANGEBACK) {
658 afs_cv2string(&tbuffer[CVBS],
660 afs_strcat(msgbuf, " seconds (of ");
662 afs_cv2string(&tbuffer[CVBS],
665 afs_strcat(msgbuf, ", via ");
666 print_internet_address(msgbuf, sa,
667 "); clock is still fast.",
671 afs_cv2string(&tbuffer[CVBS], delta));
672 afs_strcat(msgbuf, " seconds (via ");
673 print_internet_address(msgbuf, sa, ").", 0);
676 strcpy(msgbuf, "afs: setting clock ahead ");
678 afs_cv2string(&tbuffer[CVBS], -delta));
679 afs_strcat(msgbuf, " seconds (via ");
680 print_internet_address(msgbuf, sa, ").", 0);
682 /* We're only going to set it once; why bother looping? */
688 afs_osi_Free(conntimer, nservers * sizeof(afs_int32));
689 afs_osi_Free(deltas, nservers * sizeof(afs_int32));
690 afs_osi_Free(results, nservers * sizeof(afs_int32));
694 CkSrv_GetCaps(struct rx_connection **rxconns, int nconns, int nservers,
695 struct afs_conn **conns, struct srvAddr **addrs)
702 caps = afs_osi_Alloc(nservers * sizeof (Capabilities));
703 osi_Assert(caps != NULL);
704 memset(caps, 0, nservers * sizeof(Capabilities));
706 results = afs_osi_Alloc(nservers * sizeof (afs_int32));
707 osi_Assert(results != NULL);
710 multi_Rx(rxconns,nconns)
712 multi_RXAFS_GetCapabilities(&caps[multi_i]);
713 results[multi_i] = multi_error;
717 for ( i = 0 ; i < nconns ; i++ ) {
718 ts = addrs[i]->server;
721 ts->capabilities = 0;
722 ts->flags |= SCAPS_KNOWN;
723 if ( results[i] == RXGEN_OPCODE ) {
724 /* Mark server as up - it responded */
728 if ( results[i] >= 0 )
729 /* we currently handle 32-bits of capabilities */
730 if (caps[i].Capabilities_len > 0) {
731 ts->capabilities = caps[i].Capabilities_val[0];
732 xdr_free((xdrproc_t)xdr_Capabilities, &caps[i]);
733 caps[i].Capabilities_val = NULL;
734 caps[i].Capabilities_len = 0;
737 CkSrv_MarkUpDown(conns, nconns, results);
739 afs_osi_Free(caps, nservers * sizeof(Capabilities));
740 afs_osi_Free(results, nservers * sizeof(afs_int32));
743 /* check down servers (if adown), or running servers (if !adown) */
745 afs_CheckServers(int adown, struct cell *acellp)
747 afs_LoopServers(adown?AFS_LS_DOWN:AFS_LS_UP, acellp, 1, CkSrv_GetCaps,
748 afs_setTime?CkSrv_SetTime:NULL);
751 /* adown: 0 - check only down. 1 - check only up. 2 - check all */
753 afs_LoopServers(int adown, struct cell *acellp, int vlalso,
754 void (*func1) (struct rx_connection **rxconns, int nconns,
755 int nservers, struct afs_conn **conns,
756 struct srvAddr **addrs),
757 void (*func2) (struct rx_connection **rxconns, int nconns,
758 int nservers, struct afs_conn **conns,
759 struct srvAddr **addrs))
761 struct vrequest treq;
764 struct afs_conn *tc = NULL;
769 struct srvAddr **addrs;
770 struct afs_conn **conns;
772 struct rx_connection **rxconns;
773 afs_int32 *conntimer, *results;
775 AFS_STATCNT(afs_CheckServers);
778 * No sense in doing the server checks if we are running in disconnected
781 if (AFS_IS_DISCONNECTED)
784 conns = (struct afs_conn **)0;
785 rxconns = (struct rx_connection **) 0;
789 if ((code = afs_InitReq(&treq, afs_osi_credp)))
791 ObtainReadLock(&afs_xserver); /* Necessary? */
792 ObtainReadLock(&afs_xsrvAddr);
795 for (i = 0; i < NSERVERS; i++) {
796 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
801 addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
802 osi_Assert(addrs != NULL);
804 for (i = 0; i < NSERVERS; i++) {
805 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
806 if (j >= srvAddrCount)
812 ReleaseReadLock(&afs_xsrvAddr);
813 ReleaseReadLock(&afs_xserver);
815 conns = afs_osi_Alloc(j * sizeof(struct afs_conn *));
816 osi_Assert(conns != NULL);
817 rxconns = afs_osi_Alloc(j * sizeof(struct rx_connection *));
818 osi_Assert(rxconns != NULL);
819 conntimer = afs_osi_Alloc(j * sizeof (afs_int32));
820 osi_Assert(conntimer != NULL);
821 results = afs_osi_Alloc(j * sizeof (afs_int32));
822 osi_Assert(results != NULL);
824 for (i = 0; i < j; i++) {
830 /* See if a cell to check was specified. If it is spec'd and not
831 * this server's cell, just skip the server.
833 if (acellp && acellp != ts->cell)
836 if (((adown==AFS_LS_DOWN) && (sa->sa_flags & SRVADDR_ISDOWN))
837 || ((adown==AFS_LS_UP) && !(sa->sa_flags & SRVADDR_ISDOWN)))
840 /* check vlserver with special code */
841 if (sa->sa_portal == AFS_VLPORT) {
843 CheckVLServer(sa, &treq);
847 if (!ts->cell) /* not really an active server, anyway, it must */
848 continue; /* have just been added by setsprefs */
850 /* get a connection, even if host is down; bumps conn ref count */
851 tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
852 tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
853 1 /*force */ , 1 /*create */ , SHARED_LOCK);
854 afs_PutUser(tu, SHARED_LOCK);
858 if ((sa->sa_flags & SRVADDR_ISDOWN) || afs_HaveCallBacksFrom(sa->server)
859 || (tc->parent->srvr->server == afs_setTimeHost)) {
861 rxconns[nconns]=tc->id;
862 if (sa->sa_flags & SRVADDR_ISDOWN) {
863 rx_SetConnDeadTime(tc->id, 3);
870 } /* Outer loop over addrs */
872 (*func1)(rxconns, nconns, j, conns, addrs);
875 (*func2)(rxconns, nconns, j, conns, addrs);
878 for (i = 0; i < nconns; i++) {
879 if (conntimer[i] == 1)
880 rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
881 afs_PutConn(conns[i], SHARED_LOCK); /* done with it now */
884 afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
885 afs_osi_Free(conns, j * sizeof(struct afs_conn *));
886 afs_osi_Free(rxconns, j * sizeof(struct rx_connection *));
887 afs_osi_Free(conntimer, j * sizeof(afs_int32));
888 afs_osi_Free(results, j * sizeof(afs_int32));
890 } /*afs_CheckServers*/
893 /* find a server structure given the host address */
895 afs_FindServer(afs_int32 aserver, afs_uint16 aport, afsUUID * uuidp,
902 AFS_STATCNT(afs_FindServer);
904 i = afs_uuid_hash(uuidp) % NSERVERS;
905 for (ts = afs_servers[i]; ts; ts = ts->next) {
906 if ((ts->flags & SRVR_MULTIHOMED)
908 (memcmp((char *)uuidp, (char *)&ts->sr_uuid, sizeof(*uuidp))
909 == 0) && (!ts->addr || (ts->addr->sa_portal == aport)))
914 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
915 if ((sa->sa_ip == aserver) && (sa->sa_portal == aport)) {
922 } /*afs_FindServer */
925 /* some code for creating new server structs and setting preferences follows
926 * in the next few lines...
929 #define MAXDEFRANK 60000
930 #define DEFRANK 40000
932 /* Random number generator and constants from KnuthV2 2d ed, p170 */
938 a is 0.73m should be 0.01m .. 0.99m
939 c is more or less immaterial. 1 or a is suggested.
941 NB: LOW ORDER BITS are not very random. To get small random numbers,
942 treat result as <1, with implied binary point, and multiply by
944 NB: Has to be unsigned, since shifts on signed quantities may preserve
947 /* added rxi_getaddr() to try to get as much initial randomness as
948 possible, since at least one customer reboots ALL their clients
949 simultaneously -- so osi_Time is bound to be the same on some of the
950 clients. This is probably OK, but I don't want to see too much of it.
953 #define ranstage(x) (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
958 static afs_int32 state = 0;
961 AFS_STATCNT(afs_random);
966 * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
967 * bits are in a tv_usec
969 state = (t.tv_usec & (~0 << 4)) + (rxi_getaddr() & 0xff);
970 state += (t.tv_sec & 0xff);
971 for (i = 0; i < 30; i++) {
981 /* returns int 0..14 using the high bits of a pseudo-random number instead of
982 the low bits, as the low bits are "less random" than the high ones...
983 slight roundoff error exists, an excercise for the reader.
984 need to multiply by something with lots of ones in it, so multiply by
985 8 or 16 is right out.
988 afs_randomMod15(void)
992 temp = afs_random() >> 4;
993 temp = (temp * 15) >> 28;
999 afs_randomMod127(void)
1003 temp = afs_random() >> 7;
1004 temp = (temp * 127) >> 25;
1009 /* afs_SortOneServer()
1010 * Sort all of the srvAddrs, of a server struct, by rank from low to high.
1013 afs_SortOneServer(struct server *asp)
1015 struct srvAddr **rootsa, *lowsa, *tsa, *lowprev;
1018 for (rootsa = &(asp->addr); *rootsa; rootsa = &(lowsa->next_sa)) {
1020 lowsa = *rootsa; /* lowest sa is the first one */
1021 lowrank = lowsa->sa_iprank;
1023 for (tsa = *rootsa; tsa->next_sa; tsa = tsa->next_sa) {
1024 rank = tsa->next_sa->sa_iprank;
1025 if (rank < lowrank) {
1027 lowsa = tsa->next_sa;
1028 lowrank = lowsa->sa_iprank;
1031 if (lowprev) { /* found one lower, so rearrange them */
1032 lowprev->next_sa = lowsa->next_sa;
1033 lowsa->next_sa = *rootsa;
1040 * Sort the pointer to servers by the server's rank (its lowest rank).
1041 * It is assumed that the server already has its IP addrs sorted (the
1042 * first being its lowest rank: afs_GetServer() calls afs_SortOneServer()).
1045 afs_SortServers(struct server *aservers[], int count)
1050 AFS_STATCNT(afs_SortServers);
1052 for (i = 0; i < count; i++) {
1055 for (low = i, j = i + 1; j <= count; j++) {
1056 if ((!aservers[j]) || (!aservers[j]->addr))
1058 if ((!aservers[low]) || (!aservers[low]->addr))
1060 if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
1066 aservers[i] = aservers[low];
1070 } /*afs_SortServers */
1072 /* afs_SetServerPrefs is rather system-dependent. It pokes around in kernel
1073 data structures to determine what the local IP addresses and subnet masks
1074 are in order to choose which server(s) are on the local subnet.
1076 As I see it, there are several cases:
1077 1. The server address is one of this host's local addresses. In this case
1078 this server is to be preferred over all others.
1079 2. The server is on the same subnet as one of the this host's local
1080 addresses. (ie, an odd-sized subnet, not class A,B,orC)
1081 3. The server is on the same net as this host (class A,B or C)
1082 4. The server is on a different logical subnet or net than this host, but
1083 this host is a 'metric 0 gateway' to it. Ie, two address-spaces share
1084 one physical medium.
1085 5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
1087 6. This host and the server are disjoint.
1089 That is a rough order of preference. If a point-to-point link has a high
1090 metric, I'm assuming that it is a very slow link, and putting it at the
1091 bottom of the list (at least until RX works better over slow links). If
1092 its metric is 1, I'm assuming that it's relatively fast (T1) and putting
1094 It's not easy to check for case #4, so I'm ignoring it for the time being.
1096 BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
1097 That could be used to prefer certain servers fairly easily. Maybe some
1100 NOTE: this code is very system-dependent, and very dependent on the TCP/IP
1101 protocols (well, addresses that are stored in uint32s, at any rate).
1104 #define IA_DST(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_dstaddr))
1105 #define IA_BROAD(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
1107 /* SA2ULONG takes a sockaddr_in, not a sockaddr (same thing, just cast it!) */
1108 #define SA2ULONG(sa) ((sa)->sin_addr.s_addr)
1113 #define PPWEIGHT 4096
1118 #if defined(AFS_SUN5_ENV) && ! defined(AFS_SUN56_ENV)
1119 #include <inet/common.h>
1120 /* IP interface structure, one per local address */
1121 typedef struct ipif_s {
1122 /**/ struct ipif_s *ipif_next;
1123 struct ill_s *ipif_ill; /* Back pointer to our ill */
1124 long ipif_id; /* Logical unit number */
1125 u_int ipif_mtu; /* Starts at ipif_ill->ill_max_frag */
1126 afs_int32 ipif_local_addr; /* Local IP address for this if. */
1127 afs_int32 ipif_net_mask; /* Net mask for this interface. */
1128 afs_int32 ipif_broadcast_addr; /* Broadcast addr for this interface. */
1129 afs_int32 ipif_pp_dst_addr; /* Point-to-point dest address. */
1130 u_int ipif_flags; /* Interface flags. */
1131 u_int ipif_metric; /* BSD if metric, for compatibility. */
1132 u_int ipif_ire_type; /* LOCAL or LOOPBACK */
1133 mblk_t *ipif_arp_down_mp; /* Allocated at time arp comes up to
1134 * prevent awkward out of mem condition
1137 mblk_t *ipif_saved_ire_mp; /* Allocated for each extra IRE_SUBNET/
1138 * RESOLVER on this interface so that
1139 * they can survive ifconfig down.
1142 * The packet counts in the ipif contain the sum of the
1143 * packet counts in dead IREs that were affiliated with
1146 u_long ipif_fo_pkt_count; /* Forwarded thru our dead IREs */
1147 u_long ipif_ib_pkt_count; /* Inbound packets for our dead IREs */
1148 u_long ipif_ob_pkt_count; /* Outbound packets to our dead IREs */
1150 ipif_multicast_up:1, /* We have joined the allhosts group */
1154 typedef struct ipfb_s {
1155 /**/ struct ipf_s *ipfb_ipf; /* List of ... */
1156 kmutex_t ipfb_lock; /* Protect all ipf in list */
1159 typedef struct ilm_s {
1160 /**/ afs_int32 ilm_addr;
1162 u_int ilm_timer; /* IGMP */
1163 struct ipif_s *ilm_ipif; /* Back pointer to ipif */
1164 struct ilm_s *ilm_next; /* Linked list for each ill */
1167 typedef struct ill_s {
1168 /**/ struct ill_s *ill_next; /* Chained in at ill_g_head. */
1169 struct ill_s **ill_ptpn; /* Pointer to previous next. */
1170 queue_t *ill_rq; /* Read queue. */
1171 queue_t *ill_wq; /* Write queue. */
1173 int ill_error; /* Error value sent up by device. */
1175 ipif_t *ill_ipif; /* Interface chain for this ILL. */
1176 u_int ill_ipif_up_count; /* Number of IPIFs currently up. */
1177 u_int ill_max_frag; /* Max IDU. */
1178 char *ill_name; /* Our name. */
1179 u_int ill_name_length; /* Name length, incl. terminator. */
1180 u_int ill_subnet_type; /* IRE_RESOLVER or IRE_SUBNET. */
1181 u_int ill_ppa; /* Physical Point of Attachment num. */
1183 int ill_sap_length; /* Including sign (for position) */
1184 u_int ill_phys_addr_length; /* Excluding the sap. */
1185 mblk_t *ill_frag_timer_mp; /* Reassembly timer state. */
1186 ipfb_t *ill_frag_hash_tbl; /* Fragment hash list head. */
1188 queue_t *ill_bind_pending_q; /* Queue waiting for DL_BIND_ACK. */
1189 ipif_t *ill_ipif_pending; /* IPIF waiting for DL_BIND_ACK. */
1191 /* ill_hdr_length and ill_hdr_mp will be non zero if
1192 * the underlying device supports the M_DATA fastpath
1196 ilm_t *ill_ilm; /* Multicast mebership for lower ill */
1198 /* All non-nil cells between 'ill_first_mp_to_free' and
1199 * 'ill_last_mp_to_free' are freed in ill_delete.
1201 #define ill_first_mp_to_free ill_hdr_mp
1202 mblk_t *ill_hdr_mp; /* Contains fastpath template */
1203 mblk_t *ill_bcast_mp; /* DLPI header for broadcasts. */
1204 mblk_t *ill_bind_pending; /* T_BIND_REQ awaiting completion. */
1205 mblk_t *ill_resolver_mp; /* Resolver template. */
1206 mblk_t *ill_attach_mp;
1207 mblk_t *ill_bind_mp;
1208 mblk_t *ill_unbind_mp;
1209 mblk_t *ill_detach_mp;
1210 #define ill_last_mp_to_free ill_detach_mp
1212 u_int ill_frag_timer_running:1, ill_needs_attach:1, ill_is_ptp:1,
1213 ill_priv_stream:1, ill_unbind_pending:1, ill_pad_to_bit_31:27;
1214 MI_HRT_DCL(ill_rtime)
1215 MI_HRT_DCL(ill_rtmp)
1219 #ifdef AFS_USERSPACE_IP_ADDR
1221 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1224 * The IP addresses and ranks are determined by afsd (in user space) and
1225 * passed into the kernel at startup time through the AFSOP_ADVISEADDR
1226 * system call. These are stored in the data structure
1227 * called 'afs_cb_interface'.
1229 * struct srvAddr *sa; remote server
1230 * afs_int32 addr; one of my local addr in net order
1231 * afs_uint32 subnetmask; subnet mask of local addr in net order
1235 afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr,
1236 afs_uint32 subnetmask)
1238 afs_uint32 myAddr, myNet, mySubnet, netMask;
1239 afs_uint32 serverAddr;
1241 myAddr = ntohl(addr); /* one of my IP addr in host order */
1242 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1243 subnetmask = ntohl(subnetmask); /* subnet mask in host order */
1245 if (IN_CLASSA(myAddr))
1246 netMask = IN_CLASSA_NET;
1247 else if (IN_CLASSB(myAddr))
1248 netMask = IN_CLASSB_NET;
1249 else if (IN_CLASSC(myAddr))
1250 netMask = IN_CLASSC_NET;
1254 myNet = myAddr & netMask;
1255 mySubnet = myAddr & subnetmask;
1257 if ((serverAddr & netMask) == myNet) {
1258 if ((serverAddr & subnetmask) == mySubnet) {
1259 if (serverAddr == myAddr) { /* same machine */
1260 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1261 } else { /* same subnet */
1262 sa->sa_iprank = afs_min(sa->sa_iprank, HI);
1264 } else { /* same net */
1265 sa->sa_iprank = afs_min(sa->sa_iprank, MED);
1270 #else /* AFS_USERSPACE_IP_ADDR */
1271 #if (! defined(AFS_SUN5_ENV)) && (! defined(AFS_DARWIN_ENV)) && (! defined(AFS_OBSD47_ENV)) && defined(USEIFADDR)
1273 afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
1275 struct sockaddr_in *sin;
1278 if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
1279 if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
1281 if (SA2ULONG(sin) == ntohl(sa->sa_ip)) { /* ie, ME!!! */
1282 sa->sa_iprank = TOPR;
1284 t = HI + ifa->ia_ifp->if_metric; /* case #2 */
1285 if (sa->sa_iprank > t)
1289 t = MED + ifa->ia_ifp->if_metric; /* case #3 */
1290 if (sa->sa_iprank > t)
1294 #ifdef IFF_POINTTOPOINT
1295 /* check for case #4 -- point-to-point link */
1296 if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
1297 && (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
1298 if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1301 t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
1302 if (sa->sa_iprank > t)
1305 #endif /* IFF_POINTTOPOINT */
1307 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1308 #if (defined(AFS_DARWIN_ENV) || defined(AFS_OBSD47_ENV)) && defined(USEIFADDR)
1310 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1313 afsi_SetServerIPRank(struct srvAddr *sa, rx_ifaddr_t ifa)
1315 struct sockaddr sout;
1316 struct sockaddr_in *sin;
1319 afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
1320 afs_uint32 serverAddr;
1322 if (rx_ifaddr_address_family(ifa) != AF_INET)
1324 t = rx_ifaddr_address(ifa, &sout, sizeof(sout));
1326 sin = (struct sockaddr_in *)&sout;
1327 myAddr = ntohl(sin->sin_addr.s_addr); /* one of my IP addr in host order */
1331 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1332 t = rx_ifaddr_netmask(ifa, &sout, sizeof(sout));
1334 sin = (struct sockaddr_in *)&sout;
1335 subnetmask = ntohl(sin->sin_addr.s_addr); /* subnet mask in host order */
1339 t = rx_ifaddr_dstaddress(ifa, &sout, sizeof(sout));
1341 sin = (struct sockaddr_in *)&sout;
1342 myDstaddr = ntohl(sin->sin_addr.s_addr);
1347 if (IN_CLASSA(myAddr))
1348 netMask = IN_CLASSA_NET;
1349 else if (IN_CLASSB(myAddr))
1350 netMask = IN_CLASSB_NET;
1351 else if (IN_CLASSC(myAddr))
1352 netMask = IN_CLASSC_NET;
1356 myNet = myAddr & netMask;
1357 mySubnet = myAddr & subnetmask;
1359 if ((serverAddr & netMask) == myNet) {
1360 if ((serverAddr & subnetmask) == mySubnet) {
1361 if (serverAddr == myAddr) { /* same machine */
1362 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1363 } else { /* same subnet */
1364 sa->sa_iprank = afs_min(sa->sa_iprank, HI + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1366 } else { /* same net */
1367 sa->sa_iprank = afs_min(sa->sa_iprank, MED + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1370 #ifdef IFF_POINTTOPOINT
1371 /* check for case #4 -- point-to-point link */
1372 if ((rx_ifnet_flags(rx_ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
1373 && (myDstaddr == serverAddr)) {
1374 if (rx_ifnet_metric(rx_ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
1377 t = MED + (PPWEIGHT << rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1378 if (sa->sa_iprank > t)
1381 #endif /* IFF_POINTTOPOINT */
1383 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1384 #endif /* else AFS_USERSPACE_IP_ADDR */
1386 #ifdef AFS_SGI62_ENV
1388 afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1391 afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
1392 return 0; /* Never match, so we enumerate everyone */
1394 #endif /* AFS_SGI62_ENV */
1396 afs_SetServerPrefs(struct srvAddr *sa)
1398 #if defined(AFS_USERSPACE_IP_ADDR)
1402 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1403 afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1404 afs_cb_interface.subnetmask[i]);
1406 #else /* AFS_USERSPACE_IP_ADDR */
1407 #if defined(AFS_SUN5_ENV)
1408 #ifdef AFS_SUN510_ENV
1411 extern struct ill_s *ill_g_headp;
1412 long *addr = (long *)ill_g_headp;
1416 int subnet, subnetmask, net, netmask;
1420 #ifdef AFS_SUN510_ENV
1421 rw_enter(&afsifinfo_lock, RW_READER);
1423 for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
1425 if (IN_CLASSA(afsifinfo[i].ipaddr)) {
1426 netmask = IN_CLASSA_NET;
1427 } else if (IN_CLASSB(afsifinfo[i].ipaddr)) {
1428 netmask = IN_CLASSB_NET;
1429 } else if (IN_CLASSC(afsifinfo[i].ipaddr)) {
1430 netmask = IN_CLASSC_NET;
1434 net = afsifinfo[i].ipaddr & netmask;
1438 if (!rx_IsLoopbackAddr(afsifinfo[i].ipaddr)) { /* ignore loopback */
1442 *addrp++ = afsifinfo[i].ipaddr;
1447 /* XXXXXX Do the individual ip ranking below XXXXX */
1448 if ((sa->sa_ip & netmask) == net) {
1449 if ((sa->sa_ip & subnetmask) == subnet) {
1450 if (afsifinfo[i].ipaddr == sa->sa_ip) { /* ie, ME! */
1451 sa->sa_iprank = TOPR;
1453 sa->sa_iprank = HI + afsifinfo[i].metric; /* case #2 */
1456 sa->sa_iprank = MED + afsifinfo[i].metric; /* case #3 */
1459 sa->sa_iprank = LO + afsifinfo[i].metric; /* case #4 */
1461 /* check for case #5 -- point-to-point link */
1462 if ((afsifinfo[i].flags & IFF_POINTOPOINT)
1463 && (afsifinfo[i].dstaddr == sa->sa_ip)) {
1465 if (afsifinfo[i].metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1466 sa->sa_iprank = MAXDEFRANK;
1468 sa->sa_iprank = MED + (PPWEIGHT << afsifinfo[i].metric);
1473 rw_exit(&afsifinfo_lock);
1475 for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
1476 ill = ill->ill_next) {
1477 #ifdef AFS_SUN58_ENV
1478 /* Make sure this is an IPv4 ILL */
1482 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
1483 subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1484 subnetmask = ipif->ipif_net_mask;
1486 * Generate the local net using the local address and
1487 * whate we know about Class A, B and C networks.
1489 if (IN_CLASSA(ipif->ipif_local_addr)) {
1490 netmask = IN_CLASSA_NET;
1491 } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1492 netmask = IN_CLASSB_NET;
1493 } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1494 netmask = IN_CLASSC_NET;
1498 net = ipif->ipif_local_addr & netmask;
1501 if (!rx_IsLoopbackAddr(ipif->ipif_local_addr)) { /* ignore loopback */
1505 *addrp++ = ipif->ipif_local_addr;
1510 /* XXXXXX Do the individual ip ranking below XXXXX */
1511 if ((sa->sa_ip & netmask) == net) {
1512 if ((sa->sa_ip & subnetmask) == subnet) {
1513 if (ipif->ipif_local_addr == sa->sa_ip) { /* ie, ME! */
1514 sa->sa_iprank = TOPR;
1516 sa->sa_iprank = HI + ipif->ipif_metric; /* case #2 */
1519 sa->sa_iprank = MED + ipif->ipif_metric; /* case #3 */
1522 sa->sa_iprank = LO + ipif->ipif_metric; /* case #4 */
1524 /* check for case #5 -- point-to-point link */
1525 if ((ipif->ipif_flags & IFF_POINTOPOINT)
1526 && (ipif->ipif_pp_dst_addr == sa->sa_ip)) {
1528 if (ipif->ipif_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1529 sa->sa_iprank = MAXDEFRANK;
1531 sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1536 #endif /* AFS_SUN510_ENV */
1539 rx_ifnet_t ifn = NULL;
1540 struct in_ifaddr *ifad = (struct in_ifaddr *)0;
1541 struct sockaddr_in *sin;
1544 #ifdef notdef /* clean up, remove this */
1545 for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
1546 for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next) {
1547 if ((IFADDR2SA(ifad)->sa_family == AF_INET)
1548 && !(ifn->if_flags & IFF_LOOPBACK)) {
1553 ((struct sockaddr_in *)IFADDR2SA(ifad))->sin_addr.
1562 ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1564 if (ifn) { /* local, more or less */
1566 if (ifn->if_flags & IFF_LOOPBACK) {
1567 sa->sa_iprank = TOPR;
1570 #endif /* IFF_LOOPBACK */
1571 sin = (struct sockaddr_in *)IA_SIN(ifad);
1572 if (SA2ULONG(sin) == sa->sa_ip) {
1573 sa->sa_iprank = TOPR;
1576 #ifdef IFF_BROADCAST
1577 if (ifn->if_flags & IFF_BROADCAST) {
1578 if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1583 #endif /* IFF_BROADCAST */
1584 #ifdef IFF_POINTOPOINT
1585 if (ifn->if_flags & IFF_POINTOPOINT) {
1586 if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1587 if (ifn->if_metric > 4) {
1591 sa->sa_iprank = ifn->if_metric;
1594 #endif /* IFF_POINTOPOINT */
1595 sa->sa_iprank += MED + ifn->if_metric; /* couldn't find anything better */
1597 #else /* USEIFADDR */
1601 #ifdef AFS_SGI62_ENV
1602 (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1603 (caddr_t) sa, NULL);
1604 #elif defined(AFS_DARWIN80_ENV)
1612 if (!ifnet_list_get(AF_INET, &ifns, &count)) {
1613 for (m = 0; m < count; m++) {
1614 if (!ifnet_get_address_list(ifns[m], &ifads)) {
1615 for (j = 0; ifads[j] != NULL && cnt < ADDRSPERSITE; j++) {
1616 afsi_SetServerIPRank(sa, ifads[j]);
1619 ifnet_free_address_list(ifads);
1622 ifnet_list_free(ifns);
1625 #elif defined(AFS_DARWIN_ENV)
1629 TAILQ_FOREACH(ifn, &ifnet, if_link) {
1630 TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
1631 afsi_SetServerIPRank(sa, ifa);
1633 #elif defined(AFS_FBSD_ENV)
1635 struct in_ifaddr *ifa;
1636 TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
1637 afsi_SetServerIPRank(sa, ifa);
1639 #elif defined(AFS_OBSD_ENV)
1641 extern struct in_ifaddrhead in_ifaddr;
1642 struct in_ifaddr *ifa;
1643 for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1644 afsi_SetServerIPRank(sa, ifa);
1646 #elif defined(AFS_NBSD40_ENV)
1648 extern struct in_ifaddrhead in_ifaddrhead;
1649 struct in_ifaddr *ifa;
1650 for (ifa = in_ifaddrhead.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1651 afsi_SetServerIPRank(sa, ifa);
1655 struct in_ifaddr *ifa;
1656 for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
1657 afsi_SetServerIPRank(sa, ifa);
1660 #endif /* USEIFADDR */
1664 #endif /* AFS_SUN5_ENV */
1665 #endif /* else AFS_USERSPACE_IP_ADDR */
1667 sa->sa_iprank += afs_randomMod15();
1670 } /* afs_SetServerPrefs */
1678 /* afs_FlushServer()
1679 * The addresses on this server struct has changed in some way and will
1680 * clean up all other structures that may reference it.
1681 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1684 afs_FlushServer(struct server *srvp)
1687 struct server *ts, **pts;
1689 /* Find any volumes residing on this server and flush their state */
1690 afs_ResetVolumes(srvp);
1692 /* Flush all callbacks in the all vcaches for this specific server */
1693 afs_FlushServerCBs(srvp);
1695 /* Remove all the callbacks structs */
1697 struct afs_cbr *cb, *cbnext;
1699 ObtainWriteLock(&afs_xvcb, 300);
1700 for (cb = srvp->cbrs; cb; cb = cbnext) {
1703 } srvp->cbrs = (struct afs_cbr *)0;
1704 ReleaseWriteLock(&afs_xvcb);
1707 /* If no more srvAddr structs hanging off of this server struct,
1711 /* Remove the server structure from the cell list - if there */
1712 afs_RemoveCellEntry(srvp);
1714 /* Remove from the afs_servers hash chain */
1715 for (i = 0; i < NSERVERS; i++) {
1716 for (pts = &(afs_servers[i]), ts = *pts; ts;
1717 pts = &(ts->next), ts = *pts) {
1725 *pts = ts->next; /* Found it. Remove it */
1726 afs_osi_Free(ts, sizeof(struct server)); /* Free it */
1732 /* afs_RemoveSrvAddr()
1733 * This removes a SrvAddr structure from its server structure.
1734 * The srvAddr struct is not free'd because it connections may still
1735 * be open to it. It is up to the calling process to make sure it
1736 * remains connected to a server struct.
1737 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1738 * It is not removed from the afs_srvAddrs hash chain.
1741 afs_RemoveSrvAddr(struct srvAddr *sap)
1743 struct srvAddr **psa, *sa;
1750 /* Find the srvAddr in the server's list and remove it */
1751 for (psa = &(srv->addr), sa = *psa; sa; psa = &(sa->next_sa), sa = *psa) {
1759 /* Flush the server struct since it's IP address has changed */
1760 afs_FlushServer(srv);
1764 /* afs_GetCapabilities
1765 * Try and retrieve capabilities of a given file server. Carps on actual
1766 * failure. Servers are not expected to support this RPC. */
1768 afs_GetCapabilities(struct server *ts)
1770 Capabilities caps = {0, NULL};
1771 struct vrequest treq;
1772 struct afs_conn *tc;
1773 struct unixuser *tu;
1776 if ( !ts || !ts->cell )
1778 if ( !afs_osi_credp )
1781 if ((code = afs_InitReq(&treq, afs_osi_credp)))
1783 tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
1786 tc = afs_ConnBySA(ts->addr, ts->cell->fsport, ts->cell->cellNum, tu, 0, 1,
1790 /* InitCallBackStateN, triggered by our RPC, may need this */
1791 ReleaseWriteLock(&afs_xserver);
1792 code = RXAFS_GetCapabilities(tc->id, &caps);
1793 ObtainWriteLock(&afs_xserver, 723);
1794 /* we forced a conn above; important we mark it down if needed */
1795 if ((code < 0) && (code != RXGEN_OPCODE)) {
1796 afs_ServerDown(tc->parent->srvr);
1797 ForceNewConnections(tc->parent->srvr); /* multi homed clients */
1799 afs_PutConn(tc, SHARED_LOCK);
1800 if ( code && code != RXGEN_OPCODE ) {
1801 afs_warn("RXAFS_GetCapabilities failed with code %d\n", code);
1802 /* better not be anything to free. we failed! */
1806 ts->flags |= SCAPS_KNOWN;
1808 if ( caps.Capabilities_len > 0 ) {
1809 ts->capabilities = caps.Capabilities_val[0];
1810 xdr_free((xdrproc_t)xdr_Capabilities, &caps);
1811 caps.Capabilities_len = 0;
1812 caps.Capabilities_val = NULL;
1818 * Return an updated and properly initialized server structure
1819 * corresponding to the server ID, cell, and port specified.
1820 * If one does not exist, then one will be created.
1821 * aserver and aport must be in NET byte order.
1824 afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers, afs_int32 acell,
1825 u_short aport, afs_int32 locktype, afsUUID * uuidp,
1826 afs_int32 addr_uniquifier)
1828 struct server *oldts = 0, *ts, *newts, *orphts = 0;
1829 struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1831 afs_int32 iphash, k, srvcount = 0;
1832 unsigned int srvhash;
1834 AFS_STATCNT(afs_GetServer);
1836 ObtainSharedLock(&afs_xserver, 13);
1838 /* Check if the server struct exists and is up to date */
1841 panic("afs_GetServer: incorect count of servers");
1842 ObtainReadLock(&afs_xsrvAddr);
1843 ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1844 ReleaseReadLock(&afs_xsrvAddr);
1845 if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1846 /* Found a server struct that is not multihomed and has the
1847 * IP address associated with it. A correct match.
1849 ReleaseSharedLock(&afs_xserver);
1854 panic("afs_GetServer: incorrect count of servers");
1855 ts = afs_FindServer(0, aport, uuidp, locktype);
1856 if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1857 /* Found a server struct that is multihomed and same
1858 * uniqufier (same IP addrs). The above if statement is the
1859 * same as in InstallUVolumeEntry().
1861 ReleaseSharedLock(&afs_xserver);
1865 oldts = ts; /* Will reuse if same uuid */
1868 UpgradeSToWLock(&afs_xserver, 36);
1869 ObtainWriteLock(&afs_xsrvAddr, 116);
1871 srvcount = afs_totalServers;
1873 /* Reuse/allocate a new server structure */
1877 newts = afs_osi_Alloc(sizeof(struct server));
1879 panic("malloc of server struct");
1881 memset(newts, 0, sizeof(struct server));
1883 /* Add the server struct to the afs_servers[] hash chain */
1885 (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
1886 newts->next = afs_servers[srvhash];
1887 afs_servers[srvhash] = newts;
1890 /* Initialize the server structure */
1891 if (uuidp) { /* Multihomed */
1892 newts->sr_uuid = *uuidp;
1893 newts->sr_addr_uniquifier = addr_uniquifier;
1894 newts->flags |= SRVR_MULTIHOMED;
1897 newts->cell = afs_GetCell(acell, 0);
1899 fsport = (newts->cell ? newts->cell->fsport : AFS_FSPORT);
1901 /* For each IP address we are registering */
1902 for (k = 0; k < nservers; k++) {
1903 iphash = SHash(aserverp[k]);
1905 /* Check if the srvAddr structure already exists. If so, remove
1906 * it from its server structure and add it to the new one.
1908 for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
1909 if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
1912 if (oldsa && (oldsa->server != newts)) {
1913 afs_RemoveSrvAddr(oldsa); /* Remove from its server struct */
1914 oldsa->next_sa = newts->addr; /* Add to the new server struct */
1915 newts->addr = oldsa;
1918 /* Reuse/allocate a new srvAddr structure */
1922 newsa = afs_osi_Alloc(sizeof(struct srvAddr));
1924 panic("malloc of srvAddr struct");
1925 afs_totalSrvAddrs++;
1926 memset(newsa, 0, sizeof(struct srvAddr));
1928 /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1929 newsa->next_bkt = afs_srvAddrs[iphash];
1930 afs_srvAddrs[iphash] = newsa;
1932 /* Hang off of the server structure */
1933 newsa->next_sa = newts->addr;
1934 newts->addr = newsa;
1936 /* Initialize the srvAddr Structure */
1937 newsa->sa_ip = aserverp[k];
1938 newsa->sa_portal = aport;
1941 /* Update the srvAddr Structure */
1942 newsa->server = newts;
1943 if (newts->flags & SRVR_ISDOWN)
1944 newsa->sa_flags |= SRVADDR_ISDOWN;
1946 newsa->sa_flags |= SRVADDR_MH;
1948 newsa->sa_flags &= ~SRVADDR_MH;
1950 /* Compute preference values and resort */
1951 if (!newsa->sa_iprank) {
1952 afs_SetServerPrefs(newsa); /* new server rank */
1955 afs_SortOneServer(newts); /* Sort by rank */
1957 /* If we reused the server struct, remove any of its srvAddr
1958 * structs that will no longer be associated with this server.
1960 if (oldts) { /* reused the server struct */
1961 for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
1962 nextsa = orphsa->next_sa;
1963 for (k = 0; k < nservers; k++) {
1964 if (orphsa->sa_ip == aserverp[k])
1965 break; /* belongs */
1968 continue; /* belongs */
1970 /* Have a srvAddr struct. Now get a server struct (if not already) */
1972 orphts = afs_osi_Alloc(sizeof(struct server));
1974 panic("malloc of lo server struct");
1975 memset(orphts, 0, sizeof(struct server));
1978 /* Add the orphaned server to the afs_servers[] hash chain.
1979 * Its iphash does not matter since we never look up the server
1980 * in the afs_servers table by its ip address (only by uuid -
1981 * which this has none).
1983 iphash = SHash(aserverp[k]);
1984 orphts->next = afs_servers[iphash];
1985 afs_servers[iphash] = orphts;
1988 orphts->cell = afs_GetCell(acell, 0);
1991 /* Hang the srvAddr struct off of the server structure. The server
1992 * may have multiple srvAddrs, but it won't be marked multihomed.
1994 afs_RemoveSrvAddr(orphsa); /* remove */
1995 orphsa->next_sa = orphts->addr; /* hang off server struct */
1996 orphts->addr = orphsa;
1997 orphsa->server = orphts;
1998 orphsa->sa_flags |= SRVADDR_NOUSE; /* flag indicating not in use */
1999 orphsa->sa_flags &= ~SRVADDR_MH; /* Not multihomed */
2003 srvcount = afs_totalServers - srvcount; /* # servers added and removed */
2005 struct afs_stats_SrvUpDownInfo *upDownP;
2006 /* With the introduction of this new record, we need to adjust the
2007 * proper individual & global server up/down info.
2009 upDownP = GetUpDownStats(newts);
2010 upDownP->numTtlRecords += srvcount;
2011 afs_stats_cmperf.srvRecords += srvcount;
2012 if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
2013 afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
2016 ReleaseWriteLock(&afs_xsrvAddr);
2018 if ( aport == AFS_FSPORT && !(newts->flags & SCAPS_KNOWN))
2019 afs_GetCapabilities(newts);
2021 ReleaseWriteLock(&afs_xserver);
2023 } /* afs_GetServer */
2026 afs_ActivateServer(struct srvAddr *sap)
2028 osi_timeval_t currTime; /*Filled with current time */
2029 osi_timeval_t *currTimeP; /*Ptr to above */
2030 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record */
2031 struct server *aserver = sap->server;
2033 if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
2035 * This server record has not yet been activated. Go for it,
2036 * recording its ``birth''.
2038 aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
2039 currTimeP = &currTime;
2040 osi_GetuTime(currTimeP);
2041 aserver->activationTime = currTime.tv_sec;
2042 upDownP = GetUpDownStats(aserver);
2043 if (aserver->flags & SRVR_ISDOWN) {
2044 upDownP->numDownRecords++;
2046 upDownP->numUpRecords++;
2047 upDownP->numRecordsNeverDown++;
2053 afs_RemoveAllConns(void)
2056 struct server *ts, *nts;
2059 ObtainReadLock(&afs_xserver);
2060 ObtainWriteLock(&afs_xconn, 1001);
2062 /*printf("Destroying connections ... ");*/
2063 for (i = 0; i < NSERVERS; i++) {
2064 for (ts = afs_servers[i]; ts; ts = nts) {
2066 for (sa = ts->addr; sa; sa = sa->next_sa) {
2068 afs_ReleaseConns(sa->conns);
2074 /*printf("done\n");*/
2076 ReleaseWriteLock(&afs_xconn);
2077 ReleaseReadLock(&afs_xserver);
2082 afs_MarkAllServersUp(void)
2088 ObtainWriteLock(&afs_xserver, 721);
2089 ObtainWriteLock(&afs_xsrvAddr, 722);
2090 for (i = 0; i< NSERVERS; i++) {
2091 for (ts = afs_servers[i]; ts; ts = ts->next) {
2092 for (sa = ts->addr; sa; sa = sa->next_sa) {
2093 afs_MarkServerUpOrDown(sa, 0);
2097 ReleaseWriteLock(&afs_xsrvAddr);
2098 ReleaseWriteLock(&afs_xserver);