Skip to content

Commit

Permalink
Expose xfrm state's current and window statistics
Browse files Browse the repository at this point in the history
- aggregate window stats with packet counter stats

Signed-off-by: Alessandro Boch <aboch@tetrationanalytics.com>
  • Loading branch information
aboch authored and vishvananda committed Oct 30, 2017
1 parent c29ba20 commit 71fa81e
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 3 deletions.
27 changes: 24 additions & 3 deletions xfrm_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package netlink
import (
"fmt"
"net"
"time"
)

// XfrmStateAlgo represents the algorithm to use for the ipsec encryption.
Expand Down Expand Up @@ -67,6 +68,19 @@ type XfrmStateLimits struct {
TimeUseHard uint64
}

// XfrmStateStats represents the current number of bytes/packets
// processed by this State, the State's installation and first use
// time and the replay window counters.
type XfrmStateStats struct {
ReplayWindow uint32
Replay uint32
Failed uint32
Bytes uint64
Packets uint64
AddTime uint64
UseTime uint64
}

// XfrmState represents the state of an ipsec policy. It optionally
// contains an XfrmStateAlgo for encryption and one for authentication.
type XfrmState struct {
Expand All @@ -78,6 +92,7 @@ type XfrmState struct {
Reqid int
ReplayWindow int
Limits XfrmStateLimits
Statistics XfrmStateStats
Mark *XfrmMark
Auth *XfrmStateAlgo
Crypt *XfrmStateAlgo
Expand All @@ -94,10 +109,16 @@ func (sa XfrmState) Print(stats bool) string {
if !stats {
return sa.String()
}

return fmt.Sprintf("%s, ByteSoft: %s, ByteHard: %s, PacketSoft: %s, PacketHard: %s, TimeSoft: %d, TimeHard: %d, TimeUseSoft: %d, TimeUseHard: %d",
at := time.Unix(int64(sa.Statistics.AddTime), 0).Format(time.UnixDate)
ut := "-"
if sa.Statistics.UseTime > 0 {
ut = time.Unix(int64(sa.Statistics.UseTime), 0).Format(time.UnixDate)
}
return fmt.Sprintf("%s, ByteSoft: %s, ByteHard: %s, PacketSoft: %s, PacketHard: %s, TimeSoft: %d, TimeHard: %d, TimeUseSoft: %d, TimeUseHard: %d, Bytes: %d, Packets: %d, "+
"AddTime: %s, UseTime: %s, ReplayWindow: %d, Replay: %d, Failed: %d",
sa.String(), printLimit(sa.Limits.ByteSoft), printLimit(sa.Limits.ByteHard), printLimit(sa.Limits.PacketSoft), printLimit(sa.Limits.PacketHard),
sa.Limits.TimeSoft, sa.Limits.TimeHard, sa.Limits.TimeUseSoft, sa.Limits.TimeUseHard)
sa.Limits.TimeSoft, sa.Limits.TimeHard, sa.Limits.TimeUseSoft, sa.Limits.TimeUseHard, sa.Statistics.Bytes, sa.Statistics.Packets, at, ut,
sa.Statistics.ReplayWindow, sa.Statistics.Replay, sa.Statistics.Failed)
}

func printLimit(lmt uint64) string {
Expand Down
11 changes: 11 additions & 0 deletions xfrm_state_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ func xfrmStateFromXfrmUsersaInfo(msg *nl.XfrmUsersaInfo) *XfrmState {
state.Reqid = int(msg.Reqid)
state.ReplayWindow = int(msg.ReplayWindow)
lftToLimits(&msg.Lft, &state.Limits)
curToStats(&msg.Curlft, &msg.Stats, &state.Statistics)

return &state
}
Expand Down Expand Up @@ -429,6 +430,16 @@ func lftToLimits(lft *nl.XfrmLifetimeCfg, lmts *XfrmStateLimits) {
*lmts = *(*XfrmStateLimits)(unsafe.Pointer(lft))
}

func curToStats(cur *nl.XfrmLifetimeCur, wstats *nl.XfrmStats, stats *XfrmStateStats) {
stats.Bytes = cur.Bytes
stats.Packets = cur.Packets
stats.AddTime = cur.AddTime
stats.UseTime = cur.UseTime
stats.ReplayWindow = wstats.ReplayWindow
stats.Replay = wstats.Replay
stats.Failed = wstats.IntegrityFailed
}

func xfrmUsersaInfoFromXfrmState(state *XfrmState) *nl.XfrmUsersaInfo {
msg := &nl.XfrmUsersaInfo{}
msg.Family = uint16(nl.GetIPFamily(state.Dst))
Expand Down
21 changes: 21 additions & 0 deletions xfrm_state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"encoding/hex"
"net"
"testing"
"time"
)

func TestXfrmStateAddGetDel(t *testing.T) {
Expand Down Expand Up @@ -180,6 +181,26 @@ func TestXfrmStateUpdateLimits(t *testing.T) {
}
}

func TestXfrmStateStats(t *testing.T) {
setUpNetlinkTest(t)()

// Program state and record time
state := getBaseState()
now := time.Now()
if err := XfrmStateAdd(state); err != nil {
t.Fatal(err)
}
// Retrieve state
s, err := XfrmStateGet(state)
if err != nil {
t.Fatal(err)
}
// Verify stats: We expect zero counters, same second add time and unset use time
if s.Statistics.Bytes != 0 || s.Statistics.Packets != 0 || s.Statistics.AddTime != uint64(now.Unix()) || s.Statistics.UseTime != 0 {
t.Fatalf("Unexpected statistics (addTime: %s) for state:\n%s", now.Format(time.UnixDate), s.Print(true))
}
}

func getBaseState() *XfrmState {
return &XfrmState{
// Force 4 byte notation for the IPv4 addresses
Expand Down

0 comments on commit 71fa81e

Please sign in to comment.