-
Couldn't load subscription status.
- Fork 364
Symmetric routing draft #5810
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Symmetric routing draft #5810
Conversation
+on-hear-packet updates the pending and sponsees maps. +send-packet gets the lane(s) to send the packet to from the relay-state and writes the next field if forwarding.
Behn is used to delete lanes from the pending and sponsees maps after 30s without activity.
| %+ can 0 | ||
| :~ [3 reserved=0] | ||
| :~ [1 reserved=0] | ||
| [2 packet-type=0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll need at a bit to represent "is this a request?", i.e. not a response. The is-ames bit should also be consolidated into the 2-bit packet-type field to save space, and of course this function should return these new values -- my inclination would be to add the fields to the $packet type.
This is a note as much to myself as to you:
Something to keep in mind with this sort of change to the packet format is that we should ensure packets at this version are discriminable from older packets. In this case it's good enough just to look at the protocol version, but I was hoping each protocol could develop its own version to enable per-protocol updates later. We could probably still do that, though, by looking at both the protocol version bits and the packet-type bits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What would the request/response bit be used for? My current implementation is request/response agnostic. I'm setting the next lane on every forwarded packet. Is this a bad idea?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's legitimate, though maybe not useful, for a relay to set the .next field unconditionally. The relay needs to know where to forward the packet, though, which is why I think we need the request/response bit.
In Ames's current asymmetric routing, the relay doesn't care whether a packet is a request or response, so it forwards the packet to some of the destination ship's sponsors list either way. Symmetric routing needs to route responses differently from requests, though.
In symmetric routing, only the requesting ship needs to send a packet to potentially multiple sponsors. All other ships just send to a single lane. A ship in the responder's sponsors list relays a request down to the next ship down the sponsorship chain, which might be the responder ship itself. A ship sends or relays a response on whatever lane it heard the request packet come from, which is either its immediate sponsor's lane or the requester's lane.
You could almost look this up from PKI information, since if a packet's sender is our transitive sponsee and the receiver is not, it's a response, and if the receiver is our transitive sponsee and the sender is not, it's a request. However, if both sender and receiver ships are our transitive sponsees, then we don't know whether it's a request or response, so it's not clear how to maintain the symmetry of the routing.
If we use a request/response bit in the packet instead, there's no ambiguity, and figuring out the destination ship is more straightforward. If it's a request, find the next sponsor in the sponsors list for that ship. If it's a response, send it back on the lane it came from.
Unfortunately, to forward requests, a relay does still need to look up PKI information for the destination ship, to find its sponsors. It's not a huge problem, but it does increase the amount that the forwarding code needs to interact with Arvo to read PKI information -- ideally a relay could have very minimal state. So a future design might improve upon that, but I don't know how just yet, and it might not be possible without tradeoffs (such as giving the requesting ship more control over the route its packet will take through the routing hierarchy, which isn't necessarily a good thing).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes sense to me. I can change the logic to treat requests and responses differently, but I'm not sure it's necessary.
My current relay logic works like this:
- If we have a lane for sndr to rcvr in the pending map, use that.
- If we are the direct sponsor of the rcvr, send to rcvr. (rcvr is in our sponsees map)
--> otherwise, +try-next-sponsor up the sponsorship chain in case rcvr is our transitive sponsee - If we don't have an entry for the request in the pending map AND the rcvr isn't our direct or transitive sponsee, send to the rcvr's galaxy.
Regardless of request/response, +on-hear-packet stores [[rcvr sndr]] [lane (unit next-lane)] in the pending map. I think this handles the routes correctly and maintains symmetry without needing to treat requests and responses differently.
Example:
request: ~rovnys -> ~syl -> ~sipsyl -> ~ritpub-sipsyl -> ~mister-ritpub-sipsyl
~rovnys has no record of ~mister-ritpub-sipsyl in the pending requests map and is not a sponsor, so it sends the packet to the ~syl galaxy.
As the request is routed, each relay will enter [[~mister-ritpub-sipsyl ~rovnys] [previous-lane previous-previous-lane]] in its pending map. e.g. ~sypsyl will have [[~mister-ritpub-sipsyl ~rovnys] [(~syl's lane) (~rovnys's lane)]].
response: ~rovnys <- ~syl <- ~sipsyl <- ~ritpub-sipsyl <- ~mister-ritpub-sipsyl
On the way back, the relay's all have entries in their pending map for [~mister-ritpub-sipsyl ~rovnys], so they will send the packet to both lane and the next-lane.
As the request is routed, each relay will enter [[~rovnys ~mister-ritpub-sipsyl] [previous-lane previous-previous-lane]] in its pending map. e.g. ~sypsyl will have [[~rovnys ~mister-ritpub-sipsyl] [(~ritpub-sipsyl's lane) (~mister-ritpub-sipsyl's lane)].
Then, on the next request, the relays have entries in their pending map going both ways. Each relay has an entry in the pending map for [~rovnys ~mister-ritpub-sipsyl] and an entry for [~mister-ritpub-sipsyl ~rovnys]. i.e. after the first request, only the pending map is used to route packets. The result is that all of the relays then try to tighten the route in both directions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did a cursory initial review. Some nits, but this looks very promising.
|
How sure are you that this is symmetric? Is it possible for, say, two request packets in a row to take the same trajectory, then one of the relays tightens on the way back?
It might be more efficient for all the relays to tighten bidirectionally all the time, but it's a pretty different design from the original proposal, so we should be careful to think through all the edge cases and make sure it would handle them correctly.
—
~rovnys-ricfer
https://urbit.org
…On Fri, Jun 03, 2022 at 1:26 PM, leowini < ***@***.*** > wrote:
***@***.**** commented on this pull request.
In pkg/ arvo/ sys/ vane/ ames. hoon (
#5810 (comment) ) :
> ::
=/ header=@
%+ can 0
- :~ [3 reserved=0]
+ :~
[1 reserved=0]
+ [2 packet-type=0]
This makes sense to me. I can change the logic to treat requests and
responses differently, but I'm not sure it's necessary.
My current relay logic works like this:
* If we have a lane for sndr to rcvr in the pending map, use that.
* If we are the direct sponsor of the rcvr, send to rcvr. (rcvr is in our
sponsees map)
--> otherwise, +try-next-sponsor up the sponsorship chain in case rcvr is
our transitive sponsee
* If we don't have an entry for the request in the pending map AND the
rcvr isn't our direct or transitive sponsee, send to the rcvr's galaxy.
Regardless of request/response, +on-hear-packet stores [[rcvr sndr]] [lane
(unit next-lane)] in the sponsorship map. I think this handles the routes
correctly and maintains symmetry without needing to treat requests and
responses differently.
Example:
request: ~rovnys -> ~syl -> ~sipsyl -> ~ritpub-sipsyl ->
~mister-ritpub-sipsyl
~rovnys has no record of ~mister-ritpub-sipsyl in the pending requests map
and is not a sponsor, so it sends the packet to the ~syl galaxy.
As the request is routed, each relay will enter [[~mister-ritpub-sipsyl
~rovnys] [previous-lane previous-previous-lane]] in its pending map. e.g.
~sypsyl will have [[~mister-ritpub-sipsyl ~rovnys] [(~syl's lane)
(~rovnys's lane)]].
response: ~rovnys <- ~syl <- ~sipsyl <- ~ritpub-sipsyl <-
~mister-ritpub-sipsyl
On the way back, the relay's all have entries in their pending map for
[~mister-ritpub-sipsyl ~rovnys], so they will send the packet to both lane
and the next-lane.
As the request is routed, each relay will enter [[~rovnys
~mister-ritpub-sipsyl] [previous-lane previous-previous-lane]] in its
pending map. e.g. ~sypsyl will have [[~rovnys ~mister-ritpub-sipsyl]
[(~ritpub-sipsyl's lane) (~mister-ritpub-sipsyl's lane)].
Then, on the next request, the relays have entries in their pending map
going both ways. Each relay has an entry in the pending map for [~rovnys
~mister-ritpub-sipsyl] and an entry for [~mister-ritpub-sipsyl ~rovnys].
i.e. after the first request, only the pending map is used to route
packets. The result is that all of the relays then try to tighten the
route in both directions.
—
Reply to this email directly, view it on GitHub (
#5810 (comment) ) , or unsubscribe
(
https://github.com/notifications/unsubscribe-auth/AAGVR5I5SHRDSEFMB6MZVC3VNJE3ZANCNFSM5XHSY4MA
).
You are receiving this because you were mentioned. Message ID: <urbit/urbit/pull/5810/review/995311557
@ github. com>
|
|
It would be possible for a small number of packets to take a tighter route on the way back if the route tightens while the packet is at the destination. However, the route will only tighten if there is a known path to the destination on the tightened route (the packet will only tighten a route to the next lane if it receives a packet from that lane). Essentially, all packets will take the tightest known route to the destination both ways. Is there an issue with breaking strict symmetry in this way? |
pkg/arvo/sys/vane/ames.hoon
Outdated
| ~/ %send-blob | ||
| |= [for=? =ship =blob] | ||
| ++ send-packet | ||
| |= [for=? next-lane=(unit lane) =packet] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As next-lane is a unit, is for redundant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes I think so I'll get rid of it
pkg/arvo/sys/vane/ames.hoon
Outdated
| :: | ||
| =/ =blob (encode-packet packet) | ||
| (send-blob & rcvr.packet blob) | ||
| (send-packet & `lane packet) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see a caller of on-hear-forward which provides lane- am I be missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
on-hear-forward gets called in on-hear-packet, with the same sample as on-hear-packet.
%. +<
::
?. =(our rcvr.packet)
on-hear-forward
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tracing this back: it seems that +call correctly passes lane when dud is a cell by extracting it from the task lane.task on line 1065. Otherwise is passes lane (line 1071) which I don't see in the sample at that point - is it passing the type $lane and not the value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's still getting the lane and blob from the task: [lane blob ~]:task. The dud looks like a stack trace in case of a crash (I think in the arvo kernel).
pkg/arvo/sys/vane/ames.hoon
Outdated
| !=(%czar (clan:title ship)) | ||
| == | ||
| =/ final-ship rcvr.packet | ||
| %- (trace rot.veb final-ship |.("send-packet: to {<ship>}")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be {<final-ship>} as ship is no longer an alias of final-ship?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes I'll change that
| :: | ||
| +$ relay-state | ||
| $: pending=(map ship [(pair lane (unit lane)) expiry=@da]) | ||
| sponsees=(map ship [lane expiry=@da]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wasn't pending going to have both rcvr and sndr ships in it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that was the original design. I noticed that the relays only need to know the destination, so I'm pretty sure it's okay to drop the sender. e.g. if a relay knows the lane of ~zod, it shouldn't matter where the relayed packets are coming from. It just sends them to ~zod's lane.
|
This PR needs an associated issue for symmetric routing. |
|
In discussion with @belisarius222 he's going to focus on this as part of his roadmap work and we'll create an issue then that references the important bits when we get to it. As is, we're going to close this PR for now until we're working on it. |
@belisarius222
Submitting for feedback:
TODOs