Skip to content

Commit

Permalink
Fix up conntrack UTs; move to timeshim.
Browse files Browse the repository at this point in the history
  • Loading branch information
fasaxc committed Aug 7, 2020
1 parent cd41c59 commit ca3e53b
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 29 deletions.
10 changes: 0 additions & 10 deletions bpf/bpf.go
Original file line number Diff line number Diff line change
Expand Up @@ -2220,13 +2220,3 @@ func SupportsBPFDataplane() error {

return nil
}

// KTimeNanos returns a nanosecond timestamp that is comparable with the ones generated by BPF.
func KTimeNanos() int64 {
var ts unix.Timespec
err := unix.ClockGettime(unix.CLOCK_MONOTONIC, &ts)
if err != nil {
log.WithError(err).Panic("Failed to read system clock")
}
return ts.Nano()
}
10 changes: 10 additions & 0 deletions bpf/bpf_syscall.go
Original file line number Diff line number Diff line change
Expand Up @@ -598,3 +598,13 @@ func (m *MapIterator) Close() error {

return nil
}

// KTimeNanos returns a nanosecond timestamp that is comparable with the ones generated by BPF.
func KTimeNanos() int64 {
var ts unix.Timespec
err := unix.ClockGettime(unix.CLOCK_MONOTONIC, &ts)
if err != nil {
log.WithError(err).Panic("Failed to read system clock")
}
return ts.Nano()
}
4 changes: 4 additions & 0 deletions bpf/bpf_syscall_stub.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,7 @@ func (m *MapIterator) Next() (k, v []byte, err error) {
func (m *MapIterator) Close() error {
return nil
}

func KTimeNanos() int64 {
panic("BPF syscall stub")
}
27 changes: 20 additions & 7 deletions bpf/conntrack/cleanup.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
log "github.com/sirupsen/logrus"

"github.com/projectcalico/felix/bpf"
"github.com/projectcalico/felix/timeshim"
)

