Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BS: Add propagator #2616

Merged
merged 5 commits into from
Apr 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion go/beacon_srv/internal/beaconing/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ go_library(
"originator.go",
"propagator.go",
"registrar.go",
"util.go",
],
importpath = "github.com/scionproto/scion/go/beacon_srv/internal/beaconing",
visibility = ["//go/beacon_srv:__subpackages__"],
Expand All @@ -31,7 +32,6 @@ go_library(
"//go/lib/snet:go_default_library",
"//go/lib/snet/addrutil:go_default_library",
"//go/lib/spath:go_default_library",
"//go/lib/topology:go_default_library",
"//go/lib/util:go_default_library",
"//go/proto:go_default_library",
],
Expand All @@ -43,6 +43,7 @@ go_test(
"extender_test.go",
"handler_test.go",
"originator_test.go",
"propagator_test.go",
"registrar_test.go",
],
data = glob(["testdata/**"]),
Expand Down
7 changes: 7 additions & 0 deletions go/beacon_srv/internal/beaconing/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,11 @@
// The registrar is a periodic task to register segments with the appropriate
// path server. Core and Up segments are registered with the local path server.
// Down segments are registered with the originating core AS.
//
// Propagator
//
// The propagator is a periodic task to propagate beacons to the appropriate
// neighboring ASes. In a core AS, the beacons are propagated to the neighbors
// on all core link, unless they will create an AS loop. In a non-core AS, the
// beacons are propagated to the neighbors on all child links.
package beaconing
40 changes: 39 additions & 1 deletion go/beacon_srv/internal/beaconing/mock_beaconing/beaconing.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

92 changes: 37 additions & 55 deletions go/beacon_srv/internal/beaconing/originator.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,17 @@ package beaconing

import (
"context"
"hash"
"time"

"github.com/scionproto/scion/go/beacon_srv/internal/ifstate"
"github.com/scionproto/scion/go/beacon_srv/internal/onehop"
"github.com/scionproto/scion/go/lib/addr"
"github.com/scionproto/scion/go/lib/common"
"github.com/scionproto/scion/go/lib/ctrl"
"github.com/scionproto/scion/go/lib/ctrl/seg"
"github.com/scionproto/scion/go/lib/log"
"github.com/scionproto/scion/go/lib/periodic"
"github.com/scionproto/scion/go/lib/snet"
"github.com/scionproto/scion/go/lib/spath"
"github.com/scionproto/scion/go/lib/topology"
"github.com/scionproto/scion/go/lib/util"
"github.com/scionproto/scion/go/proto"
)
Expand All @@ -41,8 +39,8 @@ type Originator struct {
sender *onehop.Sender
}

