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 golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to