-
Notifications
You must be signed in to change notification settings - Fork 0
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
colibri border router #24
colibri border router #24
Conversation
ebf7c41
to
24212cc
Compare
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.
Very nice !
Thank you @mawyss for this contribution. I left only some comments about small issues I found.
Reviewed 21 of 21 files at r1.
Reviewable status: all files reviewed, 9 unresolved discussions (waiting on @mawyss)
go/lib/colibri/colibri.go, line 17 at r1 (raw file):
// Package colibri contains methods for the creation and verification of the colibri packet // timestamp and validation fields. package colibri
Since the file and package contain only functions related to COLIBRI MAC, what about changing the name of the file and package?
go/lib/colibri/colibri_test.go, line 242 at r1 (raw file):
func randUint64() uint64 { return uint64(rand.Uint32())<<32 + uint64(rand.Uint32())
We should try not to use random input in our unit tests. There are several reasons for this, among others:
- Difficult to estimate coverage.
- Difficult (sometimes) to reproduce.
- Sometimes frees us from looking for edge cases, under the false pretense they will be eventually caught.
- Fuzzing does exactly this ("random" parameters), but not in the unit tests.
go/lib/slayers/path/colibri/colibri.go, line 24 at r1 (raw file):
) type ColibriPath struct {
Where is the ColibriPath
used at?
Why do we need a different type than ColibriPathMinimal
?
go/lib/slayers/path/colibri/colibri_minimal.go, line 40 at r1 (raw file):
} type ColibriPathMinimal struct {
It would be nice to have some doc string here.
go/lib/slayers/path/colibri/colibri_minimal.go, line 120 at r1 (raw file):
// serialized. Then the Raw buffer is copied to b. func (c *ColibriPathMinimal) SerializeTo(b []byte) error { if len(b) < c.Len() {
I realize that the signature of the function comes from an interface, and we don't want to change it. Since it doesn't return the length of the bytes serialized, can we check that the buffer is exactly Len()
bytes long?
Same would apply for SerializeToInternal
go/lib/slayers/path/colibri/colibri_minimal.go, line 176 at r1 (raw file):
} // UpdateCurrHF increases/decreases the CurrHF index depending on the R flag.
We should update the comment to indicate it doesn't depend on R
anymore.
go/lib/slayers/path/colibri/hopfield_test.go, line 66 at r1 (raw file):
func randBytes(l uint16) []byte { r := make([]byte, l) rand.Read(r)
As mentioned in the colibri_test, let's avoid random inputs.
go/pkg/router/colibri_processing.go, line 146 at r1 (raw file):
if c.ingressID == 0 { // Received packet from within AS
According to your comment, we could use this fact to check that if C=1
the sender's address is that of a COLIBRI service.
(we will assume that the AS checks no spoofing for the service address happens).
This can be done in a later iteration, it's not necessary to implement it in this PR 😃
go/pkg/router/colibri_processing.go, line 163 at r1 (raw file):
return r, err } return c.forwardToRemoteEgress(egressId)
We are ignoring errors from forwardToLocalEgress
. Why not make the decision here of BR transit or AS transit?
go/pkg/router/control/conf.go, line 119 at r1 (raw file):
// DeriveColibriKey derives the private Colibri key from the given key. func DeriveColibriKey(k []byte) []byte {
Why not use the scrypto.DeriveColibriKey
function?
I also wonder why the regular SCION DeriveHFMacKey
is not using scrypto
as well.
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.
Reviewable status: 17 of 23 files reviewed, 9 unresolved discussions (waiting on @juagargi)
go/lib/colibri/colibri.go, line 17 at r1 (raw file):
Previously, juagargi (Juan A. Garcia Pardo) wrote…
Since the file and package contain only functions related to COLIBRI MAC, what about changing the name of the file and package?
The package also contains methods for the creation/verification of timestamps (expiration tick and high precision packet timestamp). It is possible that the colibri package will need to be extended later to the requirements of the end hosts, so I did not go for a more specific name. For the epic PR I received feedback to name the package simply "epic" (the package contains also methods regarding timestamps and MACs), so having "colibri" here would be consistent. Or do you anticipate having a colibri library package for the colibri service, so that it conflicts with this one?
go/lib/colibri/colibri_test.go, line 242 at r1 (raw file):
Previously, juagargi (Juan A. Garcia Pardo) wrote…
We should try not to use random input in our unit tests. There are several reasons for this, among others:
- Difficult to estimate coverage.
- Difficult (sometimes) to reproduce.
- Sometimes frees us from looking for edge cases, under the false pretense they will be eventually caught.
- Fuzzing does exactly this ("random" parameters), but not in the unit tests.
Done. Replaced random input with static values.
go/lib/slayers/path/colibri/colibri.go, line 24 at r1 (raw file):
Previously, juagargi (Juan A. Garcia Pardo) wrote…
Where is the
ColibriPath
used at?
Why do we need a different type thanColibriPathMinimal
?
The ColibriPath is currently used in the router unit tests (dataplane_test.go). It will be needed to create colibri packets at the hosts later. Note that also the SCION path type has different representations (decoded vs. raw).
go/lib/slayers/path/colibri/colibri_minimal.go, line 40 at r1 (raw file):
Previously, juagargi (Juan A. Garcia Pardo) wrote…
It would be nice to have some doc string here.
Done.
go/lib/slayers/path/colibri/colibri_minimal.go, line 120 at r1 (raw file):
Previously, juagargi (Juan A. Garcia Pardo) wrote…
I realize that the signature of the function comes from an interface, and we don't want to change it. Since it doesn't return the length of the bytes serialized, can we check that the buffer is exactly
Len()
bytes long?Same would apply for
SerializeToInternal
I am not sure whether this would work: usually there is a buffer (e.g. 1500 bytes), and each layer gets serialized one after the other, so the buffer can actually be larger than c.Len(). Also the SCION path type implementation checks for "<" and not for "=".
go/lib/slayers/path/colibri/colibri_minimal.go, line 176 at r1 (raw file):
Previously, juagargi (Juan A. Garcia Pardo) wrote…
We should update the comment to indicate it doesn't depend on
R
anymore.
Done.
go/lib/slayers/path/colibri/hopfield_test.go, line 66 at r1 (raw file):
Previously, juagargi (Juan A. Garcia Pardo) wrote…
As mentioned in the colibri_test, let's avoid random inputs.
Done.
go/pkg/router/colibri_processing.go, line 146 at r1 (raw file):
Previously, juagargi (Juan A. Garcia Pardo) wrote…
According to your comment, we could use this fact to check that if
C=1
the sender's address is that of a COLIBRI service.
(we will assume that the AS checks no spoofing for the service address happens).
This can be done in a later iteration, it's not necessary to implement it in this PR 😃
Ok, let's do that later. We need to be a bit careful at on-path ASes, because the source host in the address header of the COLIBRI packet denotes a service within the first AS (if it is an IP address).
Could it make sense to only use service identifiers for C=1 instead of actual IPs?
go/pkg/router/colibri_processing.go, line 163 at r1 (raw file):
Previously, juagargi (Juan A. Garcia Pardo) wrote…
We are ignoring errors from
forwardToLocalEgress
. Why not make the decision here of BR transit or AS transit?
I am not sure what you mean: the decision of BR transit or AS transit is actually made at this point. The router tries to forward the packet itself to the given egress interface (BR transit), and if that fails (because the router is not responsible for that interface) it forwards the packet to the appropriate border router (AS transit).
go/pkg/router/control/conf.go, line 119 at r1 (raw file):
Previously, juagargi (Juan A. Garcia Pardo) wrote…
Why not use the
scrypto.DeriveColibriKey
function?
I also wonder why the regular SCIONDeriveHFMacKey
is not usingscrypto
as well.
Good question. I was asking this myself too, and decided to implement it in the same way as with standard SCION to omit any undesirable side effects.
My guess would be that the router should be light-weight, and not need to import also asymmetric crypto functionality as would be the case in the scrypto package.
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.
Reviewed 1 of 11 files at r2.
Reviewable status: 13 of 23 files reviewed, 2 unresolved discussions (waiting on @juagargi and @mawyss)
go/lib/colibri/colibri.go, line 17 at r1 (raw file):
Previously, mawyss wrote…
The package also contains methods for the creation/verification of timestamps (expiration tick and high precision packet timestamp). It is possible that the colibri package will need to be extended later to the requirements of the end hosts, so I did not go for a more specific name. For the epic PR I received feedback to name the package simply "epic" (the package contains also methods regarding timestamps and MACs), so having "colibri" here would be consistent. Or do you anticipate having a colibri library package for the colibri service, so that it conflicts with this one?
Alright, let's keep it like that at least for now (or forever).
go/lib/slayers/path/colibri/colibri.go, line 24 at r1 (raw file):
Previously, mawyss wrote…
The ColibriPath is currently used in the router unit tests (dataplane_test.go). It will be needed to create colibri packets at the hosts later. Note that also the SCION path type has different representations (decoded vs. raw).
👍
go/lib/slayers/path/colibri/colibri_minimal.go, line 120 at r1 (raw file):
Previously, mawyss wrote…
I am not sure whether this would work: usually there is a buffer (e.g. 1500 bytes), and each layer gets serialized one after the other, so the buffer can actually be larger than c.Len(). Also the SCION path type implementation checks for "<" and not for "=".
I marked this comment as resolved, as the discussion is non blocking for the PR, and only informative.
Structs like InfoField
are serialized only from this code. In this code we call their SerializeTo
with a slice with the exact size. They could check for the exact size.
What I meant is that these methods SerializeTo(_ []byte)
come from the Path
interface. It is called upon a Path
object in SCION.SerializeTo
https://github.com/mawyss/scion/blob/colibri_dataplane/go/lib/slayers/scion.go#L181
where the buf
is allocated with the size computed from calling Len
(so the exact size).
I would (but not now) change the interface of SerializeTo
, so that it would return the size of the serialized version, so that it can be called upon a big enough buffer (with more bytes than just Len
) that does not need to be reallocated every time. But we are not going to change the interface now: that is what I meant with "don't want to change it").
After checking the rest of the implementers of the Path.SerializeTo
prototype, I see that all check for the length to be sufficient --and not exact--, so I actually prefer to leave it as you coded it.
go/pkg/router/colibri_processing.go, line 163 at r1 (raw file):
Previously, mawyss wrote…
I am not sure what you mean: the decision of BR transit or AS transit is actually made at this point. The router tries to forward the packet itself to the given egress interface (BR transit), and if that fails (because the router is not responsible for that interface) it forwards the packet to the appropriate border router (AS transit).
Let's trace a call to this function foward()
: let's say the packet has C=0
, so we arrive at:
} else {
// Data plane forwarding
if c.destinedToLocalHost(egressId) {
return c.forwardToLocalHost()
} else {
if r, err := c.forwardToLocalEgress(egressId); err == nil {
return r, err
}
return c.forwardToRemoteEgress(egressId)
}
}
In there, let's say that destinedToLocalHost
returns false
. We end up calling forwardToLocalEgress
. Let's say that forwardToLocalEgress
returns an error: looking at that function, a problem updating the current hop field or serializing would do. Then, since we have:
if r, err := c.forwardToLocalEgress(egressId); err == nil {
return r, err
}
return c.forwardToRemoteEgress(egressId)
we will directly call forwardToRemoteEgress
. But the packet was meant to be forwarded to local egress, and to report an error. Not to be sent to remote egress.
go/pkg/router/control/conf.go, line 119 at r1 (raw file):
Previously, mawyss wrote…
Good question. I was asking this myself too, and decided to implement it in the same way as with standard SCION to omit any undesirable side effects.
My guess would be that the router should be light-weight, and not need to import also asymmetric crypto functionality as would be the case in the scrypto package.
Idk. To be honest, I would change this and also the regular SCION to use the respective functions from scrypto
.
Please leave a TODO(mawyss)
so we (or someone else) will check at a later point (or remove the TODO).
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.
Reviewable status: 13 of 23 files reviewed, 2 unresolved discussions (waiting on @juagargi)
go/lib/colibri/colibri.go, line 17 at r1 (raw file):
Previously, juagargi (Juan A. Garcia Pardo) wrote…
Alright, let's keep it like that at least for now (or forever).
Ok.
go/lib/slayers/path/colibri/colibri_minimal.go, line 120 at r1 (raw file):
Previously, juagargi (Juan A. Garcia Pardo) wrote…
I marked this comment as resolved, as the discussion is non blocking for the PR, and only informative.
Structs like
InfoField
are serialized only from this code. In this code we call theirSerializeTo
with a slice with the exact size. They could check for the exact size.What I meant is that these methods
SerializeTo(_ []byte)
come from thePath
interface. It is called upon aPath
object inSCION.SerializeTo
https://github.com/mawyss/scion/blob/colibri_dataplane/go/lib/slayers/scion.go#L181
where thebuf
is allocated with the size computed from callingLen
(so the exact size).I would (but not now) change the interface of
SerializeTo
, so that it would return the size of the serialized version, so that it can be called upon a big enough buffer (with more bytes than justLen
) that does not need to be reallocated every time. But we are not going to change the interface now: that is what I meant with "don't want to change it").
After checking the rest of the implementers of thePath.SerializeTo
prototype, I see that all check for the length to be sufficient --and not exact--, so I actually prefer to leave it as you coded it.
Ok, then let's keep this then.
go/pkg/router/colibri_processing.go, line 163 at r1 (raw file):
Previously, juagargi (Juan A. Garcia Pardo) wrote…
Let's trace a call to this function
foward()
: let's say the packet hasC=0
, so we arrive at:} else { // Data plane forwarding if c.destinedToLocalHost(egressId) { return c.forwardToLocalHost() } else { if r, err := c.forwardToLocalEgress(egressId); err == nil { return r, err } return c.forwardToRemoteEgress(egressId) } }In there, let's say that
destinedToLocalHost
returnsfalse
. We end up callingforwardToLocalEgress
. Let's say thatforwardToLocalEgress
returns an error: looking at that function, a problem updating the current hop field or serializing would do. Then, since we have:if r, err := c.forwardToLocalEgress(egressId); err == nil { return r, err } return c.forwardToRemoteEgress(egressId)we will directly call
forwardToRemoteEgress
. But the packet was meant to be forwarded to local egress, and to report an error. Not to be sent to remote egress.
Done. The errors should now be properly returned.
go/pkg/router/control/conf.go, line 119 at r1 (raw file):
Previously, juagargi (Juan A. Garcia Pardo) wrote…
Idk. To be honest, I would change this and also the regular SCION to use the respective functions from
scrypto
.
Please leave aTODO(mawyss)
so we (or someone else) will check at a later point (or remove the TODO).
Done. I added a comment regarding this. In the scionproto slack I asked about the reason for this, so we will hopefully know soon.
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.
Reviewed 9 of 11 files at r2, 2 of 2 files at r3.
Reviewable status: complete! all files reviewed, all discussions resolved (waiting on @mawyss)
* Start working on COLIBRI path type definition * (De-)serialization of COLIBRI paths * Fix linter errors * Add tests for COLIBRI (de-)serialization * Start working on COLIBRI verification logic * Start working on COLIBRI forwarding logic * Finish forwarding * Linter + tests successful * Work on colibri tests * Implement updated colibri specification, adapt unit tests * Implement colibri cryptographic verification, add colibri key derivation from key0. * Remove redundant nil checks. * Reorder functions * COLIBRI library: add remaining unit tests * Run linter. * Add 'Original Payload Length' to InfoField. * Start working on COLIBRI path type definition * (De-)serialization of COLIBRI paths * Fix linter errors * Add tests for COLIBRI (de-)serialization * Start working on COLIBRI verification logic * Start working on COLIBRI forwarding logic * Finish forwarding * Linter + tests successful * Work on colibri tests * Implement updated colibri specification, adapt unit tests * Implement colibri cryptographic verification, add colibri key derivation from key0. * Remove redundant nil checks. * Reorder functions * COLIBRI library: add remaining unit tests * Run linter. * Add 'Original Payload Length' to InfoField. * Add border router tests and fix bugs. * Address comments from review. * Implement requested changes. Co-authored-by: mawyss <mawyss@ethz.ch>
Add 'Original Payload Length' to Info Field. Correct flag consistency checks. colibri border router (#24) simplify parsing. (#25) Colibri.experiments (#27) Performance changes, fixes and tests added for the NSDI paper. Per-packet MAC: replace payload size input with total packet size input. Static and sigma MAC InputData: Remove HFCount input. Fix warnings in Colibri doc. (#26) gRPC with COLIBRI primer (#28) Colibri initiator (#29) gRPC for COLIBRI (#30) Replace ColibriService.md with ColibriDesign.rst Resolve failing /go/pkg/gateway/control/fake:go_default_test Fix linter errors. Colibri.topology entry (#31) Colibri.e2e.basic api (#33) Colibri.move to co (#34) Colibri.fix data plane (#35) fix e2e mac computation, simplify. (#37) For now use the static MAC computation also for E2E. Add tests. Colibri.extended api (#38) Colibri.refactor (#39) changes from review. changes from review. changes from review. missing build file in go/co Colibri.extended api (#40) Colibri.cleanup (#41) Colibri.review (#43) Colibri.review (#44)
Colibri.header.doc (#22) Add 'Original Payload Length' to Info Field. Correct flag consistency checks. colibri border router (#24) simplify parsing. (#25) Colibri.experiments (#27) Performance changes, fixes and tests added for the NSDI paper. Per-packet MAC: replace payload size input with total packet size input. Static and sigma MAC InputData: Remove HFCount input. Fix warnings in Colibri doc. (#26) gRPC with COLIBRI primer (#28) Colibri initiator (#29) gRPC for COLIBRI (#30) Replace ColibriService.md with ColibriDesign.rst Resolve failing /go/pkg/gateway/control/fake:go_default_test Fix linter errors. Colibri.topology entry (#31) Colibri.e2e.basic api (#33) Colibri.move to co (#34) Colibri.fix data plane (#35) fix e2e mac computation, simplify. (#37) For now use the static MAC computation also for E2E. Add tests. Colibri.extended api (#38) Colibri.refactor (#39) changes from review. changes from review. changes from review. missing build file in go/co Colibri.extended api (#40) Colibri.cleanup (#41) Colibri.review (#43) Colibri.review (#44)
Colibri.header.doc (#22) Add 'Original Payload Length' to Info Field. Correct flag consistency checks. colibri border router (#24) simplify parsing. (#25) Colibri.experiments (#27) Performance changes, fixes and tests added for the NSDI paper. Per-packet MAC: replace payload size input with total packet size input. Static and sigma MAC InputData: Remove HFCount input. Fix warnings in Colibri doc. (#26) gRPC with COLIBRI primer (#28) Colibri initiator (#29) gRPC for COLIBRI (#30) Replace ColibriService.md with ColibriDesign.rst Resolve failing /go/pkg/gateway/control/fake:go_default_test Fix linter errors. Colibri.topology entry (#31) Colibri.e2e.basic api (#33) Colibri.move to co (#34) Colibri.fix data plane (#35) fix e2e mac computation, simplify. (#37) For now use the static MAC computation also for E2E. Add tests. Colibri.extended api (#38) Colibri.refactor (#39) changes from review. changes from review. changes from review. missing build file in go/co Colibri.extended api (#40) Colibri.cleanup (#41) Colibri.review (#43) Colibri.review (#44)
Colibri.header.doc (#22) Add 'Original Payload Length' to Info Field. Correct flag consistency checks. colibri border router (#24) simplify parsing. (#25) Colibri.experiments (#27) Performance changes, fixes and tests added for the NSDI paper. Per-packet MAC: replace payload size input with total packet size input. Static and sigma MAC InputData: Remove HFCount input. Fix warnings in Colibri doc. (#26) gRPC with COLIBRI primer (#28) Colibri initiator (#29) gRPC for COLIBRI (#30) Replace ColibriService.md with ColibriDesign.rst Resolve failing /go/pkg/gateway/control/fake:go_default_test Fix linter errors. Colibri.topology entry (#31) Colibri.e2e.basic api (#33) Colibri.move to co (#34) Colibri.fix data plane (#35) fix e2e mac computation, simplify. (#37) For now use the static MAC computation also for E2E. Add tests. Colibri.extended api (#38) Colibri.refactor (#39) changes from review. changes from review. changes from review. missing build file in go/co Colibri.extended api (#40) Colibri.cleanup (#41) Colibri.review (#43) Colibri.review (#44) use a auto-freshen cache for the colibri listings in sciond (#45) several fixes. Colibri.remove todos (#46) Colibri.admission list (#47) Colibri.remove tod os (#48) Colibri.integration test (#49) remove stray deleteme fixes. local topos with 1Gbps capacity for colibry purposes remove last deleteme.
* Colibri feature squashed. Colibri.header.doc (#22) Add 'Original Payload Length' to Info Field. Correct flag consistency checks. colibri border router (#24) simplify parsing. (#25) Colibri.experiments (#27) Performance changes, fixes and tests added for the NSDI paper. Per-packet MAC: replace payload size input with total packet size input. Static and sigma MAC InputData: Remove HFCount input. Fix warnings in Colibri doc. (#26) gRPC with COLIBRI primer (#28) Colibri initiator (#29) gRPC for COLIBRI (#30) Replace ColibriService.md with ColibriDesign.rst Resolve failing /go/pkg/gateway/control/fake:go_default_test Fix linter errors. Colibri.topology entry (#31) Colibri.e2e.basic api (#33) Colibri.move to co (#34) Colibri.fix data plane (#35) fix e2e mac computation, simplify. (#37) For now use the static MAC computation also for E2E. Add tests. Colibri.extended api (#38) Colibri.refactor (#39) changes from review. changes from review. changes from review. missing build file in go/co Colibri.extended api (#40) Colibri.cleanup (#41) Colibri.review (#43) Colibri.review (#44) use a auto-freshen cache for the colibri listings in sciond (#45) several fixes. Colibri.remove todos (#46) Colibri.admission list (#47) Colibri.remove tod os (#48) Colibri.integration test (#49) colibri command. (#50) Colibri.adapt end2end integration (#51) use end2end_integration to run colibri. remove colibri_integration . * extend validity check of colibri packet.
Implementation of the colibri library, the colibri packet format, and the border router forwarding logic.
Overview:
This change is