Skip to content

Commit

Permalink
Make ping after discovery concurrent
Browse files Browse the repository at this point in the history
  • Loading branch information
Maartje Eyskens committed Aug 24, 2018
1 parent 97d1252 commit a73d94c
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 7 deletions.
19 changes: 15 additions & 4 deletions hop/hop.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ type HopStatistic struct {
Sent int
TTL int
Target string
TargetIP *net.IPAddr
Last imcp.ICMPReturn
Best imcp.ICMPReturn
Worst imcp.ICMPReturn
SumElapsed time.Duration
Lost int
Packets *ring.Ring
RingBufferSize int
pingSeq int
}

type packet struct {
Expand All @@ -33,12 +35,21 @@ type packet struct {
}

func (s *HopStatistic) Next() {
r, _ := imcp.SendIMCP("0.0.0.0", s.Dest, s.TTL, s.PID, s.Timeout)
s.Packets = s.Packets.Prev()
s.Packets.Value = r
if s.Target == "" {
s.Target = r.Addr
return
}
if s.TargetIP == nil {
addr, err := net.ResolveIPAddr("ip4", s.Target)
if err != nil {
return
}
s.TargetIP = addr
}
s.pingSeq++
r, _ := imcp.SendIMCP("0.0.0.0", s.TargetIP, s.TTL, s.PID, s.Timeout, s.pingSeq)
s.Packets = s.Packets.Prev()
s.Packets.Value = r

s.Sent++
s.SumElapsed = r.Elapsed + s.SumElapsed
if !r.Success {
Expand Down
85 changes: 83 additions & 2 deletions imcp/icmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ type ICMPReturn struct {
Elapsed time.Duration
}

// SendIMCP sends a IMCP to a given destination
func SendIMCP(localAddr string, dst net.Addr, ttl, pid int, timeout time.Duration) (hop ICMPReturn, err error) {
// SendIMCP sends a IMCP to a given destination but does allow an IMCP timeout
func SendDiscoverIMCP(localAddr string, dst net.Addr, ttl, pid int, timeout time.Duration, seq int) (hop ICMPReturn, err error) {
hop.Success = false
start := time.Now()
c, err := icmp.ListenPacket("ip4:icmp", localAddr)
Expand Down Expand Up @@ -53,3 +53,84 @@ func SendIMCP(localAddr string, dst net.Addr, ttl, pid int, timeout time.Duratio
hop.Success = true
return hop, err
}

// SendIMCP sends a IMCP to a given destination
func SendIMCP(localAddr string, dst net.Addr, ttl, pid int, timeout time.Duration, seq int) (hop ICMPReturn, err error) {
hop.Success = false
start := time.Now()
c, err := icmp.ListenPacket("ip4:icmp", localAddr)
if err != nil {
return hop, err
}
defer c.Close()
c.IPv4PacketConn().SetTTL(ttl)
c.SetDeadline(time.Now().Add(timeout))
wm := icmp.Message{
Type: ipv4.ICMPTypeEcho, Code: 0,
Body: &icmp.Echo{
ID: pid, Seq: 0,
Data: []byte("hello"),
},
}
wb, err := wm.Marshal(nil)
if err != nil {
return hop, err
}

if _, err := c.WriteTo(wb, dst); err != nil {
return hop, err
}

_, err = listenForSpecific(time.Now().Add(timeout), dst.String())
if err != nil {
return hop, err
}

elapsed := time.Since(start)
hop.Elapsed = elapsed
hop.Addr = dst.String()
hop.Success = true
return hop, err
}

// listenForSpecific listens for a reply from a specific destination and returns the body if returned
func listenForSpecific(deadline time.Time, neededPeer string) (string, error) {
conn, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
if err != nil {
return "", err
}
conn.SetDeadline(deadline)
defer conn.Close()
for {
bytes := make([]byte, 1500)
n, peer, err := conn.ReadFrom(bytes)
if err != nil {
if neterr, ok := err.(*net.OpError); ok {
return "", neterr
}
}
if n == 0 {
continue
}

if peer.String() != neededPeer {
continue
}

x, err := icmp.ParseMessage(1, bytes[:n])
if err != nil {
continue
}

if x.Type.(ipv4.ICMPType).String() == "time exceeded" {
return "", nil
}

if x.Type.(ipv4.ICMPType).String() == "echo reply" {
b, _ := x.Body.Marshal(1)
return string(b[:2]), nil
}

panic(x.Type.(ipv4.ICMPType).String())
}
}
2 changes: 1 addition & 1 deletion mtr/mtr.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func (m *MTR) discover(ch chan struct{}) {
unknownHopsCount := 0
for ttl := 1; ttl < m.maxHops; ttl++ {
time.Sleep(m.hopsleep)
hopReturn, err := imcp.SendIMCP("0.0.0.0", &ipAddr, ttl, pid, m.timeout)
hopReturn, err := imcp.SendDiscoverIMCP("0.0.0.0", &ipAddr, ttl, pid, m.timeout, 1)

m.mutex.Lock()
s := m.registerStatistic(ttl, hopReturn)
Expand Down

0 comments on commit a73d94c

Please sign in to comment.