Subject: Re: SETCLIENTID issues (long)

From: [email-masked]
Date: Mon, 22 Jul 2002 11:02:23 -0500

Mike,

This is good information, thanks for posting it.
Just a couple of remarks on some of the sections below.

.
.

> - The inclusion of the callback and callback_ident fields
>   in hindsight, may have been a mistake. The reason is that
>   SETCLIENTID ought to be focused on the tricky problem
>   of safely establishing the clientid4 value. There should
>   have been a separate, SETCALLBACK operation. This way, we
>   would not issues with how to change callback information
>   without perturbing our hard won clientid4 value. I am
>   not proposing adding the SETCALLBACK operation though,
>   because it is not necessary (IMHO) to make the protocol
>   work.
>

This is essentially the idea I suggested by adding
the clientid4 into the SETCLIENTID args. A clientid4 of 0,
means the client is doing its initial SETCLIENTID call in
order to get its clientid created at the server. If the client
wants to update its callback information, it makes the
SETCLIENTID call with its assigned clientid4 value. So a
SETCLIENTID call with clientid4 == 0, is the classic SETCLIENTID
call. When clientid4 is non-zero (the server created clientid),
its effectively your suggested SETCALLBACK operation.
Of course, this implies that 0 is not a valid clientid4 value for a
server to assign.

I obviously was not clear enough in my earlier suggestion, since you
concluded that I was suggesting new persistent state at the server. That
was not my intent. It really is the concept you have described with your
SETCALLBACK op where the client uses its established clientid4 to update
its attributes. I like your idea of a separate operation better.
.
.
.

** On July 8, Rick asks

> > How is the server supposed to distinguish between a client
> > doing a retry of setclientid and different clients doing
>
> Let x be the "id" field of the nfs_client_id4 struct,
> v be the verifier, and c be the clientid4 value.
>
> A client that does a retry of a SETCLIENTID { v, x }
> gets the following result depending on the following cases:
>
.
.
.
.
>
> - DRC miss and server has recorded a confirmed { u, x, c }
>   such that v != u and has not recorded any unconfirmed
>   { *, x, * } record for x.  The server records an
>   unconfirmed { v, x, d } (d != c). The server awaits
>   confirmation of d via SETCLIENTID_CONFIRM.
>

 Is this really true given x (the nfs_client_id4.id value)
 is the same? I thought this case represents a rebooted client
 with a new verifier (assuming auth is the same). Isn't the
 server supposed to return clientid4 c so the following
 SETCLIENTID_CONFIRM call causes the server to release the
 state for the previous life of x. If the server creates
 a new record with clientid4 d, what is going to reclaim the
 record and associated state for {u, x, c}? Where did I get
 confused?
.
.
.
.
> That said, there will inevitably be NFS4ERR_CLID_INUSE
> errors reported whether due to server or client bugs, or the
> improbable occurring.  As Spencer wrote on July 18, the
> client that has done its level best to pick a collision
> free id string that still gets NFS4ERR_CLID_INUSE can use
> this algorithm: "have it [the client] wait a server lease
> period and retry the operation". I would add, that if the
> client still gets NFS4ERR_CLID_INUSE, we can assume that
> another client has usurped the id string. This is why
> the SETCLIENTID4 results look like this:
>
>   union SETCLIENTID4res switch (nfsstat4 status) {
>    case NFS4_OK:
>               SETCLIENTID4resok      resok4;
>    case NFS4ERR_CLID_INUSE:
>               clientaddr4    client_using;
>    default:
>               void;
>   };
>
> The client that gets an NFS4ERR_CLID_INUSE after waiting
> the lease period should log the offending client's
> address. Such a client might also check whether the
> offending address is one that of the client getting the
> NFS4ERR_CLID_INUSE error.
>

Would it also be acceptable for the client to then retry
the SETCLIENTID with a newly generated nfs_client_id4.id
value after it has logged a message and evaluated the
client_using information?

Carl

Carl Burnett
AIX Kernel Architecture - Distributed File Systems
(512) 838-8498, TL 678-8498
(please reply to [email-masked])

---

From: Mike Eisler <[email-masked]>
Date: Wed, 24 Jul 2002 10:46:53 -0700

Apologies for not responding sooner. I've been
having problem integrating my email setup with my vpn
setup.

> with a new verifier (assuming auth is the same). Isn't the

What has probably happenned in this scenario is that the client
has rebooted and issued an RPC SETCLIENTID { v, x }
which did not make it to the server. The client then retries.
What ha spossibly happenned is the Byzantine router scenario
that replays an old RPC request. My description deals with
either scenaro.

The server has recorded verifier u for client id string x, with
clientid4 c.. The client has sent verifier
v for the same client id string x. It is indeed a possibly rebooted client.
Or it might be the Byzantine router scenario.

What may not have been clear is that the server always responds to
to a SETCLIENTID. Thye question is what to respond with,
c or d. It is d in this case.

 > server supposed to return clientid4 c so the following

No, the server has to return clientid4 d.

> record and associated state for {u, x, c}? Where did I get

If the client truly wants to establish a new clientid4 and
thereby delete all the state associated with clientid4 c,
then it must follow up with a SETCLIENTID_CONFIRM { d }.

> client_using information

Certainly. But then the onus is on the client to implement a way to 
generate the
same nfs_client_id4.id string when it reboots. There's no requirement in the
NFSv4 specification for clients to record their generated nfs_client_id4.id
string into stable storage (for example the client may not have any local
stable storage ... it might be a diskless and getting its root partition 
from the
same NFSv4 server it is doing SETCLIENTID to).
    -mre