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 "../afs/param.h" /* Should be always first */
33 #include "../afs/stds.h"
34 #include "../afs/sysincludes.h" /* Standard vendor system headers */
38 #include <netinet/in.h>
41 #include "../h/hashing.h"
43 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV)
44 #include <netinet/in_var.h>
45 #endif /* AFS_HPUX110_ENV */
46 #endif /* !defined(UKERNEL) */
48 #include "../afs/afsincludes.h" /* Afs-based standard headers */
49 #include "../afs/afs_stats.h" /* afs statistics */
51 #if defined(AFS_SUN56_ENV)
53 #include <inet/common.h>
54 #if defined(AFS_SUN58_ENV)
55 # include <netinet/ip6.h>
56 # define ipif_local_addr ipif_lcl_addr
57 # ifndef V4_PART_OF_V6
58 # define V4_PART_OF_V6(v6) v6.s6_addr32[3]
64 /* Imported variables */
65 extern afs_int32 afs_setTime;
66 extern afs_int32 afs_waitForever;
67 extern short afs_waitForeverCount;
70 /* Exported variables */
71 afs_rwlock_t afs_xserver; /* allocation lock for servers */
72 struct server *afs_setTimeHost=0; /* last host we used for time */
73 struct server *afs_servers[NSERVERS]; /* Hashed by server`s uuid & 1st ip */
74 afs_rwlock_t afs_xsrvAddr; /* allocation lock for srvAddrs */
75 struct srvAddr *afs_srvAddrs[NSERVERS]; /* Hashed by server's ip */
78 /* debugging aids - number of alloc'd server and srvAddr structs. */
79 int afs_reuseServers = 0;
80 int afs_reuseSrvAddrs = 0;
81 int afs_totalServers = 0;
82 int afs_totalSrvAddrs = 0;
87 /*------------------------------------------------------------------------
88 * afs_MarkServerUpOrDown
91 * Mark the given server up or down, and track its uptime stats.
94 * a_serverP : Ptr to server record to fiddle with.
95 * a_isDown : Is the server is to be marked down?
101 * The CM server structures must be write-locked.
105 *------------------------------------------------------------------------*/
107 void afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
109 register struct server *a_serverP = sa->server;
110 register struct srvAddr *sap;
111 osi_timeval_t currTime, *currTimeP; /*Current time*/
112 afs_int32 downTime; /*Computed downtime, in seconds*/
113 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record*/
116 * If the server record is marked the same as the new status we've
117 * been fed, then there isn't much to be done.
119 if (( a_isDown && (sa->sa_flags & SRVADDR_ISDOWN)) ||
120 (!a_isDown && !(sa->sa_flags & SRVADDR_ISDOWN)))
124 sa->sa_flags |= SRVADDR_ISDOWN;
125 for (sap = a_serverP->addr; sap; sap = sap->next_sa) {
126 if (!(sap->sa_flags & SRVADDR_ISDOWN)) {
127 /* Not all ips are up so don't bother with the
128 * server's up/down stats */
133 * All ips are down we treat the whole server down
135 a_serverP->flags |= SRVR_ISDOWN;
137 * If this was our time server, search for another time server
139 if (a_serverP == afs_setTimeHost)
142 sa->sa_flags &= ~SRVADDR_ISDOWN;
143 /* If any ips are up, the server is also marked up */
144 a_serverP->flags &= ~SRVR_ISDOWN;
145 for (sap = a_serverP->addr; sap; sap = sap->next_sa) {
146 if (sap->sa_flags & SRVADDR_ISDOWN) {
147 /* Not all ips are up so don't bother with the
148 * server's up/down stats */
155 * Compute the current time and which overall stats record is to be
156 * updated; we'll need them one way or another.
158 currTimeP = &currTime;
159 osi_GetuTime(currTimeP);
161 if (sa->sa_portal == AFS_FSPORT) {
162 upDownP = (a_serverP->cell->cell == 1) ?
163 &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]) :
164 &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
165 } /*File Server record*/
167 upDownP = (a_serverP->cell->cell == 1) ?
168 &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]) :
169 &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
170 } /*VL Server record*/
174 * Server going up -> down; remember the beginning of this
177 a_serverP->lastDowntimeStart = currTime.tv_sec;
179 (upDownP->numDownRecords)++;
180 (upDownP->numUpRecords)--;
181 } /*Server being marked down*/
184 * Server going down -> up; remember everything about this
185 * newly-completed downtime incident.
187 downTime = currTime.tv_sec - a_serverP->lastDowntimeStart;
188 (a_serverP->numDowntimeIncidents)++;
189 a_serverP->sumOfDowntimes += downTime;
191 (upDownP->numUpRecords)++;
192 (upDownP->numDownRecords)--;
193 (upDownP->numDowntimeIncidents)++;
194 if (a_serverP->numDowntimeIncidents == 1)
195 (upDownP->numRecordsNeverDown)--;
196 upDownP->sumOfDowntimes += downTime;
197 if ((upDownP->shortestDowntime == 0) ||
198 (downTime < upDownP->shortestDowntime))
199 upDownP->shortestDowntime = downTime;
200 if ((upDownP->longestDowntime == 0) ||
201 (downTime > upDownP->longestDowntime))
202 upDownP->longestDowntime = downTime;
205 if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET0)
206 (upDownP->downDurations[0])++;
208 if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET1)
209 (upDownP->downDurations[1])++;
211 if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET2)
212 (upDownP->downDurations[2])++;
214 if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET3)
215 (upDownP->downDurations[3])++;
217 if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET4)
218 (upDownP->downDurations[4])++;
220 if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET5)
221 (upDownP->downDurations[5])++;
223 (upDownP->downDurations[6])++;
225 } /*Server being marked up*/
227 } /*MarkServerUpOrDown*/
230 void afs_ServerDown(struct srvAddr *sa)
232 register struct server *aserver = sa->server;
233 register struct srvAddr *sap;
235 AFS_STATCNT(ServerDown);
236 if (aserver->flags & SRVR_ISDOWN || sa->sa_flags & SRVADDR_ISDOWN)
238 afs_MarkServerUpOrDown(sa, SRVR_ISDOWN);
239 if (sa->sa_portal == aserver->cell->vlport)
240 print_internet_address("afs: Lost contact with volume location server ",
243 print_internet_address("afs: Lost contact with file server ", sa, "", 1);
248 /* return true if we have any callback promises from this server */
249 static HaveCallBacksFrom(aserver)
250 struct server *aserver;
253 register afs_int32 now;
255 register struct vcache *tvc;
257 AFS_STATCNT(HaveCallBacksFrom);
258 now = osi_Time(); /* for checking for expired callbacks */
259 for(i=0;i<VCSIZE;i++) { /* for all guys in the hash table */
260 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
262 * Check to see if this entry has an unexpired callback promise
263 * from the required host
265 if (aserver == tvc->callback && tvc->cbExpires >= now
266 && ((tvc->states & CRO) == 0))
272 } /*HaveCallBacksFrom*/
275 static void CheckVLServer(sa, areq)
276 struct vrequest *areq;
277 register struct srvAddr *sa;
279 register struct server *aserver = sa->server;
280 register struct conn *tc;
281 register afs_int32 code;
283 AFS_STATCNT(CheckVLServer);
284 /* Ping dead servers to see if they're back */
285 if (!(aserver->flags & SRVR_ISDOWN) || (aserver->flags & SRVR_ISGONE))
288 return; /* can't do much */
290 tc = afs_ConnByHost(aserver, aserver->cell->vlport,
291 aserver->cell->cell, areq, 1, SHARED_LOCK);
294 rx_SetConnDeadTime(tc->id, 3);
296 #ifdef RX_ENABLE_LOCKS
298 #endif /* RX_ENABLE_LOCKS */
299 code = VL_ProbeServer(tc->id);
300 #ifdef RX_ENABLE_LOCKS
302 #endif /* RX_ENABLE_LOCKS */
303 rx_SetConnDeadTime(tc->id, 50);
304 afs_PutConn(tc, SHARED_LOCK);
306 * If probe worked, or probe call not yet defined (for compatibility
307 * with old vlsevers), then we treat this server as running again
309 if (code == 0 || (code <= -450 && code >= -470)) {
310 if (tc->srvr == sa) {
311 afs_MarkServerUpOrDown(sa, 0);
312 print_internet_address("afs: volume location server ",
313 sa, " is back up", 2);
320 #ifndef AFS_MINCHANGE /* So that some can increase it in param.h */
321 #define AFS_MINCHANGE 2 /* min change we'll bother with */
323 #ifndef AFS_MAXCHANGEBACK
324 #define AFS_MAXCHANGEBACK 10 /* max seconds we'll set a clock back at once */
328 /*------------------------------------------------------------------------
329 * EXPORTED afs_CountServers
332 * Originally meant to count the number of servers and determining
333 * up/down info, this routine will now simply sum up all of the
334 * server record ages. All other up/down information is kept on the
344 * This routine locks afs_xserver for write for the duration.
347 * Set CM perf stats field sumOfRecordAges for all server record
349 *------------------------------------------------------------------------*/
351 void afs_CountServers()
353 { /*afs_CountServers*/
355 int currIdx; /*Curr idx into srv table*/
356 struct server *currSrvP; /*Ptr to curr server record*/
357 afs_int32 currChainLen; /*Length of curr hash chain*/
358 osi_timeval_t currTime; /*Current time*/
359 osi_timeval_t *currTimeP; /*Ptr to above*/
360 afs_int32 srvRecordAge; /*Age of server record, in secs*/
361 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to current up/down
362 info being manipulated*/
365 * Write-lock the server table so we don't get any interference.
367 ObtainReadLock(&afs_xserver);
370 * Iterate over each hash index in the server table, walking down each
371 * chain and tallying what we haven't computed from the records there on
372 * the fly. First, though, initialize the tallies that will change.
374 afs_stats_cmperf.srvMaxChainLength = 0;
376 afs_stats_cmperf.fs_UpDown[0].sumOfRecordAges = 0;
377 afs_stats_cmperf.fs_UpDown[0].ageOfYoungestRecord = 0;
378 afs_stats_cmperf.fs_UpDown[0].ageOfOldestRecord = 0;
379 bzero((char *) afs_stats_cmperf.fs_UpDown[0].downIncidents,
380 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
382 afs_stats_cmperf.fs_UpDown[1].sumOfRecordAges = 0;
383 afs_stats_cmperf.fs_UpDown[1].ageOfYoungestRecord = 0;
384 afs_stats_cmperf.fs_UpDown[1].ageOfOldestRecord = 0;
385 bzero((char *) afs_stats_cmperf.fs_UpDown[1].downIncidents,
386 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
388 afs_stats_cmperf.vl_UpDown[0].sumOfRecordAges = 0;
389 afs_stats_cmperf.vl_UpDown[0].ageOfYoungestRecord = 0;
390 afs_stats_cmperf.vl_UpDown[0].ageOfOldestRecord = 0;
391 bzero((char *) afs_stats_cmperf.vl_UpDown[0].downIncidents,
392 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
394 afs_stats_cmperf.vl_UpDown[1].sumOfRecordAges = 0;
395 afs_stats_cmperf.vl_UpDown[1].ageOfYoungestRecord = 0;
396 afs_stats_cmperf.vl_UpDown[1].ageOfOldestRecord = 0;
397 bzero((char *) afs_stats_cmperf.vl_UpDown[1].downIncidents,
398 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
401 * Compute the current time, used to figure out server record ages.
403 currTimeP = &currTime;
404 osi_GetuTime(currTimeP);
407 * Sweep the server hash table, tallying all we need to know.
409 for (currIdx = 0; currIdx < NSERVERS; currIdx++) {
411 for (currSrvP = afs_servers[currIdx]; currSrvP; currSrvP = currSrvP->next) {
413 * Bump the current chain length.
418 * Any further tallying for this record will only be done if it has
421 if ( (currSrvP->flags & AFS_SERVER_FLAG_ACTIVATED) &&
422 currSrvP->addr && currSrvP->cell ) {
425 * Compute the current server record's age, then remember it
426 * in the appropriate places.
428 srvRecordAge = currTime.tv_sec - currSrvP->activationTime;
429 if (currSrvP->addr->sa_portal == AFS_FSPORT) {
430 upDownP = (currSrvP->cell->cell == 1) ?
431 &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]):
432 &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
433 } /*File Server record*/
435 upDownP = (currSrvP->cell->cell == 1) ?
436 &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]):
437 &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
438 } /*VL Server record*/
440 upDownP->sumOfRecordAges += srvRecordAge;
441 if ((upDownP->ageOfYoungestRecord == 0) ||
442 (srvRecordAge < upDownP->ageOfYoungestRecord))
443 upDownP->ageOfYoungestRecord = srvRecordAge;
444 if ((upDownP->ageOfOldestRecord == 0) ||
445 (srvRecordAge > upDownP->ageOfOldestRecord))
446 upDownP->ageOfOldestRecord = srvRecordAge;
448 if (currSrvP->numDowntimeIncidents <=
449 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET0)
450 (upDownP->downIncidents[0])++;
452 if (currSrvP->numDowntimeIncidents <=
453 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET1)
454 (upDownP->downIncidents[1])++;
456 if (currSrvP->numDowntimeIncidents <=
457 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET2)
458 (upDownP->downIncidents[2])++;
460 if (currSrvP->numDowntimeIncidents <=
461 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET3)
462 (upDownP->downIncidents[3])++;
464 if (currSrvP->numDowntimeIncidents <=
465 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET4)
466 (upDownP->downIncidents[4])++;
468 (upDownP->downIncidents[5])++;
471 } /*Current server has been active*/
472 } /*Walk this chain*/
475 * Before advancing to the next chain, remember facts about this one.
477 if (currChainLen > afs_stats_cmperf.srvMaxChainLength) {
479 * We beat out the former champion (which was initially set to 0
480 * here). Mark down the new winner, and also remember if it's an
483 afs_stats_cmperf.srvMaxChainLength = currChainLen;
484 if (currChainLen > afs_stats_cmperf.srvMaxChainLengthHWM)
485 afs_stats_cmperf.srvMaxChainLengthHWM = currChainLen;
486 } /*Update chain length maximum*/
487 } /*For each hash chain*/
490 * We're done. Unlock the server table before returning to our caller.
492 ReleaseReadLock(&afs_xserver);
494 } /*afs_CountServers*/
497 /* check down servers (if adown), or running servers (if !adown) */
498 void afs_CheckServers(adown, acellp)
503 struct vrequest treq;
509 afs_int32 start, end, delta;
516 AFS_STATCNT(afs_CheckServers);
517 if (code = afs_InitReq(&treq, &afs_osi_cred)) return;
518 ObtainReadLock(&afs_xserver); /* Necessary? */
519 ObtainReadLock(&afs_xsrvAddr);
521 for (i=0;i<NSERVERS;i++) {
522 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
526 /* See if a cell to check was specified. If it is spec'd and not
527 * this server's cell, just skip the server.
529 if (acellp && acellp != ts->cell)
532 if ((!adown && (sa->sa_flags & SRVADDR_ISDOWN))
533 || (adown && !(sa->sa_flags & SRVADDR_ISDOWN)))
535 /* check vlserver with special code */
536 if (sa->sa_portal == AFS_VLPORT) {
537 CheckVLServer(sa, &treq);
541 if (!ts->cell) /* not really an active server, anyway, it must */
542 continue; /* have just been added by setsprefs */
544 /* get a connection, even if host is down; bumps conn ref count */
545 tu = afs_GetUser(treq.uid, ts->cell, SHARED_LOCK);
546 tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cell, tu,
547 1/*force*/, 1/*create*/, SHARED_LOCK);
548 afs_PutUser(tu, SHARED_LOCK);
552 if ((sa->sa_flags & SRVADDR_ISDOWN) || HaveCallBacksFrom(ts) ||
553 (tc->srvr->server == afs_setTimeHost)) {
554 if (sa->sa_flags & SRVADDR_ISDOWN) {
555 rx_SetConnDeadTime(tc->id, 3);
559 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETTIME);
560 start = osi_Time(); /* time the gettimeofday call */
561 #ifdef RX_ENABLE_LOCKS
563 #endif /* RX_ENABLE_LOCKS */
564 code = RXAFS_GetTime(tc->id, &tv.tv_sec, &tv.tv_usec);
565 #ifdef RX_ENABLE_LOCKS
567 #endif /* RX_ENABLE_LOCKS */
571 * If we're supposed to set the time, and the call worked
572 * quickly (same second response) and this is the host we
573 * use for the time and the time is really different, then
574 * really set the time
576 if (code == 0 && start == end && afs_setTime != 0 &&
577 (tc->srvr->server == afs_setTimeHost ||
579 * Sync only to a server in the local cell: cell(id)==1
582 (afs_setTimeHost == (struct server *)0 &&
583 (ts->cell->cell == 1 || (ts->cell->states&CPrimary))))) {
584 char msgbuf[90]; /* strlen("afs: setting clock...") + slop */
586 delta = end - tv.tv_sec; /* how many secs fast we are */
587 /* see if clock has changed enough to make it worthwhile */
588 if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) {
589 if (delta > AFS_MAXCHANGEBACK) {
590 /* setting clock too far back, just do it a little */
591 tv.tv_sec = end - AFS_MAXCHANGEBACK;
593 afs_osi_SetTime(&tv);
595 strcpy(msgbuf, "afs: setting clock back ");
596 if (delta > AFS_MAXCHANGEBACK) {
597 afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], AFS_MAXCHANGEBACK));
598 afs_strcat(msgbuf, " seconds (of ");
599 afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], delta - AFS_MAXCHANGEBACK));
600 afs_strcat(msgbuf, ", via ");
601 print_internet_address(msgbuf, sa, "); clock is still fast.", 0);
603 afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], delta));
604 afs_strcat(msgbuf, " seconds (via ");
605 print_internet_address(msgbuf, sa, ").", 0);
609 strcpy(msgbuf, "afs: setting clock ahead ");
610 afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], -delta));
611 afs_strcat(msgbuf, " seconds (via ");
612 print_internet_address(msgbuf, sa, ").", 0);
615 afs_setTimeHost = tc->srvr->server;
618 rx_SetConnDeadTime(tc->id, 50);
619 if (code >= 0 && (sa->sa_flags & SRVADDR_ISDOWN) && (tc->srvr == sa)) {
621 print_internet_address("afs: file server ", sa, " is back up", 2);
623 * XXX We should hold a server write lock here XXX
625 afs_MarkServerUpOrDown(sa, 0);
626 if (afs_waitForeverCount) {
627 afs_osi_Wakeup(&afs_waitForever);
634 ForceNewConnections(sa); /* multi homed clients */
638 afs_PutConn(tc, SHARED_LOCK); /* done with it now */
639 } /* for each server loop */
640 } /* for each server hash bucket loop */
641 ReleaseReadLock(&afs_xsrvAddr);
642 ReleaseReadLock(&afs_xserver);
644 } /*afs_CheckServers*/
647 /* find a server structure given the host address */
648 struct server *afs_FindServer (afs_int32 aserver, ushort aport,
649 afsUUID *uuidp, afs_int32 locktype)
655 AFS_STATCNT(afs_FindServer);
657 i = afs_uuid_hash(uuidp) % NSERVERS;
658 for (ts = afs_servers[i]; ts; ts = ts->next) {
659 if ( (ts->flags & SRVR_MULTIHOMED) &&
660 (bcmp((char *)uuidp, (char *)&ts->sr_uuid, sizeof(*uuidp)) == 0) &&
661 (!ts->addr || (ts->addr->sa_portal == aport)) )
666 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
667 if ((sa->sa_ip == aserver) && (sa->sa_portal == aport)) {
672 return (struct server *)0;
677 /* some code for creating new server structs and setting preferences follows
678 * in the next few lines...
681 #define MAXDEFRANK 60000
682 #define DEFRANK 40000
684 /* Random number generator and constants from KnuthV2 2d ed, p170 */
690 a is 0.73m should be 0.01m .. 0.99m
691 c is more or less immaterial. 1 or a is suggested.
693 NB: LOW ORDER BITS are not very random. To get small random numbers,
694 treat result as <1, with implied binary point, and multiply by
696 NB: Has to be unsigned, since shifts on signed quantities may preserve
699 /* added rxi_getaddr() to try to get as much initial randomness as
700 possible, since at least one customer reboots ALL their clients
701 simultaneously -- so osi_Time is bound to be the same on some of the
702 clients. This is probably OK, but I don't want to see too much of it.
705 #define ranstage(x) (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
706 extern afs_int32 rxi_getaddr();
708 unsigned int afs_random()
711 static afs_int32 state = 0;
714 AFS_STATCNT(afs_random);
719 * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
720 * bits are in a tv_usec
722 state = (t.tv_usec & (~0 << 4) ) + (rxi_getaddr() & 0xff);
723 state += (t.tv_sec & 0xff);
734 /* returns int 0..14 using the high bits of a pseudo-random number instead of
735 the low bits, as the low bits are "less random" than the high ones...
736 slight roundoff error exists, an excercise for the reader.
737 need to multiply by something with lots of ones in it, so multiply by
738 8 or 16 is right out.
740 int afs_randomMod15()
744 temp = afs_random() >> 4;
745 temp = (temp *15) >> 28;
750 int afs_randomMod127()
754 temp = afs_random() >> 7;
755 temp = (temp *127) >> 25;
760 /* afs_SortOneServer()
761 * Sort all of the srvAddrs, of a server struct, by rank from low to high.
763 void afs_SortOneServer(struct server *asp)
765 struct srvAddr **rootsa, *lowsa, *tsa, *lowprev;
768 for (rootsa=&(asp->addr); *rootsa; rootsa=&(lowsa->next_sa)) {
769 lowprev = (struct srvAddr *)0;
770 lowsa = *rootsa; /* lowest sa is the first one */
771 lowrank = lowsa->sa_iprank;
773 for (tsa=*rootsa; tsa->next_sa; tsa=tsa->next_sa) {
774 rank = tsa->next_sa->sa_iprank;
775 if (rank < lowrank) {
777 lowsa = tsa->next_sa;
778 lowrank = lowsa->sa_iprank;
781 if (lowprev) { /* found one lower, so rearrange them */
782 lowprev->next_sa = lowsa->next_sa;
783 lowsa->next_sa = *rootsa;
790 * Sort the pointer to servers by the server's rank (its lowest rank).
791 * It is assumed that the server already has its IP addrs sorted (the
792 * first being its lowest rank: afs_GetServer() calls afs_SortOneServer()).
794 void afs_SortServers(struct server *aservers[], int count)
799 AFS_STATCNT(afs_SortServers);
801 for (i=0; i<count; i++) {
802 if (!aservers[i]) break;
803 for (low=i,j=i+1; j<=count; j++) {
804 if (!aservers[j]) break;
805 if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
811 aservers[i] = aservers[low];
815 } /*afs_SortServers*/
817 /* afs_SetServerPrefs is rather system-dependent. It pokes around in kernel
818 data structures to determine what the local IP addresses and subnet masks
819 are in order to choose which server(s) are on the local subnet.
821 As I see it, there are several cases:
822 1. The server address is one of this host's local addresses. In this case
823 this server is to be preferred over all others.
824 2. The server is on the same subnet as one of the this host's local
825 addresses. (ie, an odd-sized subnet, not class A,B,orC)
826 3. The server is on the same net as this host (class A,B or C)
827 4. The server is on a different logical subnet or net than this host, but
828 this host is a 'metric 0 gateway' to it. Ie, two address-spaces share
830 5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
832 6. This host and the server are disjoint.
834 That is a rough order of preference. If a point-to-point link has a high
835 metric, I'm assuming that it is a very slow link, and putting it at the
836 bottom of the list (at least until RX works better over slow links). If
837 its metric is 1, I'm assuming that it's relatively fast (T1) and putting
839 It's not easy to check for case #4, so I'm ignoring it for the time being.
841 BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
842 That could be used to prefer certain servers fairly easily. Maybe some
845 NOTE: this code is very system-dependent, and very dependent on the TCP/IP
846 protocols (well, addresses that are stored in uint32s, at any rate).
849 #define IA_DST(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_dstaddr))
850 #define IA_BROAD(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
852 /* SA2ULONG takes a sockaddr_in, not a sockaddr (same thing, just cast it!) */
853 #define SA2ULONG(sa) ((sa)->sin_addr.s_addr)
858 #define PPWEIGHT 4096
863 #if defined(AFS_SUN5_ENV) && ! defined(AFS_SUN56_ENV)
864 #include <inet/common.h>
865 /* IP interface structure, one per local address */
866 typedef struct ipif_s { /**/
867 struct ipif_s * ipif_next;
868 struct ill_s * ipif_ill; /* Back pointer to our ill */
869 long ipif_id; /* Logical unit number */
870 u_int ipif_mtu; /* Starts at ipif_ill->ill_max_frag */
871 afs_int32 ipif_local_addr; /* Local IP address for this if. */
872 afs_int32 ipif_net_mask; /* Net mask for this interface. */
873 afs_int32 ipif_broadcast_addr; /* Broadcast addr for this interface. */
874 afs_int32 ipif_pp_dst_addr; /* Point-to-point dest address. */
875 u_int ipif_flags; /* Interface flags. */
876 u_int ipif_metric; /* BSD if metric, for compatibility. */
877 u_int ipif_ire_type; /* LOCAL or LOOPBACK */
878 mblk_t * ipif_arp_down_mp; /* Allocated at time arp comes up to
879 * prevent awkward out of mem condition
882 mblk_t * ipif_saved_ire_mp; /* Allocated for each extra IRE_SUBNET/
883 * RESOLVER on this interface so that
884 * they can survive ifconfig down.
887 * The packet counts in the ipif contain the sum of the
888 * packet counts in dead IREs that were affiliated with
891 u_long ipif_fo_pkt_count; /* Forwarded thru our dead IREs */
892 u_long ipif_ib_pkt_count; /* Inbound packets for our dead IREs */
893 u_long ipif_ob_pkt_count; /* Outbound packets to our dead IREs */
895 ipif_multicast_up : 1, /* We have joined the allhosts group */
899 typedef struct ipfb_s { /**/
900 struct ipf_s * ipfb_ipf; /* List of ... */
901 kmutex_t ipfb_lock; /* Protect all ipf in list */
904 typedef struct ilm_s { /**/
907 u_int ilm_timer; /* IGMP */
908 struct ipif_s * ilm_ipif; /* Back pointer to ipif */
909 struct ilm_s * ilm_next; /* Linked list for each ill */
912 typedef struct ill_s { /**/
913 struct ill_s * ill_next; /* Chained in at ill_g_head. */
914 struct ill_s ** ill_ptpn; /* Pointer to previous next. */
915 queue_t * ill_rq; /* Read queue. */
916 queue_t * ill_wq; /* Write queue. */
918 int ill_error; /* Error value sent up by device. */
920 ipif_t * ill_ipif; /* Interface chain for this ILL. */
921 u_int ill_ipif_up_count; /* Number of IPIFs currently up. */
922 u_int ill_max_frag; /* Max IDU. */
923 char * ill_name; /* Our name. */
924 u_int ill_name_length; /* Name length, incl. terminator. */
925 u_int ill_subnet_type; /* IRE_RESOLVER or IRE_SUBNET. */
926 u_int ill_ppa; /* Physical Point of Attachment num. */
928 int ill_sap_length; /* Including sign (for position) */
929 u_int ill_phys_addr_length; /* Excluding the sap. */
930 mblk_t * ill_frag_timer_mp; /* Reassembly timer state. */
931 ipfb_t * ill_frag_hash_tbl; /* Fragment hash list head. */
933 queue_t * ill_bind_pending_q; /* Queue waiting for DL_BIND_ACK. */
934 ipif_t * ill_ipif_pending; /* IPIF waiting for DL_BIND_ACK. */
936 /* ill_hdr_length and ill_hdr_mp will be non zero if
937 * the underlying device supports the M_DATA fastpath
941 ilm_t * ill_ilm; /* Multicast mebership for lower ill */
943 /* All non-nil cells between 'ill_first_mp_to_free' and
944 * 'ill_last_mp_to_free' are freed in ill_delete.
946 #define ill_first_mp_to_free ill_hdr_mp
947 mblk_t * ill_hdr_mp; /* Contains fastpath template */
948 mblk_t * ill_bcast_mp; /* DLPI header for broadcasts. */
949 mblk_t * ill_bind_pending; /* T_BIND_REQ awaiting completion. */
950 mblk_t * ill_resolver_mp; /* Resolver template. */
951 mblk_t * ill_attach_mp;
952 mblk_t * ill_bind_mp;
953 mblk_t * ill_unbind_mp;
954 mblk_t * ill_detach_mp;
955 #define ill_last_mp_to_free ill_detach_mp
958 ill_frag_timer_running : 1,
959 ill_needs_attach : 1,
962 ill_unbind_pending : 1,
964 ill_pad_to_bit_31 : 27;
965 MI_HRT_DCL(ill_rtime)
970 #ifdef AFS_USERSPACE_IP_ADDR
972 #define min(A,B) ((A)<(B)) ? (A) : (B)
975 * The IP addresses and ranks are determined by afsd (in user space) and
976 * passed into the kernel at startup time through the AFSOP_ADVISEADDR
977 * system call. These are stored in the data structure
978 * called 'afs_cb_interface'.
980 afsi_SetServerIPRank(sa, addr, subnetmask)
981 struct srvAddr *sa; /* remote server */
982 afs_int32 addr; /* one of my local addr in net order */
983 afs_uint32 subnetmask; /* subnet mask of local addr in net order */
985 afs_uint32 myAddr, myNet, mySubnet, netMask;
986 afs_uint32 serverAddr ;
988 myAddr = ntohl(addr); /* one of my IP addr in host order */
989 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
990 subnetmask = ntohl(subnetmask);/* subnet mask in host order */
992 if ( IN_CLASSA(myAddr) ) netMask = IN_CLASSA_NET;
993 else if ( IN_CLASSB(myAddr) ) netMask = IN_CLASSB_NET;
994 else if ( IN_CLASSC(myAddr) ) netMask = IN_CLASSC_NET;
997 myNet = myAddr & netMask;
998 mySubnet = myAddr & subnetmask;
1000 if ( (serverAddr & netMask ) == myNet ) {
1001 if ( (serverAddr & subnetmask ) == mySubnet) {
1002 if ( serverAddr == myAddr ) { /* same machine */
1003 sa->sa_iprank = min(sa->sa_iprank, TOPR);
1004 } else { /* same subnet */
1005 sa->sa_iprank = min(sa->sa_iprank, HI);
1007 } else { /* same net */
1008 sa->sa_iprank = min(sa->sa_iprank, MED);
1012 #else /* AFS_USERSPACE_IP_ADDR */
1013 #if (! defined(AFS_SUN5_ENV)) && defined(USEIFADDR)
1015 afsi_SetServerIPRank(sa, ifa)
1017 struct in_ifaddr *ifa;
1019 struct sockaddr_in *sin;
1022 if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
1023 if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
1025 if ( SA2ULONG(sin) == ntohl(sa->sa_ip)) { /* ie, ME!!! */
1026 sa->sa_iprank = TOPR;
1028 t = HI + ifa->ia_ifp->if_metric; /* case #2 */
1029 if (sa->sa_iprank > t)
1033 t = MED + ifa->ia_ifp->if_metric;/* case #3 */
1034 if (sa->sa_iprank > t)
1038 #ifdef IFF_POINTTOPOINT
1039 /* check for case #4 -- point-to-point link */
1040 if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT) &&
1041 (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
1042 if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED)/PPWEIGHT)
1045 t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
1046 if (sa->sa_iprank > t)
1049 #endif /* IFF_POINTTOPOINT */
1051 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR)*/
1052 #endif /* else AFS_USERSPACE_IP_ADDR */
1054 #ifdef AFS_SGI62_ENV
1056 afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1059 afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr*)h);
1060 return 0; /* Never match, so we enumerate everyone */
1062 #endif /* AFS_SGI62_ENV */
1064 static afs_SetServerPrefs(sa)
1067 #if defined(AFS_USERSPACE_IP_ADDR)
1068 extern interfaceAddr afs_cb_interface;
1072 for (i=0; i<afs_cb_interface.numberOfInterfaces; i++) {
1073 afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1074 afs_cb_interface.subnetmask[i]);
1076 #else /* AFS_USERSPACE_IP_ADDR */
1077 #if defined(AFS_SUN5_ENV)
1078 extern struct ill_s *ill_g_headp;
1081 int subnet, subnetmask, net, netmask;
1082 long *addr = (long *) ill_g_headp;
1083 extern struct ifnet *rxi_FindIfnet();
1085 if (sa) sa->sa_iprank= 0;
1086 for (ill = (struct ill_s *)*addr /*ill_g_headp*/; ill; ill = ill->ill_next ) {
1087 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next ) {
1088 subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1089 subnetmask = ipif->ipif_net_mask;
1091 * Generate the local net using the local address and
1092 * whate we know about Class A, B and C networks.
1094 if (IN_CLASSA(ipif->ipif_local_addr)) {
1095 netmask = IN_CLASSA_NET;
1096 } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1097 netmask = IN_CLASSB_NET;
1098 } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1099 netmask = IN_CLASSC_NET;
1103 net = ipif->ipif_local_addr & netmask;
1106 if (ipif->ipif_local_addr != 0x7f000001) { /* ignore loopback */
1108 if (*cnt > 16) return;
1109 *addrp++ = ipif->ipif_local_addr;
1114 /* XXXXXX Do the individual ip ranking below XXXXX */
1115 if ((sa->sa_ip & netmask) == net) {
1116 if ((sa->sa_ip & subnetmask) == subnet) {
1117 if (ipif->ipif_local_addr == sa->sa_ip) { /* ie, ME! */
1118 sa->sa_iprank = TOPR;
1120 sa->sa_iprank = HI + ipif->ipif_metric; /* case #2 */
1123 sa->sa_iprank = MED + ipif->ipif_metric; /* case #3 */
1126 sa->sa_iprank = LO + ipif->ipif_metric; /* case #4 */
1128 /* check for case #5 -- point-to-point link */
1129 if ((ipif->ipif_flags & IFF_POINTOPOINT) &&
1130 (ipif->ipif_pp_dst_addr == sa->sa_ip )) {
1132 if (ipif->ipif_metric >= (MAXDEFRANK - MED)/PPWEIGHT)
1133 sa->sa_iprank = MAXDEFRANK;
1135 sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1142 struct ifnet *ifn = (struct ifnet *)0;
1143 struct in_ifaddr *ifad = (struct in_ifaddr *) 0;
1144 struct sockaddr_in *sin;
1147 #ifdef notdef /* clean up, remove this */
1148 for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
1149 for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next){
1150 if ((IFADDR2SA(ifad)->sa_family == AF_INET)
1151 && !(ifn->if_flags & IFF_LOOPBACK)) {
1153 if (*cnt > 16) return;
1154 *addrp++ = ((struct sockaddr_in *) IFADDR2SA(ifad))->sin_addr.s_addr;
1163 ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1165 if (ifn) { /* local, more or less */
1167 if (ifn->if_flags & IFF_LOOPBACK) {
1168 sa->sa_iprank = TOPR;
1171 #endif /* IFF_LOOPBACK */
1172 sin = (struct sockaddr_in *) IA_SIN(ifad);
1173 if (SA2ULONG(sin) == sa->sa_ip) {
1174 sa->sa_iprank = TOPR;
1177 #ifdef IFF_BROADCAST
1178 if (ifn->if_flags & IFF_BROADCAST) {
1179 if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1184 #endif /* IFF_BROADCAST */
1185 #ifdef IFF_POINTOPOINT
1186 if (ifn->if_flags & IFF_POINTOPOINT) {
1187 if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1188 if (ifn->if_metric > 4) {
1192 else sa->sa_iprank = ifn->if_metric;
1195 #endif /* IFF_POINTOPOINT */
1196 sa->sa_iprank += MED + ifn->if_metric; /* couldn't find anything better */
1199 #else /* USEIFADDR */
1201 if (sa) sa->sa_iprank= LO;
1202 #ifdef AFS_SGI62_ENV
1203 (void) hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1205 #elif defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1207 struct in_ifaddr *ifa;
1208 TAILQ_FOREACH(ifa , &in_ifaddrhead, ia_link) {
1209 afsi_SetServerIPRank(sa, ifa);
1214 extern struct in_ifaddr *in_ifaddr;
1215 struct in_ifaddr *ifa;
1216 for ( ifa = in_ifaddr; ifa; ifa = ifa->ia_next ) {
1217 afsi_SetServerIPRank(sa, ifa);
1222 #endif /* USEIFADDR */
1223 #endif /* AFS_SUN5_ENV */
1224 #endif /* else AFS_USERSPACE_IP_ADDR */
1227 if (sa) sa->sa_iprank += afs_randomMod15();
1230 } /* afs_SetServerPrefs */
1237 /* afs_FlushServer()
1238 * The addresses on this server struct has changed in some way and will
1239 * clean up all other structures that may reference it.
1240 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1242 void afs_FlushServer(srvp)
1243 struct server *srvp;
1246 struct server *ts, **pts;
1248 /* Find any volumes residing on this server and flush their state */
1249 afs_ResetVolumes(srvp);
1251 /* Flush all callbacks in the all vcaches for this specific server */
1252 afs_FlushServerCBs(srvp);
1254 /* Remove all the callbacks structs */
1256 struct afs_cbr *cb, *cbnext;
1257 extern afs_lock_t afs_xvcb;
1259 MObtainWriteLock(&afs_xvcb, 300);
1260 for (cb=srvp->cbrs; cb; cb=cbnext) {
1264 srvp->cbrs = (struct afs_cbr *)0;
1265 ReleaseWriteLock(&afs_xvcb);
1268 /* If no more srvAddr structs hanging off of this server struct,
1272 /* Remove the server structure from the cell list - if there */
1273 afs_RemoveCellEntry(srvp);
1275 /* Remove from the afs_servers hash chain */
1276 for (i=0; i<NSERVERS; i++) {
1277 for (pts=&(afs_servers[i]), ts=*pts; ts; pts=&(ts->next), ts=*pts) {
1278 if (ts == srvp) break;
1283 *pts = ts->next; /* Found it. Remove it */
1284 afs_osi_Free(ts, sizeof(struct server)); /* Free it */
1290 /* afs_RemoveSrvAddr()
1291 * This removes a SrvAddr structure from its server structure.
1292 * The srvAddr struct is not free'd because it connections may still
1293 * be open to it. It is up to the calling process to make sure it
1294 * remains connected to a server struct.
1295 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1296 * It is not removed from the afs_srvAddrs hash chain.
1298 void afs_RemoveSrvAddr(sap)
1299 struct srvAddr *sap;
1301 struct srvAddr **psa, *sa;
1307 /* Find the srvAddr in the server's list and remove it */
1308 for (psa=&(srv->addr), sa=*psa; sa; psa=&(sa->next_sa), sa=*psa) {
1309 if (sa == sap) break;
1316 /* Flush the server struct since it's IP address has changed */
1317 afs_FlushServer(srv);
1322 * Return an updated and properly initialized server structure
1323 * corresponding to the server ID, cell, and port specified.
1324 * If one does not exist, then one will be created.
1325 * aserver and aport must be in NET byte order.
1327 struct server *afs_GetServer(afs_uint32 *aserverp, afs_int32 nservers,
1328 afs_int32 acell, u_short aport,
1329 afs_int32 locktype, afsUUID *uuidp,
1330 afs_int32 addr_uniquifier)
1332 struct server *oldts=0, *ts, *newts, *orphts=0;
1333 struct srvAddr *oldsa, *sa, *newsa, *nextsa, *orphsa;
1335 afs_int32 iphash, k, srvcount=0;
1336 unsigned int srvhash;
1338 AFS_STATCNT(afs_GetServer);
1340 ObtainSharedLock(&afs_xserver,13);
1342 /* Check if the server struct exists and is up to date */
1344 if (nservers != 1) panic("afs_GetServer: incorect count of servers");
1345 ObtainReadLock(&afs_xsrvAddr);
1346 ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1347 ReleaseReadLock(&afs_xsrvAddr);
1348 if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1349 /* Found a server struct that is not multihomed and has the
1350 * IP address associated with it. A correct match.
1352 ReleaseSharedLock(&afs_xserver);
1356 if (nservers <= 0) panic("afs_GetServer: incorrect count of servers");
1357 ts = afs_FindServer(0, aport, uuidp, locktype);
1358 if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1359 /* Found a server struct that is multihomed and same
1360 * uniqufier (same IP addrs). The above if statement is the
1361 * same as in InstallUVolumeEntry().
1363 ReleaseSharedLock(&afs_xserver);
1366 if (ts) oldts = ts; /* Will reuse if same uuid */
1369 UpgradeSToWLock(&afs_xserver,36);
1370 ObtainWriteLock(&afs_xsrvAddr,116);
1372 srvcount = afs_totalServers;
1374 /* Reuse/allocate a new server structure */
1378 newts = (struct server *) afs_osi_Alloc(sizeof(struct server));
1379 if (!newts) panic("malloc of server struct");
1381 bzero((char *)newts, sizeof(struct server));
1383 /* Add the server struct to the afs_servers[] hash chain */
1384 srvhash = (uuidp ? (afs_uuid_hash(uuidp)%NSERVERS) : SHash(aserverp[0]));
1385 newts->next = afs_servers[srvhash];
1386 afs_servers[srvhash] = newts;
1389 /* Initialize the server structure */
1390 if (uuidp) { /* Multihomed */
1391 newts->sr_uuid = *uuidp;
1392 newts->sr_addr_uniquifier = addr_uniquifier;
1393 newts->flags |= SRVR_MULTIHOMED;
1395 if (acell) newts->cell = afs_GetCell(acell, 0);
1397 fsport = (newts->cell ? newts->cell->fsport : AFS_FSPORT);
1399 /* For each IP address we are registering */
1400 for (k=0; k<nservers; k++) {
1401 iphash = SHash(aserverp[k]);
1403 /* Check if the srvAddr structure already exists. If so, remove
1404 * it from its server structure and add it to the new one.
1406 for (oldsa=afs_srvAddrs[iphash]; oldsa; oldsa=oldsa->next_bkt) {
1407 if ( (oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport) ) break;
1409 if (oldsa && (oldsa->server != newts)) {
1410 afs_RemoveSrvAddr(oldsa); /* Remove from its server struct */
1411 oldsa->next_sa = newts->addr; /* Add to the new server struct */
1412 newts->addr = oldsa;
1415 /* Reuse/allocate a new srvAddr structure */
1419 newsa = (struct srvAddr *) afs_osi_Alloc(sizeof(struct srvAddr));
1420 if (!newsa) panic("malloc of srvAddr struct");
1421 afs_totalSrvAddrs++;
1422 bzero((char *)newsa, sizeof(struct srvAddr));
1424 /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1425 newsa->next_bkt = afs_srvAddrs[iphash];
1426 afs_srvAddrs[iphash] = newsa;
1428 /* Hang off of the server structure */
1429 newsa->next_sa = newts->addr;
1430 newts->addr = newsa;
1432 /* Initialize the srvAddr Structure */
1433 newsa->sa_ip = aserverp[k];
1434 newsa->sa_portal = aport;
1437 /* Update the srvAddr Structure */
1438 newsa->server = newts;
1439 if (newts->flags & SRVR_ISDOWN)
1440 newsa->sa_flags |= SRVADDR_ISDOWN;
1441 if (uuidp) newsa->sa_flags |= SRVADDR_MH;
1442 else newsa->sa_flags &= ~SRVADDR_MH;
1444 /* Compute preference values and resort */
1445 if (!newsa->sa_iprank) {
1446 if (aport == fsport) {
1447 afs_SetServerPrefs(newsa); /* new fileserver rank */
1449 newsa->sa_iprank = 10000 + afs_randomMod127(); /* new vlserver rank */
1453 afs_SortOneServer(newts); /* Sort by rank */
1455 /* If we reused the server struct, remove any of its srvAddr
1456 * structs that will no longer be associated with this server.
1458 if (oldts) { /* reused the server struct */
1459 for (orphsa=newts->addr; orphsa; orphsa=nextsa) {
1460 nextsa = orphsa->next_sa;
1461 for (k=0; k<nservers; k++) {
1462 if (orphsa->sa_ip == aserverp[k]) break; /* belongs */
1464 if (k < nservers) continue; /* belongs */
1466 /* Have a srvAddr struct. Now get a server struct (if not already) */
1468 orphts = (struct server *) afs_osi_Alloc(sizeof(struct server));
1469 if (!orphts) panic("malloc of lo server struct");
1470 bzero((char *)orphts, sizeof(struct server));
1473 /* Add the orphaned server to the afs_servers[] hash chain.
1474 * Its iphash does not matter since we never look up the server
1475 * in the afs_servers table by its ip address (only by uuid -
1476 * which this has none).
1478 iphash = SHash(aserverp[k]);
1479 orphts->next = afs_servers[iphash];
1480 afs_servers[iphash] = orphts;
1482 if (acell) orphts->cell = afs_GetCell(acell, 0);
1485 /* Hang the srvAddr struct off of the server structure. The server
1486 * may have multiple srvAddrs, but it won't be marked multihomed.
1488 afs_RemoveSrvAddr(orphsa); /* remove */
1489 orphsa->next_sa = orphts->addr; /* hang off server struct */
1490 orphts->addr = orphsa;
1491 orphsa->server = orphts;
1492 orphsa->sa_flags |= SRVADDR_NOUSE; /* flag indicating not in use */
1493 orphsa->sa_flags &= ~SRVADDR_MH; /* Not multihomed */
1497 srvcount = afs_totalServers - srvcount; /* # servers added and removed */
1499 struct afs_stats_SrvUpDownInfo *upDownP;
1500 /* With the introduction of this new record, we need to adjust the
1501 * proper individual & global server up/down info.
1503 if (aport == fsport) { /* File Server record */
1504 upDownP = (acell == 1) ?
1505 &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]) :
1506 &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
1507 } else { /* VL Server record */
1508 upDownP = (acell == 1) ?
1509 &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]) :
1510 &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
1512 (upDownP->numTtlRecords) += srvcount;
1513 afs_stats_cmperf.srvRecords += srvcount;
1514 if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
1515 afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
1518 ReleaseWriteLock(&afs_xsrvAddr);
1519 ReleaseWriteLock(&afs_xserver);
1521 } /* afs_GetServer */
1523 void afs_ActivateServer(sap)
1524 struct srvAddr *sap;
1526 osi_timeval_t currTime; /*Filled with current time*/
1527 osi_timeval_t *currTimeP; /*Ptr to above*/
1528 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record*/
1529 struct server *aserver = sap->server;
1531 if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
1533 * This server record has not yet been activated. Go for it,
1534 * recording its ``birth''.
1536 aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
1537 currTimeP = &currTime;
1538 osi_GetuTime(currTimeP);
1539 aserver->activationTime = currTime.tv_sec;
1540 if (sap->sa_portal == AFS_FSPORT) {
1541 upDownP = (aserver->cell->cell == 1) ?
1542 &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]) :
1543 &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
1544 } /*File Server record*/
1546 upDownP = (aserver->cell->cell == 1) ?
1547 &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]) :
1548 &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
1549 } /*VL Server record*/
1550 if (aserver->flags & SRVR_ISDOWN)
1551 (upDownP->numDownRecords)++;
1553 (upDownP->numUpRecords)++;
1554 (upDownP->numRecordsNeverDown)++;