diff --git a/.circleci/config.yml b/.circleci/config.yml index 8725e443..82a68aad 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -48,14 +48,12 @@ jobs: command: | rm -f {yggdrasil,yggdrasilctl} GOOS=darwin GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-darwin-amd64 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-darwin-amd64; - GOOS=darwin GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-darwin-i386 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-darwin-i386; - run: name: Build for macOS (.pkg format) command: | rm -rf {yggdrasil,yggdrasilctl} GOOS=darwin GOARCH=amd64 ./build && PKGARCH=amd64 sh contrib/macos/create-pkg.sh && mv *.pkg /tmp/upload/ - GOOS=darwin GOARCH=386 ./build && PKGARCH=i386 sh contrib/macos/create-pkg.sh && mv *.pkg /tmp/upload/ - run: name: Build for OpenBSD diff --git a/cmd/yggdrasil/main.go b/cmd/yggdrasil/main.go index f67bbcef..aa5a7494 100644 --- a/cmd/yggdrasil/main.go +++ b/cmd/yggdrasil/main.go @@ -77,6 +77,7 @@ func readConfig(useconf *bool, useconffile *string, normaliseconf *bool) *nodeCo // names have changed recently. changes := map[string]string{ "Multicast": "", + "ReadTimeout": "", "LinkLocal": "MulticastInterfaces", "BoxPub": "EncryptionPublicKey", "BoxPriv": "EncryptionPrivateKey", @@ -89,11 +90,11 @@ func readConfig(useconf *bool, useconffile *string, normaliseconf *bool) *nodeCo if _, ok := dat[from]; ok { if to == "" { if !*normaliseconf { - log.Println("Warning: Deprecated config option", from, "- please remove") + log.Println("Warning: Config option", from, "is deprecated") } } else { if !*normaliseconf { - log.Println("Warning: Deprecated config option", from, "- please rename to", to) + log.Println("Warning: Config option", from, "has been renamed - please change to", to) } // If the configuration file doesn't already contain a line with the // new name then set it to the old value. This makes sure that we diff --git a/contrib/deb/generate.sh b/contrib/deb/generate.sh index 6c8f955d..4433a9d9 100644 --- a/contrib/deb/generate.sh +++ b/contrib/deb/generate.sh @@ -110,12 +110,10 @@ EOF cp yggdrasil /tmp/$PKGNAME/usr/bin/ cp yggdrasilctl /tmp/$PKGNAME/usr/bin/ cp contrib/systemd/yggdrasil.service /tmp/$PKGNAME/etc/systemd/system/ -cp contrib/systemd/yggdrasil-resume.service /tmp/$PKGNAME/etc/systemd/system/ tar -czvf /tmp/$PKGNAME/data.tar.gz -C /tmp/$PKGNAME/ \ usr/bin/yggdrasil usr/bin/yggdrasilctl \ - etc/systemd/system/yggdrasil.service \ - etc/systemd/system/yggdrasil-resume.service + etc/systemd/system/yggdrasil.service tar -czvf /tmp/$PKGNAME/control.tar.gz -C /tmp/$PKGNAME/debian . echo 2.0 > /tmp/$PKGNAME/debian-binary diff --git a/contrib/systemd/yggdrasil-resume.service b/contrib/systemd/yggdrasil-resume.service deleted file mode 100644 index c725127b..00000000 --- a/contrib/systemd/yggdrasil-resume.service +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=Restart yggdrasil on resume from sleep -After=sleep.target - -[Service] -Type=oneshot -ExecStart=/bin/systemctl restart yggdrasil - -[Install] -WantedBy=sleep.target diff --git a/contrib/systemd/yggdrasil.service b/contrib/systemd/yggdrasil.service index 1b6f1f07..6adf1ef5 100644 --- a/contrib/systemd/yggdrasil.service +++ b/contrib/systemd/yggdrasil.service @@ -18,4 +18,3 @@ Restart=always [Install] WantedBy=multi-user.target -Also=yggdrasil-resume.service diff --git a/misc/run-twolink-test b/misc/run-twolink-test new file mode 100755 index 00000000..987b6de8 --- /dev/null +++ b/misc/run-twolink-test @@ -0,0 +1,33 @@ +#!/bin/bash + +# Connects nodes in two namespaces by two links with different bandwidth (10mbit and 100mbit) + +ip netns add node1 +ip netns add node2 + +ip link add veth11 type veth peer name veth21 +ip link set veth11 netns node1 up +ip link set veth21 netns node2 up + +ip link add veth12 type veth peer name veth22 +ip link set veth12 netns node1 up +ip link set veth22 netns node2 up + +ip netns exec node1 tc qdisc add dev veth11 root tbf rate 10mbit burst 8192 latency 1ms +ip netns exec node2 tc qdisc add dev veth21 root tbf rate 10mbit burst 8192 latency 1ms + +ip netns exec node1 tc qdisc add dev veth12 root tbf rate 100mbit burst 8192 latency 1ms +ip netns exec node2 tc qdisc add dev veth22 root tbf rate 100mbit burst 8192 latency 1ms + +echo '{AdminListen: "unix://node1.sock"}' | ip netns exec node1 env PPROFLISTEN=localhost:6060 ./yggdrasil -logging "info,warn,error,debug" -useconf &> node1.log & +echo '{AdminListen: "unix://node2.sock"}' | ip netns exec node2 env PPROFLISTEN=localhost:6060 ./yggdrasil -logging "info,warn,error,debug" -useconf &> node2.log & + +echo "Started, to continue you should (possibly w/ sudo):" +echo "kill" $(jobs -p) +wait + +ip netns delete node1 +ip netns delete node2 + +ip link delete veth11 +ip link delete veth12 diff --git a/src/config/config.go b/src/config/config.go index 192b94e5..14b16490 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -16,7 +16,6 @@ type NodeConfig struct { AdminListen string `comment:"Listen address for admin connections. Default is to listen for local\nconnections either on TCP/9001 or a UNIX socket depending on your\nplatform. Use this value for yggdrasilctl -endpoint=X. To disable\nthe admin socket, use the value \"none\" instead."` Peers []string `comment:"List of connection strings for static peers in URI format, e.g.\ntcp://a.b.c.d:e or socks://a.b.c.d:e/f.g.h.i:j."` InterfacePeers map[string][]string `comment:"List of connection strings for static peers in URI format, arranged\nby source interface, e.g. { \"eth0\": [ tcp://a.b.c.d:e ] }. Note that\nSOCKS peerings will NOT be affected by this option and should go in\nthe \"Peers\" section instead."` - ReadTimeout int32 `comment:"Read timeout for connections, specified in milliseconds. If less\nthan 6000 and not negative, 6000 (the default) is used. If negative,\nreads won't time out."` AllowedEncryptionPublicKeys []string `comment:"List of peer encryption public keys to allow or incoming TCP\nconnections from. If left empty/undefined then all connections\nwill be allowed by default."` EncryptionPublicKey string `comment:"Your public encryption key. Your peers may ask you for this to put\ninto their AllowedEncryptionPublicKeys configuration."` EncryptionPrivateKey string `comment:"Your private encryption key. DO NOT share this with anyone!"` diff --git a/src/yggdrasil/link.go b/src/yggdrasil/link.go index be98dd92..ad4b1fac 100644 --- a/src/yggdrasil/link.go +++ b/src/yggdrasil/link.go @@ -216,6 +216,8 @@ func (intf *linkInterface) handler() error { case signalReady <- struct{}{}: default: } + intf.link.core.log.Debugf("Sending packet to %s: %s, source %s", + strings.ToUpper(intf.info.linkType), themString, intf.info.local) } } }() @@ -235,18 +237,21 @@ func (intf *linkInterface) handler() error { recvTimer := time.NewTimer(recvTime) defer util.TimerStop(recvTimer) for { + intf.link.core.log.Debugf("State of %s: %s, source %s :: isAlive %t isReady %t sendTimerRunning %t recvTimerRunning %t", + strings.ToUpper(intf.info.linkType), themString, intf.info.local, + isAlive, isReady, sendTimerRunning, recvTimerRunning) select { case gotMsg, ok := <-signalAlive: if !ok { return } - if !isAlive { - isAlive = true - if !isReady { - // (Re-)enable in the switch - isReady = true - intf.link.core.switchTable.idleIn <- intf.peer.port - } + util.TimerStop(recvTimer) + recvTimerRunning = false + isAlive = true + if !isReady { + // (Re-)enable in the switch + intf.link.core.switchTable.idleIn <- intf.peer.port + isReady = true } if gotMsg && !sendTimerRunning { // We got a message @@ -255,6 +260,10 @@ func (intf *linkInterface) handler() error { sendTimer.Reset(sendTime) sendTimerRunning = true } + if !gotMsg { + intf.link.core.log.Debugf("Received ack from %s: %s, source %s", + strings.ToUpper(intf.info.linkType), themString, intf.info.local) + } case sentMsg, ok := <-signalSent: // Stop any running ack timer if !ok { @@ -273,12 +282,13 @@ func (intf *linkInterface) handler() error { if !ok { return } - if !isAlive || !isReady { + if !isAlive { // Disable in the switch isReady = false } else { // Keep enabled in the switch intf.link.core.switchTable.idleIn <- intf.peer.port + isReady = true } case <-sendTimer.C: // We haven't sent anything, so signal a send of a 0 packet to let them know we're alive diff --git a/src/yggdrasil/switch.go b/src/yggdrasil/switch.go index 9d1f870a..a2877ebe 100644 --- a/src/yggdrasil/switch.go +++ b/src/yggdrasil/switch.go @@ -780,6 +780,7 @@ func (t *switchTable) doWorker() { t.queues.bufs = make(map[string]switch_buffer) // Packets per PacketStreamID (string) idle := make(map[switchPort]struct{}) // this is to deduplicate things for { + t.core.log.Debugf("Switch state: idle = %d, buffers = %d", len(idle), len(t.queues.bufs)) select { case bytes := <-t.packetIn: // Try to send it somewhere (or drop it if it's corrupt or at a dead end) diff --git a/src/yggdrasil/tcp.go b/src/yggdrasil/tcp.go index 979bc81b..c65e2e66 100644 --- a/src/yggdrasil/tcp.go +++ b/src/yggdrasil/tcp.go @@ -36,7 +36,6 @@ type tcpInterface struct { reconfigure chan chan error serv net.Listener stop chan bool - timeout time.Duration addr string mutex sync.Mutex // Protecting the below calls map[string]struct{} @@ -106,13 +105,8 @@ func (iface *tcpInterface) listen() error { iface.core.configMutex.RLock() iface.addr = iface.core.config.Listen - iface.timeout = time.Duration(iface.core.config.ReadTimeout) * time.Millisecond iface.core.configMutex.RUnlock() - if iface.timeout >= 0 && iface.timeout < default_timeout { - iface.timeout = default_timeout - } - ctx := context.Background() lc := net.ListenConfig{ Control: iface.tcpContext,