Bsically I'm writing an application that traceroutes a given set of hosts
concurrently. I got the logic pretty much done but I'm having a slight
problem with the timings. I am measuring the round-trip-times (rtt) of each
packet with classic method of defining a `begin := time.Now()` variable
just before sending the payloads, and then defining the `rtt :=
time.Since(begin)` variable right after receiving a response. The problem
is that when I do this for multiple hosts, most of the timings start
appearing in microseconds, as if the concurrent goroutines were triggering
some sort of bug in the timing mechanism. When I probe a single host, I get
the correct times so that's how I know that the logic and placement of each
of these `begin` and `rtt` declarations is fine.
Here is an example ready to be compiled and run, showcasing the issue. See
the outputs I get at the end:
package main
import (
"golang.org/x/net/ipv4"
"net"
"log"
"fmt"
"golang.org/x/net/icmp"
"time"
"os"
"strings"
"sync"
)
func main() {
fmt.Println("Probing 1 host \n\n")
getRoutes("www.google.com")
fmt.Println("Probing 2 hosts \n\n")
getRoutes("www.facebook.com", "www.twitter.com")
fmt.Println("Probing 3 hosts \n\n")
getRoutes("www.google.com", "www.facebook.com", "www.twitter.com")
}
func getRoutes(hosts ...string) {
ch := make(chan string, len(hosts))
var wg sync.WaitGroup
wg.Add(len(hosts))
for _, host := range hosts {
host := host
//time.Sleep(1000*time.Millisecond)
go func() { defer wg.Done(); trace(host, ch) }()
}
go func() { wg.Wait(); close(ch) }()
for i := range ch {
fmt.Println(i)
}
}
func trace(host string, ch chan string) {
// Tracing an IP packet route
output := []string{}
ips, err := net.LookupIP(host)
if err != nil {
log.Fatal(err)
}
var dst net.IPAddr
for _, ip := range ips {
if ip.To4() != nil {
dst.IP = ip
output = append(output, fmt.Sprintf("\n\nUsing %v for
tracing an IP packet route to %s\n\n", dst.IP, host))
break
}
}
if dst.IP == nil {
log.Fatal("no A record found")
}
c, err := net.ListenPacket("ip4:1", "0.0.0.0") // ICMP for IPv4
if err != nil {
log.Fatal(err)
}
defer c.Close()
p := ipv4.NewPacketConn(c)
id := os.Getpid()
if err := p.SetControlMessage(ipv4.FlagTTL | ipv4.FlagSrc | ipv4.FlagDst
| ipv4.FlagInterface, true); err != nil {
log.Fatal(err)
}
wm := icmp.Message{
Type: ipv4.ICMPTypeEcho, Code: 0,
Body: &icmp.Echo{
ID: id & 0xffff,
Data: []byte(host),
},
}
rb := make([]byte, 1500)
Query:
for i := 1; i <= 64; i++ {
// up to 64 hops
wm.Body.(*icmp.Echo).Seq = i
wb, err := wm.Marshal(nil)
if err != nil {
log.Fatal(err)
}
if err := p.SetTTL(i); err != nil {
log.Fatal(err)
}
begin := time.Now()
if _, err := p.WriteTo(wb, nil, &dst); err != nil {
log.Fatal(err)
}
if err := p.SetReadDeadline(time.Now().Add(3 * time.Second)); err
!= nil {
log.Fatal(err)
}
n, cm, peer, err := p.ReadFrom(rb)
if err != nil {
if err, ok := err.(net.Error); ok && err.Timeout() {
fmt.Printf("%v\t*\n", i)
continue
}
log.Fatal(err)
}
rm, err := icmp.ParseMessage(1, rb[:n])
if err != nil {
log.Fatal(err)
}
rtt := time.Since(begin)
mb, _ := rm.Body.Marshal(1)
switch rm.Type {
case ipv4.ICMPTypeTimeExceeded:
if strings.Contains(string(mb), host) {
names, _ := net.LookupAddr(peer.String())
stats := fmt.Sprintf("%d\t%v %+v %v\n\t%+v\n", i,
peer, names, rtt, cm)
output = append(output, stats)
continue
}
case ipv4.ICMPTypeEchoReply:
if strings.Contains(string(mb), host) {
names, _ := net.LookupAddr(peer.String())
stats := fmt.Sprintf("%d\t%v %+v %v\n\t%+v\n", i,
peer, names, rtt, cm)
output = append(output, stats)
break Query
}
default:
log.Printf("unknown ICMP message: %+v\n", rm)
continue
}
}
ch <- strings.Join(output, "")
return
}
OUTPUTS:
Probing 1 host
Using 216.58.219.68 for tracing an IP packet route to www.google.com
1 192.168.1.1 [router] 1.285962ms
ttl=64 src=192.168.1.1 dst=192.168.1.2 ifindex=2
5 84.16.11.234 [hu0-1-0-0-gractgtw1.net.telefonicaglobalsolutions.com.]
41.858369ms
ttl=250 src=84.16.11.234 dst=192.168.1.2 ifindex=2
10 72.14.233.233 [] 78.03747ms
ttl=54 src=72.14.233.233 dst=192.168.1.2 ifindex=2
11 216.58.219.68 [mia07s24-in-f68.1e100.net. mia07s24-in-f4.1e100.net.
mia07s24-in-f4.1e100.net. mia07s24-in-f68.1e100.net.] 79.839308ms
ttl=54 src=216.58.219.68 dst=192.168.1.2 ifindex=2
Probing 2 hosts
Using 31.13.73.36 for tracing an IP packet route to www.facebook.com
1 192.168.1.1 [router] 1.642975ms
ttl=64 src=192.168.1.1 dst=192.168.1.2 ifindex=2
6 10.7.120.193 [] 1.512576ms
ttl=62 src=10.7.120.193 dst=192.168.1.2 ifindex=2
8 84.16.11.234 [hu0-1-0-0-gractgtw1.net.telefonicaglobalsolutions.com.]
88.916µs
ttl=250 src=84.16.11.234 dst=192.168.1.2 ifindex=2
15 5.53.5.165 [ae4-grtmiabr1.net.telefonicaglobalsolutions.com.] 45.309µs
ttl=243 src=5.53.5.165 dst=192.168.1.2 ifindex=2
18 213.140.33.165
[hu-0-11-0-0-grtmiana4.net.telefonicaglobalsolutions.com.] 67.448µs
ttl=246 src=213.140.33.165 dst=192.168.1.2 ifindex=2
19 173.252.67.5 [] 201.578µs
ttl=54 src=173.252.67.5 dst=192.168.1.2 ifindex=2
20 31.13.73.36 [edge-star-mini-shv-01-mia1.facebook.com.] 181.316µs
ttl=86 src=31.13.73.36 dst=192.168.1.2 ifindex=2
Using 104.244.42.1 for tracing an IP packet route to www.twitter.com
2 192.168.1.1 [router] 1.049634ms
ttl=64 src=192.168.1.1 dst=192.168.1.2 ifindex=2
3 10.7.120.193 [] 41.772495ms
ttl=62 src=10.7.120.193 dst=192.168.1.2 ifindex=2
11 84.16.11.234 [hu0-1-0-0-gractgtw1.net.telefonicaglobalsolutions.com.]
1.070686ms
ttl=250 src=84.16.11.234 dst=192.168.1.2 ifindex=2
13 84.16.15.128 [hu-1-5-0-0-4-grtmiabr6.net.telefonicaglobalsolutions.com.
hu-1-5-0-0-4-grtmiabr6.red.telefonica-wholesale.net.] 140.145µs
ttl=249 src=84.16.15.128 dst=192.168.1.2 ifindex=2
24 104.244.42.1 [] 126.108µs
ttl=51 src=104.244.42.1 dst=192.168.1.2 ifindex=2
Probing 3 hosts
Using 216.58.219.68 for tracing an IP packet route to www.google.com
1 192.168.1.1 [router] 1.387872ms
ttl=64 src=192.168.1.1 dst=192.168.1.2 ifindex=2
12 84.16.11.234 [hu0-1-0-0-gractgtw1.net.telefonicaglobalsolutions.com.]
637.435µs
ttl=250 src=84.16.11.234 dst=192.168.1.2 ifindex=2
14 10.7.120.193 [] 43.269µs
ttl=62 src=10.7.120.193 dst=192.168.1.2 ifindex=2
20 72.14.233.233 [] 41.124µs
ttl=54 src=72.14.233.233 dst=192.168.1.2 ifindex=2
21 216.58.219.68 [mia07s24-in-f68.1e100.net. mia07s24-in-f68.1e100.net.
mia07s24-in-f4.1e100.net. mia07s24-in-f4.1e100.net.] 152.104µs
ttl=54 src=216.58.219.68 dst=192.168.1.2 ifindex=2
Using 104.244.42.65 for tracing an IP packet route to www.twitter.com
2 192.168.1.1 [router] 438.191µs
ttl=64 src=192.168.1.1 dst=192.168.1.2 ifindex=2
7 10.7.120.193 [] 1.387854ms
ttl=62 src=10.7.120.193 dst=192.168.1.2 ifindex=2
11 84.16.11.234 [hu0-1-0-0-gractgtw1.net.telefonicaglobalsolutions.com.]
60.996µs
ttl=250 src=84.16.11.234 dst=192.168.1.2 ifindex=2
29 5.53.3.243 [te0-9-0-5-grtmiabr6.net.telefonicaglobalsolutions.com.]
58.257µs
ttl=249 src=5.53.3.243 dst=192.168.1.2 ifindex=2
36 104.244.42.65 [] 52.488µs
ttl=52 src=104.244.42.65 dst=192.168.1.2 ifindex=2
Using 31.13.73.36 for tracing an IP packet route to www.facebook.com
1 192.168.1.1 [router] 1.359029ms
ttl=64 src=192.168.1.1 dst=192.168.1.2 ifindex=2
5 10.7.120.193 [] 63.257µs
ttl=62 src=10.7.120.193 dst=192.168.1.2 ifindex=2
12 84.16.11.234 [hu0-1-0-0-gractgtw1.net.telefonicaglobalsolutions.com.]
56.205µs
ttl=250 src=84.16.11.234 dst=192.168.1.2 ifindex=2
28 213.140.33.165
[hu-0-11-0-0-grtmiana4.net.telefonicaglobalsolutions.com.] 57.08µs
ttl=246 src=213.140.33.165 dst=192.168.1.2 ifindex=2
30 5.53.5.165 [ae4-grtmiabr1.net.telefonicaglobalsolutions.com.] 75.868µs
ttl=243 src=5.53.5.165 dst=192.168.1.2 ifindex=2
32 74.119.79.178 [po102.psw01a.mia1.tfbnw.net.] 100.514µs
ttl=53 src=74.119.79.178 dst=192.168.1.2 ifindex=2
33 213.140.43.120 [et6-1-0-4-grtmiana2.net.telefonicaglobalsolutions.com.]
141.644µs
ttl=248 src=213.140.43.120 dst=192.168.1.2 ifindex=2
54 173.252.67.5 [] 56.98µs
ttl=54 src=173.252.67.5 dst=192.168.1.2 ifindex=2
55 31.13.73.36 [edge-star-mini-shv-01-mia1.facebook.com.] 146.372µs
ttl=86 src=31.13.73.36 dst=192.168.1.2 ifindex=2
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.