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->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));
509 for (i = 0; i < NSERVERS; i++) {
510 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
511 if (j >= srvAddrCount)
517 ReleaseReadLock(&afs_xsrvAddr);
518 ReleaseReadLock(&afs_xserver);
519 for (i = 0; i < j; i++) {
521 ForceNewConnections(sa);
525 /* check down servers (if adown), or running servers (if !adown) */
527 afs_CheckServers(int adown, struct cell *acellp)
529 struct vrequest treq;
535 afs_int32 start, end = 0, delta;
540 struct srvAddr **addrs;
541 struct afs_conn **conns;
543 struct rx_connection **rxconns;
544 afs_int32 *conntimer, *deltas, *results;
545 Capabilities *caps = NULL;
547 AFS_STATCNT(afs_CheckServers);
550 * No sense in doing the server checks if we are running in disconnected
553 if (AFS_IS_DISCONNECTED)
556 conns = (struct afs_conn **)0;
557 rxconns = (struct rx_connection **) 0;
561 if ((code = afs_InitReq(&treq, afs_osi_credp)))
563 ObtainReadLock(&afs_xserver); /* Necessary? */
564 ObtainReadLock(&afs_xsrvAddr);
567 for (i = 0; i < NSERVERS; i++) {
568 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
573 addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
575 for (i = 0; i < NSERVERS; i++) {
576 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
577 if (j >= srvAddrCount)
583 ReleaseReadLock(&afs_xsrvAddr);
584 ReleaseReadLock(&afs_xserver);
586 conns = (struct afs_conn **)afs_osi_Alloc(j * sizeof(struct afs_conn *));
587 rxconns = (struct rx_connection **)afs_osi_Alloc(j * sizeof(struct rx_connection *));
588 conntimer = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
589 deltas = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
590 results = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
592 caps = (Capabilities *)afs_osi_Alloc(j * sizeof (Capabilities));
593 memset(caps, 0, j * sizeof(Capabilities));
595 for (i = 0; i < j; i++) {
602 /* See if a cell to check was specified. If it is spec'd and not
603 * this server's cell, just skip the server.
605 if (acellp && acellp != ts->cell)
608 if ((!adown && (sa->sa_flags & SRVADDR_ISDOWN))
609 || (adown && !(sa->sa_flags & SRVADDR_ISDOWN)))
612 /* check vlserver with special code */
613 if (sa->sa_portal == AFS_VLPORT) {
614 CheckVLServer(sa, &treq);
618 if (!ts->cell) /* not really an active server, anyway, it must */
619 continue; /* have just been added by setsprefs */
621 /* get a connection, even if host is down; bumps conn ref count */
622 tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
623 tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
624 1 /*force */ , 1 /*create */ , SHARED_LOCK);
625 afs_PutUser(tu, SHARED_LOCK);
629 if ((sa->sa_flags & SRVADDR_ISDOWN) || afs_HaveCallBacksFrom(sa->server)
630 || (tc->srvr->server == afs_setTimeHost)) {
632 rxconns[nconns]=tc->id;
633 if (sa->sa_flags & SRVADDR_ISDOWN) {
634 rx_SetConnDeadTime(tc->id, 3);
641 } /* Outer loop over addrs */
644 multi_Rx(rxconns,nconns)
646 multi_RXAFS_GetCapabilities(&caps[multi_i]);
647 results[multi_i] = multi_error;
651 for ( i = 0 ; i < nconns ; i++ ) {
652 ts = addrs[i]->server;
655 ts->capabilities = 0;
656 ts->flags |= SCAPS_KNOWN;
657 if ( results[i] == RXGEN_OPCODE ) {
658 /* Mark server as up - it responded */
662 if ( results[i] >= 0 )
663 /* we currently handle 32-bits of capabilities */
664 if (caps[i].Capabilities_len > 0) {
665 ts->capabilities = caps[i].Capabilities_val[0];
666 xdr_free((xdrproc_t)xdr_Capabilities, &caps[i]);
667 caps[i].Capabilities_val = NULL;
668 caps[i].Capabilities_len = 0;
672 if ( afs_setTime != 0 ) {
673 start = osi_Time(); /* time the gettimeofday call */
675 if ( afs_setTimeHost == NULL ) {
676 multi_Rx(rxconns,nconns)
678 tv.tv_sec = tv.tv_usec = 0;
680 (afs_uint32 *)&tv.tv_sec, (afs_uint32 *)&tv.tv_usec);
683 if (conntimer[multi_i] == 1)
684 rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
686 results[multi_i]=multi_error;
687 if ((start == end) && !multi_error)
688 deltas[multi_i] = end - tv.tv_sec;
692 else { /* find and query setTimeHost only */
693 for ( i = 0 ; i < j ; i++ ) {
694 if ( conns[i] == NULL || conns[i]->srvr == NULL )
696 if ( conns[i]->srvr->server == afs_setTimeHost ) {
697 tv.tv_sec = tv.tv_usec = 0;
698 results[i] = RXAFS_GetTime(rxconns[i],
699 (afs_uint32 *)&tv.tv_sec, (afs_uint32 *)&tv.tv_usec);
701 if ((start == end) && !results[i])
702 deltas[i] = end - tv.tv_sec;
710 for(i=0;i<nconns;i++){
714 if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) && (tc->srvr == sa)) {
716 print_internet_address("afs: file server ", sa, " is back up", 2);
718 ObtainWriteLock(&afs_xserver, 244);
719 ObtainWriteLock(&afs_xsrvAddr, 245);
720 afs_MarkServerUpOrDown(sa, 0);
721 ReleaseWriteLock(&afs_xsrvAddr);
722 ReleaseWriteLock(&afs_xserver);
724 if (afs_waitForeverCount) {
725 afs_osi_Wakeup(&afs_waitForever);
728 if (results[i] < 0) {
731 ForceNewConnections(sa); /* multi homed clients */
737 * If we're supposed to set the time, and the call worked
738 * quickly (same second response) and this is the host we
739 * use for the time and the time is really different, then
740 * really set the time
742 if (afs_setTime != 0) {
743 for (i=0; i<nconns; i++) {
748 if ((tc->srvr->server == afs_setTimeHost ||
749 /* Sync only to a server in the local cell */
750 (afs_setTimeHost == (struct server *)0 &&
751 afs_IsPrimaryCell(sa->server->cell)))) {
753 char msgbuf[90]; /* strlen("afs: setting clock...") + slop */
754 delta = end - tv.tv_sec; /* how many secs fast we are */
756 afs_setTimeHost = tc->srvr->server;
757 /* see if clock has changed enough to make it worthwhile */
758 if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) {
760 if (delta > AFS_MAXCHANGEBACK) {
761 /* setting clock too far back, just do it a little */
762 tv.tv_sec = end - AFS_MAXCHANGEBACK;
764 tv.tv_sec = end - delta;
766 afs_osi_SetTime(&tv);
768 strcpy(msgbuf, "afs: setting clock back ");
769 if (delta > AFS_MAXCHANGEBACK) {
771 afs_cv2string(&tbuffer[CVBS],
773 afs_strcat(msgbuf, " seconds (of ");
775 afs_cv2string(&tbuffer[CVBS],
778 afs_strcat(msgbuf, ", via ");
779 print_internet_address(msgbuf, sa,
780 "); clock is still fast.",
784 afs_cv2string(&tbuffer[CVBS], delta));
785 afs_strcat(msgbuf, " seconds (via ");
786 print_internet_address(msgbuf, sa, ").", 0);
789 strcpy(msgbuf, "afs: setting clock ahead ");
791 afs_cv2string(&tbuffer[CVBS], -delta));
792 afs_strcat(msgbuf, " seconds (via ");
793 print_internet_address(msgbuf, sa, ").", 0);
795 /* We're only going to set it once; why bother looping? */
801 for (i = 0; i < nconns; i++) {
802 afs_PutConn(conns[i], SHARED_LOCK); /* done with it now */
805 afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
806 afs_osi_Free(conns, j * sizeof(struct afs_conn *));
807 afs_osi_Free(rxconns, j * sizeof(struct rx_connection *));
808 afs_osi_Free(conntimer, j * sizeof(afs_int32));
809 afs_osi_Free(deltas, j * sizeof(afs_int32));
810 afs_osi_Free(results, j * sizeof(afs_int32));
811 afs_osi_Free(caps, j * sizeof(Capabilities));
813 } /*afs_CheckServers*/
816 /* find a server structure given the host address */
818 afs_FindServer(afs_int32 aserver, afs_uint16 aport, afsUUID * uuidp,
825 AFS_STATCNT(afs_FindServer);
827 i = afs_uuid_hash(uuidp) % NSERVERS;
828 for (ts = afs_servers[i]; ts; ts = ts->next) {
829 if ((ts->flags & SRVR_MULTIHOMED)
831 (memcmp((char *)uuidp, (char *)&ts->sr_uuid, sizeof(*uuidp))
832 == 0) && (!ts->addr || (ts->addr->sa_portal == aport)))
837 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
838 if ((sa->sa_ip == aserver) && (sa->sa_portal == aport)) {
845 } /*afs_FindServer */
848 /* some code for creating new server structs and setting preferences follows
849 * in the next few lines...
852 #define MAXDEFRANK 60000
853 #define DEFRANK 40000
855 /* Random number generator and constants from KnuthV2 2d ed, p170 */
861 a is 0.73m should be 0.01m .. 0.99m
862 c is more or less immaterial. 1 or a is suggested.
864 NB: LOW ORDER BITS are not very random. To get small random numbers,
865 treat result as <1, with implied binary point, and multiply by
867 NB: Has to be unsigned, since shifts on signed quantities may preserve
870 /* added rxi_getaddr() to try to get as much initial randomness as
871 possible, since at least one customer reboots ALL their clients
872 simultaneously -- so osi_Time is bound to be the same on some of the
873 clients. This is probably OK, but I don't want to see too much of it.
876 #define ranstage(x) (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
881 static afs_int32 state = 0;
884 AFS_STATCNT(afs_random);
889 * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
890 * bits are in a tv_usec
892 state = (t.tv_usec & (~0 << 4)) + (rxi_getaddr() & 0xff);
893 state += (t.tv_sec & 0xff);
894 for (i = 0; i < 30; i++) {
904 /* returns int 0..14 using the high bits of a pseudo-random number instead of
905 the low bits, as the low bits are "less random" than the high ones...
906 slight roundoff error exists, an excercise for the reader.
907 need to multiply by something with lots of ones in it, so multiply by
908 8 or 16 is right out.
911 afs_randomMod15(void)
915 temp = afs_random() >> 4;
916 temp = (temp * 15) >> 28;
922 afs_randomMod127(void)
926 temp = afs_random() >> 7;
927 temp = (temp * 127) >> 25;
932 /* afs_SortOneServer()
933 * Sort all of the srvAddrs, of a server struct, by rank from low to high.
936 afs_SortOneServer(struct server *asp)
938 struct srvAddr **rootsa, *lowsa, *tsa, *lowprev;
941 for (rootsa = &(asp->addr); *rootsa; rootsa = &(lowsa->next_sa)) {
943 lowsa = *rootsa; /* lowest sa is the first one */
944 lowrank = lowsa->sa_iprank;
946 for (tsa = *rootsa; tsa->next_sa; tsa = tsa->next_sa) {
947 rank = tsa->next_sa->sa_iprank;
948 if (rank < lowrank) {
950 lowsa = tsa->next_sa;
951 lowrank = lowsa->sa_iprank;
954 if (lowprev) { /* found one lower, so rearrange them */
955 lowprev->next_sa = lowsa->next_sa;
956 lowsa->next_sa = *rootsa;
963 * Sort the pointer to servers by the server's rank (its lowest rank).
964 * It is assumed that the server already has its IP addrs sorted (the
965 * first being its lowest rank: afs_GetServer() calls afs_SortOneServer()).
968 afs_SortServers(struct server *aservers[], int count)
973 AFS_STATCNT(afs_SortServers);
975 for (i = 0; i < count; i++) {
978 for (low = i, j = i + 1; j <= count; j++) {
979 if ((!aservers[j]) || (!aservers[j]->addr))
981 if ((!aservers[low]) || (!aservers[low]->addr))
983 if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
989 aservers[i] = aservers[low];
993 } /*afs_SortServers */
995 /* afs_SetServerPrefs is rather system-dependent. It pokes around in kernel
996 data structures to determine what the local IP addresses and subnet masks
997 are in order to choose which server(s) are on the local subnet.
999 As I see it, there are several cases:
1000 1. The server address is one of this host's local addresses. In this case
1001 this server is to be preferred over all others.
1002 2. The server is on the same subnet as one of the this host's local
1003 addresses. (ie, an odd-sized subnet, not class A,B,orC)
1004 3. The server is on the same net as this host (class A,B or C)
1005 4. The server is on a different logical subnet or net than this host, but
1006 this host is a 'metric 0 gateway' to it. Ie, two address-spaces share
1007 one physical medium.
1008 5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
1010 6. This host and the server are disjoint.
1012 That is a rough order of preference. If a point-to-point link has a high
1013 metric, I'm assuming that it is a very slow link, and putting it at the
1014 bottom of the list (at least until RX works better over slow links). If
1015 its metric is 1, I'm assuming that it's relatively fast (T1) and putting
1017 It's not easy to check for case #4, so I'm ignoring it for the time being.
1019 BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
1020 That could be used to prefer certain servers fairly easily. Maybe some
1023 NOTE: this code is very system-dependent, and very dependent on the TCP/IP
1024 protocols (well, addresses that are stored in uint32s, at any rate).
1027 #define IA_DST(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_dstaddr))
1028 #define IA_BROAD(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
1030 /* SA2ULONG takes a sockaddr_in, not a sockaddr (same thing, just cast it!) */
1031 #define SA2ULONG(sa) ((sa)->sin_addr.s_addr)
1036 #define PPWEIGHT 4096
1041 #if defined(AFS_SUN5_ENV) && ! defined(AFS_SUN56_ENV)
1042 #include <inet/common.h>
1043 /* IP interface structure, one per local address */
1044 typedef struct ipif_s {
1045 /**/ struct ipif_s *ipif_next;
1046 struct ill_s *ipif_ill; /* Back pointer to our ill */
1047 long ipif_id; /* Logical unit number */
1048 u_int ipif_mtu; /* Starts at ipif_ill->ill_max_frag */
1049 afs_int32 ipif_local_addr; /* Local IP address for this if. */
1050 afs_int32 ipif_net_mask; /* Net mask for this interface. */
1051 afs_int32 ipif_broadcast_addr; /* Broadcast addr for this interface. */
1052 afs_int32 ipif_pp_dst_addr; /* Point-to-point dest address. */
1053 u_int ipif_flags; /* Interface flags. */
1054 u_int ipif_metric; /* BSD if metric, for compatibility. */
1055 u_int ipif_ire_type; /* LOCAL or LOOPBACK */
1056 mblk_t *ipif_arp_down_mp; /* Allocated at time arp comes up to
1057 * prevent awkward out of mem condition
1060 mblk_t *ipif_saved_ire_mp; /* Allocated for each extra IRE_SUBNET/
1061 * RESOLVER on this interface so that
1062 * they can survive ifconfig down.
1065 * The packet counts in the ipif contain the sum of the
1066 * packet counts in dead IREs that were affiliated with
1069 u_long ipif_fo_pkt_count; /* Forwarded thru our dead IREs */
1070 u_long ipif_ib_pkt_count; /* Inbound packets for our dead IREs */
1071 u_long ipif_ob_pkt_count; /* Outbound packets to our dead IREs */
1073 ipif_multicast_up:1, /* We have joined the allhosts group */
1077 typedef struct ipfb_s {
1078 /**/ struct ipf_s *ipfb_ipf; /* List of ... */
1079 kmutex_t ipfb_lock; /* Protect all ipf in list */
1082 typedef struct ilm_s {
1083 /**/ afs_int32 ilm_addr;
1085 u_int ilm_timer; /* IGMP */
1086 struct ipif_s *ilm_ipif; /* Back pointer to ipif */
1087 struct ilm_s *ilm_next; /* Linked list for each ill */
1090 typedef struct ill_s {
1091 /**/ struct ill_s *ill_next; /* Chained in at ill_g_head. */
1092 struct ill_s **ill_ptpn; /* Pointer to previous next. */
1093 queue_t *ill_rq; /* Read queue. */
1094 queue_t *ill_wq; /* Write queue. */
1096 int ill_error; /* Error value sent up by device. */
1098 ipif_t *ill_ipif; /* Interface chain for this ILL. */
1099 u_int ill_ipif_up_count; /* Number of IPIFs currently up. */
1100 u_int ill_max_frag; /* Max IDU. */
1101 char *ill_name; /* Our name. */
1102 u_int ill_name_length; /* Name length, incl. terminator. */
1103 u_int ill_subnet_type; /* IRE_RESOLVER or IRE_SUBNET. */
1104 u_int ill_ppa; /* Physical Point of Attachment num. */
1106 int ill_sap_length; /* Including sign (for position) */
1107 u_int ill_phys_addr_length; /* Excluding the sap. */
1108 mblk_t *ill_frag_timer_mp; /* Reassembly timer state. */
1109 ipfb_t *ill_frag_hash_tbl; /* Fragment hash list head. */
1111 queue_t *ill_bind_pending_q; /* Queue waiting for DL_BIND_ACK. */
1112 ipif_t *ill_ipif_pending; /* IPIF waiting for DL_BIND_ACK. */
1114 /* ill_hdr_length and ill_hdr_mp will be non zero if
1115 * the underlying device supports the M_DATA fastpath
1119 ilm_t *ill_ilm; /* Multicast mebership for lower ill */
1121 /* All non-nil cells between 'ill_first_mp_to_free' and
1122 * 'ill_last_mp_to_free' are freed in ill_delete.
1124 #define ill_first_mp_to_free ill_hdr_mp
1125 mblk_t *ill_hdr_mp; /* Contains fastpath template */
1126 mblk_t *ill_bcast_mp; /* DLPI header for broadcasts. */
1127 mblk_t *ill_bind_pending; /* T_BIND_REQ awaiting completion. */
1128 mblk_t *ill_resolver_mp; /* Resolver template. */
1129 mblk_t *ill_attach_mp;
1130 mblk_t *ill_bind_mp;
1131 mblk_t *ill_unbind_mp;
1132 mblk_t *ill_detach_mp;
1133 #define ill_last_mp_to_free ill_detach_mp
1135 u_int ill_frag_timer_running:1, ill_needs_attach:1, ill_is_ptp:1,
1136 ill_priv_stream:1, ill_unbind_pending:1, ill_pad_to_bit_31:27;
1137 MI_HRT_DCL(ill_rtime)
1138 MI_HRT_DCL(ill_rtmp)
1142 #ifdef AFS_USERSPACE_IP_ADDR
1144 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1147 * The IP addresses and ranks are determined by afsd (in user space) and
1148 * passed into the kernel at startup time through the AFSOP_ADVISEADDR
1149 * system call. These are stored in the data structure
1150 * called 'afs_cb_interface'.
1152 * struct srvAddr *sa; remote server
1153 * afs_int32 addr; one of my local addr in net order
1154 * afs_uint32 subnetmask; subnet mask of local addr in net order
1158 afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr,
1159 afs_uint32 subnetmask)
1161 afs_uint32 myAddr, myNet, mySubnet, netMask;
1162 afs_uint32 serverAddr;
1164 myAddr = ntohl(addr); /* one of my IP addr in host order */
1165 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1166 subnetmask = ntohl(subnetmask); /* subnet mask in host order */
1168 if (IN_CLASSA(myAddr))
1169 netMask = IN_CLASSA_NET;
1170 else if (IN_CLASSB(myAddr))
1171 netMask = IN_CLASSB_NET;
1172 else if (IN_CLASSC(myAddr))
1173 netMask = IN_CLASSC_NET;
1177 myNet = myAddr & netMask;
1178 mySubnet = myAddr & subnetmask;
1180 if ((serverAddr & netMask) == myNet) {
1181 if ((serverAddr & subnetmask) == mySubnet) {
1182 if (serverAddr == myAddr) { /* same machine */
1183 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1184 } else { /* same subnet */
1185 sa->sa_iprank = afs_min(sa->sa_iprank, HI);
1187 } else { /* same net */
1188 sa->sa_iprank = afs_min(sa->sa_iprank, MED);
1193 #else /* AFS_USERSPACE_IP_ADDR */
1194 #if (! defined(AFS_SUN5_ENV)) && !defined(AFS_DARWIN_ENV) && defined(USEIFADDR)
1196 afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
1198 struct sockaddr_in *sin;
1201 if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
1202 if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
1204 if (SA2ULONG(sin) == ntohl(sa->sa_ip)) { /* ie, ME!!! */
1205 sa->sa_iprank = TOPR;
1207 t = HI + ifa->ia_ifp->if_metric; /* case #2 */
1208 if (sa->sa_iprank > t)
1212 t = MED + ifa->ia_ifp->if_metric; /* case #3 */
1213 if (sa->sa_iprank > t)
1217 #ifdef IFF_POINTTOPOINT
1218 /* check for case #4 -- point-to-point link */
1219 if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
1220 && (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
1221 if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1224 t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
1225 if (sa->sa_iprank > t)
1228 #endif /* IFF_POINTTOPOINT */
1230 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1231 #if defined(AFS_DARWIN_ENV) && defined(USEIFADDR)
1233 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1236 afsi_SetServerIPRank(struct srvAddr *sa, rx_ifaddr_t ifa)
1238 struct sockaddr sout;
1239 struct sockaddr_in *sin;
1242 afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
1243 afs_uint32 serverAddr;
1245 if (rx_ifaddr_address_family(ifa) != AF_INET)
1247 t = rx_ifaddr_address(ifa, &sout, sizeof(sout));
1249 sin = (struct sockaddr_in *)&sout;
1250 myAddr = ntohl(sin->sin_addr.s_addr); /* one of my IP addr in host order */
1254 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1255 t = rx_ifaddr_netmask(ifa, &sout, sizeof(sout));
1257 sin = (struct sockaddr_in *)&sout;
1258 subnetmask = ntohl(sin->sin_addr.s_addr); /* subnet mask in host order */
1262 t = rx_ifaddr_dstaddress(ifa, &sout, sizeof(sout));
1264 sin = (struct sockaddr_in *)&sout;
1265 myDstaddr = sin->sin_addr.s_addr;
1270 if (IN_CLASSA(myAddr))
1271 netMask = IN_CLASSA_NET;
1272 else if (IN_CLASSB(myAddr))
1273 netMask = IN_CLASSB_NET;
1274 else if (IN_CLASSC(myAddr))
1275 netMask = IN_CLASSC_NET;
1279 myNet = myAddr & netMask;
1280 mySubnet = myAddr & subnetmask;
1282 if ((serverAddr & netMask) == myNet) {
1283 if ((serverAddr & subnetmask) == mySubnet) {
1284 if (serverAddr == myAddr) { /* same machine */
1285 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1286 } else { /* same subnet */
1287 sa->sa_iprank = afs_min(sa->sa_iprank, HI + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1289 } else { /* same net */
1290 sa->sa_iprank = afs_min(sa->sa_iprank, MED + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1293 #ifdef IFF_POINTTOPOINT
1294 /* check for case #4 -- point-to-point link */
1295 if ((rx_ifnet_flags(rx_ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
1296 && (myDstaddr == serverAddr)) {
1297 if (rx_ifnet_metric(rx_ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
1300 t = MED + (PPWEIGHT << rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1301 if (sa->sa_iprank > t)
1304 #endif /* IFF_POINTTOPOINT */
1306 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1307 #endif /* else AFS_USERSPACE_IP_ADDR */
1309 #ifdef AFS_SGI62_ENV
1311 afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1314 afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
1315 return 0; /* Never match, so we enumerate everyone */
1317 #endif /* AFS_SGI62_ENV */
1319 afs_SetServerPrefs(struct srvAddr *sa)
1321 #if defined(AFS_USERSPACE_IP_ADDR)
1325 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1326 afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1327 afs_cb_interface.subnetmask[i]);
1329 #else /* AFS_USERSPACE_IP_ADDR */
1330 #if defined(AFS_SUN5_ENV)
1331 #ifdef AFS_SUN510_ENV
1334 extern struct ill_s *ill_g_headp;
1335 long *addr = (long *)ill_g_headp;
1339 int subnet, subnetmask, net, netmask;
1343 #ifdef AFS_SUN510_ENV
1344 rw_enter(&afsifinfo_lock, RW_READER);
1346 for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
1348 if (IN_CLASSA(afsifinfo[i].ipaddr)) {
1349 netmask = IN_CLASSA_NET;
1350 } else if (IN_CLASSB(afsifinfo[i].ipaddr)) {
1351 netmask = IN_CLASSB_NET;
1352 } else if (IN_CLASSC(afsifinfo[i].ipaddr)) {
1353 netmask = IN_CLASSC_NET;
1357 net = afsifinfo[i].ipaddr & netmask;
1361 if (!rx_IsLoopbackAddr(afsifinfo[i].ipaddr)) { /* ignore loopback */
1365 *addrp++ = afsifinfo[i].ipaddr;
1370 /* XXXXXX Do the individual ip ranking below XXXXX */
1371 if ((sa->sa_ip & netmask) == net) {
1372 if ((sa->sa_ip & subnetmask) == subnet) {
1373 if (afsifinfo[i].ipaddr == sa->sa_ip) { /* ie, ME! */
1374 sa->sa_iprank = TOPR;
1376 sa->sa_iprank = HI + afsifinfo[i].metric; /* case #2 */
1379 sa->sa_iprank = MED + afsifinfo[i].metric; /* case #3 */
1382 sa->sa_iprank = LO + afsifinfo[i].metric; /* case #4 */
1384 /* check for case #5 -- point-to-point link */
1385 if ((afsifinfo[i].flags & IFF_POINTOPOINT)
1386 && (afsifinfo[i].dstaddr == sa->sa_ip)) {
1388 if (afsifinfo[i].metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1389 sa->sa_iprank = MAXDEFRANK;
1391 sa->sa_iprank = MED + (PPWEIGHT << afsifinfo[i].metric);
1396 rw_exit(&afsifinfo_lock);
1398 for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
1399 ill = ill->ill_next) {
1400 #ifdef AFS_SUN58_ENV
1401 /* Make sure this is an IPv4 ILL */
1405 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
1406 subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1407 subnetmask = ipif->ipif_net_mask;
1409 * Generate the local net using the local address and
1410 * whate we know about Class A, B and C networks.
1412 if (IN_CLASSA(ipif->ipif_local_addr)) {
1413 netmask = IN_CLASSA_NET;
1414 } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1415 netmask = IN_CLASSB_NET;
1416 } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1417 netmask = IN_CLASSC_NET;
1421 net = ipif->ipif_local_addr & netmask;
1424 if (!rx_IsLoopbackAddr(ipif->ipif_local_addr)) { /* ignore loopback */
1428 *addrp++ = ipif->ipif_local_addr;
1433 /* XXXXXX Do the individual ip ranking below XXXXX */
1434 if ((sa->sa_ip & netmask) == net) {
1435 if ((sa->sa_ip & subnetmask) == subnet) {
1436 if (ipif->ipif_local_addr == sa->sa_ip) { /* ie, ME! */
1437 sa->sa_iprank = TOPR;
1439 sa->sa_iprank = HI + ipif->ipif_metric; /* case #2 */
1442 sa->sa_iprank = MED + ipif->ipif_metric; /* case #3 */
1445 sa->sa_iprank = LO + ipif->ipif_metric; /* case #4 */
1447 /* check for case #5 -- point-to-point link */
1448 if ((ipif->ipif_flags & IFF_POINTOPOINT)
1449 && (ipif->ipif_pp_dst_addr == sa->sa_ip)) {
1451 if (ipif->ipif_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1452 sa->sa_iprank = MAXDEFRANK;
1454 sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1459 #endif /* AFS_SUN510_ENV */
1462 rx_ifnet_t ifn = NULL;
1463 struct in_ifaddr *ifad = (struct in_ifaddr *)0;
1464 struct sockaddr_in *sin;
1467 #ifdef notdef /* clean up, remove this */
1468 for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
1469 for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next) {
1470 if ((IFADDR2SA(ifad)->sa_family == AF_INET)
1471 && !(ifn->if_flags & IFF_LOOPBACK)) {
1476 ((struct sockaddr_in *)IFADDR2SA(ifad))->sin_addr.
1485 ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1487 if (ifn) { /* local, more or less */
1489 if (ifn->if_flags & IFF_LOOPBACK) {
1490 sa->sa_iprank = TOPR;
1493 #endif /* IFF_LOOPBACK */
1494 sin = (struct sockaddr_in *)IA_SIN(ifad);
1495 if (SA2ULONG(sin) == sa->sa_ip) {
1496 sa->sa_iprank = TOPR;
1499 #ifdef IFF_BROADCAST
1500 if (ifn->if_flags & IFF_BROADCAST) {
1501 if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1506 #endif /* IFF_BROADCAST */
1507 #ifdef IFF_POINTOPOINT
1508 if (ifn->if_flags & IFF_POINTOPOINT) {
1509 if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1510 if (ifn->if_metric > 4) {
1514 sa->sa_iprank = ifn->if_metric;
1517 #endif /* IFF_POINTOPOINT */
1518 sa->sa_iprank += MED + ifn->if_metric; /* couldn't find anything better */
1520 #else /* USEIFADDR */
1524 #ifdef AFS_SGI62_ENV
1525 (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1526 (caddr_t) sa, NULL);
1527 #elif defined(AFS_DARWIN80_ENV)
1535 if (!ifnet_list_get(AF_INET, &ifns, &count)) {
1536 for (m = 0; m < count; m++) {
1537 if (!ifnet_get_address_list(ifns[m], &ifads)) {
1538 for (j = 0; ifads[j] != NULL && cnt < ADDRSPERSITE; j++) {
1539 afsi_SetServerIPRank(sa, ifads[j]);
1542 ifnet_free_address_list(ifads);
1545 ifnet_list_free(ifns);
1548 #elif defined(AFS_DARWIN_ENV)
1552 TAILQ_FOREACH(ifn, &ifnet, if_link) {
1553 TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
1554 afsi_SetServerIPRank(sa, ifa);
1556 #elif defined(AFS_FBSD_ENV)
1558 struct in_ifaddr *ifa;
1559 TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
1560 afsi_SetServerIPRank(sa, ifa);
1562 #elif defined(AFS_OBSD_ENV)
1564 extern struct in_ifaddrhead in_ifaddr;
1565 struct in_ifaddr *ifa;
1566 for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1567 afsi_SetServerIPRank(sa, ifa);
1569 #elif defined(AFS_NBSD40_ENV)
1571 extern struct in_ifaddrhead in_ifaddrhead;
1572 struct in_ifaddr *ifa;
1573 for (ifa = in_ifaddrhead.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1574 afsi_SetServerIPRank(sa, ifa);
1578 struct in_ifaddr *ifa;
1579 for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
1580 afsi_SetServerIPRank(sa, ifa);
1583 #endif /* USEIFADDR */
1587 #endif /* AFS_SUN5_ENV */
1588 #endif /* else AFS_USERSPACE_IP_ADDR */
1590 sa->sa_iprank += afs_randomMod15();
1593 } /* afs_SetServerPrefs */
1601 /* afs_FlushServer()
1602 * The addresses on this server struct has changed in some way and will
1603 * clean up all other structures that may reference it.
1604 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1607 afs_FlushServer(struct server *srvp)
1610 struct server *ts, **pts;
1612 /* Find any volumes residing on this server and flush their state */
1613 afs_ResetVolumes(srvp);
1615 /* Flush all callbacks in the all vcaches for this specific server */
1616 afs_FlushServerCBs(srvp);
1618 /* Remove all the callbacks structs */
1620 struct afs_cbr *cb, *cbnext;
1622 ObtainWriteLock(&afs_xvcb, 300);
1623 for (cb = srvp->cbrs; cb; cb = cbnext) {
1626 } srvp->cbrs = (struct afs_cbr *)0;
1627 ReleaseWriteLock(&afs_xvcb);
1630 /* If no more srvAddr structs hanging off of this server struct,
1634 /* Remove the server structure from the cell list - if there */
1635 afs_RemoveCellEntry(srvp);
1637 /* Remove from the afs_servers hash chain */
1638 for (i = 0; i < NSERVERS; i++) {
1639 for (pts = &(afs_servers[i]), ts = *pts; ts;
1640 pts = &(ts->next), ts = *pts) {
1648 *pts = ts->next; /* Found it. Remove it */
1649 afs_osi_Free(ts, sizeof(struct server)); /* Free it */
1655 /* afs_RemoveSrvAddr()
1656 * This removes a SrvAddr structure from its server structure.
1657 * The srvAddr struct is not free'd because it connections may still
1658 * be open to it. It is up to the calling process to make sure it
1659 * remains connected to a server struct.
1660 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1661 * It is not removed from the afs_srvAddrs hash chain.
1664 afs_RemoveSrvAddr(struct srvAddr *sap)
1666 struct srvAddr **psa, *sa;
1673 /* Find the srvAddr in the server's list and remove it */
1674 for (psa = &(srv->addr), sa = *psa; sa; psa = &(sa->next_sa), sa = *psa) {
1682 /* Flush the server struct since it's IP address has changed */
1683 afs_FlushServer(srv);
1687 /* afs_GetCapabilities
1688 * Try and retrieve capabilities of a given file server. Carps on actual
1689 * failure. Servers are not expected to support this RPC. */
1691 afs_GetCapabilities(struct server *ts)
1693 Capabilities caps = {0, NULL};
1694 struct vrequest treq;
1695 struct afs_conn *tc;
1696 struct unixuser *tu;
1699 if ( !ts || !ts->cell )
1701 if ( !afs_osi_credp )
1704 if ((code = afs_InitReq(&treq, afs_osi_credp)))
1706 tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
1709 tc = afs_ConnBySA(ts->addr, ts->cell->fsport, ts->cell->cellNum, tu, 0, 1,
1713 /* InitCallBackStateN, triggered by our RPC, may need this */
1714 ReleaseWriteLock(&afs_xserver);
1715 code = RXAFS_GetCapabilities(tc->id, &caps);
1716 ObtainWriteLock(&afs_xserver, 723);
1717 afs_PutConn(tc, SHARED_LOCK);
1718 if ( code && code != RXGEN_OPCODE ) {
1719 afs_warn("RXAFS_GetCapabilities failed with code %d\n", code);
1720 /* better not be anything to free. we failed! */
1724 ts->flags |= SCAPS_KNOWN;
1726 if ( caps.Capabilities_len > 0 ) {
1727 ts->capabilities = caps.Capabilities_val[0];
1728 xdr_free((xdrproc_t)xdr_Capabilities, &caps);
1729 caps.Capabilities_len = 0;
1730 caps.Capabilities_val = NULL;
1736 * Return an updated and properly initialized server structure
1737 * corresponding to the server ID, cell, and port specified.
1738 * If one does not exist, then one will be created.
1739 * aserver and aport must be in NET byte order.
1742 afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers, afs_int32 acell,
1743 u_short aport, afs_int32 locktype, afsUUID * uuidp,
1744 afs_int32 addr_uniquifier)
1746 struct server *oldts = 0, *ts, *newts, *orphts = 0;
1747 struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1749 afs_int32 iphash, k, srvcount = 0;
1750 unsigned int srvhash;
1752 AFS_STATCNT(afs_GetServer);
1754 ObtainSharedLock(&afs_xserver, 13);
1756 /* Check if the server struct exists and is up to date */
1759 panic("afs_GetServer: incorect count of servers");
1760 ObtainReadLock(&afs_xsrvAddr);
1761 ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1762 ReleaseReadLock(&afs_xsrvAddr);
1763 if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1764 /* Found a server struct that is not multihomed and has the
1765 * IP address associated with it. A correct match.
1767 ReleaseSharedLock(&afs_xserver);
1772 panic("afs_GetServer: incorrect count of servers");
1773 ts = afs_FindServer(0, aport, uuidp, locktype);
1774 if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1775 /* Found a server struct that is multihomed and same
1776 * uniqufier (same IP addrs). The above if statement is the
1777 * same as in InstallUVolumeEntry().
1779 ReleaseSharedLock(&afs_xserver);
1783 oldts = ts; /* Will reuse if same uuid */
1786 UpgradeSToWLock(&afs_xserver, 36);
1787 ObtainWriteLock(&afs_xsrvAddr, 116);
1789 srvcount = afs_totalServers;
1791 /* Reuse/allocate a new server structure */
1795 newts = (struct server *)afs_osi_Alloc(sizeof(struct server));
1797 panic("malloc of server struct");
1799 memset(newts, 0, sizeof(struct server));
1801 /* Add the server struct to the afs_servers[] hash chain */
1803 (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
1804 newts->next = afs_servers[srvhash];
1805 afs_servers[srvhash] = newts;
1808 /* Initialize the server structure */
1809 if (uuidp) { /* Multihomed */
1810 newts->sr_uuid = *uuidp;
1811 newts->sr_addr_uniquifier = addr_uniquifier;
1812 newts->flags |= SRVR_MULTIHOMED;
1815 newts->cell = afs_GetCell(acell, 0);
1817 fsport = (newts->cell ? newts->cell->fsport : AFS_FSPORT);
1819 /* For each IP address we are registering */
1820 for (k = 0; k < nservers; k++) {
1821 iphash = SHash(aserverp[k]);
1823 /* Check if the srvAddr structure already exists. If so, remove
1824 * it from its server structure and add it to the new one.
1826 for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
1827 if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
1830 if (oldsa && (oldsa->server != newts)) {
1831 afs_RemoveSrvAddr(oldsa); /* Remove from its server struct */
1832 oldsa->next_sa = newts->addr; /* Add to the new server struct */
1833 newts->addr = oldsa;
1836 /* Reuse/allocate a new srvAddr structure */
1840 newsa = (struct srvAddr *)afs_osi_Alloc(sizeof(struct srvAddr));
1842 panic("malloc of srvAddr struct");
1843 afs_totalSrvAddrs++;
1844 memset(newsa, 0, sizeof(struct srvAddr));
1846 /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1847 newsa->next_bkt = afs_srvAddrs[iphash];
1848 afs_srvAddrs[iphash] = newsa;
1850 /* Hang off of the server structure */
1851 newsa->next_sa = newts->addr;
1852 newts->addr = newsa;
1854 /* Initialize the srvAddr Structure */
1855 newsa->sa_ip = aserverp[k];
1856 newsa->sa_portal = aport;
1859 /* Update the srvAddr Structure */
1860 newsa->server = newts;
1861 if (newts->flags & SRVR_ISDOWN)
1862 newsa->sa_flags |= SRVADDR_ISDOWN;
1864 newsa->sa_flags |= SRVADDR_MH;
1866 newsa->sa_flags &= ~SRVADDR_MH;
1868 /* Compute preference values and resort */
1869 if (!newsa->sa_iprank) {
1870 afs_SetServerPrefs(newsa); /* new server rank */
1873 afs_SortOneServer(newts); /* Sort by rank */
1875 /* If we reused the server struct, remove any of its srvAddr
1876 * structs that will no longer be associated with this server.
1878 if (oldts) { /* reused the server struct */
1879 for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
1880 nextsa = orphsa->next_sa;
1881 for (k = 0; k < nservers; k++) {
1882 if (orphsa->sa_ip == aserverp[k])
1883 break; /* belongs */
1886 continue; /* belongs */
1888 /* Have a srvAddr struct. Now get a server struct (if not already) */
1891 (struct server *)afs_osi_Alloc(sizeof(struct server));
1893 panic("malloc of lo server struct");
1894 memset(orphts, 0, sizeof(struct server));
1897 /* Add the orphaned server to the afs_servers[] hash chain.
1898 * Its iphash does not matter since we never look up the server
1899 * in the afs_servers table by its ip address (only by uuid -
1900 * which this has none).
1902 iphash = SHash(aserverp[k]);
1903 orphts->next = afs_servers[iphash];
1904 afs_servers[iphash] = orphts;
1907 orphts->cell = afs_GetCell(acell, 0);
1910 /* Hang the srvAddr struct off of the server structure. The server
1911 * may have multiple srvAddrs, but it won't be marked multihomed.
1913 afs_RemoveSrvAddr(orphsa); /* remove */
1914 orphsa->next_sa = orphts->addr; /* hang off server struct */
1915 orphts->addr = orphsa;
1916 orphsa->server = orphts;
1917 orphsa->sa_flags |= SRVADDR_NOUSE; /* flag indicating not in use */
1918 orphsa->sa_flags &= ~SRVADDR_MH; /* Not multihomed */
1922 srvcount = afs_totalServers - srvcount; /* # servers added and removed */
1924 struct afs_stats_SrvUpDownInfo *upDownP;
1925 /* With the introduction of this new record, we need to adjust the
1926 * proper individual & global server up/down info.
1928 upDownP = GetUpDownStats(newts);
1929 upDownP->numTtlRecords += srvcount;
1930 afs_stats_cmperf.srvRecords += srvcount;
1931 if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
1932 afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
1935 ReleaseWriteLock(&afs_xsrvAddr);
1937 if ( aport == AFS_FSPORT && !(newts->flags & SCAPS_KNOWN))
1938 afs_GetCapabilities(newts);
1940 ReleaseWriteLock(&afs_xserver);
1942 } /* afs_GetServer */
1945 afs_ActivateServer(struct srvAddr *sap)
1947 osi_timeval_t currTime; /*Filled with current time */
1948 osi_timeval_t *currTimeP; /*Ptr to above */
1949 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record */
1950 struct server *aserver = sap->server;
1952 if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
1954 * This server record has not yet been activated. Go for it,
1955 * recording its ``birth''.
1957 aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
1958 currTimeP = &currTime;
1959 osi_GetuTime(currTimeP);
1960 aserver->activationTime = currTime.tv_sec;
1961 upDownP = GetUpDownStats(aserver);
1962 if (aserver->flags & SRVR_ISDOWN) {
1963 upDownP->numDownRecords++;
1965 upDownP->numUpRecords++;
1966 upDownP->numRecordsNeverDown++;
1972 afs_RemoveAllConns(void)
1975 struct server *ts, *nts;
1977 struct afs_conn *tc, *ntc;
1979 ObtainReadLock(&afs_xserver);
1980 ObtainWriteLock(&afs_xconn, 1001);
1982 /*printf("Destroying connections ... ");*/
1983 for (i = 0; i < NSERVERS; i++) {
1984 for (ts = afs_servers[i]; ts; ts = nts) {
1986 for (sa = ts->addr; sa; sa = sa->next_sa) {
1992 rx_DestroyConnection(tc->id);
1994 afs_osi_Free(tc, sizeof(struct afs_conn));
2002 /*printf("done\n");*/
2004 ReleaseWriteLock(&afs_xconn);
2005 ReleaseReadLock(&afs_xserver);
2010 afs_MarkAllServersUp(void)
2016 ObtainWriteLock(&afs_xserver, 721);
2017 ObtainWriteLock(&afs_xsrvAddr, 722);
2018 for (i = 0; i< NSERVERS; i++) {
2019 for (ts = afs_servers[i]; ts; ts = ts->next) {
2020 for (sa = ts->addr; sa; sa = sa->next_sa) {
2021 afs_MarkServerUpOrDown(sa, 0);
2025 ReleaseWriteLock(&afs_xsrvAddr);
2026 ReleaseWriteLock(&afs_xserver);