diff --git a/probe/endpoint/conntrack.go b/probe/endpoint/conntrack.go index deefa45753..46ec3ca8a1 100644 --- a/probe/endpoint/conntrack.go +++ b/probe/endpoint/conntrack.go @@ -8,6 +8,7 @@ import ( "os" "strings" "sync" + "io" "github.com/weaveworks/scope/common/exec" ) @@ -59,6 +60,11 @@ type Flow struct { Original, Reply, Independent *Meta `xml:"-"` } +type conntrack struct { + XMLName xml.Name `xml:"conntrack"` + Flows []Flow `xml:"flow"` +} + // Conntracker uses the conntrack command to track network connections type Conntracker struct { sync.Mutex @@ -105,7 +111,18 @@ var ConntrackModulePresent = func() bool { // NB this is not re-entrant! func (c *Conntracker) run(args ...string) { - args = append([]string{"-E", "-o", "xml"}, args...) + // Fork another conntrack, just to capture existing connections + // for which we don't get events + existingFlows, err := c.existingConnections(args...) + if err != nil { + log.Printf("conntrack existingConnections error: %v", err) + return + } + for _, flow := range existingFlows { + c.handleFlow(flow) + } + + args = append([]string{"-E", "-o", "xml", "-p", "tcp"}, args...) cmd := exec.Command("conntrack", args...) stdout, err := cmd.StdoutPipe() if err != nil { @@ -154,6 +171,31 @@ func (c *Conntracker) run(args ...string) { } } +func (c *Conntracker) existingConnections(args ...string) ([]Flow, error) { + var conntrack conntrack + args = append([]string{"-L", "-o", "xml", "-p", "tcp"}, args...) + cmd := exec.Command("conntrack", args...) + stdout, err := cmd.StdoutPipe() + if err != nil { + return conntrack.Flows, err + } + if err := cmd.Start(); err != nil { + return conntrack.Flows, err + } + defer func() { + if err := cmd.Wait(); err != nil { + log.Printf("conntrack existingConnections exit error: %v", err) + } + }() + if err := xml.NewDecoder(stdout).Decode(&conntrack); err != nil { + if err == io.EOF { + return conntrack.Flows, err + } + return conntrack.Flows, err + } + return conntrack.Flows, nil +} + // Stop stop stop func (c *Conntracker) Stop() { c.Lock()