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 */
60 #include "rx/rx_multi.h"
62 #if defined(AFS_SUN56_ENV)
64 #include <inet/common.h>
65 #if defined(AFS_SUN58_ENV)
66 # include <netinet/ip6.h>
67 # define ipif_local_addr ipif_lcl_addr
68 # ifndef V4_PART_OF_V6
69 # define V4_PART_OF_V6(v6) v6.s6_addr32[3]
75 /* Exported variables */
76 afs_rwlock_t afs_xserver; /* allocation lock for servers */
77 struct server *afs_setTimeHost = 0; /* last host we used for time */
78 struct server *afs_servers[NSERVERS]; /* Hashed by server`s uuid & 1st ip */
79 afs_rwlock_t afs_xsrvAddr; /* allocation lock for srvAddrs */
80 struct srvAddr *afs_srvAddrs[NSERVERS]; /* Hashed by server's ip */
83 /* debugging aids - number of alloc'd server and srvAddr structs. */
84 int afs_reuseServers = 0;
85 int afs_reuseSrvAddrs = 0;
86 int afs_totalServers = 0;
87 int afs_totalSrvAddrs = 0;
91 static struct afs_stats_SrvUpDownInfo *
92 GetUpDownStats(struct server *srv)
94 struct afs_stats_SrvUpDownInfo *upDownP;
95 u_short fsport = AFS_FSPORT;
98 fsport = srv->cell->fsport;
100 if (srv->addr->sa_portal == fsport)
101 upDownP = afs_stats_cmperf.fs_UpDown;
103 upDownP = afs_stats_cmperf.vl_UpDown;
105 if (srv->cell && afs_IsPrimaryCell(srv->cell))
106 return &upDownP[AFS_STATS_UPDOWN_IDX_SAME_CELL];
108 return &upDownP[AFS_STATS_UPDOWN_IDX_DIFF_CELL];
112 /*------------------------------------------------------------------------
113 * afs_MarkServerUpOrDown
116 * Mark the given server up or down, and track its uptime stats.
119 * a_serverP : Ptr to server record to fiddle with.
120 * a_isDown : Is the server is to be marked down?
126 * The CM server structures must be write-locked.
130 *------------------------------------------------------------------------*/
133 afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
135 register struct server *a_serverP = sa->server;
136 register struct srvAddr *sap;
137 osi_timeval_t currTime, *currTimeP; /*Current time */
138 afs_int32 downTime; /*Computed downtime, in seconds */
139 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record */
142 * If the server record is marked the same as the new status we've
143 * been fed, then there isn't much to be done.
145 if ((a_isDown && (sa->sa_flags & SRVADDR_ISDOWN))
146 || (!a_isDown && !(sa->sa_flags & SRVADDR_ISDOWN)))
150 sa->sa_flags |= SRVADDR_ISDOWN;
151 for (sap = a_serverP->addr; sap; sap = sap->next_sa) {
152 if (!(sap->sa_flags & SRVADDR_ISDOWN)) {
153 /* Not all ips are up so don't bother with the
154 * server's up/down stats */
159 * All ips are down we treat the whole server down
161 a_serverP->flags |= SRVR_ISDOWN;
163 * If this was our time server, search for another time server
165 if (a_serverP == afs_setTimeHost)
168 sa->sa_flags &= ~SRVADDR_ISDOWN;
169 /* If any ips are up, the server is also marked up */
170 a_serverP->flags &= ~SRVR_ISDOWN;
171 for (sap = a_serverP->addr; sap; sap = sap->next_sa) {
172 if (sap->sa_flags & SRVADDR_ISDOWN) {
173 /* Not all ips are up so don't bother with the
174 * server's up/down stats */
181 * Compute the current time and which overall stats record is to be
182 * updated; we'll need them one way or another.
184 currTimeP = &currTime;
185 osi_GetuTime(currTimeP);
187 upDownP = GetUpDownStats(a_serverP);
191 * Server going up -> down; remember the beginning of this
194 a_serverP->lastDowntimeStart = currTime.tv_sec;
196 (upDownP->numDownRecords)++;
197 (upDownP->numUpRecords)--;
198 } /*Server being marked down */
201 * Server going down -> up; remember everything about this
202 * newly-completed downtime incident.
204 downTime = currTime.tv_sec - a_serverP->lastDowntimeStart;
205 (a_serverP->numDowntimeIncidents)++;
206 a_serverP->sumOfDowntimes += downTime;
208 (upDownP->numUpRecords)++;
209 (upDownP->numDownRecords)--;
210 (upDownP->numDowntimeIncidents)++;
211 if (a_serverP->numDowntimeIncidents == 1)
212 (upDownP->numRecordsNeverDown)--;
213 upDownP->sumOfDowntimes += downTime;
214 if ((upDownP->shortestDowntime == 0)
215 || (downTime < upDownP->shortestDowntime))
216 upDownP->shortestDowntime = downTime;
217 if ((upDownP->longestDowntime == 0)
218 || (downTime > upDownP->longestDowntime))
219 upDownP->longestDowntime = downTime;
222 if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET0)
223 (upDownP->downDurations[0])++;
224 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET1)
225 (upDownP->downDurations[1])++;
226 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET2)
227 (upDownP->downDurations[2])++;
228 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET3)
229 (upDownP->downDurations[3])++;
230 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET4)
231 (upDownP->downDurations[4])++;
232 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET5)
233 (upDownP->downDurations[5])++;
235 (upDownP->downDurations[6])++;
237 } /*Server being marked up */
239 } /*MarkServerUpOrDown */
243 afs_ServerDown(struct srvAddr *sa)
245 register struct server *aserver = sa->server;
247 AFS_STATCNT(ServerDown);
248 if (aserver->flags & SRVR_ISDOWN || sa->sa_flags & SRVADDR_ISDOWN)
250 afs_MarkServerUpOrDown(sa, SRVR_ISDOWN);
251 if (sa->sa_portal == aserver->cell->vlport)
252 print_internet_address
253 ("afs: Lost contact with volume location server ", sa, "", 1);
255 print_internet_address("afs: Lost contact with file server ", sa, "",
261 /* return true if we have any callback promises from this server */
263 afs_HaveCallBacksFrom(struct server *aserver)
265 register afs_int32 now;
267 register struct vcache *tvc;
269 AFS_STATCNT(HaveCallBacksFrom);
270 now = osi_Time(); /* for checking for expired callbacks */
271 for (i = 0; i < VCSIZE; i++) { /* for all guys in the hash table */
272 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
274 * Check to see if this entry has an unexpired callback promise
275 * from the required host
277 if (aserver == tvc->callback && tvc->cbExpires >= now
278 && ((tvc->states & CRO) == 0))
284 } /*HaveCallBacksFrom */
288 CheckVLServer(register struct srvAddr *sa, struct vrequest *areq)
290 register struct server *aserver = sa->server;
291 register struct conn *tc;
292 register afs_int32 code;
294 AFS_STATCNT(CheckVLServer);
295 /* Ping dead servers to see if they're back */
296 if (!((aserver->flags & SRVR_ISDOWN) || (sa->sa_flags & SRVADDR_ISDOWN))
297 || (aserver->flags & SRVR_ISGONE))
300 return; /* can't do much */
302 tc = afs_ConnByHost(aserver, aserver->cell->vlport,
303 aserver->cell->cellNum, areq, 1, SHARED_LOCK);
306 rx_SetConnDeadTime(tc->id, 3);
309 code = VL_ProbeServer(tc->id);
311 rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
312 afs_PutConn(tc, SHARED_LOCK);
314 * If probe worked, or probe call not yet defined (for compatibility
315 * with old vlsevers), then we treat this server as running again
317 if (code == 0 || (code <= -450 && code >= -470)) {
318 if (tc->srvr == sa) {
319 afs_MarkServerUpOrDown(sa, 0);
320 print_internet_address("afs: volume location server ", sa,
328 #ifndef AFS_MINCHANGE /* So that some can increase it in param.h */
329 #define AFS_MINCHANGE 2 /* min change we'll bother with */
331 #ifndef AFS_MAXCHANGEBACK
332 #define AFS_MAXCHANGEBACK 10 /* max seconds we'll set a clock back at once */
336 /*------------------------------------------------------------------------
337 * EXPORTED afs_CountServers
340 * Originally meant to count the number of servers and determining
341 * up/down info, this routine will now simply sum up all of the
342 * server record ages. All other up/down information is kept on the
352 * This routine locks afs_xserver for write for the duration.
355 * Set CM perf stats field sumOfRecordAges for all server record
357 *------------------------------------------------------------------------*/
360 afs_CountServers(void)
362 int currIdx; /*Curr idx into srv table */
363 struct server *currSrvP; /*Ptr to curr server record */
364 afs_int32 currChainLen; /*Length of curr hash chain */
365 osi_timeval_t currTime; /*Current time */
366 osi_timeval_t *currTimeP; /*Ptr to above */
367 afs_int32 srvRecordAge; /*Age of server record, in secs */
368 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to current up/down
369 * info being manipulated */
372 * Write-lock the server table so we don't get any interference.
374 ObtainReadLock(&afs_xserver);
377 * Iterate over each hash index in the server table, walking down each
378 * chain and tallying what we haven't computed from the records there on
379 * the fly. First, though, initialize the tallies that will change.
381 afs_stats_cmperf.srvMaxChainLength = 0;
383 afs_stats_cmperf.fs_UpDown[0].sumOfRecordAges = 0;
384 afs_stats_cmperf.fs_UpDown[0].ageOfYoungestRecord = 0;
385 afs_stats_cmperf.fs_UpDown[0].ageOfOldestRecord = 0;
386 memset((char *)afs_stats_cmperf.fs_UpDown[0].downIncidents, 0,
387 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
389 afs_stats_cmperf.fs_UpDown[1].sumOfRecordAges = 0;
390 afs_stats_cmperf.fs_UpDown[1].ageOfYoungestRecord = 0;
391 afs_stats_cmperf.fs_UpDown[1].ageOfOldestRecord = 0;
392 memset((char *)afs_stats_cmperf.fs_UpDown[1].downIncidents, 0,
393 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
395 afs_stats_cmperf.vl_UpDown[0].sumOfRecordAges = 0;
396 afs_stats_cmperf.vl_UpDown[0].ageOfYoungestRecord = 0;
397 afs_stats_cmperf.vl_UpDown[0].ageOfOldestRecord = 0;
398 memset((char *)afs_stats_cmperf.vl_UpDown[0].downIncidents, 0,
399 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
401 afs_stats_cmperf.vl_UpDown[1].sumOfRecordAges = 0;
402 afs_stats_cmperf.vl_UpDown[1].ageOfYoungestRecord = 0;
403 afs_stats_cmperf.vl_UpDown[1].ageOfOldestRecord = 0;
404 memset((char *)afs_stats_cmperf.vl_UpDown[1].downIncidents, 0,
405 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
408 * Compute the current time, used to figure out server record ages.
410 currTimeP = &currTime;
411 osi_GetuTime(currTimeP);
414 * Sweep the server hash table, tallying all we need to know.
416 for (currIdx = 0; currIdx < NSERVERS; currIdx++) {
418 for (currSrvP = afs_servers[currIdx]; currSrvP;
419 currSrvP = currSrvP->next) {
421 * Bump the current chain length.
426 * Any further tallying for this record will only be done if it has
429 if ((currSrvP->flags & AFS_SERVER_FLAG_ACTIVATED)
430 && currSrvP->addr && currSrvP->cell) {
433 * Compute the current server record's age, then remember it
434 * in the appropriate places.
436 srvRecordAge = currTime.tv_sec - currSrvP->activationTime;
437 upDownP = GetUpDownStats(currSrvP);
438 upDownP->sumOfRecordAges += srvRecordAge;
439 if ((upDownP->ageOfYoungestRecord == 0)
440 || (srvRecordAge < upDownP->ageOfYoungestRecord))
441 upDownP->ageOfYoungestRecord = srvRecordAge;
442 if ((upDownP->ageOfOldestRecord == 0)
443 || (srvRecordAge > upDownP->ageOfOldestRecord))
444 upDownP->ageOfOldestRecord = srvRecordAge;
446 if (currSrvP->numDowntimeIncidents <=
447 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET0)
448 (upDownP->downIncidents[0])++;
449 else if (currSrvP->numDowntimeIncidents <=
450 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET1)
451 (upDownP->downIncidents[1])++;
452 else if (currSrvP->numDowntimeIncidents <=
453 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET2)
454 (upDownP->downIncidents[2])++;
455 else if (currSrvP->numDowntimeIncidents <=
456 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET3)
457 (upDownP->downIncidents[3])++;
458 else if (currSrvP->numDowntimeIncidents <=
459 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET4)
460 (upDownP->downIncidents[4])++;
462 (upDownP->downIncidents[5])++;
465 } /*Current server has been active */
466 } /*Walk this chain */
469 * Before advancing to the next chain, remember facts about this one.
471 if (currChainLen > afs_stats_cmperf.srvMaxChainLength) {
473 * We beat out the former champion (which was initially set to 0
474 * here). Mark down the new winner, and also remember if it's an
477 afs_stats_cmperf.srvMaxChainLength = currChainLen;
478 if (currChainLen > afs_stats_cmperf.srvMaxChainLengthHWM)
479 afs_stats_cmperf.srvMaxChainLengthHWM = currChainLen;
480 } /*Update chain length maximum */
481 } /*For each hash chain */
484 * We're done. Unlock the server table before returning to our caller.
486 ReleaseReadLock(&afs_xserver);
488 } /*afs_CountServers */
491 /* check down servers (if adown), or running servers (if !adown) */
493 afs_CheckServers(int adown, struct cell *acellp)
495 struct vrequest treq;
501 afs_int32 start, end = 0, delta;
506 struct srvAddr **addrs;
509 struct rx_connection **rxconns;
510 afs_int32 *conntimer, *deltas, *results;
512 AFS_STATCNT(afs_CheckServers);
514 conns = (struct conn **)0;
515 rxconns = (struct rx_connection **) 0;
519 if ((code = afs_InitReq(&treq, afs_osi_credp)))
521 ObtainReadLock(&afs_xserver); /* Necessary? */
522 ObtainReadLock(&afs_xsrvAddr);
525 for (i = 0; i < NSERVERS; i++) {
526 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
531 addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
533 for (i = 0; i < NSERVERS; i++) {
534 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
535 if (j >= srvAddrCount)
541 ReleaseReadLock(&afs_xsrvAddr);
542 ReleaseReadLock(&afs_xserver);
544 conns = (struct conn **)afs_osi_Alloc(j * sizeof(struct conn *));
545 rxconns = (struct rx_connection **)afs_osi_Alloc(j * sizeof(struct rx_connection *));
546 conntimer = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
547 deltas = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
548 results = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
550 for (i = 0; i < j; i++) {
557 /* See if a cell to check was specified. If it is spec'd and not
558 * this server's cell, just skip the server.
560 if (acellp && acellp != ts->cell)
563 if ((!adown && (sa->sa_flags & SRVADDR_ISDOWN))
564 || (adown && !(sa->sa_flags & SRVADDR_ISDOWN)))
567 /* check vlserver with special code */
568 if (sa->sa_portal == AFS_VLPORT) {
569 CheckVLServer(sa, &treq);
573 if (!ts->cell) /* not really an active server, anyway, it must */
574 continue; /* have just been added by setsprefs */
576 /* get a connection, even if host is down; bumps conn ref count */
577 tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
578 tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
579 1 /*force */ , 1 /*create */ , SHARED_LOCK);
580 afs_PutUser(tu, SHARED_LOCK);
584 if ((sa->sa_flags & SRVADDR_ISDOWN) || afs_HaveCallBacksFrom(sa->server)
585 || (tc->srvr->server == afs_setTimeHost)) {
587 rxconns[nconns]=tc->id;
588 if (sa->sa_flags & SRVADDR_ISDOWN) {
589 rx_SetConnDeadTime(tc->id, 3);
596 } /* Outer loop over addrs */
598 start = osi_Time(); /* time the gettimeofday call */
600 multi_Rx(rxconns,nconns)
602 tv.tv_sec = tv.tv_usec = 0;
603 multi_RXAFS_GetTime(&tv.tv_sec, &tv.tv_usec);
606 if (conntimer[multi_i] == 0)
607 rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
609 results[multi_i]=multi_error;
610 if ((start == end) && !multi_error)
611 deltas[multi_i] = end - tv.tv_sec;
616 for(i=0;i<nconns;i++){
620 if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) && (tc->srvr == sa)) {
622 print_internet_address("afs: file server ", sa, " is back up", 2);
624 ObtainWriteLock(&afs_xserver, 244);
625 ObtainWriteLock(&afs_xsrvAddr, 245);
626 afs_MarkServerUpOrDown(sa, 0);
627 ReleaseWriteLock(&afs_xsrvAddr);
628 ReleaseWriteLock(&afs_xserver);
630 if (afs_waitForeverCount) {
631 afs_osi_Wakeup(&afs_waitForever);
634 if (results[i] < 0) {
637 ForceNewConnections(sa); /* multi homed clients */
643 * If we're supposed to set the time, and the call worked
644 * quickly (same second response) and this is the host we
645 * use for the time and the time is really different, then
646 * really set the time
648 if (afs_setTime != 0) {
649 for (i=0; i<nconns; i++) {
654 if ((tc->srvr->server == afs_setTimeHost ||
655 /* Sync only to a server in the local cell */
656 (afs_setTimeHost == (struct server *)0 &&
657 afs_IsPrimaryCell(sa->server->cell)))) {
659 char msgbuf[90]; /* strlen("afs: setting clock...") + slop */
660 delta = end - tv.tv_sec; /* how many secs fast we are */
662 afs_setTimeHost = tc->srvr->server;
663 /* see if clock has changed enough to make it worthwhile */
664 if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) {
666 if (delta > AFS_MAXCHANGEBACK) {
667 /* setting clock too far back, just do it a little */
668 tv.tv_sec = end - AFS_MAXCHANGEBACK;
670 tv.tv_sec = end - delta;
672 afs_osi_SetTime(&tv);
674 strcpy(msgbuf, "afs: setting clock back ");
675 if (delta > AFS_MAXCHANGEBACK) {
677 afs_cv2string(&tbuffer[CVBS],
679 afs_strcat(msgbuf, " seconds (of ");
681 afs_cv2string(&tbuffer[CVBS],
684 afs_strcat(msgbuf, ", via ");
685 print_internet_address(msgbuf, sa,
686 "); clock is still fast.",
690 afs_cv2string(&tbuffer[CVBS], delta));
691 afs_strcat(msgbuf, " seconds (via ");
692 print_internet_address(msgbuf, sa, ").", 0);
695 strcpy(msgbuf, "afs: setting clock ahead ");
697 afs_cv2string(&tbuffer[CVBS], -delta));
698 afs_strcat(msgbuf, " seconds (via ");
699 print_internet_address(msgbuf, sa, ").", 0);
701 /* We're only going to set it once; why bother looping? */
707 for (i = 0; i < nconns; i++) {
708 afs_PutConn(conns[i], SHARED_LOCK); /* done with it now */
711 afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
712 afs_osi_Free(conns, j * sizeof(struct conn *));
713 afs_osi_Free(rxconns, j * sizeof(struct rx_connection *));
714 afs_osi_Free(conntimer, j * sizeof(afs_int32));
715 afs_osi_Free(deltas, j * sizeof(afs_int32));
716 afs_osi_Free(results, j * sizeof(afs_int32));
718 } /*afs_CheckServers*/
721 /* find a server structure given the host address */
723 afs_FindServer(afs_int32 aserver, afs_uint16 aport, afsUUID * uuidp,
730 AFS_STATCNT(afs_FindServer);
732 i = afs_uuid_hash(uuidp) % NSERVERS;
733 for (ts = afs_servers[i]; ts; ts = ts->next) {
734 if ((ts->flags & SRVR_MULTIHOMED)
736 (memcmp((char *)uuidp, (char *)&ts->sr_uuid, sizeof(*uuidp))
737 == 0) && (!ts->addr || (ts->addr->sa_portal == aport)))
742 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
743 if ((sa->sa_ip == aserver) && (sa->sa_portal == aport)) {
750 } /*afs_FindServer */
753 /* some code for creating new server structs and setting preferences follows
754 * in the next few lines...
757 #define MAXDEFRANK 60000
758 #define DEFRANK 40000
760 /* Random number generator and constants from KnuthV2 2d ed, p170 */
766 a is 0.73m should be 0.01m .. 0.99m
767 c is more or less immaterial. 1 or a is suggested.
769 NB: LOW ORDER BITS are not very random. To get small random numbers,
770 treat result as <1, with implied binary point, and multiply by
772 NB: Has to be unsigned, since shifts on signed quantities may preserve
775 /* added rxi_getaddr() to try to get as much initial randomness as
776 possible, since at least one customer reboots ALL their clients
777 simultaneously -- so osi_Time is bound to be the same on some of the
778 clients. This is probably OK, but I don't want to see too much of it.
781 #define ranstage(x) (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
786 static afs_int32 state = 0;
789 AFS_STATCNT(afs_random);
794 * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
795 * bits are in a tv_usec
797 state = (t.tv_usec & (~0 << 4)) + (rxi_getaddr() & 0xff);
798 state += (t.tv_sec & 0xff);
799 for (i = 0; i < 30; i++) {
809 /* returns int 0..14 using the high bits of a pseudo-random number instead of
810 the low bits, as the low bits are "less random" than the high ones...
811 slight roundoff error exists, an excercise for the reader.
812 need to multiply by something with lots of ones in it, so multiply by
813 8 or 16 is right out.
816 afs_randomMod15(void)
820 temp = afs_random() >> 4;
821 temp = (temp * 15) >> 28;
827 afs_randomMod127(void)
831 temp = afs_random() >> 7;
832 temp = (temp * 127) >> 25;
837 /* afs_SortOneServer()
838 * Sort all of the srvAddrs, of a server struct, by rank from low to high.
841 afs_SortOneServer(struct server *asp)
843 struct srvAddr **rootsa, *lowsa, *tsa, *lowprev;
846 for (rootsa = &(asp->addr); *rootsa; rootsa = &(lowsa->next_sa)) {
848 lowsa = *rootsa; /* lowest sa is the first one */
849 lowrank = lowsa->sa_iprank;
851 for (tsa = *rootsa; tsa->next_sa; tsa = tsa->next_sa) {
852 rank = tsa->next_sa->sa_iprank;
853 if (rank < lowrank) {
855 lowsa = tsa->next_sa;
856 lowrank = lowsa->sa_iprank;
859 if (lowprev) { /* found one lower, so rearrange them */
860 lowprev->next_sa = lowsa->next_sa;
861 lowsa->next_sa = *rootsa;
868 * Sort the pointer to servers by the server's rank (its lowest rank).
869 * It is assumed that the server already has its IP addrs sorted (the
870 * first being its lowest rank: afs_GetServer() calls afs_SortOneServer()).
873 afs_SortServers(struct server *aservers[], int count)
878 AFS_STATCNT(afs_SortServers);
880 for (i = 0; i < count; i++) {
883 for (low = i, j = i + 1; j <= count; j++) {
884 if ((!aservers[j]) || (!aservers[j]->addr))
886 if ((!aservers[low]) || (!aservers[low]->addr))
888 if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
894 aservers[i] = aservers[low];
898 } /*afs_SortServers */
900 /* afs_SetServerPrefs is rather system-dependent. It pokes around in kernel
901 data structures to determine what the local IP addresses and subnet masks
902 are in order to choose which server(s) are on the local subnet.
904 As I see it, there are several cases:
905 1. The server address is one of this host's local addresses. In this case
906 this server is to be preferred over all others.
907 2. The server is on the same subnet as one of the this host's local
908 addresses. (ie, an odd-sized subnet, not class A,B,orC)
909 3. The server is on the same net as this host (class A,B or C)
910 4. The server is on a different logical subnet or net than this host, but
911 this host is a 'metric 0 gateway' to it. Ie, two address-spaces share
913 5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
915 6. This host and the server are disjoint.
917 That is a rough order of preference. If a point-to-point link has a high
918 metric, I'm assuming that it is a very slow link, and putting it at the
919 bottom of the list (at least until RX works better over slow links). If
920 its metric is 1, I'm assuming that it's relatively fast (T1) and putting
922 It's not easy to check for case #4, so I'm ignoring it for the time being.
924 BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
925 That could be used to prefer certain servers fairly easily. Maybe some
928 NOTE: this code is very system-dependent, and very dependent on the TCP/IP
929 protocols (well, addresses that are stored in uint32s, at any rate).
932 #define IA_DST(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_dstaddr))
933 #define IA_BROAD(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
935 /* SA2ULONG takes a sockaddr_in, not a sockaddr (same thing, just cast it!) */
936 #define SA2ULONG(sa) ((sa)->sin_addr.s_addr)
941 #define PPWEIGHT 4096
946 #if defined(AFS_SUN5_ENV) && ! defined(AFS_SUN56_ENV)
947 #include <inet/common.h>
948 /* IP interface structure, one per local address */
949 typedef struct ipif_s {
950 /**/ struct ipif_s *ipif_next;
951 struct ill_s *ipif_ill; /* Back pointer to our ill */
952 long ipif_id; /* Logical unit number */
953 u_int ipif_mtu; /* Starts at ipif_ill->ill_max_frag */
954 afs_int32 ipif_local_addr; /* Local IP address for this if. */
955 afs_int32 ipif_net_mask; /* Net mask for this interface. */
956 afs_int32 ipif_broadcast_addr; /* Broadcast addr for this interface. */
957 afs_int32 ipif_pp_dst_addr; /* Point-to-point dest address. */
958 u_int ipif_flags; /* Interface flags. */
959 u_int ipif_metric; /* BSD if metric, for compatibility. */
960 u_int ipif_ire_type; /* LOCAL or LOOPBACK */
961 mblk_t *ipif_arp_down_mp; /* Allocated at time arp comes up to
962 * prevent awkward out of mem condition
965 mblk_t *ipif_saved_ire_mp; /* Allocated for each extra IRE_SUBNET/
966 * RESOLVER on this interface so that
967 * they can survive ifconfig down.
970 * The packet counts in the ipif contain the sum of the
971 * packet counts in dead IREs that were affiliated with
974 u_long ipif_fo_pkt_count; /* Forwarded thru our dead IREs */
975 u_long ipif_ib_pkt_count; /* Inbound packets for our dead IREs */
976 u_long ipif_ob_pkt_count; /* Outbound packets to our dead IREs */
978 ipif_multicast_up:1, /* We have joined the allhosts group */
982 typedef struct ipfb_s {
983 /**/ struct ipf_s *ipfb_ipf; /* List of ... */
984 kmutex_t ipfb_lock; /* Protect all ipf in list */
987 typedef struct ilm_s {
988 /**/ afs_int32 ilm_addr;
990 u_int ilm_timer; /* IGMP */
991 struct ipif_s *ilm_ipif; /* Back pointer to ipif */
992 struct ilm_s *ilm_next; /* Linked list for each ill */
995 typedef struct ill_s {
996 /**/ struct ill_s *ill_next; /* Chained in at ill_g_head. */
997 struct ill_s **ill_ptpn; /* Pointer to previous next. */
998 queue_t *ill_rq; /* Read queue. */
999 queue_t *ill_wq; /* Write queue. */
1001 int ill_error; /* Error value sent up by device. */
1003 ipif_t *ill_ipif; /* Interface chain for this ILL. */
1004 u_int ill_ipif_up_count; /* Number of IPIFs currently up. */
1005 u_int ill_max_frag; /* Max IDU. */
1006 char *ill_name; /* Our name. */
1007 u_int ill_name_length; /* Name length, incl. terminator. */
1008 u_int ill_subnet_type; /* IRE_RESOLVER or IRE_SUBNET. */
1009 u_int ill_ppa; /* Physical Point of Attachment num. */
1011 int ill_sap_length; /* Including sign (for position) */
1012 u_int ill_phys_addr_length; /* Excluding the sap. */
1013 mblk_t *ill_frag_timer_mp; /* Reassembly timer state. */
1014 ipfb_t *ill_frag_hash_tbl; /* Fragment hash list head. */
1016 queue_t *ill_bind_pending_q; /* Queue waiting for DL_BIND_ACK. */
1017 ipif_t *ill_ipif_pending; /* IPIF waiting for DL_BIND_ACK. */
1019 /* ill_hdr_length and ill_hdr_mp will be non zero if
1020 * the underlying device supports the M_DATA fastpath
1024 ilm_t *ill_ilm; /* Multicast mebership for lower ill */
1026 /* All non-nil cells between 'ill_first_mp_to_free' and
1027 * 'ill_last_mp_to_free' are freed in ill_delete.
1029 #define ill_first_mp_to_free ill_hdr_mp
1030 mblk_t *ill_hdr_mp; /* Contains fastpath template */
1031 mblk_t *ill_bcast_mp; /* DLPI header for broadcasts. */
1032 mblk_t *ill_bind_pending; /* T_BIND_REQ awaiting completion. */
1033 mblk_t *ill_resolver_mp; /* Resolver template. */
1034 mblk_t *ill_attach_mp;
1035 mblk_t *ill_bind_mp;
1036 mblk_t *ill_unbind_mp;
1037 mblk_t *ill_detach_mp;
1038 #define ill_last_mp_to_free ill_detach_mp
1040 u_int ill_frag_timer_running:1, ill_needs_attach:1, ill_is_ptp:1,
1041 ill_priv_stream:1, ill_unbind_pending:1, ill_pad_to_bit_31:27;
1042 MI_HRT_DCL(ill_rtime)
1043 MI_HRT_DCL(ill_rtmp)
1047 #ifdef AFS_USERSPACE_IP_ADDR
1049 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1052 * The IP addresses and ranks are determined by afsd (in user space) and
1053 * passed into the kernel at startup time through the AFSOP_ADVISEADDR
1054 * system call. These are stored in the data structure
1055 * called 'afs_cb_interface'.
1057 * struct srvAddr *sa; remote server
1058 * afs_int32 addr; one of my local addr in net order
1059 * afs_uint32 subnetmask; subnet mask of local addr in net order
1063 afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr,
1064 afs_uint32 subnetmask)
1066 afs_uint32 myAddr, myNet, mySubnet, netMask;
1067 afs_uint32 serverAddr;
1069 myAddr = ntohl(addr); /* one of my IP addr in host order */
1070 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1071 subnetmask = ntohl(subnetmask); /* subnet mask in host order */
1073 if (IN_CLASSA(myAddr))
1074 netMask = IN_CLASSA_NET;
1075 else if (IN_CLASSB(myAddr))
1076 netMask = IN_CLASSB_NET;
1077 else if (IN_CLASSC(myAddr))
1078 netMask = IN_CLASSC_NET;
1082 myNet = myAddr & netMask;
1083 mySubnet = myAddr & subnetmask;
1085 if ((serverAddr & netMask) == myNet) {
1086 if ((serverAddr & subnetmask) == mySubnet) {
1087 if (serverAddr == myAddr) { /* same machine */
1088 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1089 } else { /* same subnet */
1090 sa->sa_iprank = afs_min(sa->sa_iprank, HI);
1092 } else { /* same net */
1093 sa->sa_iprank = afs_min(sa->sa_iprank, MED);
1097 #else /* AFS_USERSPACE_IP_ADDR */
1098 #if (! defined(AFS_SUN5_ENV)) && !defined(AFS_DARWIN60_ENV) && defined(USEIFADDR)
1100 afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
1102 struct sockaddr_in *sin;
1105 if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
1106 if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
1108 if (SA2ULONG(sin) == ntohl(sa->sa_ip)) { /* ie, ME!!! */
1109 sa->sa_iprank = TOPR;
1111 t = HI + ifa->ia_ifp->if_metric; /* case #2 */
1112 if (sa->sa_iprank > t)
1116 t = MED + ifa->ia_ifp->if_metric; /* case #3 */
1117 if (sa->sa_iprank > t)
1121 #ifdef IFF_POINTTOPOINT
1122 /* check for case #4 -- point-to-point link */
1123 if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
1124 && (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
1125 if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1128 t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
1129 if (sa->sa_iprank > t)
1132 #endif /* IFF_POINTTOPOINT */
1134 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1135 #if defined(AFS_DARWIN60_ENV) && defined(USEIFADDR)
1137 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1140 afsi_SetServerIPRank(sa, ifa)
1142 #ifdef AFS_DARWIN80_ENV
1148 struct sockaddr sout;
1149 struct sockaddr_in *sin;
1152 afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
1153 afs_uint32 serverAddr;
1155 if (ifaddr_address_family(ifa) != AF_INET)
1157 t = ifaddr_address(ifa, &sout, sizeof(sout));
1159 sin = (struct sockaddr_in *)&sout;
1160 myAddr = ntohl(sin->sin_addr.s_addr); /* one of my IP addr in host order */
1164 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1165 t = ifaddr_netmask(ifa, &sout, sizeof(sout));
1167 sin = (struct sockaddr_in *)&sout;
1168 subnetmask = ntohl(sin->sin_addr.s_addr); /* subnet mask in host order */
1172 t = ifaddr_dstaddress(ifa, &sout, sizeof(sout));
1174 sin = (struct sockaddr_in *)&sout;
1175 myDstaddr = sin->sin_addr.s_addr;
1180 if (IN_CLASSA(myAddr))
1181 netMask = IN_CLASSA_NET;
1182 else if (IN_CLASSB(myAddr))
1183 netMask = IN_CLASSB_NET;
1184 else if (IN_CLASSC(myAddr))
1185 netMask = IN_CLASSC_NET;
1189 myNet = myAddr & netMask;
1190 mySubnet = myAddr & subnetmask;
1192 if ((serverAddr & netMask) == myNet) {
1193 if ((serverAddr & subnetmask) == mySubnet) {
1194 if (serverAddr == myAddr) { /* same machine */
1195 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1196 } else { /* same subnet */
1197 sa->sa_iprank = afs_min(sa->sa_iprank, HI + ifnet_metric(ifaddr_ifnet(ifa)));
1199 } else { /* same net */
1200 sa->sa_iprank = afs_min(sa->sa_iprank, MED + ifnet_metric(ifaddr_ifnet(ifa)));
1203 #ifdef IFF_POINTTOPOINT
1204 /* check for case #4 -- point-to-point link */
1205 if ((ifnet_flags(ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
1206 && (myDstaddr == serverAddr)) {
1207 if (ifnet_metric(ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
1210 t = MED + (PPWEIGHT << ifnet_metric(ifaddr_ifnet(ifa)));
1211 if (sa->sa_iprank > t)
1214 #endif /* IFF_POINTTOPOINT */
1216 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1217 #endif /* else AFS_USERSPACE_IP_ADDR */
1219 #ifdef AFS_SGI62_ENV
1222 afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1224 afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
1225 return 0; /* Never match, so we enumerate everyone */
1227 #endif /* AFS_SGI62_ENV */
1228 static int afs_SetServerPrefs(struct srvAddr *sa) {
1229 #if defined(AFS_USERSPACE_IP_ADDR)
1233 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1234 afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1235 afs_cb_interface.subnetmask[i]);
1237 #else /* AFS_USERSPACE_IP_ADDR */
1238 #if defined(AFS_SUN5_ENV)
1239 #ifdef AFS_SUN510_ENV
1240 ill_walk_context_t ctx;
1242 extern struct ill_s *ill_g_headp;
1243 long *addr = (long *)ill_g_headp;
1247 int subnet, subnetmask, net, netmask;
1251 #ifdef AFS_SUN510_ENV
1252 for (ill = ILL_START_WALK_ALL(&ctx) ; ill ; ill = ill_next(&ctx, ill)) {
1254 for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
1255 ill = ill->ill_next) {
1257 #ifdef AFS_SUN58_ENV
1258 /* Make sure this is an IPv4 ILL */
1262 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
1263 subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1264 subnetmask = ipif->ipif_net_mask;
1266 * Generate the local net using the local address and
1267 * whate we know about Class A, B and C networks.
1269 if (IN_CLASSA(ipif->ipif_local_addr)) {
1270 netmask = IN_CLASSA_NET;
1271 } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1272 netmask = IN_CLASSB_NET;
1273 } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1274 netmask = IN_CLASSC_NET;
1278 net = ipif->ipif_local_addr & netmask;
1281 if (ipif->ipif_local_addr != 0x7f000001) { /* ignore loopback */
1285 *addrp++ = ipif->ipif_local_addr;
1290 /* XXXXXX Do the individual ip ranking below XXXXX */
1291 if ((sa->sa_ip & netmask) == net) {
1292 if ((sa->sa_ip & subnetmask) == subnet) {
1293 if (ipif->ipif_local_addr == sa->sa_ip) { /* ie, ME! */
1294 sa->sa_iprank = TOPR;
1296 sa->sa_iprank = HI + ipif->ipif_metric; /* case #2 */
1299 sa->sa_iprank = MED + ipif->ipif_metric; /* case #3 */
1302 sa->sa_iprank = LO + ipif->ipif_metric; /* case #4 */
1304 /* check for case #5 -- point-to-point link */
1305 if ((ipif->ipif_flags & IFF_POINTOPOINT)
1306 && (ipif->ipif_pp_dst_addr == sa->sa_ip)) {
1308 if (ipif->ipif_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1309 sa->sa_iprank = MAXDEFRANK;
1311 sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1318 struct ifnet *ifn = NULL;
1319 struct in_ifaddr *ifad = (struct in_ifaddr *)0;
1320 struct sockaddr_in *sin;
1323 #ifdef notdef /* clean up, remove this */
1324 for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
1325 for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next) {
1326 if ((IFADDR2SA(ifad)->sa_family == AF_INET)
1327 && !(ifn->if_flags & IFF_LOOPBACK)) {
1332 ((struct sockaddr_in *)IFADDR2SA(ifad))->sin_addr.
1341 ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1343 if (ifn) { /* local, more or less */
1345 if (ifn->if_flags & IFF_LOOPBACK) {
1346 sa->sa_iprank = TOPR;
1349 #endif /* IFF_LOOPBACK */
1350 sin = (struct sockaddr_in *)IA_SIN(ifad);
1351 if (SA2ULONG(sin) == sa->sa_ip) {
1352 sa->sa_iprank = TOPR;
1355 #ifdef IFF_BROADCAST
1356 if (ifn->if_flags & IFF_BROADCAST) {
1357 if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1362 #endif /* IFF_BROADCAST */
1363 #ifdef IFF_POINTOPOINT
1364 if (ifn->if_flags & IFF_POINTOPOINT) {
1365 if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1366 if (ifn->if_metric > 4) {
1370 sa->sa_iprank = ifn->if_metric;
1373 #endif /* IFF_POINTOPOINT */
1374 sa->sa_iprank += MED + ifn->if_metric; /* couldn't find anything better */
1376 #else /* USEIFADDR */
1380 #ifdef AFS_SGI62_ENV
1381 (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1382 (caddr_t) sa, NULL);
1383 #elif defined(AFS_DARWIN80_ENV)
1387 ifaddr_t *addresses, address;
1388 t = ifnet_get_address_list_family(NULL, &addresses, AF_INET);
1390 while(addresses[cnt] != NULL) {
1391 afsi_SetServerIPRank(sa, address);
1394 ifnet_free_address_list(addresses);
1397 #elif defined(AFS_DARWIN60_ENV)
1401 TAILQ_FOREACH(ifn, &ifnet, if_link) {
1402 TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
1403 afsi_SetServerIPRank(sa, ifa);
1405 #elif defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1407 struct in_ifaddr *ifa;
1408 TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
1409 afsi_SetServerIPRank(sa, ifa);
1411 #elif defined(AFS_OBSD_ENV)
1413 extern struct in_ifaddrhead in_ifaddr;
1414 struct in_ifaddr *ifa;
1415 for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1416 afsi_SetServerIPRank(sa, ifa);
1420 struct in_ifaddr *ifa;
1421 for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
1422 afsi_SetServerIPRank(sa, ifa);
1426 #endif /* USEIFADDR */
1427 #endif /* AFS_SUN5_ENV */
1428 #endif /* else AFS_USERSPACE_IP_ADDR */
1430 sa->sa_iprank += afs_randomMod15();
1433 } /* afs_SetServerPrefs */
1441 /* afs_FlushServer()
1442 * The addresses on this server struct has changed in some way and will
1443 * clean up all other structures that may reference it.
1444 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1446 void afs_FlushServer(struct server *srvp) {
1448 struct server *ts, **pts;
1450 /* Find any volumes residing on this server and flush their state */
1451 afs_ResetVolumes(srvp);
1453 /* Flush all callbacks in the all vcaches for this specific server */
1454 afs_FlushServerCBs(srvp);
1456 /* Remove all the callbacks structs */
1458 struct afs_cbr *cb, *cbnext;
1460 MObtainWriteLock(&afs_xvcb, 300);
1461 for (cb = srvp->cbrs; cb; cb = cbnext) {
1464 } srvp->cbrs = (struct afs_cbr *)0;
1465 ReleaseWriteLock(&afs_xvcb);
1468 /* If no more srvAddr structs hanging off of this server struct,
1472 /* Remove the server structure from the cell list - if there */
1473 afs_RemoveCellEntry(srvp);
1475 /* Remove from the afs_servers hash chain */
1476 for (i = 0; i < NSERVERS; i++) {
1477 for (pts = &(afs_servers[i]), ts = *pts; ts;
1478 pts = &(ts->next), ts = *pts) {
1486 *pts = ts->next; /* Found it. Remove it */
1487 afs_osi_Free(ts, sizeof(struct server)); /* Free it */
1493 /* afs_RemoveSrvAddr()
1494 * This removes a SrvAddr structure from its server structure.
1495 * The srvAddr struct is not free'd because it connections may still
1496 * be open to it. It is up to the calling process to make sure it
1497 * remains connected to a server struct.
1498 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1499 * It is not removed from the afs_srvAddrs hash chain.
1501 void afs_RemoveSrvAddr(struct srvAddr *sap) {
1502 struct srvAddr **psa, *sa;
1509 /* Find the srvAddr in the server's list and remove it */
1510 for (psa = &(srv->addr), sa = *psa; sa; psa = &(sa->next_sa), sa = *psa) {
1518 /* Flush the server struct since it's IP address has changed */
1519 afs_FlushServer(srv);
1524 * Return an updated and properly initialized server structure
1525 * corresponding to the server ID, cell, and port specified.
1526 * If one does not exist, then one will be created.
1527 * aserver and aport must be in NET byte order.
1529 struct server *afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers,
1530 afs_int32 acell, u_short aport,
1531 afs_int32 locktype, afsUUID * uuidp,
1532 afs_int32 addr_uniquifier) {
1533 struct server *oldts = 0, *ts, *newts, *orphts = 0;
1534 struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1536 afs_int32 iphash, k, srvcount = 0;
1537 unsigned int srvhash;
1539 AFS_STATCNT(afs_GetServer);
1541 ObtainSharedLock(&afs_xserver, 13);
1543 /* Check if the server struct exists and is up to date */
1546 panic("afs_GetServer: incorect count of servers");
1547 ObtainReadLock(&afs_xsrvAddr);
1548 ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1549 ReleaseReadLock(&afs_xsrvAddr);
1550 if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1551 /* Found a server struct that is not multihomed and has the
1552 * IP address associated with it. A correct match.
1554 ReleaseSharedLock(&afs_xserver);
1559 panic("afs_GetServer: incorrect count of servers");
1560 ts = afs_FindServer(0, aport, uuidp, locktype);
1561 if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1562 /* Found a server struct that is multihomed and same
1563 * uniqufier (same IP addrs). The above if statement is the
1564 * same as in InstallUVolumeEntry().
1566 ReleaseSharedLock(&afs_xserver);
1570 oldts = ts; /* Will reuse if same uuid */
1573 UpgradeSToWLock(&afs_xserver, 36);
1574 ObtainWriteLock(&afs_xsrvAddr, 116);
1576 srvcount = afs_totalServers;
1578 /* Reuse/allocate a new server structure */
1582 newts = (struct server *)afs_osi_Alloc(sizeof(struct server));
1584 panic("malloc of server struct");
1586 memset((char *)newts, 0, sizeof(struct server));
1588 /* Add the server struct to the afs_servers[] hash chain */
1590 (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
1591 newts->next = afs_servers[srvhash];
1592 afs_servers[srvhash] = newts;
1595 /* Initialize the server structure */
1596 if (uuidp) { /* Multihomed */
1597 newts->sr_uuid = *uuidp;
1598 newts->sr_addr_uniquifier = addr_uniquifier;
1599 newts->flags |= SRVR_MULTIHOMED;
1602 newts->cell = afs_GetCell(acell, 0);
1604 fsport = (newts->cell ? newts->cell->fsport : AFS_FSPORT);
1606 /* For each IP address we are registering */
1607 for (k = 0; k < nservers; k++) {
1608 iphash = SHash(aserverp[k]);
1610 /* Check if the srvAddr structure already exists. If so, remove
1611 * it from its server structure and add it to the new one.
1613 for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
1614 if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
1617 if (oldsa && (oldsa->server != newts)) {
1618 afs_RemoveSrvAddr(oldsa); /* Remove from its server struct */
1619 oldsa->next_sa = newts->addr; /* Add to the new server struct */
1620 newts->addr = oldsa;
1623 /* Reuse/allocate a new srvAddr structure */
1627 newsa = (struct srvAddr *)afs_osi_Alloc(sizeof(struct srvAddr));
1629 panic("malloc of srvAddr struct");
1630 afs_totalSrvAddrs++;
1631 memset((char *)newsa, 0, sizeof(struct srvAddr));
1633 /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1634 newsa->next_bkt = afs_srvAddrs[iphash];
1635 afs_srvAddrs[iphash] = newsa;
1637 /* Hang off of the server structure */
1638 newsa->next_sa = newts->addr;
1639 newts->addr = newsa;
1641 /* Initialize the srvAddr Structure */
1642 newsa->sa_ip = aserverp[k];
1643 newsa->sa_portal = aport;
1646 /* Update the srvAddr Structure */
1647 newsa->server = newts;
1648 if (newts->flags & SRVR_ISDOWN)
1649 newsa->sa_flags |= SRVADDR_ISDOWN;
1651 newsa->sa_flags |= SRVADDR_MH;
1653 newsa->sa_flags &= ~SRVADDR_MH;
1655 /* Compute preference values and resort */
1656 if (!newsa->sa_iprank) {
1657 if (aport == fsport) {
1658 afs_SetServerPrefs(newsa); /* new fileserver rank */
1660 newsa->sa_iprank = 10000 + afs_randomMod127(); /* new vlserver rank */
1664 afs_SortOneServer(newts); /* Sort by rank */
1666 /* If we reused the server struct, remove any of its srvAddr
1667 * structs that will no longer be associated with this server.
1669 if (oldts) { /* reused the server struct */
1670 for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
1671 nextsa = orphsa->next_sa;
1672 for (k = 0; k < nservers; k++) {
1673 if (orphsa->sa_ip == aserverp[k])
1674 break; /* belongs */
1677 continue; /* belongs */
1679 /* Have a srvAddr struct. Now get a server struct (if not already) */
1682 (struct server *)afs_osi_Alloc(sizeof(struct server));
1684 panic("malloc of lo server struct");
1685 memset((char *)orphts, 0, sizeof(struct server));
1688 /* Add the orphaned server to the afs_servers[] hash chain.
1689 * Its iphash does not matter since we never look up the server
1690 * in the afs_servers table by its ip address (only by uuid -
1691 * which this has none).
1693 iphash = SHash(aserverp[k]);
1694 orphts->next = afs_servers[iphash];
1695 afs_servers[iphash] = orphts;
1698 orphts->cell = afs_GetCell(acell, 0);
1701 /* Hang the srvAddr struct off of the server structure. The server
1702 * may have multiple srvAddrs, but it won't be marked multihomed.
1704 afs_RemoveSrvAddr(orphsa); /* remove */
1705 orphsa->next_sa = orphts->addr; /* hang off server struct */
1706 orphts->addr = orphsa;
1707 orphsa->server = orphts;
1708 orphsa->sa_flags |= SRVADDR_NOUSE; /* flag indicating not in use */
1709 orphsa->sa_flags &= ~SRVADDR_MH; /* Not multihomed */
1713 srvcount = afs_totalServers - srvcount; /* # servers added and removed */
1715 struct afs_stats_SrvUpDownInfo *upDownP;
1716 /* With the introduction of this new record, we need to adjust the
1717 * proper individual & global server up/down info.
1719 upDownP = GetUpDownStats(newts);
1720 upDownP->numTtlRecords += srvcount;
1721 afs_stats_cmperf.srvRecords += srvcount;
1722 if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
1723 afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
1726 ReleaseWriteLock(&afs_xsrvAddr);
1727 ReleaseWriteLock(&afs_xserver);
1729 } /* afs_GetServer */
1731 void afs_ActivateServer(struct srvAddr *sap) {
1732 osi_timeval_t currTime; /*Filled with current time */
1733 osi_timeval_t *currTimeP; /*Ptr to above */
1734 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record */
1735 struct server *aserver = sap->server;
1737 if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
1739 * This server record has not yet been activated. Go for it,
1740 * recording its ``birth''.
1742 aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
1743 currTimeP = &currTime;
1744 osi_GetuTime(currTimeP);
1745 aserver->activationTime = currTime.tv_sec;
1746 upDownP = GetUpDownStats(aserver);
1747 if (aserver->flags & SRVR_ISDOWN) {
1748 upDownP->numDownRecords++;
1750 upDownP->numUpRecords++;
1751 upDownP->numRecordsNeverDown++;
1757 void shutdown_server()
1761 for (i = 0; i < NSERVERS; i++) {
1762 struct server *ts, *next;
1764 ts = afs_servers[i];
1767 afs_osi_Free(ts, sizeof(struct server));
1772 for (i = 0; i < NSERVERS; i++) {
1773 struct srvAddr *sa, *next;
1775 sa = afs_srvAddrs[i];
1777 next = sa->next_bkt;
1778 afs_osi_Free(sa, sizeof(struct srvAddr));