Skip to content

Commit

Permalink
first draft
Browse files Browse the repository at this point in the history
gazelle

avoid using math package

avoid using duration.Seconds()

fb1

fb2

fb3

remove leftover

add gauge

fb 3

fix build

fb
  • Loading branch information
uniquefine committed Oct 11, 2023
1 parent 1774cbf commit 45ba0a6
Show file tree
Hide file tree
Showing 24 changed files with 297 additions and 63 deletions.
2 changes: 2 additions & 0 deletions control/beaconing/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ go_library(
"//private/segment/verifier:go_default_library",
"//private/topology:go_default_library",
"//private/tracing:go_default_library",
"//private/trust:go_default_library",
"@com_github_opentracing_opentracing_go//:go_default_library",
],
)
Expand Down Expand Up @@ -70,6 +71,7 @@ go_test(
"//pkg/scrypto/signed:go_default_library",
"//pkg/segment:go_default_library",
"//pkg/segment/extensions/staticinfo:go_default_library",
"//pkg/slayers/path:go_default_library",
"//pkg/slayers/path/scion:go_default_library",
"//pkg/snet:go_default_library",
"//pkg/snet/addrutil:go_default_library",
Expand Down
64 changes: 50 additions & 14 deletions control/beaconing/extender.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,22 @@ import (
"github.com/scionproto/scion/control/ifstate"
"github.com/scionproto/scion/pkg/addr"
"github.com/scionproto/scion/pkg/log"
"github.com/scionproto/scion/pkg/metrics"
"github.com/scionproto/scion/pkg/private/serrors"
"github.com/scionproto/scion/pkg/private/util"
seg "github.com/scionproto/scion/pkg/segment"
"github.com/scionproto/scion/pkg/segment/extensions/digest"
"github.com/scionproto/scion/pkg/segment/extensions/epic"
"github.com/scionproto/scion/pkg/slayers/path"
"github.com/scionproto/scion/private/trust"
)

// SignerGen generates signers and returns their expiration time.
type SignerGen interface {
// Generate generates a signer it.
Generate(ctx context.Context) (trust.Signer, error)
}

// Extender extends path segments.
type Extender interface {
// Extend extends the path segment. The zero value for ingress indicates
Expand All @@ -44,8 +52,8 @@ type Extender interface {
type DefaultExtender struct {
// IA is the local IA
IA addr.IA
// Signer is used to sign path segments.
Signer seg.Signer
// SignerGen is used to sign path segments.
SignerGen SignerGen
// MAC is used to calculate the hop field MAC.
MAC func() hash.Hash
// Intfs holds all interfaces in the AS.
Expand All @@ -60,6 +68,11 @@ type DefaultExtender struct {
StaticInfo func() *StaticInfoCfg
// EPIC defines whether the EPIC authenticators should be added when the segment is extended.
EPIC bool

// SegmentExpirationDeficient is a gauge that is set to 1 if the expiration time of the segment
// is below the maximum expiration time. This happens when the signer expiration time is lower
// than the maximum segment expiration time.
SegmentExpirationDeficient metrics.Gauge
}

// Extend extends the beacon with hop fields.
Expand All @@ -85,8 +98,27 @@ func (s *DefaultExtender) Extend(
}
ts := pseg.Info.Timestamp

signer, err := s.SignerGen.Generate(ctx)
if err != nil {
return serrors.WrapStr("getting signer", err)
}
// Make sure the hop expiration time is not longer than the signer expiration time.
expTime := s.MaxExpTime()
if ts.Add(path.ExpTimeToDuration(expTime)).After(signer.Expiration) {
metrics.GaugeSet(s.SegmentExpirationDeficient, 1)
var err error
expTime, err = path.ExpTimeFromDuration(signer.Expiration.Sub(ts))
if err != nil {
return serrors.WrapStr(
"calculating expiry time from signer expiration time", err,
"signer_expiration", signer.Expiration,
)
}
} else {
metrics.GaugeSet(s.SegmentExpirationDeficient, 0)
}
hopBeta := extractBeta(pseg)
hopEntry, epicHopMac, err := s.createHopEntry(ingress, egress, ts, hopBeta)
hopEntry, epicHopMac, err := s.createHopEntry(ingress, egress, expTime, ts, hopBeta)
if err != nil {
return serrors.WrapStr("creating hop entry", err)
}
Expand All @@ -104,7 +136,7 @@ func (s *DefaultExtender) Extend(
// is traversed.

peerBeta := hopBeta ^ binary.BigEndian.Uint16(hopEntry.HopField.MAC[:2])
peerEntries, epicPeerMacs, err := s.createPeerEntries(egress, peers, ts, peerBeta)
peerEntries, epicPeerMacs, err := s.createPeerEntries(egress, peers, expTime, ts, peerBeta)
if err != nil {
return err
}
Expand Down Expand Up @@ -143,7 +175,7 @@ func (s *DefaultExtender) Extend(
}
}

if err := pseg.AddASEntry(ctx, asEntry, s.Signer); err != nil {
if err := pseg.AddASEntry(ctx, asEntry, signer); err != nil {
return err
}
if egress == 0 {
Expand All @@ -153,12 +185,12 @@ func (s *DefaultExtender) Extend(
}

func (s *DefaultExtender) createPeerEntries(egress uint16, peers []uint16,
ts time.Time, beta uint16) ([]seg.PeerEntry, [][]byte, error) {
expTime uint8, ts time.Time, beta uint16) ([]seg.PeerEntry, [][]byte, error) {

peerEntries := make([]seg.PeerEntry, 0, len(peers))
peerEpicMacs := make([][]byte, 0, len(peers))
for _, peer := range peers {
peerEntry, epicMac, err := s.createPeerEntry(peer, egress, ts, beta)
peerEntry, epicMac, err := s.createPeerEntry(peer, egress, expTime, ts, beta)
if err != nil {
log.Debug("Ignoring peer link upon error",
"task", s.Task, "peer_interface", peer, "err", err)
Expand All @@ -170,15 +202,20 @@ func (s *DefaultExtender) createPeerEntries(egress uint16, peers []uint16,
return peerEntries, peerEpicMacs, nil
}

func (s *DefaultExtender) createHopEntry(ingress, egress uint16, ts time.Time,
beta uint16) (seg.HopEntry, []byte, error) {
func (s *DefaultExtender) createHopEntry(
ingress,
egress uint16,
expTime uint8,
ts time.Time,
beta uint16,
) (seg.HopEntry, []byte, error) {

remoteInMTU, err := s.remoteMTU(ingress)
if err != nil {
return seg.HopEntry{}, nil, serrors.WrapStr("checking remote ingress interface (mtu)", err,
"interfaces", ingress)
}
hopF, epicMac := s.createHopF(ingress, egress, ts, beta)
hopF, epicMac := s.createHopF(ingress, egress, expTime, ts, beta)
return seg.HopEntry{
IngressMTU: int(remoteInMTU),
HopField: seg.HopField{
Expand All @@ -190,15 +227,15 @@ func (s *DefaultExtender) createHopEntry(ingress, egress uint16, ts time.Time,
}, epicMac, nil
}

func (s *DefaultExtender) createPeerEntry(ingress, egress uint16, ts time.Time,
func (s *DefaultExtender) createPeerEntry(ingress, egress uint16, expTime uint8, ts time.Time,
beta uint16) (seg.PeerEntry, []byte, error) {

remoteInIA, remoteInIfID, remoteInMTU, err := s.remoteInfo(ingress)
if err != nil {
return seg.PeerEntry{}, nil, serrors.WrapStr("checking remote ingress interface", err,
"ingress_interface", ingress)
}
hopF, epicMac := s.createHopF(ingress, egress, ts, beta)
hopF, epicMac := s.createHopF(ingress, egress, expTime, ts, beta)
return seg.PeerEntry{
PeerMTU: int(remoteInMTU),
Peer: remoteInIA,
Expand Down Expand Up @@ -259,10 +296,9 @@ func (s *DefaultExtender) remoteInfo(ifid uint16) (
return topoInfo.IA, topoInfo.RemoteID, topoInfo.MTU, nil
}

func (s *DefaultExtender) createHopF(ingress, egress uint16, ts time.Time,
func (s *DefaultExtender) createHopF(ingress, egress uint16, expTime uint8, ts time.Time,
beta uint16) (path.HopField, []byte) {

expTime := s.MaxExpTime()
input := make([]byte, path.MACBufferSize)
path.MACInput(beta, util.TimeToSecs(ts), expTime, ingress, egress, input)

Expand Down
114 changes: 107 additions & 7 deletions control/beaconing/extender_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ import (
cryptopb "github.com/scionproto/scion/pkg/proto/crypto"
"github.com/scionproto/scion/pkg/scrypto"
seg "github.com/scionproto/scion/pkg/segment"
"github.com/scionproto/scion/pkg/slayers/path"
"github.com/scionproto/scion/private/topology"
"github.com/scionproto/scion/private/trust"
)

func TestDefaultExtenderExtend(t *testing.T) {
Expand Down Expand Up @@ -98,8 +100,8 @@ func TestDefaultExtenderExtend(t *testing.T) {
intfs.Get(peer).Activate(peerRemoteIfs[peer])
}
ext := &beaconing.DefaultExtender{
IA: topo.IA(),
Signer: testSigner(t, priv, topo.IA()),
IA: topo.IA(),
SignerGen: testSignerGen{Signer: testSigner(t, priv, topo.IA())},
MAC: func() hash.Hash {
mac, err := scrypto.InitMac(make([]byte, 16))
require.NoError(t, err)
Expand Down Expand Up @@ -171,8 +173,8 @@ func TestDefaultExtenderExtend(t *testing.T) {
intfs := ifstate.NewInterfaces(interfaceInfos(topo), ifstate.Config{})
require.NoError(t, err)
ext := &beaconing.DefaultExtender{
IA: topo.IA(),
Signer: testSigner(t, priv, topo.IA()),
IA: topo.IA(),
SignerGen: testSignerGen{Signer: testSigner(t, priv, topo.IA())},
MAC: func() hash.Hash {
mac, err := scrypto.InitMac(make([]byte, 16))
require.NoError(t, err)
Expand All @@ -189,8 +191,106 @@ func TestDefaultExtenderExtend(t *testing.T) {
err = ext.Extend(context.Background(), pseg, 0, graph.If_111_A_112_X, []uint16{})
require.NoError(t, err)
assert.Equal(t, uint8(1), pseg.ASEntries[0].HopEntry.HopField.ExpTime)

})
t.Run("segment and signer expiration interaction", func(t *testing.T) {
ts := time.Now()
testCases := map[string]struct {
SignerGen beaconing.SignerGen
MaxExpTime func() uint8
ExpTime uint8
ErrAssertion assert.ErrorAssertionFunc
}{
"signer expires before max expiration time": {
SignerGen: testSignerGen{
Signer: func() trust.Signer {
s := testSigner(t, priv, topo.IA())
s.Expiration = ts.Add(path.MaxTTL / 2)
return s
}(),
},
ExpTime: 127,
MaxExpTime: func() uint8 { return 255 },
ErrAssertion: assert.NoError,
},
"signer expires after max expiration time": {
SignerGen: testSignerGen{
Signer: func() trust.Signer {
s := testSigner(t, priv, topo.IA())
s.Expiration = ts.Add(path.MaxTTL)
return s
}(),
},
ExpTime: 254,
MaxExpTime: func() uint8 { return 254 },
ErrAssertion: assert.NoError,
},
"minimum signer expiration time": {
SignerGen: testSignerGen{
Signer: func() trust.Signer {
s := testSigner(t, priv, topo.IA())
s.Expiration = ts.Add(path.MaxTTL / 256)
return s
}(),
},
ExpTime: 0,
MaxExpTime: func() uint8 { return 10 },
ErrAssertion: assert.NoError,
},
"signer expiration time too small": {
SignerGen: testSignerGen{
Signer: func() trust.Signer {
s := testSigner(t, priv, topo.IA())
s.Expiration = ts.Add(path.MaxTTL / 257)
return s
}(),
},
MaxExpTime: func() uint8 { return 10 },
ErrAssertion: assert.Error,
},
"signer expiration time too large uses MaxExpTime": {
SignerGen: testSignerGen{
Signer: func() trust.Signer {
s := testSigner(t, priv, topo.IA())
s.Expiration = ts.Add(2 * path.MaxTTL)
return s
}(),
},
ExpTime: 157,
MaxExpTime: func() uint8 { return 157 },
ErrAssertion: assert.NoError,
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
mctrl := gomock.NewController(t)
defer mctrl.Finish()
intfs := ifstate.NewInterfaces(interfaceInfos(topo), ifstate.Config{})
require.NoError(t, err)
ext := &beaconing.DefaultExtender{
IA: topo.IA(),
SignerGen: tc.SignerGen,
MAC: func() hash.Hash {
mac, err := scrypto.InitMac(make([]byte, 16))
require.NoError(t, err)
return mac
},
Intfs: intfs,
MTU: 1337,
MaxExpTime: tc.MaxExpTime,
StaticInfo: func() *beaconing.StaticInfoCfg { return nil },
}
pseg, err := seg.CreateSegment(ts, uint16(mrand.Int()))
require.NoError(t, err)
err = ext.Extend(context.Background(), pseg, 0, graph.If_111_A_112_X, []uint16{})
tc.ErrAssertion(t, err)
if err != nil {
return
}
assert.Equal(t, tc.ExpTime, pseg.ASEntries[0].HopEntry.HopField.ExpTime)
})
}
})

t.Run("segment is not extended on error", func(t *testing.T) {
defaultSigner := func(t *testing.T) seg.Signer {
return testSigner(t, priv, topo.IA())
Expand Down Expand Up @@ -238,8 +338,8 @@ func TestDefaultExtenderExtend(t *testing.T) {
defer mctrl.Finish()
intfs := ifstate.NewInterfaces(interfaceInfos(topo), ifstate.Config{})
ext := &beaconing.DefaultExtender{
IA: topo.IA(),
Signer: testSigner(t, priv, topo.IA()),
IA: topo.IA(),
SignerGen: testSignerGen{Signer: testSigner(t, priv, topo.IA())},
MAC: func() hash.Hash {
mac, err := scrypto.InitMac(make([]byte, 16))
require.NoError(t, err)
Expand Down
4 changes: 2 additions & 2 deletions control/beaconing/originator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func TestOriginatorRun(t *testing.T) {
Extender: &beaconing.DefaultExtender{
IA: topo.IA(),
MTU: topo.MTU(),
Signer: signer,
SignerGen: testSignerGen{Signer: signer},
Intfs: intfs,
MAC: macFactory,
MaxExpTime: func() uint8 { return beacon.DefaultMaxExpTime },
Expand Down Expand Up @@ -130,7 +130,7 @@ func TestOriginatorRun(t *testing.T) {
Extender: &beaconing.DefaultExtender{
IA: topo.IA(),
MTU: topo.MTU(),
Signer: signer,
SignerGen: testSignerGen{Signer: signer},
Intfs: intfs,
MAC: macFactory,
MaxExpTime: func() uint8 { return beacon.DefaultMaxExpTime },
Expand Down
6 changes: 3 additions & 3 deletions control/beaconing/propagator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func TestPropagatorRunNonCore(t *testing.T) {
Extender: &beaconing.DefaultExtender{
IA: topo.IA(),
MTU: topo.MTU(),
Signer: testSigner(t, priv, topo.IA()),
SignerGen: testSignerGen{Signer: testSigner(t, priv, topo.IA())},
Intfs: intfs,
MAC: macFactory,
MaxExpTime: func() uint8 { return beacon.DefaultMaxExpTime },
Expand Down Expand Up @@ -138,7 +138,7 @@ func TestPropagatorRunCore(t *testing.T) {
Extender: &beaconing.DefaultExtender{
IA: topo.IA(),
MTU: topo.MTU(),
Signer: testSigner(t, priv, topo.IA()),
SignerGen: testSignerGen{Signer: testSigner(t, priv, topo.IA())},
Intfs: intfs,
MAC: macFactory,
MaxExpTime: func() uint8 { return beacon.DefaultMaxExpTime },
Expand Down Expand Up @@ -226,7 +226,7 @@ func TestPropagatorFastRecovery(t *testing.T) {
Extender: &beaconing.DefaultExtender{
IA: topo.IA(),
MTU: topo.MTU(),
Signer: testSigner(t, priv, topo.IA()),
SignerGen: testSignerGen{Signer: testSigner(t, priv, topo.IA())},
Intfs: intfs,
MAC: macFactory,
MaxExpTime: func() uint8 { return beacon.DefaultMaxExpTime },
Expand Down
Loading

0 comments on commit 45ba0a6

Please sign in to comment.