type Timeouts struct {
Expand Down Expand Up @@ -133,7 +134,7 @@ func (s *Scanner) get(k Key) (Value, error) {
type LivenessScanner struct {
timeouts Timeouts
dsr bool
NowNanos func() int64
time timeshim.Interface

// goTimeOfLastKTimeLookup is the go timestamp of the last time we looked up the kernel time.
// We cache the kernel time because it's expensive to look up (vs looking up a go timestamp which uses vdso).
Expand All @@ -142,18 +143,30 @@ type LivenessScanner struct {
cachedKTime int64
}

func NewLivenessScanner(timeouts Timeouts, dsr bool) *LivenessScanner {
return &LivenessScanner{
func NewLivenessScanner(timeouts Timeouts, dsr bool, opts ...LivenessScannerOpt) *LivenessScanner {
ls := &LivenessScanner{
timeouts: timeouts,
dsr: dsr,
NowNanos: bpf.KTimeNanos,
time: timeshim.RealTime(),
}
for _, opt := range opts {
opt(ls)
}
return ls
}

type LivenessScannerOpt func(ls *LivenessScanner)

func WithTimeShim(shim timeshim.Interface) LivenessScannerOpt {
return func(ls *LivenessScanner) {
ls.time = shim
}
}

func (l *LivenessScanner) ScanEntry(ctKey Key, ctVal Value, get EntryGet) ScanVerdict {
if l.cachedKTime == 0 || time.Since(l.goTimeOfLastKTimeLookup) > time.Second {
l.cachedKTime = l.NowNanos()
l.goTimeOfLastKTimeLookup = time.Now()
if l.cachedKTime == 0 || l.time.Since(l.goTimeOfLastKTimeLookup) > time.Second {
l.cachedKTime = l.time.KTimeNanos()
l.goTimeOfLastKTimeLookup = l.time.Now()
}
now := l.cachedKTime

Expand Down
2 changes: 1 addition & 1 deletion bpf/conntrack/conntrack_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func init() {
logrus.SetFormatter(&logutils.Formatter{})
}

func TestCalculationGraph(t *testing.T) {
func TestBPFConntrack(t *testing.T) {
RegisterFailHandler(Fail)
junitReporter := reporters.NewJUnitReporter("../../report/bpf_conntrack_suite.xml")
RunSpecsWithDefaultAndCustomReporters(t, "BPF Conntrack Suite", []Reporter{junitReporter})
Expand Down
15 changes: 7 additions & 8 deletions bpf/conntrack/conntrack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"time"

"github.com/projectcalico/felix/bpf"
"github.com/projectcalico/felix/timeshim/mocktime"

. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/extensions/table"
Expand All @@ -30,7 +31,7 @@ import (
"github.com/projectcalico/felix/bpf/mock"
)

const now = 1000 * time.Hour
var now = mocktime.StartKTime

var (
ip1 = net.ParseIP("10.0.0.1")
Expand Down Expand Up @@ -73,13 +74,13 @@ var _ = Describe("BPF Conntrack LivenessCalculator", func() {
var lc *conntrack.LivenessScanner
var scanner *conntrack.Scanner
var ctMap *mock.Map
var mockTime *mocktime.MockTime

BeforeEach(func() {
mockTime = mocktime.New()
Expect(mockTime.KTimeNanos()).To(BeNumerically("==",now))
ctMap = mock.NewMockMap(conntrack.MapParams)
lc = conntrack.NewLivenessScanner(timeouts, false)
lc.NowNanos = func() int64 {
return int64(now)
}
lc = conntrack.NewLivenessScanner(timeouts, false, conntrack.WithTimeShim(mockTime))
scanner = conntrack.NewScanner(ctMap, lc.ScanEntry)
})

Expand Down Expand Up @@ -119,9 +120,7 @@ var _ = Describe("BPF Conntrack LivenessCalculator", func() {
By("always deleting the entry if we fast-forward time")
err = ctMap.Update(key.AsBytes(), entry[:])
Expect(err).NotTo(HaveOccurred())
lc.NowNanos = func() int64 {
return int64(now + 2*time.Hour)
}
mockTime.IncrementTime(2*time.Hour)
scanner.Scan()
_, err = ctMap.Get(key.AsBytes())
Expect(bpf.IsNotExists(err)).To(BeTrue(), "Scan() should have cleaned up entry")
Expand Down
15 changes: 12 additions & 3 deletions timeshim/mocktime/mocktime.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ import (
"github.com/projectcalico/felix/timeshim"
)

var startTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
var StartTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
var StartKTime = 1000 * time.Hour
var KTimeEpoch = StartTime.Add(-StartKTime)

func New() *MockTime {
return &MockTime{
currentTime: startTime,
currentTime: StartTime,
}
}

Expand Down Expand Up @@ -125,6 +127,13 @@ func (m *MockTime) Now() time.Time {
return t
}

func (m *MockTime) KTimeNanos() int64 {
m.lock.Lock()
defer m.lock.Unlock()
// Kernel time isn't necessarily coupled to the same epoch so use a different one.
return int64(m.currentTime.Sub(KTimeEpoch))
}

func (m *MockTime) Since(t time.Time) time.Duration {
return m.Now().Sub(t)
}
Expand Down Expand Up @@ -153,7 +162,7 @@ func (m *MockTime) incrementTimeLockHeld(t time.Duration) {
}

m.currentTime = m.currentTime.Add(t)
logrus.WithField("increment", t).WithField("t", m.currentTime.Sub(startTime)).Info("Incrementing time")
logrus.WithField("increment", t).WithField("t", m.currentTime.Sub(StartTime)).Info("Incrementing time")

if len(m.timers) == 0 {
return
Expand Down
7 changes: 7 additions & 0 deletions timeshim/time.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ package timeshim

import (
"time"

"github.com/projectcalico/felix/bpf"
)

// Time is our shim interface to the time package.
Expand All @@ -25,6 +27,7 @@ type Interface interface {
Until(t time.Time) time.Duration
After(t time.Duration) <-chan time.Time
NewTimer(d Duration) Timer
KTimeNanos() int64
}

type Time = time.Time
Expand Down Expand Up @@ -79,3 +82,7 @@ func (realTime) Now() time.Time {
func (realTime) Since(t time.Time) time.Duration {
return time.Since(t)
}

func (realTime) KTimeNanos() int64 {
return bpf.KTimeNanos()
}

0 comments on commit ca3e53b

Please sign in to comment.