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_DARWIN60_ENV)
49 #include <netinet/in_var.h>
50 #endif /* AFS_HPUX110_ENV */
51 #ifdef AFS_DARWIN60_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 register struct server *a_serverP = sa->server;
134 register struct srvAddr *sap;
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 register 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)
263 register afs_int32 now;
265 register struct vcache *tvc;
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(register struct srvAddr *sa, struct vrequest *areq)
288 register struct server *aserver = sa->server;
289 register struct afs_conn *tc;
290 register afs_int32 code;
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((char *)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((char *)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((char *)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((char *)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()
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;
546 AFS_STATCNT(afs_CheckServers);
549 * No sense in doing the server checks if we are running in disconnected
552 if (AFS_IS_DISCONNECTED)
555 conns = (struct afs_conn **)0;
556 rxconns = (struct rx_connection **) 0;
560 if ((code = afs_InitReq(&treq, afs_osi_credp)))
562 ObtainReadLock(&afs_xserver); /* Necessary? */
563 ObtainReadLock(&afs_xsrvAddr);
566 for (i = 0; i < NSERVERS; i++) {
567 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
572 addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
574 for (i = 0; i < NSERVERS; i++) {
575 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
576 if (j >= srvAddrCount)
582 ReleaseReadLock(&afs_xsrvAddr);
583 ReleaseReadLock(&afs_xserver);
585 conns = (struct afs_conn **)afs_osi_Alloc(j * sizeof(struct afs_conn *));
586 rxconns = (struct rx_connection **)afs_osi_Alloc(j * sizeof(struct rx_connection *));
587 conntimer = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
588 deltas = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
589 results = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
591 for (i = 0; i < j; i++) {
598 /* See if a cell to check was specified. If it is spec'd and not
599 * this server's cell, just skip the server.
601 if (acellp && acellp != ts->cell)
604 if ((!adown && (sa->sa_flags & SRVADDR_ISDOWN))
605 || (adown && !(sa->sa_flags & SRVADDR_ISDOWN)))
608 /* check vlserver with special code */
609 if (sa->sa_portal == AFS_VLPORT) {
610 CheckVLServer(sa, &treq);
614 if (!ts->cell) /* not really an active server, anyway, it must */
615 continue; /* have just been added by setsprefs */
617 /* get a connection, even if host is down; bumps conn ref count */
618 tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
619 tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
620 1 /*force */ , 1 /*create */ , SHARED_LOCK);
621 afs_PutUser(tu, SHARED_LOCK);
625 if ((sa->sa_flags & SRVADDR_ISDOWN) || afs_HaveCallBacksFrom(sa->server)
626 || (tc->srvr->server == afs_setTimeHost)) {
628 rxconns[nconns]=tc->id;
629 if (sa->sa_flags & SRVADDR_ISDOWN) {
630 rx_SetConnDeadTime(tc->id, 3);
637 } /* Outer loop over addrs */
639 start = osi_Time(); /* time the gettimeofday call */
641 multi_Rx(rxconns,nconns)
643 tv.tv_sec = tv.tv_usec = 0;
644 multi_RXAFS_GetTime((afs_uint32 *)&tv.tv_sec, (afs_uint32 *)&tv.tv_usec);
647 if (conntimer[multi_i] == 1)
648 rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
650 results[multi_i]=multi_error;
651 if ((start == end) && !multi_error)
652 deltas[multi_i] = end - tv.tv_sec;
657 for(i=0;i<nconns;i++){
661 if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) && (tc->srvr == sa)) {
663 print_internet_address("afs: file server ", sa, " is back up", 2);
665 ObtainWriteLock(&afs_xserver, 244);
666 ObtainWriteLock(&afs_xsrvAddr, 245);
667 afs_MarkServerUpOrDown(sa, 0);
668 ReleaseWriteLock(&afs_xsrvAddr);
669 ReleaseWriteLock(&afs_xserver);
671 if (afs_waitForeverCount) {
672 afs_osi_Wakeup(&afs_waitForever);
675 if (results[i] < 0) {
678 ForceNewConnections(sa); /* multi homed clients */
684 * If we're supposed to set the time, and the call worked
685 * quickly (same second response) and this is the host we
686 * use for the time and the time is really different, then
687 * really set the time
689 if (afs_setTime != 0) {
690 for (i=0; i<nconns; i++) {
695 if ((tc->srvr->server == afs_setTimeHost ||
696 /* Sync only to a server in the local cell */
697 (afs_setTimeHost == (struct server *)0 &&
698 afs_IsPrimaryCell(sa->server->cell)))) {
700 char msgbuf[90]; /* strlen("afs: setting clock...") + slop */
701 delta = end - tv.tv_sec; /* how many secs fast we are */
703 afs_setTimeHost = tc->srvr->server;
704 /* see if clock has changed enough to make it worthwhile */
705 if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) {
707 if (delta > AFS_MAXCHANGEBACK) {
708 /* setting clock too far back, just do it a little */
709 tv.tv_sec = end - AFS_MAXCHANGEBACK;
711 tv.tv_sec = end - delta;
713 afs_osi_SetTime(&tv);
715 strcpy(msgbuf, "afs: setting clock back ");
716 if (delta > AFS_MAXCHANGEBACK) {
718 afs_cv2string(&tbuffer[CVBS],
720 afs_strcat(msgbuf, " seconds (of ");
722 afs_cv2string(&tbuffer[CVBS],
725 afs_strcat(msgbuf, ", via ");
726 print_internet_address(msgbuf, sa,
727 "); clock is still fast.",
731 afs_cv2string(&tbuffer[CVBS], delta));
732 afs_strcat(msgbuf, " seconds (via ");
733 print_internet_address(msgbuf, sa, ").", 0);
736 strcpy(msgbuf, "afs: setting clock ahead ");
738 afs_cv2string(&tbuffer[CVBS], -delta));
739 afs_strcat(msgbuf, " seconds (via ");
740 print_internet_address(msgbuf, sa, ").", 0);
742 /* We're only going to set it once; why bother looping? */
748 for (i = 0; i < nconns; i++) {
749 afs_PutConn(conns[i], SHARED_LOCK); /* done with it now */
752 afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
753 afs_osi_Free(conns, j * sizeof(struct afs_conn *));
754 afs_osi_Free(rxconns, j * sizeof(struct rx_connection *));
755 afs_osi_Free(conntimer, j * sizeof(afs_int32));
756 afs_osi_Free(deltas, j * sizeof(afs_int32));
757 afs_osi_Free(results, j * sizeof(afs_int32));
759 } /*afs_CheckServers*/
762 /* find a server structure given the host address */
764 afs_FindServer(afs_int32 aserver, afs_uint16 aport, afsUUID * uuidp,
771 AFS_STATCNT(afs_FindServer);
773 i = afs_uuid_hash(uuidp) % NSERVERS;
774 for (ts = afs_servers[i]; ts; ts = ts->next) {
775 if ((ts->flags & SRVR_MULTIHOMED)
777 (memcmp((char *)uuidp, (char *)&ts->sr_uuid, sizeof(*uuidp))
778 == 0) && (!ts->addr || (ts->addr->sa_portal == aport)))
783 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
784 if ((sa->sa_ip == aserver) && (sa->sa_portal == aport)) {
791 } /*afs_FindServer */
794 /* some code for creating new server structs and setting preferences follows
795 * in the next few lines...
798 #define MAXDEFRANK 60000
799 #define DEFRANK 40000
801 /* Random number generator and constants from KnuthV2 2d ed, p170 */
807 a is 0.73m should be 0.01m .. 0.99m
808 c is more or less immaterial. 1 or a is suggested.
810 NB: LOW ORDER BITS are not very random. To get small random numbers,
811 treat result as <1, with implied binary point, and multiply by
813 NB: Has to be unsigned, since shifts on signed quantities may preserve
816 /* added rxi_getaddr() to try to get as much initial randomness as
817 possible, since at least one customer reboots ALL their clients
818 simultaneously -- so osi_Time is bound to be the same on some of the
819 clients. This is probably OK, but I don't want to see too much of it.
822 #define ranstage(x) (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
827 static afs_int32 state = 0;
830 AFS_STATCNT(afs_random);
835 * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
836 * bits are in a tv_usec
838 state = (t.tv_usec & (~0 << 4)) + (rxi_getaddr() & 0xff);
839 state += (t.tv_sec & 0xff);
840 for (i = 0; i < 30; i++) {
850 /* returns int 0..14 using the high bits of a pseudo-random number instead of
851 the low bits, as the low bits are "less random" than the high ones...
852 slight roundoff error exists, an excercise for the reader.
853 need to multiply by something with lots of ones in it, so multiply by
854 8 or 16 is right out.
857 afs_randomMod15(void)
861 temp = afs_random() >> 4;
862 temp = (temp * 15) >> 28;
868 afs_randomMod127(void)
872 temp = afs_random() >> 7;
873 temp = (temp * 127) >> 25;
878 /* afs_SortOneServer()
879 * Sort all of the srvAddrs, of a server struct, by rank from low to high.
882 afs_SortOneServer(struct server *asp)
884 struct srvAddr **rootsa, *lowsa, *tsa, *lowprev;
887 for (rootsa = &(asp->addr); *rootsa; rootsa = &(lowsa->next_sa)) {
889 lowsa = *rootsa; /* lowest sa is the first one */
890 lowrank = lowsa->sa_iprank;
892 for (tsa = *rootsa; tsa->next_sa; tsa = tsa->next_sa) {
893 rank = tsa->next_sa->sa_iprank;
894 if (rank < lowrank) {
896 lowsa = tsa->next_sa;
897 lowrank = lowsa->sa_iprank;
900 if (lowprev) { /* found one lower, so rearrange them */
901 lowprev->next_sa = lowsa->next_sa;
902 lowsa->next_sa = *rootsa;
909 * Sort the pointer to servers by the server's rank (its lowest rank).
910 * It is assumed that the server already has its IP addrs sorted (the
911 * first being its lowest rank: afs_GetServer() calls afs_SortOneServer()).
914 afs_SortServers(struct server *aservers[], int count)
919 AFS_STATCNT(afs_SortServers);
921 for (i = 0; i < count; i++) {
924 for (low = i, j = i + 1; j <= count; j++) {
925 if ((!aservers[j]) || (!aservers[j]->addr))
927 if ((!aservers[low]) || (!aservers[low]->addr))
929 if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
935 aservers[i] = aservers[low];
939 } /*afs_SortServers */
941 /* afs_SetServerPrefs is rather system-dependent. It pokes around in kernel
942 data structures to determine what the local IP addresses and subnet masks
943 are in order to choose which server(s) are on the local subnet.
945 As I see it, there are several cases:
946 1. The server address is one of this host's local addresses. In this case
947 this server is to be preferred over all others.
948 2. The server is on the same subnet as one of the this host's local
949 addresses. (ie, an odd-sized subnet, not class A,B,orC)
950 3. The server is on the same net as this host (class A,B or C)
951 4. The server is on a different logical subnet or net than this host, but
952 this host is a 'metric 0 gateway' to it. Ie, two address-spaces share
954 5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
956 6. This host and the server are disjoint.
958 That is a rough order of preference. If a point-to-point link has a high
959 metric, I'm assuming that it is a very slow link, and putting it at the
960 bottom of the list (at least until RX works better over slow links). If
961 its metric is 1, I'm assuming that it's relatively fast (T1) and putting
963 It's not easy to check for case #4, so I'm ignoring it for the time being.
965 BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
966 That could be used to prefer certain servers fairly easily. Maybe some
969 NOTE: this code is very system-dependent, and very dependent on the TCP/IP
970 protocols (well, addresses that are stored in uint32s, at any rate).
973 #define IA_DST(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_dstaddr))
974 #define IA_BROAD(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
976 /* SA2ULONG takes a sockaddr_in, not a sockaddr (same thing, just cast it!) */
977 #define SA2ULONG(sa) ((sa)->sin_addr.s_addr)
982 #define PPWEIGHT 4096
987 #if defined(AFS_SUN5_ENV) && ! defined(AFS_SUN56_ENV)
988 #include <inet/common.h>
989 /* IP interface structure, one per local address */
990 typedef struct ipif_s {
991 /**/ struct ipif_s *ipif_next;
992 struct ill_s *ipif_ill; /* Back pointer to our ill */
993 long ipif_id; /* Logical unit number */
994 u_int ipif_mtu; /* Starts at ipif_ill->ill_max_frag */
995 afs_int32 ipif_local_addr; /* Local IP address for this if. */
996 afs_int32 ipif_net_mask; /* Net mask for this interface. */
997 afs_int32 ipif_broadcast_addr; /* Broadcast addr for this interface. */
998 afs_int32 ipif_pp_dst_addr; /* Point-to-point dest address. */
999 u_int ipif_flags; /* Interface flags. */
1000 u_int ipif_metric; /* BSD if metric, for compatibility. */
1001 u_int ipif_ire_type; /* LOCAL or LOOPBACK */
1002 mblk_t *ipif_arp_down_mp; /* Allocated at time arp comes up to
1003 * prevent awkward out of mem condition
1006 mblk_t *ipif_saved_ire_mp; /* Allocated for each extra IRE_SUBNET/
1007 * RESOLVER on this interface so that
1008 * they can survive ifconfig down.
1011 * The packet counts in the ipif contain the sum of the
1012 * packet counts in dead IREs that were affiliated with
1015 u_long ipif_fo_pkt_count; /* Forwarded thru our dead IREs */
1016 u_long ipif_ib_pkt_count; /* Inbound packets for our dead IREs */
1017 u_long ipif_ob_pkt_count; /* Outbound packets to our dead IREs */
1019 ipif_multicast_up:1, /* We have joined the allhosts group */
1023 typedef struct ipfb_s {
1024 /**/ struct ipf_s *ipfb_ipf; /* List of ... */
1025 kmutex_t ipfb_lock; /* Protect all ipf in list */
1028 typedef struct ilm_s {
1029 /**/ afs_int32 ilm_addr;
1031 u_int ilm_timer; /* IGMP */
1032 struct ipif_s *ilm_ipif; /* Back pointer to ipif */
1033 struct ilm_s *ilm_next; /* Linked list for each ill */
1036 typedef struct ill_s {
1037 /**/ struct ill_s *ill_next; /* Chained in at ill_g_head. */
1038 struct ill_s **ill_ptpn; /* Pointer to previous next. */
1039 queue_t *ill_rq; /* Read queue. */
1040 queue_t *ill_wq; /* Write queue. */
1042 int ill_error; /* Error value sent up by device. */
1044 ipif_t *ill_ipif; /* Interface chain for this ILL. */
1045 u_int ill_ipif_up_count; /* Number of IPIFs currently up. */
1046 u_int ill_max_frag; /* Max IDU. */
1047 char *ill_name; /* Our name. */
1048 u_int ill_name_length; /* Name length, incl. terminator. */
1049 u_int ill_subnet_type; /* IRE_RESOLVER or IRE_SUBNET. */
1050 u_int ill_ppa; /* Physical Point of Attachment num. */
1052 int ill_sap_length; /* Including sign (for position) */
1053 u_int ill_phys_addr_length; /* Excluding the sap. */
1054 mblk_t *ill_frag_timer_mp; /* Reassembly timer state. */
1055 ipfb_t *ill_frag_hash_tbl; /* Fragment hash list head. */
1057 queue_t *ill_bind_pending_q; /* Queue waiting for DL_BIND_ACK. */
1058 ipif_t *ill_ipif_pending; /* IPIF waiting for DL_BIND_ACK. */
1060 /* ill_hdr_length and ill_hdr_mp will be non zero if
1061 * the underlying device supports the M_DATA fastpath
1065 ilm_t *ill_ilm; /* Multicast mebership for lower ill */
1067 /* All non-nil cells between 'ill_first_mp_to_free' and
1068 * 'ill_last_mp_to_free' are freed in ill_delete.
1070 #define ill_first_mp_to_free ill_hdr_mp
1071 mblk_t *ill_hdr_mp; /* Contains fastpath template */
1072 mblk_t *ill_bcast_mp; /* DLPI header for broadcasts. */
1073 mblk_t *ill_bind_pending; /* T_BIND_REQ awaiting completion. */
1074 mblk_t *ill_resolver_mp; /* Resolver template. */
1075 mblk_t *ill_attach_mp;
1076 mblk_t *ill_bind_mp;
1077 mblk_t *ill_unbind_mp;
1078 mblk_t *ill_detach_mp;
1079 #define ill_last_mp_to_free ill_detach_mp
1081 u_int ill_frag_timer_running:1, ill_needs_attach:1, ill_is_ptp:1,
1082 ill_priv_stream:1, ill_unbind_pending:1, ill_pad_to_bit_31:27;
1083 MI_HRT_DCL(ill_rtime)
1084 MI_HRT_DCL(ill_rtmp)
1088 #ifdef AFS_USERSPACE_IP_ADDR
1090 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1093 * The IP addresses and ranks are determined by afsd (in user space) and
1094 * passed into the kernel at startup time through the AFSOP_ADVISEADDR
1095 * system call. These are stored in the data structure
1096 * called 'afs_cb_interface'.
1098 * struct srvAddr *sa; remote server
1099 * afs_int32 addr; one of my local addr in net order
1100 * afs_uint32 subnetmask; subnet mask of local addr in net order
1104 afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr,
1105 afs_uint32 subnetmask)
1107 afs_uint32 myAddr, myNet, mySubnet, netMask;
1108 afs_uint32 serverAddr;
1110 myAddr = ntohl(addr); /* one of my IP addr in host order */
1111 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1112 subnetmask = ntohl(subnetmask); /* subnet mask in host order */
1114 if (IN_CLASSA(myAddr))
1115 netMask = IN_CLASSA_NET;
1116 else if (IN_CLASSB(myAddr))
1117 netMask = IN_CLASSB_NET;
1118 else if (IN_CLASSC(myAddr))
1119 netMask = IN_CLASSC_NET;
1123 myNet = myAddr & netMask;
1124 mySubnet = myAddr & subnetmask;
1126 if ((serverAddr & netMask) == myNet) {
1127 if ((serverAddr & subnetmask) == mySubnet) {
1128 if (serverAddr == myAddr) { /* same machine */
1129 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1130 } else { /* same subnet */
1131 sa->sa_iprank = afs_min(sa->sa_iprank, HI);
1133 } else { /* same net */
1134 sa->sa_iprank = afs_min(sa->sa_iprank, MED);
1139 #else /* AFS_USERSPACE_IP_ADDR */
1140 #if (! defined(AFS_SUN5_ENV)) && !defined(AFS_DARWIN60_ENV) && defined(USEIFADDR)
1142 afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
1144 struct sockaddr_in *sin;
1147 if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
1148 if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
1150 if (SA2ULONG(sin) == ntohl(sa->sa_ip)) { /* ie, ME!!! */
1151 sa->sa_iprank = TOPR;
1153 t = HI + ifa->ia_ifp->if_metric; /* case #2 */
1154 if (sa->sa_iprank > t)
1158 t = MED + ifa->ia_ifp->if_metric; /* case #3 */
1159 if (sa->sa_iprank > t)
1163 #ifdef IFF_POINTTOPOINT
1164 /* check for case #4 -- point-to-point link */
1165 if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
1166 && (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
1167 if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1170 t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
1171 if (sa->sa_iprank > t)
1174 #endif /* IFF_POINTTOPOINT */
1176 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1177 #if defined(AFS_DARWIN60_ENV) && defined(USEIFADDR)
1179 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1182 afsi_SetServerIPRank(sa, ifa)
1184 #ifdef AFS_DARWIN80_ENV
1190 struct sockaddr sout;
1191 struct sockaddr_in *sin;
1194 afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
1195 afs_uint32 serverAddr;
1197 if (ifaddr_address_family(ifa) != AF_INET)
1199 t = ifaddr_address(ifa, &sout, sizeof(sout));
1201 sin = (struct sockaddr_in *)&sout;
1202 myAddr = ntohl(sin->sin_addr.s_addr); /* one of my IP addr in host order */
1206 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1207 t = ifaddr_netmask(ifa, &sout, sizeof(sout));
1209 sin = (struct sockaddr_in *)&sout;
1210 subnetmask = ntohl(sin->sin_addr.s_addr); /* subnet mask in host order */
1214 t = ifaddr_dstaddress(ifa, &sout, sizeof(sout));
1216 sin = (struct sockaddr_in *)&sout;
1217 myDstaddr = sin->sin_addr.s_addr;
1222 if (IN_CLASSA(myAddr))
1223 netMask = IN_CLASSA_NET;
1224 else if (IN_CLASSB(myAddr))
1225 netMask = IN_CLASSB_NET;
1226 else if (IN_CLASSC(myAddr))
1227 netMask = IN_CLASSC_NET;
1231 myNet = myAddr & netMask;
1232 mySubnet = myAddr & subnetmask;
1234 if ((serverAddr & netMask) == myNet) {
1235 if ((serverAddr & subnetmask) == mySubnet) {
1236 if (serverAddr == myAddr) { /* same machine */
1237 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1238 } else { /* same subnet */
1239 sa->sa_iprank = afs_min(sa->sa_iprank, HI + ifnet_metric(ifaddr_ifnet(ifa)));
1241 } else { /* same net */
1242 sa->sa_iprank = afs_min(sa->sa_iprank, MED + ifnet_metric(ifaddr_ifnet(ifa)));
1245 #ifdef IFF_POINTTOPOINT
1246 /* check for case #4 -- point-to-point link */
1247 if ((ifnet_flags(ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
1248 && (myDstaddr == serverAddr)) {
1249 if (ifnet_metric(ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
1252 t = MED + (PPWEIGHT << ifnet_metric(ifaddr_ifnet(ifa)));
1253 if (sa->sa_iprank > t)
1256 #endif /* IFF_POINTTOPOINT */
1258 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1259 #endif /* else AFS_USERSPACE_IP_ADDR */
1261 #ifdef AFS_SGI62_ENV
1264 afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1266 afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
1267 return 0; /* Never match, so we enumerate everyone */
1269 #endif /* AFS_SGI62_ENV */
1270 static int afs_SetServerPrefs(struct srvAddr *sa) {
1271 #if defined(AFS_USERSPACE_IP_ADDR)
1275 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1276 afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1277 afs_cb_interface.subnetmask[i]);
1279 #else /* AFS_USERSPACE_IP_ADDR */
1280 #if defined(AFS_SUN5_ENV)
1281 #ifdef AFS_SUN510_ENV
1284 extern struct ill_s *ill_g_headp;
1285 long *addr = (long *)ill_g_headp;
1289 int subnet, subnetmask, net, netmask;
1293 #ifdef AFS_SUN510_ENV
1294 rw_enter(&afsifinfo_lock, RW_READER);
1296 for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
1298 if (IN_CLASSA(afsifinfo[i].ipaddr)) {
1299 netmask = IN_CLASSA_NET;
1300 } else if (IN_CLASSB(afsifinfo[i].ipaddr)) {
1301 netmask = IN_CLASSB_NET;
1302 } else if (IN_CLASSC(afsifinfo[i].ipaddr)) {
1303 netmask = IN_CLASSC_NET;
1307 net = afsifinfo[i].ipaddr & netmask;
1311 if (afsifinfo[i].ipaddr != 0x7f000001) { /* ignore loopback */
1315 *addrp++ = afsifinfo[i].ipaddr;
1320 /* XXXXXX Do the individual ip ranking below XXXXX */
1321 if ((sa->sa_ip & netmask) == net) {
1322 if ((sa->sa_ip & subnetmask) == subnet) {
1323 if (afsifinfo[i].ipaddr == sa->sa_ip) { /* ie, ME! */
1324 sa->sa_iprank = TOPR;
1326 sa->sa_iprank = HI + afsifinfo[i].metric; /* case #2 */
1329 sa->sa_iprank = MED + afsifinfo[i].metric; /* case #3 */
1332 sa->sa_iprank = LO + afsifinfo[i].metric; /* case #4 */
1334 /* check for case #5 -- point-to-point link */
1335 if ((afsifinfo[i].flags & IFF_POINTOPOINT)
1336 && (afsifinfo[i].dstaddr == sa->sa_ip)) {
1338 if (afsifinfo[i].metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1339 sa->sa_iprank = MAXDEFRANK;
1341 sa->sa_iprank = MED + (PPWEIGHT << afsifinfo[i].metric);
1346 rw_exit(&afsifinfo_lock);
1348 for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
1349 ill = ill->ill_next) {
1350 #ifdef AFS_SUN58_ENV
1351 /* Make sure this is an IPv4 ILL */
1355 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
1356 subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1357 subnetmask = ipif->ipif_net_mask;
1359 * Generate the local net using the local address and
1360 * whate we know about Class A, B and C networks.
1362 if (IN_CLASSA(ipif->ipif_local_addr)) {
1363 netmask = IN_CLASSA_NET;
1364 } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1365 netmask = IN_CLASSB_NET;
1366 } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1367 netmask = IN_CLASSC_NET;
1371 net = ipif->ipif_local_addr & netmask;
1374 if (ipif->ipif_local_addr != 0x7f000001) { /* ignore loopback */
1378 *addrp++ = ipif->ipif_local_addr;
1383 /* XXXXXX Do the individual ip ranking below XXXXX */
1384 if ((sa->sa_ip & netmask) == net) {
1385 if ((sa->sa_ip & subnetmask) == subnet) {
1386 if (ipif->ipif_local_addr == sa->sa_ip) { /* ie, ME! */
1387 sa->sa_iprank = TOPR;
1389 sa->sa_iprank = HI + ipif->ipif_metric; /* case #2 */
1392 sa->sa_iprank = MED + ipif->ipif_metric; /* case #3 */
1395 sa->sa_iprank = LO + ipif->ipif_metric; /* case #4 */
1397 /* check for case #5 -- point-to-point link */
1398 if ((ipif->ipif_flags & IFF_POINTOPOINT)
1399 && (ipif->ipif_pp_dst_addr == sa->sa_ip)) {
1401 if (ipif->ipif_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1402 sa->sa_iprank = MAXDEFRANK;
1404 sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1409 #endif /* AFS_SUN510_ENV */
1412 struct ifnet *ifn = NULL;
1413 struct in_ifaddr *ifad = (struct in_ifaddr *)0;
1414 struct sockaddr_in *sin;
1417 #ifdef notdef /* clean up, remove this */
1418 for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
1419 for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next) {
1420 if ((IFADDR2SA(ifad)->sa_family == AF_INET)
1421 && !(ifn->if_flags & IFF_LOOPBACK)) {
1426 ((struct sockaddr_in *)IFADDR2SA(ifad))->sin_addr.
1435 ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1437 if (ifn) { /* local, more or less */
1439 if (ifn->if_flags & IFF_LOOPBACK) {
1440 sa->sa_iprank = TOPR;
1443 #endif /* IFF_LOOPBACK */
1444 sin = (struct sockaddr_in *)IA_SIN(ifad);
1445 if (SA2ULONG(sin) == sa->sa_ip) {
1446 sa->sa_iprank = TOPR;
1449 #ifdef IFF_BROADCAST
1450 if (ifn->if_flags & IFF_BROADCAST) {
1451 if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1456 #endif /* IFF_BROADCAST */
1457 #ifdef IFF_POINTOPOINT
1458 if (ifn->if_flags & IFF_POINTOPOINT) {
1459 if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1460 if (ifn->if_metric > 4) {
1464 sa->sa_iprank = ifn->if_metric;
1467 #endif /* IFF_POINTOPOINT */
1468 sa->sa_iprank += MED + ifn->if_metric; /* couldn't find anything better */
1470 #else /* USEIFADDR */
1474 #ifdef AFS_SGI62_ENV
1475 (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1476 (caddr_t) sa, NULL);
1477 #elif defined(AFS_DARWIN80_ENV)
1485 if (!ifnet_list_get(AF_INET, &ifn, &count)) {
1486 for (m = 0; m < count; m++) {
1487 if (!ifnet_get_address_list(ifn[m], &ifads)) {
1488 for (j = 0; ifads[j] != NULL && cnt < ADDRSPERSITE; j++) {
1489 afsi_SetServerIPRank(sa, ifads[j]);
1492 ifnet_free_address_list(ifads);
1495 ifnet_list_free(ifn);
1498 #elif defined(AFS_DARWIN60_ENV)
1502 TAILQ_FOREACH(ifn, &ifnet, if_link) {
1503 TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
1504 afsi_SetServerIPRank(sa, ifa);
1506 #elif defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1508 struct in_ifaddr *ifa;
1509 TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
1510 afsi_SetServerIPRank(sa, ifa);
1512 #elif defined(AFS_OBSD_ENV)
1514 extern struct in_ifaddrhead in_ifaddr;
1515 struct in_ifaddr *ifa;
1516 for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1517 afsi_SetServerIPRank(sa, ifa);
1521 struct in_ifaddr *ifa;
1522 for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
1523 afsi_SetServerIPRank(sa, ifa);
1527 #endif /* USEIFADDR */
1528 #endif /* AFS_SUN5_ENV */
1529 #endif /* else AFS_USERSPACE_IP_ADDR */
1531 sa->sa_iprank += afs_randomMod15();
1534 } /* afs_SetServerPrefs */
1542 /* afs_FlushServer()
1543 * The addresses on this server struct has changed in some way and will
1544 * clean up all other structures that may reference it.
1545 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1547 void afs_FlushServer(struct server *srvp) {
1549 struct server *ts, **pts;
1551 /* Find any volumes residing on this server and flush their state */
1552 afs_ResetVolumes(srvp);
1554 /* Flush all callbacks in the all vcaches for this specific server */
1555 afs_FlushServerCBs(srvp);
1557 /* Remove all the callbacks structs */
1559 struct afs_cbr *cb, *cbnext;
1561 MObtainWriteLock(&afs_xvcb, 300);
1562 for (cb = srvp->cbrs; cb; cb = cbnext) {
1565 } srvp->cbrs = (struct afs_cbr *)0;
1566 ReleaseWriteLock(&afs_xvcb);
1569 /* If no more srvAddr structs hanging off of this server struct,
1573 /* Remove the server structure from the cell list - if there */
1574 afs_RemoveCellEntry(srvp);
1576 /* Remove from the afs_servers hash chain */
1577 for (i = 0; i < NSERVERS; i++) {
1578 for (pts = &(afs_servers[i]), ts = *pts; ts;
1579 pts = &(ts->next), ts = *pts) {
1587 *pts = ts->next; /* Found it. Remove it */
1588 afs_osi_Free(ts, sizeof(struct server)); /* Free it */
1594 /* afs_RemoveSrvAddr()
1595 * This removes a SrvAddr structure from its server structure.
1596 * The srvAddr struct is not free'd because it connections may still
1597 * be open to it. It is up to the calling process to make sure it
1598 * remains connected to a server struct.
1599 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1600 * It is not removed from the afs_srvAddrs hash chain.
1602 void afs_RemoveSrvAddr(struct srvAddr *sap) {
1603 struct srvAddr **psa, *sa;
1610 /* Find the srvAddr in the server's list and remove it */
1611 for (psa = &(srv->addr), sa = *psa; sa; psa = &(sa->next_sa), sa = *psa) {
1619 /* Flush the server struct since it's IP address has changed */
1620 afs_FlushServer(srv);
1625 * Return an updated and properly initialized server structure
1626 * corresponding to the server ID, cell, and port specified.
1627 * If one does not exist, then one will be created.
1628 * aserver and aport must be in NET byte order.
1630 struct server *afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers,
1631 afs_int32 acell, u_short aport,
1632 afs_int32 locktype, afsUUID * uuidp,
1633 afs_int32 addr_uniquifier) {
1634 struct server *oldts = 0, *ts, *newts, *orphts = 0;
1635 struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1637 afs_int32 iphash, k, srvcount = 0;
1638 unsigned int srvhash;
1640 AFS_STATCNT(afs_GetServer);
1642 ObtainSharedLock(&afs_xserver, 13);
1644 /* Check if the server struct exists and is up to date */
1647 panic("afs_GetServer: incorect count of servers");
1648 ObtainReadLock(&afs_xsrvAddr);
1649 ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1650 ReleaseReadLock(&afs_xsrvAddr);
1651 if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1652 /* Found a server struct that is not multihomed and has the
1653 * IP address associated with it. A correct match.
1655 ReleaseSharedLock(&afs_xserver);
1660 panic("afs_GetServer: incorrect count of servers");
1661 ts = afs_FindServer(0, aport, uuidp, locktype);
1662 if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1663 /* Found a server struct that is multihomed and same
1664 * uniqufier (same IP addrs). The above if statement is the
1665 * same as in InstallUVolumeEntry().
1667 ReleaseSharedLock(&afs_xserver);
1671 oldts = ts; /* Will reuse if same uuid */
1674 UpgradeSToWLock(&afs_xserver, 36);
1675 ObtainWriteLock(&afs_xsrvAddr, 116);
1677 srvcount = afs_totalServers;
1679 /* Reuse/allocate a new server structure */
1683 newts = (struct server *)afs_osi_Alloc(sizeof(struct server));
1685 panic("malloc of server struct");
1687 memset((char *)newts, 0, sizeof(struct server));
1689 /* Add the server struct to the afs_servers[] hash chain */
1691 (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
1692 newts->next = afs_servers[srvhash];
1693 afs_servers[srvhash] = newts;
1696 /* Initialize the server structure */
1697 if (uuidp) { /* Multihomed */
1698 newts->sr_uuid = *uuidp;
1699 newts->sr_addr_uniquifier = addr_uniquifier;
1700 newts->flags |= SRVR_MULTIHOMED;
1703 newts->cell = afs_GetCell(acell, 0);
1705 fsport = (newts->cell ? newts->cell->fsport : AFS_FSPORT);
1707 /* For each IP address we are registering */
1708 for (k = 0; k < nservers; k++) {
1709 iphash = SHash(aserverp[k]);
1711 /* Check if the srvAddr structure already exists. If so, remove
1712 * it from its server structure and add it to the new one.
1714 for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
1715 if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
1718 if (oldsa && (oldsa->server != newts)) {
1719 afs_RemoveSrvAddr(oldsa); /* Remove from its server struct */
1720 oldsa->next_sa = newts->addr; /* Add to the new server struct */
1721 newts->addr = oldsa;
1724 /* Reuse/allocate a new srvAddr structure */
1728 newsa = (struct srvAddr *)afs_osi_Alloc(sizeof(struct srvAddr));
1730 panic("malloc of srvAddr struct");
1731 afs_totalSrvAddrs++;
1732 memset((char *)newsa, 0, sizeof(struct srvAddr));
1734 /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1735 newsa->next_bkt = afs_srvAddrs[iphash];
1736 afs_srvAddrs[iphash] = newsa;
1738 /* Hang off of the server structure */
1739 newsa->next_sa = newts->addr;
1740 newts->addr = newsa;
1742 /* Initialize the srvAddr Structure */
1743 newsa->sa_ip = aserverp[k];
1744 newsa->sa_portal = aport;
1747 /* Update the srvAddr Structure */
1748 newsa->server = newts;
1749 if (newts->flags & SRVR_ISDOWN)
1750 newsa->sa_flags |= SRVADDR_ISDOWN;
1752 newsa->sa_flags |= SRVADDR_MH;
1754 newsa->sa_flags &= ~SRVADDR_MH;
1756 /* Compute preference values and resort */
1757 if (!newsa->sa_iprank) {
1758 afs_SetServerPrefs(newsa); /* new server rank */
1761 afs_SortOneServer(newts); /* Sort by rank */
1763 /* If we reused the server struct, remove any of its srvAddr
1764 * structs that will no longer be associated with this server.
1766 if (oldts) { /* reused the server struct */
1767 for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
1768 nextsa = orphsa->next_sa;
1769 for (k = 0; k < nservers; k++) {
1770 if (orphsa->sa_ip == aserverp[k])
1771 break; /* belongs */
1774 continue; /* belongs */
1776 /* Have a srvAddr struct. Now get a server struct (if not already) */
1779 (struct server *)afs_osi_Alloc(sizeof(struct server));
1781 panic("malloc of lo server struct");
1782 memset((char *)orphts, 0, sizeof(struct server));
1785 /* Add the orphaned server to the afs_servers[] hash chain.
1786 * Its iphash does not matter since we never look up the server
1787 * in the afs_servers table by its ip address (only by uuid -
1788 * which this has none).
1790 iphash = SHash(aserverp[k]);
1791 orphts->next = afs_servers[iphash];
1792 afs_servers[iphash] = orphts;
1795 orphts->cell = afs_GetCell(acell, 0);
1798 /* Hang the srvAddr struct off of the server structure. The server
1799 * may have multiple srvAddrs, but it won't be marked multihomed.
1801 afs_RemoveSrvAddr(orphsa); /* remove */
1802 orphsa->next_sa = orphts->addr; /* hang off server struct */
1803 orphts->addr = orphsa;
1804 orphsa->server = orphts;
1805 orphsa->sa_flags |= SRVADDR_NOUSE; /* flag indicating not in use */
1806 orphsa->sa_flags &= ~SRVADDR_MH; /* Not multihomed */
1810 srvcount = afs_totalServers - srvcount; /* # servers added and removed */
1812 struct afs_stats_SrvUpDownInfo *upDownP;
1813 /* With the introduction of this new record, we need to adjust the
1814 * proper individual & global server up/down info.
1816 upDownP = GetUpDownStats(newts);
1817 upDownP->numTtlRecords += srvcount;
1818 afs_stats_cmperf.srvRecords += srvcount;
1819 if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
1820 afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
1823 ReleaseWriteLock(&afs_xsrvAddr);
1824 ReleaseWriteLock(&afs_xserver);
1826 } /* afs_GetServer */
1828 void afs_ActivateServer(struct srvAddr *sap) {
1829 osi_timeval_t currTime; /*Filled with current time */
1830 osi_timeval_t *currTimeP; /*Ptr to above */
1831 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record */
1832 struct server *aserver = sap->server;
1834 if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
1836 * This server record has not yet been activated. Go for it,
1837 * recording its ``birth''.
1839 aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
1840 currTimeP = &currTime;
1841 osi_GetuTime(currTimeP);
1842 aserver->activationTime = currTime.tv_sec;
1843 upDownP = GetUpDownStats(aserver);
1844 if (aserver->flags & SRVR_ISDOWN) {
1845 upDownP->numDownRecords++;
1847 upDownP->numUpRecords++;
1848 upDownP->numRecordsNeverDown++;
1853 void afs_RemoveAllConns()
1856 struct server *ts, *nts;
1858 struct afs_conn *tc, *ntc;
1860 ObtainReadLock(&afs_xserver);
1861 ObtainWriteLock(&afs_xconn, 1001);
1863 /*printf("Destroying connections ... ");*/
1864 for (i = 0; i < NSERVERS; i++) {
1865 for (ts = afs_servers[i]; ts; ts = nts) {
1867 for (sa = ts->addr; sa; sa = sa->next_sa) {
1873 rx_DestroyConnection(tc->id);
1875 afs_osi_Free(tc, sizeof(struct afs_conn));
1883 /*printf("done\n");*/
1885 ReleaseWriteLock(&afs_xconn);
1886 ReleaseReadLock(&afs_xserver);
1890 void afs_MarkAllServersUp()
1896 ObtainWriteLock(&afs_xserver, 721);
1897 ObtainWriteLock(&afs_xsrvAddr, 722);
1898 for (i = 0; i< NSERVERS; i++) {
1899 for (ts = afs_servers[i]; ts; ts = ts->next) {
1900 for (sa = ts->addr; sa; sa = sa->next_sa) {
1901 afs_MarkServerUpOrDown(sa, 0);
1905 ReleaseWriteLock(&afs_xsrvAddr);
1906 ReleaseWriteLock(&afs_xserver);
1909 void shutdown_server()
1913 for (i = 0; i < NSERVERS; i++) {
1914 struct server *ts, *next;
1916 ts = afs_servers[i];
1919 afs_osi_Free(ts, sizeof(struct server));
1924 for (i = 0; i < NSERVERS; i++) {
1925 struct srvAddr *sa, *next;
1927 sa = afs_srvAddrs[i];
1929 next = sa->next_bkt;
1930 afs_osi_Free(sa, sizeof(struct srvAddr));