Merge 1.8.0~pre4 packaging into master
[pkg-k5-afs_openafs.git] / src / afs / afs_server.c
blob79b4704ec65307f77e4a0e60675ed20a23cada07
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
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
8 */
11 * Implements:
12 * afs_MarkServerUpOrDown
13 * afs_ServerDown
14 * afs_CountServers
15 * afs_CheckServers
16 * afs_FindServer
17 * afs_random
18 * afs_randomMod127
19 * afs_SortServers
20 * afsi_SetServerIPRank
21 * afs_GetServer
22 * afs_ActivateServer
25 * Local:
26 * HaveCallBacksFrom
27 * CheckVLServer
28 * afs_SortOneServer
29 * afs_SetServerPrefs
32 #include <afsconfig.h>
33 #include "afs/param.h"
36 #include "afs/stds.h"
37 #include "afs/sysincludes.h" /* Standard vendor system headers */
39 #if !defined(UKERNEL)
40 #if !defined(AFS_LINUX20_ENV)
41 #include <net/if.h>
42 #endif
43 #include <netinet/in.h>
45 #ifdef AFS_SGI62_ENV
46 #include "h/hashing.h"
47 #endif
48 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV)
49 #include <netinet/in_var.h>
50 #endif /* AFS_HPUX110_ENV */
51 #ifdef AFS_DARWIN_ENV
52 #include <net/if_var.h>
53 #endif
54 #endif /* !defined(UKERNEL) */
56 #include "afsincludes.h" /* Afs-based standard headers */
57 #include "afs/afs_stats.h" /* afs statistics */
58 #include "rx/rx_multi.h"
60 #if defined(AFS_SUN5_ENV)
61 #include <inet/led.h>
62 #include <inet/common.h>
63 #include <netinet/ip6.h>
64 #define ipif_local_addr ipif_lcl_addr
65 #ifndef V4_PART_OF_V6
66 # define V4_PART_OF_V6(v6) v6.s6_addr32[3]
67 #endif
68 #include <inet/ip.h>
69 #endif
71 /* Exported variables */
72 afs_rwlock_t afs_xserver; /* allocation lock for servers */
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;
86 static struct afs_stats_SrvUpDownInfo *
87 GetUpDownStats(struct server *srv)
89 struct afs_stats_SrvUpDownInfo *upDownP;
90 u_short fsport = AFS_FSPORT;
92 if (srv->cell)
93 fsport = srv->cell->fsport;
95 if (srv->addr->sa_portal == fsport)
96 upDownP = afs_stats_cmperf.fs_UpDown;
97 else
98 upDownP = afs_stats_cmperf.vl_UpDown;
100 if (srv->cell && afs_IsPrimaryCell(srv->cell))
101 return &upDownP[AFS_STATS_UPDOWN_IDX_SAME_CELL];
102 else
103 return &upDownP[AFS_STATS_UPDOWN_IDX_DIFF_CELL];
107 /*------------------------------------------------------------------------
108 * afs_MarkServerUpOrDown
110 * Description:
111 * Mark the given server up or down, and track its uptime stats.
113 * Arguments:
114 * a_serverP : Ptr to server record to fiddle with.
115 * a_isDown : Is the server is to be marked down?
117 * Returns:
118 * Nothing.
120 * Environment:
121 * The CM server structures must be write-locked.
123 * Side Effects:
124 * As advertised.
125 *------------------------------------------------------------------------*/
127 void
128 afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
130 struct server *a_serverP = sa->server;
131 struct srvAddr *sap;
132 osi_timeval_t currTime, *currTimeP; /*Current time */
133 afs_int32 downTime; /*Computed downtime, in seconds */
134 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record */
137 * If the server record is marked the same as the new status we've
138 * been fed, then there isn't much to be done.
140 if ((a_isDown && (sa->sa_flags & SRVADDR_ISDOWN))
141 || (!a_isDown && !(sa->sa_flags & SRVADDR_ISDOWN)))
142 return;
144 if (a_isDown) {
145 sa->sa_flags |= SRVADDR_ISDOWN;
146 for (sap = a_serverP->addr; sap; sap = sap->next_sa) {
147 if (!(sap->sa_flags & SRVADDR_ISDOWN)) {
148 /* Not all ips are up so don't bother with the
149 * server's up/down stats */
150 return;
154 * All ips are down we treat the whole server down
156 a_serverP->flags |= SRVR_ISDOWN;
157 } else {
158 sa->sa_flags &= ~SRVADDR_ISDOWN;
159 /* If any ips are up, the server is also marked up */
160 a_serverP->flags &= ~SRVR_ISDOWN;
161 for (sap = a_serverP->addr; sap; sap = sap->next_sa) {
162 if (sap->sa_flags & SRVADDR_ISDOWN) {
163 /* Not all ips are up so don't bother with the
164 * server's up/down stats */
165 return;
169 #ifndef AFS_NOSTATS
171 * Compute the current time and which overall stats record is to be
172 * updated; we'll need them one way or another.
174 currTimeP = &currTime;
175 osi_GetuTime(currTimeP);
177 upDownP = GetUpDownStats(a_serverP);
179 if (a_isDown) {
181 * Server going up -> down; remember the beginning of this
182 * downtime incident.
184 a_serverP->lastDowntimeStart = currTime.tv_sec;
186 (upDownP->numDownRecords)++;
187 (upDownP->numUpRecords)--;
188 } /*Server being marked down */
189 else {
191 * Server going down -> up; remember everything about this
192 * newly-completed downtime incident.
194 downTime = currTime.tv_sec - a_serverP->lastDowntimeStart;
195 (a_serverP->numDowntimeIncidents)++;
196 a_serverP->sumOfDowntimes += downTime;
198 (upDownP->numUpRecords)++;
199 (upDownP->numDownRecords)--;
200 (upDownP->numDowntimeIncidents)++;
201 if (a_serverP->numDowntimeIncidents == 1)
202 (upDownP->numRecordsNeverDown)--;
203 upDownP->sumOfDowntimes += downTime;
204 if ((upDownP->shortestDowntime == 0)
205 || (downTime < upDownP->shortestDowntime))
206 upDownP->shortestDowntime = downTime;
207 if ((upDownP->longestDowntime == 0)
208 || (downTime > upDownP->longestDowntime))
209 upDownP->longestDowntime = downTime;
212 if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET0)
213 (upDownP->downDurations[0])++;
214 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET1)
215 (upDownP->downDurations[1])++;
216 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET2)
217 (upDownP->downDurations[2])++;
218 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET3)
219 (upDownP->downDurations[3])++;
220 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET4)
221 (upDownP->downDurations[4])++;
222 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET5)
223 (upDownP->downDurations[5])++;
224 else
225 (upDownP->downDurations[6])++;
227 } /*Server being marked up */
228 #endif
229 } /*MarkServerUpOrDown */
232 afs_int32
233 afs_ServerDown(struct srvAddr *sa, int code, struct rx_connection *rxconn)
235 struct server *aserver = sa->server;
237 AFS_STATCNT(ServerDown);
238 if (aserver->flags & SRVR_ISDOWN || sa->sa_flags & SRVADDR_ISDOWN)
239 return 0;
240 afs_MarkServerUpOrDown(sa, SRVR_ISDOWN);
241 if (sa->sa_portal == aserver->cell->vlport)
242 print_internet_address("afs: Lost contact with volume location server ",
243 sa, "", 1, code, rxconn);
244 else
245 print_internet_address("afs: Lost contact with file server ", sa, "",
246 1, code, rxconn);
247 return 1;
248 } /*ServerDown */
251 /* return true if we have any callback promises from this server */
253 afs_HaveCallBacksFrom(struct server *aserver)
255 afs_int32 now;
256 int i;
257 struct vcache *tvc;
259 AFS_STATCNT(HaveCallBacksFrom);
260 now = osi_Time(); /* for checking for expired callbacks */
261 for (i = 0; i < VCSIZE; i++) { /* for all guys in the hash table */
262 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
264 * Check to see if this entry has an unexpired callback promise
265 * from the required host
267 if (aserver == tvc->callback && tvc->cbExpires >= now
268 && ((tvc->f.states & CRO) == 0))
269 return 1;
272 return 0;
274 } /*HaveCallBacksFrom */
277 static void
278 CheckVLServer(struct srvAddr *sa, struct vrequest *areq)
280 struct server *aserver = sa->server;
281 struct afs_conn *tc;
282 afs_int32 code;
283 struct rx_connection *rxconn;
285 AFS_STATCNT(CheckVLServer);
286 /* Ping dead servers to see if they're back */
287 if (!((aserver->flags & SRVR_ISDOWN) || (sa->sa_flags & SRVADDR_ISDOWN))
288 || (aserver->flags & SRVR_ISGONE))
289 return;
290 if (!aserver->cell)
291 return; /* can't do much */
293 tc = afs_ConnByHost(aserver, aserver->cell->vlport,
294 aserver->cell->cellNum, areq, 1, SHARED_LOCK, 0,
295 &rxconn);
296 if (!tc)
297 return;
298 rx_SetConnDeadTime(rxconn, 3);
300 RX_AFS_GUNLOCK();
301 code = VL_ProbeServer(rxconn);
302 RX_AFS_GLOCK();
303 rx_SetConnDeadTime(rxconn, afs_rx_deadtime);
305 * If probe worked, or probe call not yet defined (for compatibility
306 * with old vlsevers), then we treat this server as running again
308 if (code == 0 || (code <= -450 && code >= -470)) {
309 if (tc->parent->srvr == sa) {
310 afs_MarkServerUpOrDown(sa, 0);
311 print_internet_address("afs: volume location server ", sa,
312 " is back up", 2, code, rxconn);
315 afs_PutConn(tc, rxconn, SHARED_LOCK);
317 } /*CheckVLServer */
320 #ifndef AFS_MINCHANGE /* So that some can increase it in param.h */
321 #define AFS_MINCHANGE 2 /* min change we'll bother with */
322 #endif
323 #ifndef AFS_MAXCHANGEBACK
324 #define AFS_MAXCHANGEBACK 10 /* max seconds we'll set a clock back at once */
325 #endif
328 /*------------------------------------------------------------------------
329 * EXPORTED afs_CountServers
331 * Description:
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
335 * fly.
337 * Arguments:
338 * None.
340 * Returns:
341 * Nothing.
343 * Environment:
344 * This routine locks afs_xserver for write for the duration.
346 * Side Effects:
347 * Set CM perf stats field sumOfRecordAges for all server record
348 * entries.
349 *------------------------------------------------------------------------*/
351 void
352 afs_CountServers(void)
354 int currIdx; /*Curr idx into srv table */
355 struct server *currSrvP; /*Ptr to curr server record */
356 afs_int32 currChainLen; /*Length of curr hash chain */
357 osi_timeval_t currTime; /*Current time */
358 osi_timeval_t *currTimeP; /*Ptr to above */
359 afs_int32 srvRecordAge; /*Age of server record, in secs */
360 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to current up/down
361 * info being manipulated */
364 * Write-lock the server table so we don't get any interference.
366 ObtainReadLock(&afs_xserver);
369 * Iterate over each hash index in the server table, walking down each
370 * chain and tallying what we haven't computed from the records there on
371 * the fly. First, though, initialize the tallies that will change.
373 afs_stats_cmperf.srvMaxChainLength = 0;
375 afs_stats_cmperf.fs_UpDown[0].sumOfRecordAges = 0;
376 afs_stats_cmperf.fs_UpDown[0].ageOfYoungestRecord = 0;
377 afs_stats_cmperf.fs_UpDown[0].ageOfOldestRecord = 0;
378 memset(afs_stats_cmperf.fs_UpDown[0].downIncidents, 0,
379 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
381 afs_stats_cmperf.fs_UpDown[1].sumOfRecordAges = 0;
382 afs_stats_cmperf.fs_UpDown[1].ageOfYoungestRecord = 0;
383 afs_stats_cmperf.fs_UpDown[1].ageOfOldestRecord = 0;
384 memset(afs_stats_cmperf.fs_UpDown[1].downIncidents, 0,
385 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
387 afs_stats_cmperf.vl_UpDown[0].sumOfRecordAges = 0;
388 afs_stats_cmperf.vl_UpDown[0].ageOfYoungestRecord = 0;
389 afs_stats_cmperf.vl_UpDown[0].ageOfOldestRecord = 0;
390 memset(afs_stats_cmperf.vl_UpDown[0].downIncidents, 0,
391 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
393 afs_stats_cmperf.vl_UpDown[1].sumOfRecordAges = 0;
394 afs_stats_cmperf.vl_UpDown[1].ageOfYoungestRecord = 0;
395 afs_stats_cmperf.vl_UpDown[1].ageOfOldestRecord = 0;
396 memset(afs_stats_cmperf.vl_UpDown[1].downIncidents, 0,
397 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
400 * Compute the current time, used to figure out server record ages.
402 currTimeP = &currTime;
403 osi_GetuTime(currTimeP);
406 * Sweep the server hash table, tallying all we need to know.
408 for (currIdx = 0; currIdx < NSERVERS; currIdx++) {
409 currChainLen = 0;
410 for (currSrvP = afs_servers[currIdx]; currSrvP;
411 currSrvP = currSrvP->next) {
413 * Bump the current chain length.
415 currChainLen++;
418 * Any further tallying for this record will only be done if it has
419 * been activated.
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 upDownP = GetUpDownStats(currSrvP);
430 upDownP->sumOfRecordAges += srvRecordAge;
431 if ((upDownP->ageOfYoungestRecord == 0)
432 || (srvRecordAge < upDownP->ageOfYoungestRecord))
433 upDownP->ageOfYoungestRecord = srvRecordAge;
434 if ((upDownP->ageOfOldestRecord == 0)
435 || (srvRecordAge > upDownP->ageOfOldestRecord))
436 upDownP->ageOfOldestRecord = srvRecordAge;
438 if (currSrvP->numDowntimeIncidents <=
439 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET0)
440 (upDownP->downIncidents[0])++;
441 else if (currSrvP->numDowntimeIncidents <=
442 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET1)
443 (upDownP->downIncidents[1])++;
444 else if (currSrvP->numDowntimeIncidents <=
445 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET2)
446 (upDownP->downIncidents[2])++;
447 else if (currSrvP->numDowntimeIncidents <=
448 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET3)
449 (upDownP->downIncidents[3])++;
450 else if (currSrvP->numDowntimeIncidents <=
451 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET4)
452 (upDownP->downIncidents[4])++;
453 else
454 (upDownP->downIncidents[5])++;
457 } /*Current server has been active */
458 } /*Walk this chain */
461 * Before advancing to the next chain, remember facts about this one.
463 if (currChainLen > afs_stats_cmperf.srvMaxChainLength) {
465 * We beat out the former champion (which was initially set to 0
466 * here). Mark down the new winner, and also remember if it's an
467 * all-time winner.
469 afs_stats_cmperf.srvMaxChainLength = currChainLen;
470 if (currChainLen > afs_stats_cmperf.srvMaxChainLengthHWM)
471 afs_stats_cmperf.srvMaxChainLengthHWM = currChainLen;
472 } /*Update chain length maximum */
473 } /*For each hash chain */
476 * We're done. Unlock the server table before returning to our caller.
478 ReleaseReadLock(&afs_xserver);
480 } /*afs_CountServers */
483 void
484 ForceAllNewConnections(void)
486 int srvAddrCount;
487 struct srvAddr **addrs;
488 struct srvAddr *sa;
489 afs_int32 i, j;
491 ObtainReadLock(&afs_xserver); /* Necessary? */
492 ObtainReadLock(&afs_xsrvAddr);
494 srvAddrCount = 0;
495 for (i = 0; i < NSERVERS; i++) {
496 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
497 srvAddrCount++;
501 addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
502 osi_Assert(addrs != NULL);
503 j = 0;
504 for (i = 0; i < NSERVERS; i++) {
505 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
506 if (j >= srvAddrCount)
507 break;
508 addrs[j++] = sa;
512 ReleaseReadLock(&afs_xsrvAddr);
513 ReleaseReadLock(&afs_xserver);
514 for (i = 0; i < j; i++) {
515 sa = addrs[i];
516 ForceNewConnections(sa);
520 static void
521 CkSrv_MarkUpDown(struct afs_conn **conns, struct rx_connection **rxconns,
522 int nconns, afs_int32 *results)
524 struct srvAddr *sa;
525 struct afs_conn *tc;
526 afs_int32 i;
528 for(i = 0; i < nconns; i++){
529 tc = conns[i];
530 sa = tc->parent->srvr;
532 if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) &&
533 (tc->parent->srvr == sa)) {
534 /* server back up */
535 print_internet_address("afs: file server ", sa, " is back up", 2,
536 results[i], rxconns[i]);
538 ObtainWriteLock(&afs_xserver, 244);
539 ObtainWriteLock(&afs_xsrvAddr, 245);
540 afs_MarkServerUpOrDown(sa, 0);
541 ReleaseWriteLock(&afs_xsrvAddr);
542 ReleaseWriteLock(&afs_xserver);
544 if (afs_waitForeverCount) {
545 afs_osi_Wakeup(&afs_waitForever);
547 } else {
548 if (results[i] < 0) {
549 /* server crashed */
550 afs_ServerDown(sa, results[i], rxconns[i]);
551 ForceNewConnections(sa); /* multi homed clients */
557 void
558 CkSrv_GetCaps(int nconns, struct rx_connection **rxconns,
559 struct afs_conn **conns)
561 Capabilities *caps;
562 afs_int32 *results;
563 afs_int32 i;
564 struct server *ts;
566 caps = afs_osi_Alloc(nconns * sizeof (Capabilities));
567 osi_Assert(caps != NULL);
568 memset(caps, 0, nconns * sizeof(Capabilities));
570 results = afs_osi_Alloc(nconns * sizeof (afs_int32));
571 osi_Assert(results != NULL);
573 AFS_GUNLOCK();
574 multi_Rx(rxconns,nconns)
576 multi_RXAFS_GetCapabilities(&caps[multi_i]);
577 results[multi_i] = multi_error;
578 } multi_End;
579 AFS_GLOCK();
581 for ( i = 0 ; i < nconns ; i++ ) {
582 ts = conns[i]->parent->srvr->server;
583 if ( !ts )
584 continue;
585 ts->capabilities = 0;
586 ts->flags |= SCAPS_KNOWN;
587 if ( results[i] == RXGEN_OPCODE ) {
588 /* Mark server as up - it responded */
589 results[i] = 0;
590 continue;
592 if ( results[i] >= 0 )
593 /* we currently handle 32-bits of capabilities */
594 if (caps[i].Capabilities_len > 0) {
595 ts->capabilities = caps[i].Capabilities_val[0];
596 xdr_free((xdrproc_t)xdr_Capabilities, &caps[i]);
597 caps[i].Capabilities_val = NULL;
598 caps[i].Capabilities_len = 0;
601 CkSrv_MarkUpDown(conns, rxconns, nconns, results);
603 afs_osi_Free(caps, nconns * sizeof(Capabilities));
604 afs_osi_Free(results, nconns * sizeof(afs_int32));
607 /* check down servers (if adown), or running servers (if !adown) */
608 void
609 afs_CheckServers(int adown, struct cell *acellp)
611 afs_LoopServers(adown?AFS_LS_DOWN:AFS_LS_UP, acellp, 1, CkSrv_GetCaps, NULL);
614 /* adown: AFS_LS_UP - check only up
615 * AFS_LS_DOWN - check only down.
616 * AFS_LS_ALL - check all */
617 void
618 afs_LoopServers(int adown, struct cell *acellp, int vlalso,
619 void (*func1) (int nservers, struct rx_connection **rxconns,
620 struct afs_conn **conns),
621 void (*func2) (int nservers, struct rx_connection **rxconns,
622 struct afs_conn **conns))
624 struct vrequest *treq = NULL;
625 struct server *ts;
626 struct srvAddr *sa;
627 struct afs_conn *tc = NULL;
628 afs_int32 i, j;
629 afs_int32 code;
630 struct unixuser *tu;
631 int srvAddrCount;
632 struct srvAddr **addrs;
633 struct afs_conn **conns;
634 int nconns;
635 struct rx_connection **rxconns;
636 afs_int32 *conntimer;
638 AFS_STATCNT(afs_CheckServers);
641 * No sense in doing the server checks if we are running in disconnected
642 * mode
644 if (AFS_IS_DISCONNECTED)
645 return;
647 if ((code = afs_CreateReq(&treq, afs_osi_credp)))
648 return;
649 ObtainReadLock(&afs_xserver); /* Necessary? */
650 ObtainReadLock(&afs_xsrvAddr);
652 srvAddrCount = 0;
653 for (i = 0; i < NSERVERS; i++) {
654 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
655 srvAddrCount++;
659 addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
660 osi_Assert(addrs != NULL);
661 j = 0;
662 for (i = 0; i < NSERVERS; i++) {
663 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
664 if (j >= srvAddrCount)
665 break;
666 addrs[j++] = sa;
670 ReleaseReadLock(&afs_xsrvAddr);
671 ReleaseReadLock(&afs_xserver);
673 conns = afs_osi_Alloc(j * sizeof(struct afs_conn *));
674 osi_Assert(conns != NULL);
675 rxconns = afs_osi_Alloc(j * sizeof(struct rx_connection *));
676 osi_Assert(rxconns != NULL);
677 conntimer = afs_osi_Alloc(j * sizeof (afs_int32));
678 osi_Assert(conntimer != NULL);
680 nconns = 0;
681 for (i = 0; i < j; i++) {
682 struct rx_connection *rxconn;
683 sa = addrs[i];
684 ts = sa->server;
685 if (!ts)
686 continue;
688 /* See if a cell to check was specified. If it is spec'd and not
689 * this server's cell, just skip the server.
691 if (acellp && acellp != ts->cell)
692 continue;
694 if (((adown==AFS_LS_DOWN) && !(sa->sa_flags & SRVADDR_ISDOWN))
695 || ((adown==AFS_LS_UP) && (sa->sa_flags & SRVADDR_ISDOWN)))
696 continue;
698 /* check vlserver with special code */
699 if (sa->sa_portal == AFS_VLPORT) {
700 if (vlalso)
701 CheckVLServer(sa, treq);
702 continue;
705 if (!ts->cell) /* not really an active server, anyway, it must */
706 continue; /* have just been added by setsprefs */
708 /* get a connection, even if host is down; bumps conn ref count */
709 tu = afs_GetUser(treq->uid, ts->cell->cellNum, SHARED_LOCK);
710 tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
711 1 /*force */ , 1 /*create */ , SHARED_LOCK, 0,
712 &rxconn);
713 afs_PutUser(tu, SHARED_LOCK);
714 if (!tc)
715 continue;
717 if ((sa->sa_flags & SRVADDR_ISDOWN) || afs_HaveCallBacksFrom(sa->server)) {
718 conns[nconns]=tc;
719 rxconns[nconns]=rxconn;
720 if (sa->sa_flags & SRVADDR_ISDOWN) {
721 rx_SetConnDeadTime(rxconn, 3);
722 conntimer[nconns]=1;
723 } else {
724 conntimer[nconns]=0;
726 nconns++;
727 } else /* not holding, kill ref */
728 afs_PutConn(tc, rxconn, SHARED_LOCK);
729 } /* Outer loop over addrs */
731 afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
732 addrs = NULL;
734 (*func1)(nconns, rxconns, conns);
736 if (func2) {
737 (*func2)(nconns, rxconns, conns);
740 for (i = 0; i < nconns; i++) {
741 if (conntimer[i] == 1)
742 rx_SetConnDeadTime(rxconns[i], afs_rx_deadtime);
743 afs_PutConn(conns[i], rxconns[i], SHARED_LOCK); /* done with it now */
746 afs_osi_Free(conns, j * sizeof(struct afs_conn *));
747 afs_osi_Free(rxconns, j * sizeof(struct rx_connection *));
748 afs_osi_Free(conntimer, j * sizeof(afs_int32));
749 afs_DestroyReq(treq);
751 } /*afs_CheckServers*/
754 /* find a server structure given the host address */
755 struct server *
756 afs_FindServer(afs_int32 aserver, afs_uint16 aport, afsUUID * uuidp,
757 afs_int32 locktype)
759 struct server *ts;
760 struct srvAddr *sa;
761 int i;
763 AFS_STATCNT(afs_FindServer);
764 if (uuidp) {
765 i = afs_uuid_hash(uuidp) % NSERVERS;
766 for (ts = afs_servers[i]; ts; ts = ts->next) {
767 if ((ts->flags & SRVR_MULTIHOMED)
769 (memcmp((char *)uuidp, (char *)&ts->sr_uuid, sizeof(*uuidp))
770 == 0) && (!ts->addr || (ts->addr->sa_portal == aport)))
771 return ts;
773 } else {
774 i = SHash(aserver);
775 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
776 if ((sa->sa_ip == aserver) && (sa->sa_portal == aport)) {
777 return sa->server;
781 return NULL;
783 } /*afs_FindServer */
786 /* some code for creating new server structs and setting preferences follows
787 * in the next few lines...
790 #define MAXDEFRANK 60000
791 #define DEFRANK 40000
793 /* Random number generator and constants from KnuthV2 2d ed, p170 */
795 /* Rules:
796 X = (aX + c) % m
797 m is a power of two
798 a % 8 is 5
799 a is 0.73m should be 0.01m .. 0.99m
800 c is more or less immaterial. 1 or a is suggested.
802 NB: LOW ORDER BITS are not very random. To get small random numbers,
803 treat result as <1, with implied binary point, and multiply by
804 desired modulus.
805 NB: Has to be unsigned, since shifts on signed quantities may preserve
806 the sign bit.
808 /* added rxi_getaddr() to try to get as much initial randomness as
809 possible, since at least one customer reboots ALL their clients
810 simultaneously -- so osi_Time is bound to be the same on some of the
811 clients. This is probably OK, but I don't want to see too much of it.
814 #define ranstage(x) (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
816 unsigned int
817 afs_random(void)
819 static afs_int32 state = 0;
820 int i;
822 AFS_STATCNT(afs_random);
823 if (!state) {
824 osi_timeval_t t;
825 osi_GetTime(&t);
827 * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
828 * bits are in a tv_usec
830 state = (t.tv_usec & (~0 << 4)) + (rxi_getaddr() & 0xff);
831 state += (t.tv_sec & 0xff);
832 for (i = 0; i < 30; i++) {
833 ranstage(state);
837 ranstage(state);
838 return (state);
840 } /*afs_random */
842 /* returns int 0..14 using the high bits of a pseudo-random number instead of
843 the low bits, as the low bits are "less random" than the high ones...
844 slight roundoff error exists, an excercise for the reader.
845 need to multiply by something with lots of ones in it, so multiply by
846 8 or 16 is right out.
849 afs_randomMod15(void)
851 afs_uint32 temp;
853 temp = afs_random() >> 4;
854 temp = (temp * 15) >> 28;
856 return temp;
860 afs_randomMod127(void)
862 afs_uint32 temp;
864 temp = afs_random() >> 7;
865 temp = (temp * 127) >> 25;
867 return temp;
870 /* afs_SortOneServer()
871 * Sort all of the srvAddrs, of a server struct, by rank from low to high.
873 void
874 afs_SortOneServer(struct server *asp)
876 struct srvAddr **rootsa, *lowsa, *tsa, *lowprev;
877 int lowrank, rank;
879 for (rootsa = &(asp->addr); *rootsa; rootsa = &(lowsa->next_sa)) {
880 lowprev = NULL;
881 lowsa = *rootsa; /* lowest sa is the first one */
882 lowrank = lowsa->sa_iprank;
884 for (tsa = *rootsa; tsa->next_sa; tsa = tsa->next_sa) {
885 rank = tsa->next_sa->sa_iprank;
886 if (rank < lowrank) {
887 lowprev = tsa;
888 lowsa = tsa->next_sa;
889 lowrank = lowsa->sa_iprank;
892 if (lowprev) { /* found one lower, so rearrange them */
893 lowprev->next_sa = lowsa->next_sa;
894 lowsa->next_sa = *rootsa;
895 *rootsa = lowsa;
900 /* afs_SortServer()
901 * Sort the pointer to servers by the server's rank (its lowest rank).
902 * It is assumed that the server already has its IP addrs sorted (the
903 * first being its lowest rank: afs_GetServer() calls afs_SortOneServer()).
905 void
906 afs_SortServers(struct server *aservers[], int count)
908 struct server *ts;
909 int i, j, low;
911 AFS_STATCNT(afs_SortServers);
913 for (i = 0; i < count; i++) {
914 if (!aservers[i])
915 break;
916 for (low = i, j = i + 1; j <= count; j++) {
917 if ((!aservers[j]) || (!aservers[j]->addr))
918 break;
919 if ((!aservers[low]) || (!aservers[low]->addr))
920 break;
921 if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
922 low = j;
925 if (low != i) {
926 ts = aservers[i];
927 aservers[i] = aservers[low];
928 aservers[low] = ts;
931 } /*afs_SortServers */
933 /* afs_SetServerPrefs is rather system-dependent. It pokes around in kernel
934 data structures to determine what the local IP addresses and subnet masks
935 are in order to choose which server(s) are on the local subnet.
937 As I see it, there are several cases:
938 1. The server address is one of this host's local addresses. In this case
939 this server is to be preferred over all others.
940 2. The server is on the same subnet as one of the this host's local
941 addresses. (ie, an odd-sized subnet, not class A,B,orC)
942 3. The server is on the same net as this host (class A,B or C)
943 4. The server is on a different logical subnet or net than this host, but
944 this host is a 'metric 0 gateway' to it. Ie, two address-spaces share
945 one physical medium.
946 5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
947 server.
948 6. This host and the server are disjoint.
950 That is a rough order of preference. If a point-to-point link has a high
951 metric, I'm assuming that it is a very slow link, and putting it at the
952 bottom of the list (at least until RX works better over slow links). If
953 its metric is 1, I'm assuming that it's relatively fast (T1) and putting
954 it ahead of #6.
955 It's not easy to check for case #4, so I'm ignoring it for the time being.
957 BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
958 That could be used to prefer certain servers fairly easily. Maybe some
959 other time...
961 NOTE: this code is very system-dependent, and very dependent on the TCP/IP
962 protocols (well, addresses that are stored in uint32s, at any rate).
965 #define IA_DST(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_dstaddr))
966 #define IA_BROAD(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
968 /* SA2ULONG takes a sockaddr_in, not a sockaddr (same thing, just cast it!) */
969 #define SA2ULONG(sa) ((sa)->sin_addr.s_addr)
970 #define TOPR 5000
971 #define HI 20000
972 #define MED 30000
973 #define LO DEFRANK
974 #define PPWEIGHT 4096
976 #define USEIFADDR
978 #ifdef AFS_USERSPACE_IP_ADDR
979 #ifndef afs_min
980 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
981 #endif
983 * The IP addresses and ranks are determined by afsd (in user space) and
984 * passed into the kernel at startup time through the AFSOP_ADVISEADDR
985 * system call. These are stored in the data structure
986 * called 'afs_cb_interface'.
988 * struct srvAddr *sa; remote server
989 * afs_int32 addr; one of my local addr in net order
990 * afs_uint32 subnetmask; subnet mask of local addr in net order
993 void
994 afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr,
995 afs_uint32 subnetmask)
997 afs_uint32 myAddr, myNet, mySubnet, netMask;
998 afs_uint32 serverAddr;
1000 myAddr = ntohl(addr); /* one of my IP addr in host order */
1001 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1002 subnetmask = ntohl(subnetmask); /* subnet mask in host order */
1004 if (IN_CLASSA(myAddr))
1005 netMask = IN_CLASSA_NET;
1006 else if (IN_CLASSB(myAddr))
1007 netMask = IN_CLASSB_NET;
1008 else if (IN_CLASSC(myAddr))
1009 netMask = IN_CLASSC_NET;
1010 else
1011 netMask = 0;
1013 myNet = myAddr & netMask;
1014 mySubnet = myAddr & subnetmask;
1016 if ((serverAddr & netMask) == myNet) {
1017 if ((serverAddr & subnetmask) == mySubnet) {
1018 if (serverAddr == myAddr) { /* same machine */
1019 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1020 } else { /* same subnet */
1021 sa->sa_iprank = afs_min(sa->sa_iprank, HI);
1023 } else { /* same net */
1024 sa->sa_iprank = afs_min(sa->sa_iprank, MED);
1027 return;
1029 #else /* AFS_USERSPACE_IP_ADDR */
1030 #if (! defined(AFS_SUN5_ENV)) && (! defined(AFS_DARWIN_ENV)) && (! defined(AFS_OBSD47_ENV)) && (! defined(AFS_FBSD_ENV)) && defined(USEIFADDR)
1031 void
1032 afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
1034 struct sockaddr_in *sin;
1035 int t;
1037 if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
1038 if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
1039 sin = IA_SIN(ifa);
1040 if (SA2ULONG(sin) == ntohl(sa->sa_ip)) { /* ie, ME!!! */
1041 sa->sa_iprank = TOPR;
1042 } else {
1043 t = HI + ifa->ia_ifp->if_metric; /* case #2 */
1044 if (sa->sa_iprank > t)
1045 sa->sa_iprank = t;
1047 } else {
1048 t = MED + ifa->ia_ifp->if_metric; /* case #3 */
1049 if (sa->sa_iprank > t)
1050 sa->sa_iprank = t;
1053 #if defined(IFF_POINTOPOINT) && !defined(UKERNEL)
1054 /* check for case #4 -- point-to-point link */
1055 if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
1056 && (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
1057 if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1058 t = MAXDEFRANK;
1059 else
1060 t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
1061 if (sa->sa_iprank > t)
1062 sa->sa_iprank = t;
1064 #endif /* IFF_POINTOPOINT */
1066 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1067 #if (defined(AFS_DARWIN_ENV) || defined(AFS_OBSD47_ENV) || defined(AFS_FBSD_ENV)) && defined(USEIFADDR)
1068 #ifndef afs_min
1069 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1070 #endif
1071 void
1072 afsi_SetServerIPRank(struct srvAddr *sa, rx_ifaddr_t ifa)
1074 struct sockaddr sout;
1075 struct sockaddr_in *sin;
1076 #if defined(AFS_DARWIN80_ENV) && !defined(UKERNEL)
1077 int t;
1078 #else
1079 void *t;
1080 #endif
1082 afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
1083 afs_uint32 serverAddr;
1085 if (rx_ifaddr_address_family(ifa) != AF_INET)
1086 return;
1087 t = rx_ifaddr_address(ifa, &sout, sizeof(sout));
1088 if (t != 0) {
1089 sin = (struct sockaddr_in *)&sout;
1090 myAddr = ntohl(sin->sin_addr.s_addr); /* one of my IP addr in host order */
1091 } else {
1092 myAddr = 0;
1094 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1095 t = rx_ifaddr_netmask(ifa, &sout, sizeof(sout));
1096 if (t != 0) {
1097 sin = (struct sockaddr_in *)&sout;
1098 subnetmask = ntohl(sin->sin_addr.s_addr); /* subnet mask in host order */
1099 } else {
1100 subnetmask = 0;
1102 t = rx_ifaddr_dstaddress(ifa, &sout, sizeof(sout));
1103 if (t != 0) {
1104 sin = (struct sockaddr_in *)&sout;
1105 myDstaddr = ntohl(sin->sin_addr.s_addr);
1106 } else {
1107 myDstaddr = 0;
1110 if (IN_CLASSA(myAddr))
1111 netMask = IN_CLASSA_NET;
1112 else if (IN_CLASSB(myAddr))
1113 netMask = IN_CLASSB_NET;
1114 else if (IN_CLASSC(myAddr))
1115 netMask = IN_CLASSC_NET;
1116 else
1117 netMask = 0;
1119 myNet = myAddr & netMask;
1120 mySubnet = myAddr & subnetmask;
1122 if ((serverAddr & netMask) == myNet) {
1123 if ((serverAddr & subnetmask) == mySubnet) {
1124 if (serverAddr == myAddr) { /* same machine */
1125 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1126 } else { /* same subnet */
1127 sa->sa_iprank = afs_min(sa->sa_iprank, HI + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1129 } else { /* same net */
1130 sa->sa_iprank = afs_min(sa->sa_iprank, MED + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1133 #ifdef IFF_POINTTOPOINT
1134 /* check for case #4 -- point-to-point link */
1135 if ((rx_ifnet_flags(rx_ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
1136 && (myDstaddr == serverAddr)) {
1137 if (rx_ifnet_metric(rx_ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
1138 t = MAXDEFRANK;
1139 else
1140 t = MED + (PPWEIGHT << rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1141 if (sa->sa_iprank > t)
1142 sa->sa_iprank = t;
1144 #endif /* IFF_POINTTOPOINT */
1146 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1147 #endif /* else AFS_USERSPACE_IP_ADDR */
1149 #ifdef AFS_SGI62_ENV
1150 static int
1151 afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1152 caddr_t arg2)
1154 afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
1155 return 0; /* Never match, so we enumerate everyone */
1157 #endif /* AFS_SGI62_ENV */
1158 static int
1159 afs_SetServerPrefs(struct srvAddr *const sa)
1161 #if defined(AFS_USERSPACE_IP_ADDR)
1162 int i;
1164 sa->sa_iprank = LO;
1165 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1166 afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1167 afs_cb_interface.subnetmask[i]);
1169 #else /* AFS_USERSPACE_IP_ADDR */
1170 #if defined(AFS_SUN5_ENV)
1171 #ifdef AFS_SUN510_ENV
1172 int i = 0;
1173 #else
1174 extern struct ill_s *ill_g_headp;
1175 long *addr = (long *)ill_g_headp;
1176 ill_t *ill;
1177 ipif_t *ipif;
1178 #endif
1179 int subnet, subnetmask, net, netmask;
1181 sa->sa_iprank = 0;
1182 #ifdef AFS_SUN510_ENV
1183 rw_enter(&afsifinfo_lock, RW_READER);
1185 for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
1187 if (IN_CLASSA(afsifinfo[i].ipaddr)) {
1188 netmask = IN_CLASSA_NET;
1189 } else if (IN_CLASSB(afsifinfo[i].ipaddr)) {
1190 netmask = IN_CLASSB_NET;
1191 } else if (IN_CLASSC(afsifinfo[i].ipaddr)) {
1192 netmask = IN_CLASSC_NET;
1193 } else {
1194 netmask = 0;
1196 net = afsifinfo[i].ipaddr & netmask;
1199 /* XXXXXX Do the individual ip ranking below XXXXX */
1200 if ((sa->sa_ip & netmask) == net) {
1201 if ((sa->sa_ip & subnetmask) == subnet) {
1202 if (afsifinfo[i].ipaddr == sa->sa_ip) { /* ie, ME! */
1203 sa->sa_iprank = TOPR;
1204 } else {
1205 sa->sa_iprank = HI + afsifinfo[i].metric; /* case #2 */
1207 } else {
1208 sa->sa_iprank = MED + afsifinfo[i].metric; /* case #3 */
1210 } else {
1211 sa->sa_iprank = LO + afsifinfo[i].metric; /* case #4 */
1213 /* check for case #5 -- point-to-point link */
1214 if ((afsifinfo[i].flags & IFF_POINTOPOINT)
1215 && (afsifinfo[i].dstaddr == sa->sa_ip)) {
1217 if (afsifinfo[i].metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1218 sa->sa_iprank = MAXDEFRANK;
1219 else
1220 sa->sa_iprank = MED + (PPWEIGHT << afsifinfo[i].metric);
1225 rw_exit(&afsifinfo_lock);
1226 #else
1227 for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
1228 ill = ill->ill_next) {
1229 /* Make sure this is an IPv4 ILL */
1230 if (ill->ill_isv6)
1231 continue;
1232 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
1233 subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1234 subnetmask = ipif->ipif_net_mask;
1236 * Generate the local net using the local address and
1237 * whate we know about Class A, B and C networks.
1239 if (IN_CLASSA(ipif->ipif_local_addr)) {
1240 netmask = IN_CLASSA_NET;
1241 } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1242 netmask = IN_CLASSB_NET;
1243 } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1244 netmask = IN_CLASSC_NET;
1245 } else {
1246 netmask = 0;
1248 net = ipif->ipif_local_addr & netmask;
1250 /* XXXXXX Do the individual ip ranking below XXXXX */
1251 if ((sa->sa_ip & netmask) == net) {
1252 if ((sa->sa_ip & subnetmask) == subnet) {
1253 if (ipif->ipif_local_addr == sa->sa_ip) { /* ie, ME! */
1254 sa->sa_iprank = TOPR;
1255 } else {
1256 sa->sa_iprank = HI + ipif->ipif_metric; /* case #2 */
1258 } else {
1259 sa->sa_iprank = MED + ipif->ipif_metric; /* case #3 */
1261 } else {
1262 sa->sa_iprank = LO + ipif->ipif_metric; /* case #4 */
1264 /* check for case #5 -- point-to-point link */
1265 if ((ipif->ipif_flags & IFF_POINTOPOINT)
1266 && (ipif->ipif_pp_dst_addr == sa->sa_ip)) {
1268 if (ipif->ipif_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1269 sa->sa_iprank = MAXDEFRANK;
1270 else
1271 sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1276 #endif /* AFS_SUN510_ENV */
1277 #else
1278 #ifndef USEIFADDR
1279 rx_ifnet_t ifn = NULL;
1280 struct in_ifaddr *ifad = (struct in_ifaddr *)0;
1281 struct sockaddr_in *sin;
1283 sa->sa_iprank = 0;
1284 ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1285 if (ifn) { /* local, more or less */
1286 #ifdef IFF_LOOPBACK
1287 if (ifn->if_flags & IFF_LOOPBACK) {
1288 sa->sa_iprank = TOPR;
1289 goto end;
1291 #endif /* IFF_LOOPBACK */
1292 sin = (struct sockaddr_in *)IA_SIN(ifad);
1293 if (SA2ULONG(sin) == sa->sa_ip) {
1294 sa->sa_iprank = TOPR;
1295 goto end;
1297 #ifdef IFF_BROADCAST
1298 if (ifn->if_flags & IFF_BROADCAST) {
1299 if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1300 sa->sa_iprank = HI;
1301 goto end;
1304 #endif /* IFF_BROADCAST */
1305 #ifdef IFF_POINTOPOINT
1306 if (ifn->if_flags & IFF_POINTOPOINT) {
1307 if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1308 if (ifn->if_metric > 4) {
1309 sa->sa_iprank = LO;
1310 goto end;
1311 } else
1312 sa->sa_iprank = ifn->if_metric;
1315 #endif /* IFF_POINTOPOINT */
1316 sa->sa_iprank += MED + ifn->if_metric; /* couldn't find anything better */
1318 #else /* USEIFADDR */
1320 sa->sa_iprank = LO;
1321 #ifdef AFS_SGI62_ENV
1322 (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1323 (caddr_t) sa, NULL);
1324 #elif defined(AFS_DARWIN80_ENV)
1326 errno_t t;
1327 unsigned int count;
1328 int cnt=0, m, j;
1329 rx_ifaddr_t *ifads;
1330 rx_ifnet_t *ifns;
1332 if (!ifnet_list_get(AF_INET, &ifns, &count)) {
1333 for (m = 0; m < count; m++) {
1334 if (!ifnet_get_address_list(ifns[m], &ifads)) {
1335 for (j = 0; ifads[j] != NULL && cnt < ADDRSPERSITE; j++) {
1336 afsi_SetServerIPRank(sa, ifads[j]);
1337 cnt++;
1339 ifnet_free_address_list(ifads);
1342 ifnet_list_free(ifns);
1345 #elif defined(AFS_DARWIN_ENV)
1347 rx_ifnet_t ifn;
1348 rx_ifaddr_t ifa;
1349 TAILQ_FOREACH(ifn, &ifnet, if_link) {
1350 TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
1351 afsi_SetServerIPRank(sa, ifa);
1353 #elif defined(AFS_FBSD_ENV)
1355 struct in_ifaddr *ifa;
1356 #if defined(AFS_FBSD80_ENV)
1357 TAILQ_FOREACH(ifa, &V_in_ifaddrhead, ia_link) {
1358 #else
1359 TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
1360 #endif
1361 afsi_SetServerIPRank(sa, &ifa->ia_ifa);
1363 #elif defined(AFS_OBSD_ENV)
1365 extern struct in_ifaddrhead in_ifaddr;
1366 struct in_ifaddr *ifa;
1367 for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1368 afsi_SetServerIPRank(sa, ifa);
1370 #elif defined(AFS_NBSD40_ENV)
1372 extern struct in_ifaddrhead in_ifaddrhead;
1373 struct in_ifaddr *ifa;
1374 for (ifa = in_ifaddrhead.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1375 afsi_SetServerIPRank(sa, ifa);
1377 #else
1379 struct in_ifaddr *ifa;
1380 for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
1381 afsi_SetServerIPRank(sa, ifa);
1383 #endif
1384 #endif /* USEIFADDR */
1385 #ifndef USEIFADDR
1386 end:
1387 #endif
1388 #endif /* AFS_SUN5_ENV */
1389 #endif /* else AFS_USERSPACE_IP_ADDR */
1390 sa->sa_iprank += afs_randomMod15();
1392 return 0;
1393 } /* afs_SetServerPrefs */
1395 #undef TOPR
1396 #undef HI
1397 #undef MED
1398 #undef LO
1399 #undef PPWEIGHT
1401 /* afs_FlushServer()
1402 * The addresses on this server struct has changed in some way and will
1403 * clean up all other structures that may reference it.
1404 * The afs_xserver, afs_xvcb and afs_xsrvAddr locks are assumed taken.
1406 static void
1407 afs_FlushServer(struct server *srvp, struct volume *tv)
1409 afs_int32 i;
1410 struct server *ts, **pts;
1412 /* Find any volumes residing on this server and flush their state */
1413 afs_ResetVolumes(srvp, tv);
1415 /* Flush all callbacks in the all vcaches for this specific server */
1416 afs_FlushServerCBs(srvp);
1418 /* Remove all the callbacks structs */
1419 if (srvp->cbrs) {
1420 struct afs_cbr *cb, *cbnext;
1422 for (cb = srvp->cbrs; cb; cb = cbnext) {
1423 cbnext = cb->next;
1424 afs_FreeCBR(cb);
1425 } srvp->cbrs = (struct afs_cbr *)0;
1428 /* If no more srvAddr structs hanging off of this server struct,
1429 * then clean it up.
1431 if (!srvp->addr) {
1432 /* Remove the server structure from the cell list - if there */
1433 afs_RemoveCellEntry(srvp);
1435 /* Remove from the afs_servers hash chain */
1436 for (i = 0; i < NSERVERS; i++) {
1437 for (pts = &(afs_servers[i]), ts = *pts; ts;
1438 pts = &(ts->next), ts = *pts) {
1439 if (ts == srvp)
1440 break;
1442 if (ts)
1443 break;
1445 if (ts) {
1446 *pts = ts->next; /* Found it. Remove it */
1447 afs_osi_Free(ts, sizeof(struct server)); /* Free it */
1448 afs_totalServers--;
1453 /* afs_RemoveSrvAddr()
1454 * This removes a SrvAddr structure from its server structure.
1455 * The srvAddr struct is not free'd because it connections may still
1456 * be open to it. It is up to the calling process to make sure it
1457 * remains connected to a server struct.
1458 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1459 * It is not removed from the afs_srvAddrs hash chain.
1460 * If resetting volumes, do not reset volume tv
1462 static void
1463 afs_RemoveSrvAddr(struct srvAddr *sap, struct volume *tv)
1465 struct srvAddr **psa, *sa;
1466 struct server *srv;
1468 if (!sap)
1469 return;
1470 srv = sap->server;
1472 /* Find the srvAddr in the server's list and remove it */
1473 for (psa = &(srv->addr), sa = *psa; sa; psa = &(sa->next_sa), sa = *psa) {
1474 if (sa == sap)
1475 break;
1476 } if (sa) {
1477 *psa = sa->next_sa;
1478 sa->next_sa = 0;
1479 sa->server = 0;
1481 /* Flush the server struct since it's IP address has changed */
1482 afs_FlushServer(srv, tv);
1486 /* afs_GetCapabilities
1487 * Try and retrieve capabilities of a given file server. Carps on actual
1488 * failure. Servers are not expected to support this RPC. */
1489 void
1490 afs_GetCapabilities(struct server *ts)
1492 Capabilities caps = {0, NULL};
1493 struct vrequest *treq = NULL;
1494 struct afs_conn *tc;
1495 struct unixuser *tu;
1496 struct rx_connection *rxconn;
1497 afs_int32 code;
1499 if ( !ts || !ts->cell )
1500 return;
1501 if ( !afs_osi_credp )
1502 return;
1504 if ((code = afs_CreateReq(&treq, afs_osi_credp)))
1505 return;
1506 tu = afs_GetUser(treq->uid, ts->cell->cellNum, SHARED_LOCK);
1507 if ( !tu ) {
1508 afs_DestroyReq(treq);
1509 return;
1511 tc = afs_ConnBySA(ts->addr, ts->cell->fsport, ts->cell->cellNum, tu, 0, 1,
1512 SHARED_LOCK, 0, &rxconn);
1513 afs_PutUser(tu, SHARED_LOCK);
1514 if ( !tc ) {
1515 afs_DestroyReq(treq);
1516 return;
1518 /* InitCallBackStateN, triggered by our RPC, may need this */
1519 ReleaseWriteLock(&afs_xserver);
1520 code = RXAFS_GetCapabilities(rxconn, &caps);
1521 ObtainWriteLock(&afs_xserver, 723);
1522 /* we forced a conn above; important we mark it down if needed */
1523 if ((code < 0) && (code != RXGEN_OPCODE)) {
1524 afs_ServerDown(tc->parent->srvr, code, rxconn);
1525 ForceNewConnections(tc->parent->srvr); /* multi homed clients */
1527 afs_PutConn(tc, rxconn, SHARED_LOCK);
1528 if ( code && code != RXGEN_OPCODE ) {
1529 afs_warn("RXAFS_GetCapabilities failed with code %d\n", code);
1530 /* better not be anything to free. we failed! */
1531 afs_DestroyReq(treq);
1532 return;
1535 ts->flags |= SCAPS_KNOWN;
1537 if ( caps.Capabilities_len > 0 ) {
1538 ts->capabilities = caps.Capabilities_val[0];
1539 xdr_free((xdrproc_t)xdr_Capabilities, &caps);
1540 caps.Capabilities_len = 0;
1541 caps.Capabilities_val = NULL;
1544 afs_DestroyReq(treq);
1547 static struct server *
1548 afs_SearchServer(u_short aport, afsUUID * uuidp, afs_int32 locktype,
1549 struct server **oldts, afs_int32 addr_uniquifier)
1551 struct server *ts = afs_FindServer(0, aport, uuidp, locktype);
1552 if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1553 /* Found a server struct that is multihomed and same
1554 * uniqufier (same IP addrs). The above if statement is the
1555 * same as in InstallUVolumeEntry().
1557 return ts;
1559 if (ts)
1560 *oldts = ts; /* Will reuse if same uuid */
1561 return NULL;
1565 * Return an updated and properly initialized server structure.
1567 * Takes a server ID, cell, and port.
1568 * If server does not exist, then one will be created.
1569 * @param[in] aserverp
1570 * The server address in network byte order
1571 * @param[in] nservers
1572 * The number of IP addresses claimed by the server
1573 * @param[in] acell
1574 * The cell the server is in
1575 * @param[in] aport
1576 * The port for the server (fileserver or vlserver) in network byte order
1577 * @param[in] locktype
1578 * The type of lock to hold when iterating server hash (unused).
1579 * @param[in] uuidp
1580 * The uuid for servers supporting one.
1581 * @param[in] addr_uniquifier
1582 * The vldb-provider per-instantiated-server uniquifer counter.
1583 * @param[in] tv
1584 * A volume not to reset information for if the server addresses
1585 * changed.
1587 * @return
1588 * A server structure matching the request.
1590 struct server *
1591 afs_GetServer(afs_uint32 *aserverp, afs_int32 nservers, afs_int32 acell,
1592 u_short aport, afs_int32 locktype, afsUUID * uuidp,
1593 afs_int32 addr_uniquifier, struct volume *tv)
1595 struct server *oldts = 0, *ts, *newts, *orphts = 0;
1596 struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1597 afs_int32 iphash, k, srvcount = 0;
1598 unsigned int srvhash;
1600 AFS_STATCNT(afs_GetServer);
1602 ObtainSharedLock(&afs_xserver, 13);
1604 /* Check if the server struct exists and is up to date */
1605 if (!uuidp) {
1606 if (nservers != 1)
1607 panic("afs_GetServer: incorrect count of servers");
1608 ObtainReadLock(&afs_xsrvAddr);
1609 ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1610 ReleaseReadLock(&afs_xsrvAddr);
1611 if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1612 /* Found a server struct that is not multihomed and has the
1613 * IP address associated with it. A correct match.
1615 ReleaseSharedLock(&afs_xserver);
1616 return (ts);
1618 } else {
1619 if (nservers <= 0)
1620 panic("afs_GetServer: incorrect count of servers");
1622 ts = afs_SearchServer(aport, uuidp, locktype, &oldts, addr_uniquifier);
1623 if (ts) {
1624 ReleaseSharedLock(&afs_xserver);
1625 return ts;
1630 * Lock hierarchy requires xvcb, then xserver. We *have* xserver.
1631 * Do a little dance and see if we can grab xvcb. If not, we
1632 * need to recheck that oldts is still right after a drop and reobtain.
1634 if (EWOULDBLOCK == NBObtainWriteLock(&afs_xvcb, 300)) {
1635 ReleaseSharedLock(&afs_xserver);
1636 ObtainWriteLock(&afs_xvcb, 299);
1637 ObtainWriteLock(&afs_xserver, 35);
1639 /* we don't know what changed while we didn't hold the lock */
1640 oldts = 0;
1641 ts = afs_SearchServer(aport, uuidp, locktype, &oldts,
1642 addr_uniquifier);
1643 if (ts) {
1644 ReleaseWriteLock(&afs_xserver);
1645 ReleaseWriteLock(&afs_xvcb);
1646 return ts;
1648 } else {
1649 UpgradeSToWLock(&afs_xserver, 36);
1651 ObtainWriteLock(&afs_xsrvAddr, 116);
1652 srvcount = afs_totalServers;
1654 /* Reuse/allocate a new server structure */
1655 if (oldts) {
1656 newts = oldts;
1657 } else {
1658 newts = afs_osi_Alloc(sizeof(struct server));
1659 if (!newts)
1660 panic("malloc of server struct");
1661 afs_totalServers++;
1662 memset(newts, 0, sizeof(struct server));
1664 /* Add the server struct to the afs_servers[] hash chain */
1665 srvhash =
1666 (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
1667 newts->next = afs_servers[srvhash];
1668 afs_servers[srvhash] = newts;
1671 /* Initialize the server structure */
1672 if (uuidp) { /* Multihomed */
1673 newts->sr_uuid = *uuidp;
1674 newts->sr_addr_uniquifier = addr_uniquifier;
1675 newts->flags |= SRVR_MULTIHOMED;
1677 if (acell)
1678 /* Use the afs_GetCellStale variant to avoid afs_GetServer recursion. */
1679 newts->cell = afs_GetCellStale(acell, 0);
1681 /* For each IP address we are registering */
1682 for (k = 0; k < nservers; k++) {
1683 iphash = SHash(aserverp[k]);
1685 /* Check if the srvAddr structure already exists. If so, remove
1686 * it from its server structure and add it to the new one.
1688 for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
1689 if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
1690 break;
1692 if (oldsa && (oldsa->server != newts)) {
1693 afs_RemoveSrvAddr(oldsa, tv); /* Remove from its server struct */
1694 oldsa->next_sa = newts->addr; /* Add to the new server struct */
1695 newts->addr = oldsa;
1698 /* Reuse/allocate a new srvAddr structure */
1699 if (oldsa) {
1700 newsa = oldsa;
1701 } else {
1702 newsa = afs_osi_Alloc(sizeof(struct srvAddr));
1703 if (!newsa)
1704 panic("malloc of srvAddr struct");
1705 afs_totalSrvAddrs++;
1706 memset(newsa, 0, sizeof(struct srvAddr));
1708 /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1709 newsa->next_bkt = afs_srvAddrs[iphash];
1710 afs_srvAddrs[iphash] = newsa;
1712 /* Hang off of the server structure */
1713 newsa->next_sa = newts->addr;
1714 newts->addr = newsa;
1716 /* Initialize the srvAddr Structure */
1717 newsa->sa_ip = aserverp[k];
1718 newsa->sa_portal = aport;
1721 /* Update the srvAddr Structure */
1722 newsa->server = newts;
1723 if (newts->flags & SRVR_ISDOWN)
1724 newsa->sa_flags |= SRVADDR_ISDOWN;
1725 if (uuidp)
1726 newsa->sa_flags |= SRVADDR_MH;
1727 else
1728 newsa->sa_flags &= ~SRVADDR_MH;
1730 /* Compute preference values and resort */
1731 if (!newsa->sa_iprank) {
1732 afs_SetServerPrefs(newsa); /* new server rank */
1735 afs_SortOneServer(newts); /* Sort by rank */
1737 /* If we reused the server struct, remove any of its srvAddr
1738 * structs that will no longer be associated with this server.
1740 if (oldts) { /* reused the server struct */
1741 for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
1742 nextsa = orphsa->next_sa;
1743 for (k = 0; k < nservers; k++) {
1744 if (orphsa->sa_ip == aserverp[k])
1745 break; /* belongs */
1747 if (k < nservers)
1748 continue; /* belongs */
1750 /* Have a srvAddr struct. Now get a server struct (if not already) */
1751 if (!orphts) {
1752 orphts = afs_osi_Alloc(sizeof(struct server));
1753 if (!orphts)
1754 panic("malloc of lo server struct");
1755 memset(orphts, 0, sizeof(struct server));
1756 afs_totalServers++;
1758 /* Add the orphaned server to the afs_servers[] hash chain.
1759 * Its iphash does not matter since we never look up the server
1760 * in the afs_servers table by its ip address (only by uuid -
1761 * which this has none).
1763 iphash = SHash(aserverp[k]);
1764 orphts->next = afs_servers[iphash];
1765 afs_servers[iphash] = orphts;
1767 if (acell)
1768 /* Use the afs_GetCellStale variant to avoid afs_GetServer recursion. */
1769 orphts->cell = afs_GetCellStale(acell, 0);
1772 /* Hang the srvAddr struct off of the server structure. The server
1773 * may have multiple srvAddrs, but it won't be marked multihomed.
1775 afs_RemoveSrvAddr(orphsa, tv); /* remove */
1776 orphsa->next_sa = orphts->addr; /* hang off server struct */
1777 orphts->addr = orphsa;
1778 orphsa->server = orphts;
1779 orphsa->sa_flags |= SRVADDR_NOUSE; /* flag indicating not in use */
1780 orphsa->sa_flags &= ~SRVADDR_MH; /* Not multihomed */
1783 /* We can't need this below, and won't reacquire */
1784 ReleaseWriteLock(&afs_xvcb);
1786 srvcount = afs_totalServers - srvcount; /* # servers added and removed */
1787 if (srvcount) {
1788 struct afs_stats_SrvUpDownInfo *upDownP;
1789 /* With the introduction of this new record, we need to adjust the
1790 * proper individual & global server up/down info.
1792 upDownP = GetUpDownStats(newts);
1793 upDownP->numTtlRecords += srvcount;
1794 afs_stats_cmperf.srvRecords += srvcount;
1795 if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
1796 afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
1798 /* We can't need this below, and won't reacquire */
1799 ReleaseWriteLock(&afs_xvcb);
1801 ReleaseWriteLock(&afs_xsrvAddr);
1803 if ( aport == AFS_FSPORT && !(newts->flags & SCAPS_KNOWN))
1804 afs_GetCapabilities(newts);
1806 ReleaseWriteLock(&afs_xserver);
1807 return (newts);
1808 } /* afs_GetServer */
1810 void
1811 afs_ActivateServer(struct srvAddr *sap)
1813 osi_timeval_t currTime; /*Filled with current time */
1814 osi_timeval_t *currTimeP; /*Ptr to above */
1815 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record */
1816 struct server *aserver = sap->server;
1818 if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
1820 * This server record has not yet been activated. Go for it,
1821 * recording its ``birth''.
1823 aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
1824 currTimeP = &currTime;
1825 osi_GetuTime(currTimeP);
1826 aserver->activationTime = currTime.tv_sec;
1827 upDownP = GetUpDownStats(aserver);
1828 if (aserver->flags & SRVR_ISDOWN) {
1829 upDownP->numDownRecords++;
1830 } else {
1831 upDownP->numUpRecords++;
1832 upDownP->numRecordsNeverDown++;
1837 void
1838 afs_RemoveAllConns(void)
1840 int i;
1841 struct server *ts, *nts;
1842 struct srvAddr *sa;
1844 ObtainReadLock(&afs_xserver);
1845 ObtainWriteLock(&afs_xconn, 1001);
1847 /*printf("Destroying connections ... ");*/
1848 for (i = 0; i < NSERVERS; i++) {
1849 for (ts = afs_servers[i]; ts; ts = nts) {
1850 nts = ts->next;
1851 for (sa = ts->addr; sa; sa = sa->next_sa) {
1852 if (sa->conns) {
1853 afs_ReleaseConns(sa->conns);
1854 sa->conns = NULL;
1855 sa->natping = NULL;
1860 /*printf("done\n");*/
1862 ReleaseWriteLock(&afs_xconn);
1863 ReleaseReadLock(&afs_xserver);
1867 void
1868 afs_MarkAllServersUp(void)
1870 int i;
1871 struct server *ts;
1872 struct srvAddr *sa;
1874 ObtainWriteLock(&afs_xserver, 721);
1875 ObtainWriteLock(&afs_xsrvAddr, 722);
1876 for (i = 0; i< NSERVERS; i++) {
1877 for (ts = afs_servers[i]; ts; ts = ts->next) {
1878 for (sa = ts->addr; sa; sa = sa->next_sa) {
1879 afs_MarkServerUpOrDown(sa, 0);
1883 ReleaseWriteLock(&afs_xsrvAddr);
1884 ReleaseWriteLock(&afs_xserver);