From 1865df92044e7fb138272b93fde0fbe5795087d3 Mon Sep 17 00:00:00 2001 From: Sergiu Costea Date: Tue, 16 Jun 2020 15:40:24 +0200 Subject: [PATCH] snet: add support for new SCION header Also: - plugs feature flag support to all snet using applications with the exception of the border router. Note that CLI tools need need a CLI flag to be added to enable the feature. --- go/examples/pingpong/pingpong.go | 25 ++++++++++++++++++++++-- go/integration/common.go | 12 +++++++++++- go/integration/end2end/main.go | 4 ++++ go/lib/infra/infraenv/infraenv.go | 6 ++++++ go/lib/sciond/pathprobe/paths.go | 4 ++++ go/lib/snet/base.go | 3 +++ go/lib/snet/dispatcher.go | 9 ++++++++- go/lib/snet/packet_conn.go | 19 +++++++++++++----- go/pkg/cs/main.go | 3 +++ go/pkg/showpaths/showpaths.go | 2 ++ go/scion-pki/certs/renew.go | 3 +++ go/sig/internal/sigcmn/common.go | 32 ++++++++++++++++++++++--------- go/sig/main.go | 2 +- go/tools/showpaths/paths.go | 2 ++ 14 files changed, 107 insertions(+), 19 deletions(-) diff --git a/go/examples/pingpong/pingpong.go b/go/examples/pingpong/pingpong.go index 60efddd32d..636ec7f7f9 100644 --- a/go/examples/pingpong/pingpong.go +++ b/go/examples/pingpong/pingpong.go @@ -228,7 +228,17 @@ func (c *client) run() { if err != nil { LogFatal("Unable to initialize SCION network", "err", err) } - network := snet.NewNetwork(local.IA, ds, sd.RevHandler{Connector: sciondConn}) + network := &snet.SCIONNetwork{ + LocalIA: local.IA, + Dispatcher: &snet.DefaultPacketDispatcherService{ + Dispatcher: ds, + SCMPHandler: snet.NewSCMPHandler( + sd.RevHandler{Connector: sciondConn}, + ), + // TODO(scrye): set this when we have CLI support for features + Version2: false, + }, + } // Connect to remote address. Note that currently the SCION library // does not support automatic binding to local addresses, so the local @@ -348,7 +358,18 @@ func (s server) run() { if err != nil { LogFatal("Unable to initialize SCION network", "err", err) } - network := snet.NewNetwork(local.IA, ds, sd.RevHandler{Connector: sciondConn}) + network := &snet.SCIONNetwork{ + LocalIA: local.IA, + Dispatcher: &snet.DefaultPacketDispatcherService{ + Dispatcher: ds, + SCMPHandler: snet.NewSCMPHandler( + sciond.RevHandler{Connector: sciondConn}, + ), + // TODO(scrye): set this when we have CLI support for features + Version2: false, + }, + } + if err != nil { LogFatal("Unable to initialize SCION network", "err", err) } diff --git a/go/integration/common.go b/go/integration/common.go index a5d4eb4ecb..9daf50e276 100644 --- a/go/integration/common.go +++ b/go/integration/common.go @@ -108,7 +108,17 @@ func InitNetwork() *snet.SCIONNetwork { if err != nil { LogFatal("Unable to initialize SCION network", "err", err) } - n := snet.NewNetwork(Local.IA, ds, sciond.RevHandler{Connector: sciondConn}) + n := &snet.SCIONNetwork{ + LocalIA: Local.IA, + Dispatcher: &snet.DefaultPacketDispatcherService{ + Dispatcher: ds, + SCMPHandler: snet.NewSCMPHandler( + sciond.RevHandler{Connector: sciondConn}, + ), + // TODO(scrye): set this when we have CLI support for features + Version2: false, + }, + } log.Debug("SCION network successfully initialized") return n } diff --git a/go/integration/end2end/main.go b/go/integration/end2end/main.go index 1a91d8ed1c..441ec2563b 100644 --- a/go/integration/end2end/main.go +++ b/go/integration/end2end/main.go @@ -107,6 +107,8 @@ func (s server) run() { SCMPHandler: snet.NewSCMPHandler( sciond.RevHandler{Connector: integration.SDConn()}, ), + // TODO(scrye): set this when we have CLI support for features + Version2: false, } conn, port, err := connFactory.Register(context.Background(), integration.Local.IA, integration.Local.Host, addr.SvcNone) @@ -165,6 +167,8 @@ func (c client) run() int { SCMPHandler: snet.NewSCMPHandler( sciond.RevHandler{Connector: integration.SDConn()}, ), + // TODO(scrye): set this when we have CLI support for features + Version2: false, } var err error diff --git a/go/lib/infra/infraenv/infraenv.go b/go/lib/infra/infraenv/infraenv.go index c2ee546d81..50e5146b39 100644 --- a/go/lib/infra/infraenv/infraenv.go +++ b/go/lib/infra/infraenv/infraenv.go @@ -81,6 +81,9 @@ type NetworkConfig struct { // SVCRouter is used to discover the underlay addresses of intra-AS SVC // servers. SVCRouter messenger.LocalSVCRouter + + // Version2 switches packets to SCION header format version 2. + Version2 bool } // Messenger initializes a SCION control-plane RPC endpoint using the specified @@ -138,6 +141,7 @@ func (nc *NetworkConfig) AddressRewriter( if connFactory == nil { connFactory = &snet.DefaultPacketDispatcherService{ Dispatcher: reliable.NewDispatcher(""), + Version2: nc.Version2, } } @@ -187,6 +191,7 @@ func (nc *NetworkConfig) initUDPSocket(quicAddress string) (net.PacketConn, erro packetDispatcher := svc.NewResolverPacketDispatcher( &snet.DefaultPacketDispatcherService{ Dispatcher: dispatcherService, + Version2: nc.Version2, }, &LegacyForwardingHandler{ BaseHandler: &svc.BaseHandler{ @@ -214,6 +219,7 @@ func (nc *NetworkConfig) initQUICSocket() (net.PacketConn, error) { Dispatcher: &snet.DefaultPacketDispatcherService{ Dispatcher: dispatcherService, SCMPHandler: ignoreSCMP{}, + Version2: nc.Version2, }, } udpAddr, err := net.ResolveUDPAddr("udp", nc.QUIC.Address) diff --git a/go/lib/sciond/pathprobe/paths.go b/go/lib/sciond/pathprobe/paths.go index ac2d607467..89601ae55f 100644 --- a/go/lib/sciond/pathprobe/paths.go +++ b/go/lib/sciond/pathprobe/paths.go @@ -95,6 +95,9 @@ type Prober struct { DstIA addr.IA LocalIA addr.IA LocalIP net.IP + + // Version2 switches packets to SCION header format version 2. + Version2 bool } // GetStatuses probes the paths and returns the statuses of the paths. The @@ -119,6 +122,7 @@ func (p Prober) GetStatuses(ctx context.Context, Dispatcher: &snet.DefaultPacketDispatcherService{ Dispatcher: reliable.NewDispatcher(""), SCMPHandler: scmpH, + Version2: p.Version2, }, } snetConn, err := network.Listen(ctx, "udp", &net.UDPAddr{IP: p.LocalIP}, addr.SvcNone) diff --git a/go/lib/snet/base.go b/go/lib/snet/base.go index 6de48b2a36..61ab1779da 100644 --- a/go/lib/snet/base.go +++ b/go/lib/snet/base.go @@ -34,6 +34,9 @@ type scionConnBase struct { // Describes L4 protocol; currently only udp is implemented net string + + // version2 switches packets to SCION header format version 2. + version2 bool } func (c *scionConnBase) LocalAddr() net.Addr { diff --git a/go/lib/snet/dispatcher.go b/go/lib/snet/dispatcher.go index 6933ba8f2e..a95c081f76 100644 --- a/go/lib/snet/dispatcher.go +++ b/go/lib/snet/dispatcher.go @@ -45,6 +45,9 @@ type DefaultPacketDispatcherService struct { // handler is nil, errors are returned back to applications every time an // SCMP message is received. SCMPHandler SCMPHandler + + // Version2 switches packets to SCION header format version 2. + Version2 bool } func (s *DefaultPacketDispatcherService) Register(ctx context.Context, ia addr.IA, @@ -54,7 +57,11 @@ func (s *DefaultPacketDispatcherService) Register(ctx context.Context, ia addr.I if err != nil { return nil, 0, err } - return &SCIONPacketConn{conn: rconn, scmpHandler: s.SCMPHandler}, port, nil + return &SCIONPacketConn{ + conn: rconn, + scmpHandler: s.SCMPHandler, + version2: s.Version2, + }, port, nil } // RevocationHandler is called by the default SCMP Handler whenever revocations are encountered. diff --git a/go/lib/snet/packet_conn.go b/go/lib/snet/packet_conn.go index 19fbad88c9..2ad453157e 100644 --- a/go/lib/snet/packet_conn.go +++ b/go/lib/snet/packet_conn.go @@ -124,6 +124,9 @@ type SCIONPacketConn struct { // handler is nil, errors are returned back to applications every time an // SCMP message is received. scmpHandler SCMPHandler + + // version2 switches packets to SCION header format version 2. + version2 bool } // NewSCIONPacketConn creates a new conn with packet serialization/decoding @@ -164,7 +167,12 @@ func (c *SCIONPacketConn) WriteTo(pkt *Packet, ov *net.UDPAddr) error { Pld: pkt.Payload, } pkt.Prepare() - n, err := hpkt.WriteScnPkt(scnPkt, common.RawBytes(pkt.Bytes)) + var n int + if c.version2 { + n, err = hpkt.WriteScnPkt2(scnPkt, pkt.Bytes) + } else { + n, err = hpkt.WriteScnPkt(scnPkt, common.RawBytes(pkt.Bytes)) + } if err != nil { return common.NewBasicError("Unable to serialize SCION packet", err) } @@ -230,11 +238,12 @@ func (c *SCIONPacketConn) readFrom(pkt *Packet, ov *net.UDPAddr) error { // TODO(scrye): scnPkt is a temporary solution. Its functionality will be // absorbed by the easier to use Packet structure in this package. - scnPkt := &spkt.ScnPkt{ - DstIA: addr.IA{}, - SrcIA: addr.IA{}, + scnPkt := &spkt.ScnPkt{} + if c.version2 { + err = hpkt.ParseScnPkt2(scnPkt, common.RawBytes(pkt.Bytes)) + } else { + err = hpkt.ParseScnPkt(scnPkt, common.RawBytes(pkt.Bytes)) } - err = hpkt.ParseScnPkt(scnPkt, common.RawBytes(pkt.Bytes)) if err != nil { metrics.M.ParseErrors().Inc() return common.NewBasicError("SCION packet parse error", err) diff --git a/go/pkg/cs/main.go b/go/pkg/cs/main.go index 09af0e345e..b2492fe70e 100644 --- a/go/pkg/cs/main.go +++ b/go/pkg/cs/main.go @@ -232,6 +232,7 @@ func (app *App) Run() int { }, SVCResolutionFraction: Cfg.QUIC.ResolutionFraction, SVCRouter: messenger.NewSVCRouter(itopo.Provider()), + Version2: Cfg.Features.HeaderV2, } msgr, err := nc.Messenger() if err != nil { @@ -458,6 +459,7 @@ func (app *App) Run() int { } pktDisp := &snet.DefaultPacketDispatcherService{ Dispatcher: dispatcherService, + Version2: Cfg.Features.HeaderV2, } // We do not need to drain the connection, since the src address is spoofed // to contain the topo address. @@ -488,6 +490,7 @@ func (app *App) Run() int { &onehop.OHPPacketDispatcherService{ PacketDispatcherService: &snet.DefaultPacketDispatcherService{ Dispatcher: reliable.NewDispatcher(""), + Version2: Cfg.Features.HeaderV2, }, }, ), diff --git a/go/pkg/showpaths/showpaths.go b/go/pkg/showpaths/showpaths.go index c23ac3f78b..83fdc2371a 100644 --- a/go/pkg/showpaths/showpaths.go +++ b/go/pkg/showpaths/showpaths.go @@ -114,6 +114,8 @@ func Run(ctx context.Context, dst addr.IA, cfg Config) (*Result, error) { DstIA: dst, LocalIA: localIA, LocalIP: localIP, + // TODO(scrye): set this when we have CLI support for features + Version2: false, }.GetStatuses(ctx, paths) if err != nil { serrors.WrapStr("failed to get status", err) diff --git a/go/scion-pki/certs/renew.go b/go/scion-pki/certs/renew.go index 28c6f7e036..2472f147cf 100644 --- a/go/scion-pki/certs/renew.go +++ b/go/scion-pki/certs/renew.go @@ -389,6 +389,7 @@ func buildMsgr(ctx context.Context, ds reliable.Dispatcher, sds sciond.Service, SCMPHandler: snet.NewSCMPHandler( sciond.RevHandler{Connector: sdConn}, ), + Version2: false, // TODO(scrye): set this to true when we have CLI support for features }, } conn, err := sn.Dial(ctx, "udp", local.Host, remote, addr.SvcNone) @@ -408,6 +409,8 @@ func buildMsgr(ctx context.Context, ds reliable.Dispatcher, sds sciond.Service, LocalIA: local.IA, ConnFactory: &snet.DefaultPacketDispatcherService{ Dispatcher: ds, + // TODO(scrye): set this to true when we have CLI support for features + Version2: false, }, LocalIP: local.Host.IP, Payload: []byte{0x00, 0x00, 0x00, 0x00}, diff --git a/go/sig/internal/sigcmn/common.go b/go/sig/internal/sigcmn/common.go index cd7ca69b86..b268a68bf5 100644 --- a/go/sig/internal/sigcmn/common.go +++ b/go/sig/internal/sigcmn/common.go @@ -57,13 +57,13 @@ var ( CtrlConn *snet.Conn ) -func Init(cfg sigconfig.SigConf, sdCfg env.SCIONDClient) error { +func Init(cfg sigconfig.SigConf, sdCfg env.SCIONDClient, features env.Features) error { IA = cfg.IA CtrlAddr = cfg.IP CtrlPort = int(cfg.CtrlPort) DataAddr = cfg.IP DataPort = int(cfg.EncapPort) - network, resolver, err := initNetwork(cfg, sdCfg) + network, resolver, err := initNetwork(cfg, sdCfg, features) if err != nil { return common.NewBasicError("Error creating local SCION Network context", err) } @@ -81,7 +81,7 @@ func Init(cfg sigconfig.SigConf, sdCfg env.SCIONDClient) error { } func initNetwork(cfg sigconfig.SigConf, - sdCfg env.SCIONDClient) (*snet.SCIONNetwork, pathmgr.Resolver, error) { + sdCfg env.SCIONDClient, features env.Features) (*snet.SCIONNetwork, pathmgr.Resolver, error) { var err error Dispatcher, err = newDispatcher(cfg) @@ -89,25 +89,32 @@ func initNetwork(cfg sigconfig.SigConf, return nil, nil, serrors.WrapStr("unable to initialize SCION dispatcher", err) } if sdCfg.FakeData != "" { - return initNetworkWithFakeSCIOND(cfg, sdCfg) + return initNetworkWithFakeSCIOND(cfg, sdCfg, features) } - return initNetworkWithRealSCIOND(cfg, sdCfg) + return initNetworkWithRealSCIOND(cfg, sdCfg, features) } func initNetworkWithFakeSCIOND(cfg sigconfig.SigConf, - sdCfg env.SCIONDClient) (*snet.SCIONNetwork, pathmgr.Resolver, error) { + sdCfg env.SCIONDClient, features env.Features) (*snet.SCIONNetwork, pathmgr.Resolver, error) { sciondConn, err := fake.NewFromFile(sdCfg.FakeData) if err != nil { return nil, nil, serrors.WrapStr("unable to initialize fake SCIOND service", err) } pathResolver := pathmgr.New(sciondConn, pathmgr.Timers{}, sdCfg.PathCount) - network := snet.NewNetwork(cfg.IA, Dispatcher, pathResolver) + network := &snet.SCIONNetwork{ + LocalIA: cfg.IA, + Dispatcher: &snet.DefaultPacketDispatcherService{ + Dispatcher: Dispatcher, + SCMPHandler: snet.NewSCMPHandler(pathResolver), + Version2: features.HeaderV2, + }, + } return network, pathResolver, nil } func initNetworkWithRealSCIOND(cfg sigconfig.SigConf, - sdCfg env.SCIONDClient) (*snet.SCIONNetwork, pathmgr.Resolver, error) { + sdCfg env.SCIONDClient, features env.Features) (*snet.SCIONNetwork, pathmgr.Resolver, error) { // TODO(karampok). To be kept until https://github.com/scionproto/scion/issues/3377 deadline := time.Now().Add(sdCfg.InitialConnectPeriod.Duration) @@ -115,7 +122,14 @@ func initNetworkWithRealSCIOND(cfg sigconfig.SigConf, for tries := 0; time.Now().Before(deadline); tries++ { resolver, err := snetmigrate.ResolverFromSD(sdCfg.Address, sdCfg.PathCount) if err == nil { - return snet.NewNetwork(cfg.IA, Dispatcher, resolver), resolver, nil + return &snet.SCIONNetwork{ + LocalIA: cfg.IA, + Dispatcher: &snet.DefaultPacketDispatcherService{ + Dispatcher: Dispatcher, + SCMPHandler: snet.NewSCMPHandler(resolver), + Version2: features.HeaderV2, + }, + }, resolver, nil } log.Debug("SIG is retrying to get NewNetwork", "err", err) retErr = err diff --git a/go/sig/main.go b/go/sig/main.go index a9ded1a484..0ed31cb272 100644 --- a/go/sig/main.go +++ b/go/sig/main.go @@ -83,7 +83,7 @@ func realMain() int { log.Error("TUN device initialization failed", "err", err) return 1 } - if err := sigcmn.Init(cfg.Sig, cfg.Sciond); err != nil { + if err := sigcmn.Init(cfg.Sig, cfg.Sciond, cfg.Features); err != nil { log.Error("SIG common initialization failed", "err", err) return 1 } diff --git a/go/tools/showpaths/paths.go b/go/tools/showpaths/paths.go index 7f74ef8e04..b0052a7e1e 100644 --- a/go/tools/showpaths/paths.go +++ b/go/tools/showpaths/paths.go @@ -94,6 +94,8 @@ func main() { DstIA: dstIA, LocalIA: localIA, LocalIP: localIP, + // TODO(scrye): set this when we have CLI support for features + Version2: false, }.GetStatuses(ctx, paths) if err != nil { LogFatal("Failed to get status", "err", err)