netsys-lab / scion-path-discovery

The goal of the SCION-Pathdiscovery project is to leverage the path-awareness features of the SCION secure Internet architecture in order to discover a fast and reliable content lookup and delivery.
Apache License 2.0
0 stars 1 forks source link

Make mppingpong example mutlipath-capable #20

Closed martenwallewein closed 3 years ago

martenwallewein commented 3 years ago

At the moment, we have an example called mppingpong that sends ping and pong packets between to sockets, using one path. The next step would be to apply sending those packets over multiple paths. To do so, please consider the following things:

Target of mppingpong

The main point that mppingpong should visualize is the communication over multiple paths. Each socket (client or server) will send a packet containing the its path as payload (although the path is already in the SCION header, this information is normally not accessible from applications, so we add it again here for simplicity). Mppingpong logs over what paths it sends ping and over what paths it receives pongs, so that it's clearly visible that multipath is going on here.

Example: Send ping over Path xxx Send ping over Path yyy Receive pong over Path zzz ...

Using the underlying connections instead of mp.read/write

Since writing the path in the packets is an application specific task, it would be not recommended to implement it in the packet scheduler. Therefor, please use the connections that the MPPeerSock opens for all paths to send an receive data. How to get them is already part of the example:

    go func() {
        for {
            log.Info("Waiting for new connections")
            conns := <-mpSock.OnConnectionsChange
            log.Infof("New Connections available, got %d", len(conns))
            for i, v := range conns {
                log.Infof("Connection %d is %s", i, packets.ConnTypeToString(v.GetType()))
            }
        }
    }()

Each connection is either incoming our outgoing. Please call read on the incoming connection (it's always one for the moment) and write on all outgoing connections. Connections can be filtered by calling GetType().

How to get the path and serialize/deserialize it

Each outgoing connection has a GetPath function that returns it's current path. This should be used to write the path of each connection to the remote socket. Serializing it can be done in a way like this:

               var network bytes.Buffer
        enc := gob.NewEncoder(&network) // Will write to network.
        err := enc.Encode(conn.GetPath())
        conn.Write(network.Bytes())

Deserializing a path from a packet would look like this:

        _, err := s.connections[0].Read(bts)
    p := snet.Path{}
    network := bytes.NewBuffer(bts) // Stand-in for a network connection
    dec := gob.NewDecoder(network)
    err = dec.Decode(&p)

Why incoming and outgoing connections

Please consider the following image describing how two sockets connect each other via multiple paths.

Screenshot from 2021-09-15 12-05-37

Since UDP does not provide connection-oriented communication, the connection that a socket listens on will not be able to send packets, because there is no remote known. Similar connections that were created using dial: Since the port is chosen randomly, no remote socket will send data to this port, meaning that there will be no incoming traffic for this connection.

martenwallewein commented 3 years ago

One thing to serialize/deserialize paths: register path.Path (from snet/path) type to gob gob.Register(path.Path{})