// NewOriginator creates a new originator. It takes ownership of the one-hop sender.
func NewOriginator(intfs *ifstate.Interfaces, cfg Config,
// NewOriginator creates a new originator.
func NewOriginator(intfs *ifstate.Interfaces, mac hash.Hash, cfg Config,
sender *onehop.Sender) (*Originator, error) {

cfg.InitDefaults()
Expand All @@ -54,7 +52,7 @@ func NewOriginator(intfs *ifstate.Interfaces, cfg Config,
segExtender: segExtender{
cfg: cfg,
intfs: intfs,
mac: sender.MAC,
mac: mac,
task: "originator",
},
}
Expand All @@ -63,35 +61,22 @@ func NewOriginator(intfs *ifstate.Interfaces, cfg Config,

// Run originates core and downstream beacons.
func (o *Originator) Run(_ context.Context) {
intfs := o.intfs.All()
o.originateBeacons(intfs, proto.LinkType_core)
o.originateBeacons(intfs, proto.LinkType_child)
o.originateBeacons(proto.LinkType_core)
o.originateBeacons(proto.LinkType_child)
}

// originateBeacons creates and sends a beacon for each active interface of
// the specified link type.
func (o *Originator) originateBeacons(intfs map[common.IFIDType]*ifstate.Interface,
linkType proto.LinkType) {
func (o *Originator) originateBeacons(linkType proto.LinkType) {

active, nonActive := sortedIntfs(o.intfs, linkType)
if len(nonActive) > 0 {
log.Debug("[Originator] Ignore non-active interfaces", "intfs", nonActive)
}
infoF := o.createInfoF(time.Now())
for ifid, info := range intfs {
intf := info.TopoInfo()
if intf.LinkType != linkType {
continue
}
state := info.State()
if state != ifstate.Active {
log.Debug("[Originator] Skipping non-active interface", "ifid", ifid, "state", state)
continue
}
msg, err := o.createBeaconMsg(ifid, intf, infoF)
if err != nil {
log.Error("[Originator] Skipping interface on error", "ifid", ifid, "err", err)
continue
}
ov := intf.InternalAddrs.PublicOverlay(intf.InternalAddrs.Overlay)
if err := o.sender.Send(msg, ov); err != nil {
log.Error("[Originator] Unable to send packet", "ifid", "err", err)
for _, ifid := range active {
if err := o.originateBeacon(ifid, infoF); err != nil {
log.Error("[Originator] Unable to originate on interface", "ifid", ifid, "err", err)
}
}
}
Expand All @@ -106,40 +91,37 @@ func (o *Originator) createInfoF(now time.Time) spath.InfoField {
return infoF
}

// createBeaconMsg creates a beacon for the given interface, signs it and
// wraps it in a one-hop message.
func (o *Originator) createBeaconMsg(ifid common.IFIDType, intf topology.IFInfo,
infoF spath.InfoField) (*onehop.Msg, error) {

bseg, err := o.createBeacon(ifid, intf, infoF)
if err != nil {
return nil, common.NewBasicError("Unable to create beacon", err, "ifid", ifid)
// originateBeacon originates a beacon on the given ifid.
func (o *Originator) originateBeacon(ifid common.IFIDType, infoF spath.InfoField) error {
intf := o.intfs.Get(ifid)
if intf == nil {
return common.NewBasicError("Interface does not exist", nil)
}
pld, err := ctrl.NewPld(bseg, nil)
topoInfo := intf.TopoInfo()
msg, err := o.createBeaconMsg(ifid, infoF, topoInfo.ISD_AS)
if err != nil {
return nil, common.NewBasicError("Unable to create payload", err)
return err
}
spld, err := pld.SignedPld(o.cfg.Signer)
if err != nil {
return nil, common.NewBasicError("Unable to sign payload", err)
ov := topoInfo.InternalAddrs.PublicOverlay(topoInfo.InternalAddrs.Overlay)
if err := o.sender.Send(msg, ov); err != nil {
return common.NewBasicError("Unable to send packet", err)
}
packed, err := spld.PackPld()
return nil
}

// createBeaconMsg creates a beacon for the given interface, signs it and
// wraps it in a one-hop message.
func (o *Originator) createBeaconMsg(ifid common.IFIDType, infoF spath.InfoField,
remoteIA addr.IA) (*onehop.Msg, error) {

bseg, err := o.createBeacon(ifid, infoF)
if err != nil {
return nil, common.NewBasicError("Unable to pack payload", err)
}
msg := &onehop.Msg{
Dst: snet.SCIONAddress{
IA: intf.ISD_AS,
Host: addr.SvcBS,
},
Ifid: ifid,
InfoTime: time.Now(),
Pld: packed,
return nil, common.NewBasicError("Unable to create beacon", err, "ifid", ifid)
}
return msg, nil
return packBeaconMsg(bseg, remoteIA, ifid, o.cfg.Signer)
}

func (o *Originator) createBeacon(ifid common.IFIDType, intf topology.IFInfo,
func (o *Originator) createBeacon(ifid common.IFIDType,
infoF spath.InfoField) (*seg.Beacon, error) {

bseg, err := seg.NewSeg(&infoF)
Expand Down
65 changes: 35 additions & 30 deletions go/beacon_srv/internal/beaconing/originator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func TestOriginatorRun(t *testing.T) {
mctrl := gomock.NewController(t)
defer mctrl.Finish()
conn := mock_snet.NewMockPacketConn(mctrl)
o, err := NewOriginator(intfs,
o, err := NewOriginator(intfs, mac,
Config{
MTU: uint16(itopo.Get().MTU),
Signer: signer,
Expand All @@ -76,10 +76,6 @@ func TestOriginatorRun(t *testing.T) {
intfs.Get(42).Activate(84)
intfs.Get(1129).Activate(82)

type msg struct {
pkt *snet.SCIONPacket
ov *overlay.OverlayAddr
}
msgsMtx := sync.Mutex{}
var msgs []msg
conn.EXPECT().WriteTo(gomock.Any(), gomock.Any()).Times(2).DoAndReturn(
Expand All @@ -97,36 +93,45 @@ func TestOriginatorRun(t *testing.T) {
o.Run(nil)
for i, msg := range msgs {
Convey(fmt.Sprintf("Packet %d is correct", i), func() {
// Extract segment from the payload
spld, err := ctrl.NewSignedPldFromRaw(msg.pkt.Payload.(common.RawBytes))
SoMsg("SPldErr", err, ShouldBeNil)
pld, err := spld.UnsafePld()
SoMsg("PldErr", err, ShouldBeNil)
err = pld.Beacon.Parse()
SoMsg("ParseErr", err, ShouldBeNil)
pseg := pld.Beacon.Segment
Convey("Segment can be validated", func() {
err = pseg.Validate(seg.ValidateBeacon)
SoMsg("err", err, ShouldBeNil)
})
Convey("Segment can be verified", func() {
err = pseg.VerifyASEntry(context.Background(), segVerifier(pub), 0)
SoMsg("err", err, ShouldBeNil)
})
Convey("Beacon on correct interface", func() {
hopF, err := msg.pkt.Path.GetHopField(msg.pkt.Path.HopOff)
xtest.FailOnErr(t, err)
bHopF, err := pseg.ASEntries[pseg.MaxAEIdx()].HopEntries[0].HopField()
xtest.FailOnErr(t, err)
SoMsg("Egress", hopF.ConsEgress, ShouldEqual, bHopF.ConsEgress)
brAddr := itopo.Get().IFInfoMap[hopF.ConsEgress].InternalAddrs
SoMsg("ov", msg.ov, ShouldResemble, brAddr.PublicOverlay(brAddr.Overlay))
})
checkMsg(t, msg, pub)
})
}
})
}

type msg struct {
pkt *snet.SCIONPacket
ov *overlay.OverlayAddr
}

func checkMsg(t *testing.T, msg msg, pub common.RawBytes) {
// Extract segment from the payload
spld, err := ctrl.NewSignedPldFromRaw(msg.pkt.Payload.(common.RawBytes))
SoMsg("SPldErr", err, ShouldBeNil)
pld, err := spld.UnsafePld()
SoMsg("PldErr", err, ShouldBeNil)
err = pld.Beacon.Parse()
SoMsg("ParseErr", err, ShouldBeNil)
pseg := pld.Beacon.Segment
Convey("Segment can be validated", func() {
err = pseg.Validate(seg.ValidateBeacon)
SoMsg("err", err, ShouldBeNil)
})
Convey("Segment can be verified", func() {
err = pseg.VerifyASEntry(context.Background(), segVerifier(pub), pseg.MaxAEIdx())
SoMsg("err", err, ShouldBeNil)
})
Convey("Beacon on correct interface", func() {
hopF, err := msg.pkt.Path.GetHopField(msg.pkt.Path.HopOff)
xtest.FailOnErr(t, err)
bHopF, err := pseg.ASEntries[pseg.MaxAEIdx()].HopEntries[0].HopField()
xtest.FailOnErr(t, err)
SoMsg("Egress", hopF.ConsEgress, ShouldEqual, bHopF.ConsEgress)
brAddr := itopo.Get().IFInfoMap[hopF.ConsEgress].InternalAddrs
SoMsg("ov", msg.ov, ShouldResemble, brAddr.PublicOverlay(brAddr.Overlay))
})
}

func testTopo(t *testing.T, fn string) *topology.Topo {
topo, err := topology.LoadFromFile(fn)
xtest.FailOnErr(t, err)
Expand Down
Loading