# Implementation Goals From a working Transport Layer (TL + Socket) implementation, wrap/decorate to add an disruption layer, to simulate various network incidents: - Delay (fixed, random, ...) - Reordering packets - Packet injection (duplication, fake packets,...) - Packet loss - Buffer/Jam behavior (blocking packets until threshold on time/#packets/...) - other behaviors Suggested implementation direction: - focus on sender-side: trigger new behaviors on calling Send() - implement a new Socket type (leveraging the existing interface), wrapping another socket # Implementation ## Design choices - Buffer Jam: we realized that taking into account the number of packets to be buffered will introduce sequentiality. It might be better to simulate the jam using sinusoidal (or similar, having a stateful filter) delays - Injection: Beyond randomizing the payload, we also thought about spoofing (changing the source address for example). But: - too 'random' packets -> trigger early drops, more useful as unit tests rather than stress-test - crafting precise packets: hard to define, + risk of implementing an actual attack (overkill given the threat model considered?) - Reordering: To avoid sequentiality issues (and +-converting a packet-based system to a stream-based system) we implicitly implemented it through delays only ## New Transport Layer - DisruptedLayer ``` type DisruptedTransport struct { transport.Transport filters []Filter } ``` Wrapper for a 'normal TL'. Needed as Sockets are instantiated by call to the TL. Contains the 'normal TL', and a list of filters (uninitialized) to be copied and launched for every instantiated disrupted socket. On socket creation, a 'normal socket' is created through the wrapped TL, then wrapped in a DisruptedSocket, for which filters are copied and `Start()`-ed, then an 'end-of-line' listening goroutine is launched (see further). ## New Socket - DisruptedSocket ``` type Socket struct { transport.ClosableSocket filters []Filter } ``` Wrapper for a 'normal Socket'. Contains an ordered list of autonomous filters, sequentially connected by channels transmitting `SendingTriplet`s (decorated packets with destination and timeout to use on the actual normalSocket `Send()`). ``` type SendingTriplet struct { dest string pkt transport.Packet timeout time.Duration } ``` An incoming packet is transferred to the first Filter of the list through its input channel (non-blocking `In()` call), which will act on it and transmit to the next filter, etc. The DisruptedSocket has a goroutine listening on the last channel, and calling the normalSocket `Send()` as soon as a SendingTriplet is available. Due to the asynchronous nature of this implementation, DisruptedSocket's `Send()` is non-blocking (always returning nil). ## Filters (old version) Spec: one op only, `Pass(pkt transport.Packet) ([]transport.Packet)`, called concurrently (slice to handle packet injection) Issues: - apply filter n+1 on all filters outputted by filter n ? - delays: blocking on a packet blocks all the slice - privileges: trying to send duplicates directly means the Filter has sending privileges (-> access to the socket ?) ## Filters (new version) ``` type Filter interface { Start() // Launch Filter listener Stop() // Stop Filter listener Copy() Filter // Copy Filter pass(tripl SendingTriplet) // Internal, compute the filter function on an augmented packet SetIO(chan SendingTriplet, chan SendingTriplet) // Used to initialize channels In(SendingTriplet) // (blocking) To feed a packet into the filter } ``` Autonomous item with in/out channels. Once `Start()`-ed, waits on input packets, processes (non-blocking) them using `pass()` and transmits to `out` channel. Also waits on a quit channel, triggered by `Stop()`. `Copy()` needed to instantiate all sockets. `SetIO()` and `In()` needed at TL-level to resp. initialize all filters for a new socket, and feed a packet into the first filter when calling `Send()`. - Injection: - Pseudo-random: - [ ] unmarshable (sanity check) - [ ] marshable w/ random packet ID - [ ] marshable w/ random source (spoof) - [x] Duplication: poisson distribution for #packets added - Delay: - [x] Exponential (HW transfer time) - [x] Stateful (pseudo-atomic op needed, at least monotonic inc) ~periodic for jam simulation w/ non-0 mean - [x] Fixed - Loss: - [x] Probabilistic drops of packets --- --- # Draft ## Issues - various (Filter design) Issue: need for interface (~virtual class), so that `Start()` launches listener on in/out and calls `pass()`. Pb: `pass()` needs out channel, ended up with cyclic dependancy design. (lack of virtual classes/inheritance in Golang?) **Solved** by accepting redundant code (every Filter has its own Start(), Stop(), SetIO(), In() implementations even if identical) ## How to test filters - integrate them into some tests - # Discussions - Ref implem => 100% tests ? - Adapt all tests, only integration ? - filters implement Socket (ClosableSocket) - Send direct - go routine en continue + delais # Réu 02/08 - recv side - filter -> interface Socket (truc récursif) - integrate filters into tests - func option pattern pr init - implementation with a queue ![](https://hackmd.io/_uploads/r1IPQb_ih.png)