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"
39 #include "afs/sysincludes.h" /* Standard vendor system headers */
42 #if !defined(AFS_LINUX20_ENV)
45 #include <netinet/in.h>
48 #include "h/hashing.h"
50 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN60_ENV)
51 #include <netinet/in_var.h>
52 #endif /* AFS_HPUX110_ENV */
53 #ifdef AFS_DARWIN60_ENV
54 #include <net/if_var.h>
56 #endif /* !defined(UKERNEL) */
58 #include "afsincludes.h" /* Afs-based standard headers */
59 #include "afs/afs_stats.h" /* afs statistics */
61 #if defined(AFS_SUN56_ENV)
63 #include <inet/common.h>
64 #if defined(AFS_SUN58_ENV)
65 # include <netinet/ip6.h>
66 # define ipif_local_addr ipif_lcl_addr
67 # ifndef V4_PART_OF_V6
68 # define V4_PART_OF_V6(v6) v6.s6_addr32[3]
74 /* Exported variables */
75 afs_rwlock_t afs_xserver; /* allocation lock for servers */
76 struct server *afs_setTimeHost = 0; /* last host we used for time */
77 struct server *afs_servers[NSERVERS]; /* Hashed by server`s uuid & 1st ip */
78 afs_rwlock_t afs_xsrvAddr; /* allocation lock for srvAddrs */
79 struct srvAddr *afs_srvAddrs[NSERVERS]; /* Hashed by server's ip */
82 /* debugging aids - number of alloc'd server and srvAddr structs. */
83 int afs_reuseServers = 0;
84 int afs_reuseSrvAddrs = 0;
85 int afs_totalServers = 0;
86 int afs_totalSrvAddrs = 0;
90 static struct afs_stats_SrvUpDownInfo *
91 GetUpDownStats(struct server *srv)
93 struct afs_stats_SrvUpDownInfo *upDownP;
94 u_short fsport = AFS_FSPORT;
97 fsport = srv->cell->fsport;
99 if (srv->addr->sa_portal == fsport)
100 upDownP = afs_stats_cmperf.fs_UpDown;
102 upDownP = afs_stats_cmperf.vl_UpDown;
104 if (srv->cell && afs_IsPrimaryCell(srv->cell))
105 return &upDownP[AFS_STATS_UPDOWN_IDX_SAME_CELL];
107 return &upDownP[AFS_STATS_UPDOWN_IDX_DIFF_CELL];
111 /*------------------------------------------------------------------------
112 * afs_MarkServerUpOrDown
115 * Mark the given server up or down, and track its uptime stats.
118 * a_serverP : Ptr to server record to fiddle with.
119 * a_isDown : Is the server is to be marked down?
125 * The CM server structures must be write-locked.
129 *------------------------------------------------------------------------*/
132 afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
134 register struct server *a_serverP = sa->server;
135 register struct srvAddr *sap;
136 osi_timeval_t currTime, *currTimeP; /*Current time */
137 afs_int32 downTime; /*Computed downtime, in seconds */
138 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record */
141 * If the server record is marked the same as the new status we've
142 * been fed, then there isn't much to be done.
144 if ((a_isDown && (sa->sa_flags & SRVADDR_ISDOWN))
145 || (!a_isDown && !(sa->sa_flags & SRVADDR_ISDOWN)))
149 sa->sa_flags |= SRVADDR_ISDOWN;
150 for (sap = a_serverP->addr; sap; sap = sap->next_sa) {
151 if (!(sap->sa_flags & SRVADDR_ISDOWN)) {
152 /* Not all ips are up so don't bother with the
153 * server's up/down stats */
158 * All ips are down we treat the whole server down
160 a_serverP->flags |= SRVR_ISDOWN;
162 * If this was our time server, search for another time server
164 if (a_serverP == afs_setTimeHost)
167 sa->sa_flags &= ~SRVADDR_ISDOWN;
168 /* If any ips are up, the server is also marked up */
169 a_serverP->flags &= ~SRVR_ISDOWN;
170 for (sap = a_serverP->addr; sap; sap = sap->next_sa) {
171 if (sap->sa_flags & SRVADDR_ISDOWN) {
172 /* Not all ips are up so don't bother with the
173 * server's up/down stats */
180 * Compute the current time and which overall stats record is to be
181 * updated; we'll need them one way or another.
183 currTimeP = &currTime;
184 osi_GetuTime(currTimeP);
186 upDownP = GetUpDownStats(a_serverP);
190 * Server going up -> down; remember the beginning of this
193 a_serverP->lastDowntimeStart = currTime.tv_sec;
195 (upDownP->numDownRecords)++;
196 (upDownP->numUpRecords)--;
197 } /*Server being marked down */
200 * Server going down -> up; remember everything about this
201 * newly-completed downtime incident.
203 downTime = currTime.tv_sec - a_serverP->lastDowntimeStart;
204 (a_serverP->numDowntimeIncidents)++;
205 a_serverP->sumOfDowntimes += downTime;
207 (upDownP->numUpRecords)++;
208 (upDownP->numDownRecords)--;
209 (upDownP->numDowntimeIncidents)++;
210 if (a_serverP->numDowntimeIncidents == 1)
211 (upDownP->numRecordsNeverDown)--;
212 upDownP->sumOfDowntimes += downTime;
213 if ((upDownP->shortestDowntime == 0)
214 || (downTime < upDownP->shortestDowntime))
215 upDownP->shortestDowntime = downTime;
216 if ((upDownP->longestDowntime == 0)
217 || (downTime > upDownP->longestDowntime))
218 upDownP->longestDowntime = downTime;
221 if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET0)
222 (upDownP->downDurations[0])++;
223 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET1)
224 (upDownP->downDurations[1])++;
225 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET2)
226 (upDownP->downDurations[2])++;
227 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET3)
228 (upDownP->downDurations[3])++;
229 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET4)
230 (upDownP->downDurations[4])++;
231 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET5)
232 (upDownP->downDurations[5])++;
234 (upDownP->downDurations[6])++;
236 } /*Server being marked up */
238 } /*MarkServerUpOrDown */
242 afs_ServerDown(struct srvAddr *sa)
244 register struct server *aserver = sa->server;
246 AFS_STATCNT(ServerDown);
247 if (aserver->flags & SRVR_ISDOWN || sa->sa_flags & SRVADDR_ISDOWN)
249 afs_MarkServerUpOrDown(sa, SRVR_ISDOWN);
250 if (sa->sa_portal == aserver->cell->vlport)
251 print_internet_address
252 ("afs: Lost contact with volume location server ", sa, "", 1);
254 print_internet_address("afs: Lost contact with file server ", sa, "",
260 /* return true if we have any callback promises from this server */
262 HaveCallBacksFrom(struct server *aserver)
264 register afs_int32 now;
266 register struct vcache *tvc;
268 AFS_STATCNT(HaveCallBacksFrom);
269 now = osi_Time(); /* for checking for expired callbacks */
270 for (i = 0; i < VCSIZE; i++) { /* for all guys in the hash table */
271 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
273 * Check to see if this entry has an unexpired callback promise
274 * from the required host
276 if (aserver == tvc->callback && tvc->cbExpires >= now
277 && ((tvc->states & CRO) == 0))
283 } /*HaveCallBacksFrom */
287 CheckVLServer(register struct srvAddr *sa, struct vrequest *areq)
289 register struct server *aserver = sa->server;
290 register struct conn *tc;
291 register afs_int32 code;
293 AFS_STATCNT(CheckVLServer);
294 /* Ping dead servers to see if they're back */
295 if (!((aserver->flags & SRVR_ISDOWN) || (sa->sa_flags & SRVADDR_ISDOWN))
296 || (aserver->flags & SRVR_ISGONE))
299 return; /* can't do much */
301 tc = afs_ConnByHost(aserver, aserver->cell->vlport,
302 aserver->cell->cellNum, areq, 1, SHARED_LOCK);
305 rx_SetConnDeadTime(tc->id, 3);
308 code = VL_ProbeServer(tc->id);
310 rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
311 afs_PutConn(tc, SHARED_LOCK);
313 * If probe worked, or probe call not yet defined (for compatibility
314 * with old vlsevers), then we treat this server as running again
316 if (code == 0 || (code <= -450 && code >= -470)) {
317 if (tc->srvr == sa) {
318 afs_MarkServerUpOrDown(sa, 0);
319 print_internet_address("afs: volume location server ", sa,
327 #ifndef AFS_MINCHANGE /* So that some can increase it in param.h */
328 #define AFS_MINCHANGE 2 /* min change we'll bother with */
330 #ifndef AFS_MAXCHANGEBACK
331 #define AFS_MAXCHANGEBACK 10 /* max seconds we'll set a clock back at once */
335 /*------------------------------------------------------------------------
336 * EXPORTED afs_CountServers
339 * Originally meant to count the number of servers and determining
340 * up/down info, this routine will now simply sum up all of the
341 * server record ages. All other up/down information is kept on the
351 * This routine locks afs_xserver for write for the duration.
354 * Set CM perf stats field sumOfRecordAges for all server record
356 *------------------------------------------------------------------------*/
359 afs_CountServers(void)
361 int currIdx; /*Curr idx into srv table */
362 struct server *currSrvP; /*Ptr to curr server record */
363 afs_int32 currChainLen; /*Length of curr hash chain */
364 osi_timeval_t currTime; /*Current time */
365 osi_timeval_t *currTimeP; /*Ptr to above */
366 afs_int32 srvRecordAge; /*Age of server record, in secs */
367 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to current up/down
368 * info being manipulated */
371 * Write-lock the server table so we don't get any interference.
373 ObtainReadLock(&afs_xserver);
376 * Iterate over each hash index in the server table, walking down each
377 * chain and tallying what we haven't computed from the records there on
378 * the fly. First, though, initialize the tallies that will change.
380 afs_stats_cmperf.srvMaxChainLength = 0;
382 afs_stats_cmperf.fs_UpDown[0].sumOfRecordAges = 0;
383 afs_stats_cmperf.fs_UpDown[0].ageOfYoungestRecord = 0;
384 afs_stats_cmperf.fs_UpDown[0].ageOfOldestRecord = 0;
385 memset((char *)afs_stats_cmperf.fs_UpDown[0].downIncidents, 0,
386 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
388 afs_stats_cmperf.fs_UpDown[1].sumOfRecordAges = 0;
389 afs_stats_cmperf.fs_UpDown[1].ageOfYoungestRecord = 0;
390 afs_stats_cmperf.fs_UpDown[1].ageOfOldestRecord = 0;
391 memset((char *)afs_stats_cmperf.fs_UpDown[1].downIncidents, 0,
392 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
394 afs_stats_cmperf.vl_UpDown[0].sumOfRecordAges = 0;
395 afs_stats_cmperf.vl_UpDown[0].ageOfYoungestRecord = 0;
396 afs_stats_cmperf.vl_UpDown[0].ageOfOldestRecord = 0;
397 memset((char *)afs_stats_cmperf.vl_UpDown[0].downIncidents, 0,
398 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
400 afs_stats_cmperf.vl_UpDown[1].sumOfRecordAges = 0;
401 afs_stats_cmperf.vl_UpDown[1].ageOfYoungestRecord = 0;
402 afs_stats_cmperf.vl_UpDown[1].ageOfOldestRecord = 0;
403 memset((char *)afs_stats_cmperf.vl_UpDown[1].downIncidents, 0,
404 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
407 * Compute the current time, used to figure out server record ages.
409 currTimeP = &currTime;
410 osi_GetuTime(currTimeP);
413 * Sweep the server hash table, tallying all we need to know.
415 for (currIdx = 0; currIdx < NSERVERS; currIdx++) {
417 for (currSrvP = afs_servers[currIdx]; currSrvP;
418 currSrvP = currSrvP->next) {
420 * Bump the current chain length.
425 * Any further tallying for this record will only be done if it has
428 if ((currSrvP->flags & AFS_SERVER_FLAG_ACTIVATED)
429 && currSrvP->addr && currSrvP->cell) {
432 * Compute the current server record's age, then remember it
433 * in the appropriate places.
435 srvRecordAge = currTime.tv_sec - currSrvP->activationTime;
436 upDownP = GetUpDownStats(currSrvP);
437 upDownP->sumOfRecordAges += srvRecordAge;
438 if ((upDownP->ageOfYoungestRecord == 0)
439 || (srvRecordAge < upDownP->ageOfYoungestRecord))
440 upDownP->ageOfYoungestRecord = srvRecordAge;
441 if ((upDownP->ageOfOldestRecord == 0)
442 || (srvRecordAge > upDownP->ageOfOldestRecord))
443 upDownP->ageOfOldestRecord = srvRecordAge;
445 if (currSrvP->numDowntimeIncidents <=
446 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET0)
447 (upDownP->downIncidents[0])++;
448 else if (currSrvP->numDowntimeIncidents <=
449 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET1)
450 (upDownP->downIncidents[1])++;
451 else if (currSrvP->numDowntimeIncidents <=
452 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET2)
453 (upDownP->downIncidents[2])++;
454 else if (currSrvP->numDowntimeIncidents <=
455 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET3)
456 (upDownP->downIncidents[3])++;
457 else if (currSrvP->numDowntimeIncidents <=
458 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET4)
459 (upDownP->downIncidents[4])++;
461 (upDownP->downIncidents[5])++;
464 } /*Current server has been active */
465 } /*Walk this chain */
468 * Before advancing to the next chain, remember facts about this one.
470 if (currChainLen > afs_stats_cmperf.srvMaxChainLength) {
472 * We beat out the former champion (which was initially set to 0
473 * here). Mark down the new winner, and also remember if it's an
476 afs_stats_cmperf.srvMaxChainLength = currChainLen;
477 if (currChainLen > afs_stats_cmperf.srvMaxChainLengthHWM)
478 afs_stats_cmperf.srvMaxChainLengthHWM = currChainLen;
479 } /*Update chain length maximum */
480 } /*For each hash chain */
483 * We're done. Unlock the server table before returning to our caller.
485 ReleaseReadLock(&afs_xserver);
487 } /*afs_CountServers */
490 /* check down servers (if adown), or running servers (if !adown) */
492 afs_CheckServers(int adown, struct cell *acellp)
494 struct vrequest treq;
500 afs_int32 start, end, delta;
506 struct srvAddr **addrs;
509 AFS_STATCNT(afs_CheckServers);
510 if ((code = afs_InitReq(&treq, &afs_osi_cred)))
512 ObtainReadLock(&afs_xserver); /* Necessary? */
513 ObtainReadLock(&afs_xsrvAddr);
516 for (i = 0; i < NSERVERS; i++) {
517 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
522 addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
524 for (i = 0; i < NSERVERS; i++) {
525 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
526 if (j >= srvAddrCount)
532 ReleaseReadLock(&afs_xsrvAddr);
533 ReleaseReadLock(&afs_xserver);
535 for (i = 0; i < j; i++) {
541 /* See if a cell to check was specified. If it is spec'd and not
542 * this server's cell, just skip the server.
544 if (acellp && acellp != ts->cell)
547 if ((!adown && (sa->sa_flags & SRVADDR_ISDOWN))
548 || (adown && !(sa->sa_flags & SRVADDR_ISDOWN)))
551 /* check vlserver with special code */
552 if (sa->sa_portal == AFS_VLPORT) {
553 CheckVLServer(sa, &treq);
557 if (!ts->cell) /* not really an active server, anyway, it must */
558 continue; /* have just been added by setsprefs */
560 /* get a connection, even if host is down; bumps conn ref count */
561 tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
562 tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
563 1 /*force */ , 1 /*create */ , SHARED_LOCK);
564 afs_PutUser(tu, SHARED_LOCK);
568 if ((sa->sa_flags & SRVADDR_ISDOWN) || HaveCallBacksFrom(ts)
569 || (tc->srvr->server == afs_setTimeHost)) {
570 if (sa->sa_flags & SRVADDR_ISDOWN) {
571 rx_SetConnDeadTime(tc->id, 3);
577 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETTIME);
578 start = osi_Time(); /* time the gettimeofday call */
581 RXAFS_GetTime(tc->id, (afs_int32 *) & tv.tv_sec,
582 (afs_int32 *) & tv.tv_usec);
587 * If we're supposed to set the time, and the call worked
588 * quickly (same second response) and this is the host we
589 * use for the time and the time is really different, then
590 * really set the time
592 if (code == 0 && start == end && afs_setTime != 0
593 && (tc->srvr->server == afs_setTimeHost ||
594 /* Sync only to a server in the local cell */
595 (afs_setTimeHost == (struct server *)0
596 && afs_IsPrimaryCell(ts->cell)))) {
598 char msgbuf[90]; /* strlen("afs: setting clock...") + slop */
600 delta = end - tv.tv_sec; /* how many secs fast we are */
601 /* see if clock has changed enough to make it worthwhile */
602 if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) {
603 if (delta > AFS_MAXCHANGEBACK) {
604 /* setting clock too far back, just do it a little */
605 tv.tv_sec = end - AFS_MAXCHANGEBACK;
607 afs_osi_SetTime(&tv);
609 strcpy(msgbuf, "afs: setting clock back ");
610 if (delta > AFS_MAXCHANGEBACK) {
612 afs_cv2string(&tbuffer[CVBS],
614 afs_strcat(msgbuf, " seconds (of ");
616 afs_cv2string(&tbuffer[CVBS],
619 afs_strcat(msgbuf, ", via ");
620 print_internet_address(msgbuf, sa,
621 "); clock is still fast.",
625 afs_cv2string(&tbuffer[CVBS], delta));
626 afs_strcat(msgbuf, " seconds (via ");
627 print_internet_address(msgbuf, sa, ").", 0);
630 strcpy(msgbuf, "afs: setting clock ahead ");
632 afs_cv2string(&tbuffer[CVBS], -delta));
633 afs_strcat(msgbuf, " seconds (via ");
634 print_internet_address(msgbuf, sa, ").", 0);
637 afs_setTimeHost = tc->srvr->server;
640 rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
641 if (code >= 0 && (sa->sa_flags & SRVADDR_ISDOWN)
642 && (tc->srvr == sa)) {
644 print_internet_address("afs: file server ", sa, " is back up",
647 ObtainWriteLock(&afs_xserver, 244);
648 ObtainWriteLock(&afs_xsrvAddr, 245);
649 afs_MarkServerUpOrDown(sa, 0);
650 ReleaseWriteLock(&afs_xsrvAddr);
651 ReleaseWriteLock(&afs_xserver);
653 if (afs_waitForeverCount) {
654 afs_osi_Wakeup(&afs_waitForever);
660 ForceNewConnections(sa); /* multi homed clients */
665 afs_PutConn(tc, SHARED_LOCK); /* done with it now */
666 } /* Outer loop over addrs */
668 afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
670 } /*afs_CheckServers */
673 /* find a server structure given the host address */
675 afs_FindServer(afs_int32 aserver, ushort aport, afsUUID * uuidp,
682 AFS_STATCNT(afs_FindServer);
684 i = afs_uuid_hash(uuidp) % NSERVERS;
685 for (ts = afs_servers[i]; ts; ts = ts->next) {
686 if ((ts->flags & SRVR_MULTIHOMED)
688 (memcmp((char *)uuidp, (char *)&ts->sr_uuid, sizeof(*uuidp))
689 == 0) && (!ts->addr || (ts->addr->sa_portal == aport)))
694 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
695 if ((sa->sa_ip == aserver) && (sa->sa_portal == aport)) {
702 } /*afs_FindServer */
705 /* some code for creating new server structs and setting preferences follows
706 * in the next few lines...
709 #define MAXDEFRANK 60000
710 #define DEFRANK 40000
712 /* Random number generator and constants from KnuthV2 2d ed, p170 */
718 a is 0.73m should be 0.01m .. 0.99m
719 c is more or less immaterial. 1 or a is suggested.
721 NB: LOW ORDER BITS are not very random. To get small random numbers,
722 treat result as <1, with implied binary point, and multiply by
724 NB: Has to be unsigned, since shifts on signed quantities may preserve
727 /* added rxi_getaddr() to try to get as much initial randomness as
728 possible, since at least one customer reboots ALL their clients
729 simultaneously -- so osi_Time is bound to be the same on some of the
730 clients. This is probably OK, but I don't want to see too much of it.
733 #define ranstage(x) (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
738 static afs_int32 state = 0;
741 AFS_STATCNT(afs_random);
746 * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
747 * bits are in a tv_usec
749 state = (t.tv_usec & (~0 << 4)) + (rxi_getaddr() & 0xff);
750 state += (t.tv_sec & 0xff);
751 for (i = 0; i < 30; i++) {
761 /* returns int 0..14 using the high bits of a pseudo-random number instead of
762 the low bits, as the low bits are "less random" than the high ones...
763 slight roundoff error exists, an excercise for the reader.
764 need to multiply by something with lots of ones in it, so multiply by
765 8 or 16 is right out.
768 afs_randomMod15(void)
772 temp = afs_random() >> 4;
773 temp = (temp * 15) >> 28;
779 afs_randomMod127(void)
783 temp = afs_random() >> 7;
784 temp = (temp * 127) >> 25;
789 /* afs_SortOneServer()
790 * Sort all of the srvAddrs, of a server struct, by rank from low to high.
793 afs_SortOneServer(struct server *asp)
795 struct srvAddr **rootsa, *lowsa, *tsa, *lowprev;
798 for (rootsa = &(asp->addr); *rootsa; rootsa = &(lowsa->next_sa)) {
800 lowsa = *rootsa; /* lowest sa is the first one */
801 lowrank = lowsa->sa_iprank;
803 for (tsa = *rootsa; tsa->next_sa; tsa = tsa->next_sa) {
804 rank = tsa->next_sa->sa_iprank;
805 if (rank < lowrank) {
807 lowsa = tsa->next_sa;
808 lowrank = lowsa->sa_iprank;
811 if (lowprev) { /* found one lower, so rearrange them */
812 lowprev->next_sa = lowsa->next_sa;
813 lowsa->next_sa = *rootsa;
820 * Sort the pointer to servers by the server's rank (its lowest rank).
821 * It is assumed that the server already has its IP addrs sorted (the
822 * first being its lowest rank: afs_GetServer() calls afs_SortOneServer()).
825 afs_SortServers(struct server *aservers[], int count)
830 AFS_STATCNT(afs_SortServers);
832 for (i = 0; i < count; i++) {
835 for (low = i, j = i + 1; j <= count; j++) {
836 if ((!aservers[j]) || (!aservers[j]->addr))
838 if ((!aservers[low]) || (!aservers[low]->addr))
840 if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
846 aservers[i] = aservers[low];
850 } /*afs_SortServers */
852 /* afs_SetServerPrefs is rather system-dependent. It pokes around in kernel
853 data structures to determine what the local IP addresses and subnet masks
854 are in order to choose which server(s) are on the local subnet.
856 As I see it, there are several cases:
857 1. The server address is one of this host's local addresses. In this case
858 this server is to be preferred over all others.
859 2. The server is on the same subnet as one of the this host's local
860 addresses. (ie, an odd-sized subnet, not class A,B,orC)
861 3. The server is on the same net as this host (class A,B or C)
862 4. The server is on a different logical subnet or net than this host, but
863 this host is a 'metric 0 gateway' to it. Ie, two address-spaces share
865 5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
867 6. This host and the server are disjoint.
869 That is a rough order of preference. If a point-to-point link has a high
870 metric, I'm assuming that it is a very slow link, and putting it at the
871 bottom of the list (at least until RX works better over slow links). If
872 its metric is 1, I'm assuming that it's relatively fast (T1) and putting
874 It's not easy to check for case #4, so I'm ignoring it for the time being.
876 BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
877 That could be used to prefer certain servers fairly easily. Maybe some
880 NOTE: this code is very system-dependent, and very dependent on the TCP/IP
881 protocols (well, addresses that are stored in uint32s, at any rate).
884 #define IA_DST(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_dstaddr))
885 #define IA_BROAD(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
887 /* SA2ULONG takes a sockaddr_in, not a sockaddr (same thing, just cast it!) */
888 #define SA2ULONG(sa) ((sa)->sin_addr.s_addr)
893 #define PPWEIGHT 4096
898 #if defined(AFS_SUN5_ENV) && ! defined(AFS_SUN56_ENV)
899 #include <inet/common.h>
900 /* IP interface structure, one per local address */
901 typedef struct ipif_s {
902 /**/ struct ipif_s *ipif_next;
903 struct ill_s *ipif_ill; /* Back pointer to our ill */
904 long ipif_id; /* Logical unit number */
905 u_int ipif_mtu; /* Starts at ipif_ill->ill_max_frag */
906 afs_int32 ipif_local_addr; /* Local IP address for this if. */
907 afs_int32 ipif_net_mask; /* Net mask for this interface. */
908 afs_int32 ipif_broadcast_addr; /* Broadcast addr for this interface. */
909 afs_int32 ipif_pp_dst_addr; /* Point-to-point dest address. */
910 u_int ipif_flags; /* Interface flags. */
911 u_int ipif_metric; /* BSD if metric, for compatibility. */
912 u_int ipif_ire_type; /* LOCAL or LOOPBACK */
913 mblk_t *ipif_arp_down_mp; /* Allocated at time arp comes up to
914 * prevent awkward out of mem condition
917 mblk_t *ipif_saved_ire_mp; /* Allocated for each extra IRE_SUBNET/
918 * RESOLVER on this interface so that
919 * they can survive ifconfig down.
922 * The packet counts in the ipif contain the sum of the
923 * packet counts in dead IREs that were affiliated with
926 u_long ipif_fo_pkt_count; /* Forwarded thru our dead IREs */
927 u_long ipif_ib_pkt_count; /* Inbound packets for our dead IREs */
928 u_long ipif_ob_pkt_count; /* Outbound packets to our dead IREs */
930 ipif_multicast_up:1, /* We have joined the allhosts group */
934 typedef struct ipfb_s {
935 /**/ struct ipf_s *ipfb_ipf; /* List of ... */
936 kmutex_t ipfb_lock; /* Protect all ipf in list */
939 typedef struct ilm_s {
940 /**/ afs_int32 ilm_addr;
942 u_int ilm_timer; /* IGMP */
943 struct ipif_s *ilm_ipif; /* Back pointer to ipif */
944 struct ilm_s *ilm_next; /* Linked list for each ill */
947 typedef struct ill_s {
948 /**/ struct ill_s *ill_next; /* Chained in at ill_g_head. */
949 struct ill_s **ill_ptpn; /* Pointer to previous next. */
950 queue_t *ill_rq; /* Read queue. */
951 queue_t *ill_wq; /* Write queue. */
953 int ill_error; /* Error value sent up by device. */
955 ipif_t *ill_ipif; /* Interface chain for this ILL. */
956 u_int ill_ipif_up_count; /* Number of IPIFs currently up. */
957 u_int ill_max_frag; /* Max IDU. */
958 char *ill_name; /* Our name. */
959 u_int ill_name_length; /* Name length, incl. terminator. */
960 u_int ill_subnet_type; /* IRE_RESOLVER or IRE_SUBNET. */
961 u_int ill_ppa; /* Physical Point of Attachment num. */
963 int ill_sap_length; /* Including sign (for position) */
964 u_int ill_phys_addr_length; /* Excluding the sap. */
965 mblk_t *ill_frag_timer_mp; /* Reassembly timer state. */
966 ipfb_t *ill_frag_hash_tbl; /* Fragment hash list head. */
968 queue_t *ill_bind_pending_q; /* Queue waiting for DL_BIND_ACK. */
969 ipif_t *ill_ipif_pending; /* IPIF waiting for DL_BIND_ACK. */
971 /* ill_hdr_length and ill_hdr_mp will be non zero if
972 * the underlying device supports the M_DATA fastpath
976 ilm_t *ill_ilm; /* Multicast mebership for lower ill */
978 /* All non-nil cells between 'ill_first_mp_to_free' and
979 * 'ill_last_mp_to_free' are freed in ill_delete.
981 #define ill_first_mp_to_free ill_hdr_mp
982 mblk_t *ill_hdr_mp; /* Contains fastpath template */
983 mblk_t *ill_bcast_mp; /* DLPI header for broadcasts. */
984 mblk_t *ill_bind_pending; /* T_BIND_REQ awaiting completion. */
985 mblk_t *ill_resolver_mp; /* Resolver template. */
986 mblk_t *ill_attach_mp;
988 mblk_t *ill_unbind_mp;
989 mblk_t *ill_detach_mp;
990 #define ill_last_mp_to_free ill_detach_mp
992 u_int ill_frag_timer_running:1, ill_needs_attach:1, ill_is_ptp:1,
993 ill_priv_stream:1, ill_unbind_pending:1, ill_pad_to_bit_31:27;
994 MI_HRT_DCL(ill_rtime)
999 #ifdef AFS_USERSPACE_IP_ADDR
1001 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1004 * The IP addresses and ranks are determined by afsd (in user space) and
1005 * passed into the kernel at startup time through the AFSOP_ADVISEADDR
1006 * system call. These are stored in the data structure
1007 * called 'afs_cb_interface'.
1009 * struct srvAddr *sa; remote server
1010 * afs_int32 addr; one of my local addr in net order
1011 * afs_uint32 subnetmask; subnet mask of local addr in net order
1015 afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr,
1016 afs_uint32 subnetmask)
1018 afs_uint32 myAddr, myNet, mySubnet, netMask;
1019 afs_uint32 serverAddr;
1021 myAddr = ntohl(addr); /* one of my IP addr in host order */
1022 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1023 subnetmask = ntohl(subnetmask); /* subnet mask in host order */
1025 if (IN_CLASSA(myAddr))
1026 netMask = IN_CLASSA_NET;
1027 else if (IN_CLASSB(myAddr))
1028 netMask = IN_CLASSB_NET;
1029 else if (IN_CLASSC(myAddr))
1030 netMask = IN_CLASSC_NET;
1034 myNet = myAddr & netMask;
1035 mySubnet = myAddr & subnetmask;
1037 if ((serverAddr & netMask) == myNet) {
1038 if ((serverAddr & subnetmask) == mySubnet) {
1039 if (serverAddr == myAddr) { /* same machine */
1040 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1041 } else { /* same subnet */
1042 sa->sa_iprank = afs_min(sa->sa_iprank, HI);
1044 } else { /* same net */
1045 sa->sa_iprank = afs_min(sa->sa_iprank, MED);
1049 #else /* AFS_USERSPACE_IP_ADDR */
1050 #if (! defined(AFS_SUN5_ENV)) && !defined(AFS_DARWIN60_ENV) && defined(USEIFADDR)
1052 afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
1054 struct sockaddr_in *sin;
1057 if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
1058 if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
1060 if (SA2ULONG(sin) == ntohl(sa->sa_ip)) { /* ie, ME!!! */
1061 sa->sa_iprank = TOPR;
1063 t = HI + ifa->ia_ifp->if_metric; /* case #2 */
1064 if (sa->sa_iprank > t)
1068 t = MED + ifa->ia_ifp->if_metric; /* case #3 */
1069 if (sa->sa_iprank > t)
1073 #ifdef IFF_POINTTOPOINT
1074 /* check for case #4 -- point-to-point link */
1075 if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
1076 && (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
1077 if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1080 t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
1081 if (sa->sa_iprank > t)
1084 #endif /* IFF_POINTTOPOINT */
1086 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1087 #if defined(AFS_DARWIN60_ENV) && defined(USEIFADDR)
1089 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1092 afsi_SetServerIPRank(sa, ifa)
1096 struct sockaddr_in *sin;
1099 afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
1100 afs_uint32 serverAddr;
1102 if (ifa->ifa_addr->sa_family != AF_INET)
1104 sin = (struct sockaddr_in *)ifa->ifa_addr;
1105 myAddr = ntohl(sin->sin_addr.s_addr); /* one of my IP addr in host order */
1106 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1107 sin = (struct sockaddr_in *)ifa->ifa_netmask;
1108 subnetmask = ntohl(sin->sin_addr.s_addr); /* subnet mask in host order */
1109 sin = (struct sockaddr_in *)ifa->ifa_dstaddr;
1111 myDstaddr = sin->sin_addr.s_addr;
1113 if (IN_CLASSA(myAddr))
1114 netMask = IN_CLASSA_NET;
1115 else if (IN_CLASSB(myAddr))
1116 netMask = IN_CLASSB_NET;
1117 else if (IN_CLASSC(myAddr))
1118 netMask = IN_CLASSC_NET;
1122 myNet = myAddr & netMask;
1123 mySubnet = myAddr & subnetmask;
1125 if ((serverAddr & netMask) == myNet) {
1126 if ((serverAddr & subnetmask) == mySubnet) {
1127 if (serverAddr == myAddr) { /* same machine */
1128 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1129 } else { /* same subnet */
1130 sa->sa_iprank = afs_min(sa->sa_iprank, HI + ifa->ifa_metric);
1132 } else { /* same net */
1133 sa->sa_iprank = afs_min(sa->sa_iprank, MED + ifa->ifa_metric);
1136 #ifdef IFF_POINTTOPOINT
1137 /* check for case #4 -- point-to-point link */
1138 if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
1139 && (myDstaddr == serverAddr))
1141 if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1144 t = MED + (PPWEIGHT << ifa->->ifa_metric);
1145 if (sa->sa_iprank > t)
1148 #endif /* IFF_POINTTOPOINT */
1150 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1151 #endif /* else AFS_USERSPACE_IP_ADDR */
1153 #ifdef AFS_SGI62_ENV
1156 afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1158 afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
1159 return 0; /* Never match, so we enumerate everyone */
1161 #endif /* AFS_SGI62_ENV */
1162 static int afs_SetServerPrefs(struct srvAddr *sa) {
1163 #if defined(AFS_USERSPACE_IP_ADDR)
1167 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1168 afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1169 afs_cb_interface.subnetmask[i]);
1171 #else /* AFS_USERSPACE_IP_ADDR */
1172 #if defined(AFS_SUN5_ENV)
1173 extern struct ill_s *ill_g_headp;
1176 int subnet, subnetmask, net, netmask;
1177 long *addr = (long *)ill_g_headp;
1181 for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
1182 ill = ill->ill_next) {
1183 #ifdef AFS_SUN58_ENV
1184 /* Make sure this is an IPv4 ILL */
1188 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
1189 subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1190 subnetmask = ipif->ipif_net_mask;
1192 * Generate the local net using the local address and
1193 * whate we know about Class A, B and C networks.
1195 if (IN_CLASSA(ipif->ipif_local_addr)) {
1196 netmask = IN_CLASSA_NET;
1197 } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1198 netmask = IN_CLASSB_NET;
1199 } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1200 netmask = IN_CLASSC_NET;
1204 net = ipif->ipif_local_addr & netmask;
1207 if (ipif->ipif_local_addr != 0x7f000001) { /* ignore loopback */
1211 *addrp++ = ipif->ipif_local_addr;
1216 /* XXXXXX Do the individual ip ranking below XXXXX */
1217 if ((sa->sa_ip & netmask) == net) {
1218 if ((sa->sa_ip & subnetmask) == subnet) {
1219 if (ipif->ipif_local_addr == sa->sa_ip) { /* ie, ME! */
1220 sa->sa_iprank = TOPR;
1222 sa->sa_iprank = HI + ipif->ipif_metric; /* case #2 */
1225 sa->sa_iprank = MED + ipif->ipif_metric; /* case #3 */
1228 sa->sa_iprank = LO + ipif->ipif_metric; /* case #4 */
1230 /* check for case #5 -- point-to-point link */
1231 if ((ipif->ipif_flags & IFF_POINTOPOINT)
1232 && (ipif->ipif_pp_dst_addr == sa->sa_ip)) {
1234 if (ipif->ipif_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1235 sa->sa_iprank = MAXDEFRANK;
1237 sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1244 struct ifnet *ifn = NULL;
1245 struct in_ifaddr *ifad = (struct in_ifaddr *)0;
1246 struct sockaddr_in *sin;
1249 #ifdef notdef /* clean up, remove this */
1250 for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
1251 for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next) {
1252 if ((IFADDR2SA(ifad)->sa_family == AF_INET)
1253 && !(ifn->if_flags & IFF_LOOPBACK)) {
1258 ((struct sockaddr_in *)IFADDR2SA(ifad))->sin_addr.
1267 ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1269 if (ifn) { /* local, more or less */
1271 if (ifn->if_flags & IFF_LOOPBACK) {
1272 sa->sa_iprank = TOPR;
1275 #endif /* IFF_LOOPBACK */
1276 sin = (struct sockaddr_in *)IA_SIN(ifad);
1277 if (SA2ULONG(sin) == sa->sa_ip) {
1278 sa->sa_iprank = TOPR;
1281 #ifdef IFF_BROADCAST
1282 if (ifn->if_flags & IFF_BROADCAST) {
1283 if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1288 #endif /* IFF_BROADCAST */
1289 #ifdef IFF_POINTOPOINT
1290 if (ifn->if_flags & IFF_POINTOPOINT) {
1291 if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1292 if (ifn->if_metric > 4) {
1296 sa->sa_iprank = ifn->if_metric;
1299 #endif /* IFF_POINTOPOINT */
1300 sa->sa_iprank += MED + ifn->if_metric; /* couldn't find anything better */
1302 #else /* USEIFADDR */
1306 #ifdef AFS_SGI62_ENV
1307 (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1308 (caddr_t) sa, NULL);
1309 #elif defined(AFS_DARWIN60_ENV)
1313 TAILQ_FOREACH(ifn, &ifnet, if_link) {
1314 TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
1315 afsi_SetServerIPRank(sa, ifa);
1317 #elif defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1319 struct in_ifaddr *ifa;
1320 TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
1321 afsi_SetServerIPRank(sa, ifa);
1323 #elif defined(AFS_OBSD_ENV)
1325 extern struct in_ifaddrhead in_ifaddr;
1326 struct in_ifaddr *ifa;
1327 for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1328 afsi_SetServerIPRank(sa, ifa);
1332 struct in_ifaddr *ifa;
1333 for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
1334 afsi_SetServerIPRank(sa, ifa);
1338 #endif /* USEIFADDR */
1339 #endif /* AFS_SUN5_ENV */
1340 #endif /* else AFS_USERSPACE_IP_ADDR */
1342 sa->sa_iprank += afs_randomMod15();
1345 } /* afs_SetServerPrefs */
1353 /* afs_FlushServer()
1354 * The addresses on this server struct has changed in some way and will
1355 * clean up all other structures that may reference it.
1356 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1358 void afs_FlushServer(struct server *srvp) {
1360 struct server *ts, **pts;
1362 /* Find any volumes residing on this server and flush their state */
1363 afs_ResetVolumes(srvp);
1365 /* Flush all callbacks in the all vcaches for this specific server */
1366 afs_FlushServerCBs(srvp);
1368 /* Remove all the callbacks structs */
1370 struct afs_cbr *cb, *cbnext;
1372 MObtainWriteLock(&afs_xvcb, 300);
1373 for (cb = srvp->cbrs; cb; cb = cbnext) {
1376 } srvp->cbrs = (struct afs_cbr *)0;
1377 ReleaseWriteLock(&afs_xvcb);
1380 /* If no more srvAddr structs hanging off of this server struct,
1384 /* Remove the server structure from the cell list - if there */
1385 afs_RemoveCellEntry(srvp);
1387 /* Remove from the afs_servers hash chain */
1388 for (i = 0; i < NSERVERS; i++) {
1389 for (pts = &(afs_servers[i]), ts = *pts; ts;
1390 pts = &(ts->next), ts = *pts) {
1398 *pts = ts->next; /* Found it. Remove it */
1399 afs_osi_Free(ts, sizeof(struct server)); /* Free it */
1405 /* afs_RemoveSrvAddr()
1406 * This removes a SrvAddr structure from its server structure.
1407 * The srvAddr struct is not free'd because it connections may still
1408 * be open to it. It is up to the calling process to make sure it
1409 * remains connected to a server struct.
1410 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1411 * It is not removed from the afs_srvAddrs hash chain.
1413 void afs_RemoveSrvAddr(struct srvAddr *sap) {
1414 struct srvAddr **psa, *sa;
1421 /* Find the srvAddr in the server's list and remove it */
1422 for (psa = &(srv->addr), sa = *psa; sa; psa = &(sa->next_sa), sa = *psa) {
1430 /* Flush the server struct since it's IP address has changed */
1431 afs_FlushServer(srv);
1436 * Return an updated and properly initialized server structure
1437 * corresponding to the server ID, cell, and port specified.
1438 * If one does not exist, then one will be created.
1439 * aserver and aport must be in NET byte order.
1441 struct server *afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers,
1442 afs_int32 acell, u_short aport,
1443 afs_int32 locktype, afsUUID * uuidp,
1444 afs_int32 addr_uniquifier) {
1445 struct server *oldts = 0, *ts, *newts, *orphts = 0;
1446 struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1448 afs_int32 iphash, k, srvcount = 0;
1449 unsigned int srvhash;
1451 AFS_STATCNT(afs_GetServer);
1453 ObtainSharedLock(&afs_xserver, 13);
1455 /* Check if the server struct exists and is up to date */
1458 panic("afs_GetServer: incorect count of servers");
1459 ObtainReadLock(&afs_xsrvAddr);
1460 ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1461 ReleaseReadLock(&afs_xsrvAddr);
1462 if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1463 /* Found a server struct that is not multihomed and has the
1464 * IP address associated with it. A correct match.
1466 ReleaseSharedLock(&afs_xserver);
1471 panic("afs_GetServer: incorrect count of servers");
1472 ts = afs_FindServer(0, aport, uuidp, locktype);
1473 if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1474 /* Found a server struct that is multihomed and same
1475 * uniqufier (same IP addrs). The above if statement is the
1476 * same as in InstallUVolumeEntry().
1478 ReleaseSharedLock(&afs_xserver);
1482 oldts = ts; /* Will reuse if same uuid */
1485 UpgradeSToWLock(&afs_xserver, 36);
1486 ObtainWriteLock(&afs_xsrvAddr, 116);
1488 srvcount = afs_totalServers;
1490 /* Reuse/allocate a new server structure */
1494 newts = (struct server *)afs_osi_Alloc(sizeof(struct server));
1496 panic("malloc of server struct");
1498 memset((char *)newts, 0, sizeof(struct server));
1500 /* Add the server struct to the afs_servers[] hash chain */
1502 (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
1503 newts->next = afs_servers[srvhash];
1504 afs_servers[srvhash] = newts;
1507 /* Initialize the server structure */
1508 if (uuidp) { /* Multihomed */
1509 newts->sr_uuid = *uuidp;
1510 newts->sr_addr_uniquifier = addr_uniquifier;
1511 newts->flags |= SRVR_MULTIHOMED;
1514 newts->cell = afs_GetCell(acell, 0);
1516 fsport = (newts->cell ? newts->cell->fsport : AFS_FSPORT);
1518 /* For each IP address we are registering */
1519 for (k = 0; k < nservers; k++) {
1520 iphash = SHash(aserverp[k]);
1522 /* Check if the srvAddr structure already exists. If so, remove
1523 * it from its server structure and add it to the new one.
1525 for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
1526 if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
1529 if (oldsa && (oldsa->server != newts)) {
1530 afs_RemoveSrvAddr(oldsa); /* Remove from its server struct */
1531 oldsa->next_sa = newts->addr; /* Add to the new server struct */
1532 newts->addr = oldsa;
1535 /* Reuse/allocate a new srvAddr structure */
1539 newsa = (struct srvAddr *)afs_osi_Alloc(sizeof(struct srvAddr));
1541 panic("malloc of srvAddr struct");
1542 afs_totalSrvAddrs++;
1543 memset((char *)newsa, 0, sizeof(struct srvAddr));
1545 /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1546 newsa->next_bkt = afs_srvAddrs[iphash];
1547 afs_srvAddrs[iphash] = newsa;
1549 /* Hang off of the server structure */
1550 newsa->next_sa = newts->addr;
1551 newts->addr = newsa;
1553 /* Initialize the srvAddr Structure */
1554 newsa->sa_ip = aserverp[k];
1555 newsa->sa_portal = aport;
1558 /* Update the srvAddr Structure */
1559 newsa->server = newts;
1560 if (newts->flags & SRVR_ISDOWN)
1561 newsa->sa_flags |= SRVADDR_ISDOWN;
1563 newsa->sa_flags |= SRVADDR_MH;
1565 newsa->sa_flags &= ~SRVADDR_MH;
1567 /* Compute preference values and resort */
1568 if (!newsa->sa_iprank) {
1569 if (aport == fsport) {
1570 afs_SetServerPrefs(newsa); /* new fileserver rank */
1572 newsa->sa_iprank = 10000 + afs_randomMod127(); /* new vlserver rank */
1576 afs_SortOneServer(newts); /* Sort by rank */
1578 /* If we reused the server struct, remove any of its srvAddr
1579 * structs that will no longer be associated with this server.
1581 if (oldts) { /* reused the server struct */
1582 for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
1583 nextsa = orphsa->next_sa;
1584 for (k = 0; k < nservers; k++) {
1585 if (orphsa->sa_ip == aserverp[k])
1586 break; /* belongs */
1589 continue; /* belongs */
1591 /* Have a srvAddr struct. Now get a server struct (if not already) */
1594 (struct server *)afs_osi_Alloc(sizeof(struct server));
1596 panic("malloc of lo server struct");
1597 memset((char *)orphts, 0, sizeof(struct server));
1600 /* Add the orphaned server to the afs_servers[] hash chain.
1601 * Its iphash does not matter since we never look up the server
1602 * in the afs_servers table by its ip address (only by uuid -
1603 * which this has none).
1605 iphash = SHash(aserverp[k]);
1606 orphts->next = afs_servers[iphash];
1607 afs_servers[iphash] = orphts;
1610 orphts->cell = afs_GetCell(acell, 0);
1613 /* Hang the srvAddr struct off of the server structure. The server
1614 * may have multiple srvAddrs, but it won't be marked multihomed.
1616 afs_RemoveSrvAddr(orphsa); /* remove */
1617 orphsa->next_sa = orphts->addr; /* hang off server struct */
1618 orphts->addr = orphsa;
1619 orphsa->server = orphts;
1620 orphsa->sa_flags |= SRVADDR_NOUSE; /* flag indicating not in use */
1621 orphsa->sa_flags &= ~SRVADDR_MH; /* Not multihomed */
1625 srvcount = afs_totalServers - srvcount; /* # servers added and removed */
1627 struct afs_stats_SrvUpDownInfo *upDownP;
1628 /* With the introduction of this new record, we need to adjust the
1629 * proper individual & global server up/down info.
1631 upDownP = GetUpDownStats(newts);
1632 upDownP->numTtlRecords += srvcount;
1633 afs_stats_cmperf.srvRecords += srvcount;
1634 if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
1635 afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
1638 ReleaseWriteLock(&afs_xsrvAddr);
1639 ReleaseWriteLock(&afs_xserver);
1641 } /* afs_GetServer */
1643 void afs_ActivateServer(struct srvAddr *sap) {
1644 osi_timeval_t currTime; /*Filled with current time */
1645 osi_timeval_t *currTimeP; /*Ptr to above */
1646 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record */
1647 struct server *aserver = sap->server;
1649 if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
1651 * This server record has not yet been activated. Go for it,
1652 * recording its ``birth''.
1654 aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
1655 currTimeP = &currTime;
1656 osi_GetuTime(currTimeP);
1657 aserver->activationTime = currTime.tv_sec;
1658 upDownP = GetUpDownStats(aserver);
1659 if (aserver->flags & SRVR_ISDOWN) {
1660 upDownP->numDownRecords++;
1662 upDownP->numUpRecords++;
1663 upDownP->numRecordsNeverDown++;